Compare commits

...

384 commits

Author SHA1 Message Date
Zed A. Shaw
0afaa20c1d Improved the code so it uses ai::EntityAI and it now will find healing when it gets low. Has a bug where it stalls when finding healing and gets into combat. 2025-09-07 23:56:24 -04:00
Zed A. Shaw
7207d53885 Autowalker now figures out there's an enemy near when first entering a level. 2025-09-06 22:50:20 -04:00
Zed A. Shaw
ed33a36bca Autowalker now will grab healing when they need it and can grab it. 2025-09-06 00:02:42 -04:00
Zed A. Shaw
29ab9721af Now they AI will heal when they can, but not yet go get itesm before/during combat. 2025-09-05 23:48:59 -04:00
Zed A. Shaw
a2192e25eb AI can now walk to where healing items are and pick them up to use. 2025-09-05 23:20:45 -04:00
Zed A. Shaw
fe37aa11df Accidental crash when you click on an empty inventory. 2025-09-05 11:56:36 -04:00
Zed A. Shaw
f03a3a31a8 Autowalker now walks more accurately to locations, fights enemies, and also picks up loot drops and healing items _only_. 2025-09-04 23:40:36 -04:00
Zed A. Shaw
40b2d7f45d Bring over various autowalker improvements. 2025-09-04 12:23:43 -04:00
Zed A. Shaw
9c5bad5959 This fixes the bug where you get 'stuck' while moving and passing an enemy. Need to sort out why this fixes it though. Closes #30. 2025-09-04 11:48:12 -04:00
Zed A. Shaw
ba5fc73127 Disable collecting items for now. 2025-09-04 11:46:51 -04:00
Zed A. Shaw
ca3b04b895 Invalid test, should be enemy. 2025-09-03 11:28:29 -04:00
Zed A. Shaw
0c8cb197c2 Fix the map opening and closing all the time. 2025-09-02 13:56:19 -04:00
Zed A. Shaw
a11e7de14e Fix up the spatialmap to have an occupied_by method which checks if a square is occupied and returns what is there. 2025-09-02 12:46:05 -04:00
Zed A. Shaw
759f93cae0 Autowalker now correctly faces enemies to fight them. 2025-09-02 11:31:01 -04:00
Zed A. Shaw
9faad5f263 FINALLY figured out how to rotate to face a square, thanks to all the help from Twitch chat. I need to study Trig. 2025-09-02 02:26:08 -04:00
Zed A. Shaw
d822cb3438 Have a way to detect the best rotation but it's still off a bit. Seems to choose wrong in simple situations. Look in System::shortest_rotate. 2025-09-01 01:37:03 -04:00
Zed A. Shaw
f98cc543f6 Autowalker now paths reliably and can attack enemies by facing them. Just need to make it fight diagonally. 2025-08-31 00:47:21 -04:00
Zed A. Shaw
4365aa4bfc Now added a System::multi_path which can target to multiple entities. 2025-08-31 00:39:35 -04:00
Zed A. Shaw
fc678c6b42 Pathing in either diagonal or simple motion works. 2025-08-31 00:17:47 -04:00
Zed A. Shaw
e92fd2b6f3 Needed to rewrite the pathing to get this to work. I actually had been using a purposefully broken pathing algorithm from when I was making random maps. 2025-08-30 10:48:52 -04:00
Zed A. Shaw
c894f6e094 Initial part of the rewrite for the autowalker to fix the pathing and aiming issues. 2025-08-26 00:55:27 -04:00
Zed A. Shaw
63eaea3536 rewrite game_level::player_position to be more efficient. 2025-08-26 00:46:58 -04:00
Zed A. Shaw
4a2d8770d9 Cleaned up how the camera is configured so that it can be easily queried in other parts like the autowalker. 2025-08-25 23:23:05 -04:00
Zed A. Shaw
b4569622a0 Cleanup the autowalker for new work. 2025-08-25 22:44:53 -04:00
Zed A. Shaw
4bf9a9177f Made an AI debug view to I can make working on the AI easier. I might add the ability to toggle things on/off live to see what the AI does. 2025-08-23 01:40:51 -04:00
Zed A. Shaw
fc8e65f4d6 Enemies how fight back when cornered, either by being blocked by another enemy or when at a dead end walls. 2025-08-22 22:29:22 -04:00
Zed A. Shaw
586343a614 Enemies will now fight back if they're cornered. Was actually way easier than I thought. 2025-08-21 23:32:34 -04:00
Zed A. Shaw
7ffa6025ce And finally fix some of the API names to make more sense in their current location. 2025-08-20 23:49:30 -04:00
Zed A. Shaw
a20d701096 Rename to GameDB and GameDB::Level. 2025-08-20 23:20:36 -04:00
Zed A. Shaw
c46927ea10 Now all of the old LevelManager code is gone. Next phase is to rename the Game:: to something better then test the shit out of it. 2025-08-20 13:31:02 -04:00
Zed A. Shaw
a83ee77eea levelmanager.* is now gone, but the code is just moved over to game_level. Now to clean up the api and give it a new name. 2025-08-20 01:10:42 -04:00
Zed A. Shaw
5aca2fb56a Tests are now clean so next step is to officially nuke the level manager. 2025-08-20 00:48:20 -04:00
Zed A. Shaw
564f9842a2 All of the UIs should be cleared out, and that just leaves the tests. 2025-08-19 23:58:42 -04:00
Zed A. Shaw
d5ff57e025 Now systems.cpp is disconnected from levelmanager. That leaves the GUIs and then to completely remove it and clean up the api. 2025-08-19 11:05:32 -04:00
Zed A. Shaw
81e25f73bb Next phase of the refactor is done. Now to replace everything in Systems. 2025-08-19 01:07:28 -04:00
Zed A. Shaw
644ff6edc0 Bad test that wasn't running. 2025-08-18 23:55:14 -04:00
Zed A. Shaw
097879440d Changed facts in DinkyECS to be a shared_ptr so that it is a singular data store instead of copied around. Closes #85. 2025-08-18 02:17:04 -04:00
Zed A. Shaw
b839fb6463 The problem was keeping a reference in a class/object means that it will not get updated copies when levelmanager makes a new level. Honestly that whole constelation of bullshit needs to die. Closes #62. 2025-08-18 01:13:31 -04:00
Zed A. Shaw
ae1a48deed Now I have a better error that's more exact, but I think next level of this is to just show a generic texture for missing ones. Closes #80. 2025-08-17 11:08:01 -04:00
Zed A. Shaw
25a143cf22 Turns out I don't need to remove so much when I simply don't want to display something. Closes #82. 2025-08-17 10:51:08 -04:00
Zed A. Shaw
20fa95bd93 Simple test to make sure world events actually loop. Closes #84. 2025-08-17 10:18:06 -04:00
Zed A. Shaw
a86912705c Refactored the mouse handling to use the new guecss Modifiers system and improved Clickable. 2025-08-14 14:10:28 -04:00
Zed A. Shaw
ad0069e899 Made it so you can right-click on an item to use it, but yeah it's bad. Gotta refactor. 2025-08-13 11:43:23 -04:00
Zed A. Shaw
42575ef1f5 Updated the lootable body asset. 2025-08-13 11:43:05 -04:00
Zed A. Shaw
f19c1dbb20 Now you can heal yourself. 2025-08-11 16:59:19 -04:00
Zed A. Shaw
e03a63f9fb A little bit of refactoring while thinking about the loot next. 2025-08-10 12:42:28 -04:00
Zed A. Shaw
48e28ee636 New dead_body_lootable sprite for dead things you can loot. 2025-08-10 12:30:42 -04:00
Zed A. Shaw
b9209beddd Better error when you have duplicate map icons. 2025-08-10 12:29:53 -04:00
Zed A. Shaw
8594568ff4 Slight clean up. 2025-08-10 12:29:24 -04:00
Zed A. Shaw
521180b086 Refactor out the junk randomizer and put it in rituals where it belongs. 2025-08-10 11:20:22 -04:00
Zed A. Shaw
05d54ff661 Now also combat works no matter what's on the ground. Closes #81. 2025-08-09 00:13:38 -04:00
Zed A. Shaw
f84b63f0e6 The problem with picking up items under a dead body is fixed but now need to fix combat. 2025-08-07 12:13:39 -04:00
Zed A. Shaw
97fe02d99d Add a new dead_body sprite for things that are dead but you can't loot them. 2025-08-06 23:13:29 -04:00
Zed A. Shaw
0d889cd0ff Quick start to making it possible to use healing items, or any item really. Going with a style that it has to be on your toolbar to use it, and the toolbelt looks in your inventory to see ifyou have healing items. 2025-08-06 13:16:22 -04:00
Zed A. Shaw
b9656013b0 Now have dead bodies working but need art for it. 2025-08-06 12:15:21 -04:00
Zed A. Shaw
fc4eacadb0 There's now a Collision component that determines collision if its set. Closes #72. 2025-08-06 11:43:39 -04:00
Zed A. Shaw
9bf6926dc3 A bit of optimization to keep from generating the sorted sprite list over and over. Also tried to solve the problem of tombstone covering everything but no luck. 2025-08-03 23:58:59 -04:00
Zed A. Shaw
077f0e84ea Don't add wiggle to the things in the player's square since that moves them into the player eyes. 2025-08-03 22:34:03 -04:00
Zed A. Shaw
a4a4389281 Move amt's examples into scratchpad for later review. 2025-08-03 22:33:29 -04:00
Zed A. Shaw
9c02fb846b Now the spatialmap determines the 'wiggle factor' when there's multiple entities in a cell, which staggers them visually. Closes #78. 2025-08-03 01:56:34 -04:00
Zed A. Shaw
694ee210d6 Now floor drops always work by having a drop against a wall just drop at your feet. Closes #77. 2025-08-02 23:26:42 -04:00
Zed A. Shaw
1788b8fb28 Now items drop where you aim, and won't let you drop on a floor. But maybe one more change. 2025-08-02 23:11:59 -04:00
Zed A. Shaw
23ead1f0ca SpatialMap now has a full test suite and that helped find some bugs. 2025-08-01 13:33:34 -04:00
Zed A. Shaw
f26189c696 SpatialMap now uses unordered_multimap to allow for multiple items in a square, but they're also tagged to mark some with collision. 2025-07-31 13:00:39 -04:00
Zed A. Shaw
b193bab148 Add in the tests from finding the bug in spatial map. 2025-07-31 00:03:36 -04:00
Zed A. Shaw
569d04725a This is the cause of the bug where going to the next level caused things to disappear. What happened is that on next level this code was adding the player but _not_ adding them to collision. Then when the player moved the spatialmap would remove them, see they're technically 'no collision' and then add them back in without collision. 2025-07-31 00:03:13 -04:00
Zed A. Shaw
e51fb8627c Switching to Linux to find a memory bug and I want to keep a record of what caused it. 2025-07-30 22:34:26 -04:00
Zed A. Shaw
be3eef7082 Make money. 2025-07-30 11:52:12 -04:00
Zed A. Shaw
d6326c9e41 Mostly working spatical map with 2 level collision/space structure. Not the best implementation but this is the idea. 2025-07-29 03:12:44 -04:00
Zed A. Shaw
fd53f92fe6 Prep for fixing the spatialmap to allow for entities without collision to still be in the space. 2025-07-29 02:13:29 -04:00
Zed A. Shaw
d93bc1615c Big changes to use the new lel-guecs setup but now almost everything works. Only thing missing is Issue #16 in quecs. 2025-07-23 14:03:41 -04:00
Zed A. Shaw
86ddfc460f Update to the new lel-guecs with Icons and the ability to set a Sprite to stretch or not. Now Icons for loot pickup work perfectly, but need to be centered. 2025-07-22 17:21:28 -04:00
Zed A. Shaw
ff7111b006 Icons now work way better and don't have the the 'Rayview cuts icons' bug. It actually was a bug in the lel-guecs Sprite class that was using the TextureRect from the source sprite. Now its initialized with the framesize from the .json. This also uses the new guecs::Icon, but I have to fix that as it doesn't scale correctly. Closes #2. 2025-07-22 15:04:22 -04:00
Zed A. Shaw
b311713064 Quick prototype of how switch to an icon during pickup makes the rendering bug go away and also looks better visually. 2025-07-22 01:08:48 -04:00
Zed A. Shaw
6f91533950 Fog of War now works fairly normally, but I think I'll have to do something so people don't live in the map. Probably something like hearing distance is increased because you're louder with a map out, and you can't see enemies on the map. 2025-07-21 23:21:24 -04:00
Zed A. Shaw
2997dc363b FoW is now moved into lighting so light determines what's seen not player's last position. Not sure if I like that though. 2025-07-21 13:10:03 -04:00
Zed A. Shaw
d264760405 Fog of War works but it's in the wrong place and needs to be based on light. 2025-07-20 01:34:39 -04:00
Zed A. Shaw
2802a44ba4 Clean up System::render_map. 2025-07-18 13:25:32 -04:00
Zed A. Shaw
aa72cfe4a4 Now have a working compass based directional player sprite in the map, but using the compass isn't going to work long term. Need to move that into the raycaster.cpp and get real degrees for facing direction. 2025-07-18 13:09:53 -04:00
Zed A. Shaw
3b81959aa9 Map now displays way better. The paper is gone for now. 2025-07-17 14:22:04 -04:00
Zed A. Shaw
973495b687 Map now has a color theme rather than random colors. 2025-07-17 12:59:20 -04:00
Zed A. Shaw
379060b8c7 Can now set a color to another already existing color. 2025-07-17 12:39:24 -04:00
Zed A. Shaw
f4fa50a413 Colors are now being loaded from assets/palette.json 2025-07-17 10:50:09 -04:00
Zed A. Shaw
48a7f72411 Now have a simple color palette system. 2025-07-16 12:46:49 -04:00
Zed A. Shaw
0272ba8540 Trying a bit of color changes. 2025-07-15 14:46:14 -04:00
Zed A. Shaw
75646619b3 Map now displays and works, just need to refine the colors and the compass directions. 2025-07-15 13:28:23 -04:00
Zed A. Shaw
dca38397e7 Systems::render_map now holds the logic to render the map, and it's working well enough to use for displaying. 2025-07-15 11:39:05 -04:00
Zed A. Shaw
0d1eacdc5c Now entities are drawn after the map so that there's no holes. 2025-07-12 14:46:42 -04:00
Zed A. Shaw
72ecca8c82 I can now draw a map and then render it with the sprites pretty easily. Problem currently is the entities replace their floor tiles so need to fix that. 2025-07-12 13:34:31 -04:00
Zed A. Shaw
a3f82139e9 One step closer to map rendering from tile sprites. 2025-07-12 12:05:18 -04:00
Zed A. Shaw
dd541ae59d Ripped out the string based map and created a Matrix map drawing function. 2025-07-12 10:51:55 -04:00
Zed A. Shaw
d9219a8c64 This cleans up how I'm rendering the map but there's no way I can render a large map like this. It'd be way too big. 2025-07-12 00:35:57 -04:00
Zed A. Shaw
3b06105813 Map tiles are generating fine, and I can make a map, now to bring it into the game and see how it works. 2025-07-11 22:38:08 -04:00
Zed A. Shaw
5db3d1a306 Tried out using the actual textures from the game but they don't really have the feel I want. I'll have to think about it. 2025-07-11 02:24:47 -04:00
Zed A. Shaw
5e01eb29a9 There's a bug where the last item in tiles.json draws a black square, which is why I named ceiling_blue to zceiling_blue to temporarily solve it. 2025-07-11 01:02:27 -04:00
Zed A. Shaw
b2a6262964 Now have background color for the sprites used in the maps. 2025-07-10 00:12:32 -04:00
Zed A. Shaw
b16ca3fd65 I now have hacked in basic color for the wall tiles but not enemies and items. 2025-07-09 14:36:31 -04:00
Zed A. Shaw
b2d0b0ee4c Map tiles are now correctly sized and positioned. Errors from before were due to floating point being used for positioning. 2025-07-09 13:34:18 -04:00
Zed A. Shaw
2c011079a8 I have a test now that can generate a map image so I'll make it look nice there before bringing the code into the game. 2025-07-09 01:54:49 -04:00
Zed A. Shaw
cfefffe1cc I now can output a map_tiles.json that has all of the tiles in the tile sheet tagged by their display char and where they are. 2025-07-09 00:34:50 -04:00
Zed A. Shaw
40611d4d54 Crop the map sprite so it's not bigger than necessary. 2025-07-08 22:54:59 -04:00
Zed A. Shaw
04b3cf3f16 Now have a sprite sheet with tiles expanded to fill the cell, but other sprites reduced to 80% and centered in the cell. 2025-07-08 13:26:43 -04:00
Zed A. Shaw
d6e2b64140 icongen now makes a sprite sheet for the map which should be easier to work with. 2025-07-08 13:09:39 -04:00
Zed A. Shaw
dbc2000434 Started a map icon gen tool that will load the fonts and create tile sprites for everything I use. 2025-07-08 00:55:45 -04:00
Zed A. Shaw
056b0b307b Implemented a little screenshot tool. 2025-07-08 00:55:24 -04:00
Zed A. Shaw
f64b202ee7 Finally have inventory not crashing for most edge cases. This solves many bugs but mostly closes #58. 2025-07-07 13:25:17 -04:00
Zed A. Shaw
601f3331ed As an experiment, disable copy and move of the StatusUI. 2025-07-06 23:59:06 -04:00
Zed A. Shaw
cd89625c96 Just need one function for the 'hold_item' action. 2025-07-06 23:35:17 -04:00
Zed A. Shaw
265e53e05a Simple fix, and honestly I should eliminate this whole thing and use one unified event system. Closes #1. 2025-07-06 12:05:28 -04:00
Zed A. Shaw
af3568154a Just had to grab the sprite, duh. Closes #3. 2025-07-06 11:36:30 -04:00
Zed A. Shaw
1baf90a776 Easy fix, just set aiming_at in the camera position. Closes #57. 2025-07-05 12:04:07 -04:00
Zed A. Shaw
a26f0b0c0a Player's aim is now updated constantly as they move, just need to solve #57 to complete it. Closes #9. 2025-07-05 11:18:26 -04:00
Zed A. Shaw
584c4e9f67 Make the AIM_CLICK handler in FSM properly deal with an item already there while looting or not. Closes #56. 2025-07-03 22:26:06 -04:00
Zed A. Shaw
87e69bebde There was a memory corruption bug in remove() because I get a reference to the slot string, then remove it from by_entity, but that deletes the string so then later using it to remove by_slot silently fails because map.erase() silently fails. Closes. #54. 2025-07-03 13:07:04 -04:00
Zed A. Shaw
970905fcd5 Make the player's inventory just a regular entity attached to the player.entity. 2025-07-02 23:55:06 -04:00
Zed A. Shaw
2421a33bb0 Swapping and putting back now work in the status_ui inventory, but now I need to refactor so this operation works on any inventory::Model. 2025-07-02 23:24:06 -04:00
Zed A. Shaw
784f753e72 Standardized on using only DinkyECS:Entity for most inventory:::Model operations, then create swap based on the same entities. 2025-07-02 14:25:44 -04:00
Zed A. Shaw
8c8d6dc9e7 Clean things up before solving the move problem. 2025-07-02 10:51:23 -04:00
Zed A. Shaw
6576164fad Give a healing potion too for testing. 2025-07-02 10:49:05 -04:00
Zed A. Shaw
b6d1ae2700 Move the management of the 'fake loose items container' into the loot_ui.cpp rather than get rid of it. Closes #34. 2025-07-01 14:26:39 -04:00
Zed A. Shaw
efdb0cb119 Just use get_if here instead. 2025-07-01 14:26:01 -04:00
Zed A. Shaw
8bbafc4d10 Raycaster now keeps track of the square we are aimed but _does not_ know what is there, that's the job of other things like MainUI. Closes #50. 2025-06-30 12:36:00 -04:00
Zed A. Shaw
0d79ce35b3 Every sprite's dimensions are now taken from their config rather than a global. Closes #42. 2025-06-30 11:00:01 -04:00
Zed A. Shaw
a418b48e94 Don't re-run the whole next level thing on every spawned item. Closes #48 2025-06-30 10:38:53 -04:00
Zed A. Shaw
b28b76ee2d Ritual blanket now has its own internal id but I'm sort of thinking it needs to be more like inventory::Model. Closes #47. 2025-06-30 10:15:22 -04:00
Zed A. Shaw
cad51f4908 Use RGBA for the uint32_t color pixels. Closes #49. 2025-06-29 11:53:17 -04:00
Zed A. Shaw
ab1a415b55 Refactored the CameraLOL to be inside the rayview instead of a convolute main_ui->camera->rayview and back. Closes #16. 2025-06-29 11:11:12 -04:00
Zed A. Shaw
75c28cd764 Fixed a few places. Closes #11 2025-06-28 23:30:41 -04:00
Zed A. Shaw
b603ef5a3f Forgot to update the level in the RitualUI so nothing actually worked. Closes #41. 2025-06-28 23:17:36 -04:00
Zed A. Shaw
6a0725e401 Simply re-init the overlay on new level. Closes #14. 2025-06-28 22:39:46 -04:00
Zed A. Shaw
02c42eb042 System::distribute_loot now manages setting up loot junk and does a new entity instead of reusing old ones, that allows System::death to do a coorect world->destroy() on the dead thing. Closes #46. 2025-06-28 13:19:07 -04:00
Zed A. Shaw
6437bd3b54 Now have a 'destroy' method that removes everything related to an entity. Closes #18. 2025-06-28 12:47:17 -04:00
Zed A. Shaw
7602fb0b31 Not using Weapon anymore. 2025-06-28 11:53:48 -04:00
Zed A. Shaw
57d69015c2 Renamed to random_walk since that's what it called. Closes #26. 2025-06-28 11:38:06 -04:00
Zed A. Shaw
769530b45c Now standardized on GameConfig everywhere I can. Closes #28. 2025-06-28 11:32:58 -04:00
Zed A. Shaw
b0204772c7 Need to not transition out of END if the slot clicked is empty. Closes #45 2025-06-28 11:09:37 -04:00
Zed A. Shaw
19682fd0bc Add the frame width/height to SpriteTexture. Closes #13 2025-06-27 01:21:50 -04:00
Zed A. Shaw
ea92dcc3c4 Change from ENEMY_SPAWN to ENTITY_SPAWN since that's what it does. Closes #31 2025-06-26 23:22:22 -04:00
Zed A. Shaw
fcd1bc589c Make a function to access overlay cells Closes #35. 2025-06-26 23:17:53 -04:00
Zed A. Shaw
f668ff6b7a First round of cleanup. dnd_loot. 2025-06-25 14:28:35 -04:00
Zed A. Shaw
689bb150c6 I think that's all the edge cases handled. You can more loot around fairly arbitrarily. 2025-06-24 14:00:14 -04:00
Zed A. Shaw
6ff1919587 Cleaned up the move operation more so that I can use it in the other places that I need it. 2025-06-24 13:23:55 -04:00
Zed A. Shaw
f559b5a39d Fixed the problem where the only way to complete a grab/drop operation was to capture the MOUSE_CLICK directly. Solution was to move the mouse processing out of DNDLoot and only handle the MOUSE_MOVE/DRAG. 2025-06-24 11:33:37 -04:00
Zed A. Shaw
6a72d1160f When things die you get their things. 2025-06-23 01:50:43 -04:00
Zed A. Shaw
fb064ffbf1 Loot boxes now have ritual items and you can click on them, or the enemy just dies. 2025-06-23 01:33:09 -04:00
Zed A. Shaw
3c5021e4c9 So far most of the bugs are solved but there's still some edge cases in the inventory dance. 2025-06-22 23:54:50 -04:00
Zed A. Shaw
e0588847fa Tracked down the bug that was caused by picking up an item but not removing its Position in the world, so when you go to another level it gets brought back to life causing a dupe. 2025-06-22 12:50:09 -04:00
Zed A. Shaw
2c6565c40a Kind of jank but the old functionality is back, and now needs to move to loot ui dealing with any container. 2025-06-21 11:01:12 -04:00
Zed A. Shaw
812407c3df Now the loot UI can work with any container and only uses an ECS id to work, not have its own contents. 2025-06-21 10:51:45 -04:00
Zed A. Shaw
a0eff927b6 Big BIG refactor to make inventory use a model that's placed into the world, following a more sane MVC style. 2025-06-20 13:17:12 -04:00
Zed A. Shaw
119b3ed11d Can now drag an item out of inventory and drop on the ground, then pick it back up, and put it in a loot container, and then back again. Still buggy but working for now. 2025-06-19 00:45:22 -04:00
Zed A. Shaw
68e50342e5 Can now drag an item out of inventory and drop it. 2025-06-18 11:26:38 -04:00
Zed A. Shaw
87459d41bb Add the buttons I'll need for the next round of development. 2025-06-17 12:46:17 -04:00
Zed A. Shaw
dfd3118d04 Make the transitions more solid by having an open/close set of functions to maintain cleaning up internal state. 2025-06-17 12:24:11 -04:00
Zed A. Shaw
029a0f86ae Drag now show the icon while you're dragging, so now need to work out all of the edge cases for each action. 2025-06-17 11:50:03 -04:00
Zed A. Shaw
ca74b817e5 You can grab stuff off the ground and put in your inventory but it doesn't show the sprite while you do it yet. 2025-06-15 00:12:46 -04:00
Zed A. Shaw
cd02507023 Make a function that handles the mouse events for everything since those are very similar. 2025-06-14 22:56:23 -04:00
Zed A. Shaw
d99d9a68c8 Tried to use Ragel to create state machines but its lacking an incremental mode and doesn't do any logging of state activity so debugging is harder. Put it in scratchpad for reference though. 2025-06-14 12:34:27 -04:00
Zed A. Shaw
7fc32b0248 Trying out Ragel's state machine generation as an alternative to the DinkyFSM style. 2025-06-14 00:43:40 -04:00
Zed A. Shaw
9468990f76 DNDLoot works now, just had to fix a problem with the constructor. 2025-06-13 10:46:05 -04:00
Zed A. Shaw
82ee8f68f7 Created a separate FSM for the DND functionality that compiles but need to wire it in to work. 2025-06-13 00:57:45 -04:00
Zed A. Shaw
1ab708c4eb Clean up more of the FSM so that it's almost nothing.Now I'll try to make a stand-alone 'dnd' state machine to handle drag and drop functionality. 2025-06-12 22:51:58 -04:00
Zed A. Shaw
06a843f169 Autowalker does some basic item pickup now, just for testing. 2025-06-12 20:12:13 -04:00
Zed A. Shaw
af933c827a Have a separate container vs. item loot for the different situations where you're pick items out of a container vs. an item on the ground. 2025-06-12 19:41:32 -04:00
Zed A. Shaw
7db64b73c5 Made some notes for the next bit of work. 2025-06-12 13:45:54 -04:00
Zed A. Shaw
7b0bac4f59 You now click on things to interact with them. 2025-06-12 13:24:25 -04:00
Zed A. Shaw
2aa4f0a2e8 Finally can pick things up, but it's really bad so far. Need a bunch of refactoring in how the collision system works, and make it so collision and maps can have multiple entities in the same square. 2025-06-12 13:06:36 -04:00
Zed A. Shaw
2458f01ebd Loot UI now opens when you can loot something, but it's still buggy and doesn't always show the stuff. 2025-06-12 00:10:21 -04:00
Zed A. Shaw
86eabed3db Now when you loot an item the loot UI works. 2025-06-11 23:49:37 -04:00
Zed A. Shaw
38159a5f84 Fix the window coordinates so that you can resize. 2025-06-11 00:56:41 -04:00
Zed A. Shaw
d6c5a89251 Fix the last few loot bugs before actually implementing the data model for inventory and loot. 2025-06-10 22:58:57 -04:00
Zed A. Shaw
4a48910273 There's a UISystem now for to compliment the entities and components in GUECS. I now use that to do the drag/drop transfers instead of raw code right in the FSM. 2025-06-10 13:13:40 -04:00
Zed A. Shaw
e01e697535 Move now works better, and the API is a lot cleaner. Now just need to make it not crash. 2025-06-10 11:12:04 -04:00
Zed A. Shaw
be7b86a913 Mostly refactored out the common things for drag/drop so now just to refine how it's used and bring back moving the sprite around. 2025-06-10 00:52:38 -04:00
Zed A. Shaw
570b70ab0c More of the drag/drop is handled by the GrabSource/DropTarget components. 2025-06-09 23:59:44 -04:00
Zed A. Shaw
7a551cf83a Remove commit_drop from status and loot UI since DropTarget already does that. 2025-06-09 22:57:49 -04:00
Zed A. Shaw
343f3a246f Cleaned up and unified the source before the big refactor. 2025-06-09 22:31:15 -04:00
Zed A. Shaw
0d6a71b06f Fixed a couple little bugs in the state so now can refactor out the dnd code. 2025-06-09 22:18:13 -04:00
Zed A. Shaw
2a6b892e7f Can now round-trip a torch from loot to inventory and back. 2025-06-09 14:02:26 -04:00
Zed A. Shaw
4b0d76bbcc Even better API, but still not the best organization. This will let me implement both sides, then I can pull it out and try to generalize it into a few guecs components. 2025-06-08 23:55:59 -04:00
Zed A. Shaw
3e0adf0c22 Better meaning API on both sides for the drag-n-drop operations, but I _swear_ there's a way to do this in the GrabSource/DropTarget instead. 2025-06-08 23:27:43 -04:00
Zed A. Shaw
47c219b86e Disable inventory select for now until I can get drag-n-drop formalized better. 2025-06-08 22:15:25 -04:00
Zed A. Shaw
e1c2869d1c Sometimes we click too fast in the router to just handle it in IDLE. 2025-06-08 22:06:12 -04:00
Zed A. Shaw
461ad03d27 Taking things from the LootUI to the StatusUI works way better now and there's a DropTarget to match the GrabSource. 2025-06-08 00:37:30 -04:00
Zed A. Shaw
842aac3127 Worked out an initial stab at a GrabSource for drag-n-drop or just simple grabbing things in the UI. 2025-06-07 15:29:18 -04:00
Zed A. Shaw
94385b195d Mostly worked out how to do looting but now need how to take out of inventory and put into loot. 2025-06-07 00:11:29 -04:00
Zed A. Shaw
c509162be1 The event router is working well and I can do drag-n-drop but I'll have to rethink where to use it. 2025-06-05 23:31:38 -04:00
Zed A. Shaw
5aa54d875f Initial first steps in pulling the SFML event processing out of the gui::fsm so that I can handle more complex things like drag and drop. 2025-06-05 01:23:52 -04:00
Zed A. Shaw
0674908e49 Implemented an initial cut at the event router. Its job is to take the random events from SFML and translate them into nice clean orderly events to the Gui::FSM. 2025-06-04 12:19:24 -04:00
Zed A. Shaw
5c47a0151c Basic loot UI mostly working. Each time you open there's a torch and you can place it visually on any slot on your character. 2025-06-03 13:43:16 -04:00
Zed A. Shaw
4b34de2109 Initial loot UI works to load an item by its world entity ID. 2025-06-02 23:34:31 -04:00
Zed A. Shaw
f208ca946e Made the components module work like textures and sound so that there's just one constant map of components. 2025-06-02 23:33:59 -04:00
Zed A. Shaw
ab391aaa97 Have a plan for the new inventory and looting system, now have to implement it. Temporarily you can't pick anything up, but it will go away. 2025-06-02 00:58:16 -04:00
Zed A. Shaw
b8d2d1870d Clean up the debug UI so that it's not using the jank debug component I didn't use anyway. 2025-06-01 11:10:25 -04:00
Zed A. Shaw
e8199a973c Fix up the healing potion so it looks more like a healing potion. 2025-05-30 22:31:03 -04:00
Zed A. Shaw
d2a5dfa713 Rooms are now styled randomly based on assets/styles.json which will evolve into specifications for themes of levels and rooms in them plus other configs. 2025-05-30 20:35:17 -04:00
Zed A. Shaw
e45de2a2cf The config now prints a way better error message if you give it a bad file to use. 2025-05-30 19:53:53 -04:00
Zed A. Shaw
dc8648016d Refactor the way assets are laid out in the assets/ dir and then have a build script that can automatically pixelate/posterize images that I save, saving me tons of time. 2025-05-30 17:49:15 -04:00
Zed A. Shaw
3dc70c3af6 This implements base ambient lighting for tiles which helps with tiles like lava and ceiling lights. 2025-05-29 12:34:25 -04:00
Zed A. Shaw
74a1801069 More scripts for converting and pixelating images for the game. 2025-05-29 12:31:59 -04:00
Zed A. Shaw
cdd58ee21a Another nice scritp from fred. 2025-05-29 12:30:51 -04:00
Zed A. Shaw
31df3fe7a3 Better light ceiling and floor tiles. 2025-05-29 00:44:52 -04:00
Zed A. Shaw
dd463d7d6e Did a bunch of pixelation tests and I think this is the best setup so far. 2025-05-26 23:36:22 -04:00
Zed A. Shaw
931d9493d2 The raycaster can now pair a floor with a ceiling tile and to demonstrate this I have a blue light that shines on to a stone floor. I also played with just pixelating a regular image rather than painting it and honestly it looks better in a lot of ways. 2025-05-26 13:59:26 -04:00
Zed A. Shaw
e015652f4c Now have the ability to load different textures for the floor, not ceiling though, it just matches the floor. 2025-05-26 00:29:32 -04:00
Zed A. Shaw
8453e7c3b9 Map is back. 2025-05-25 22:39:42 -04:00
Zed A. Shaw
af2947c50a Simple styling of the rooms done. 2025-05-25 12:12:08 -04:00
Zed A. Shaw
5cb74151f5 Remove more dead code from texturemgr. 2025-05-25 11:44:14 -04:00
Zed A. Shaw
3a745d492a Refactored out the tilemap since it was mostly doing nothing useful. 2025-05-25 11:39:43 -04:00
Zed A. Shaw
ea9f6bf383 Prior to deleting the TileMap to see if I can just replace it with new features in Map and textures::. 2025-05-25 10:30:45 -04:00
Zed A. Shaw
f45dbe8c48 Ready to refactor the tilemap so I can stylize different parts of the maps generated. 2025-05-24 12:34:45 -04:00
Zed A. Shaw
96a585220b Raycaster now leaves colors that are above a threshold to have a 'glow' effect. 2025-05-24 12:03:26 -04:00
Zed A. Shaw
c0d668fb0b Played around with a circular map real quick. 2025-05-24 10:58:28 -04:00
Zed A. Shaw
9dcc2036aa Trying a new 'glowing moss' texture to sort out how to make the raycaster alter the light of a surface that has its own light. 2025-05-24 00:47:44 -04:00
Zed A. Shaw
e361984c40 Fixed a long standing bug I didn't realize where I did -1 on the map in the raycaster which made the textures not actually work. 2025-05-24 00:47:01 -04:00
Zed A. Shaw
90c37fe4c9 Fixing up how rotation works with combat and then making the lighting better. 2025-05-22 14:25:42 -04:00
Zed A. Shaw
4eaf3c35d6 Fixed up the map generator so that it's placing entities in non-overlapping tiles and adapting the style for the size. It can also deal with maps that have no rooms better and places the stairs better. 2025-05-22 12:24:59 -04:00
Zed A. Shaw
5f1a453fb4 Refactored the maze functions to be a builder that can do different things to the maze. Also when I hit p in the game it'll save the map to a file. This was extremely hard for no reason. 2025-05-21 13:56:53 -04:00
Zed A. Shaw
20f03731e5 Cleaned up the maze placement so that I can have mazes without rooms and with other features. 2025-05-20 12:53:03 -04:00
Zed A. Shaw
37715f05a5 Cleaned up maze and ready to use. 2025-05-20 10:32:20 -04:00
Zed A. Shaw
33cd490ed3 Playing with maze gen again. 2025-05-20 03:19:58 -04:00
Zed A. Shaw
c97648ab3a Remove useless log messages and bring back the tests. 2025-05-19 11:40:56 -04:00
Zed A. Shaw
ac252bf09d Maze works well now and there's something placed in all rooms and dead ends. Will need to randomize it more so not every dead end is an enemy. 2025-05-19 11:19:33 -04:00
Zed A. Shaw
a0b785cb2a Hunt-and-kill algorithm rocks. It handles everything I need for map gen, including spawn points, room placement, and the maze like map. 2025-05-19 01:40:23 -04:00
Zed A. Shaw
0f8e61797f Now using a hunt-and-kill maze algorithm. 2025-05-18 14:37:43 -04:00
Zed A. Shaw
7a0b2f988d Add a terrible maze generation algorithm to test if a maze style map looks/feels better. The walls are disabled so you can walk around. 2025-05-18 01:00:47 -04:00
Zed A. Shaw
6cbfcf993e Meson build was using the wrong sfml_main on windows. 2025-05-16 23:40:13 -04:00
Zed A. Shaw
0eb245d113 Working on a better character view. 2025-05-16 01:22:12 -04:00
Zed A. Shaw
d6e64dd06b The log is now moved to the map, but changing StatusUI caused a weird compiler error so need to remove logs from that separate. 2025-05-16 00:43:45 -04:00
Zed A. Shaw
a2246d2b71 Move the map_view and mini_map into gui as well. 2025-05-16 00:07:24 -04:00
Zed A. Shaw
bed5ce22d2 Move gui_fsm to fsm but this causes some problems. 2025-05-15 23:54:59 -04:00
Zed A. Shaw
cc44c9d37a Move the guecstra stuff into the gui. 2025-05-15 22:50:59 -04:00
Zed A. Shaw
dfc6aa08e9 Loot UI is now mostly formed, just need to get loot into it and make it work. 2025-05-14 11:49:09 -04:00
Zed A. Shaw
8545b8cf1d Simple Loot UI started. 2025-05-14 00:51:53 -04:00
Zed A. Shaw
8a3046e141 The colors and other theme elements can be configured in assets/config.json 2025-05-13 22:52:27 -04:00
Zed A. Shaw
74a8599977 Fully converted to using the lel-guecs library externally now. 2025-05-13 02:48:39 -04:00
Zed A. Shaw
7c90eb6da1 GUECS now doesn't have the facts feature from DinkyECS and instead you refer to the whole area with gui.MAIN. This is an entity that's at 0 and represents the whole grid. Background is placed there. 2025-05-04 23:40:06 -04:00
Zed A. Shaw
abea6da2e0 More GUECS cleanup before releasing. Still need to sort out events and reduce the amount of stuff that GUECS needs. 2025-05-04 23:28:36 -04:00
Zed A. Shaw
1780a758b3 Initial GUECS refactor is done, it's now on its own with no other dependencies, but now I need to trim it down to do only what it needs. 2025-05-04 11:56:30 -04:00
Zed A. Shaw
20176cf54a GUECS refactor part 1. 2025-05-04 11:06:53 -04:00
Zed A. Shaw
4e7f837240 Cleanup of GUECS and the textures manager. 2025-05-03 23:38:03 -04:00
Zed A. Shaw
438bd8ab8a Finally upgraded the strings to const& since I'm about to pull guecs out and distribute it. Oh well, the joke's finally over. 2025-05-03 14:52:56 -04:00
Zed A. Shaw
82ce3cb6be Autowalker now knows how to craft its first weapon and open the map. 2025-05-03 12:19:02 -04:00
Zed A. Shaw
70d27b9a95 GUECS now has a click_on function so you can programatically click on buttons for testing. 2025-05-03 12:18:39 -04:00
Zed A. Shaw
78ba83e916 Move the map opened detect out to the class. 2025-05-02 23:41:29 -04:00
Zed A. Shaw
c4ed26184b Autowalker now opens the map at first to test that it works. 2025-05-02 23:39:05 -04:00
Zed A. Shaw
edf10c976a Cleaned up the ritual UI some more and solved a few more bugs, then brought in a quick 'dubious combination' image. 2025-05-02 11:39:39 -04:00
Zed A. Shaw
bac552c3d7 Ritual ui now does the combination correctly. 2025-05-02 00:23:07 -04:00
Zed A. Shaw
dab0e092e6 RitualUI is mostly working, but need to make the consumption of items work in the UI. 2025-05-01 23:46:30 -04:00
Zed A. Shaw
6269d10807 The ritual UI is now a lot better using a FSM to control everything. Probably one more session to work out the remaining functionality. 2025-05-01 14:40:24 -04:00
Zed A. Shaw
8a1f42c0f1 RitualUI is now ritual::UI and uses a FSM to coordinate its activities. 2025-05-01 00:24:11 -04:00
Zed A. Shaw
d1bd6b7c45 Mostly does everything I need, minus the ritual description. That'll have to probably be a separate generator. Next, rewrite this crap. 2025-04-30 11:39:42 -04:00
Zed A. Shaw
2ceab51c40 A really shitty ritual crafting UI is working but needs a big reshape. 2025-04-29 23:59:40 -04:00
Zed A. Shaw
14619558fa Better UI for the ritual crafting that almost works, but need to get the selected items to move down. Might need some state machine love soon. 2025-04-28 13:21:10 -04:00
Zed A. Shaw
9d55b2954a The rituals can now craft from items taken from dead enemies and they go into the blanket right away. 2025-04-27 13:48:35 -04:00
Zed A. Shaw
1a9e068d02 Junk items are now transfered to your blanket so you can use them in crafting. No UI for that though. 2025-04-27 13:35:05 -04:00
Zed A. Shaw
bc557652ba The player now has some starting items to craft a first weapon, and it is craftable in the UI. 2025-04-26 13:18:43 -04:00
Zed A. Shaw
c8a8d2b1af You can now craft a single ritual from the blanket. 2025-04-26 02:51:13 -04:00
Zed A. Shaw
292711f91f Prep for the actually making ritual crafting work. 2025-04-26 02:21:59 -04:00
Zed A. Shaw
ad1d08ca96 There's now an hp status indicator 'doll' when you click on it your host (character) will tell you how they're doing for HP. 2025-04-26 00:57:23 -04:00
Zed A. Shaw
dac9b1b3de rcrnstn found a way to make the shaders work under MESA by forcing the version number to 120 and no default params in functions. 2025-04-25 23:36:18 -04:00
Zed A. Shaw
1ab5fa4291 Fix from ORBLISH suggestion to stop any component that's not hover/clicked on in the mouse handler. 2025-04-25 23:17:45 -04:00
Zed A. Shaw
4c03fe1ed3 Make the raycaster 'highlight' things you point at. 2025-04-25 23:17:31 -04:00
Zed A. Shaw
bc31750d9c Fix from ORBLISH suggestion to stop any component that's not hover/clicked on in the mouse handler. 2025-04-25 23:17:14 -04:00
Zed A. Shaw
8aeac5397a Windows installer fix before 0.2 release. 2025-04-25 12:17:00 -04:00
Zed A. Shaw
2fb1687997 Now have sounds and shaders working on the button for each of the different elements. 2025-04-25 11:54:30 -04:00
Zed A. Shaw
eb350698aa Only default mute sounds in debug. 2025-04-25 02:12:44 -04:00
Zed A. Shaw
e0d7744eeb Make file now detects windows or not and does the weird thing. 2025-04-25 01:48:40 -04:00
Zed A. Shaw
5aa9bcb655 Remove stray log. 2025-04-25 01:48:23 -04:00
Zed A. Shaw
c51d46aeb8 Meson build now attempts to force local only build and linkage. 2025-04-25 00:55:58 -04:00
Zed A. Shaw
57e8774fad Make the make more linux friendly. 2025-04-25 00:17:24 -04:00
Zed A. Shaw
eb709930f5 Combat UI now uses different icons for different attack elements. 2025-04-24 23:48:25 -04:00
Zed A. Shaw
30997cbff5 Test rituals are now configurable in assets/config.json 2025-04-24 23:06:15 -04:00
Zed A. Shaw
ebb69dd589 Rituals are now taken from the belt and shown in th combat_ui and in the system::combat. They aren't used in combat calcs yet though. 2025-04-24 13:43:57 -04:00
Zed A. Shaw
00c28f47eb Rituals are now being added a belt on the player in a temp function in LevelManager. 2025-04-24 12:27:29 -04:00
Zed A. Shaw
a70f11646a RitualBelt now has an API. 2025-04-24 03:32:20 -04:00
Zed A. Shaw
31b35b43eb Added the ritual belt first cut. 2025-04-24 03:06:31 -04:00
Zed A. Shaw
17d30e2ed2 Add a dump function and clean up some data. 2025-04-24 02:44:07 -04:00
Zed A. Shaw
5d924c764f Rituals can now be configured to have a kind and an element based on the results. 2025-04-24 02:03:18 -04:00
Zed A. Shaw
a342c53b02 RitualEngine now uses the crafting results to create a description of the ritual's combat in a RitualAction struct. 2025-04-24 01:15:49 -04:00
Zed A. Shaw
43435509f6 Fixed system to use the BattleEngine result. 2025-04-24 00:45:25 -04:00
Zed A. Shaw
bf8a2dc0c5 Simple quick way to do different attacks that play different shaders. 2025-04-23 12:32:28 -04:00
Zed A. Shaw
58981fd8ed Setting up to have a fire attack and lightning attack. 2025-04-20 22:53:43 -04:00
Zed A. Shaw
787be78a69 Now I can attach arbitrary shaders to sprites based on things that happen in the world. 2025-04-20 00:09:56 -04:00
Zed A. Shaw
bec8fe0a13 Note from ORBLISH on idea for hover sounds. 2025-04-17 23:05:26 -04:00
Zed A. Shaw
1b4f55804c The flame shader now only turns on when facing an enemy. Next is tagging enemies with specific shaders to apply at a specific time. 2025-04-16 00:02:27 -04:00
Zed A. Shaw
5ffa3b0d1e Everyone is on fire temporarily. 2025-04-15 19:34:39 -04:00
Zed A. Shaw
467a26628c Wrong shader. 2025-04-15 12:47:07 -04:00
Zed A. Shaw
137dcc1f30 Missing resources. 2025-04-15 12:46:13 -04:00
Zed A. Shaw
57e042e786 Now have a do_if on GUECS for many of the 'if this exists do this' patterns. 2025-04-15 12:02:24 -04:00
Zed A. Shaw
2ecef8d9f9 Have a basic little click sound going, but hover events will need some work. I'm doing those on every mouse move. 2025-04-15 11:38:38 -04:00
Zed A. Shaw
7186c2ecb0 I think this is the best I can do for a hover vs. click shader effect. Just do it in a shader based on a uniform setting. 2025-04-15 01:01:44 -04:00
Zed A. Shaw
84a5f06dac Reworked the way shaders are configured to reduce the amount of times clicks on buttons cause the shared shaders to reset. 2025-04-14 23:06:08 -04:00
Zed A. Shaw
19b9a4affd The reload mechanism for shaders is a bit better, but still to make them unique. 2025-04-14 13:16:19 -04:00
Zed A. Shaw
08bc48df3d GLSL smoothstep is NOT lerp, it's 'Hermite linear interpolation' which basically means not a damn thing anyone says it is. mix is what I want. 2025-04-14 12:12:21 -04:00
Zed A. Shaw
766b20f3f8 Rayview now uses the shader manager. 2025-04-13 22:31:13 -04:00
Zed A. Shaw
edee3ac0c9 Quick test that shows the shader now just work on any UI element. 2025-04-13 17:16:27 -04:00
Zed A. Shaw
35ced58cc9 Shaders now are managed by a manger that can do hot reloading and it also will detect a bad shader and use an ERROR shader so you know it's busted visually. 2025-04-13 17:11:21 -04:00
Zed A. Shaw
a5b8e411e3 I can now apply shaders to any GUI element, but I need a shader manager that will allow for hot reloading and tracking input/output variables. 2025-04-13 15:17:08 -04:00
Zed A. Shaw
80b4faf940 Added a screen size parameters to the fragviewer. 2025-04-11 11:44:33 -04:00
Zed A. Shaw
576110ea44 Fragviewer can now load a sprite from my sprite list and then apply shaders to it. 2025-04-10 23:42:45 -04:00
Zed A. Shaw
724d3edb61 Wrote my own quick and dirty fragment shader viewer. 2025-04-09 23:59:09 -04:00
Zed A. Shaw
b5d93399d5 Converted the buttons to reflect the actions you can take. 2025-04-08 14:36:51 -04:00
Zed A. Shaw
d7e9944e58 Change the buttons to text for development until I can get the icons/art. 2025-04-08 13:01:56 -04:00
Zed A. Shaw
e11a374d26 No need to compile arena anymore. 2025-04-08 13:01:37 -04:00
Zed A. Shaw
5a3b567fd1 Solve a problem where if you give a name for cell and the name doesn't exist you get a crash during world query in GUECS. 2025-04-08 13:01:24 -04:00
Zed A. Shaw
0e2f213871 Added in a new art for a 'gold savior' and refined the battle engine more but it's not quite what I want. 2025-04-07 14:02:32 -04:00
Zed A. Shaw
ca328e10dc Rework the source so that battle is in its own thing to work on. 2025-04-07 10:35:30 -04:00
Zed A. Shaw
e6a8a8b338 Fixed the map so that it shows directional arrows instead of a compass. 2025-04-06 23:29:25 -04:00
Zed A. Shaw
c7c48658bd Lots of dumb little edits to sort out what I'm aiming at. I'll next clean out most of this in a refactor. 2025-04-06 15:32:19 -04:00
Zed A. Shaw
1f90367f51 Initial battle engine is now integrated in the systems so now I can finally get the turn based combat to work the way I envision. 2025-04-06 00:45:51 -04:00
Zed A. Shaw
e18aeaf05c Bring back a simple blood splatter texture. 2025-04-05 17:48:24 -04:00
Zed A. Shaw
b832bbd78a Fixed how sprites/textures are loaded so tehy default to frame 0 of any multi-frame textures. 2025-04-05 17:17:26 -04:00
Zed A. Shaw
6d73c87c4e Debug UI now has little icons for each enemy and can spawn any enemy. Also I forgot the files. 2025-04-05 12:25:34 -04:00
Zed A. Shaw
07ce8a4148 New debug_ui that shows perf data, other debug info, and allows spawning enemies. 2025-04-05 12:09:19 -04:00
Zed A. Shaw
4f090159ab Started working on this 'arena tester' tool that would let me load an enemy and test them, but then realized I could just make it so I can spawn enemies in the game. I'm keeping the arena around as it will be useful later as a scriptable testing tool, but for now just spawn and test. 2025-04-04 12:45:55 -04:00
Zed A. Shaw
b6c1eba1b3 Actually I can just use the ai::distance_to_goal function on the fit_sort to sort by cost and distance. 2025-04-03 10:25:41 -04:00
Zed A. Shaw
c1aba2d5c8 This does a 'fit_sort' whenever the state is changed. fit_sort effectively sorts the actions by distance+cost so that the cost is actually present unlike the original algorithm. 2025-04-03 10:14:50 -04:00
Zed A. Shaw
c014e65c13 Gave up on trying to get the GOAP algorithm to correctly apply the cost structure to competing choices, and instead I take the resulting action list and simply find the next best one based on cost. 2025-04-01 13:48:59 -04:00
Zed A. Shaw
52f45e1d45 Mostly fixed up but I have to figure out why cost on actions isn't changing the priority. 2025-03-31 13:51:27 -04:00
Zed A. Shaw
862d8b4d81 Now have a cycle and repeated action mitigation technique in the AI algorithm called 'delete shit you've seen'. 2025-03-31 11:27:48 -04:00
Zed A. Shaw
6fa7b0a418 Accidentally committed code during testing. 2025-03-30 13:41:43 -04:00
Zed A. Shaw
0ebc60793a Brought back the closed_set to avoid visiting nodes already handled. 2025-03-30 12:55:59 -04:00
Zed A. Shaw
922fbeba0e AI now follows the A* algorithm more closely by using a separate priority queue from the open_set. 2025-03-30 12:37:34 -04:00
Zed A. Shaw
72951f308f Converted almost everything to use wstring so that it works better with SFML and the unicode/utf8 usage in the system. 2025-03-28 12:40:46 -04:00
Zed A. Shaw
47c6bfd531 AI engine is working and I have a little BattleEngine going but the AI is working better than it should in systems.cpp. Need to find out why then make the BattleEngine avoid running entities that have END in action lists. 2025-03-26 13:34:52 -04:00
Zed A. Shaw
da273cbee6 Refactored rituals so they can be used in different situations. 2025-03-24 12:30:58 -04:00
Zed A. Shaw
5af9a6664e Have a few basic monochrome test items and the first little leather pouches on the 'tool belt'. 2025-03-23 11:34:50 -04:00
Zed A. Shaw
d7ff7d6acf Map view now displays a simple status message, more to come. 2025-03-23 00:25:11 -04:00
Zed A. Shaw
6fe343d82d Bad commit previously, but not minimap updates. 2025-03-23 00:06:16 -04:00
Zed A. Shaw
322797f787 Now have a full map and a mini map, but I think the mini map will stop rendering sometimes. 2025-03-23 00:04:23 -04:00
Zed A. Shaw
193d97eb48 Bring over the dbg.h to see if it's usefule. 2025-03-22 23:21:12 -04:00
Zed A. Shaw
2e79cf8781 Map is way better and components::Tile is _vastly_ improved by switching to a wchar_t on display and letting nlohmann::json auto convert it for me. 2025-03-22 02:10:56 -04:00
Zed A. Shaw
2b57552152 Not the greatest but this is kind of what I want for the map. 2025-03-21 11:12:04 -04:00
Zed A. Shaw
6c9016eb0f After some prototyping I have what I think I want for the map. Just a simple piece of paper you take out that has the ASCII map on it. 2025-03-21 02:51:02 -04:00
Zed A. Shaw
acbf384e2a Fixed some of the easing functions but still not sure with RAT_GIANT doesn't move. 2025-03-20 04:25:15 -04:00
Zed A. Shaw
a53f81715d Have a basic map prototype gui working. 2025-03-20 04:13:22 -04:00
Zed A. Shaw
8b3573b01d Basic Ritual crafting UI is prototyped, so next step is to create some items and refine the UI with a possible FSM to keep it organized. 2025-03-20 03:25:35 -04:00
Zed A. Shaw
1aa6674e42 Created a nice utility library for doing animations, and used it in the ritual crafting UI. 2025-03-20 01:10:01 -04:00
Zed A. Shaw
0a40135f5d Throw in the distance to mess with it later. 2025-03-19 22:34:56 -04:00
Zed A. Shaw
65c9e4b0c6 Initially implemented 'ritual blanket' UI for the crafting of rituals in combat. 2025-03-19 22:10:17 -04:00
Zed A. Shaw
263b7741f6 The ritual UI is now in its own thing, but not hooked up yet. 2025-03-19 00:48:43 -04:00
Zed A. Shaw
f1cc9f86c1 Very early prototype of the ritual crafting UI, but it needs its own thing. 2025-03-19 00:14:43 -04:00
Zed A. Shaw
a6d83db20c Fixed up dbc.cpp so now just use it everywhere. I next need to find a way to pass that to format automatically. 2025-03-17 23:53:58 -04:00
Zed A. Shaw
2baa044695 Final little fixes for testing. 2025-03-17 23:36:14 -04:00
Zed A. Shaw
5ed8196c80 Brought line numbers back for the dbc.cpp logging stuff. May not work in clang because of the bug they have (had?). 2025-03-17 23:16:51 -04:00
Zed A. Shaw
0efb17371b Now have a simple stats test. 2025-03-17 22:56:18 -04:00
Zed A. Shaw
d3158291f7 Did a full code coverage review and improved many of the tests and a bunch of code. I'll do one more final walk through all the code before getting back to work on the new combat system. 2025-03-17 15:23:47 -04:00
Zed A. Shaw
113a4a3b3e Now have a coverage report. 2025-03-17 00:21:27 -04:00
Zed A. Shaw
c4611c0138 Right before coverage destroys everything. 2025-03-16 23:17:43 -04:00
Zed A. Shaw
1d2968f826 Move the ritual stuff to the combat namespace. 2025-03-16 13:46:40 -04:00
Zed A. Shaw
49531ba148 Rituals are more or less sorted out in theory, and they helped find a cycle in the GOAP algorithm that I'm detecting/preventing. 2025-03-16 13:34:38 -04:00
Zed A. Shaw
8368d2e751 Prep for the next cleaning quality cycle. 2025-03-16 10:26:54 -04:00
Zed A. Shaw
15bb69624b Rituals now work mostly how I want, and even prototyped the idea of a cursed item giving you a debuff and also boosting damage more. 2025-03-16 00:46:24 -04:00
Zed A. Shaw
eeea3c794f The basic idea of using GOAP to figure out if combined items will produce a valid ritual, and what kind of things the ritual does, mostly works. 2025-03-15 23:39:54 -04:00
Zed A. Shaw
7984540c0c Added a check to see if a found state is already in a closed_set so I can skip it. 2025-03-15 22:57:09 -04:00
Zed A. Shaw
63f032ff12 BREAKING: First idea for the combat system but there's a bug in goap where I'm not removing closed parts or something like that. 2025-03-15 22:30:10 -04:00
Zed A. Shaw
75db188dc6 AI is now mostly working. Enemies will attack the player, and some of them are marked as not tough so they'll run away when they get low health. 2025-03-15 11:43:46 -04:00
Zed A. Shaw
c4e01775bc Enemies will now get scared when their health is low. 2025-03-15 10:45:27 -04:00
Zed A. Shaw
00f76dfb34 Need to tag the events with their number for debugging. 2025-03-15 10:45:07 -04:00
Zed A. Shaw
2815375836 Test now can work the enemy AI to prototype behavior. 2025-03-14 23:48:03 -04:00
Zed A. Shaw
db5a371766 Moving some stuff around before writing a test to confirm the EntityAI. 2025-03-14 22:39:08 -04:00
Zed A. Shaw
f3e157a0f7 Enemy AI is now prototyped and can find the player and attack them. 2025-03-14 13:41:22 -04:00
Zed A. Shaw
ad71631809 Enemies and now using the GOAP AI to decide when to attack the player, but it's very rough right now. I need to sort out how to store the AI states and use them in the System. 2025-03-14 11:14:25 -04:00
Zed A. Shaw
77f2e94515 Figuring out something weird about the Pathing::random_walk code. 2025-03-13 23:03:14 -04:00
Zed A. Shaw
ee804581a8 Autowalker is working way better and now I have a plan for using the AI in the System. 2025-03-13 13:44:42 -04:00
Zed A. Shaw
0623170dbc Autowalker AI now knows when it has items, and knows it should find healing, but it's not working quite yet. 2025-03-12 13:56:05 -04:00
Zed A. Shaw
d15c9b12fd Autowalker is now using the GOAP AI system and works way better. Still quite a lot of jank in the code but that'll get removed over time. Next thing is being able to detect when its near an item/enemy and properly react. 2025-03-12 12:15:21 -04:00
Zed A. Shaw
ff81c78d13 The autowalker now uses the GOAP AI system to walk the map and do its thing. The code needs a big cleanup, so I might just do a full rewrite based on what I know now. 2025-03-12 00:41:40 -04:00
Zed A. Shaw
fc66d221d4 Now have the ability to do partial solutions that will create potential paths to the goal, and a test that runs the scripts from plans in different scenarios. Also, this ai_debug thing needs some work. 2025-03-11 15:33:14 -04:00
Zed A. Shaw
3f83d3f0bb A bit more cleanup to avoid duplicate testing and to separate the GOAP algorithm code from the little AI Manager thing. 2025-03-11 10:57:29 -04:00
Zed A. Shaw
b2c1b220ac ai.cpp now has a nice easy to use API for loading and running the GOAP things. 2025-03-11 00:32:11 -04:00
Zed A. Shaw
a079f882df Quick renaming of stuff to be more generic as 'AI'. Now maybe I can get some sweet sweet investor money. 2025-03-10 22:30:56 -04:00
Zed A. Shaw
9d6dc2f5dd Now can load action specs from JSON. 2025-03-10 14:07:31 -04:00
Zed A. Shaw
3d8a2d4342 GOAP now uses only bit operations to do its thing. 2025-03-10 12:13:08 -04:00
Zed A. Shaw
01525388ec GOAP is now working in a basic way, time to clean it up. 2025-03-10 11:06:26 -04:00
Zed A. Shaw
2992193447 GOAP is now matching cppGOAP but needs a serious cleanup. 2025-03-10 00:42:59 -04:00
Zed A. Shaw
15c2efc415 A barely working GOAP now, but need to confirm it's on par with other libraries. 2025-03-09 23:40:15 -04:00
Zed A. Shaw
a34e2cd475 GOAP is structured but not working yet. 2025-03-09 14:05:53 -04:00
Zed A. Shaw
a34becdaeb A simple A* pathing function that works on maps, but I'll be changing it to do the GOAP pathing. 2025-03-08 23:23:29 -05:00
Zed A. Shaw
73b0600039 Quick notes on the linux build. 2025-03-06 23:51:18 -05:00
Zed A. Shaw
b68fd249ca Catch a system error that OSX's SFML produces since it's at the end and looks like just a cleanup mistake. 2025-03-06 22:22:42 -05:00
Zed A. Shaw
b7948f8154 Build is working on both OSX and Windows. Now for linux. 2025-03-06 20:22:51 -05:00
Zed A. Shaw
e1f9942da3 Mostly working OSX build options, but it crashes on close with a thread error. 2025-03-06 14:11:12 -05:00
349 changed files with 13742 additions and 5403 deletions

2
.gitignore vendored
View file

@ -27,3 +27,5 @@ backup
*.dll *.dll
*.world *.world
coverage coverage
coverage/*
.venv

View file

@ -1 +1 @@
set makeprg=meson\ compile\ -C\ . set makeprg=make\ -f\ ../Makefile\ build

View file

@ -1,47 +1,72 @@
ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
all: build test all: build test
reset: reset:
ifeq '$(OS)' 'Windows_NT'
powershell -executionpolicy bypass .\scripts\reset_build.ps1 powershell -executionpolicy bypass .\scripts\reset_build.ps1
else
sh -x ./scripts/reset_build.sh
endif
%.cpp : %.rl %.cpp : %.rl
ragel -o $@ $< ragel -I $(ROOT_DIR) -G1 -o $@ $<
build: ansi_parser.cpp lel_parser.cpp %.dot: %.rl
meson compile -j 10 -C builddir 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: release_build:
meson --wipe builddir -Db_ndebug=true --buildtype release meson --wipe builddir -Db_ndebug=true --buildtype release
meson compile -j 10 -C builddir meson compile -j 10 -C builddir
debug_build: debug_build:
meson setup --wipe builddir --buildtype debug meson setup --wipe builddir -Db_ndebug=true --buildtype debugoptimized
meson compile -j 10 -C builddir meson compile -j 10 -C builddir
tracy_build: tracy_build:
meson setup --wipe builddir --buildtype debugoptimized -Dtracy_enable=true -Dtracy:on_demand=true meson setup --wipe builddir --buildtype debugoptimized -Dtracy_enable=true -Dtracy:on_demand=true
meson compile -j 10 -C builddir meson compile -j 10 -C builddir
test: build test:
./builddir/runtests ./builddir/runtests -d yes
run: build test run: build test
ifeq '$(OS)' 'Windows_NT'
powershell "cp ./builddir/zedcaster.exe ." powershell "cp ./builddir/zedcaster.exe ."
./zedcaster ./zedcaster
else
./builddir/zedcaster
endif
debug: build debug: build
gdb --nx -x .gdbinit --ex run --args builddir/zedcaster.exe gdb --nx -x .gdbinit --ex run --args builddir/zedcaster
debug_run: build 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 debug_walk: build test
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster.exe t gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster t
clean: clean:
meson compile --clean -C builddir meson compile --clean -C builddir
debug_test: build 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: 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

View file

@ -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: On all platforms you'll need these components:
* [Meson](https://mesonbuild.com/) -- which needs Python. * [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. * [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. * [git](https://git-scm.com/) -- Which should be on almost every platform, and is installed by default with my Windows setup scripts.
### Windows Instructions ### Windows Instructions
@ -88,7 +89,7 @@ cd raycaster
# first compile takes a while # first compile takes a while
make make
./builddir/raycaster ./builddir/zedcaster
``` ```
You don't need `make run` because Linux and OSX are sane operating systems that don't lock every 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. 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 ## 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. * 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View file

@ -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;
}

View file

@ -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);
};

View file

@ -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
View 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
View 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
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

View file

@ -3,7 +3,7 @@
"components": [ "components": [
{"_type": "BossFight", {"_type": "BossFight",
"background": "boss_fight_background", "background": "boss_fight_background",
"stage": false, "stage": null,
"weapon_sound": "Sword_Hit_2" "weapon_sound": "Sword_Hit_2"
}, },
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false}, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},
@ -24,7 +24,7 @@
"components": [ "components": [
{"_type": "BossFight", {"_type": "BossFight",
"background": "devils_fingers_background", "background": "devils_fingers_background",
"stage": false, "stage": "devils_fingers_stage",
"weapon_sound": "Sword_Hit_2" "weapon_sound": "Sword_Hit_2"
}, },
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false}, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},

View file

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 665 KiB

After

Width:  |  Height:  |  Size: 665 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1,011 KiB

After

Width:  |  Height:  |  Size: 1,011 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 466 KiB

After

Width:  |  Height:  |  Size: 466 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 818 KiB

After

Width:  |  Height:  |  Size: 818 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 413 KiB

After

Width:  |  Height:  |  Size: 413 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

View file

@ -17,45 +17,233 @@
"Marmot_Scream_1": "assets/sounds/Creature_Sounds-Marmot_Scream_1.ogg", "Marmot_Scream_1": "assets/sounds/Creature_Sounds-Marmot_Scream_1.ogg",
"blank": "assets/sounds/blank.ogg", "blank": "assets/sounds/blank.ogg",
"pickup": "assets/sounds/pickup.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": { "sprites": {
"armored_knight": "assets/armored_knight_1-256.png", "gold_savior":
"sword": "assets/cinqueda_1-512.png", {"path": "assets/sprites/gold_savior.png",
"rat_with_sword": "assets/rat_with_sword-256.png", "frame_width": 256,
"rat_king": "assets/rat_king-256.png", "frame_height": 256
"rat_king_boss": "assets/rat_king_2_frame_animation.png", },
"barrel_small": "assets/wood_barrel_small-256.png", "armored_knight":
"hanging_brazier": "assets/hanging_brazier-256.png", {"path": "assets/sprites/armored_knight_1.png",
"torch_pillar": "assets/torch_pillar-256.png", "frame_width": 256,
"torch_crappy": "assets/torch_crappy-256.png", "frame_height": 256
"torch_horizontal_floor": "assets/torch_horizontal_floor-256.png", },
"evil_eye": "assets/evil_eye-sprites.png", "axe_ranger":
"peasant_girl": "assets/undead_peasant-256.png", {"path": "assets/sprites/axe_ranger.png",
"grave_stone": "assets/grave_stone-256.png", "frame_width": 256,
"floor": "assets/floor_tile_test-256.png", "frame_height": 256
"ceiling": "assets/ceiling_test-256.png", },
"healing_potion_small": "assets/healing_potion_small-256.png", "hairy_spider":
"well_down": "assets/well_down-256.png", {"path": "assets/sprites/hairy_spider.png",
"rope_vines_up": "assets/rope_vines_up-256.png", "frame_width": 256,
"tripwire_trap": "assets/tripwire_trap-256.png", "frame_height": 256
"cinqueda": "assets/cinqueda_1-256.png", },
"left_gui": "assets/left_gui.png", "rat_with_sword":
"blood_splatter": "assets/blood_splatter-256.png", {"path": "assets/sprites/rat_with_sword.png",
"trash_button": "assets/trash_button.png", "frame_width": 256,
"axe_ranger": "assets/axe_ranger-256.png", "frame_height": 256
"hairy_spider": "assets/hairy_spider-256.png", },
"down_the_well": "assets/down_the_well.jpg", "rat_king_boss":
"boss_fight_background": "assets/rat_king_boss_fight_background.jpg", {"path": "assets/bossfights/rat_king_2_frame_animation.png",
"devils_fingers_background": "assets/devils_fingers_background.jpg", "frame_width": 720,
"devils_fingers_sprite": "assets/devils_fingers_sprite.png", "frame_height": 720
"devils_fingers_stage": "assets/devils_fingers_stage.png", },
"tunnel_with_rocks": "assets/tunnel_with_rocks.png", "barrel_small":
"tunnel_with_rocks_stage": "assets/tunnel_with_rocks_stage.png" {"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": { "worldgen": {
"enemy_probability": 80, "enemy_probability": 50,
"empty_room_probability": 10,
"device_probability": 10 "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"
} }
} }

View file

@ -7,13 +7,13 @@
"inventory_count": 0, "inventory_count": 0,
"randomized": false, "randomized": false,
"components": [ "components": [
{"_type": "Tile", "display": "\u2ac5", {"_type": "Tile", "display": 6105,
"foreground": [24, 205, 189], "foreground": "devices/fg:stairs_down",
"background": [24, 205, 189] "background": "devices/bg:stairs_down"
}, },
{"_type": "Device", {"_type": "Device",
"config": {"test": true}, "config": {},
"events": ["Events::GUI::STAIRS_DOWN"]}, "events": ["STAIRS_DOWN"]},
{"_type": "Sprite", "name": "well_down", "width": 256, "height": 256, "scale": 1.0} {"_type": "Sprite", "name": "well_down", "width": 256, "height": 256, "scale": 1.0}
] ]
}, },
@ -24,13 +24,13 @@
"inventory_count": 0, "inventory_count": 0,
"placement": "fixed", "placement": "fixed",
"components": [ "components": [
{"_type": "Tile", "display": "\u2259", {"_type": "Tile", "display": 8793,
"foreground": [24, 205, 189], "foreground": "devices/fg:stairs_up",
"background": [24, 205, 189] "background": "devices/fg:stairs_up"
}, },
{"_type": "Device", {"_type": "Device",
"config": {"test": true}, "config": {},
"events": ["Events::GUI::STAIRS_UP"]}, "events": ["STAIRS_UP"]},
{"_type": "Sprite", "name": "rope_vines_up", "width": 256, "height": 256, "scale": 1.0} {"_type": "Sprite", "name": "rope_vines_up", "width": 256, "height": 256, "scale": 1.0}
] ]
}, },
@ -40,14 +40,66 @@
"description": "Watch where you're going.", "description": "Watch where you're going.",
"inventory_count": 0, "inventory_count": 0,
"components": [ "components": [
{"_type": "Tile", "display": "\u1ac7", {"_type": "Tile", "display": 95,
"foreground": [24, 205, 189], "foreground": "devices/fg:tripwire",
"background": [24, 205, 189] "background": "devices/bg:tripwire"
}, },
{"_type": "Device", {"_type": "Device", "config": {}, "events": ["TRAP"]},
"config": {"test": true},
"events": ["Events::GUI::TRAP"]},
{"_type": "Sprite", "name": "tripwire_trap", "width": 256, "height": 256, "scale": 1.0} {"_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}
]
} }
} }

View file

@ -2,24 +2,43 @@
"PLAYER_TILE": { "PLAYER_TILE": {
"placement": "fixed", "placement": "fixed",
"components": [ "components": [
{"_type": "Tile", "display": "\ua66b", {"_type": "Tile", "display": 10733,
"foreground": [255, 200, 125], "foreground": "enemies/fg:player",
"background": [30, 20, 75] "background": "color:transparent"
}, },
{"_type": "Combat", "hp": 200, "max_hp": 200, "damage": 10, "dead": false}, {"_type": "Combat", "hp": 200, "max_hp": 200, "damage": 10, "dead": false},
{"_type": "Motion", "dx": 0, "dy": 0, "random": 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": { "KNIGHT": {
"components": [ "components": [
{"_type": "Tile", "display": "\u088d", {"_type": "Tile", "display": 2216,
"foreground": [131, 213, 238], "foreground": "enemies/fg:knight",
"background": [30, 20, 75] "background": "color:transparent"
}, },
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false}, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false},
{"_type": "Collision", "has": true},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false}, {"_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": "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": "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"} {"_type": "Sound", "attack": "Sword_Hit_2", "death": "Humanoid_Death_1"}
@ -27,41 +46,47 @@
}, },
"AXE_RANGER": { "AXE_RANGER": {
"components": [ "components": [
{"_type": "Tile", "display": "\u076a", {"_type": "Tile", "display": 1898,
"foreground": [156, 172, 197], "foreground": "enemies/fg:axe_ranger",
"background": [30, 20, 75] "background": "color:transparent"
}, },
{"_type": "Combat", "hp": 40, "max_hp": 40, "damage": 10, "dead": false}, {"_type": "Combat", "hp": 40, "max_hp": 40, "damage": 10, "dead": false},
{"_type": "Collision", "has": true},
{"_type": "Motion", "dx": 0, "dy": 0, "random": 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": "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"} {"_type": "Sound", "attack": "Sword_Hit_2", "death": "Ranger_1"}
] ]
}, },
"RAT_GIANT": { "RAT_GIANT": {
"components": [ "components": [
{"_type": "Tile", "display": "\u08ac", {"_type": "Tile", "display": 2220,
"foreground": [205, 164, 246], "foreground": "enemies/fg:rat_giant",
"background": [30, 20, 75] "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": "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": "Animation", "easing": 3, "ease_rate": 0.5, "scale": 0.1, "simple": true, "frames": 10, "speed": 1.0, "stationary": false}, {"_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": "Sprite", "name": "rat_with_sword", "width": 256, "height": 256, "scale": 1.0},
{"_type": "Sound", "attack": "Small_Rat", "death": "Creature_Death_1"} {"_type": "Sound", "attack": "Small_Rat", "death": "Creature_Death_1"}
] ]
}, },
"SPIDER_GIANT_HAIRY": { "SPIDER_GIANT_HAIRY": {
"components": [ "components": [
{"_type": "Tile", "display": "\u08ea", {"_type": "Tile", "display": 1218,
"foreground": [205, 164, 246], "foreground": "enemies/fg:spider_giant",
"background": [30, 20, 75] "background": "color:transparent"
}, },
{"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false}, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false},
{"_type": "Collision", "has": true},
{"_type": "Motion", "dx": 0, "dy": 0, "random": false}, {"_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": "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": "Sprite", "name": "hairy_spider", "width": 256, "height": 256, "scale": 1.0},
{"_type": "Sound", "attack": "Spider_1", "death": "Spider_2"} {"_type": "Sound", "attack": "Spider_1", "death": "Spider_2"}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

12
assets/icons.json Normal file
View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -6,87 +6,27 @@
"inventory_count": 1, "inventory_count": 1,
"components": [ "components": [
{"_type": "LightSource", "strength": 50, "radius": 2.5}, {"_type": "LightSource", "strength": 50, "radius": 2.5},
{"_type": "Tile", "display": "\u0f08", {"_type": "Tile", "display": 3848,
"foreground": [24, 120, 189], "foreground": "items/fg:flame",
"background": [230,120, 120] "background": "color:transparent"
}, },
{"_type": "Sprite", "name": "torch_horizontal_floor", "width": 256, "height": 256, "scale": 1.0}, {"_type": "Sprite", "name": "torch_horizontal_floor", "width": 256, "height": 256, "scale": 1.0},
{"_type": "Sound", "attack": "pickup", "death": "blank"} {"_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": { "POTION_HEALING_SMALL": {
"id": "POTION_HEALING_SMALL", "id": "POTION_HEALING_SMALL",
"name": "Small Healing Potion", "name": "Small Healing Potion",
"description": "A small healing potion.", "description": "A small healing potion.",
"inventory_count": 1, "inventory_count": 1,
"components": [ "components": [
{"_type": "Tile", "display": "\u03eb", {"_type": "Tile", "display": 1003,
"foreground": [255, 205, 189], "foreground": "items/fg:potion",
"background": [255, 205, 189] "background": "color:transparent"
}, },
{"_type": "Curative", "hp": 20}, {"_type": "Curative", "hp": 20},
{"_type": "Sprite", "name": "healing_potion_small", "width": 256, "height": 256, "scale": 1.0}, {"_type": "Sprite", "name": "healing_potion_small", "width": 256, "height": 256, "scale": 1.0},
{"_type": "Sound", "attack": "pickup", "death": "blank"} {"_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"}
]
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
assets/items/chess_pawn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

BIN
assets/items/cinqueda.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
assets/items/mushroom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

140
assets/map_tiles.json Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

81
assets/palette.json Normal file
View 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]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

202
assets/rituals.json Normal file
View 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"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Some files were not shown because too many files have changed in this diff Show more