Merge branch 'qutrin/loot-table' into 'master'

Implement a Lottery system

See merge request veloren/veloren!1147
This commit is contained in:
Joshua Barretto 2020-07-04 15:53:37 +00:00
commit 518edcb85c
5 changed files with 163 additions and 288 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added Lottery system for loot
- Added context-sensitive crosshair
- Announce alias changes to all clients
- Dance animation

View File

@ -0,0 +1,103 @@
[
// All loot rates go here
// miscellaneous
(0.4, "common.items.velorite"),
(0.6, "common.items.veloritefrag"),
(1.5, "common.items.potion_minor"),
(1, "common.items.collar"),
// swords
(0.1, "common.items.weapons.sword.starter_sword"),
(0.1, "common.items.weapons.sword.wood_sword"),
(0.1, "common.items.weapons.sword.short_sword_0"),
(0.06, "common.items.weapons.sword.greatsword_2h_dam-0"),
(0.06, "common.items.weapons.sword.greatsword_2h_dam-1"),
(0.06, "common.items.weapons.sword.greatsword_2h_dam-2"),
(0.03, "common.items.weapons.sword.greatsword_2h_simple-0"),
(0.03, "common.items.weapons.sword.greatsword_2h_simple-1"),
(0.03, "common.items.weapons.sword.greatsword_2h_simple-2"),
(0.01, "common.items.weapons.sword.greatsword_2h_orn-0"),
(0.01, "common.items.weapons.sword.greatsword_2h_orn-1"),
(0.01, "common.items.weapons.sword.greatsword_2h_orn-2"),
(0.04, "common.items.weapons.sword.long_2h_dam-0"),
(0.04, "common.items.weapons.sword.long_2h_dam-1"),
(0.04, "common.items.weapons.sword.long_2h_dam-2"),
(0.04, "common.items.weapons.sword.long_2h_dam-3"),
(0.04, "common.items.weapons.sword.long_2h_dam-4"),
(0.04, "common.items.weapons.sword.long_2h_dam-5"),
(0.02, "common.items.weapons.sword.long_2h_simple-0"),
(0.02, "common.items.weapons.sword.long_2h_simple-1"),
(0.02, "common.items.weapons.sword.long_2h_simple-2"),
(0.02, "common.items.weapons.sword.long_2h_simple-3"),
(0.02, "common.items.weapons.sword.long_2h_simple-4"),
(0.02, "common.items.weapons.sword.long_2h_simple-5"),
(0.007, "common.items.weapons.sword.long_2h_orn-0"),
(0.007, "common.items.weapons.sword.long_2h_orn-1"),
(0.007, "common.items.weapons.sword.long_2h_orn-2"),
(0.007, "common.items.weapons.sword.long_2h_orn-3"),
(0.007, "common.items.weapons.sword.long_2h_orn-4"),
(0.007, "common.items.weapons.sword.long_2h_orn-5"),
// axes
(1, "common.items.weapons.axe.starter_axe"),
// staves
(1, "common.items.weapons.staff.staff_nature"),
(1, "common.items.weapons.staff.starter_staff"),
// hammers
(1, "common.items.weapons.hammer.starter_hammer"),
// bows
(1, "common.items.weapons.bow.starter_bow"),
// belts
(0.2, "common.items.armor.belt.cloth_blue_0"),
(0.2, "common.items.armor.belt.cloth_green_0"),
(0.2, "common.items.armor.belt.cloth_purple_0"),
(0.15, "common.items.armor.belt.leather_0"),
(0.15, "common.items.armor.belt.leather_2"),
(0.1, "common.items.armor.belt.steel_0"),
(0.05, "common.items.armor.belt.plate_0"),
// chests
(0.2, "common.items.armor.chest.cloth_blue_0"),
(0.2, "common.items.armor.chest.cloth_green_0"),
(0.2, "common.items.armor.chest.cloth_purple_0"),
(0.15, "common.items.armor.chest.leather_0"),
(0.15, "common.items.armor.chest.leather_2"),
(0.1, "common.items.armor.chest.steel_0"),
(0.05, "common.items.armor.chest.plate_green_0"),
// shoes
(0.2, "common.items.armor.foot.cloth_blue_0"),
(0.2, "common.items.armor.foot.cloth_green_0"),
(0.2, "common.items.armor.foot.cloth_purple_0"),
(0.15, "common.items.armor.foot.leather_0"),
(0.15, "common.items.armor.foot.leather_2"),
(0.1, "common.items.armor.foot.steel_0"),
(0.05, "common.items.armor.foot.plate_0"),
// pants
(0.2, "common.items.armor.pants.cloth_blue_0"),
(0.2, "common.items.armor.pants.cloth_green_0"),
(0.2, "common.items.armor.pants.cloth_purple_0"),
(0.15, "common.items.armor.pants.green_0"),
(0.15, "common.items.armor.pants.leather_0"),
(0.1, "common.items.armor.pants.steel_0"),
(0.05, "common.items.armor.pants.plate_green_0"),
// shoulders
(0.2, "common.items.armor.shoulder.cloth_blue_0"),
(0.2, "common.items.armor.shoulder.cloth_green_0"),
(0.2, "common.items.armor.shoulder.cloth_purple_0"),
(0.1, "common.items.armor.shoulder.leather_0"),
(0.1, "common.items.armor.shoulder.leather_1"),
(0.1, "common.items.armor.shoulder.leather_2"),
(0.1, "common.items.armor.shoulder.steel_0"),
(0.05, "common.items.armor.shoulder.plate_0"),
//gloves
(0.2, "common.items.armor.hand.cloth_blue_0"),
(0.2, "common.items.armor.hand.cloth_green_0"),
(0.2, "common.items.armor.hand.cloth_purple_0"),
(0.15, "common.items.armor.hand.leather_0"),
(0.15, "common.items.armor.hand.leather_2"),
(0.1, "common.items.armor.hand.steel_0"),
(0.05, "common.items.armor.hand.plate_0"),
// rings
(0.6, "common.items.armor.ring.ring_0"),
// capes
(0.6, "common.items.armor.back.short_0"),
// necks
(0.6, "common.items.armor.neck.neck_0"),
]

View File

@ -0,0 +1,47 @@
use crate::assets::{self, Asset};
use rand::prelude::*;
use std::{fs::File, io::BufReader};
// Generate a random float between 0 and 1
pub fn rand() -> f32 {
let mut rng = rand::thread_rng();
rng.gen()
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Lottery<T> {
items: Vec<(f32, T)>,
total: f32,
}
impl Asset for Lottery<String> {
const ENDINGS: &'static [&'static str] = &["ron"];
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
ron::de::from_reader::<BufReader<File>, Vec<(f32, String)>>(buf_reader)
.map(|items| Lottery::from_rates(items.into_iter()))
.map_err(assets::Error::parse_error)
}
}
impl<T> Lottery<T> {
pub fn from_rates(items: impl Iterator<Item = (f32, T)>) -> Self {
let mut total = 0.0;
let items = items
.map(|(rate, item)| {
total += rate;
(total - rate, item)
})
.collect();
Self { items, total }
}
pub fn choose(&self) -> &T {
let x = rand() * self.total;
&self.items[self
.items
.binary_search_by(|(y, _)| y.partial_cmp(&x).unwrap())
.unwrap_or_else(|i| i.saturating_sub(1))]
.1
}
}

View File

@ -1,4 +1,5 @@
pub mod armor;
pub mod lottery;
pub mod tool;
// Reexports
@ -9,7 +10,6 @@ use crate::{
effect::Effect,
terrain::{Block, BlockKind},
};
use rand::seq::SliceRandom;
use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
use std::{fs::File, io::BufReader};
@ -179,118 +179,12 @@ impl Item {
},
BlockKind::ShortGrass => Some(assets::load_expect_cloned("common.items.grasses.short")),
BlockKind::Coconut => Some(assets::load_expect_cloned("common.items.coconut")),
BlockKind::Chest => Some(assets::load_expect_cloned(
[
//miscellaneous
"common.items.velorite",
"common.items.veloritefrag",
"common.items.potion_minor",
"common.items.collar",
//swords
"common.items.weapons.sword.starter_sword",
"common.items.weapons.sword.wood_sword",
"common.items.weapons.sword.short_sword_0",
"common.items.weapons.sword.greatsword_2h_simple-0",
"common.items.weapons.sword.greatsword_2h_simple-1",
"common.items.weapons.sword.greatsword_2h_simple-2",
"common.items.weapons.sword.long_2h_simple-0",
"common.items.weapons.sword.long_2h_simple-1",
"common.items.weapons.sword.long_2h_simple-2",
"common.items.weapons.sword.long_2h_simple-3",
"common.items.weapons.sword.long_2h_simple-4",
"common.items.weapons.sword.long_2h_simple-5",
"common.items.weapons.sword.greatsword_2h_dam-0",
"common.items.weapons.sword.greatsword_2h_dam-1",
"common.items.weapons.sword.greatsword_2h_dam-2",
"common.items.weapons.sword.greatsword_2h_orn-0",
"common.items.weapons.sword.greatsword_2h_orn-1",
"common.items.weapons.sword.greatsword_2h_orn-2",
"common.items.weapons.sword.long_2h_dam-0",
"common.items.weapons.sword.long_2h_dam-1",
"common.items.weapons.sword.long_2h_dam-2",
"common.items.weapons.sword.long_2h_dam-3",
"common.items.weapons.sword.long_2h_dam-4",
"common.items.weapons.sword.long_2h_dam-5",
"common.items.weapons.sword.long_2h_orn-0",
"common.items.weapons.sword.long_2h_orn-1",
"common.items.weapons.sword.long_2h_orn-2",
"common.items.weapons.sword.long_2h_orn-3",
"common.items.weapons.sword.long_2h_orn-4",
"common.items.weapons.sword.long_2h_orn-5",
"common.items.weapons.sword.long_2h_simple-0",
"common.items.weapons.sword.long_2h_simple-1",
"common.items.weapons.sword.long_2h_simple-2",
"common.items.weapons.sword.long_2h_simple-3",
"common.items.weapons.sword.long_2h_simple-4",
"common.items.weapons.sword.long_2h_simple-5",
//axes
"common.items.weapons.axe.starter_axe",
//staves
"common.items.weapons.staff.staff_nature",
"common.items.weapons.staff.starter_staff",
//hammers
"common.items.weapons.hammer.starter_hammer",
//bows
"common.items.weapons.bow.starter_bow",
//belts
"common.items.armor.belt.plate_0",
"common.items.armor.belt.steel_0",
"common.items.armor.belt.leather_0",
"common.items.armor.belt.leather_2",
"common.items.armor.belt.cloth_blue_0",
"common.items.armor.belt.cloth_green_0",
"common.items.armor.belt.cloth_purple_0",
//chests
"common.items.armor.chest.plate_green_0",
"common.items.armor.chest.leather_0",
"common.items.armor.chest.steel_0",
"common.items.armor.chest.leather_2",
"common.items.armor.chest.cloth_blue_0",
"common.items.armor.chest.cloth_green_0",
"common.items.armor.chest.cloth_purple_0",
//shoes
"common.items.armor.foot.plate_0",
"common.items.armor.foot.steel_0",
"common.items.armor.foot.leather_0",
"common.items.armor.foot.leather_2",
"common.items.armor.foot.cloth_blue_0",
"common.items.armor.foot.cloth_green_0",
"common.items.armor.foot.cloth_purple_0",
//pants
"common.items.armor.pants.plate_green_0",
"common.items.armor.pants.green_0",
"common.items.armor.pants.leather_0",
"common.items.armor.pants.steel_0",
"common.items.armor.pants.cloth_blue_0",
"common.items.armor.pants.cloth_green_0",
"common.items.armor.pants.cloth_purple_0",
//shoulders
"common.items.armor.shoulder.plate_0",
"common.items.armor.shoulder.steel_0",
"common.items.armor.shoulder.leather_1",
"common.items.armor.shoulder.leather_0",
"common.items.armor.shoulder.leather_2",
"common.items.armor.shoulder.cloth_blue_0",
"common.items.armor.shoulder.cloth_green_0",
"common.items.armor.shoulder.cloth_purple_0",
//gloves
"common.items.armor.hand.leather_0",
"common.items.armor.hand.leather_2",
"common.items.armor.hand.steel_0",
"common.items.armor.hand.plate_0",
"common.items.armor.hand.cloth_blue_0",
"common.items.armor.hand.cloth_green_0",
"common.items.armor.hand.cloth_purple_0",
//rings
"common.items.armor.ring.ring_0",
//capes
"common.items.armor.back.short_0",
//necks
"common.items.armor.neck.neck_0",
]
.choose(&mut rand::thread_rng())
.unwrap(), // Can't fail
)),
BlockKind::Chest => {
let chosen = assets::load_expect::<lottery::Lottery<_>>("common.items.loot_table");
let chosen = chosen.choose();
Some(assets::load_expect_cloned(chosen))
},
_ => None,
}
}

View File

@ -1,7 +1,7 @@
use crate::{client::Client, Server, SpawnPoint, StateExt};
use common::{
assets,
comp::{self, object, Body, HealthChange, HealthSource, Item, Player, Stats},
comp::{self, item::lottery::Lottery, object, Body, HealthChange, HealthSource, Player, Stats},
msg::{PlayerListUpdate, ServerMsg},
state::BlockChange,
sync::{Uid, WorldSyncExt},
@ -9,7 +9,6 @@ use common::{
terrain::{Block, TerrainGrid},
vol::{ReadVol, Vox},
};
use rand::seq::SliceRandom;
use specs::{join::Join, Entity as EcsEntity, WorldExt};
use tracing::error;
use vek::Vec3;
@ -112,179 +111,10 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
item_drops.remove(entity);
item_drop.0
} else {
assets::load_expect_cloned::<Item>(
[
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.collar",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.collar",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.collar",
"common.items.veloritefrag",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.collar",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.collar",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.cheese",
"common.items.mushroom",
"common.items.apple",
"common.items.collar",
"common.items.collar",
"common.items.collar",
"common.items.collar",
"common.items.collar",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.veloritefrag",
"common.items.velorite",
"common.items.armor.ring.ring_0",
"common.items.armor.neck.neck_0",
"common.items.mushroom",
"common.items.coconut",
"common.items.coconut",
"common.items.coconut",
"common.items.coconut",
"common.items.coconut",
"common.items.potion_minor",
"common.items.potion_minor",
"common.items.potion_minor",
"common.items.potion_minor",
"common.items.potion_minor",
"common.items.potion_minor",
"common.items.weapons.tool.broom",
"common.items.weapons.tool.shovel-1",
"common.items.weapons.staff.staff_nature",
"common.items.flowers.yellow",
"common.items.armor.pants.worker_blue_0",
"common.items.armor.chest.worker_yellow_0",
"common.items.armor.chest.worker_green_0",
"common.items.armor.chest.worker_orange_0",
"common.items.armor.back.short_0",
"common.items.weapons.staff.staff_nature",
"common.items.weapons.sword.starter_sword",
"common.items.weapons.axe.starter_axe",
"common.items.weapons.staff.staff_nature",
"common.items.weapons.hammer.starter_hammer",
"common.items.weapons.bow.starter_bow",
"common.items.weapons.staff.starter_staff",
"common.items.weapons.sword.starter_sword",
"common.items.weapons.axe.starter_axe",
"common.items.weapons.staff.staff_nature",
"common.items.weapons.hammer.starter_hammer",
"common.items.weapons.bow.starter_bow",
"common.items.weapons.staff.starter_staff",
"common.items.weapons.sword.starter_sword",
"common.items.weapons.axe.starter_axe",
"common.items.weapons.staff.staff_nature",
"common.items.weapons.hammer.starter_hammer",
"common.items.weapons.bow.starter_bow",
"common.items.weapons.staff.starter_staff",
"common.items.weapons.sword.greatsword_2h_simple-0",
"common.items.weapons.sword.greatsword_2h_simple-1",
"common.items.weapons.sword.greatsword_2h_simple-2",
"common.items.weapons.sword.long_2h_simple-0",
"common.items.weapons.sword.long_2h_simple-1",
"common.items.weapons.sword.long_2h_simple-2",
"common.items.weapons.sword.long_2h_simple-3",
"common.items.weapons.sword.long_2h_simple-4",
"common.items.weapons.sword.long_2h_simple-5",
]
.choose(&mut rand::thread_rng())
.unwrap(),
)
let chosen = assets::load_expect::<Lottery<_>>("common.items.loot_table");
let chosen = chosen.choose();
assets::load_expect_cloned(chosen)
};
let _ = state.ecs().write_storage().insert(entity, item);