Added sceptre tactic and sceptre cultists

This commit is contained in:
Knightress Paladin 2021-07-06 01:29:11 -07:00
parent 0cf92321f1
commit 2d1799e6f1
4 changed files with 154 additions and 6 deletions

View File

@ -5,11 +5,7 @@ EntityConfig (
loot: Some(LootTable("common.loot_tables.dungeon.tier-5.enemy")), loot: Some(LootTable("common.loot_tables.dungeon.tier-5.enemy")),
main_tool: Some(Choice([ main_tool: Some(Choice([
(1.0, Some(Item("common.items.weapons.axe_1h.orichalcum-0"))), (1.0, Some(Item("common.items.weapons.sceptre.sceptre_velorite_0"))),
(2.0, Some(Item("common.items.weapons.sword.cultist"))),
(1.0, Some(Item("common.items.weapons.hammer.cultist_purp_2h-0"))),
(1.0, Some(Item("common.items.weapons.hammer_1h.orichalcum-0"))),
(1.0, Some(Item("common.items.weapons.bow.velorite"))),
])), ])),
second_tool: None, second_tool: None,

View File

@ -4,4 +4,5 @@
Tree("common.skillset.dungeon.tier-5.axe"), Tree("common.skillset.dungeon.tier-5.axe"),
Tree("common.skillset.dungeon.tier-5.hammer"), Tree("common.skillset.dungeon.tier-5.hammer"),
Tree("common.skillset.dungeon.tier-5.bow"), Tree("common.skillset.dungeon.tier-5.bow"),
Tree("common.skillset.dungeon.tier-5.sceptre"),
]) ])

View File

@ -0,0 +1,21 @@
([
Group(Weapon(Sceptre)),
// Beam
Skill((Sceptre(LDamage), Some(1))),
Skill((Sceptre(LRange), Some(1))),
Skill((Sceptre(LLifesteal), Some(1))),
Skill((Sceptre(LRegen), Some(1))),
// Heal
Skill((Sceptre(HHeal), Some(1))),
Skill((Sceptre(HCost), Some(1))),
Skill((Sceptre(HRange), Some(1))),
// Ward
Skill((Sceptre(UnlockAura), None)),
Skill((Sceptre(AStrength), Some(1))),
Skill((Sceptre(ADuration), Some(1))),
Skill((Sceptre(ARange), Some(1))),
Skill((Sceptre(ACost), Some(1))),
])

View File

@ -17,7 +17,7 @@ use common::{
tool::{AbilitySpec, ToolKind}, tool::{AbilitySpec, ToolKind},
Item, ItemDesc, ItemKind, Item, ItemDesc, ItemKind,
}, },
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill}, skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill, SceptreSkill},
Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterAbility, Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterAbility,
CharacterState, ControlAction, ControlEvent, Controller, Energy, Health, HealthChange, CharacterState, ControlAction, ControlEvent, Controller, Energy, Health, HealthChange,
InputKind, Inventory, InventoryAction, LightEmitter, MountState, Ori, PhysicsState, Pos, InputKind, Inventory, InventoryAction, LightEmitter, MountState, Ori, PhysicsState, Pos,
@ -99,6 +99,7 @@ pub enum Tactic {
Sword, Sword,
Bow, Bow,
Staff, Staff,
Sceptre,
StoneGolem, StoneGolem,
CircleCharge { radius: u32, circle_time: u32 }, CircleCharge { radius: u32, circle_time: u32 },
QuadLowRanged, QuadLowRanged,
@ -1613,6 +1614,7 @@ impl<'a> AgentData<'a> {
let tool_tactic = |tool_kind| match tool_kind { let tool_tactic = |tool_kind| match tool_kind {
ToolKind::Bow => Tactic::Bow, ToolKind::Bow => Tactic::Bow,
ToolKind::Staff => Tactic::Staff, ToolKind::Staff => Tactic::Staff,
ToolKind::Sceptre => Tactic::Sceptre,
ToolKind::Hammer => Tactic::Hammer, ToolKind::Hammer => Tactic::Hammer,
ToolKind::Sword | ToolKind::Spear => Tactic::Sword, ToolKind::Sword | ToolKind::Spear => Tactic::Sword,
ToolKind::Axe => Tactic::Axe, ToolKind::Axe => Tactic::Axe,
@ -1630,6 +1632,7 @@ impl<'a> AgentData<'a> {
"Axe Simple" | "Sword Simple" => Tactic::Sword, "Axe Simple" | "Sword Simple" => Tactic::Sword,
"Staff Simple" => Tactic::Staff, "Staff Simple" => Tactic::Staff,
"Bow Simple" => Tactic::Bow, "Bow Simple" => Tactic::Bow,
"Sceptre Simple" => Tactic::Sceptre,
"Stone Golem" => Tactic::StoneGolem, "Stone Golem" => Tactic::StoneGolem,
"Quad Med Quick" => Tactic::CircleCharge { "Quad Med Quick" => Tactic::CircleCharge {
radius: 3, radius: 3,
@ -1815,6 +1818,9 @@ impl<'a> AgentData<'a> {
Tactic::Staff => { Tactic::Staff => {
self.handle_staff_attack(agent, controller, &attack_data, &tgt_data, &read_data) self.handle_staff_attack(agent, controller, &attack_data, &tgt_data, &read_data)
}, },
Tactic::Sceptre => {
self.handle_sceptre_attack(agent, controller, &attack_data, &tgt_data, &read_data)
},
Tactic::StoneGolem => self.handle_stone_golem_attack( Tactic::StoneGolem => self.handle_stone_golem_attack(
agent, agent,
controller, controller,
@ -2431,6 +2437,130 @@ impl<'a> AgentData<'a> {
} }
} }
fn handle_sceptre_attack(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
) {
const DESIRED_ENERGY_LEVEL: u32 = 500;
// Logic to use abilities
if attack_data.dist_sqrd > attack_data.min_attack_dist.powi(2)
&& can_see_tgt(
&*read_data.terrain,
self.pos,
tgt_data.pos,
attack_data.dist_sqrd,
)
{
// If far enough away, and can see target, attempt to shoot beam
if self.energy.current() < DESIRED_ENERGY_LEVEL {
// If low on energy, use primary to attempt to regen energy
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
} else if self
.skill_set
.has_skill(Skill::Sceptre(SceptreSkill::UnlockAura))
&& self.energy.current() > 100
&& thread_rng().gen_bool(0.7)
{
// Use ward if target is far enough away and have sufficient energy
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(0)));
}
else {
// If at desired energy level but not able to ward, just attack
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
} else if attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) {
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
&& self.energy.current() > CharacterAbility::default_roll().get_energy_cost()
&& !matches!(self.char_state, CharacterState::BasicAura(c) if !matches!(c.stage_section, StageSection::Recover))
{
// Else roll away if can roll and have enough energy, and not using beam
// (other attacks have interrupt handled above) unless in recover
controller
.actions
.push(ControlAction::basic_input(InputKind::Roll));
} else {
if attack_data.angle < 15.0 {
controller
.actions
.push(ControlAction::basic_input(InputKind::Primary));
}
}
}
// Logic to move. Intentionally kept separate from ability logic so duplicated
// work is less necessary.
if attack_data.dist_sqrd < (2.0 * attack_data.min_attack_dist).powi(2) {
// Attempt to move away from target if too close
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
},
) {
controller.inputs.move_dir =
-bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
}
} else if attack_data.dist_sqrd < MAX_PATH_DIST.powi(2) {
// Else attempt to circle target if neither too close nor too far
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 can_see_tgt(
&*read_data.terrain,
self.pos,
tgt_data.pos,
attack_data.dist_sqrd,
) && attack_data.angle < 45.0
{
controller.inputs.move_dir = bearing
.xy()
.rotated_z(thread_rng().gen_range(0.5..1.57))
.try_normalized()
.unwrap_or_else(Vec2::zero)
* speed;
} else {
// Unless cannot see target, then move towards them
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;
}
}
// Sometimes try to roll
if self.body.map(|b| b.is_humanoid()).unwrap_or(false)
&& attack_data.dist_sqrd < 16.0f32.powi(2)
&& thread_rng().gen::<f32>() < 0.01
{
controller
.actions
.push(ControlAction::basic_input(InputKind::Roll));
}
} else {
// If too far, move towards target
self.path_toward_target(agent, controller, tgt_data, read_data, false, None);
}
}
fn handle_stone_golem_attack( fn handle_stone_golem_attack(
&self, &self,
agent: &mut Agent, agent: &mut Agent,