mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Stunned and jump anims, stats, spawns, more IA work
This commit is contained in:
parent
f6d7ba33ef
commit
a6e396e29a
@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Interation hints now appear for sprites and entities
|
- Interation hints now appear for sprites and entities
|
||||||
- Players can now mount and ride pets
|
- Players can now mount and ride pets
|
||||||
- Experimental shaders, that can be enabled in Voxygen's settings (see the book for more information)
|
- Experimental shaders, that can be enabled in Voxygen's settings (see the book for more information)
|
||||||
|
- Added arthropods
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -229,6 +229,11 @@
|
|||||||
abilities: [],
|
abilities: [],
|
||||||
),
|
),
|
||||||
Custom("Arthropod Basic"): (
|
Custom("Arthropod Basic"): (
|
||||||
|
primary: "common.abilities.custom.arthropodbasic.singlestrike",
|
||||||
|
secondary: "common.abilities.custom.arthropodbasic.ensnaringweb",
|
||||||
|
abilities: [],
|
||||||
|
),
|
||||||
|
Custom("Arthropod Leap"): (
|
||||||
primary: "common.abilities.custom.arthropodbasic.singlestrike",
|
primary: "common.abilities.custom.arthropodbasic.singlestrike",
|
||||||
secondary: "common.abilities.custom.arthropodbasic.ensnaringweb",
|
secondary: "common.abilities.custom.arthropodbasic.ensnaringweb",
|
||||||
abilities: [
|
abilities: [
|
||||||
|
@ -4,12 +4,16 @@ LeapMelee(
|
|||||||
movement_duration: 0.4,
|
movement_duration: 0.4,
|
||||||
swing_duration: 0.075,
|
swing_duration: 0.075,
|
||||||
recover_duration: 0.2,
|
recover_duration: 0.2,
|
||||||
base_damage: 120,
|
melee_constructor: (
|
||||||
base_poise_damage: 60,
|
kind: Bash(
|
||||||
|
damage: 120.0,
|
||||||
|
poise: 60.0,
|
||||||
knockback: 4.0,
|
knockback: 4.0,
|
||||||
|
energy_regen: 0.0,
|
||||||
|
),
|
||||||
range: 4.5,
|
range: 4.5,
|
||||||
max_angle: 180.0,
|
angle: 180.0,
|
||||||
|
),
|
||||||
forward_leap_strength: 40.0,
|
forward_leap_strength: 40.0,
|
||||||
vertical_leap_strength: 10.0,
|
vertical_leap_strength: 10.0,
|
||||||
damage_kind: Crushing,
|
|
||||||
)
|
)
|
||||||
|
@ -2,9 +2,9 @@ ComboMelee(
|
|||||||
stage_data: [
|
stage_data: [
|
||||||
(
|
(
|
||||||
stage: 1,
|
stage: 1,
|
||||||
base_damage: 100,
|
base_damage: 40,
|
||||||
damage_increase: 0,
|
damage_increase: 0,
|
||||||
base_poise_damage: 28,
|
base_poise_damage: 15,
|
||||||
poise_damage_increase: 0,
|
poise_damage_increase: 0,
|
||||||
knockback: 3.0,
|
knockback: 3.0,
|
||||||
range: 3.0,
|
range: 3.0,
|
||||||
|
@ -1,13 +1,21 @@
|
|||||||
DashMelee(
|
DashMelee(
|
||||||
energy_cost: 0,
|
energy_cost: 0,
|
||||||
base_damage: 150,
|
melee_constructor: (
|
||||||
scaled_damage: 600,
|
kind: Stab(
|
||||||
base_poise_damage: 25,
|
damage: 12.0,
|
||||||
scaled_poise_damage: 100,
|
poise: 25.0,
|
||||||
base_knockback: 10.0,
|
knockback: 10.0,
|
||||||
scaled_knockback: 30.0,
|
energy_regen: 0.0,
|
||||||
|
),
|
||||||
|
scaled: Some(Stab(
|
||||||
|
damage: 50.0,
|
||||||
|
poise: 100.0,
|
||||||
|
knockback: 30.0,
|
||||||
|
energy_regen: 0.0,
|
||||||
|
)),
|
||||||
range: 5.0,
|
range: 5.0,
|
||||||
angle: 90.0,
|
angle: 90.0,
|
||||||
|
),
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
forward_speed: 5.0,
|
forward_speed: 5.0,
|
||||||
buildup_duration: 0.3,
|
buildup_duration: 0.3,
|
||||||
@ -17,11 +25,4 @@ DashMelee(
|
|||||||
ori_modifier: 0.3,
|
ori_modifier: 0.3,
|
||||||
charge_through: false,
|
charge_through: false,
|
||||||
is_interruptible: false,
|
is_interruptible: false,
|
||||||
damage_kind: Piercing,
|
|
||||||
damage_effect: Some(Buff((
|
|
||||||
kind: Bleeding,
|
|
||||||
dur_secs: 10.0,
|
|
||||||
strength: DamageFraction(0.1),
|
|
||||||
chance: 0.1,
|
|
||||||
))),
|
|
||||||
)
|
)
|
||||||
|
@ -2,12 +2,12 @@ ComboMelee(
|
|||||||
stage_data: [
|
stage_data: [
|
||||||
(
|
(
|
||||||
stage: 1,
|
stage: 1,
|
||||||
base_damage: 100,
|
base_damage: 70,
|
||||||
damage_increase: 0,
|
damage_increase: 0,
|
||||||
base_poise_damage: 28,
|
base_poise_damage: 28,
|
||||||
poise_damage_increase: 0,
|
poise_damage_increase: 0,
|
||||||
knockback: 3.0,
|
knockback: 3.0,
|
||||||
range: 2.7,
|
range: 3.0,
|
||||||
angle: 60.0,
|
angle: 60.0,
|
||||||
base_buildup_duration: 0.4,
|
base_buildup_duration: 0.4,
|
||||||
base_swing_duration: 0.1,
|
base_swing_duration: 0.1,
|
||||||
|
@ -2,7 +2,7 @@ ComboMelee(
|
|||||||
stage_data: [
|
stage_data: [
|
||||||
(
|
(
|
||||||
stage: 1,
|
stage: 1,
|
||||||
base_damage: 100,
|
base_damage: 60,
|
||||||
damage_increase: 0,
|
damage_increase: 0,
|
||||||
base_poise_damage: 28,
|
base_poise_damage: 28,
|
||||||
poise_damage_increase: 0,
|
poise_damage_increase: 0,
|
||||||
|
@ -3,7 +3,7 @@ EntityConfig (
|
|||||||
body: RandomWith("antlion"),
|
body: RandomWith("antlion"),
|
||||||
alignment: Alignment(Enemy),
|
alignment: Alignment(Enemy),
|
||||||
|
|
||||||
loot: LootTable("common.loot_tables.creature.arthropod.web"),
|
loot: LootTable("common.loot_tables.creature.arthropod.carapace"),
|
||||||
|
|
||||||
hands: Uninit,
|
hands: Uninit,
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
EntityConfig (
|
EntityConfig (
|
||||||
name: Automatic,
|
name: Automatic,
|
||||||
body: RandomWith("black_window"),
|
body: RandomWith("black_widow"),
|
||||||
alignment: Alignment(Enemy),
|
alignment: Alignment(Enemy),
|
||||||
|
|
||||||
loot: LootTable("common.loot_tables.creature.arthropod.web"),
|
loot: LootTable("common.loot_tables.creature.arthropod.venom"),
|
||||||
|
|
||||||
hands: Uninit,
|
hands: Uninit,
|
||||||
|
|
||||||
|
11
assets/common/entity/wild/aggressive/cave_spider.ron
Normal file
11
assets/common/entity/wild/aggressive/cave_spider.ron
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
EntityConfig (
|
||||||
|
name: Automatic,
|
||||||
|
body: RandomWith("cave_spider"),
|
||||||
|
alignment: Alignment(Enemy),
|
||||||
|
|
||||||
|
loot: LootTable("common.loot_tables.creature.arthropod.web"),
|
||||||
|
|
||||||
|
hands: Uninit,
|
||||||
|
|
||||||
|
meta: [],
|
||||||
|
)
|
11
assets/common/entity/wild/aggressive/weevil.ron
Normal file
11
assets/common/entity/wild/aggressive/weevil.ron
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
EntityConfig (
|
||||||
|
name: Automatic,
|
||||||
|
body: RandomWith("weevil"),
|
||||||
|
alignment: Alignment(Enemy),
|
||||||
|
|
||||||
|
loot: LootTable("common.loot_tables.creature.arthropod.leaf"),
|
||||||
|
|
||||||
|
hands: Uninit,
|
||||||
|
|
||||||
|
meta: [],
|
||||||
|
)
|
11
assets/common/entity/wild/peaceful/crawler_molten.ron
Normal file
11
assets/common/entity/wild/peaceful/crawler_molten.ron
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
EntityConfig (
|
||||||
|
name: Automatic,
|
||||||
|
body: RandomWith("crawler_molten"),
|
||||||
|
alignment: Alignment(Wild),
|
||||||
|
|
||||||
|
loot: LootTable("common.loot_tables.creature.arthropod.ooze"),
|
||||||
|
|
||||||
|
hands: Uninit,
|
||||||
|
|
||||||
|
meta: [],
|
||||||
|
)
|
11
assets/common/entity/wild/peaceful/crawler_moss.ron
Normal file
11
assets/common/entity/wild/peaceful/crawler_moss.ron
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
EntityConfig (
|
||||||
|
name: Automatic,
|
||||||
|
body: RandomWith("crawler_moss"),
|
||||||
|
alignment: Alignment(Wild),
|
||||||
|
|
||||||
|
loot: LootTable("common.loot_tables.creature.arthropod.ooze"),
|
||||||
|
|
||||||
|
hands: Uninit,
|
||||||
|
|
||||||
|
meta: [],
|
||||||
|
)
|
11
assets/common/entity/wild/peaceful/crawler_sand.ron
Normal file
11
assets/common/entity/wild/peaceful/crawler_sand.ron
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
EntityConfig (
|
||||||
|
name: Automatic,
|
||||||
|
body: RandomWith("crawler_sand"),
|
||||||
|
alignment: Alignment(Wild),
|
||||||
|
|
||||||
|
loot: LootTable("common.loot_tables.creature.arthropod.ooze"),
|
||||||
|
|
||||||
|
hands: Uninit,
|
||||||
|
|
||||||
|
meta: [],
|
||||||
|
)
|
21
assets/common/items/npc_weapons/unique/arthropodleap.ron
Normal file
21
assets/common/items/npc_weapons/unique/arthropodleap.ron
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
ItemDef(
|
||||||
|
name: "Arthropod Leap",
|
||||||
|
description: "testing123",
|
||||||
|
kind: Tool((
|
||||||
|
kind: Natural,
|
||||||
|
hands: Two,
|
||||||
|
stats: Direct((
|
||||||
|
equip_time_secs: 0.01,
|
||||||
|
power: 1.0,
|
||||||
|
effect_power: 1.0,
|
||||||
|
speed: 1.0,
|
||||||
|
crit_chance: 0.1,
|
||||||
|
range: 1.0,
|
||||||
|
energy_efficiency: 1.0,
|
||||||
|
buff_strength: 1.0,
|
||||||
|
)),
|
||||||
|
)),
|
||||||
|
quality: Low,
|
||||||
|
tags: [],
|
||||||
|
ability_spec: Some(Custom("Arthropod Leap")),
|
||||||
|
)
|
@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
(1.0, ItemQuantity("common.items.crafting_ing.twigs", 1, 3)),
|
|
||||||
(1.0, ItemQuantity("common.items.flowers.plant_fiber", 1, 3)),
|
(1.0, ItemQuantity("common.items.flowers.plant_fiber", 1, 3)),
|
||||||
|
(0.5, ItemQuantity("common.items.crafting_ing.twigs", 1, 3)),
|
||||||
|
(0.5, ItemQuantity("common.items.crafting_ing.animal_misc.viscous_ooze", 1, 1)),
|
||||||
]
|
]
|
4
assets/common/loot_tables/creature/arthropod/ooze.ron
Normal file
4
assets/common/loot_tables/creature/arthropod/ooze.ron
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
(1.0, ItemQuantity("common.items.crafting_ing.sticky_thread", 1, 3)),
|
||||||
|
(0.5, ItemQuantity("common.items.crafting_ing.animal_misc.viscous_ooze", 1, 1)),
|
||||||
|
]
|
4
assets/common/loot_tables/creature/arthropod/venom.ron
Normal file
4
assets/common/loot_tables/creature/arthropod/venom.ron
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
(1.0, ItemQuantity("common.items.crafting_ing.sticky_thread", 1, 3)),
|
||||||
|
(0.5, ItemQuantity("common.items.crafting_ing.animal_misc.venom_sac", 1, 1)),
|
||||||
|
]
|
@ -1,3 +1,3 @@
|
|||||||
[
|
[
|
||||||
(1.0, ItemQuantity("common.items.crafting_ing.cloth.silk", 1, 3)),
|
(1.0, ItemQuantity("common.items.crafting_ing.sticky_thread", 1, 3)),
|
||||||
]
|
]
|
@ -1230,15 +1230,15 @@
|
|||||||
),
|
),
|
||||||
horn_beetle: (
|
horn_beetle: (
|
||||||
keyword: "horn_beetle",
|
keyword: "horn_beetle",
|
||||||
generic: "Hornbeetle"
|
generic: "Horn Beetle"
|
||||||
),
|
),
|
||||||
leaf_beetle: (
|
leaf_beetle: (
|
||||||
keyword: "leaf_beetle",
|
keyword: "leaf_beetle",
|
||||||
generic: "Leafbeetle"
|
generic: "Leaf Beetle"
|
||||||
),
|
),
|
||||||
stag_beetle: (
|
stag_beetle: (
|
||||||
keyword: "stag_beetle",
|
keyword: "stag_beetle",
|
||||||
generic: "Stagbeetle"
|
generic: "Stag Beetle"
|
||||||
),
|
),
|
||||||
weevil: (
|
weevil: (
|
||||||
keyword: "weevil",
|
keyword: "weevil",
|
||||||
@ -1258,7 +1258,7 @@
|
|||||||
),
|
),
|
||||||
crawler_sand: (
|
crawler_sand: (
|
||||||
keyword: "crawler_sand",
|
keyword: "crawler_sand",
|
||||||
generic: "Molten Crawler"
|
generic: "Sand Crawler"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
BIN
assets/voxygen/element/de_buffs/debuff_poisoned_0.png
(Stored with Git LFS)
BIN
assets/voxygen/element/de_buffs/debuff_poisoned_0.png
(Stored with Git LFS)
Binary file not shown.
@ -4,10 +4,13 @@ SpawnEntry (
|
|||||||
rules: [
|
rules: [
|
||||||
Pack(
|
Pack(
|
||||||
groups: [
|
groups: [
|
||||||
(1, (1, 1, "common.entity.wild.peaceful.camel")),
|
// Casual
|
||||||
(1, (1, 1, "common.entity.wild.peaceful.sand_hare")),
|
(2, (1, 1, "common.entity.wild.peaceful.camel")),
|
||||||
(1, (1, 1, "common.entity.wild.peaceful.sand_salamander")),
|
(2, (1, 1, "common.entity.wild.peaceful.sand_hare")),
|
||||||
(1, (1, 1, "common.entity.wild.peaceful.gecko")),
|
(2, (1, 1, "common.entity.wild.peaceful.sand_salamander")),
|
||||||
|
(2, (1, 1, "common.entity.wild.peaceful.gecko")),
|
||||||
|
// Rare
|
||||||
|
(1, (1, 1, "common.entity.wild.peaceful.crawler_sand")),
|
||||||
],
|
],
|
||||||
is_underwater: false,
|
is_underwater: false,
|
||||||
day_period: [Morning, Noon, Evening],
|
day_period: [Morning, Noon, Evening],
|
||||||
|
@ -8,12 +8,13 @@ SpawnEntry (
|
|||||||
(110, (1, 1, "common.entity.wild.aggressive.bonerattler")),
|
(110, (1, 1, "common.entity.wild.aggressive.bonerattler")),
|
||||||
(100, (1, 1, "common.entity.wild.aggressive.sand_raptor")),
|
(100, (1, 1, "common.entity.wild.aggressive.sand_raptor")),
|
||||||
(100, (1, 1, "common.entity.wild.aggressive.sandshark")),
|
(100, (1, 1, "common.entity.wild.aggressive.sandshark")),
|
||||||
(100, (1, 1, "common.entity.wild.aggressive.stag_beetle")),
|
(100, (1, 1, "common.entity.wild.aggressive.antlion")),
|
||||||
// Rare
|
// Rare
|
||||||
(20, (1, 1, "common.entity.wild.aggressive.lavadrake")),
|
(20, (1, 1, "common.entity.wild.aggressive.lavadrake")),
|
||||||
(20, (1, 1, "common.entity.wild.aggressive.ntouka")),
|
(20, (1, 1, "common.entity.wild.aggressive.ntouka")),
|
||||||
(20, (1, 1, "common.entity.wild.aggressive.archaeos")),
|
(20, (1, 1, "common.entity.wild.aggressive.archaeos")),
|
||||||
(20, (1, 1, "common.entity.wild.aggressive.ngoubou")),
|
(20, (1, 1, "common.entity.wild.aggressive.ngoubou")),
|
||||||
|
(20, (1, 1, "common.entity.wild.aggressive.tarantula")),
|
||||||
// Ultra_rare
|
// Ultra_rare
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.roshwalr_boss")),
|
(1, (1, 1, "common.entity.wild.aggressive.roshwalr_boss")),
|
||||||
],
|
],
|
||||||
|
@ -10,6 +10,9 @@ SpawnEntry (
|
|||||||
// Rare
|
// Rare
|
||||||
(1, (1, 1, "common.entity.wild.peaceful.tortoise")),
|
(1, (1, 1, "common.entity.wild.peaceful.tortoise")),
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.monitor")),
|
(1, (1, 1, "common.entity.wild.aggressive.monitor")),
|
||||||
|
(1, (1, 1, "common.entity.wild.aggressive.horn_beetle")),
|
||||||
|
(1, (1, 1, "common.entity.wild.aggressive.stag_beetle")),
|
||||||
|
(1, (1, 1, "common.entity.wild.peaceful.crawler_moss")),
|
||||||
],
|
],
|
||||||
is_underwater: false,
|
is_underwater: false,
|
||||||
day_period: [Morning, Noon, Evening],
|
day_period: [Morning, Noon, Evening],
|
||||||
|
@ -6,7 +6,6 @@ SpawnEntry (
|
|||||||
groups: [
|
groups: [
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.wendigo")),
|
(1, (1, 1, "common.entity.wild.aggressive.wendigo")),
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.dreadhorn")),
|
(1, (1, 1, "common.entity.wild.aggressive.dreadhorn")),
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.horn_beetle")),
|
|
||||||
],
|
],
|
||||||
is_underwater: false,
|
is_underwater: false,
|
||||||
day_period: [Night, Morning, Noon, Evening],
|
day_period: [Night, Morning, Noon, Evening],
|
||||||
|
@ -9,6 +9,7 @@ SpawnEntry (
|
|||||||
(1, (1, 1, "common.entity.wild.aggressive.wood_raptor")),
|
(1, (1, 1, "common.entity.wild.aggressive.wood_raptor")),
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.deadwood")),
|
(1, (1, 1, "common.entity.wild.aggressive.deadwood")),
|
||||||
(1, (1, 1, "common.entity.wild.aggressive.saber")),
|
(1, (1, 1, "common.entity.wild.aggressive.saber")),
|
||||||
|
(1, (1, 1, "common.entity.wild.aggressive.weevil")),
|
||||||
],
|
],
|
||||||
is_underwater: false,
|
is_underwater: false,
|
||||||
day_period: [Night, Morning, Noon, Evening],
|
day_period: [Night, Morning, Noon, Evening],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
biped_small, bird_medium, humanoid, quadruped_low, quadruped_medium, quadruped_small, ship,
|
arthropod, biped_small, bird_medium, humanoid, quadruped_low, quadruped_medium,
|
||||||
Body, UtteranceKind,
|
quadruped_small, ship, Body, UtteranceKind,
|
||||||
},
|
},
|
||||||
path::Chaser,
|
path::Chaser,
|
||||||
rtsim::{Memory, MemoryItem, RtSimController, RtSimEvent},
|
rtsim::{Memory, MemoryItem, RtSimController, RtSimEvent},
|
||||||
@ -267,7 +267,19 @@ impl<'a> From<&'a Body> for Psyche {
|
|||||||
Body::Theropod(_) => 0.0,
|
Body::Theropod(_) => 0.0,
|
||||||
Body::Ship(_) => 0.0,
|
Body::Ship(_) => 0.0,
|
||||||
Body::Dragon(_) => 0.0,
|
Body::Dragon(_) => 0.0,
|
||||||
Body::Arthropod(_) => 1.0,
|
Body::Arthropod(arthropod) => match arthropod.species {
|
||||||
|
arthropod::Species::Tarantula => 0.0,
|
||||||
|
arthropod::Species::Blackwidow => 0.0,
|
||||||
|
arthropod::Species::Antlion => 0.0,
|
||||||
|
arthropod::Species::Hornbeetle => 0.1,
|
||||||
|
arthropod::Species::Leafbeetle => 0.1,
|
||||||
|
arthropod::Species::Stagbeetle => 0.1,
|
||||||
|
arthropod::Species::Weevil => 0.0,
|
||||||
|
arthropod::Species::Cavespider => 0.0,
|
||||||
|
arthropod::Species::Moltencrawler => 0.2,
|
||||||
|
arthropod::Species::Mosscrawler => 0.2,
|
||||||
|
arthropod::Species::Sandcrawler => 0.2,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
sight_dist: 40.0,
|
sight_dist: 40.0,
|
||||||
listen_dist: 30.0,
|
listen_dist: 30.0,
|
||||||
|
@ -406,14 +406,14 @@ impl Body {
|
|||||||
arthropod::Species::Tarantula => Vec3::new(4.0, 4.0, 1.8),
|
arthropod::Species::Tarantula => Vec3::new(4.0, 4.0, 1.8),
|
||||||
arthropod::Species::Blackwidow => Vec3::new(4.0, 4.0, 2.0),
|
arthropod::Species::Blackwidow => Vec3::new(4.0, 4.0, 2.0),
|
||||||
arthropod::Species::Antlion => Vec3::new(4.0, 4.0, 2.2),
|
arthropod::Species::Antlion => Vec3::new(4.0, 4.0, 2.2),
|
||||||
arthropod::Species::Hornbeetle => Vec3::new(4.0, 4.0, 1.6),
|
arthropod::Species::Hornbeetle => Vec3::new(3.2, 3.2, 1.3),
|
||||||
arthropod::Species::Leafbeetle => Vec3::new(4.0, 4.0, 1.6),
|
arthropod::Species::Leafbeetle => Vec3::new(3.2, 3.2, 1.3),
|
||||||
arthropod::Species::Stagbeetle => Vec3::new(4.0, 4.0, 1.6),
|
arthropod::Species::Stagbeetle => Vec3::new(3.2, 3.2, 1.3),
|
||||||
arthropod::Species::Weevil => Vec3::new(4.0, 4.0, 1.6),
|
arthropod::Species::Weevil => Vec3::new(3.2, 3.2, 1.6),
|
||||||
arthropod::Species::Cavespider => Vec3::new(4.0, 4.0, 1.8),
|
arthropod::Species::Cavespider => Vec3::new(4.0, 4.0, 1.4),
|
||||||
arthropod::Species::Moltencrawler => Vec3::new(4.0, 5.0, 1.9),
|
arthropod::Species::Moltencrawler => Vec3::new(3.2, 4.0, 1.5),
|
||||||
arthropod::Species::Mosscrawler => Vec3::new(4.0, 5.0, 1.8),
|
arthropod::Species::Mosscrawler => Vec3::new(3.2, 4.0, 1.4),
|
||||||
arthropod::Species::Sandcrawler => Vec3::new(4.0, 5.0, 1.8),
|
arthropod::Species::Sandcrawler => Vec3::new(3.2, 4.0, 1.4),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -659,7 +659,20 @@ impl Body {
|
|||||||
quadruped_low::Species::Deadwood => 120,
|
quadruped_low::Species::Deadwood => 120,
|
||||||
_ => 70,
|
_ => 70,
|
||||||
},
|
},
|
||||||
Body::Arthropod(_) => 10000,
|
Body::Arthropod(arthropod) => match arthropod.species {
|
||||||
|
arthropod::Species::Tarantula => 120,
|
||||||
|
arthropod::Species::Blackwidow => 120,
|
||||||
|
arthropod::Species::Antlion => 80,
|
||||||
|
arthropod::Species::Hornbeetle => 90,
|
||||||
|
arthropod::Species::Leafbeetle => 90,
|
||||||
|
arthropod::Species::Stagbeetle => 90,
|
||||||
|
arthropod::Species::Weevil => 80,
|
||||||
|
arthropod::Species::Cavespider => 60,
|
||||||
|
arthropod::Species::Moltencrawler => 80,
|
||||||
|
arthropod::Species::Mosscrawler => 80,
|
||||||
|
arthropod::Species::Sandcrawler => 80,
|
||||||
|
_ => 70,
|
||||||
|
},
|
||||||
Body::Ship(_) => 1000,
|
Body::Ship(_) => 1000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -688,6 +701,7 @@ impl Body {
|
|||||||
| bird_large::Species::Cockatrice
|
| bird_large::Species::Cockatrice
|
||||||
| bird_large::Species::FlameWyvern
|
| bird_large::Species::FlameWyvern
|
||||||
),
|
),
|
||||||
|
Body::Arthropod(b) => matches!(b.species, arthropod::Species::Moltencrawler),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
BuffKind::Ensnared => match self {
|
BuffKind::Ensnared => match self {
|
||||||
|
@ -314,7 +314,11 @@ impl Body {
|
|||||||
Body::BedBlue => 50.0,
|
Body::BedBlue => 50.0,
|
||||||
Body::Bedroll => 3.0,
|
Body::Bedroll => 3.0,
|
||||||
Body::Bench => 100.0,
|
Body::Bench => 100.0,
|
||||||
Body::BoltFire | Body::BoltFireBig | Body::BoltNature | Body::BoltIcicle | Body::SpitPoison => 1.0,
|
Body::BoltFire
|
||||||
|
| Body::BoltFireBig
|
||||||
|
| Body::BoltNature
|
||||||
|
| Body::BoltIcicle
|
||||||
|
| Body::SpitPoison => 1.0,
|
||||||
Body::Bomb => {
|
Body::Bomb => {
|
||||||
0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3)
|
0.5 * IRON_DENSITY * std::f32::consts::PI / 6.0 * self.dimensions().x.powi(3)
|
||||||
},
|
},
|
||||||
|
@ -74,8 +74,8 @@ pub enum BuffKind {
|
|||||||
/// Strength scales the movement speed debuff non-linearly. 0.5 is 50%
|
/// Strength scales the movement speed debuff non-linearly. 0.5 is 50%
|
||||||
/// speed, 1.0 is 33% speed.
|
/// speed, 1.0 is 33% speed.
|
||||||
Ensnared,
|
Ensnared,
|
||||||
/// Does damage to a creature over time
|
/// Drain stamina to a creature over time
|
||||||
/// Strength should be 10x the DPS of the debuff
|
/// Strength should be the energy per second of the debuff
|
||||||
Poisoned,
|
Poisoned,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,9 +271,12 @@ fn default_main_tool(body: &Body) -> Item {
|
|||||||
| arthropod::Species::Antlion => Some(Item::new_from_asset_expect(
|
| arthropod::Species::Antlion => Some(Item::new_from_asset_expect(
|
||||||
"common.items.npc_weapons.unique.arthropodcharge",
|
"common.items.npc_weapons.unique.arthropodcharge",
|
||||||
)),
|
)),
|
||||||
arthropod::Species::Cavespider => Some(Item::new_from_asset_expect(
|
arthropod::Species::Cavespider | arthropod::Species::Blackwidow => Some(
|
||||||
"common.items.npc_weapons.unique.arthropodranged",
|
Item::new_from_asset_expect("common.items.npc_weapons.unique.arthropodranged"),
|
||||||
)),
|
),
|
||||||
|
arthropod::Species::Weevil | arthropod::Species::Tarantula => Some(
|
||||||
|
Item::new_from_asset_expect("common.items.npc_weapons.unique.arthropodleap"),
|
||||||
|
),
|
||||||
_ => Some(Item::new_from_asset_expect(
|
_ => Some(Item::new_from_asset_expect(
|
||||||
"common.items.npc_weapons.unique.arthropodbasic",
|
"common.items.npc_weapons.unique.arthropodbasic",
|
||||||
)),
|
)),
|
||||||
|
@ -236,7 +236,7 @@ impl ProjectileConstructor {
|
|||||||
let buff = AttackEffect::new(
|
let buff = AttackEffect::new(
|
||||||
Some(GroupTarget::OutOfGroup),
|
Some(GroupTarget::OutOfGroup),
|
||||||
CombatEffect::Buff(CombatBuff {
|
CombatEffect::Buff(CombatBuff {
|
||||||
kind: BuffKind::Burning,
|
kind: BuffKind::Poisoned,
|
||||||
dur_secs: 5.0,
|
dur_secs: 5.0,
|
||||||
strength: CombatBuffStrength::DamageFraction(0.2 * buff_strength),
|
strength: CombatBuffStrength::DamageFraction(0.2 * buff_strength),
|
||||||
chance: 1.0,
|
chance: 1.0,
|
||||||
|
@ -7,7 +7,8 @@ use common::{
|
|||||||
Buffs,
|
Buffs,
|
||||||
},
|
},
|
||||||
fluid_dynamics::{Fluid, LiquidKind},
|
fluid_dynamics::{Fluid, LiquidKind},
|
||||||
Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState, Stats,
|
Energy, Group, Health, HealthChange, Inventory, LightEmitter, ModifierKind, PhysicsState,
|
||||||
|
Stats,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
resources::{DeltaTime, Time},
|
resources::{DeltaTime, Time},
|
||||||
@ -30,6 +31,7 @@ pub struct ReadData<'a> {
|
|||||||
server_bus: Read<'a, EventBus<ServerEvent>>,
|
server_bus: Read<'a, EventBus<ServerEvent>>,
|
||||||
inventories: ReadStorage<'a, Inventory>,
|
inventories: ReadStorage<'a, Inventory>,
|
||||||
healths: ReadStorage<'a, Health>,
|
healths: ReadStorage<'a, Health>,
|
||||||
|
energies: ReadStorage<'a, Energy>,
|
||||||
physics_states: ReadStorage<'a, PhysicsState>,
|
physics_states: ReadStorage<'a, PhysicsState>,
|
||||||
groups: ReadStorage<'a, Group>,
|
groups: ReadStorage<'a, Group>,
|
||||||
uid_allocator: Read<'a, UidAllocator>,
|
uid_allocator: Read<'a, UidAllocator>,
|
||||||
@ -79,11 +81,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
light_emitters.remove(entity);
|
light_emitters.remove(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (entity, mut buff_comp, mut stat, health, physics_state) in (
|
for (entity, mut buff_comp, mut stat, health, energy, physics_state) in (
|
||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
&mut buffs,
|
&mut buffs,
|
||||||
&mut stats,
|
&mut stats,
|
||||||
&read_data.healths,
|
&read_data.healths,
|
||||||
|
&read_data.energies,
|
||||||
read_data.physics_states.maybe(),
|
read_data.physics_states.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
@ -251,7 +254,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let amount = match *kind {
|
let amount = match *kind {
|
||||||
ModifierKind::Additive => *accumulated,
|
ModifierKind::Additive => *accumulated,
|
||||||
ModifierKind::Fractional => {
|
ModifierKind::Fractional => {
|
||||||
health.maximum() as f32 * *accumulated
|
energy.maximum() as f32 * *accumulated
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
server_emitter.emit(ServerEvent::EnergyChange {
|
server_emitter.emit(ServerEvent::EnergyChange {
|
||||||
|
@ -1694,6 +1694,8 @@ impl<'a> AgentData<'a> {
|
|||||||
"Theropod Basic" | "Theropod Bird" => Tactic::Theropod,
|
"Theropod Basic" | "Theropod Bird" => Tactic::Theropod,
|
||||||
"Arthropod Basic" => Tactic::ArthropodBasic,
|
"Arthropod Basic" => Tactic::ArthropodBasic,
|
||||||
"Arthropod Charge" => Tactic::ArthropodCharge,
|
"Arthropod Charge" => Tactic::ArthropodCharge,
|
||||||
|
"Arthropod Ranged" => Tactic::ArthropodRanged,
|
||||||
|
"Arthropod Leap" => Tactic::ArthropodLeap,
|
||||||
"Theropod Charge" => Tactic::CircleCharge {
|
"Theropod Charge" => Tactic::CircleCharge {
|
||||||
radius: 6,
|
radius: 6,
|
||||||
circle_time: 1,
|
circle_time: 1,
|
||||||
@ -1984,6 +1986,21 @@ impl<'a> AgentData<'a> {
|
|||||||
tgt_data,
|
tgt_data,
|
||||||
read_data,
|
read_data,
|
||||||
),
|
),
|
||||||
|
Tactic::ArthropodLeap => self.handle_arthropod_leap_attack(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
&attack_data,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
rng,
|
||||||
|
),
|
||||||
|
Tactic::ArthropodRanged => self.handle_arthropod_ranged_attack(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
&attack_data,
|
||||||
|
tgt_data,
|
||||||
|
read_data,
|
||||||
|
),
|
||||||
Tactic::Turret => {
|
Tactic::Turret => {
|
||||||
self.handle_turret_attack(agent, controller, &attack_data, tgt_data, read_data)
|
self.handle_turret_attack(agent, controller, &attack_data, tgt_data, read_data)
|
||||||
},
|
},
|
||||||
|
@ -1681,13 +1681,135 @@ impl<'a> AgentData<'a> {
|
|||||||
self.path_toward_target(agent, controller, tgt_data, read_data, true, false, None);
|
self.path_toward_target(agent, controller, tgt_data, read_data, true, false, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_arthropod_basic_attack(
|
pub fn handle_arthropod_basic_attack(
|
||||||
&self,
|
&self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
controller: &mut Controller,
|
controller: &mut Controller,
|
||||||
attack_data: &AttackData,
|
attack_data: &AttackData,
|
||||||
tgt_data: &TargetData,
|
tgt_data: &TargetData,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
|
) {
|
||||||
|
agent.action_state.timer += read_data.dt.0;
|
||||||
|
if agent.action_state.timer > 7.0
|
||||||
|
&& attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2)
|
||||||
|
{
|
||||||
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
|
// Reset timer
|
||||||
|
if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover))
|
||||||
|
{
|
||||||
|
agent.action_state.timer = 0.0;
|
||||||
|
}
|
||||||
|
} else if attack_data.angle < 90.0
|
||||||
|
&& attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2)
|
||||||
|
{
|
||||||
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Primary));
|
||||||
|
} else {
|
||||||
|
self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_arthropod_ranged_attack(
|
||||||
|
&self,
|
||||||
|
agent: &mut Agent,
|
||||||
|
controller: &mut Controller,
|
||||||
|
attack_data: &AttackData,
|
||||||
|
tgt_data: &TargetData,
|
||||||
|
read_data: &ReadData,
|
||||||
|
) {
|
||||||
|
agent.action_state.timer += read_data.dt.0;
|
||||||
|
if agent.action_state.timer > 6.0
|
||||||
|
&& attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2)
|
||||||
|
{
|
||||||
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
|
// Reset timer
|
||||||
|
if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover))
|
||||||
|
{
|
||||||
|
agent.action_state.timer = 0.0;
|
||||||
|
}
|
||||||
|
} else if attack_data.dist_sqrd < (3.0 * attack_data.min_attack_dist).powi(2)
|
||||||
|
&& attack_data.angle < 90.0
|
||||||
|
{
|
||||||
|
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
|
||||||
|
.xy()
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec2::unit_y);
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Primary));
|
||||||
|
} else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) {
|
||||||
|
if let Some((bearing, speed)) = agent.chaser.chase(
|
||||||
|
&*read_data.terrain,
|
||||||
|
self.pos.0,
|
||||||
|
self.vel.0,
|
||||||
|
tgt_data.pos.0,
|
||||||
|
TraversalConfig {
|
||||||
|
min_tgt_dist: 1.25,
|
||||||
|
..self.traversal_config
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
if attack_data.angle < 15.0
|
||||||
|
&& can_see_tgt(
|
||||||
|
&*read_data.terrain,
|
||||||
|
self.pos,
|
||||||
|
tgt_data.pos,
|
||||||
|
attack_data.dist_sqrd,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if agent.action_state.timer > 5.0 {
|
||||||
|
agent.action_state.timer = 0.0;
|
||||||
|
} else if agent.action_state.timer > 2.5 {
|
||||||
|
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
|
||||||
|
.xy()
|
||||||
|
.rotated_z(1.75 * PI)
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec2::zero)
|
||||||
|
* speed;
|
||||||
|
agent.action_state.timer += read_data.dt.0;
|
||||||
|
} else {
|
||||||
|
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
|
||||||
|
.xy()
|
||||||
|
.rotated_z(0.25 * PI)
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_else(Vec2::zero)
|
||||||
|
* speed;
|
||||||
|
agent.action_state.timer += read_data.dt.0;
|
||||||
|
}
|
||||||
|
controller
|
||||||
|
.actions
|
||||||
|
.push(ControlAction::basic_input(InputKind::Ability(0)));
|
||||||
|
self.jump_if(controller, bearing.z > 1.5);
|
||||||
|
controller.inputs.move_z = bearing.z;
|
||||||
|
} else {
|
||||||
|
controller.inputs.move_dir =
|
||||||
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
|
self.jump_if(controller, bearing.z > 1.5);
|
||||||
|
controller.inputs.move_z = bearing.z;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
agent.target = None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_arthropod_leap_attack(
|
||||||
|
&self,
|
||||||
|
agent: &mut Agent,
|
||||||
|
controller: &mut Controller,
|
||||||
|
attack_data: &AttackData,
|
||||||
|
tgt_data: &TargetData,
|
||||||
|
read_data: &ReadData,
|
||||||
|
rng: &mut impl Rng,
|
||||||
) {
|
) {
|
||||||
agent.action_state.timer += read_data.dt.0;
|
agent.action_state.timer += read_data.dt.0;
|
||||||
if agent.action_state.timer > 12.0
|
if agent.action_state.timer > 12.0
|
||||||
@ -1698,7 +1820,10 @@ impl<'a> AgentData<'a> {
|
|||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
// Reset timer
|
// Reset timer
|
||||||
|
if matches!(self.char_state, CharacterState::SpriteSummon(c) if matches!(c.stage_section, StageSection::Recover))
|
||||||
|
{
|
||||||
agent.action_state.timer = 0.0;
|
agent.action_state.timer = 0.0;
|
||||||
|
}
|
||||||
} else if attack_data.angle < 90.0
|
} else if attack_data.angle < 90.0
|
||||||
&& attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2)
|
&& attack_data.dist_sqrd < (1.5 * attack_data.min_attack_dist).powi(2)
|
||||||
{
|
{
|
||||||
@ -1706,7 +1831,7 @@ impl<'a> AgentData<'a> {
|
|||||||
controller
|
controller
|
||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Primary));
|
.push(ControlAction::basic_input(InputKind::Primary));
|
||||||
} else if thread_rng().gen_bool(0.01)
|
} else if rng.gen_bool(0.01)
|
||||||
&& attack_data.angle < 15.0
|
&& attack_data.angle < 15.0
|
||||||
&& attack_data.dist_sqrd < (6.0 * attack_data.min_attack_dist).powi(2)
|
&& attack_data.dist_sqrd < (6.0 * attack_data.min_attack_dist).powi(2)
|
||||||
{
|
{
|
||||||
@ -1718,7 +1843,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_arthropod_charge_attack(
|
pub fn handle_arthropod_charge_attack(
|
||||||
&self,
|
&self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
controller: &mut Controller,
|
controller: &mut Controller,
|
||||||
|
@ -95,6 +95,8 @@ pub enum Tactic {
|
|||||||
BirdLargeBasic,
|
BirdLargeBasic,
|
||||||
ArthropodCharge,
|
ArthropodCharge,
|
||||||
ArthropodBasic,
|
ArthropodBasic,
|
||||||
|
ArthropodRanged,
|
||||||
|
ArthropodLeap,
|
||||||
Minotaur,
|
Minotaur,
|
||||||
ClayGolem,
|
ClayGolem,
|
||||||
TidalWarrior,
|
TidalWarrior,
|
||||||
|
@ -35,8 +35,6 @@ impl Animation for AlphaAnimation {
|
|||||||
let subtract = global_time - timer;
|
let subtract = global_time - timer;
|
||||||
let check = subtract - subtract.trunc();
|
let check = subtract - subtract.trunc();
|
||||||
let mirror = (check - 0.5).signum();
|
let mirror = (check - 0.5).signum();
|
||||||
//let movement1 = mirror * movement1base * pullback;
|
|
||||||
//let movement2 = mirror * movement2base * pullback;
|
|
||||||
let movement1abs = movement1 * pullback;
|
let movement1abs = movement1 * pullback;
|
||||||
let movement2abs = movement2 * pullback;
|
let movement2abs = movement2 * pullback;
|
||||||
let movement3abs = movement3 * pullback;
|
let movement3abs = movement3 * pullback;
|
||||||
|
@ -31,21 +31,8 @@ impl Animation for DashAnimation {
|
|||||||
_ => (0.0, 0.0, 0.0, 0.0),
|
_ => (0.0, 0.0, 0.0, 0.0),
|
||||||
};
|
};
|
||||||
let pullback = 1.0 - movement3;
|
let pullback = 1.0 - movement3;
|
||||||
//let subtract = global_time - timer;
|
|
||||||
//let check = subtract - subtract.trunc();
|
|
||||||
//let mirror = (check - 0.5).signum();
|
|
||||||
//let twitch1 = (mirror * movement1base * 9.5).sin();
|
|
||||||
//let twitch1fast = (mirror * movement1base * 25.0).sin();
|
|
||||||
//let twitch3 = (mirror * movement3 * 4.0).sin();
|
|
||||||
//let movement1 = mirror * movement1base * pullback;
|
|
||||||
//let movement2 = mirror * movement2base * pullback;
|
|
||||||
let movement1abs = movement1base * pullback;
|
let movement1abs = movement1base * pullback;
|
||||||
let movement2abs = movement2base * pullback;
|
let movement2abs = movement2base * pullback;
|
||||||
//let short = ((1.0 / (0.72 + 0.28 * ((anim_time * 16.0_f32 + PI *
|
|
||||||
// 0.25).sin()).powi(2))) .sqrt())
|
|
||||||
// * ((anim_time * 16.0 + PI * 0.25).sin())
|
|
||||||
// * chargemovementbase
|
|
||||||
// * pullback;
|
|
||||||
let shortalt = (anim_time * 200.0 + PI * 0.25).sin() * chargemovementbase * pullback;
|
let shortalt = (anim_time * 200.0 + PI * 0.25).sin() * chargemovementbase * pullback;
|
||||||
|
|
||||||
next.chest.scale = Vec3::one();
|
next.chest.scale = Vec3::one();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::{super::Animation, ArthropodSkeleton, SkeletonAttr};
|
use super::{
|
||||||
//use std::{f32::consts::PI, ops::Mul};
|
super::{vek::*, Animation},
|
||||||
use super::super::vek::*;
|
ArthropodSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct IdleAnimation;
|
pub struct IdleAnimation;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::{super::Animation, ArthropodSkeleton, SkeletonAttr};
|
use super::{
|
||||||
//use std::f32::consts::PI;
|
super::{vek::*, Animation},
|
||||||
use super::super::vek::*;
|
ArthropodSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct JumpAnimation;
|
pub struct JumpAnimation;
|
||||||
|
|
||||||
@ -40,15 +41,31 @@ impl Animation for JumpAnimation {
|
|||||||
|
|
||||||
next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
||||||
next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
||||||
|
next.leg_fl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.0) * Quaternion::rotation_y(0.6);
|
||||||
|
next.leg_fr.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.0) * Quaternion::rotation_y(-0.6);
|
||||||
|
|
||||||
next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
||||||
next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
||||||
|
next.leg_fcl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.1) * Quaternion::rotation_y(0.6);
|
||||||
|
next.leg_fcr.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.1) * Quaternion::rotation_y(-0.6);
|
||||||
|
|
||||||
next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
||||||
next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
||||||
|
next.leg_bcl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.2) * Quaternion::rotation_y(0.6);
|
||||||
|
next.leg_bcr.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.2) * Quaternion::rotation_y(-0.6);
|
||||||
|
|
||||||
next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
||||||
next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
||||||
|
next.leg_bl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.3) * Quaternion::rotation_y(0.6);
|
||||||
|
next.leg_br.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.3) * Quaternion::rotation_y(-0.6);
|
||||||
|
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
|
@ -35,18 +35,11 @@ impl Animation for LeapMeleeAnimation {
|
|||||||
};
|
};
|
||||||
let pullback = 1.0 - movement4;
|
let pullback = 1.0 - movement4;
|
||||||
let early_pullback = 1.0 - movement3base;
|
let early_pullback = 1.0 - movement3base;
|
||||||
//let subtract = global_time - timer;
|
|
||||||
//let check = subtract - subtract.trunc();
|
|
||||||
//let mirror = (check - 0.5).signum();
|
|
||||||
let movement1abs = movement1base * pullback;
|
let movement1abs = movement1base * pullback;
|
||||||
let movement2abs = movement2base * pullback;
|
let movement2abs = movement2base * pullback;
|
||||||
let movement3abs = movement3base * pullback;
|
let movement3abs = movement3base * pullback;
|
||||||
|
|
||||||
//let twitch1 = (movement1base * 10.0).sin() * (1.0 - movement2base);
|
|
||||||
//let twitch3 = (movement3base * 5.0).sin() * mirror;
|
|
||||||
//let twitch1abs = twitch1 * mirror;
|
|
||||||
let shortalt = (global_time * 80.0).sin() * movement2base * early_pullback;
|
let shortalt = (global_time * 80.0).sin() * movement2base * early_pullback;
|
||||||
dbg!(anim_time);
|
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / s_a.scaler;
|
next.chest.scale = Vec3::one() / s_a.scaler;
|
||||||
|
|
||||||
@ -126,7 +119,9 @@ impl Animation for LeapMeleeAnimation {
|
|||||||
* Quaternion::rotation_z(movement1abs * -1.4);
|
* Quaternion::rotation_z(movement1abs * -1.4);
|
||||||
next.wing_br.orientation =
|
next.wing_br.orientation =
|
||||||
Quaternion::rotation_x((movement1abs * -0.2 + movement2abs * -0.6) * early_pullback)
|
Quaternion::rotation_x((movement1abs * -0.2 + movement2abs * -0.6) * early_pullback)
|
||||||
* Quaternion::rotation_y(movement1abs * -0.4 + shortalt * 2.0 + movement2abs * -0.1)
|
* Quaternion::rotation_y(
|
||||||
|
movement1abs * -0.4 + shortalt * 2.0 + movement2abs * -0.1,
|
||||||
|
)
|
||||||
* Quaternion::rotation_z(movement1abs * 1.4);
|
* Quaternion::rotation_z(movement1abs * 1.4);
|
||||||
|
|
||||||
next
|
next
|
||||||
|
@ -96,9 +96,7 @@ impl Skeleton for ArthropodSkeleton {
|
|||||||
|
|
||||||
// TODO: mount points
|
// TODO: mount points
|
||||||
//use comp::arthropod::Species::*;
|
//use comp::arthropod::Species::*;
|
||||||
let (mount_bone_mat, mount_bone_ori) = match (body.species, body.body_type) {
|
let (mount_bone_mat, mount_bone_ori) = (chest_mat, self.chest.orientation);
|
||||||
_ => (chest_mat, self.chest.orientation),
|
|
||||||
};
|
|
||||||
// Offset from the mounted bone's origin.
|
// Offset from the mounted bone's origin.
|
||||||
// Note: This could be its own bone if we need to animate it independently.
|
// Note: This could be its own bone if we need to animate it independently.
|
||||||
let mount_position = (mount_bone_mat * Vec4::from_point(mount_point(&body)))
|
let mount_position = (mount_bone_mat * Vec4::from_point(mount_point(&body)))
|
||||||
@ -239,7 +237,7 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
|||||||
(Antlion, _) => (4.0, 11.5, -4.0),
|
(Antlion, _) => (4.0, 11.5, -4.0),
|
||||||
(Hornbeetle, _) => (5.0, 6.0, -3.0),
|
(Hornbeetle, _) => (5.0, 6.0, -3.0),
|
||||||
(Leafbeetle, _) => (5.0, 6.0, -1.0),
|
(Leafbeetle, _) => (5.0, 6.0, -1.0),
|
||||||
(Stagbeetle, _) => (5.0, 6.0, -2.0),
|
(Stagbeetle, _) => (4.5, 6.0, -2.0),
|
||||||
(Weevil, _) => (5.0, 9.0, -2.0),
|
(Weevil, _) => (5.0, 9.0, -2.0),
|
||||||
(Cavespider, _) => (4.0, 13.0, -3.0),
|
(Cavespider, _) => (4.0, 13.0, -3.0),
|
||||||
(Moltencrawler, _) => (2.5, 14.0, -3.0),
|
(Moltencrawler, _) => (2.5, 14.0, -3.0),
|
||||||
@ -263,9 +261,9 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
|||||||
(Tarantula, _) => (1.5, 10.5, -1.5),
|
(Tarantula, _) => (1.5, 10.5, -1.5),
|
||||||
(Blackwidow, _) => (2.5, 10.0, -5.5),
|
(Blackwidow, _) => (2.5, 10.0, -5.5),
|
||||||
(Antlion, _) => (6.0, 7.5, -4.0),
|
(Antlion, _) => (6.0, 7.5, -4.0),
|
||||||
(Hornbeetle, _) => (6.0, 6.0, -3.0),
|
(Hornbeetle, _) => (5.0, 6.0, -3.0),
|
||||||
(Leafbeetle, _) => (6.0, 5.0, -2.5),
|
(Leafbeetle, _) => (4.5, 5.0, -2.5),
|
||||||
(Stagbeetle, _) => (6.0, 6.0, -2.0),
|
(Stagbeetle, _) => (5.0, 6.0, -2.0),
|
||||||
(Weevil, _) => (6.0, 5.0, -2.5),
|
(Weevil, _) => (6.0, 5.0, -2.5),
|
||||||
(Cavespider, _) => (2.5, 9.5, -2.5),
|
(Cavespider, _) => (2.5, 9.5, -2.5),
|
||||||
(Moltencrawler, _) => (2.5, 8.0, -3.0),
|
(Moltencrawler, _) => (2.5, 8.0, -3.0),
|
||||||
@ -289,14 +287,14 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
|||||||
(Tarantula, _) => (1.0),
|
(Tarantula, _) => (1.0),
|
||||||
(Blackwidow, _) => (1.0),
|
(Blackwidow, _) => (1.0),
|
||||||
(Antlion, _) => (1.0),
|
(Antlion, _) => (1.0),
|
||||||
(Hornbeetle, _) => (1.0),
|
(Hornbeetle, _) => (0.8),
|
||||||
(Leafbeetle, _) => (1.0),
|
(Leafbeetle, _) => (0.8),
|
||||||
(Stagbeetle, _) => (1.0),
|
(Stagbeetle, _) => (0.8),
|
||||||
(Weevil, _) => (1.0),
|
(Weevil, _) => (0.8),
|
||||||
(Cavespider, _) => (1.0),
|
(Cavespider, _) => (1.0),
|
||||||
(Moltencrawler, _) => (1.0),
|
(Moltencrawler, _) => (0.8),
|
||||||
(Mosscrawler, _) => (1.0),
|
(Mosscrawler, _) => (0.8),
|
||||||
(Sandcrawler, _) => (1.0),
|
(Sandcrawler, _) => (0.8),
|
||||||
},
|
},
|
||||||
// Z ori (front, front center, back center, center)
|
// Z ori (front, front center, back center, center)
|
||||||
leg_ori: match (body.species, body.body_type) {
|
leg_ori: match (body.species, body.body_type) {
|
||||||
@ -313,11 +311,8 @@ impl<'a> From<&'a Body> for SkeletonAttr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_point(body: &Body) -> Vec3<f32> {
|
fn mount_point(_body: &Body) -> Vec3<f32> {
|
||||||
// TODO: mount points
|
// TODO: mount points
|
||||||
//use comp::arthropod::{BodyType::*, Species::*};
|
//use comp::arthropod::{BodyType::*, Species::*};
|
||||||
match (body.species, body.body_type) {
|
(0.0, -6.0, 6.0).into()
|
||||||
(_, _) => (0.0, -6.0, 6.0),
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::{super::Animation, ArthropodSkeleton, SkeletonAttr};
|
use super::{
|
||||||
//use std::{f32::consts::PI, ops::Mul};
|
super::{vek::*, Animation},
|
||||||
use super::super::vek::*;
|
ArthropodSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
|
|
||||||
pub struct RunAnimation;
|
pub struct RunAnimation;
|
||||||
|
@ -36,7 +36,7 @@ impl Animation for ShootAnimation {
|
|||||||
|
|
||||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
||||||
next.head.orientation = Quaternion::rotation_x(movement1abs * 0.35 + twitch * -0.02)
|
next.head.orientation = Quaternion::rotation_x(movement1abs * 0.35 + twitch * -0.02)
|
||||||
* Quaternion::rotation_y(0.0); //* Quaternion::rotation_z((movement1abs * 4.0 * PI).sin() * 0.02);
|
* Quaternion::rotation_y(0.0);
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
|
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ use super::{
|
|||||||
ArthropodSkeleton, SkeletonAttr,
|
ArthropodSkeleton, SkeletonAttr,
|
||||||
};
|
};
|
||||||
use common::states::utils::StageSection;
|
use common::states::utils::StageSection;
|
||||||
//use std::ops::Rem;
|
|
||||||
|
|
||||||
pub struct StunnedAnimation;
|
pub struct StunnedAnimation;
|
||||||
|
|
||||||
@ -25,28 +24,23 @@ impl Animation for StunnedAnimation {
|
|||||||
let mut next = (*skeleton).clone();
|
let mut next = (*skeleton).clone();
|
||||||
|
|
||||||
let (_movement1base, movement2, twitch) = match stage_section {
|
let (_movement1base, movement2, twitch) = match stage_section {
|
||||||
Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0),
|
Some(StageSection::Buildup) => (anim_time.powf(0.1), 0.0, anim_time),
|
||||||
Some(StageSection::Recover) => {
|
Some(StageSection::Recover) => (1.0, anim_time.powf(4.0), 1.0),
|
||||||
(1.0, anim_time.powf(3.0), ((1.0 - anim_time) * 10.0).sin())
|
|
||||||
},
|
|
||||||
_ => (0.0, 0.0, 0.0),
|
_ => (0.0, 0.0, 0.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
let pullback = 1.0 - movement2;
|
let pullback = 1.0 - movement2;
|
||||||
//let subtract = global_time - timer;
|
|
||||||
//let check = subtract - subtract.trunc();
|
|
||||||
//let mirror = (check - 0.5).signum();
|
|
||||||
//let movement1 = mirror * movement1base * pullback;
|
|
||||||
//let movement1abs = movement1base * pullback;
|
|
||||||
|
|
||||||
let subtract = global_time - timer;
|
let subtract = global_time - timer;
|
||||||
let check = subtract - subtract.trunc();
|
let check = subtract - subtract.trunc();
|
||||||
let mirror = (check - 0.5).signum();
|
let mirror = (check - 0.5).signum();
|
||||||
|
let twitch1 = mirror * (twitch * 20.0).cos() * pullback;
|
||||||
let twitch2 = mirror * (twitch * 20.0).sin() * pullback;
|
let twitch2 = mirror * (twitch * 20.0).sin() * pullback;
|
||||||
|
|
||||||
next.chest.scale = Vec3::one() / s_a.scaler;
|
next.chest.scale = Vec3::one() / s_a.scaler;
|
||||||
|
|
||||||
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
|
||||||
|
next.head.orientation = Quaternion::rotation_z(twitch2 * 0.6);
|
||||||
|
|
||||||
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
|
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
|
||||||
|
|
||||||
@ -61,15 +55,31 @@ impl Animation for StunnedAnimation {
|
|||||||
|
|
||||||
next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
next.leg_fl.position = Vec3::new(-s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
||||||
next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
next.leg_fr.position = Vec3::new(s_a.leg_f.0, s_a.leg_f.1, s_a.leg_f.2);
|
||||||
|
next.leg_fl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.0) * Quaternion::rotation_x(twitch1 * 0.8 + 0.4);
|
||||||
|
next.leg_fr.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.0) * Quaternion::rotation_x(-twitch1 * 0.8 - 0.4);
|
||||||
|
|
||||||
next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
next.leg_fcl.position = Vec3::new(-s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
||||||
next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
next.leg_fcr.position = Vec3::new(s_a.leg_fc.0, s_a.leg_fc.1, s_a.leg_fc.2);
|
||||||
|
next.leg_fcl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.1) * Quaternion::rotation_y(twitch2 * 0.8 + 0.4);
|
||||||
|
next.leg_fcr.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.1) * Quaternion::rotation_y(-twitch2 * 0.8 - 0.4);
|
||||||
|
|
||||||
next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
next.leg_bcl.position = Vec3::new(-s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
||||||
next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
next.leg_bcr.position = Vec3::new(s_a.leg_bc.0, s_a.leg_bc.1, s_a.leg_bc.2);
|
||||||
|
next.leg_bcl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.2) * Quaternion::rotation_y(twitch1 * 0.8 + 0.4);
|
||||||
|
next.leg_bcr.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.2) * Quaternion::rotation_y(-twitch1 * 0.8 - 0.4);
|
||||||
|
|
||||||
next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
next.leg_bl.position = Vec3::new(-s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
||||||
next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
next.leg_br.position = Vec3::new(s_a.leg_b.0, s_a.leg_b.1, s_a.leg_b.2);
|
||||||
|
next.leg_bl.orientation =
|
||||||
|
Quaternion::rotation_z(s_a.leg_ori.3) * Quaternion::rotation_y(twitch2 * 0.8 + 0.4);
|
||||||
|
next.leg_br.orientation =
|
||||||
|
Quaternion::rotation_z(-s_a.leg_ori.3) * Quaternion::rotation_y(-twitch2 * 0.8 - 0.4);
|
||||||
|
|
||||||
next
|
next
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,6 @@ impl Animation for SummonAnimation {
|
|||||||
let subtract = global_time - timer;
|
let subtract = global_time - timer;
|
||||||
let check = subtract - subtract.trunc();
|
let check = subtract - subtract.trunc();
|
||||||
let mirror = (check - 0.5).signum();
|
let mirror = (check - 0.5).signum();
|
||||||
//let movement1 = mirror * movement1base * pullback;
|
|
||||||
//let movement2 = mirror * movement2base * pullback;
|
|
||||||
let movement1abs = movement1 * pullback;
|
let movement1abs = movement1 * pullback;
|
||||||
let movement2abs = movement2 * pullback;
|
let movement2abs = movement2 * pullback;
|
||||||
let movement3abs = movement3 * pullback;
|
let movement3abs = movement3 * pullback;
|
||||||
|
@ -469,15 +469,16 @@ pub fn apply_caves_supplement<'a>(
|
|||||||
match dynamic_rng.gen_range(0..6) {
|
match dynamic_rng.gen_range(0..6) {
|
||||||
0 => "common.entity.wild.aggressive.rocksnapper",
|
0 => "common.entity.wild.aggressive.rocksnapper",
|
||||||
1 => "common.entity.wild.aggressive.cave_salamander",
|
1 => "common.entity.wild.aggressive.cave_salamander",
|
||||||
2 => "common.entity.wild.aggressive.tarantula",
|
2 => "common.entity.wild.aggressive.cave_spider",
|
||||||
3 => "common.entity.wild.aggressive.antlion",
|
3 => "common.entity.wild.aggressive.antlion",
|
||||||
4 => "common.entity.wild.aggressive.black_widow",
|
4 => "common.entity.wild.peaceful.crawler_molten",
|
||||||
_ => "common.entity.wild.aggressive.asp",
|
_ => "common.entity.wild.aggressive.asp",
|
||||||
}
|
}
|
||||||
} else if cave_depth < 190.0 {
|
} else if cave_depth < 190.0 {
|
||||||
match dynamic_rng.gen_range(0..3) {
|
match dynamic_rng.gen_range(0..4) {
|
||||||
0 => "common.entity.wild.aggressive.rocksnapper",
|
0 => "common.entity.wild.aggressive.rocksnapper",
|
||||||
1 => "common.entity.wild.aggressive.lavadrake",
|
1 => "common.entity.wild.aggressive.lavadrake",
|
||||||
|
2 => "common.entity.wild.aggressive.black_widow",
|
||||||
_ => "common.entity.wild.aggressive.basilisk",
|
_ => "common.entity.wild.aggressive.basilisk",
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user