Browse Source

Add a combat system

master
Graham Northup 6 months ago
parent
commit
7f6fd9cb3e
  1. 4
      Cargo.toml
  2. 59
      src/world/entity/mod.rs
  3. 16
      src/world/entity/player.rs
  4. 7
      src/world/mod.rs

4
Cargo.toml

@ -7,8 +7,8 @@ edition = "2018"
[dependencies]
rogue_util = { git = "https://github.com/grissess/rogue_utils" }
termion = "^1"
rand_distr = "^0.2"
rand_distr = "^0.4"
[dependencies.rand]
version = "^0.7"
version = "^0.8"
features = ["small_rng"]

59
src/world/entity/mod.rs

@ -3,6 +3,7 @@ pub mod player;
use super::*;
use rogue_util::{coord::*, raster, grid::Grid};
use std::fmt::Debug;
use rand::Rng;
pub trait Visible {
fn is_transparent(&self) -> bool;
@ -35,9 +36,48 @@ impl LinfDir {
}
}
pub type Hp = usize;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DamageKind {
Phys, Magic,
#[doc(hidden)]
_NeverExhaustive
}
#[derive(Debug, Clone, Copy)]
pub struct DamageDesc {
pub kind: DamageKind,
pub base: Hp,
pub add: Hp,
}
#[derive(Debug, Clone, Copy)]
pub struct Damage {
pub kind: DamageKind,
pub amount: Hp,
}
impl DamageDesc {
pub fn roll(&self) -> Damage {
let mut amt = self.base;
if self.add > 0 {
amt += rand::thread_rng().gen_range(0 ..= self.add);
}
Damage { kind: self.kind, amount: amt }
}
}
impl From<&DamageDesc> for Damage {
fn from(dd: &DamageDesc) -> Self {
dd.roll()
}
}
#[derive(Debug, Clone)]
pub enum Action {
Move(LinfDir),
Attack(EntWeak, Rc<Vec<DamageDesc>>),
Wait,
Quit,
}
@ -115,21 +155,32 @@ const DEFAULT_ACT_TIME: usize = 10000;
const ECLS_LIVING: usize = 1;
pub trait Entity {
pub trait Entity: Debug {
fn pos(&self) -> V2i;
fn set_pos(&mut self, v: V2i);
fn next_time(&self) -> usize;
fn set_next_time(&mut self, t: usize);
fn hp(&self) -> Hp;
fn set_hp(&mut self, h: Hp);
fn class(&self) -> usize { 0 }
fn hp(&self) -> isize { 100 }
fn set_hp(&mut self, _hp: isize) {}
fn char(&self) -> char { 'E' }
fn sight(&self) -> usize { DEFAULT_SIGHT_RADIUS }
fn act_time(&self) -> usize { DEFAULT_ACT_TIME }
fn is_dead(&self) -> bool { self.hp() <= 0 }
fn act(&mut self, _obs: &Observation) -> Action { Action::Wait }
fn heal(&mut self, amount: Hp) {
let hp = self.hp().saturating_add(amount);
self.set_hp(hp);
}
fn harm(&mut self, amount: Hp) {
let hp = self.hp().saturating_sub(amount);
self.set_hp(hp);
}
fn is_dead(&self) -> bool { self.hp() == 0 }
fn take_damage(&mut self, dmg: Damage) {
self.harm(dmg.amount);
}
}
pub type EntBox = Box<dyn Entity>;

16
src/world/entity/player.rs

@ -2,14 +2,26 @@ use super::*;
use rogue_util::coord::*;
use termion::event::Key;
use std::io;
use std::fmt::{self, Formatter};
pub struct Player<R> {
pos: V2i,
hp: usize, // TODO
hp: Hp, // TODO
time: usize,
input: R,
}
impl<R> Debug for Player<R> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Player")
.field("pos", &self.pos)
.field("hp", &self.hp)
.field("time", &self.time)
.field("input", &"...")
.finish()
}
}
impl<R> Player<R> {
pub fn new(p: V2i, r: R) -> Player<R> {
Player {
@ -29,6 +41,8 @@ impl<R> Entity for Player<R>
fn set_pos(&mut self, p: V2i) { self.pos = p; }
fn next_time(&self) -> usize { self.time }
fn set_next_time(&mut self, t: usize) { self.time = t; }
fn hp(&self) -> Hp { self.hp }
fn set_hp(&mut self, hp: Hp) { self.hp = hp; }
fn class(&self) -> usize {
ECLS_LIVING

7
src/world/mod.rs

@ -171,6 +171,13 @@ impl World {
}
e.set_pos(p + dp);
},
Attack(who, vd) => {
if let Some(who) = who.upgrade() {
for dd in vd.iter() {
who.borrow_mut().take_damage(dd.into());
}
}
},
Quit => {
return Some(());
},

Loading…
Cancel
Save