Compare commits
10 commits
cbff127b40
...
1777a6bbf2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1777a6bbf2 | ||
|
|
aa83417ba3 | ||
|
|
dfc86452fc | ||
|
|
d22eaa554d | ||
|
|
cbd4b858ac | ||
|
|
ae0d205037 | ||
|
|
36a49ef768 | ||
|
|
db60f75bd9 | ||
|
|
8073997eb3 | ||
|
|
e742b8772d |
6
Makefile
|
|
@ -37,7 +37,7 @@ tracy_build:
|
||||||
meson compile -j 10 -C builddir
|
meson compile -j 10 -C builddir
|
||||||
|
|
||||||
test: build
|
test: build
|
||||||
./builddir/runtests -d yes "[systems-engine]"
|
./builddir/runtests -d yes
|
||||||
|
|
||||||
run: build test
|
run: build test
|
||||||
ifeq '$(OS)' 'Windows_NT'
|
ifeq '$(OS)' 'Windows_NT'
|
||||||
|
|
@ -48,7 +48,7 @@ else
|
||||||
endif
|
endif
|
||||||
|
|
||||||
debug: build
|
debug: build
|
||||||
gdb --nx -x .gdbinit --ex run --args builddir/runtests "[systems-engine]"
|
gdb --nx -x .gdbinit --ex run --args builddir/runtests
|
||||||
|
|
||||||
debug_run: build
|
debug_run: build
|
||||||
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster
|
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/zedcaster
|
||||||
|
|
@ -60,7 +60,7 @@ clean:
|
||||||
meson compile --clean -C builddir
|
meson compile --clean -C builddir
|
||||||
|
|
||||||
debug_test: build
|
debug_test: build
|
||||||
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests "[systems-engine]"
|
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests
|
||||||
|
|
||||||
win_installer:
|
win_installer:
|
||||||
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'
|
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
"close": []
|
"close": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rat_with_sword": {
|
"spider_bot": {
|
||||||
"sheet": {
|
"sheet": {
|
||||||
"frames": 1,
|
"frames": 1,
|
||||||
"frame_width": 256,
|
"frame_width": 256,
|
||||||
|
|
@ -98,14 +98,14 @@
|
||||||
"close": []
|
"close": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"female_hand": {
|
"hands_sword_attack": {
|
||||||
"sheet": {
|
"sheet": {
|
||||||
"frames": 3,
|
"frames": 3,
|
||||||
"frame_width": 900,
|
"frame_width": 512,
|
||||||
"frame_height": 600
|
"frame_height": 341
|
||||||
},
|
},
|
||||||
"sequences": {
|
"sequences": {
|
||||||
"idle": {"frames": [0, 1, 2], "durations": [10, 10, 20] }
|
"idle": {"frames": [0, 1, 2], "durations": [25, 5, 20] }
|
||||||
},
|
},
|
||||||
"transforms": {
|
"transforms": {
|
||||||
"basic": {
|
"basic": {
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
"max_y": 1.0,
|
"max_y": 1.0,
|
||||||
"flipped": false,
|
"flipped": false,
|
||||||
"scaled": false,
|
"scaled": false,
|
||||||
"toggled": true,
|
"toggled": false,
|
||||||
"looped": false,
|
"looped": false,
|
||||||
"relative": false,
|
"relative": false,
|
||||||
"easing": "none",
|
"easing": "none",
|
||||||
|
|
|
||||||
|
|
@ -1,62 +1,29 @@
|
||||||
{
|
{
|
||||||
"sounds": {
|
"sounds": {
|
||||||
"Sword_Hit_1": "assets/sounds/Creature_Sounds-Sword_Hit_1.ogg",
|
|
||||||
"Evil_Eye_Sound_1": "assets/sounds/Creature_Sounds-Evil_Eye_Sound_1.ogg",
|
|
||||||
"Evil_Eye_Sound_2": "assets/sounds/Creature_Sounds-Evil_Eye_Sound_2.ogg",
|
|
||||||
"Giant_Voice_1": "assets/sounds/Creature_Sounds-Giant_Voice_1.ogg",
|
|
||||||
"Medium_Rat": "assets/sounds/Creature_Sounds-Medium_Rat.ogg",
|
|
||||||
"Ranger_1": "assets/sounds/Creature_Sounds-Ranger_1.ogg",
|
|
||||||
"Small_Rat": "assets/sounds/Creature_Sounds-Small_Rat.ogg",
|
|
||||||
"Spider_1": "assets/sounds/Creature_Sounds-Spider_1.ogg",
|
|
||||||
"Spider_2": "assets/sounds/Creature_Sounds-Spider_2.ogg",
|
|
||||||
"Sword_Hit_1": "assets/sounds/Creature_Sounds-Sword_Hit_1.ogg",
|
|
||||||
"Sword_Hit_2": "assets/sounds/Creature_Sounds-Sword_Hit_2.ogg",
|
|
||||||
"walk": "assets/sounds/Creature_Sounds-Walk.ogg",
|
|
||||||
"Creature_Death_1": "assets/sounds/Creature_Sounds-Creature_Death_1.ogg",
|
|
||||||
"Humanoid_Death_1": "assets/sounds/Creature_Sounds-Humanoid_Death_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",
|
|
||||||
"ui_click": "assets/sounds/ui_click.ogg",
|
"ui_click": "assets/sounds/ui_click.ogg",
|
||||||
"ui_hover": "assets/sounds/ui_hover.ogg",
|
"ui_hover": "assets/sounds/ui_hover.ogg",
|
||||||
"punch_cartoony": "assets/sounds/punch_cartoony.ogg",
|
"walk": "assets/sounds/walk.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": {
|
||||||
"rat_with_sword":
|
"spider_bot":
|
||||||
{"path": "assets/sprites/rat_with_sword.png",
|
{"path": "assets/sprites/spider_bot.png",
|
||||||
"frame_width": 256,
|
"frame_width": 256,
|
||||||
"frame_height": 256
|
"frame_height": 256
|
||||||
},
|
},
|
||||||
"torch_crappy":
|
"repair_kit":
|
||||||
{"path": "assets/items/torch_crappy.png",
|
{"path": "assets/items/repair_kit.png",
|
||||||
"frame_width": 256,
|
"frame_width": 256,
|
||||||
"frame_height": 256
|
"frame_height": 256
|
||||||
},
|
},
|
||||||
"torch_horizontal_floor":
|
"sword_1":
|
||||||
{"path": "assets/items/torch_horizontal_floor.png",
|
{"path": "assets/items/sword_1_sprite.png",
|
||||||
"frame_width": 256,
|
"frame_width": 256,
|
||||||
"frame_height": 256
|
"frame_height": 256
|
||||||
},
|
},
|
||||||
"peasant_girl":
|
"ladder_down":
|
||||||
{"path": "assets/sprites/peasant_girl_2.png",
|
{"path": "assets/sprites/ladder_down.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_width": 256,
|
||||||
"frame_height": 256
|
"frame_height": 256
|
||||||
},
|
},
|
||||||
|
|
@ -75,13 +42,8 @@
|
||||||
"frame_width": 256,
|
"frame_width": 256,
|
||||||
"frame_height": 256
|
"frame_height": 256
|
||||||
},
|
},
|
||||||
"peasant_girl":
|
"hands_sword_attack":
|
||||||
{"path": "assets/sprites/peasant_girl_2.png",
|
{"path": "assets/hands/hands_sword_attack.png",
|
||||||
"frame_width": 256,
|
|
||||||
"frame_height": 256
|
|
||||||
},
|
|
||||||
"female_hand":
|
|
||||||
{"path": "assets/hands/female_hand.png",
|
|
||||||
"frame_width": 900,
|
"frame_width": 900,
|
||||||
"frame_height": 600
|
"frame_height": 600
|
||||||
}
|
}
|
||||||
|
|
@ -109,9 +71,9 @@
|
||||||
"border_px": 1,
|
"border_px": 1,
|
||||||
"text_size": 20,
|
"text_size": 20,
|
||||||
"label_size": 20,
|
"label_size": 20,
|
||||||
"font_file_name": "assets/text.otf"
|
"font_file_name": "assets/text.ttf"
|
||||||
},
|
},
|
||||||
"player": {
|
"player": {
|
||||||
"hands": "female_hand"
|
"hands": "hands_sword_attack"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
{"_type": "Device",
|
{"_type": "Device",
|
||||||
"config": {},
|
"config": {},
|
||||||
"events": ["STAIRS_DOWN"]},
|
"events": ["STAIRS_DOWN"]},
|
||||||
{"_type": "Sprite", "name": "well_down", "width": 256, "height": 256, "scale": 1.0}
|
{"_type": "Sprite", "name": "ladder_down", "width": 256, "height": 256, "scale": 1.0}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"DEAD_BODY_LOOTABLE": {
|
"DEAD_BODY_LOOTABLE": {
|
||||||
|
|
|
||||||
BIN
assets/doors/door_plain.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -6,7 +6,7 @@
|
||||||
"foreground": "enemies/fg:player",
|
"foreground": "enemies/fg:player",
|
||||||
"background": "color:transparent"
|
"background": "color:transparent"
|
||||||
},
|
},
|
||||||
{"_type": "Combat", "hp": 200, "max_hp": 200, "ap": 0, "max_ap": 12, "ap_delta": 6, "damage": 50, "dead": false},
|
{"_type": "Combat", "ap": 0, "max_ap": 12, "ap_delta": 6, "damage": 50, "dead": false},
|
||||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
||||||
{"_type": "Collision", "has": true},
|
{"_type": "Collision", "has": true},
|
||||||
{"_type": "EnemyConfig", "ai_script": "Host::actions", "ai_start_name": "Host::initial_state", "ai_goal_name": "Host::final_state"},
|
{"_type": "EnemyConfig", "ai_script": "Host::actions", "ai_start_name": "Host::initial_state", "ai_goal_name": "Host::final_state"},
|
||||||
|
|
@ -14,19 +14,18 @@
|
||||||
{"_type": "LightSource", "strength": 35, "radius": 2.0}
|
{"_type": "LightSource", "strength": 35, "radius": 2.0}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"RAT_GIANT": {
|
"SPIDER_BOT": {
|
||||||
"components": [
|
"components": [
|
||||||
{"_type": "Tile", "display": 2220,
|
{"_type": "Tile", "display": 2220,
|
||||||
"foreground": "enemies/fg:rat_giant",
|
"foreground": "enemies/fg:rat_giant",
|
||||||
"background": "color:transparent"
|
"background": "color:transparent"
|
||||||
},
|
},
|
||||||
{"_type": "Combat", "hp": 50, "max_hp": 50, "ap": 0, "max_ap": 12, "ap_delta": 6,"damage": 2, "dead": false},
|
{"_type": "Combat", "ap": 0, "max_ap": 12, "ap_delta": 6,"damage": 2, "dead": false},
|
||||||
{"_type": "Collision", "has": true},
|
{"_type": "Collision", "has": true},
|
||||||
{"_type": "Motion", "dx": 0, "dy": 0, "random": false},
|
{"_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": "EnemyConfig", "ai_script": "Enemy::actions", "ai_start_name": "Enemy::initial_state", "ai_goal_name": "Enemy::final_state"},
|
||||||
{"_type": "Personality", "hearing_distance": 5, "tough": false},
|
{"_type": "Personality", "hearing_distance": 5, "tough": false},
|
||||||
{"_type": "Sprite", "name": "rat_with_sword", "scale": 1.0},
|
{"_type": "Sprite", "name": "spider_bot", "scale": 1.0}
|
||||||
{"_type": "Sound", "attack": "Small_Rat", "death": "Creature_Death_1"}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
assets/hands/hands_sword_attack.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"healing_potion_small":
|
"repair_kit":
|
||||||
{"path": "assets/icons/healing_potion_small.png",
|
{"path": "assets/icons/repair_kit.png",
|
||||||
"frame_width": 96,
|
"frame_width": 96,
|
||||||
"frame_height": 96
|
"frame_height": 96
|
||||||
},
|
},
|
||||||
"torch_horizontal_floor":
|
"sword_1":
|
||||||
{"path": "assets/icons/torch_horizontal_floor.png",
|
{"path": "assets/icons/sword_1_icon.png",
|
||||||
"frame_width": 96,
|
"frame_width": 300,
|
||||||
"frame_height": 96
|
"frame_height": 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
assets/icons/repair_kit.png
Normal file
|
After Width: | Height: | Size: 912 B |
BIN
assets/icons/sword_1_icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -1,23 +1,8 @@
|
||||||
{
|
{
|
||||||
"TORCH_BAD": {
|
"REPAIR_KIT": {
|
||||||
"id": "TORCH_BAD",
|
"id": "REPAIR_KIT",
|
||||||
"name": "Crappy Torch",
|
"name": "Robot Repair Kit",
|
||||||
"description": "A torch that barely lights the way. You wonder if it'd be better to not see the person who murders you.",
|
"description": "A healing item for robots.",
|
||||||
"inventory_count": 1,
|
|
||||||
"components": [
|
|
||||||
{"_type": "LightSource", "strength": 50, "radius": 2.5},
|
|
||||||
{"_type": "Tile", "display": 3848,
|
|
||||||
"foreground": "items/fg:flame",
|
|
||||||
"background": "color:transparent"
|
|
||||||
},
|
|
||||||
{"_type": "Sprite", "name": "torch_horizontal_floor", "width": 256, "height": 256, "scale": 1.0},
|
|
||||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"POTION_HEALING_SMALL": {
|
|
||||||
"id": "POTION_HEALING_SMALL",
|
|
||||||
"name": "Small Healing Potion",
|
|
||||||
"description": "A small healing potion.",
|
|
||||||
"inventory_count": 1,
|
"inventory_count": 1,
|
||||||
"components": [
|
"components": [
|
||||||
{"_type": "Tile", "display": 1003,
|
{"_type": "Tile", "display": 1003,
|
||||||
|
|
@ -25,7 +10,21 @@
|
||||||
"background": "color:transparent"
|
"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": "repair_kit", "width": 256, "height": 256, "scale": 1.0},
|
||||||
|
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"SWORD_1": {
|
||||||
|
"id": "SWORD_1",
|
||||||
|
"name": "Robot Repair Kit",
|
||||||
|
"description": "A healing item for robots.",
|
||||||
|
"inventory_count": 1,
|
||||||
|
"components": [
|
||||||
|
{"_type": "Tile", "display": 1004,
|
||||||
|
"foreground": "items/fg:potion",
|
||||||
|
"background": "color:transparent"
|
||||||
|
},
|
||||||
|
{"_type": "Sprite", "name": "sword_1", "width": 300, "height": 100, "scale": 1.0},
|
||||||
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
{"_type": "Sound", "attack": "pickup", "death": "blank"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
assets/items/repair_kit.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/items/sword_1_sprite.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
assets/items/torch_horizontal_floor.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/map_tiles.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
|
|
@ -5,17 +5,17 @@
|
||||||
},
|
},
|
||||||
"gui/theme": {
|
"gui/theme": {
|
||||||
"black": [0, 0, 0, 255],
|
"black": [0, 0, 0, 255],
|
||||||
"dark_dark": [10, 10, 10, 255],
|
"dark_dark": [22, 10, 7, 255],
|
||||||
"dark_mid": [30, 30, 30, 255],
|
"dark_mid": [53, 25, 18, 255],
|
||||||
"dark_light": [60, 60, 60, 255],
|
"dark_light": [91, 42, 31, 255],
|
||||||
"mid": [100, 100, 100, 255],
|
"mid": [142, 65, 48, 255],
|
||||||
"light_dark": [150, 150, 150, 255],
|
"light_dark": [193, 89, 65, 255],
|
||||||
"light_mid": [200, 200, 200, 255],
|
"light_mid": [255, 117, 86, 255],
|
||||||
"light_light": [230, 230, 230, 255],
|
"light_light": [255, 194, 181, 255],
|
||||||
"white": [255, 255, 255, 255],
|
"white": [255, 255, 255, 255],
|
||||||
"fill_color": "gui/theme:dark_mid",
|
"fill_color": [28, 29, 33, 255],
|
||||||
"text_color": "gui/theme:light_light",
|
"text_color": [209, 209, 209, 255],
|
||||||
"bg_color": "gui/theme:mid",
|
"bg_color": "gui/theme:dark_light",
|
||||||
"border_color": "gui/theme:dark_dark",
|
"border_color": "gui/theme:dark_dark",
|
||||||
"bg_color_dark": "gui/theme:black"
|
"bg_color_dark": "gui/theme:black"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
BIN
assets/sounds/blank.ogg
Normal file
BIN
assets/sounds/pickup.ogg
Normal file
BIN
assets/sounds/ui_click.ogg
Normal file
BIN
assets/sounds/ui_hover.ogg
Normal file
BIN
assets/sounds/walk.ogg
Normal file
BIN
assets/sprites/dead_body.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/sprites/dead_body_lootable.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/sprites/ladder_down.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
assets/sprites/rat_with_sword.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/sprites/spider_bot.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
assets/text.ttf
Normal file
BIN
assets/textures/ceiling_black.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/textures/floor_gray_stone.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/textures/wall_plain.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -8,9 +8,30 @@ namespace components {
|
||||||
|
|
||||||
if(attack) {
|
if(attack) {
|
||||||
my_dmg = Random::uniform<int>(1, damage);
|
my_dmg = Random::uniform<int>(1, damage);
|
||||||
target.hp -= my_dmg;
|
target.hit_limb(my_dmg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return my_dmg;
|
return my_dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Combat::hit_limb(int my_dmg) {
|
||||||
|
body_parts["head"] -= my_dmg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Combat::is_dead() {
|
||||||
|
return body_parts["head"] < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Combat::almost_dead() {
|
||||||
|
return body_parts["head"] < 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Combat::can_heal() {
|
||||||
|
return body_parts["head"] < 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Combat::apply_healing(Curative& cure) {
|
||||||
|
int new_hp = body_parts["head"] + cure.hp;
|
||||||
|
body_parts["head"] = std::min(new_hp, 50);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,6 @@ namespace components {
|
||||||
std::string ai_goal_name;
|
std::string ai_goal_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Curative {
|
|
||||||
int hp = 10;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Sprite {
|
struct Sprite {
|
||||||
string name;
|
string name;
|
||||||
float scale;
|
float scale;
|
||||||
|
|
@ -106,12 +102,17 @@ namespace components {
|
||||||
std::vector<std::array<std::string, 4>> beats;
|
std::vector<std::array<std::string, 4>> beats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Curative {
|
||||||
|
int hp = 10;
|
||||||
|
};
|
||||||
|
|
||||||
struct Combat {
|
struct Combat {
|
||||||
int hp;
|
|
||||||
int max_hp;
|
|
||||||
int ap_delta;
|
int ap_delta;
|
||||||
int max_ap;
|
int max_ap;
|
||||||
int damage;
|
int damage;
|
||||||
|
std::unordered_map<std::string, int> body_parts{
|
||||||
|
{"head", 50},
|
||||||
|
};
|
||||||
|
|
||||||
// everyone starts at 0 but ap_delta is added each round
|
// everyone starts at 0 but ap_delta is added each round
|
||||||
int ap = 0;
|
int ap = 0;
|
||||||
|
|
@ -120,6 +121,11 @@ namespace components {
|
||||||
bool dead = false;
|
bool dead = false;
|
||||||
|
|
||||||
int attack(Combat &target);
|
int attack(Combat &target);
|
||||||
|
void hit_limb(int my_dmg);
|
||||||
|
bool is_dead();
|
||||||
|
bool almost_dead();
|
||||||
|
bool can_heal();
|
||||||
|
void apply_healing(Curative& cure);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LightSource {
|
struct LightSource {
|
||||||
|
|
@ -156,7 +162,7 @@ namespace components {
|
||||||
ENROLL_COMPONENT(EnemyConfig, ai_script, ai_start_name, ai_goal_name);
|
ENROLL_COMPONENT(EnemyConfig, ai_script, ai_start_name, ai_goal_name);
|
||||||
ENROLL_COMPONENT(Personality, hearing_distance, tough);
|
ENROLL_COMPONENT(Personality, hearing_distance, tough);
|
||||||
ENROLL_COMPONENT(Motion, dx, dy, random);
|
ENROLL_COMPONENT(Motion, dx, dy, random);
|
||||||
ENROLL_COMPONENT(Combat, hp, max_hp, ap_delta, max_ap, damage, dead);
|
ENROLL_COMPONENT(Combat, ap_delta, max_ap, damage, dead);
|
||||||
ENROLL_COMPONENT(Device, config, events);
|
ENROLL_COMPONENT(Device, config, events);
|
||||||
ENROLL_COMPONENT(Storyboard, image, audio, layout, beats);
|
ENROLL_COMPONENT(Storyboard, image, audio, layout, beats);
|
||||||
ENROLL_COMPONENT(Sound, attack, death);
|
ENROLL_COMPONENT(Sound, attack, death);
|
||||||
|
|
|
||||||
82
src/game/registry.hpp
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include "game/components.hpp"
|
||||||
|
|
||||||
|
namespace System {
|
||||||
|
using MovingFunc = std::function<void(components::Position& move_to)>;
|
||||||
|
using CombatFunc = std::function<void(int attack_id)>;
|
||||||
|
using RenderFunc = std::function<void()>;
|
||||||
|
using UpdateFunc = std::function<void()>;
|
||||||
|
using UseItemFunc = std::function<void(const std::string& slot_name)>;
|
||||||
|
using PickupFunc = std::function<void()>;
|
||||||
|
|
||||||
|
struct Registry {
|
||||||
|
std::vector<MovingFunc> $moving;
|
||||||
|
std::vector<CombatFunc> $combat;
|
||||||
|
std::vector<RenderFunc> $render;
|
||||||
|
std::vector<UpdateFunc> $update;
|
||||||
|
std::vector<UseItemFunc> $use_item;
|
||||||
|
std::vector<PickupFunc> $pickup;
|
||||||
|
|
||||||
|
void addMoving(MovingFunc action) {
|
||||||
|
$moving.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCombat(CombatFunc action) {
|
||||||
|
$combat.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addRender(RenderFunc action) {
|
||||||
|
$render.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addUpdate(UpdateFunc action) {
|
||||||
|
$update.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addUseItem(UseItemFunc action) {
|
||||||
|
$use_item.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPickup(PickupFunc action) {
|
||||||
|
$pickup.emplace_back(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void runMoving(components::Position move_to) {
|
||||||
|
for(auto func : $moving) {
|
||||||
|
func(move_to);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runCombat(int attack_id) {
|
||||||
|
for(auto func : $combat) {
|
||||||
|
func(attack_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runRender() {
|
||||||
|
for(auto func : $render) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runUpdate() {
|
||||||
|
for(auto func : $update) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runUseItem(const std::string& slot_name) {
|
||||||
|
for(auto func : $use_item) {
|
||||||
|
func(slot_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runPickup() {
|
||||||
|
for(auto func : $pickup) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -167,15 +167,14 @@ void System::distribute_loot(Position target_pos) {
|
||||||
auto loot_entity = world.entity();
|
auto loot_entity = world.entity();
|
||||||
|
|
||||||
if(inventory_count > 0) {
|
if(inventory_count > 0) {
|
||||||
auto& entity_data = config.devices["DEAD_BODY_LOOTABLE"];
|
dbc::log("!!!!!!!!!!!!!!!! ============= LOOTING BODIES NOT READY");
|
||||||
components::configure_entity(world, loot_entity, entity_data["components"]);
|
}
|
||||||
// BUG: inventory_count here isn't really used to remove it
|
|
||||||
world.set<InventoryItem>(loot_entity, {inventory_count, entity_data});
|
// NOTE: refer to the code in raycaster for this
|
||||||
} else {
|
|
||||||
// this creates a dead body on the ground
|
// this creates a dead body on the ground
|
||||||
auto& entity_data = config.devices["DEAD_BODY"];
|
auto& entity_data = config.devices["DEAD_BODY"];
|
||||||
components::configure_entity(world, loot_entity, entity_data["components"]);
|
components::configure_entity(world, loot_entity, entity_data["components"]);
|
||||||
}
|
|
||||||
|
|
||||||
set_position(world, *level.collision, loot_entity, target_pos);
|
set_position(world, *level.collision, loot_entity, target_pos);
|
||||||
level.world->send<game::Event>(game::Event::ENTITY_SPAWN, loot_entity, {});
|
level.world->send<game::Event>(game::Event::ENTITY_SPAWN, loot_entity, {});
|
||||||
|
|
@ -189,7 +188,7 @@ void System::death() {
|
||||||
|
|
||||||
world.query<Combat>([&](auto ent, auto &combat) {
|
world.query<Combat>([&](auto ent, auto &combat) {
|
||||||
// bring out yer dead
|
// bring out yer dead
|
||||||
if(combat.hp <= 0 && !combat.dead) {
|
if(combat.is_dead() && !combat.dead) {
|
||||||
combat.dead = true;
|
combat.dead = true;
|
||||||
if(ent != player.entity) {
|
if(ent != player.entity) {
|
||||||
// we won't change out the player's components later
|
// we won't change out the player's components later
|
||||||
|
|
@ -197,7 +196,7 @@ void System::death() {
|
||||||
}
|
}
|
||||||
// we need to send this event for everything that dies
|
// we need to send this event for everything that dies
|
||||||
world.send<game::Event>(game::Event::DEATH, ent, {});
|
world.send<game::Event>(game::Event::DEATH, ent, {});
|
||||||
} else if(float(combat.hp) / float(combat.max_hp) < 0.5f) {
|
} else if(combat.almost_dead()) {
|
||||||
// if enemies are below 50% health they are marked with bad health
|
// if enemies are below 50% health they are marked with bad health
|
||||||
if(world.has<ai::EntityAI>(ent)) {
|
if(world.has<ai::EntityAI>(ent)) {
|
||||||
auto& enemy_ai = world.get<ai::EntityAI>(ent);
|
auto& enemy_ai = world.get<ai::EntityAI>(ent);
|
||||||
|
|
@ -474,34 +473,23 @@ bool System::inventory_occupied(Entity container_id, const std::string& name) {
|
||||||
return inventory.has(name);
|
return inventory.has(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::use_item(const string& slot_name) {
|
void System::use_item(const string& slot_name) {
|
||||||
auto& level = GameDB::current_level();
|
auto& level = GameDB::current_level();
|
||||||
auto& world = *level.world;
|
auto& world = *level.world;
|
||||||
auto& inventory = world.get<inventory::Model>(level.player);
|
auto& inventory = world.get<inventory::Model>(level.player);
|
||||||
auto& player_combat = world.get<Combat>(level.player);
|
auto& player_combat = world.get<Combat>(level.player);
|
||||||
|
|
||||||
if(player_combat.hp >= player_combat.max_hp) return false;
|
if(!player_combat.can_heal()) return;
|
||||||
if(!inventory.has(slot_name)) return false;
|
if(!inventory.has(slot_name)) return;
|
||||||
|
|
||||||
auto what = inventory.get(slot_name);
|
auto what = inventory.get(slot_name);
|
||||||
|
|
||||||
if(auto curative = world.get_if<Curative>(what)) {
|
if(auto curative = world.get_if<Curative>(what)) {
|
||||||
inventory.remove(what);
|
inventory.remove(what);
|
||||||
|
player_combat.apply_healing(*curative);
|
||||||
player_combat.hp += curative->hp;
|
|
||||||
|
|
||||||
if(player_combat.hp > player_combat.max_hp) {
|
|
||||||
player_combat.hp = player_combat.max_hp;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbc::log($F("player health now {}",
|
|
||||||
player_combat.hp));
|
|
||||||
|
|
||||||
world.remove<Curative>(what);
|
world.remove<Curative>(what);
|
||||||
return true;
|
|
||||||
} else {
|
} else {
|
||||||
dbc::log($F("no usable item at {}", what));
|
dbc::log($F("no usable item at {}", what));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,3 +529,19 @@ void System::clear_attack() {
|
||||||
|
|
||||||
void System::spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy) {
|
void System::spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void System::init(Registry& reg) {
|
||||||
|
reg.addRender(System::clear_attack);
|
||||||
|
reg.addUseItem(System::use_item);
|
||||||
|
reg.addMoving(System::move_player);
|
||||||
|
reg.addCombat(System::combat);
|
||||||
|
reg.addPickup(System::pickup);
|
||||||
|
reg.addUpdate(System::generate_paths);
|
||||||
|
reg.addUpdate(System::enemy_ai_initialize);
|
||||||
|
reg.addUpdate(System::enemy_pathing);
|
||||||
|
reg.addUpdate(System::motion);
|
||||||
|
reg.addUpdate(System::collision);
|
||||||
|
reg.addUpdate(System::lighting);
|
||||||
|
reg.addUpdate(System::death);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
#include "algos/spatialmap.hpp"
|
#include "algos/spatialmap.hpp"
|
||||||
#include "game/level.hpp"
|
#include "game/level.hpp"
|
||||||
#include "events.hpp"
|
#include "events.hpp"
|
||||||
|
#include "game/registry.hpp"
|
||||||
|
|
||||||
namespace System {
|
namespace System {
|
||||||
|
|
||||||
using namespace components;
|
using namespace components;
|
||||||
using namespace DinkyECS;
|
using namespace DinkyECS;
|
||||||
using std::string, matrix::Matrix;
|
using std::string, matrix::Matrix;
|
||||||
|
|
@ -32,15 +34,15 @@ namespace System {
|
||||||
|
|
||||||
void pickup();
|
void pickup();
|
||||||
|
|
||||||
|
// BUG: these might need to go somewhere else....
|
||||||
bool place_in_container(Entity cont_id, const string& name, Entity world_entity);
|
bool place_in_container(Entity cont_id, const string& name, Entity world_entity);
|
||||||
|
|
||||||
void remove_from_container(Entity cont_id, const std::string& name);
|
void remove_from_container(Entity cont_id, const std::string& name);
|
||||||
void remove_from_world(Entity entity);
|
void remove_from_world(Entity entity);
|
||||||
void inventory_swap(Entity container_id, const std::string& a_name, const std::string &b_name);
|
void inventory_swap(Entity container_id, const std::string& a_name, const std::string &b_name);
|
||||||
bool inventory_occupied(Entity container_id, const std::string& name);
|
bool inventory_occupied(Entity container_id, const std::string& name);
|
||||||
|
|
||||||
void set_position(DinkyECS::World& world, SpatialMap& collision, Entity entity, Position pos);
|
void set_position(DinkyECS::World& world, SpatialMap& collision, Entity entity, Position pos);
|
||||||
bool use_item(const std::string& slot_name);
|
void use_item(const std::string& slot_name);
|
||||||
|
|
||||||
game::Event shortest_rotate(Point player_at, Point aiming_at, Point turning_to);
|
game::Event shortest_rotate(Point player_at, Point aiming_at, Point turning_to);
|
||||||
|
|
||||||
|
|
@ -67,4 +69,6 @@ namespace System {
|
||||||
|
|
||||||
void clear_attack();
|
void clear_attack();
|
||||||
void spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy);
|
void spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy);
|
||||||
|
|
||||||
|
void init(Registry& reg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -199,15 +199,14 @@ void WorldBuilder::place_stairs(DinkyECS::World& world, GameConfig& config) {
|
||||||
|
|
||||||
void WorldBuilder::configure_starting_items(DinkyECS::World &world) {
|
void WorldBuilder::configure_starting_items(DinkyECS::World &world) {
|
||||||
auto& player = world.get_the<Player>();
|
auto& player = world.get_the<Player>();
|
||||||
|
|
||||||
auto torch_id = System::spawn_item(world, "TORCH_BAD");
|
|
||||||
|
|
||||||
auto &inventory = world.get<inventory::Model>(player.entity);
|
auto &inventory = world.get<inventory::Model>(player.entity);
|
||||||
inventory.add("hand_r", torch_id);
|
|
||||||
world.make_constant(torch_id);
|
|
||||||
|
|
||||||
auto healing = System::spawn_item(world, "POTION_HEALING_SMALL");
|
auto healing = System::spawn_item(world, "REPAIR_KIT");
|
||||||
inventory.add("pocket_l", healing);
|
inventory.add("inv0", healing);
|
||||||
|
|
||||||
|
auto sword = System::spawn_item(world, "SWORD_1");
|
||||||
|
inventory.add("hand_main", sword);
|
||||||
|
|
||||||
world.make_constant(healing);
|
world.make_constant(healing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ inline void set_scale_position(sf::Sprite& sprite, sf::Vector2f& position, sf::V
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Raycaster::sprite_casting() {
|
void Raycaster::sprite_casting(sf::RenderTarget& target) {
|
||||||
auto& lights = $level.lights->lighting();
|
auto& lights = $level.lights->lighting();
|
||||||
auto world = $level.world;
|
auto world = $level.world;
|
||||||
$level.collision->distance_sorted($sprite_order, {(size_t)$pos_x, (size_t)$pos_y}, RENDER_DISTANCE);
|
$level.collision->distance_sorted($sprite_order, {(size_t)$pos_x, (size_t)$pos_y}, RENDER_DISTANCE);
|
||||||
|
|
@ -212,7 +212,6 @@ void Raycaster::sprite_casting() {
|
||||||
sf::Vector2f scale{sprite_scale_w, sprite_scale_h};
|
sf::Vector2f scale{sprite_scale_w, sprite_scale_h};
|
||||||
sf::Vector2f position{x + origin.x * scale.x, y + origin.y * scale.y};
|
sf::Vector2f position{x + origin.x * scale.x, y + origin.y * scale.y};
|
||||||
sf::IntRect in_texture{ {tex_x, tex_y}, {tex_render_width, texture_height}};
|
sf::IntRect in_texture{ {tex_x, tex_y}, {tex_render_width, texture_height}};
|
||||||
|
|
||||||
shared_ptr<sf::Shader> effect = System::sprite_effect(rec.entity);
|
shared_ptr<sf::Shader> effect = System::sprite_effect(rec.entity);
|
||||||
|
|
||||||
if(effect) {
|
if(effect) {
|
||||||
|
|
@ -231,7 +230,7 @@ void Raycaster::sprite_casting() {
|
||||||
set_scale_position(*sf_sprite, position, scale, in_texture, origin);
|
set_scale_position(*sf_sprite, position, scale, in_texture, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
$sprites_to_render.emplace_back(sf_sprite, effect);
|
target.draw(*sf_sprite, effect.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -438,16 +437,12 @@ void Raycaster::update() {
|
||||||
draw_ceiling_floor();
|
draw_ceiling_floor();
|
||||||
cast_rays();
|
cast_rays();
|
||||||
draw_pixel_buffer();
|
draw_pixel_buffer();
|
||||||
sprite_casting();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUG: if target is a rendertarget then I can say it has to be the viewport only, then I can get rid of $screen_pos_x/y
|
// BUG: if target is a rendertarget then I can say it has to be the viewport only, then I can get rid of $screen_pos_x/y
|
||||||
void Raycaster::render(sf::RenderTarget& target) {
|
void Raycaster::render(sf::RenderTarget& target) {
|
||||||
target.draw($view_sprite);
|
target.draw($view_sprite);
|
||||||
|
sprite_casting(target);
|
||||||
for(auto [sprite, effect] : $sprites_to_render) {
|
|
||||||
target.draw(*sprite, effect.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Raycaster::update_sprite(DinkyECS::Entity ent, components::Sprite& sprite) {
|
void Raycaster::update_sprite(DinkyECS::Entity ent, components::Sprite& sprite) {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ struct CameraLOL {
|
||||||
double target_plane_y = 0.0;
|
double target_plane_y = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SpriteRender = std::pair<std::shared_ptr<sf::Sprite>, std::shared_ptr<sf::Shader>>;
|
using SpriteRender = std::pair<sf::Sprite, std::shared_ptr<sf::Shader>>;
|
||||||
|
|
||||||
struct Raycaster {
|
struct Raycaster {
|
||||||
sf::Texture $view_texture;
|
sf::Texture $view_texture;
|
||||||
|
|
@ -64,7 +64,7 @@ struct Raycaster {
|
||||||
void cast_rays();
|
void cast_rays();
|
||||||
void draw_ceiling_floor();
|
void draw_ceiling_floor();
|
||||||
void draw_pixel_buffer();
|
void draw_pixel_buffer();
|
||||||
void sprite_casting();
|
void sprite_casting(sf::RenderTarget& target);
|
||||||
void update();
|
void update();
|
||||||
void render(sf::RenderTarget& target);
|
void render(sf::RenderTarget& target);
|
||||||
|
|
||||||
|
|
|
||||||
61
src/gui/body_ui.cpp
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "gui/body_ui.hpp"
|
||||||
|
#include "game/components.hpp"
|
||||||
|
#include <guecs/ui.hpp>
|
||||||
|
#include "algos/rand.hpp"
|
||||||
|
#include <fmt/xchar.h>
|
||||||
|
#include "gui/guecstra.hpp"
|
||||||
|
#include "game/systems.hpp"
|
||||||
|
#include "game/inventory.hpp"
|
||||||
|
#include "game/level.hpp"
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
using namespace guecs;
|
||||||
|
using std::any, std::any_cast, std::string, std::make_any;
|
||||||
|
|
||||||
|
void BodyUI::init(size_t x, size_t y, size_t width, size_t height) {
|
||||||
|
$gui.position(x, y, width, height);
|
||||||
|
$gui.layout(
|
||||||
|
"[head]"
|
||||||
|
"[chest]"
|
||||||
|
"[right_arm]"
|
||||||
|
"[left_arm]"
|
||||||
|
"[stomach]"
|
||||||
|
"[left_leg]"
|
||||||
|
"[right_leg]");
|
||||||
|
|
||||||
|
$gui.set<Background>($gui.MAIN, {$gui.$parser, });
|
||||||
|
|
||||||
|
for(auto& [name, cell] : $gui.cells()) {
|
||||||
|
auto gui_id = $gui.entity(name);
|
||||||
|
|
||||||
|
$gui.set<Text>(gui_id, {guecs::to_wstring(name)});
|
||||||
|
$gui.set<Meter>(gui_id, {1.0f, THEME.DARK_MID, {}});
|
||||||
|
}
|
||||||
|
|
||||||
|
$gui.init();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BodyUI::mouse(float x, float y, guecs::Modifiers mods) {
|
||||||
|
return $gui.mouse(x, y, mods);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BodyUI::update() {
|
||||||
|
auto world = GameDB::current_world();
|
||||||
|
auto& player = world->get_the<components::Player>();
|
||||||
|
auto& player_combat = world->get<components::Combat>(player.entity);
|
||||||
|
|
||||||
|
for(auto& [key, value] : player_combat.body_parts) {
|
||||||
|
auto gui_id = $gui.entity(key);
|
||||||
|
|
||||||
|
if(auto meter = $gui.get_if<Meter>(gui_id)) {
|
||||||
|
meter->percent = float(value) / 50.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BodyUI::render(sf::RenderWindow &window) {
|
||||||
|
$gui.render(window);
|
||||||
|
// $gui.debug_layout(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/gui/body_ui.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
#include "constants.hpp"
|
||||||
|
#include <deque>
|
||||||
|
#include "graphics/textures.hpp"
|
||||||
|
#include <guecs/ui.hpp>
|
||||||
|
#include "gui/guecstra.hpp"
|
||||||
|
|
||||||
|
namespace gui {
|
||||||
|
class BodyUI {
|
||||||
|
public:
|
||||||
|
guecs::UI $gui{};
|
||||||
|
|
||||||
|
void init(size_t x, size_t y, size_t width, size_t height);
|
||||||
|
void render(sf::RenderWindow &window);
|
||||||
|
void update();
|
||||||
|
bool mouse(float x, float y, guecs::Modifiers mods);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@ namespace gui {
|
||||||
"[spawn1|spawn2|spawn3]"
|
"[spawn1|spawn2|spawn3]"
|
||||||
"[spawn4|spawn5|spawn6]");
|
"[spawn4|spawn5|spawn6]");
|
||||||
|
|
||||||
add_spawn_button("RAT_GIANT", "rat_with_sword", "spawn4");
|
// add_spawn_button("RAT_GIANT", "rat_with_sword", "spawn4");
|
||||||
|
|
||||||
$gui.init();
|
$gui.init();
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +48,6 @@ namespace gui {
|
||||||
auto map = level.map;
|
auto map = level.map;
|
||||||
|
|
||||||
std::wstring stats = $F(L"STATS\n"
|
std::wstring stats = $F(L"STATS\n"
|
||||||
L"HP: {}\n"
|
|
||||||
L"mean:{:>8.5}\n"
|
L"mean:{:>8.5}\n"
|
||||||
L"sdev: {:>8.5}\n"
|
L"sdev: {:>8.5}\n"
|
||||||
L"min: {:>8.5}\n"
|
L"min: {:>8.5}\n"
|
||||||
|
|
@ -58,7 +57,7 @@ namespace gui {
|
||||||
L"VSync? {}\n"
|
L"VSync? {}\n"
|
||||||
L"FR Limit: {}\n"
|
L"FR Limit: {}\n"
|
||||||
L"Debug? {}\n\n",
|
L"Debug? {}\n\n",
|
||||||
player_combat.hp, $stats.mean(), $stats.stddev(), $stats.min,
|
$stats.mean(), $stats.stddev(), $stats.min,
|
||||||
$stats.max, $stats.n, level.index, map->width(), map->height(),
|
$stats.max, $stats.n, level.index, map->width(), map->height(),
|
||||||
VSYNC, FRAME_LIMIT, DEBUG_BUILD);
|
VSYNC, FRAME_LIMIT, DEBUG_BUILD);
|
||||||
|
|
||||||
|
|
@ -74,9 +73,6 @@ namespace gui {
|
||||||
if(active) {
|
if(active) {
|
||||||
auto& level = GameDB::current_level();
|
auto& level = GameDB::current_level();
|
||||||
// it's on now, enable things
|
// it's on now, enable things
|
||||||
auto player = level.world->get_the<components::Player>();
|
|
||||||
auto& player_combat = level.world->get<components::Combat>(player.entity);
|
|
||||||
player_combat.hp = player_combat.max_hp;
|
|
||||||
$gui.show_text("debug_text", L"STATS");
|
$gui.show_text("debug_text", L"STATS");
|
||||||
} else {
|
} else {
|
||||||
// it's off now, close it
|
// it's off now, close it
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ namespace gui {
|
||||||
void FSM::MOVING(Event ) {
|
void FSM::MOVING(Event ) {
|
||||||
// this should be an optional that returns a point
|
// this should be an optional that returns a point
|
||||||
if(auto move_to = $main_ui.play_move()) {
|
if(auto move_to = $main_ui.play_move()) {
|
||||||
System::move_player(*move_to);
|
$systems.runMoving(*move_to);
|
||||||
run_systems();
|
run_systems();
|
||||||
$main_ui.dirty();
|
$main_ui.dirty();
|
||||||
state(State::IDLE);
|
state(State::IDLE);
|
||||||
|
|
@ -70,7 +70,7 @@ namespace gui {
|
||||||
switch(ev) {
|
switch(ev) {
|
||||||
case TICK: {
|
case TICK: {
|
||||||
dbc::log("!!!!!! FIX System::combat(0) doesn't use any weapons, only first");
|
dbc::log("!!!!!! FIX System::combat(0) doesn't use any weapons, only first");
|
||||||
System::combat(0);
|
$systems.runCombat(0);
|
||||||
run_systems();
|
run_systems();
|
||||||
state(State::IN_COMBAT);
|
state(State::IN_COMBAT);
|
||||||
} break;
|
} break;
|
||||||
|
|
@ -79,7 +79,7 @@ namespace gui {
|
||||||
break;
|
break;
|
||||||
case ATTACK: {
|
case ATTACK: {
|
||||||
int attack_id = std::any_cast<int>(data);
|
int attack_id = std::any_cast<int>(data);
|
||||||
System::combat(attack_id);
|
$systems.runCombat(attack_id);
|
||||||
run_systems();
|
run_systems();
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -174,10 +174,8 @@ namespace gui {
|
||||||
case USE_ITEM: {
|
case USE_ITEM: {
|
||||||
auto gui_id = std::any_cast<guecs::Entity>(data);
|
auto gui_id = std::any_cast<guecs::Entity>(data);
|
||||||
auto& slot_name = $status_ui.$gui.name_for(gui_id);
|
auto& slot_name = $status_ui.$gui.name_for(gui_id);
|
||||||
|
$systems.runUseItem(slot_name);
|
||||||
if(System::use_item(slot_name)) {
|
|
||||||
$status_ui.update();
|
$status_ui.update();
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case MOUSE_CLICK:
|
case MOUSE_CLICK:
|
||||||
mouse_action(guecs::NO_MODS);
|
mouse_action(guecs::NO_MODS);
|
||||||
|
|
@ -186,7 +184,7 @@ namespace gui {
|
||||||
mouse_action({1 << guecs::ModBit::hover});
|
mouse_action({1 << guecs::ModBit::hover});
|
||||||
} break;
|
} break;
|
||||||
case AIM_CLICK:
|
case AIM_CLICK:
|
||||||
System::pickup();
|
$systems.runPickup();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break; // ignore everything else
|
break; // ignore everything else
|
||||||
|
|
@ -312,9 +310,6 @@ namespace gui {
|
||||||
$debug_ui.debug();
|
$debug_ui.debug();
|
||||||
shaders::reload();
|
shaders::reload();
|
||||||
break;
|
break;
|
||||||
case KEY::O:
|
|
||||||
autowalking = true;
|
|
||||||
break;
|
|
||||||
case KEY::L:
|
case KEY::L:
|
||||||
// This will go away as soon as containers work
|
// This will go away as soon as containers work
|
||||||
$loot_ui.set_target($loot_ui.$temp_loot);
|
$loot_ui.set_target($loot_ui.$temp_loot);
|
||||||
|
|
@ -360,10 +355,8 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSM::render() {
|
void FSM::render() {
|
||||||
$window.clear();
|
|
||||||
|
|
||||||
// this clears any attack animations, like fire
|
// this clears any attack animations, like fire
|
||||||
System::clear_attack();
|
$systems.runRender();
|
||||||
// BUG: this is the render for this class, and where I add an update
|
// BUG: this is the render for this class, and where I add an update
|
||||||
draw_gui();
|
draw_gui();
|
||||||
|
|
||||||
|
|
@ -371,13 +364,7 @@ namespace gui {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSM::run_systems() {
|
void FSM::run_systems() {
|
||||||
System::generate_paths();
|
$systems.runUpdate();
|
||||||
System::enemy_ai_initialize();
|
|
||||||
System::enemy_pathing();
|
|
||||||
System::motion();
|
|
||||||
System::collision();
|
|
||||||
System::lighting();
|
|
||||||
System::death();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FSM::active() {
|
bool FSM::active() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
|
#include "game/registry.hpp"
|
||||||
#include "algos/simplefsm.hpp"
|
#include "algos/simplefsm.hpp"
|
||||||
#include "gui/debug_ui.hpp"
|
#include "gui/debug_ui.hpp"
|
||||||
#include "gui/main_ui.hpp"
|
#include "gui/main_ui.hpp"
|
||||||
|
|
@ -35,12 +36,11 @@ namespace gui {
|
||||||
LootUI $loot_ui;
|
LootUI $loot_ui;
|
||||||
gui::routing::Router $router;
|
gui::routing::Router $router;
|
||||||
DNDLoot $dnd_loot;
|
DNDLoot $dnd_loot;
|
||||||
|
System::Registry $systems;
|
||||||
|
|
||||||
FSM();
|
FSM();
|
||||||
|
|
||||||
void event(game::Event ev, std::any data={});
|
void event(game::Event ev, std::any data={});
|
||||||
void autowalk();
|
|
||||||
void start_autowalk(double rot_speed);
|
|
||||||
|
|
||||||
void START(game::Event ev);
|
void START(game::Event ev);
|
||||||
void MOVING(game::Event ev);
|
void MOVING(game::Event ev);
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ namespace gui {
|
||||||
dbc::check(world->has<components::Sprite>(item),
|
dbc::check(world->has<components::Sprite>(item),
|
||||||
"item in inventory UI doesn't exist in world. New level?");
|
"item in inventory UI doesn't exist in world. New level?");
|
||||||
auto& sprite = world->get<components::Sprite>(item);
|
auto& sprite = world->get<components::Sprite>(item);
|
||||||
|
fmt::println("!!!!!!!!!!! trying to load {}", sprite.name);
|
||||||
$gui.set_init<guecs::Icon>(id, {sprite.name});
|
$gui.set_init<guecs::Icon>(id, {sprite.name});
|
||||||
|
|
||||||
guecs::GrabSource grabber{
|
guecs::GrabSource grabber{
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,11 @@ namespace gui {
|
||||||
$window.setFramerateLimit(FRAME_LIMIT);
|
$window.setFramerateLimit(FRAME_LIMIT);
|
||||||
|
|
||||||
auto config = settings::get("config");
|
auto config = settings::get("config");
|
||||||
|
|
||||||
$hand = textures::get_sprite(config["player"]["hands"]);
|
$hand = textures::get_sprite(config["player"]["hands"]);
|
||||||
$hand_anim = animation::load("assets/animation.json", config["player"]["hands"]);
|
$hand_anim = animation::load("assets/animation.json", config["player"]["hands"]);
|
||||||
|
int width = $hand_anim.sheet.frame_width;
|
||||||
|
int height = $hand_anim.sheet.frame_height;
|
||||||
|
$hand.sprite->setPosition({float(RAY_VIEW_X + (RAY_VIEW_WIDTH - width) / 2), float(RAY_VIEW_HEIGHT - height)});
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainUI::dirty() {
|
void MainUI::dirty() {
|
||||||
|
|
@ -148,7 +150,6 @@ namespace gui {
|
||||||
if($hand_anim.playing) {
|
if($hand_anim.playing) {
|
||||||
$hand_anim.update();
|
$hand_anim.update();
|
||||||
$hand_anim.apply(*$hand.sprite);
|
$hand_anim.apply(*$hand.sprite);
|
||||||
$hand.sprite->setPosition({RAY_VIEW_X, RAY_VIEW_Y});
|
|
||||||
$window.draw(*$hand.sprite);
|
$window.draw(*$hand.sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,13 @@ namespace gui {
|
||||||
$gui.init();
|
$gui.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void make_clickable_area(guecs::UI &gui, const std::string &name) {
|
inline void make_clickable_area(guecs::UI &gui, const std::string name) {
|
||||||
auto area = gui.entity(name);
|
auto area = gui.entity(name);
|
||||||
|
|
||||||
gui.set<Clickable>(area, {
|
gui.set<Clickable>(area, {
|
||||||
[&](auto) {
|
[=](auto) {
|
||||||
auto world = GameDB::current_world();
|
auto world = GameDB::current_world();
|
||||||
|
fmt::println("CLICK {}", name);
|
||||||
world->send<game::Event>(game::Event::AIM_CLICK, area, {});
|
world->send<game::Event>(game::Event::AIM_CLICK, area, {});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,14 @@ namespace gui {
|
||||||
{
|
{
|
||||||
$gui.position(x, y, width, height);
|
$gui.position(x, y, width, height);
|
||||||
$gui.layout(
|
$gui.layout(
|
||||||
"[=slot1]"
|
"[*%(100, 300)body_ui]"
|
||||||
"[=slot2]"
|
"[_]"
|
||||||
"[=hand_r]"
|
"[_]"
|
||||||
"[=pocket_l]");
|
"[=inv0|=inv1|=inv2]"
|
||||||
|
"[=inv3|=inv4|=inv5]"
|
||||||
|
"[=inv6|=inv7|=inv8]"
|
||||||
|
"[=hand_main]"
|
||||||
|
"[=hand_off]");
|
||||||
}
|
}
|
||||||
|
|
||||||
void StatusUI::init() {
|
void StatusUI::init() {
|
||||||
|
|
@ -28,9 +32,13 @@ namespace gui {
|
||||||
for(auto& [name, cell] : $gui.cells()) {
|
for(auto& [name, cell] : $gui.cells()) {
|
||||||
auto gui_id = $gui.entity(name);
|
auto gui_id = $gui.entity(name);
|
||||||
|
|
||||||
$gui.set<Rectangle>(gui_id, {});
|
|
||||||
|
|
||||||
$gui.set<Text>(gui_id, {guecs::to_wstring(name)});
|
$gui.set<Text>(gui_id, {guecs::to_wstring(name)});
|
||||||
|
|
||||||
|
if(name.starts_with("body_")) {
|
||||||
|
auto& cell = $gui.cell_for(name);
|
||||||
|
$body_ui.init(cell.x, cell.y, cell.w, cell.h);
|
||||||
|
} else {
|
||||||
|
$gui.set<Rectangle>(gui_id, {});
|
||||||
$gui.set<Clickable>(gui_id, {
|
$gui.set<Clickable>(gui_id, {
|
||||||
guecs::make_action(gui_id, game::Event::INV_SELECT, {gui_id})
|
guecs::make_action(gui_id, game::Event::INV_SELECT, {gui_id})
|
||||||
});
|
});
|
||||||
|
|
@ -40,6 +48,7 @@ namespace gui {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$gui.init();
|
$gui.init();
|
||||||
update();
|
update();
|
||||||
|
|
@ -54,6 +63,8 @@ namespace gui {
|
||||||
auto player = world->get_the<components::Player>();
|
auto player = world->get_the<components::Player>();
|
||||||
auto& inventory = world->get<inventory::Model>(player.entity);
|
auto& inventory = world->get<inventory::Model>(player.entity);
|
||||||
|
|
||||||
|
$body_ui.update();
|
||||||
|
|
||||||
for(const auto& [slot, cell] : $gui.cells()) {
|
for(const auto& [slot, cell] : $gui.cells()) {
|
||||||
|
|
||||||
if(inventory.has(slot)) {
|
if(inventory.has(slot)) {
|
||||||
|
|
@ -79,6 +90,7 @@ namespace gui {
|
||||||
|
|
||||||
void StatusUI::render(sf::RenderWindow &window) {
|
void StatusUI::render(sf::RenderWindow &window) {
|
||||||
$gui.render(window);
|
$gui.render(window);
|
||||||
|
$body_ui.render(window);
|
||||||
// $gui.debug_layout(window);
|
// $gui.debug_layout(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,13 @@
|
||||||
#include "graphics/textures.hpp"
|
#include "graphics/textures.hpp"
|
||||||
#include <guecs/ui.hpp>
|
#include <guecs/ui.hpp>
|
||||||
#include "gui/guecstra.hpp"
|
#include "gui/guecstra.hpp"
|
||||||
|
#include "gui/body_ui.hpp"
|
||||||
|
|
||||||
namespace gui {
|
namespace gui {
|
||||||
class StatusUI {
|
class StatusUI {
|
||||||
public:
|
public:
|
||||||
guecs::UI $gui;
|
guecs::UI $gui{};
|
||||||
|
BodyUI $body_ui{};
|
||||||
|
|
||||||
explicit StatusUI(size_t x, size_t y, size_t width, size_t height);
|
explicit StatusUI(size_t x, size_t y, size_t width, size_t height);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "gui/backend.hpp"
|
#include "gui/backend.hpp"
|
||||||
#include "game/level.hpp"
|
#include "game/level.hpp"
|
||||||
#include "graphics/camera.hpp"
|
#include "graphics/camera.hpp"
|
||||||
|
#include "game/systems.hpp"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -21,6 +22,7 @@ int main(int argc, char* argv[]) {
|
||||||
sound::mute(true);
|
sound::mute(true);
|
||||||
|
|
||||||
gui::FSM main;
|
gui::FSM main;
|
||||||
|
System::init(main.$systems);
|
||||||
main.event(game::Event::START);
|
main.event(game::Event::START);
|
||||||
|
|
||||||
sound::play("ambient_1", true);
|
sound::play("ambient_1", true);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ sources = files(
|
||||||
'gui/status_ui.cpp',
|
'gui/status_ui.cpp',
|
||||||
'gui/main_ui.cpp',
|
'gui/main_ui.cpp',
|
||||||
'gui/overlay_ui.cpp',
|
'gui/overlay_ui.cpp',
|
||||||
|
'gui/body_ui.cpp',
|
||||||
|
|
||||||
# graphics
|
# graphics
|
||||||
'graphics/animation.cpp',
|
'graphics/animation.cpp',
|
||||||
|
|
|
||||||
|
|
@ -25,20 +25,17 @@ TEST_CASE("battle operations fantasy", "[combat-battle]") {
|
||||||
|
|
||||||
DinkyECS::Entity host = 0;
|
DinkyECS::Entity host = 0;
|
||||||
ai::EntityAI host_ai("Host::actions", host_start, host_goal);
|
ai::EntityAI host_ai("Host::actions", host_start, host_goal);
|
||||||
components::Combat host_combat{
|
components::Combat host_combat{.ap_delta=6, .max_ap=12, .damage=20};
|
||||||
.hp=100, .max_hp=100, .ap_delta=6, .max_ap=12, .damage=20};
|
|
||||||
battle.add_enemy({host, &host_ai, &host_combat, true});
|
battle.add_enemy({host, &host_ai, &host_combat, true});
|
||||||
|
|
||||||
DinkyECS::Entity axe_ranger = 1;
|
DinkyECS::Entity axe_ranger = 1;
|
||||||
ai::EntityAI axe_ai("Enemy::actions", ai_start, ai_goal);
|
ai::EntityAI axe_ai("Enemy::actions", ai_start, ai_goal);
|
||||||
components::Combat axe_combat{
|
components::Combat axe_combat{.ap_delta=8, .max_ap=12, .damage=20};
|
||||||
.hp=20, .max_hp=20, .ap_delta=8, .max_ap=12, .damage=20};
|
|
||||||
battle.add_enemy({axe_ranger, &axe_ai, &axe_combat});
|
battle.add_enemy({axe_ranger, &axe_ai, &axe_combat});
|
||||||
|
|
||||||
DinkyECS::Entity rat = 2;
|
DinkyECS::Entity rat = 2;
|
||||||
ai::EntityAI rat_ai("Enemy::actions", ai_start, ai_goal);
|
ai::EntityAI rat_ai("Enemy::actions", ai_start, ai_goal);
|
||||||
components::Combat rat_combat{
|
components::Combat rat_combat{.ap_delta=2, .max_ap=10, .damage=10};
|
||||||
.hp=10, .max_hp=10, .ap_delta=2, .max_ap=10, .damage=10};
|
|
||||||
battle.add_enemy({rat, &rat_ai, &rat_combat});
|
battle.add_enemy({rat, &rat_ai, &rat_combat});
|
||||||
|
|
||||||
battle.set_all("enemy_found", true);
|
battle.set_all("enemy_found", true);
|
||||||
|
|
@ -50,8 +47,8 @@ TEST_CASE("battle operations fantasy", "[combat-battle]") {
|
||||||
battle.set(host, "have_healing", false);
|
battle.set(host, "have_healing", false);
|
||||||
battle.set(host, "tough_personality", false);
|
battle.set(host, "tough_personality", false);
|
||||||
|
|
||||||
while(host_combat.hp > 0) {
|
while(!host_combat.is_dead()) {
|
||||||
battle.set(host, "health_good", host_combat.hp > 20);
|
battle.set(host, "health_good", host_combat.almost_dead());
|
||||||
|
|
||||||
battle.player_request("use_healing");
|
battle.player_request("use_healing");
|
||||||
battle.player_request("kill_enemy");
|
battle.player_request("kill_enemy");
|
||||||
|
|
@ -62,11 +59,6 @@ TEST_CASE("battle operations fantasy", "[combat-battle]") {
|
||||||
while(auto act = battle.next()) {
|
while(auto act = battle.next()) {
|
||||||
auto& [enemy, wants_to, cost, enemy_state] = *act;
|
auto& [enemy, wants_to, cost, enemy_state] = *act;
|
||||||
|
|
||||||
// fmt::println(">>>>> entity: {} wants to {} cost={}; has {} HP; {} ap",
|
|
||||||
// enemy.entity, wants_to,
|
|
||||||
// cost, enemy.combat->hp,
|
|
||||||
// enemy.combat->ap);
|
|
||||||
|
|
||||||
switch(enemy_state) {
|
switch(enemy_state) {
|
||||||
case BattleHostState::agree:
|
case BattleHostState::agree:
|
||||||
// fmt::println("HOST and PLAYER requests match {}, doing it.", wants_to);
|
// fmt::println("HOST and PLAYER requests match {}, doing it.", wants_to);
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@ using namespace components;
|
||||||
TEST_CASE("test the loot ui", "[loot]") {
|
TEST_CASE("test the loot ui", "[loot]") {
|
||||||
auto items = settings::get("assets/items.json");
|
auto items = settings::get("assets/items.json");
|
||||||
DinkyECS::World world;
|
DinkyECS::World world;
|
||||||
auto torch = world.entity();
|
auto repair_kit = world.entity();
|
||||||
auto& data = items["TORCH_BAD"];
|
auto& data = items["REPAIR_KIT"];
|
||||||
|
|
||||||
components::init();
|
components::init();
|
||||||
components::configure_entity(world, torch, data["components"]);
|
components::configure_entity(world, repair_kit, data["components"]);
|
||||||
|
|
||||||
auto& torch_sprite = world.get<Sprite>(torch);
|
auto& repair_kit_sprite = world.get<Sprite>(repair_kit);
|
||||||
REQUIRE(torch_sprite.name == "torch_horizontal_floor");
|
REQUIRE(repair_kit_sprite.name == "repair_kit");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,8 @@ TEST_CASE("color palette test", "[color-palette]") {
|
||||||
// confirm it's idempotent
|
// confirm it's idempotent
|
||||||
palette::init();
|
palette::init();
|
||||||
|
|
||||||
sf::Color expect{10, 10, 10, 255};
|
|
||||||
|
|
||||||
auto gui_text = palette::get("gui/theme:dark_dark");
|
auto gui_text = palette::get("gui/theme:dark_dark");
|
||||||
REQUIRE(gui_text == expect);
|
REQUIRE(gui_text.r > 0);
|
||||||
|
REQUIRE(gui_text.g > 0);
|
||||||
gui_text = palette::get("gui/theme", "mid");
|
REQUIRE(gui_text.b > 0);
|
||||||
REQUIRE(gui_text != expect);
|
|
||||||
|
|
||||||
expect = {100, 100, 100, 255};
|
|
||||||
REQUIRE(gui_text == expect);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@
|
||||||
#include "game/systems.hpp"
|
#include "game/systems.hpp"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
#include "game/registry.hpp"
|
||||||
|
|
||||||
|
using components::Position;
|
||||||
|
|
||||||
TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
|
TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
|
||||||
Matrix map = matrix::make(3, 3);
|
Matrix map = matrix::make(3, 3);
|
||||||
|
|
@ -35,104 +37,45 @@ TEST_CASE("figure out best rotation direction", "[systems-rotate]") {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using MovingFunc = std::function<void()>;
|
|
||||||
using CombatFunc = std::function<void(bool)>;
|
|
||||||
using RenderFunc = std::function<void()>;
|
|
||||||
using UpdateFunc = std::function<void()>;
|
|
||||||
using UseFunc = std::function<void()>;
|
|
||||||
using PickupFunc = std::function<void()>;
|
|
||||||
|
|
||||||
struct Engine {
|
void test_moving(Position& move_to) {
|
||||||
std::vector<MovingFunc> $moving;
|
fmt::println("MOVING: {},{}", move_to.location.x, move_to.location.y);
|
||||||
std::vector<CombatFunc> $combat;
|
|
||||||
std::vector<RenderFunc> $render;
|
|
||||||
std::vector<UpdateFunc> $update;
|
|
||||||
std::vector<UseFunc> $use;
|
|
||||||
std::vector<PickupFunc> $pickup;
|
|
||||||
|
|
||||||
void addMoving(MovingFunc action) {
|
|
||||||
$moving.emplace_back(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addCombat(CombatFunc action) {
|
|
||||||
$combat.emplace_back(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addRender(RenderFunc action) {
|
|
||||||
$render.emplace_back(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addUpdate(UpdateFunc action) {
|
|
||||||
$update.emplace_back(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addUse(UseFunc action) {
|
|
||||||
$use.emplace_back(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addPickup(PickupFunc action) {
|
|
||||||
$pickup.emplace_back(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
void runMoving() {
|
|
||||||
for(auto func : $moving) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runCombat(bool attr) {
|
|
||||||
for(auto func : $combat) {
|
|
||||||
func(attr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runRender() {
|
|
||||||
for(auto func : $render) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runUpdate() {
|
|
||||||
for(auto func : $update) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runUse() {
|
|
||||||
for(auto func : $use) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void runPickup() {
|
|
||||||
for(auto func : $pickup) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void test_system_1() {
|
|
||||||
fmt::println("TEST 1");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_combat(bool what) {
|
void test_combat(int attack_id) {
|
||||||
fmt::println("TEST 2: {}", what);
|
fmt::println("ATTACK: {}", attack_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_render() {
|
||||||
|
fmt::println("RENDER");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_update() {
|
||||||
|
fmt::println("UPDATE");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_use_item(const std::string& slot_name) {
|
||||||
|
fmt::println("USE ITEM {}", slot_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_pickup() {
|
||||||
|
fmt::println("PICKUP");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("new system running engine thing", "[systems-engine]") {
|
TEST_CASE("new system running engine thing", "[systems-engine]") {
|
||||||
Engine systems;
|
System::Registry systems;
|
||||||
|
|
||||||
systems.addMoving(test_system_1);
|
systems.addMoving(test_moving);
|
||||||
systems.addCombat(test_combat);
|
systems.addCombat(test_combat);
|
||||||
systems.addRender(test_system_1);
|
systems.addRender(test_render);
|
||||||
systems.addUpdate(test_system_1);
|
systems.addUpdate(test_update);
|
||||||
systems.addUse(test_system_1);
|
systems.addUseItem(test_use_item);
|
||||||
systems.addPickup(test_system_1);
|
systems.addPickup(test_pickup);
|
||||||
|
|
||||||
systems.runCombat(false);
|
systems.runCombat(1);
|
||||||
systems.runMoving();
|
systems.runMoving({1,1});
|
||||||
systems.runRender();
|
systems.runRender();
|
||||||
systems.runUpdate();
|
systems.runUpdate();
|
||||||
systems.runUse();
|
systems.runUseItem("hand_l");
|
||||||
systems.runPickup();
|
systems.runPickup();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ TEST_CASE("test texture management", "[textures]") {
|
||||||
components::init();
|
components::init();
|
||||||
textures::init();
|
textures::init();
|
||||||
|
|
||||||
auto spider = textures::get_sprite("rat_with_sword");
|
auto spider = textures::get_sprite("spider_bot");
|
||||||
REQUIRE(spider.sprite != nullptr);
|
REQUIRE(spider.sprite != nullptr);
|
||||||
REQUIRE(spider.texture != nullptr);
|
REQUIRE(spider.texture != nullptr);
|
||||||
REQUIRE(spider.frame_size.x == TEXTURE_WIDTH);
|
REQUIRE(spider.frame_size.x == TEXTURE_WIDTH);
|
||||||
REQUIRE(spider.frame_size.y == TEXTURE_HEIGHT);
|
REQUIRE(spider.frame_size.y == TEXTURE_HEIGHT);
|
||||||
|
|
||||||
auto image = textures::load_image("assets/sprites/rat_with_sword.png");
|
auto image = textures::load_image("assets/sprites/spider_bot.png");
|
||||||
|
|
||||||
size_t floor_tile = textures::get_id("floor_tile");
|
size_t floor_tile = textures::get_id("floor_tile");
|
||||||
size_t gray_stone = textures::get_id("door_plain");
|
size_t gray_stone = textures::get_id("door_plain");
|
||||||
|
|
|
||||||