From 110085eacf6e0a985cdafa38f6c1f359f91a7a5b Mon Sep 17 00:00:00 2001 From: James Melkonian Date: Wed, 19 May 2021 20:45:07 -0700 Subject: [PATCH] Health, energy, mass, and density to RON --- assets/common/body/aggro.ron | 204 +++++++ assets/common/body/base_energy.ron | 67 +++ assets/common/body/base_health.ron | 142 +++++ assets/common/body/base_health_increase.ron | 114 ++++ assets/common/body/density.ron | 62 +++ assets/common/body/mass.ron | 109 ++++ assets/server/manifests/psyche2.ron | 492 +++++++++++++++++ common/src/comp/agent.rs | 79 +-- common/src/comp/body.rs | 561 ++++++++++---------- common/src/comp/energy.rs | 21 +- common/src/comp/health.rs | 21 +- common/src/event.rs | 8 + common/src/states/basic_summon.rs | 6 +- common/src/states/utils.rs | 82 +-- common/systems/src/stats.rs | 30 +- server/src/cmd.rs | 38 +- server/src/events/entity_manipulation.rs | 34 ++ server/src/events/mod.rs | 8 +- server/src/lib.rs | 3 + server/src/rtsim/tick.rs | 24 +- server/src/state_ext.rs | 128 ++++- server/src/sys/agent.rs | 2 + server/src/sys/terrain.rs | 24 +- 23 files changed, 1784 insertions(+), 475 deletions(-) create mode 100644 assets/common/body/aggro.ron create mode 100644 assets/common/body/base_energy.ron create mode 100644 assets/common/body/base_health.ron create mode 100644 assets/common/body/base_health_increase.ron create mode 100644 assets/common/body/density.ron create mode 100644 assets/common/body/mass.ron create mode 100644 assets/server/manifests/psyche2.ron diff --git a/assets/common/body/aggro.ron b/assets/common/body/aggro.ron new file mode 100644 index 0000000000..c60a95242c --- /dev/null +++ b/assets/common/body/aggro.ron @@ -0,0 +1,204 @@ +( + humanoid: ( + body: 0.8, + species: ( + danari: Some(0.9), + dwarf: Some(0.8), + elf: Some(0.7), + human: Some(0.6), + orc: Some(0.9), + undead: Some(0.9), + ) + ), + quadruped_medium: ( + body: 0.6, + species: ( + grolgar: Some(0.8), + saber: Some(0.8), + tuskram: Some(0.7), + lion: Some(0.8), + tarasque: Some(0.8), + tiger: Some(0.8), + wolf: Some(0.8), + frostfang: Some(0.9), + mouflon: Some(0.7), + catoblepas: Some(0.8), + bonerattler: Some(0.8), + deer: Some(0.6), + hirdrasil: Some(0.7), + roshwalr: Some(0.8), + donkey: Some(0.7), + camel: Some(0.7), + zebra: Some(0.7), + antelope: Some(0.6), + kelpie: Some(0.7), + horse: Some(0.7), + barghest: Some(0.5), + cattle: Some(0.7), + darkhound: Some(0.9), + highland: Some(0.7), + yak: Some(0.7), + panda: Some(0.7), + bear: Some(0.9), + dreadhorn: Some(0.8), + moose: Some(0.8), + snowleopard: Some(0.9), + ) + ), + quadruped_small: ( + body: 0.0, + species: ( + pig: Some(0.5), + fox: Some(0.3), + sheep: Some(0.5), + boar: Some(0.8), + jackalope: Some(0.4), + skunk: Some(0.6), + cat: Some(0.2), + batfox: Some(0.6), + raccoon: Some(0.4), + quokka: Some(0.4), + dodarock: Some(0.9), + holladon: Some(1.0), + hyena: Some(0.4), + rabbit: Some(0.1), + truffler: Some(0.8), + frog: Some(0.4), + rat: Some(0.0), + axolotl: Some(0.0), + gecko: Some(0.0), + turtle: Some(0.8), + squirrel: Some(0.1), + fungome: Some(0.0), + porcupine: Some(0.4), + beaver: Some(0.5), + hare: Some(0.3), + dog: Some(0.5), + goat: Some(0.5), + ) + ), + bird_medium: ( + body: 0.8, + species: ( + duck: Some(0.8), + chicken: Some(0.8), + goose: Some(0.8), + peacock: Some(0.8), + eagle: Some(0.8), + owl: Some(0.8), + parrot: Some(0.8), + ) + ), + biped_large: ( + body: 1.0, + species: ( + ogre: Some(1.0), + cyclops: Some(1.0), + wendigo: Some(1.0), + troll: Some(1.0), + dullahan: Some(1.0), + werewolf: Some(1.0), + saurok_occult: Some(1.0), + saurok_mighty: Some(1.0), + saurok_sly: Some(1.0), + mindflayer: Some(1.0), + minotaur: Some(1.0), + tidalwarrior: Some(1.0), + yeti: Some(1.0), + harvester: Some(1.0), + oni_blue: Some(1.0), + oni_red: Some(1.0), + ) + ), + golem: ( + body: 1.0, + species: ( + stonegolem: Some(1.0), + treant: Some(1.0), + claygolem: Some(1.0), + ) + ), + theropod: ( + body: 1.0, + species: ( + archaeos: Some(1.0), + odonto: Some(1.0), + raptor_sand: Some(1.0), + raptor_snow: Some(1.0), + raptor_wood: Some(1.0), + sunlizard: Some(1.0), + yale: Some(1.0), + ntouka: Some(1.0), + ) + ), + dragon: ( + body: 1.0, + species: ( + reddragon: Some(1.0), + ) + ), + object: ( + body: 1.0, + species: () + ), + ship: ( + body: 1.0, + species: (), + ), + biped_small: ( + body: 0.5, + species: ( + gnome: Some(0.5), + sahagin: Some(0.5), + adlet: Some(0.5), + gnarling: Some(0.5), + mandragora: Some(0.5), + kappa: Some(0.5), + cactid: Some(0.5), + gnoll: Some(0.5), + haniwa: Some(0.5), + myrmidon: Some(0.5), + husk: Some(0.5), + ) + ), + fish_small: ( + body: 0.0, + species: ( + clownfish: Some(0.0), + piranha: Some(0.0), + ) + ), + fish_medium: ( + body: 0.15, + species: ( + marlin: Some(0.15), + icepike: Some(0.15), + ) + ), + bird_large: ( + body: 0.9, + species: ( + phoenix: Some(0.9), + cockatrice: Some(0.9), + ) + ), + quadruped_low: ( + body: 0.6, + species: ( + crocodile: Some(0.8), + alligator: Some(0.8), + salamander: Some(0.7), + monitor: Some(0.7), + asp: Some(0.9), + tortoise: Some(0.6), + rocksnapper: Some(0.8), + pangolin: Some(0.4), + maneater: Some(0.8), + sandshark: Some(0.9), + hakulaq: Some(0.9), + lavadrake: Some(0.9), + basilisk: Some(0.8), + deadwood: Some(0.6), + ) + ) +) diff --git a/assets/common/body/base_energy.ron b/assets/common/body/base_energy.ron new file mode 100644 index 0000000000..d0305e24a5 --- /dev/null +++ b/assets/common/body/base_energy.ron @@ -0,0 +1,67 @@ +( + humanoid: ( + body: 750, + species: (), + ), + quadruped_medium: ( + body: 1000, + species: (), + ), + quadruped_small: ( + body: 1000, + species: (), + ), + bird_medium: ( + body: 1000, + species: (), + ), + biped_large: ( + body: 3000, + species: ( + dullahan: Some(4000), + ) + ), + golem: ( + body: 1000, + species: (), + ), + theropod: ( + body: 1000, + species: (), + ), + dragon: ( + body: 1000, + species: (), + ), + object: ( + body: 1000, + species: () + ), + ship: ( + body: 1000, + species: (), + ), + biped_small: ( + body: 1000, + species: (), + ), + fish_small: ( + body: 1000, + species: (), + ), + fish_medium: ( + body: 1000, + species: (), + ), + bird_large: ( + body: 3000, + species: ( + phoenix: Some(6000), + cockatrice: Some(4000), + ) + ), + quadruped_low: ( + body: 1000, + species: (), + ) +) diff --git a/assets/common/body/base_health.ron b/assets/common/body/base_health.ron new file mode 100644 index 0000000000..c5e5cd986b --- /dev/null +++ b/assets/common/body/base_health.ron @@ -0,0 +1,142 @@ +( + humanoid: ( + body: 500, + species: (), + ), + quadruped_medium: ( + body: 700, + species: ( + grolgar: Some(900), + saber: Some(600), + tuskram: Some(900), + lion: Some(900), + tarasque: Some(1500), + tiger: Some(700), + wolf: Some(550), + frostfang: Some(400), + mouflon: Some(500), + catoblepas: Some(1000), + bonerattler: Some(500), + deer: Some(500), + roshwalr: Some(800), + donkey: Some(550), + zebra: Some(550), + antelope: Some(450), + kelpie: Some(600), + horse: Some(600), + barghest: Some(1700), + cattle: Some(1000), + highland: Some(1200), + yak: Some(1100), + panda: Some(900), + bear: Some(900), + moose: Some(800), + dreadhorn: Some(1100), + snowleopard: Some(900), + ) + ), + quadruped_small: ( + body: 400, + species: ( + boar: Some(700), + batfox: Some(400), + dodarock: Some(1000), + holladon: Some(800), + hyena: Some(450), + truffler: Some(450), + ) + ), + bird_medium: ( + body: 250, + species: ( + chicken: Some(300), + duck: Some(300), + goose: Some(300), + peacock: Some(350), + eagle: Some(450), + ) + ), + biped_large: ( + body: 1200, + species: ( + ogre: Some(3200), + cyclops: Some(3200), + wendigo: Some(2800), + troll: Some(2400), + dullahan: Some(3000), + mindflayer: Some(12500), + minotaur: Some(30000), + tidalwarrior: Some(2500), + yeti: Some(4000), + harvester: Some(3000), + oni_blue: Some(2400), + oni_red: Some(2400), + ) + ), + golem: ( + body: 10000, + species: ( + claygolem: Some(7500), + ) + ), + theropod: ( + body: 1100, + species: ( + archaeos: Some(3500), + odonto: Some(3000), + ) + ), + dragon: ( + body: 5000, + species: (), + ), + object: ( + body: 10000, + species: (), + ), + ship: ( + body: 10000, + species: (), + ), + biped_small: ( + body: 600, + species: ( + gnarling: Some(500), + adlet: Some(600), + sahagin: Some(800), + haniwa: Some(900), + myrmidon: Some(900), + husk: Some(200), + ) + ), + fish_small: ( + body: 20, + species: (), + ), + fish_medium: ( + body: 250, + species: (), + ), + bird_large: ( + body: 3000, + species: (), + ), + quadruped_low: ( + body: 700, + species: ( + crocodile: Some(900), + alligator: Some(800), + monitor: Some(600), + asp: Some(750), + tortoise: Some(900), + rocksnapper: Some(1200), + pangolin: Some(400), + maneater: Some(700), + sandshark: Some(900), + hakulaq: Some(500), + lavadrake: Some(1000), + basilisk: Some(1000), + deadwood: Some(700), + ) + ) +) diff --git a/assets/common/body/base_health_increase.ron b/assets/common/body/base_health_increase.ron new file mode 100644 index 0000000000..5e96474afd --- /dev/null +++ b/assets/common/body/base_health_increase.ron @@ -0,0 +1,114 @@ +( + humanoid: ( + body: 50, + species: (), + ), + quadruped_medium: ( + body: 20, + species: ( + grolgar: Some(30), + tuskram: Some(30), + lion: Some(40), + tarasque: Some(60), + wolf: Some(20), + frostfang: Some(40), + mouflon: Some(30), + catoblepas: Some(50), + bonerattler: Some(30), + hirdrasil: Some(30), + roshwalr: Some(40), + donkey: Some(30), + camel: Some(30), + zebra: Some(30), + kelpie: Some(30), + horse: Some(30), + barghest: Some(50), + cattle: Some(30), + highland: Some(30), + yak: Some(30), + panda: Some(40), + bear: Some(40), + moose: Some(30), + dreadhorn: Some(50), + ) + ), + quadruped_small: ( + body: 10, + species: ( + boar: Some(20), + dodarock: Some(30), + holladon: Some(30), + hyena: Some(20), + truffler: Some(20), + ) + ), + bird_medium: ( + body: 10, + species: (), + ), + biped_large: ( + body: 100, + species: ( + ogre: Some(70), + cyclops: Some(80), + wendigo: Some(80), + troll: Some(60), + dullahan: Some(120), + tidalwarrior: Some(90), + yeti: Some(80), + harvester: Some(80), + // Boss enemies have their health set, + // not adjusted by level. + ) + ), + golem: ( + body: 0, + species: (), + ), + theropod: ( + body: 20, + species: (), + ), + dragon: ( + body: 500, + species: (), + ), + object: ( + body: 10, + species: (), + ), + ship: ( + body: 10, + species: (), + ), + biped_small: ( + body: 10, + species: (), + ), + fish_small: ( + body: 10, + species: (), + ), + fish_medium: ( + body: 10, + species: (), + ), + bird_large: ( + body: 120, + species: (), + ), + quadruped_low: ( + body: 20, + species: ( + salamander: Some(10), + monitor: Some(10), + asp: Some(10), + rocksnapper: Some(50), + pangolin: Some(10), + maneater: Some(30), + sandshark: Some(40), + hakulaq: Some(10), + deadwood: Some(30), + ) + ) +) diff --git a/assets/common/body/density.ron b/assets/common/body/density.ron new file mode 100644 index 0000000000..c69dc11dc1 --- /dev/null +++ b/assets/common/body/density.ron @@ -0,0 +1,62 @@ +( + humanoid: ( + body: 990.0, + species: (), + ), + quadruped_medium: ( + body: 990.0, + species: (), + ), + quadruped_small: ( + body: 990.0, + species: (), + ), + biped_large: ( + body: 990.0, + species: (), + ), + golem: ( + body: 2500.0, + species: (), + ), + theropod: ( + body: 990.0, + species: (), + ), + dragon: ( + body: 3700.0, + species: (), + ), + object: ( + body: 990.0, + species: () + ), + ship: ( + body: 990.0, + species: (), + ), + biped_small: ( + body: 990.0, + species: (), + ), + fish_small: ( + body: 999.1, + species: (), + ), + fish_medium: ( + body: 999.1, + species: (), + ), + bird_medium: ( + body: 700.0, + species: (), + ), + bird_large: ( + body: 990.0, + species: (), + ), + quadruped_low: ( + body: 990.0, + species: (), + ) +) diff --git a/assets/common/body/mass.ron b/assets/common/body/mass.ron new file mode 100644 index 0000000000..51100c6cea --- /dev/null +++ b/assets/common/body/mass.ron @@ -0,0 +1,109 @@ +( + humanoid: ( + body: 77.0, + species: ( + danari: Some(60.0), + dwarf: Some(80.0), + elf: Some(77.0), + human: Some(77.0), + orc: Some(95.0), + undead: Some(65.0), + ) + ), + quadruped_medium: ( + body: 200.0, + species: ( + saber: Some(130.0), + lion: Some(170.0), + deer: Some(80.0), + antelope: Some(120.0), + kelpie: Some(300.0), + horse: Some(300.0), + cattle: Some(575.0), + highland: Some(600.0), + yak: Some(600.0), + bear: Some(500.0), + moose: Some(500.0), + ) + ), + quadruped_small: ( + body: 80.0, + species: ( + boar: Some(80.0), + batfox: Some(50.0), + dodarock: Some(150.0), + holladon: Some(100.0), + hyena: Some(70.0), + truffler: Some(150.0), + ) + ), + biped_large: ( + body: 400.0, + species: ( + mindflayer: Some(420.0), + minotaur: Some(500.0), + ) + ), + golem: ( + body: 1000.0, + species: (), + ), + theropod: ( + body: 1000.0, + species: ( + archaeos: Some(10000.0), + ntouka: Some(5000.0), + odonto: Some(10000.0), + raptor_sand: Some(500.0), + raptor_snow: Some(500.0), + raptor_wood: Some(500.0), + sunlizard: Some(500.0), + ) + ), + dragon: ( + body: 2000.0, + species: (), + ), + object: ( + body: 1.0, + species: () + ), + ship: ( + body: 1.0, + species: (), + ), + biped_small: ( + body: 50.0, + species: (), + ), + fish_small: ( + body: 1.0, + species: (), + ), + fish_medium: ( + body: 2.5, + species: (), + ), + bird_medium: ( + body: 2.0, + species: (), + ), + bird_large: ( + body: 200.0, + species: (), + ), + quadruped_low: ( + body: 200.0, + species: ( + crocodile: Some(360.0), + alligator: Some(360.0), + monitor: Some(100.0), + asp: Some(300.0), + tortoise: Some(200.0), + rocksnapper: Some(300.0), + pangolin: Some(60.0), + lavadrake: Some(500.0), + deadwood: Some(50.0), + ) + ) +) diff --git a/assets/server/manifests/psyche2.ron b/assets/server/manifests/psyche2.ron new file mode 100644 index 0000000000..f9303b9e54 --- /dev/null +++ b/assets/server/manifests/psyche2.ron @@ -0,0 +1,492 @@ +( + humanoid: ( + body: ( + aggro: 0.8, + ), + species: ( + danari: ( + aggro: 0.9, + ), + dwarf: ( + aggro: 0.8, + ), + elf: ( + aggro: 0.7, + ), + human: ( + aggro: 0.6, + ), + orc: ( + aggro: 0.9, + ), + undead: ( + aggro: 0.9, + ) + ) + ), + quadruped_medium: ( + body: ( + aggro: 0.8, + ), + species: ( + grolgar: ( + aggro: 0.8, + ), + saber: ( + aggro: 0.8, + ), + tuskram: ( + aggro: 0.7, + ), + lion: ( + aggro: 0.8, + ), + tarasque: ( + aggro: 0.8, + ), + tiger: ( + aggro: 0.8, + ), + wolf: ( + aggro: 0.8, + ), + frostfang: ( + aggro: 0.9, + ), + mouflon: ( + aggro: 0.7, + ), + catoblepas: ( + aggro: 0.8, + ), + bonerattler: ( + aggro: 0.8, + ), + deer: ( + aggro: 0.6, + ), + hirdrasil: ( + aggro: 0.7, + ), + roshwalr: ( + aggro: 0.8, + ), + donkey: ( + aggro: 0.7, + ), + camel: ( + aggro: 0.7, + ), + zebra: ( + aggro: 0.7, + ), + antelope: ( + aggro: 0.6, + ), + kelpie: ( + aggro: 0.7, + ), + horse: ( + aggro: 0.7, + ), + barghest: ( + aggro: 0.5, + ), + cattle: ( + aggro: 0.7, + ), + darkhound: ( + aggro: 0.9, + ), + highland: ( + aggro: 0.7, + ), + yak: ( + aggro: 0.7, + ), + panda: ( + aggro: 0.7, + ), + bear: ( + aggro: 0.9, + ), + dreadhorn: ( + aggro: 0.8, + ), + moose: ( + aggro: 0.8, + ), + snowleopard: ( + aggro: 0.9, + ) + ) + ), + quadruped_small: ( + body: ( + aggro: 0.8, + ), + species: ( + pig: ( + aggro: 0.5, + ), + fox: ( + aggro: 0.3, + ), + sheep: ( + aggro: 0.5, + ), + boar: ( + aggro: 0.8, + ), + jackalope: ( + aggro: 0.4, + ), + skunk: ( + aggro: 0.6, + ), + cat: ( + aggro: 0.2, + ), + batfox: ( + aggro: 0.6, + ), + raccoon: ( + aggro: 0.4, + ), + quokka: ( + aggro: 0.4, + ), + dodarock: ( + aggro: 0.9, + ), + holladon: ( + aggro: 1.0, + ), + hyena: ( + aggro: 0.4, + ), + rabbit: ( + aggro: 0.1, + ), + truffler: ( + aggro: 0.8, + ), + frog: ( + aggro: 0.4, + ), + rat: ( + aggro: 0.0, + ), + axolotl: ( + aggro: 0.0, + ), + gecko: ( + aggro: 0.0, + ), + turtle: ( + aggro: 0.8, + ), + squirrel: ( + aggro: 0.1, + ), + fungome: ( + aggro: 0.0, + ), + porcupine: ( + aggro: 0.4, + ), + beaver: ( + aggro: 0.5, + ), + hare: ( + aggro: 0.3, + ), + dog: ( + aggro: 0.5, + ), + goat: ( + aggro: 0.5, + ) + ) + ), + bird_medium: ( + body: ( + aggro: 0.8, + ), + species: ( + duck: ( + aggro: 0.8, + ), + chicken: ( + aggro: 0.8, + ), + goose: ( + aggro: 0.8, + ), + peacock: ( + aggro: 0.8, + ), + eagle: ( + aggro: 0.8, + ), + owl: ( + aggro: 0.8, + ), + parrot: ( + aggro: 0.8, + ), + ) + ), + biped_large: ( + body: ( + aggro: 1.0, + ), + species: ( + ogre: ( + aggro: 1.0, + ), + cyclops: ( + aggro: 1.0, + ), + wendigo: ( + aggro: 1.0, + ), + troll: ( + aggro: 1.0, + ), + dullahan: ( + aggro: 1.0, + ), + werewolf: ( + aggro: 1.0, + ), + saurok_occult: ( + aggro: 1.0, + ), + saurok_mighty: ( + aggro: 1.0, + ), + saurok_sly: ( + aggro: 1.0, + ), + mindflayer: ( + aggro: 1.0, + ), + minotaur: ( + aggro: 1.0, + ), + tidalwarrior: ( + aggro: 1.0, + ), + yeti: ( + aggro: 1.0, + ), + harvester: ( + aggro: 1.0, + ), + oni_blue: ( + aggro: 1.0, + ), + oni_red: ( + aggro: 1.0, + ), + ) + ), + golem: ( + body: ( + aggro: 1.0, + ), + species: ( + stonegolem: ( + aggro: 1.0, + ), + treant: ( + aggro: 1.0, + ), + claygolem: ( + aggro: 1.0, + ) + ) + ), + theropod: ( + body: ( + aggro: 1.0, + ), + species: ( + archaeos: ( + aggro: 1.0, + ), + odonto: ( + aggro: 1.0, + ), + raptor_sand: ( + aggro: 1.0, + ), + raptor_snow: ( + aggro: 1.0, + ), + raptor_wood: ( + aggro: 1.0, + ), + sunlizard: ( + aggro: 1.0, + ), + yale: ( + aggro: 1.0, + ), + ntouka: ( + aggro: 1.0, + ) + ) + ), + dragon: ( + body: ( + aggro: 1.0, + ), + species: ( + reddragon: ( + aggro: 1.0, + ) + ) + ), + object: ( + body: ( + aggro: 1.0, + ), + species: () + ), + ship: ( + body: ( + aggro: 1.0, + ), + species: (), + ), + biped_small: ( + body: ( + aggro: 0.5, + ), + species: ( + gnome: ( + aggro: 0.5, + ), + sahagin: ( + aggro: 0.5, + ), + adlet: ( + aggro: 0.5, + ), + gnarling: ( + aggro: 0.5, + ), + mandragora: ( + aggro: 0.5, + ), + kappa: ( + aggro: 0.5, + ), + cactid: ( + aggro: 0.5, + ), + gnoll: ( + aggro: 0.5, + ), + haniwa: ( + aggro: 0.5, + ), + myrmidon: ( + aggro: 0.5, + ), + husk: ( + aggro: 0.5, + ) + ) + ), + fish_small: ( + body: ( + aggro: 0.0, + ), + species: ( + clownfish: ( + aggro: 0.0, + ), + piranha: ( + aggro: 0.0, + ) + ) + ), + fish_medium: ( + body: ( + aggro: 0.15, + ), + species: ( + marlin: ( + aggro: 0.15, + ), + icepike: ( + aggro: 0.15, + ) + ) + ), + bird_large: ( + body: ( + aggro: 0.9, + ), + species: ( + phoenix: ( + aggro: 0.9, + ), + cockatrice: ( + aggro: 0.9, + ), + ) + ), + quadruped_low: ( + body: ( + aggro: 0.8, + ), + species: ( + crocodile: ( + aggro: 0.8, + ), + alligator: ( + aggro: 0.8, + ), + salamander: ( + aggro: 0.7, + ), + monitor: ( + aggro: 0.7, + ), + asp: ( + aggro: 0.9, + ), + tortoise: ( + aggro: 0.6, + ), + rocksnapper: ( + aggro: 0.8, + ), + pangolin: ( + aggro: 0.4, + ), + maneater: ( + aggro: 0.8, + ), + sandshark: ( + aggro: 0.9, + ), + hakulaq: ( + aggro: 0.9, + ), + lavadrake: ( + aggro: 0.9, + ), + basilisk: ( + aggro: 0.8, + ), + deadwood: ( + aggro: 0.6, + ), + ) + ) +) diff --git a/common/src/comp/agent.rs b/common/src/comp/agent.rs index 0bb02f01ec..0eb1d03ce7 100644 --- a/common/src/comp/agent.rs +++ b/common/src/comp/agent.rs @@ -1,5 +1,4 @@ use crate::{ - comp::{humanoid, quadruped_low, quadruped_medium, quadruped_small, Body}, path::Chaser, rtsim::RtSimController, trade::{PendingTrade, ReducedInventory, SiteId, SitePrices, TradeId, TradeResult}, @@ -163,80 +162,6 @@ pub struct Psyche { pub aggro: f32, // 0.0 = always flees, 1.0 = always attacks, 0.5 = flee at 50% health } -impl<'a> From<&'a Body> for Psyche { - fn from(body: &'a Body) -> Self { - Self { - aggro: match body { - Body::Humanoid(humanoid) => match humanoid.species { - humanoid::Species::Danari => 0.9, - humanoid::Species::Dwarf => 0.8, - humanoid::Species::Elf => 0.7, - humanoid::Species::Human => 0.6, - humanoid::Species::Orc => 0.9, - humanoid::Species::Undead => 0.9, - }, - Body::QuadrupedSmall(quadruped_small) => match quadruped_small.species { - quadruped_small::Species::Pig => 0.5, - quadruped_small::Species::Fox => 0.3, - quadruped_small::Species::Sheep => 0.5, - quadruped_small::Species::Boar => 0.8, - quadruped_small::Species::Jackalope => 0.4, - quadruped_small::Species::Skunk => 0.6, - quadruped_small::Species::Cat => 0.2, - quadruped_small::Species::Batfox => 0.6, - quadruped_small::Species::Raccoon => 0.4, - quadruped_small::Species::Quokka => 0.4, - quadruped_small::Species::Dodarock => 0.9, - quadruped_small::Species::Holladon => 1.0, - quadruped_small::Species::Hyena => 0.4, - quadruped_small::Species::Rabbit => 0.1, - quadruped_small::Species::Truffler => 0.8, - quadruped_small::Species::Frog => 0.4, - quadruped_small::Species::Hare => 0.2, - quadruped_small::Species::Goat => 0.5, - _ => 0.0, - }, - Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { - quadruped_medium::Species::Tuskram => 0.7, - quadruped_medium::Species::Frostfang => 0.9, - quadruped_medium::Species::Mouflon => 0.7, - quadruped_medium::Species::Catoblepas => 0.8, - quadruped_medium::Species::Deer => 0.6, - quadruped_medium::Species::Hirdrasil => 0.7, - quadruped_medium::Species::Donkey => 0.7, - quadruped_medium::Species::Camel => 0.7, - quadruped_medium::Species::Zebra => 0.7, - quadruped_medium::Species::Antelope => 0.6, - quadruped_medium::Species::Horse => 0.7, - quadruped_medium::Species::Cattle => 0.7, - quadruped_medium::Species::Darkhound => 0.9, - quadruped_medium::Species::Dreadhorn => 0.8, - quadruped_medium::Species::Snowleopard => 0.7, - _ => 0.5, - }, - Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { - quadruped_low::Species::Salamander => 0.7, - quadruped_low::Species::Monitor => 0.7, - quadruped_low::Species::Asp => 0.9, - quadruped_low::Species::Pangolin => 0.4, - _ => 0.6, - }, - Body::BipedSmall(_) => 0.5, - Body::BirdMedium(_) => 0.5, - Body::BirdLarge(_) => 0.9, - Body::FishMedium(_) => 0.15, - Body::FishSmall(_) => 0.0, - Body::BipedLarge(_) => 1.0, - Body::Object(_) => 1.0, - Body::Golem(_) => 1.0, - Body::Theropod(_) => 1.0, - Body::Dragon(_) => 1.0, - Body::Ship(_) => 1.0, - }, - } - } -} - #[derive(Clone, Debug)] /// Events that affect agent behavior from other entities/players/environment pub enum AgentEvent { @@ -338,16 +263,16 @@ impl Agent { pub fn new( patrol_origin: Option>, - body: &Body, behavior: Behavior, no_flee: bool, + aggro: f32, ) -> Self { Agent { patrol_origin, psyche: if no_flee { Psyche { aggro: 1.0 } } else { - Psyche::from(body) + Psyche { aggro } }, behavior, ..Default::default() diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 21411bd035..0d0e515e5c 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -16,7 +16,6 @@ pub mod theropod; use crate::{ assets::{self, Asset}, - consts::{HUMAN_DENSITY, WATER_DENSITY}, make_case_elim, npc::NpcKind, }; @@ -146,126 +145,205 @@ impl< const EXTENSION: &'static str = "ron"; } +pub type BodyAggro = f32; +pub type SpeciesAggro = Option; +/// Type holding aggro data for bodies and species. +pub type AllBodiesAggro = AllBodies; + +pub type BodyDensity = f32; +pub type SpeciesDensity = Option; +/// Type holding density data for bodies and species. +pub type AllBodiesDensity = AllBodies; + +pub type BodyMass = f32; +pub type SpeciesMass = Option; +/// Type holding mass data for bodies and species. +pub type AllBodiesMass = AllBodies; + +pub type BodyBaseEnergy = u32; +pub type SpeciesBaseEnergy = Option; +/// Type holding mass data for bodies and species. +pub type AllBodiesBaseEnergy = AllBodies; + +pub type BodyBaseHealth = u32; +pub type SpeciesBaseHealth = Option; +/// Type holding mass data for bodies and species. +pub type AllBodiesBaseHealth = AllBodies; + +pub type BodyBaseHealthIncrease = u32; +pub type SpeciesBaseHealthIncrease = Option; +/// Type holding mass data for bodies and species. +pub type AllBodiesBaseHealthIncrease = AllBodies; + +#[derive(Clone, Debug, Default, Deserialize)] +pub struct BodyAttributes { + pub aggro: Option, + pub density: Option, + pub mass: Option, + pub base_energy: Option, + pub base_health: Option, + pub base_health_increase: Option, +} + +impl assets::Compound for BodyAttributes { + fn load( + cache: &assets::AssetCache, + _: &str, + ) -> Result { + let aggro = cache.load_owned::("common.body.aggro")?; + let density = cache.load_owned::("common.body.density")?; + let mass = cache.load_owned::("common.body.mass")?; + let energy = cache.load_owned::("common.body.base_energy")?; + let health = cache.load_owned::("common.body.base_health")?; + let health_increase = + cache.load_owned::("common.body.base_health_increase")?; + + Ok(Self { + aggro: Some(aggro), + density: Some(density), + mass: Some(mass), + base_energy: Some(energy), + base_health: Some(health), + base_health_increase: Some(health_increase), + }) + } +} + +pub fn get_body_f32_attribute< + 'a, + Species, + SpeciesData: for<'b> core::ops::Index<&'b Species, Output = Option>, +>( + body_data: &'a BodyData, + species: Species, +) -> f32 { + body_data.species[&species].unwrap_or_else(|| body_data.body) +} + +pub fn get_body_u32_attribute< + 'a, + Species, + SpeciesData: for<'b> core::ops::Index<&'b Species, Output = Option>, +>( + body_data: &'a BodyData, + species: Species, +) -> u32 { + body_data.species[&species].unwrap_or_else(|| body_data.body) +} + impl Body { pub fn is_humanoid(&self) -> bool { matches!(self, Body::Humanoid(_)) } /// Average density of the body - // Units are based on kg/m³ - pub fn density(&self) -> Density { - let d = match self { - // based on a house sparrow (Passer domesticus) - Body::BirdMedium(_) => 700.0, - Body::BirdLarge(_) => 2_200.0, - - // based on its mass divided by the volume of a bird scaled up to the size of the dragon - Body::Dragon(_) => 3_700.0, - - Body::Golem(_) => WATER_DENSITY * 2.5, - Body::Humanoid(_) => HUMAN_DENSITY, + /// Units are based on kg/m³ + pub fn density(&self, body_densities: &AllBodiesDensity) -> Density { + let density_value = match self { + Body::BipedLarge(body) => { + get_body_f32_attribute(&body_densities.biped_large, body.species) + }, + Body::BipedSmall(body) => { + get_body_f32_attribute(&body_densities.biped_small, body.species) + }, + Body::BirdMedium(body) => { + get_body_f32_attribute(&body_densities.bird_medium, body.species) + }, + Body::BirdLarge(body) => { + get_body_f32_attribute(&body_densities.bird_large, body.species) + }, + Body::Dragon(body) => get_body_f32_attribute(&body_densities.dragon, body.species), + Body::FishMedium(body) => { + get_body_f32_attribute(&body_densities.fish_medium, body.species) + }, + Body::FishSmall(body) => { + get_body_f32_attribute(&body_densities.fish_small, body.species) + }, + Body::Golem(body) => get_body_f32_attribute(&body_densities.golem, body.species), + Body::Humanoid(body) => get_body_f32_attribute(&body_densities.humanoid, body.species), + Body::QuadrupedLow(body) => { + get_body_f32_attribute(&body_densities.quadruped_low, body.species) + }, + Body::QuadrupedMedium(body) => { + get_body_f32_attribute(&body_densities.quadruped_medium, body.species) + }, + Body::QuadrupedSmall(body) => { + get_body_f32_attribute(&body_densities.quadruped_small, body.species) + }, + Body::Theropod(body) => get_body_f32_attribute(&body_densities.theropod, body.species), Body::Ship(ship) => ship.density().0, Body::Object(object) => object.density().0, - _ => HUMAN_DENSITY, }; - Density(d) + Density(density_value) } - // Values marked with ~✅ are checked based on their RL equivalent. - // Discrepancy in size compared to their RL equivalents has not necessarily been - // taken into account. - pub fn mass(&self) -> Mass { + /// Units are kg + pub fn mass(&self, body_masses: &AllBodiesMass) -> Mass { let m = match self { - Body::BipedLarge(body) => match body.species { - biped_large::Species::Slysaurok => 400.0, - biped_large::Species::Occultsaurok => 400.0, - biped_large::Species::Mightysaurok => 400.0, - biped_large::Species::Mindflayer => 420.0, - biped_large::Species::Minotaur => 500.0, - _ => 400.0, + Body::BipedLarge(body) => { + get_body_f32_attribute(&body_masses.biped_large, body.species) }, - Body::BipedSmall(_) => 50.0, - - // ravens are 0.69-2 kg, crows are 0.51 kg on average - Body::BirdMedium(_) => 1.0, - Body::BirdLarge(_) => 200.0, - - Body::Dragon(_) => 20_000.0, - Body::FishMedium(_) => 2.5, - Body::FishSmall(_) => 1.0, - Body::Golem(_) => 10_000.0, - Body::Humanoid(humanoid) => { - // humanoids are quite a bit larger than in real life, so we multiply their mass - // to scale it up proportionally (remember cube law) - 1.0 * match (humanoid.species, humanoid.body_type) { - (humanoid::Species::Orc, humanoid::BodyType::Male) => 120.0, - (humanoid::Species::Orc, humanoid::BodyType::Female) => 120.0, - (humanoid::Species::Human, humanoid::BodyType::Male) => 77.0, // ~✅ - (humanoid::Species::Human, humanoid::BodyType::Female) => 59.0, // ~✅ - (humanoid::Species::Elf, humanoid::BodyType::Male) => 77.0, - (humanoid::Species::Elf, humanoid::BodyType::Female) => 59.0, - (humanoid::Species::Dwarf, humanoid::BodyType::Male) => 70.0, - (humanoid::Species::Dwarf, humanoid::BodyType::Female) => 70.0, - (humanoid::Species::Undead, humanoid::BodyType::Male) => 70.0, - (humanoid::Species::Undead, humanoid::BodyType::Female) => 50.0, - (humanoid::Species::Danari, humanoid::BodyType::Male) => 80.0, - (humanoid::Species::Danari, humanoid::BodyType::Female) => 60.0, - } + Body::BipedSmall(body) => { + get_body_f32_attribute(&body_masses.biped_small, body.species) }, - Body::Object(obj) => obj.mass().0, - Body::QuadrupedLow(body) => match body.species { - quadruped_low::Species::Alligator => 360.0, // ~✅ - quadruped_low::Species::Asp => 300.0, - // saltwater crocodiles can weigh around 1 ton, but our version is the size of an - // alligator or smaller, so whatever - quadruped_low::Species::Crocodile => 360.0, - quadruped_low::Species::Deadwood => 400.0, - quadruped_low::Species::Lavadrake => 500.0, - quadruped_low::Species::Monitor => 100.0, - quadruped_low::Species::Pangolin => 100.0, - quadruped_low::Species::Salamander => 65.0, - quadruped_low::Species::Tortoise => 200.0, - _ => 200.0, + Body::BirdMedium(body) => { + get_body_f32_attribute(&body_masses.bird_medium, body.species) }, - Body::QuadrupedMedium(body) => match body.species { - quadruped_medium::Species::Bear => 500.0, // ~✅ (350-700 kg) - quadruped_medium::Species::Cattle => 575.0, // ~✅ (500-650 kg) - quadruped_medium::Species::Deer => 80.0, - quadruped_medium::Species::Donkey => 200.0, - quadruped_medium::Species::Highland => 200.0, - quadruped_medium::Species::Horse => 500.0, // ~✅ - quadruped_medium::Species::Kelpie => 200.0, - quadruped_medium::Species::Lion => 170.0, // ~✅ (110-225 kg) - quadruped_medium::Species::Panda => 200.0, - quadruped_medium::Species::Saber => 130.0, - quadruped_medium::Species::Yak => 200.0, - _ => 200.0, + Body::BirdLarge(body) => get_body_f32_attribute(&body_masses.bird_large, body.species), + Body::Dragon(body) => get_body_f32_attribute(&body_masses.dragon, body.species), + Body::FishMedium(body) => { + get_body_f32_attribute(&body_masses.fish_medium, body.species) }, - Body::QuadrupedSmall(body) => match body.species { - quadruped_small::Species::Batfox => 50.0, - quadruped_small::Species::Boar => 80.0, // ~✅ (60-100 kg) - quadruped_small::Species::Dodarock => 150.0, - quadruped_small::Species::Holladon => 150.0, - quadruped_small::Species::Hyena => 70.0, // ~✅ (vaguely) - quadruped_small::Species::Truffler => 150.0, - _ => 80.0, + Body::FishSmall(body) => get_body_f32_attribute(&body_masses.fish_small, body.species), + Body::Golem(body) => get_body_f32_attribute(&body_masses.golem, body.species), + Body::Humanoid(body) => get_body_f32_attribute(&body_masses.humanoid, body.species), + Body::QuadrupedLow(body) => { + get_body_f32_attribute(&body_masses.quadruped_low, body.species) }, - Body::Theropod(body) => match body.species { - // for reference, elephants are in the range of 2.6-6.9 tons - // and Tyrannosaurus rex were ~8.4-14 tons - theropod::Species::Archaeos => 13_000.0, - theropod::Species::Ntouka => 13_000.0, - theropod::Species::Odonto => 13_000.0, - - theropod::Species::Sandraptor => 500.0, - theropod::Species::Snowraptor => 500.0, - theropod::Species::Sunlizard => 500.0, - theropod::Species::Woodraptor => 500.0, - theropod::Species::Yale => 1_000.0, + Body::QuadrupedMedium(body) => { + get_body_f32_attribute(&body_masses.quadruped_medium, body.species) }, - Body::Ship(ship) => ship.mass().0, + Body::QuadrupedSmall(body) => { + get_body_f32_attribute(&body_masses.quadruped_small, body.species) + }, + Body::Theropod(body) => get_body_f32_attribute(&body_masses.theropod, body.species), + Body::Ship(ship) => ship.density().0, + Body::Object(object) => object.density().0, }; Mass(m) } + pub fn aggro(&self, body_aggros: &AllBodiesAggro) -> f32 { + match self { + Body::BipedLarge(body) => { + get_body_f32_attribute(&body_aggros.biped_large, body.species) + }, + Body::BipedSmall(body) => { + get_body_f32_attribute(&body_aggros.biped_small, body.species) + }, + Body::BirdMedium(body) => { + get_body_f32_attribute(&body_aggros.bird_medium, body.species) + }, + Body::BirdLarge(body) => get_body_f32_attribute(&body_aggros.bird_large, body.species), + Body::FishSmall(body) => get_body_f32_attribute(&body_aggros.fish_small, body.species), + Body::FishMedium(body) => { + get_body_f32_attribute(&body_aggros.fish_medium, body.species) + }, + Body::Humanoid(body) => get_body_f32_attribute(&body_aggros.humanoid, body.species), + Body::QuadrupedMedium(body) => { + get_body_f32_attribute(&body_aggros.quadruped_medium, body.species) + }, + Body::QuadrupedSmall(body) => { + get_body_f32_attribute(&body_aggros.quadruped_small, body.species) + }, + Body::Theropod(body) => get_body_f32_attribute(&body_aggros.theropod, body.species), + Body::Dragon(body) => get_body_f32_attribute(&body_aggros.dragon, body.species), + Body::QuadrupedLow(body) => { + get_body_f32_attribute(&body_aggros.quadruped_low, body.species) + }, + Body::Golem(body) => get_body_f32_attribute(&body_aggros.golem, body.species), + Body::Ship(_) | Body::Object(_) => 0.0, + } + } + /// The width (shoulder to shoulder), length (nose to tail) and height /// respectively pub fn dimensions(&self) -> Vec3 { @@ -367,226 +445,123 @@ impl Body { pub fn height(&self) -> f32 { self.dimensions().z } - pub fn base_energy(&self) -> u32 { + pub fn base_energy(&self, body_energies: &AllBodiesBaseEnergy) -> u32 { match self { - Body::BipedLarge(biped_large) => match biped_large.species { - biped_large::Species::Dullahan => 4000, - _ => 3000, + Body::BipedLarge(body) => { + get_body_u32_attribute(&body_energies.biped_large, body.species) }, - Body::BirdLarge(body) => match body.species { - bird_large::Species::Cockatrice => 4000, - bird_large::Species::Phoenix => 6000, + Body::BipedSmall(body) => { + get_body_u32_attribute(&body_energies.biped_small, body.species) }, - Body::Humanoid(_) => 750, - _ => 1000, + Body::BirdMedium(body) => { + get_body_u32_attribute(&body_energies.bird_medium, body.species) + }, + Body::BirdLarge(body) => { + get_body_u32_attribute(&body_energies.bird_large, body.species) + }, + Body::FishSmall(body) => { + get_body_u32_attribute(&body_energies.fish_small, body.species) + }, + Body::FishMedium(body) => { + get_body_u32_attribute(&body_energies.fish_medium, body.species) + }, + Body::Humanoid(body) => get_body_u32_attribute(&body_energies.humanoid, body.species), + Body::QuadrupedMedium(body) => { + get_body_u32_attribute(&body_energies.quadruped_medium, body.species) + }, + Body::QuadrupedSmall(body) => { + get_body_u32_attribute(&body_energies.quadruped_small, body.species) + }, + Body::Theropod(body) => get_body_u32_attribute(&body_energies.theropod, body.species), + Body::Dragon(body) => get_body_u32_attribute(&body_energies.dragon, body.species), + Body::QuadrupedLow(body) => { + get_body_u32_attribute(&body_energies.quadruped_low, body.species) + }, + Body::Golem(body) => get_body_u32_attribute(&body_energies.golem, body.species), + Body::Ship(_) | Body::Object(_) => 1000, } } - #[allow(unreachable_patterns)] - pub fn base_health(&self) -> u32 { + pub fn base_health(&self, body_healths: &AllBodiesBaseHealth) -> u32 { match self { - Body::Humanoid(_) => 500, - Body::QuadrupedSmall(quadruped_small) => match quadruped_small.species { - quadruped_small::Species::Boar => 700, - quadruped_small::Species::Batfox => 400, - quadruped_small::Species::Dodarock => 1000, - quadruped_small::Species::Holladon => 800, - quadruped_small::Species::Hyena => 450, - quadruped_small::Species::Truffler => 450, - _ => 400, + Body::BipedLarge(body) => { + get_body_u32_attribute(&body_healths.biped_large, body.species) }, - Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { - quadruped_medium::Species::Grolgar => 900, - quadruped_medium::Species::Saber => 600, - quadruped_medium::Species::Tiger => 700, - quadruped_medium::Species::Lion => 900, - quadruped_medium::Species::Tarasque => 1500, - quadruped_medium::Species::Wolf => 550, - quadruped_medium::Species::Frostfang => 400, - quadruped_medium::Species::Mouflon => 500, - quadruped_medium::Species::Catoblepas => 1000, - quadruped_medium::Species::Bonerattler => 500, - quadruped_medium::Species::Deer => 500, - quadruped_medium::Species::Hirdrasil => 700, - quadruped_medium::Species::Roshwalr => 800, - quadruped_medium::Species::Donkey => 550, - quadruped_medium::Species::Zebra => 550, - quadruped_medium::Species::Antelope => 450, - quadruped_medium::Species::Kelpie => 600, - quadruped_medium::Species::Horse => 600, - quadruped_medium::Species::Barghest => 1700, - quadruped_medium::Species::Cattle => 1000, - quadruped_medium::Species::Highland => 1200, - quadruped_medium::Species::Yak => 1100, - quadruped_medium::Species::Panda => 900, - quadruped_medium::Species::Bear => 900, - quadruped_medium::Species::Moose => 800, - quadruped_medium::Species::Dreadhorn => 1100, - _ => 700, + Body::BipedSmall(body) => { + get_body_u32_attribute(&body_healths.biped_small, body.species) }, - Body::BirdMedium(bird_medium) => match bird_medium.species { - bird_medium::Species::Chicken => 300, - bird_medium::Species::Duck => 300, - bird_medium::Species::Goose => 300, - bird_medium::Species::Parrot => 250, - bird_medium::Species::Peacock => 350, - bird_medium::Species::Eagle => 450, - _ => 250, + Body::BirdMedium(body) => { + get_body_u32_attribute(&body_healths.bird_medium, body.species) }, - Body::FishMedium(_) => 250, - Body::Dragon(_) => 5000, - Body::BirdLarge(_) => 3000, - Body::FishSmall(_) => 20, - Body::BipedLarge(biped_large) => match biped_large.species { - biped_large::Species::Ogre => 3200, - biped_large::Species::Cyclops => 3200, - biped_large::Species::Wendigo => 2800, - biped_large::Species::Troll => 2400, - biped_large::Species::Dullahan => 3000, - biped_large::Species::Mindflayer => 12500, - biped_large::Species::Tidalwarrior => 2500, - biped_large::Species::Yeti => 4000, - biped_large::Species::Minotaur => 30000, - biped_large::Species::Harvester => 3000, - biped_large::Species::Blueoni => 2400, - biped_large::Species::Redoni => 2400, - _ => 1200, + Body::BirdLarge(body) => get_body_u32_attribute(&body_healths.bird_large, body.species), + Body::FishSmall(body) => get_body_u32_attribute(&body_healths.fish_small, body.species), + Body::FishMedium(body) => { + get_body_u32_attribute(&body_healths.fish_medium, body.species) }, - Body::BipedSmall(biped_small) => match biped_small.species { - biped_small::Species::Gnarling => 500, - biped_small::Species::Adlet => 600, - biped_small::Species::Sahagin => 800, - biped_small::Species::Haniwa => 900, - biped_small::Species::Myrmidon => 900, - biped_small::Species::Husk => 200, - _ => 600, + Body::Humanoid(body) => get_body_u32_attribute(&body_healths.humanoid, body.species), + Body::QuadrupedMedium(body) => { + get_body_u32_attribute(&body_healths.quadruped_medium, body.species) }, + Body::QuadrupedSmall(body) => { + get_body_u32_attribute(&body_healths.quadruped_small, body.species) + }, + Body::Theropod(body) => get_body_u32_attribute(&body_healths.theropod, body.species), + Body::Dragon(body) => get_body_u32_attribute(&body_healths.dragon, body.species), + Body::QuadrupedLow(body) => { + get_body_u32_attribute(&body_healths.quadruped_low, body.species) + }, + Body::Golem(body) => get_body_u32_attribute(&body_healths.golem, body.species), + Body::Ship(_) => 10000, Body::Object(object) => match object { object::Body::TrainingDummy => 10000, object::Body::Crossbow => 800, object::Body::HaniwaSentry => 600, _ => 10000, }, - Body::Golem(golem) => match golem.species { - golem::Species::ClayGolem => 7500, - _ => 10000, - }, - Body::Theropod(theropod) => match theropod.species { - theropod::Species::Archaeos => 3500, - theropod::Species::Odonto => 3000, - _ => 1100, - }, - Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { - quadruped_low::Species::Crocodile => 800, - quadruped_low::Species::Alligator => 900, - quadruped_low::Species::Monitor => 600, - quadruped_low::Species::Asp => 750, - quadruped_low::Species::Tortoise => 900, - quadruped_low::Species::Rocksnapper => 1200, - quadruped_low::Species::Pangolin => 400, - quadruped_low::Species::Maneater => 700, - quadruped_low::Species::Sandshark => 900, - quadruped_low::Species::Hakulaq => 500, - quadruped_low::Species::Lavadrake => 1000, - quadruped_low::Species::Basilisk => 1000, - quadruped_low::Species::Deadwood => 700, - _ => 700, - }, - Body::Ship(_) => 10000, } } - #[allow(unreachable_patterns)] - pub fn base_health_increase(&self) -> u32 { + pub fn base_health_increase(&self, body_health_increases: &AllBodiesBaseHealthIncrease) -> u32 { match self { - Body::Humanoid(_) => 50, - Body::QuadrupedSmall(quadruped_small) => match quadruped_small.species { - quadruped_small::Species::Boar => 20, - quadruped_small::Species::Batfox => 10, - quadruped_small::Species::Dodarock => 30, - quadruped_small::Species::Holladon => 30, - quadruped_small::Species::Hyena => 20, - quadruped_small::Species::Truffler => 20, - _ => 10, + Body::BipedLarge(body) => { + get_body_u32_attribute(&body_health_increases.biped_large, body.species) }, - Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { - quadruped_medium::Species::Grolgar => 30, - quadruped_medium::Species::Saber => 20, - quadruped_medium::Species::Tiger => 20, - quadruped_medium::Species::Tuskram => 30, - quadruped_medium::Species::Lion => 40, - quadruped_medium::Species::Tarasque => 60, - quadruped_medium::Species::Wolf => 20, - quadruped_medium::Species::Frostfang => 40, - quadruped_medium::Species::Mouflon => 30, - quadruped_medium::Species::Catoblepas => 50, - quadruped_medium::Species::Bonerattler => 30, - quadruped_medium::Species::Deer => 20, - quadruped_medium::Species::Hirdrasil => 30, - quadruped_medium::Species::Roshwalr => 40, - quadruped_medium::Species::Donkey => 30, - quadruped_medium::Species::Camel => 30, - quadruped_medium::Species::Zebra => 30, - quadruped_medium::Species::Antelope => 20, - quadruped_medium::Species::Kelpie => 30, - quadruped_medium::Species::Horse => 30, - quadruped_medium::Species::Barghest => 50, - quadruped_medium::Species::Cattle => 30, - quadruped_medium::Species::Highland => 30, - quadruped_medium::Species::Yak => 30, - quadruped_medium::Species::Panda => 40, - quadruped_medium::Species::Bear => 40, - quadruped_medium::Species::Moose => 30, - quadruped_medium::Species::Dreadhorn => 50, - _ => 20, + Body::BipedSmall(body) => { + get_body_u32_attribute(&body_health_increases.biped_small, body.species) }, - Body::BirdMedium(bird_medium) => match bird_medium.species { - bird_medium::Species::Chicken => 10, - bird_medium::Species::Duck => 10, - bird_medium::Species::Goose => 10, - bird_medium::Species::Parrot => 10, - bird_medium::Species::Peacock => 10, - bird_medium::Species::Eagle => 10, - _ => 20, + Body::BirdMedium(body) => { + get_body_u32_attribute(&body_health_increases.bird_medium, body.species) }, - Body::FishMedium(_) => 10, - Body::Dragon(_) => 500, - Body::BirdLarge(_) => 120, - Body::FishSmall(_) => 10, - Body::BipedLarge(biped_large) => match biped_large.species { - biped_large::Species::Ogre => 70, - biped_large::Species::Cyclops => 80, - biped_large::Species::Wendigo => 80, - biped_large::Species::Troll => 60, - biped_large::Species::Dullahan => 120, - biped_large::Species::Tidalwarrior => 90, - biped_large::Species::Yeti => 80, - biped_large::Species::Harvester => 80, - // Boss enemies have their health set, not adjusted by level. - biped_large::Species::Mindflayer => 0, - biped_large::Species::Minotaur => 0, - _ => 100, + Body::BirdLarge(body) => { + get_body_u32_attribute(&body_health_increases.bird_large, body.species) }, - Body::BipedSmall(_) => 10, - Body::Object(_) => 10, - Body::Golem(_) => 0, - Body::Theropod(_) => 20, - Body::QuadrupedLow(quadruped_low) => match quadruped_low.species { - quadruped_low::Species::Crocodile => 20, - quadruped_low::Species::Alligator => 20, - quadruped_low::Species::Salamander => 10, - quadruped_low::Species::Monitor => 10, - quadruped_low::Species::Asp => 10, - quadruped_low::Species::Tortoise => 20, - quadruped_low::Species::Rocksnapper => 50, - quadruped_low::Species::Pangolin => 10, - quadruped_low::Species::Maneater => 30, - quadruped_low::Species::Sandshark => 40, - quadruped_low::Species::Hakulaq => 10, - quadruped_low::Species::Deadwood => 30, - _ => 20, + Body::FishSmall(body) => { + get_body_u32_attribute(&body_health_increases.fish_small, body.species) }, + Body::FishMedium(body) => { + get_body_u32_attribute(&body_health_increases.fish_medium, body.species) + }, + Body::Humanoid(body) => { + get_body_u32_attribute(&body_health_increases.humanoid, body.species) + }, + Body::QuadrupedMedium(body) => { + get_body_u32_attribute(&body_health_increases.quadruped_medium, body.species) + }, + Body::QuadrupedSmall(body) => { + get_body_u32_attribute(&body_health_increases.quadruped_small, body.species) + }, + Body::Theropod(body) => { + get_body_u32_attribute(&body_health_increases.theropod, body.species) + }, + Body::Dragon(body) => { + get_body_u32_attribute(&body_health_increases.dragon, body.species) + }, + Body::QuadrupedLow(body) => { + get_body_u32_attribute(&body_health_increases.quadruped_low, body.species) + }, + Body::Golem(body) => get_body_u32_attribute(&body_health_increases.golem, body.species), Body::Ship(_) => 500, + Body::Object(_) => 10, } } diff --git a/common/src/comp/energy.rs b/common/src/comp/energy.rs index e540cb6ad5..f5e8bef70a 100644 --- a/common/src/comp/energy.rs +++ b/common/src/comp/energy.rs @@ -1,4 +1,3 @@ -use crate::comp::Body; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; @@ -31,10 +30,10 @@ pub enum StatChangeError { } impl Energy { - pub fn new(body: Body, level: u16) -> Energy { + pub fn new(base_energy: u32, level: u16) -> Energy { let mut energy = Energy::empty(); - energy.update_max_energy(Some(body), level); + energy.update_max_energy(base_energy, level); energy.set_to(energy.maximum(), EnergySource::Revive); energy @@ -96,15 +95,13 @@ impl Energy { // it'll set it to base max pub fn last_set(&mut self) { self.last_max = self.maximum } - pub fn update_max_energy(&mut self, body: Option, level: u16) { - if let Some(body) = body { - self.set_base_max(body.base_energy() + 50 * level as u32); - self.set_maximum(body.base_energy() + 50 * level as u32); - self.change_by(EnergyChange { - amount: 50, - source: EnergySource::LevelUp, - }); - } + pub fn update_max_energy(&mut self, base_energy: u32, level: u16) { + self.set_base_max(base_energy + 50 * level as u32); + self.set_maximum(base_energy + 50 * level as u32); + self.change_by(EnergyChange { + amount: 50, + source: EnergySource::LevelUp, + }); } pub fn reset_max(&mut self) { diff --git a/common/src/comp/health.rs b/common/src/comp/health.rs index 3015a01f44..1bb1d7fed5 100644 --- a/common/src/comp/health.rs +++ b/common/src/comp/health.rs @@ -1,5 +1,4 @@ #[cfg(not(target_arch = "wasm32"))] -use crate::comp::Body; use crate::{uid::Uid, DamageSource}; use serde::{Deserialize, Serialize}; @@ -45,10 +44,10 @@ pub struct Health { impl Health { #[cfg(not(target_arch = "wasm32"))] - pub fn new(body: Body, level: u16) -> Self { + pub fn new(base_health: u32, base_health_increase: u32, level: u16) -> Self { let mut health = Health::empty(); - health.update_max_hp(Some(body), level); + health.update_max_health(base_health, base_health_increase, level); health.set_to(health.maximum(), HealthSource::Revive); health @@ -120,15 +119,13 @@ impl Health { // TODO: Delete this once stat points will be a thing #[cfg(not(target_arch = "wasm32"))] - pub fn update_max_hp(&mut self, body: Option, level: u16) { - if let Some(body) = body { - self.set_base_max(body.base_health() + body.base_health_increase() * level as u32); - self.set_maximum(body.base_health() + body.base_health_increase() * level as u32); - self.change_by(HealthChange { - amount: body.base_health_increase() as i32, - cause: HealthSource::LevelUp, - }); - } + pub fn update_max_health(&mut self, base_health: u32, base_health_increase: u32, level: u16) { + self.set_base_max(base_health + base_health_increase * level as u32); + self.set_maximum(base_health + base_health_increase * level as u32); + self.change_by(HealthChange { + amount: base_health_increase as i32, + cause: HealthSource::LevelUp, + }); } /// Returns the fraction of health an entity has remaining diff --git a/common/src/event.rs b/common/src/event.rs index fc6b0f0cce..50e8c975d1 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -41,6 +41,14 @@ pub enum ServerEvent { explosion: Explosion, owner: Option, }, + ModifyHealthLevel { + entity: EcsEntity, + level: u16, + }, + ModifyEnergyLevel { + entity: EcsEntity, + level: u16, + }, Damage { entity: EcsEntity, change: comp::HealthChange, diff --git a/common/src/states/basic_summon.rs b/common/src/states/basic_summon.rs index 7c0a382768..5cab2a4f44 100644 --- a/common/src/states/basic_summon.rs +++ b/common/src/states/basic_summon.rs @@ -98,8 +98,10 @@ impl CharacterBehavior for Data { pos: *data.pos, stats, skill_set, + // FIXME somehow get husk health in here health: comp::Health::new( - body, + 200, + 10, self.static_data.summon_info.health_scaling, ), poise: comp::Poise::new(body), @@ -107,9 +109,9 @@ impl CharacterBehavior for Data { body, agent: Some(comp::Agent::new( None, - &body, Behavior::from(BehaviorCapability::SPEAK), true, + 0.0, )), alignment: comp::Alignment::Owned(*data.uid), scale: self diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 1547bc9838..cd68e8fb92 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -160,35 +160,40 @@ impl Body { /// Returns thrust force if the body type can swim, otherwise None pub fn swim_thrust(&self) -> Option { - match self { - Body::Object(_) | Body::Ship(_) => None, - Body::BipedLarge(_) | Body::Golem(_) => Some(200.0 * self.mass().0), - Body::BipedSmall(_) => Some(100.0 * self.mass().0), - Body::BirdMedium(_) => Some(50.0 * self.mass().0), - Body::BirdLarge(_) => Some(50.0 * self.mass().0), - Body::FishMedium(_) => Some(50.0 * self.mass().0), - Body::FishSmall(_) => Some(50.0 * self.mass().0), - Body::Dragon(_) => Some(200.0 * self.mass().0), - Body::Humanoid(_) => Some(200.0 * self.mass().0), - Body::Theropod(body) => match body.species { - theropod::Species::Sandraptor - | theropod::Species::Snowraptor - | theropod::Species::Sunlizard - | theropod::Species::Woodraptor - | theropod::Species::Yale => Some(200.0 * self.mass().0), - _ => Some(100.0 * self.mass().0), - }, - Body::QuadrupedLow(_) => Some(300.0 * self.mass().0), - Body::QuadrupedMedium(_) => Some(300.0 * self.mass().0), - Body::QuadrupedSmall(_) => Some(300.0 * self.mass().0), - } + Some(14000.0) + //match self { + // Body::Object(_) | Body::Ship(_) => None, + // Body::BipedLarge(_) | Body::Golem(_) => Some(200.0 * + // self.mass().0), Body::BipedSmall(_) => Some(100.0 * + // self.mass().0), Body::BirdMedium(_) => Some(50.0 * + // self.mass().0), Body::BirdLarge(_) => Some(50.0 * + // self.mass().0), Body::FishMedium(_) => Some(50.0 * + // self.mass().0), Body::FishSmall(_) => Some(50.0 * + // self.mass().0), Body::Dragon(_) => Some(200.0 * + // self.mass().0), Body::Humanoid(_) => Some(200.0 * + // self.mass().0), Body::Theropod(body) => match body.species + // { theropod::Species::Sandraptor + // | theropod::Species::Snowraptor + // | theropod::Species::Sunlizard + // | theropod::Species::Woodraptor + // | theropod::Species::Yale => Some(200.0 * self.mass().0), + // _ => Some(100.0 * self.mass().0), + // }, + // Body::QuadrupedLow(_) => Some(300.0 * self.mass().0), + // Body::QuadrupedMedium(_) => Some(300.0 * self.mass().0), + // Body::QuadrupedSmall(_) => Some(300.0 * self.mass().0), + //} } /// Returns thrust force if the body type can fly, otherwise None pub fn fly_thrust(&self) -> Option { match self { - Body::BirdMedium(_) => Some(GRAVITY * self.mass().0 * 2.0), - Body::BirdLarge(_) => Some(GRAVITY * self.mass().0 * 0.5), + //Body::BirdMedium(_) => Some(GRAVITY * self.mass().0 * 2.0), + //Body::BirdLarge(_) => Some(GRAVITY * self.mass().0 * 0.5), + //Body::Dragon(_) => Some(200_000.0), + //Body::Ship(ship::Body::DefaultAirship) => Some(300_000.0), + Body::BirdMedium(_) => Some(GRAVITY * 0.5), + Body::BirdLarge(_) => Some(GRAVITY * 2.0), Body::Dragon(_) => Some(200_000.0), Body::Ship(ship::Body::DefaultAirship) => Some(300_000.0), _ => None, @@ -197,20 +202,21 @@ impl Body { /// Returns jump impulse if the body type can jump, otherwise None pub fn jump_impulse(&self) -> Option { - match self { - Body::Object(_) | Body::Ship(_) => None, - Body::BipedLarge(_) | Body::Dragon(_) | Body::Golem(_) | Body::QuadrupedLow(_) => { - Some(0.1 * self.mass().0) - }, - Body::QuadrupedMedium(_) => Some(0.4 * self.mass().0), - Body::Theropod(body) => match body.species { - theropod::Species::Snowraptor - | theropod::Species::Sandraptor - | theropod::Species::Woodraptor => Some(0.4 * self.mass().0), - _ => None, - }, - _ => Some(0.4 * self.mass().0), - } + Some(30.0) + //match self { + // Body::Object(_) | Body::Ship(_) => None, + // Body::BipedLarge(_) | Body::Dragon(_) | Body::Golem(_) | Body::QuadrupedLow(_) => { + // Some(0.1 * self.mass().0) + // }, + // Body::QuadrupedMedium(_) => Some(0.4 * self.mass().0), + // Body::Theropod(body) => match body.species { + // theropod::Species::Snowraptor + // | theropod::Species::Sandraptor + // | theropod::Species::Woodraptor => Some(0.4 * self.mass().0), + // _ => None, + // }, + // _ => Some(0.4 * self.mass().0), + //} .map(|f| f * GRAVITY) } diff --git a/common/systems/src/stats.rs b/common/systems/src/stats.rs index 4539978d62..38444bc68c 100644 --- a/common/systems/src/stats.rs +++ b/common/systems/src/stats.rs @@ -2,8 +2,8 @@ use common::{ comp::{ self, skills::{GeneralSkill, Skill}, - Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, Poise, - PoiseChange, PoiseSource, Pos, SkillSet, Stats, + CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, Poise, PoiseChange, + PoiseSource, Pos, SkillSet, Stats, }, event::{EventBus, ServerEvent}, outcome::Outcome, @@ -28,7 +28,6 @@ pub struct ReadData<'a> { server_bus: Read<'a, EventBus>, positions: ReadStorage<'a, Pos>, uids: ReadStorage<'a, Uid>, - bodies: ReadStorage<'a, Body>, char_states: ReadStorage<'a, CharacterState>, } @@ -112,13 +111,13 @@ impl<'a> System<'a> for Sys { } let stat = stats; - let update_max_hp = { + let update_max_health = { let health = health.get_unchecked(); (stat.max_health_modifier - 1.0).abs() > f32::EPSILON || health.base_max() != health.maximum() }; - if update_max_hp { + if update_max_health { let mut health = health.get_mut_unchecked(); health.scale_maximum(stat.max_health_modifier); } @@ -148,33 +147,32 @@ impl<'a> System<'a> for Sys { } // Apply effects from leveling skills - for (mut skill_set, mut health, mut energy, body) in ( - &mut skill_sets.restrict_mut(), - &mut healths.restrict_mut(), - &mut energies.restrict_mut(), - &read_data.bodies, - ) - .join() + for (entity, mut skill_set) in (&read_data.entities, &mut skill_sets.restrict_mut()).join() { let skillset = skill_set.get_unchecked(); if skillset.modify_health { - let mut health = health.get_mut_unchecked(); + //let mut health = health.get_mut_unchecked(); let health_level = skillset .skill_level(Skill::General(GeneralSkill::HealthIncrease)) .unwrap_or(None) .unwrap_or(0); - health.update_max_hp(Some(*body), health_level); + server_event_emitter.emit(ServerEvent::ModifyHealthLevel { + entity, + level: health_level, + }); let mut skillset = skill_set.get_mut_unchecked(); skillset.modify_health = false; } let skillset = skill_set.get_unchecked(); if skillset.modify_energy { - let mut energy = energy.get_mut_unchecked(); let energy_level = skillset .skill_level(Skill::General(GeneralSkill::EnergyIncrease)) .unwrap_or(None) .unwrap_or(0); - energy.update_max_energy(Some(*body), energy_level); + server_event_emitter.emit(ServerEvent::ModifyEnergyLevel { + entity, + level: energy_level, + }); let mut skill_set = skill_set.get_mut_unchecked(); skill_set.modify_energy = false; } diff --git a/server/src/cmd.rs b/server/src/cmd.rs index c5bf6f059f..fefe425924 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -1007,6 +1007,23 @@ fn handle_spawn( let body = body(); let loadout = LoadoutBuilder::build_loadout(body, None, None, None).build(); let inventory = Inventory::new_with_loadout(loadout); + let (base_health, base_health_increase) = { + let body_attributes = server + .state + .ecs() + .read_resource::(); + ( + body_attributes + .base_health + .as_ref() + .map_or(500, |bh| body.base_health(&bh)), + body_attributes + .base_health_increase + .as_ref() + .map_or(30, |bhi| body.base_health_increase(&bhi)), + ) + //(500, 30) + }; let mut entity_base = server .state @@ -1014,7 +1031,7 @@ fn handle_spawn( pos, comp::Stats::new(get_npc_name(id, npc::BodyType::from_body(body))), comp::SkillSet::default(), - comp::Health::new(body, 1), + comp::Health::new(base_health, base_health_increase, 1), comp::Poise::new(body), inventory, body, @@ -1107,7 +1124,24 @@ fn handle_spawn_training_dummy( let stats = comp::Stats::new("Training Dummy".to_string()); let skill_set = comp::SkillSet::default(); - let health = comp::Health::new(body, 0); + let (base_health, base_health_increase) = { + let body_attributes = server + .state + .ecs() + .read_resource::(); + ( + body_attributes + .base_health + .as_ref() + .map_or(500, |bh| body.base_health(&bh)), + body_attributes + .base_health_increase + .as_ref() + .map_or(30, |bhi| body.base_health_increase(&bhi)), + ) + //(500, 30) + }; + let health = comp::Health::new(base_health, base_health_increase, 0); let poise = comp::Poise::new(body); server diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 33fcc05826..fe1ab21a00 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -62,6 +62,40 @@ pub fn handle_damage(server: &Server, entity: EcsEntity, change: HealthChange) { } } +pub fn handle_update_health_level(server: &Server, entity: EcsEntity, level: u16) { + let ecs = &server.state.ecs(); + if let Some(body) = ecs.read_storage::().get(entity) { + let body_attributes = ecs.read_resource::(); + let base_health = body_attributes + .base_health + .as_ref() + .map_or(500, |bh| body.base_health(&bh)); + let base_health_increase = body_attributes + .base_health_increase + .as_ref() + .map_or(500, |bhi| body.base_health_increase(&bhi)); + + if let Some(mut health) = ecs.write_storage::().get_mut(entity) { + health.update_max_health(base_health, base_health_increase, level); + } + } +} + +pub fn handle_update_energy_level(server: &Server, entity: EcsEntity, level: u16) { + let ecs = &server.state.ecs(); + if let Some(body) = ecs.read_storage::().get(entity) { + let body_attributes = ecs.read_resource::(); + let base_energy = body_attributes + .base_energy + .as_ref() + .map_or(1000, |bh| body.base_energy(&bh)); + + if let Some(mut energy) = ecs.write_storage::().get_mut(entity) { + energy.update_max_energy(base_energy, level); + } + } +} + pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3) { let ecs = &server.state.ecs(); let clients = ecs.read_storage::(); diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index c808e8f28a..7303203dc4 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -8,7 +8,7 @@ use entity_creation::{ use entity_manipulation::{ handle_aura, handle_buff, handle_combo_change, handle_damage, handle_delete, handle_destroy, handle_energy_change, handle_explosion, handle_knockback, handle_land_on_ground, handle_poise, - handle_respawn, handle_teleport_to, + handle_respawn, handle_teleport_to, handle_update_energy_level, handle_update_health_level, }; use group_manip::handle_group; use information::handle_site_info; @@ -90,6 +90,12 @@ impl Server { handle_knockback(&self, entity, impulse) }, ServerEvent::Damage { entity, change } => handle_damage(&self, entity, change), + ServerEvent::ModifyHealthLevel { entity, level } => { + handle_update_health_level(&self, entity, level) + }, + ServerEvent::ModifyEnergyLevel { entity, level } => { + handle_update_energy_level(&self, entity, level) + }, ServerEvent::PoiseChange { entity, change, diff --git a/server/src/lib.rs b/server/src/lib.rs index 705f5178b5..54fab914a0 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -232,6 +232,9 @@ impl Server { let msm = comp::inventory::item::MaterialStatManifest::default(); state.ecs_mut().insert(msm); + let body_attributes = comp::body::BodyAttributes::load_expect_cloned(""); + state.ecs_mut().insert(body_attributes); + state.ecs_mut().insert(CharacterLoader::new( Arc::>::clone(&database_settings), )?); diff --git a/server/src/rtsim/tick.rs b/server/src/rtsim/tick.rs index c729445fa9..a3392dd7b6 100644 --- a/server/src/rtsim/tick.rs +++ b/server/src/rtsim/tick.rs @@ -2,7 +2,10 @@ use super::*; use common::{ - comp::{self, inventory::loadout_builder::LoadoutBuilder, Behavior, BehaviorCapability}, + comp::{ + self, body::BodyAttributes, inventory::loadout_builder::LoadoutBuilder, Behavior, + BehaviorCapability, + }, event::{EventBus, ServerEvent}, resources::{DeltaTime, Time}, terrain::TerrainGrid, @@ -21,6 +24,7 @@ impl<'a> System<'a> for Sys { Read<'a, Time>, Read<'a, DeltaTime>, Read<'a, EventBus>, + Read<'a, BodyAttributes>, WriteExpect<'a, RtSim>, ReadExpect<'a, TerrainGrid>, ReadExpect<'a, Arc>, @@ -40,6 +44,7 @@ impl<'a> System<'a> for Sys { time, dt, server_event_bus, + body_attributes, mut rtsim, terrain, world, @@ -103,17 +108,30 @@ impl<'a> System<'a> for Sys { .map(|e| e as f32) + Vec3::new(0.5, 0.5, body.flying_height()); let pos = comp::Pos(spawn_pos); + let aggro = body_attributes + .aggro + .as_ref() + .map_or(0.0, |ba| body.aggro(&ba)); let agent = Some(comp::Agent::new( None, - &body, if matches!(body, comp::Body::Humanoid(_)) { Behavior::from(BehaviorCapability::SPEAK) } else { Behavior::default() }, false, + aggro, )); + let base_health = body_attributes + .base_health + .as_ref() + .map_or(500, |bh| body.base_health(&bh)); + let base_health_increase = body_attributes + .base_health_increase + .as_ref() + .map_or(30, |bhi| body.base_health_increase(&bhi)); + let rtsim_entity = Some(RtSimEntity(id)); let event = match body { comp::Body::Ship(ship) => ServerEvent::CreateShip { @@ -127,7 +145,7 @@ impl<'a> System<'a> for Sys { pos: comp::Pos(spawn_pos), stats: comp::Stats::new(entity.get_name()), skill_set: comp::SkillSet::default(), - health: comp::Health::new(body, 10), + health: comp::Health::new(base_health, base_health_increase, 10), loadout: match body { comp::Body::Humanoid(_) => entity.get_loadout(), _ => LoadoutBuilder::new().build(), diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs index 0088b4ca92..72dad300d4 100644 --- a/server/src/state_ext.rs +++ b/server/src/state_ext.rs @@ -8,7 +8,7 @@ use common::{ comp::{ self, skills::{GeneralSkill, Skill}, - Group, Inventory, + Density, Group, Inventory, Mass, }, effect::Effect, resources::TimeOfDay, @@ -180,6 +180,24 @@ impl StateExt for State { inventory: comp::Inventory, body: comp::Body, ) -> EcsEntityBuilder { + let (mass, density, base_energy) = { + let body_attributes = &self.ecs().read_resource::(); + ( + body_attributes + .mass + .as_ref() + .map_or(Mass::default(), |bm| body.mass(&bm)), + body_attributes + .density + .as_ref() + .map_or(Density::default(), |bd| body.density(&bd)), + body_attributes + .base_energy + .as_ref() + .map_or(0, |be| body.base_energy(&be)), + ) + //(Mass::default(), Density::default(), 100) + }; self.ecs_mut() .create_entity_synced() .with(pos) @@ -192,8 +210,8 @@ impl StateExt for State { )) .unwrap_or_default(), ) - .with(body.mass()) - .with(body.density()) + .with(mass) + .with(density) .with(match body { comp::Body::Ship(ship) => comp::Collider::Voxel { id: ship.manifest_entry().to_string(), @@ -207,7 +225,7 @@ impl StateExt for State { .with(comp::Controller::default()) .with(body) .with(comp::Energy::new( - body, + base_energy, skill_set .skill_level(Skill::General(GeneralSkill::EnergyIncrease)) .unwrap_or(None) @@ -227,13 +245,27 @@ impl StateExt for State { fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder { let body = comp::Body::Object(object); + let (mass, density) = { + let body_attributes = &self.ecs().read_resource::(); + ( + body_attributes + .mass + .as_ref() + .map_or(Mass::default(), |bm| body.mass(&bm)), + body_attributes + .density + .as_ref() + .map_or(Density::default(), |bd| body.density(&bd)), + ) + //(Mass::default(), Density::default()) + }; self.ecs_mut() .create_entity_synced() .with(pos) .with(comp::Vel(Vec3::zero())) .with(comp::Ori::default()) - .with(body.mass()) - .with(body.density()) + .with(mass) + .with(density) .with(comp::Collider::Box { radius: body.radius(), z_min: 0.0, @@ -249,14 +281,32 @@ impl StateExt for State { mountable: bool, ) -> EcsEntityBuilder { let body = comp::Body::Ship(ship); + let (mass, density, base_energy) = { + let body_attributes = &self.ecs().read_resource::(); + ( + body_attributes + .mass + .as_ref() + .map_or(Mass::default(), |bm| body.mass(&bm)), + body_attributes + .density + .as_ref() + .map_or(Density::default(), |bd| body.density(&bd)), + body_attributes + .base_energy + .as_ref() + .map_or(0, |be| body.base_energy(&be)), + ) + //(Mass::default(), Density::default(), 100) + }; let mut builder = self .ecs_mut() .create_entity_synced() .with(pos) .with(comp::Vel(Vec3::zero())) .with(comp::Ori::default()) - .with(body.mass()) - .with(body.density()) + .with(mass) + .with(density) .with(comp::Collider::Voxel { id: ship.manifest_entry().to_string(), }) @@ -267,7 +317,7 @@ impl StateExt for State { .with(comp::CharacterState::default()) // TODO: some of these are required in order for the character_behavior system to // recognize a possesed airship; that system should be refactored to use `.maybe()` - .with(comp::Energy::new(ship.into(), 0)) + .with(comp::Energy::new(base_energy, 0)) .with(comp::Stats::new("Airship".to_string())) .with(comp::SkillSet::default()) .with(comp::Combo::default()); @@ -285,13 +335,27 @@ impl StateExt for State { body: comp::Body, projectile: comp::Projectile, ) -> EcsEntityBuilder { + let (mass, density) = { + let body_attributes = &self.ecs().read_resource::(); + ( + body_attributes + .mass + .as_ref() + .map_or(Mass::default(), |bm| body.mass(&bm)), + body_attributes + .density + .as_ref() + .map_or(Density::default(), |bd| body.density(&bd)), + ) + //(Mass::default(), Density::default()) + }; self.ecs_mut() .create_entity_synced() .with(pos) .with(vel) .with(comp::Ori::from_unnormalized_vec(vel.0).unwrap_or_default()) - .with(body.mass()) - .with(body.density()) + .with(mass) + .with(density) .with(comp::Collider::Point) .with(body) .with(projectile) @@ -470,6 +534,34 @@ impl StateExt for State { fn update_character_data(&mut self, entity: EcsEntity, components: PersistedComponents) { let (body, stats, skill_set, inventory, waypoint) = components; + let (mass, density, base_energy, base_health, base_health_increase) = { + let body_attributes = &self.ecs().read_resource::(); + ( + body_attributes + .mass + .as_ref() + .map_or(Mass::default(), |bm| body.mass(&bm)), + body_attributes + .density + .as_ref() + .map_or(Density::default(), |bd| body.density(&bd)), + // FIXME what should the default value be here? + body_attributes + .base_energy + .as_ref() + .map_or(0, |be| body.base_energy(&be)), + // FIXME what should the default value be here? + body_attributes + .base_health + .as_ref() + .map_or(500, |bh| body.base_health(&bh)), + body_attributes + .base_health_increase + .as_ref() + .map_or(30, |bhi| body.base_health_increase(&bhi)), + ) + //(Mass::default(), Density::default(), 100, 500, 30) + }; if let Some(player_uid) = self.read_component_copied::(entity) { // Notify clients of a player list update @@ -489,8 +581,8 @@ impl StateExt for State { z_max: body.height(), }); self.write_component_ignore_entity_dead(entity, body); - self.write_component_ignore_entity_dead(entity, body.mass()); - self.write_component_ignore_entity_dead(entity, body.density()); + self.write_component_ignore_entity_dead(entity, mass); + self.write_component_ignore_entity_dead(entity, density); let (health_level, energy_level) = ( skill_set .skill_level(Skill::General(GeneralSkill::HealthIncrease)) @@ -501,8 +593,14 @@ impl StateExt for State { .unwrap_or(None) .unwrap_or(0), ); - self.write_component_ignore_entity_dead(entity, comp::Health::new(body, health_level)); - self.write_component_ignore_entity_dead(entity, comp::Energy::new(body, energy_level)); + self.write_component_ignore_entity_dead( + entity, + comp::Health::new(base_health, base_health_increase, health_level), + ); + self.write_component_ignore_entity_dead( + entity, + comp::Energy::new(base_energy, energy_level), + ); self.write_component_ignore_entity_dead(entity, comp::Poise::new(body)); self.write_component_ignore_entity_dead(entity, stats); self.write_component_ignore_entity_dead(entity, skill_set); diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 07210fb3fa..f695c68943 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -590,6 +590,8 @@ impl<'a> AgentData<'a> { ) { decrement_awareness(agent); forget_old_sounds(agent, read_data); + let msg = format!("aggro: {}", agent.psyche.aggro); + event_emitter.emit(ServerEvent::Chat(UnresolvedChatMsg::npc(*self.uid, msg))); // Set owner if no target if agent.target.is_none() && thread_rng().gen_bool(0.1) { diff --git a/server/src/sys/terrain.rs b/server/src/sys/terrain.rs index b352de9438..03a1f00ec0 100644 --- a/server/src/sys/terrain.rs +++ b/server/src/sys/terrain.rs @@ -4,8 +4,8 @@ use crate::{ }; use common::{ comp::{ - self, bird_medium, inventory::loadout_builder::LoadoutConfig, Alignment, - BehaviorCapability, Pos, + self, bird_medium, body::BodyAttributes, inventory::loadout_builder::LoadoutConfig, + Alignment, BehaviorCapability, Pos, }, event::{EventBus, ServerEvent}, generation::get_npc_name, @@ -91,6 +91,7 @@ impl<'a> System<'a> for Sys { Read<'a, Tick>, Read<'a, SpawnPoint>, Read<'a, Settings>, + Read<'a, BodyAttributes>, ReadExpect<'a, NetworkRequestMetrics>, WriteExpect<'a, ChunkGenerator>, WriteExpect<'a, TerrainGrid>, @@ -112,6 +113,7 @@ impl<'a> System<'a> for Sys { tick, spawn_point, server_settings, + body_attributes, network_metrics, mut chunk_generator, mut terrain, @@ -207,7 +209,16 @@ impl<'a> System<'a> for Sys { let loadout = LoadoutBuilder::build_loadout(body, main_tool, loadout_config, economy).build(); - let health = comp::Health::new(body, entity.level.unwrap_or(0)); + let base_health = body_attributes + .base_health + .as_ref() + .map_or(500, |bh| body.base_health(&bh)); + let base_health_increase = body_attributes + .base_health_increase + .as_ref() + .map_or(30, |bhi| body.base_health_increase(&bhi)); + let health = + comp::Health::new(base_health, base_health_increase, entity.level.unwrap_or(0)); let poise = comp::Poise::new(body); let can_speak = match body { @@ -225,6 +236,11 @@ impl<'a> System<'a> for Sys { None }; + let aggro = body_attributes + .aggro + .as_ref() + .map_or(0.0, |ba| body.aggro(&ba)); + // TODO: This code sets an appropriate base_damage for the enemy. This doesn't // work because the damage is now saved in an ability /* @@ -244,7 +260,6 @@ impl<'a> System<'a> for Sys { agent: if entity.has_agency { Some(comp::Agent::new( Some(entity.pos), - &body, Behavior::default() .maybe_with_capabilities( can_speak.then(|| BehaviorCapability::SPEAK), @@ -254,6 +269,7 @@ impl<'a> System<'a> for Sys { loadout_config, Some(comp::inventory::loadout_builder::LoadoutConfig::Guard) ), + aggro, )) } else { None