Skip to content
This repository has been archived by the owner on Sep 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #25 from HiggsTardigradeTau/master
Browse files Browse the repository at this point in the history
Implement Generic Leader 2
  • Loading branch information
AnneKitsune authored Jan 6, 2021
2 parents a064f3d + e76ae4d commit 50b46bd
Show file tree
Hide file tree
Showing 9 changed files with 209 additions and 73 deletions.
12 changes: 12 additions & 0 deletions assets/effector_defs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,15 @@ defs:
effects:
- - ActionPointRefillRate
- MultiplicativeMultiplier: 0.0
AttackSpeedIncrease:
key: AttackSpeedIncrease
duration: 0.0
effects:
- - AttackSpeed
- AdditiveMultiplier: 0.1
HalfMovementSpeed:
key: HalfMovementSpeed
duration: 4.0
effects:
- - ActionPointRefillRate
- MultiplicativeMultiplier: 0.5
4 changes: 2 additions & 2 deletions assets/leader_defs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ defs:
key: Generic2
name: "Hero2"
skills:
- DoubleDamage
- AOE
- AttackSpeedIncrease
- SlowAOE
Generic3:
key: Generic3
name: "Hero3"
Expand Down
27 changes: 27 additions & 0 deletions assets/skill_defs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,30 @@ defs:
MinValue: 1.0
item_conditions: []
stat_effectors: []
AttackSpeedIncrease:
key: AttackSpeedIncrease
name: Attack Speed Increase
friendly_name: attack_speed_increase
description: Increase attack speed by 10% with every subsequent attack up to a 100% increase.
cooldown: 0.0
passive: true
conditions:
- stat_key: AttacksDealt
condition:
MaxValue: 10.0
item_conditions: []
stat_effectors:
- AttackSpeedIncrease
SlowAOE:
key: SlowAOE
name: Slow AOE
friendly_name: slow_aoe
description: Does 50 damage to all enemy entities around, and slows them by 50% for 4 seconds. Active only if 3 or more enemy entities are present. Cooldown of 12s.
cooldown: 12.0
passive: true
conditions:
- stat_key: EnemiesAround
condition:
MinValue: 3.0
item_conditions: []
stat_effectors: []
1 change: 0 additions & 1 deletion assets/stat_defs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,3 @@ defs:
min_value: 0
max_value: ~
icon_path: ~

4 changes: 4 additions & 0 deletions src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub enum Skills {
DoubleAttackSpeed,
NatureSummon,
Root,
AttackSpeedIncrease,
SlowAOE,
}

/// The different items ids.
Expand All @@ -48,6 +50,8 @@ pub enum Effectors {
DoubleDamage,
DoubleAttackSpeed,
Root,
AttackSpeedIncrease,
HalfMovementSpeed,
}

/// The different leader ids.
Expand Down
95 changes: 76 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@ const SCREEN_WIDTH: u32 = 100;
const SCREEN_HEIGHT: u32 = 50;
const CREEP_SPAWN_TICKS: u32 = 50;
const CREEP_ATTACK_RADIUS: f32 = 2.1;
//const LEADER_ATTACK_RADIUS: f32 = 2.1;
//const MELEE_LEADER_ATTACK_RADIUS: f32 = 2.1;
//const RANGED_LEADER_ATTACK_RADIUS: f32 = 6.3;
const AOE_RADIUS: f32 = 4.0;
const AOE_DAMAGE: f64 = 100.0;
const SLOW_AOE_RADIUS: f32 = 8.0;
const SLOW_AOE_DAMAGE: f64 = 50.0;
const TOWER_RANGE: f32 = 5.0;
const TOWER_PROJECTILE_EXPLOSION_RADIUS: f32 = 2.1;
const TARGET_FPS: f32 = 20.0;
Expand Down Expand Up @@ -424,25 +427,25 @@ fn main() -> BError {
));
}

// TODO re-enable de the hero
// TODO re-enable the hero
// currently disabled to make the game balanced
// Create generic hero 1
// centity!(
// world,
// Point::new(PLAY_WIDTH as i32 / 2, PLAY_HEIGHT as i32 - 11),
// Sprite {
// glyph: to_cp437('L'),
// //fg: RGBA::named(YELLOW),
// fg: RGBA::named(RED),
// bg: RGBA::named(GREEN),
// },
// SpriteIndex(6),
// Team::Me,
// _default_inventory,
// Leader(1),
// default_stats,
// skillset,
// );
/*centity!(
world,
Point::new(PLAY_WIDTH as i32 / 2, PLAY_HEIGHT as i32 - 11),
Sprite {
glyph: to_cp437('L'),
//fg: RGBA::named(YELLOW),
fg: RGBA::named(RED),
bg: RGBA::named(GREEN),
},
SpriteIndex(6),
Team::Me,
_default_inventory.clone(),
Leader(1),
default_stats.clone(),
skillset,
);*/
/*let hero1 = world
.create()
.with(Point::new(PLAY_WIDTH as i32 / 2, PLAY_HEIGHT as i32 - 11))
Expand All @@ -459,7 +462,7 @@ fn main() -> BError {
.with(Comp(skillset))
.with(AiPath::new(NavigationPath::new()))
.with(Leader(1))
.with(Hero1ProximityAttack::new(LEADER_ATTACK_RADIUS))
.with(Hero1ProximityAttack::new(MELEE_LEADER_ATTACK_RADIUS))
.with(Name("Generic Leader 1".to_string()))
.with(Comp(default_stats.clone()))
.with(Comp(EffectorSet::<Effectors>::default()))
Expand All @@ -470,6 +473,60 @@ fn main() -> BError {
// Make hero HP really high. Used for testing win conditions.
//world.write_storage::<Comp<StatSet<Stats>>>().get_mut(hero1).unwrap().0.stats.get_mut(&Stats::Health).unwrap().value = 10000000.0;

// hero2 skill set
skillset = SkillSet::new(HashMap::new());
skillset
.skills
.insert(Skills::SlowAOE, SkillInstance::new(Skills::SlowAOE, 0.0));

skillset.skills.insert(
Skills::AttackSpeedIncrease,
SkillInstance::new(Skills::AttackSpeedIncrease, 0.0),
);

// TODO re-enable the hero
// currently disabled to make the game balanced
// Create generic hero 2
/*centity!(
world,
Point::new(PLAY_WIDTH as i32 / 2, PLAY_HEIGHT as i32 - 40),
Sprite {
glyph: to_cp437('L'),
//fg: RGBA::named(YELLOW),
fg: RGBA::named(BLUE),
bg: RGBA::named(GREEN),
},
SpriteIndex(5),
Team::Other,
_default_inventory.clone(),
Leader(2),
default_stats.clone(),
skillset,
);*/
/*let hero2 = world
.create()
.with(Point::new(PLAY_WIDTH as i32 / 2, PLAY_HEIGHT as i32 - 1))
.with(Sprite {
glyph: to_cp437('L'),
//fg: RGBA::named(YELLOW),
fg: RGBA::named(BLUE),
bg: RGBA::named(GREEN),
})
.with(SpriteIndex(5))
.with(Team::Other)
.with(Hero1SimpleMovement)
.with(Comp(default_inventory.clone()))
.with(Comp(skillset))
.with(AiPath::new(NavigationPath::new()))
.with(Leader(2))
.with(Hero1ProximityAttack::new(RANGED_LEADER_ATTACK_RADIUS))
.with(Name("Generic Leader 2".to_string()))
.with(Comp(default_stats.clone()))
.with(Comp(EffectorSet::<Effectors>::default()))
.with(FleeToBase(50.0))
.with(IsCaught(false))
.build();*/

create_map_bg(&mut world);

let gs = State {
Expand Down
33 changes: 33 additions & 0 deletions src/systems/aoe_damage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ pub fn aoe_damage_system(
teams: &Components<Team>,
entities: &Entities,
events: &Vec<SkillTriggerEvent<Skills>>,
effector_defs: &EffectorDefinitions<Stats, Effectors>,
effectors: &mut Components<EffectorSet<Effectors>>,
game_events: &mut Vec<GameEvent>,
) -> SystemResult {
for ev in events.iter() {
Expand All @@ -22,6 +24,37 @@ pub fn aoe_damage_system(
game_events.push(GameEvent::DamageEntity(e, AOE_DAMAGE));
}
}
} else if ev.1 == Skills::SlowAOE {
// Damage around and apply effector
if let (Some(from), Some(team)) = (positions.get(ev.0), teams.get(ev.0)) {
for (e, _, _) in entities_in_radius(
from,
&*entities,
&positions,
|e, _| teams.get(e).map(|t| t != team).unwrap_or(false),
|_, _, d| d <= SLOW_AOE_RADIUS,
) {
game_events.push(GameEvent::DamageEntity(e, SLOW_AOE_DAMAGE));

let slow_effector = effector_defs
.defs
.get(&Effectors::HalfMovementSpeed)
.expect("Unknown effector key.");

if effectors.get(e).is_none() {
effectors.insert(e, EffectorSet::default());
}

effectors
.get_mut(e)
.unwrap()
.effectors
.push(EffectorInstance::new(
Effectors::HalfMovementSpeed,
slow_effector.duration,
))
}
}
}
}
Ok(())
Expand Down
95 changes: 46 additions & 49 deletions src/systems/hero1_simple_movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,60 @@ pub fn hero1_simple_movement_system(
positions: &Components<Point>,
targets: &mut Components<AiDestination>,
) -> SystemResult {
for (e, leader, flee, leader_team, caught) in
join!(&entities && &leaders && &retreats && &teams && &is_caught)
for (e, flee, leader_team, caught) in
join!(&entities && &retreats && &teams && &is_caught)
{
let e = e.unwrap();
let leader = leader.unwrap();
let flee = flee.unwrap();
let leader_team = leader_team.unwrap();
let caught = caught.unwrap();
if leader.0 == 1 {
if caught.0 {
for (e, _, team, pos) in
join!(&entities && &simple_movements && &teams && &positions)
{
if caught.0 {
for (e, _, team, pos) in
join!(&entities && &simple_movements && &teams && &positions)
{
let e = e.unwrap();
let team = team.unwrap();
let pos = pos.unwrap();
// find closest leader in other team
// TODO: optimize
let mut vec = join!(&teams && &positions && &stats && &leaders)
.filter(|(t, _, _, _)| *t.unwrap() != *team)
.map(|(_, p, _, _)| (dist(pos, p.unwrap()), p.unwrap().clone()))
.collect::<Vec<_>>();
vec.sort_by(|e1, e2| e1.0.partial_cmp(&e2.0).unwrap());
let closest = vec.into_iter().next().map(|(_d, p)| p);
if let Some(c) = closest {
targets.insert(e, AiDestination::new(c.clone())).unwrap();
} else {
targets.remove(e);
}
}
} else {
// retreat if health is low
if stats
.get(e)
.unwrap()
.stats
.get(&Stats::Health)
.unwrap()
.value
<= flee.0
{
for (point, team, _) in join!(&positions && &teams && &cores) {
if team.unwrap() == leader_team {
targets
.insert(e, AiDestination::new(point.unwrap().clone()))
.unwrap();
}
}
} else {
for (e, _, pos) in join!(&entities && &simple_movements && &positions) {
let e = e.unwrap();
let team = team.unwrap();
let pos = pos.unwrap();
// find closest leader in other team
// find closest creep
// TODO: optimize
let mut vec = join!(&teams && &positions && &stats && &leaders)
.filter(|(t, _, _, _)| *t.unwrap() != *team)
.map(|(_, p, _, _)| (dist(pos, p.unwrap()), p.unwrap().clone()))
let mut vec = join!(&positions && &stats && &creeps)
.map(|(p, _, _)| (dist(pos, p.unwrap()), p.unwrap().clone()))
.collect::<Vec<_>>();
vec.sort_by(|e1, e2| e1.0.partial_cmp(&e2.0).unwrap());
let closest = vec.into_iter().next().map(|(_d, p)| p);
Expand All @@ -44,42 +77,6 @@ pub fn hero1_simple_movement_system(
targets.remove(e);
}
}
} else {
// retreat if health is low
if stats
.get(e)
.unwrap()
.stats
.get(&Stats::Health)
.unwrap()
.value
<= flee.0
{
for (point, team, _) in join!(&positions && &teams && &cores) {
if team.unwrap() == leader_team {
targets
.insert(e, AiDestination::new(point.unwrap().clone()))
.unwrap();
}
}
} else {
for (e, _, pos) in join!(&entities && &simple_movements && &positions) {
let e = e.unwrap();
let pos = pos.unwrap();
// find closest creep
// TODO: optimize
let mut vec = join!(&positions && &stats && &creeps)
.map(|(p, _, _)| (dist(pos, p.unwrap()), p.unwrap().clone()))
.collect::<Vec<_>>();
vec.sort_by(|e1, e2| e1.0.partial_cmp(&e2.0).unwrap());
let closest = vec.into_iter().next().map(|(_d, p)| p);
if let Some(c) = closest {
targets.insert(e, AiDestination::new(c.clone())).unwrap();
} else {
targets.remove(e);
}
}
}
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/systems/update_enemies_around_stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,22 @@ pub fn update_enemies_around_system(
entities: &Entities,
positions: &Components<Point>,
teams: &Components<Team>,
skills: &Components<SkillSet<Skills>>,
stats: &mut Components<StatSet<Stats>>,
) -> SystemResult {
for (pos, stat, team) in join!(&positions && &mut stats && &teams) {
for (pos, stat, team, skill) in join!(&positions && &mut stats && &teams && &skills) {
let mut radius = AOE_RADIUS;

if let Some(_) = skill.unwrap().skills.get(&Skills::SlowAOE) {
radius = SLOW_AOE_RADIUS;
}

let c = entities_in_radius(
pos.unwrap(),
&*entities,
&positions,
|e, _| teams.get(e).map(|t| t != team.unwrap()).unwrap_or(false),
|_, _, d| d <= AOE_RADIUS,
|_, _, d| d <= radius,
)
.len() as f64;
stat.unwrap()
Expand Down

0 comments on commit 50b46bd

Please sign in to comment.