mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Created csv export tool to get all item drops from an entity
This commit is contained in:
parent
396604f6d8
commit
2dceadaebb
@ -17,13 +17,14 @@ use veloren_common::{
|
|||||||
ItemKind,
|
ItemKind,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
generation::EntityConfig,
|
||||||
lottery::{LootSpec, Lottery},
|
lottery::{LootSpec, Lottery},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(StructOpt)]
|
#[derive(StructOpt)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
/// Available arguments: "armor-stats", "weapon-stats", "all-items",
|
/// Available arguments: "armor-stats", "weapon-stats", "all-items",
|
||||||
/// "loot-table"
|
/// "loot-table", "entity-drops"
|
||||||
function: String,
|
function: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,6 +276,101 @@ fn loot_table(loot_table: &str) -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn entity_drops(entity_config: &str) -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut wtr = csv::Writer::from_path("drop_table.csv")?;
|
||||||
|
wtr.write_record(&["Percent Chance", "Item Path", "Quantity"])?;
|
||||||
|
|
||||||
|
let entity_config = "common.entity.".to_owned() + entity_config;
|
||||||
|
|
||||||
|
let entity_config = EntityConfig::load_expect(&entity_config).read();
|
||||||
|
|
||||||
|
// Create initial entry in drop table
|
||||||
|
let entry: (f32, LootSpec<String>) = (1.0, entity_config.loot.clone());
|
||||||
|
|
||||||
|
let mut table = vec![entry];
|
||||||
|
|
||||||
|
// Keep converting loot table lootspecs into non-loot table lootspecs until no
|
||||||
|
// more loot tables
|
||||||
|
while table
|
||||||
|
.iter()
|
||||||
|
.any(|(_, loot_spec)| matches!(loot_spec, LootSpec::LootTable(_)))
|
||||||
|
{
|
||||||
|
// Partition table of loot specs into a table of items and nothings, and another
|
||||||
|
// table of loot tables
|
||||||
|
let (sub_tables, main_table): (Vec<_>, Vec<_>) = table
|
||||||
|
.into_iter()
|
||||||
|
.partition(|(_, loot_spec)| matches!(loot_spec, LootSpec::LootTable(_)));
|
||||||
|
table = main_table;
|
||||||
|
|
||||||
|
// Change table of loot tables to only contain the string that loads the loot
|
||||||
|
// table
|
||||||
|
let sub_tables = sub_tables.iter().filter_map(|(chance, loot_spec)| {
|
||||||
|
if let LootSpec::LootTable(loot_table) = loot_spec {
|
||||||
|
Some((chance, loot_table))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (chance, loot_table) in sub_tables {
|
||||||
|
let loot_table = Lottery::<LootSpec<String>>::load_expect(&loot_table).read();
|
||||||
|
// Converts from lottery's weight addition for each consecutive entry to keep
|
||||||
|
// the weights as they are in the ron file
|
||||||
|
let loot_table: Vec<_> = loot_table
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, (chance, item))| {
|
||||||
|
let chance = if let Some((next_chance, _)) = loot_table.iter().nth(i + 1) {
|
||||||
|
next_chance - chance
|
||||||
|
} else {
|
||||||
|
loot_table.total() - chance
|
||||||
|
};
|
||||||
|
(chance, item)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
// Gets sum of all weights to use in normalization of entries
|
||||||
|
let weights_sum: f32 = loot_table.iter().map(|(chance, _)| chance).sum();
|
||||||
|
// Normalizes each entry in sub-loot table
|
||||||
|
let loot_table = loot_table
|
||||||
|
.iter()
|
||||||
|
.map(|(chance, item)| (chance / weights_sum, item));
|
||||||
|
for (sub_chance, &item) in loot_table {
|
||||||
|
// Multiplies normalized entry within each loot table by the chance for the loot
|
||||||
|
// table to drop in the above table
|
||||||
|
let entry = (chance * sub_chance, item.clone());
|
||||||
|
table.push(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalizes each item drop entry so that everything adds to 1
|
||||||
|
let table_weight_sum: f32 = table.iter().map(|(chance, _)| chance).sum();
|
||||||
|
let table = table
|
||||||
|
.iter()
|
||||||
|
.map(|(chance, item)| (chance / table_weight_sum, item));
|
||||||
|
|
||||||
|
for (chance, item) in table {
|
||||||
|
// Changes normalized weight to add to 100, and rounds at 2nd decimal
|
||||||
|
let percent_chance = chance
|
||||||
|
.mul(10_f32.powi(4))
|
||||||
|
.round()
|
||||||
|
.div(10_f32.powi(2))
|
||||||
|
.to_string();
|
||||||
|
let (item, quantity) = match item {
|
||||||
|
LootSpec::Item(item) => (item.to_string(), "1".to_string()),
|
||||||
|
LootSpec::ItemQuantity(item, lower, upper) => {
|
||||||
|
(item.to_string(), format!("{}-{}", lower, upper))
|
||||||
|
},
|
||||||
|
LootSpec::LootTable(_) => panic!("Shouldn't exist"),
|
||||||
|
LootSpec::Nothing => ("Nothing".to_string(), "-".to_string()),
|
||||||
|
};
|
||||||
|
|
||||||
|
wtr.write_record(&[&percent_chance, &item, &quantity])?
|
||||||
|
}
|
||||||
|
|
||||||
|
wtr.flush()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let args = Cli::from_args();
|
let args = Cli::from_args();
|
||||||
if args.function.eq_ignore_ascii_case("armor-stats") {
|
if args.function.eq_ignore_ascii_case("armor-stats") {
|
||||||
@ -297,6 +393,14 @@ fn main() {
|
|||||||
if let Err(e) = loot_table(&loot_table_name) {
|
if let Err(e) = loot_table(&loot_table_name) {
|
||||||
println!("Error: {}\n", e)
|
println!("Error: {}\n", e)
|
||||||
}
|
}
|
||||||
|
} else if args.function.eq_ignore_ascii_case("entity-drops") {
|
||||||
|
let entity_config = get_input(
|
||||||
|
"Specify the name of the entity to export loot drops to csv. Assumes entity config is \
|
||||||
|
in directory: assets.common.entity.\n",
|
||||||
|
);
|
||||||
|
if let Err(e) = entity_drops(&entity_config) {
|
||||||
|
println!("Error: {}\n", e)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
"Invalid argument, available \
|
"Invalid argument, available \
|
||||||
|
@ -105,7 +105,7 @@ pub struct EntityConfig {
|
|||||||
|
|
||||||
/// Loot
|
/// Loot
|
||||||
/// See LootSpec in lottery
|
/// See LootSpec in lottery
|
||||||
loot: LootSpec<String>,
|
pub loot: LootSpec<String>,
|
||||||
|
|
||||||
/// Hands:
|
/// Hands:
|
||||||
/// - TwoHanded(ItemSpec) for one 2h or 1h weapon,
|
/// - TwoHanded(ItemSpec) for one 2h or 1h weapon,
|
||||||
|
Loading…
Reference in New Issue
Block a user