#items #loot #system #drop #stack #root #context

lootr

一个简单的类RPG式的寻宝系统

3 个版本 (破坏性)

0.7.0 2023年3月13日
0.4.0 2023年3月8日
0.3.0 2023年3月7日

#1070Rust 模式

MIT/Apache

50KB
797

Lootr

Lootr \lutʁ\ 是一个简单的类RPG式的寻宝系统。

Lootr 提供了一种在游戏上下文中组织称为寻宝的常见数据的方法。它帮助您管理哪些物品可以被找到,在一个通用且统计控制的系统中。

它深受 Bob Nystrom 的工作启发 http://journal.stuffwithstuff.com/2014/07/05/dropping-loot

在此处有可用的 JS 版本 https://github.com/vincent/lootr
在此处有可用的 C# 版本 https://github.com/Sparox/LootrCsharp

在 Lootr 中,可寻宝物品按类别和项目组织成一个树状结构。

ROOT
├─ Staff
├─ equipment
│  ├─ Glove
│  │  Boots
│  └─ leather
│     │  Jacket
│     └─ Pads
└─ weapons
   ├─ Bat
   └─ Knife

然后,一系列的掉落描述了物品是如何从寻宝操作中产生的。

equipment: .5 chances, stack of 1
equipment: .2 chances, stack of 2
equipment: .1 chances, stack of 2

例如,这可能导致装备树中的物品

  • 1 双靴子,平均每两次投掷出现一次
  • 2 双手套,每5次投掷出现一次
  • 1 把刀,每10次投掷出现一次

创建一个寻宝袋

创建物品。

use lootr::{Lootr, item::Item};
let mut loot = Lootr::new();

loot.add(
    Item::a("Berries")
);

物品可以有属性。

use lootr::{Lootr, item::{Item, Props}};
let mut loot = Lootr::new();

let item = Item::from("crown", Props::from([
    ("strength", "10"),
    ("charisma", "+100")
]));

loot.add(item);

// Items can printed
// crown{strength=10,charisma=+100}

每个级别由一个 .items 列表和嵌套的 .branches 组成。

通过添加分支来组织寻宝库

use lootr::Lootr;
let mut loot = Lootr::new();

let weapons = loot.add_branch("weapons", Lootr::new());
let armor = loot.add_branch("armor", Lootr::new());

可选地包含物品

use lootr::{Lootr, item::Item};
let mut loot = Lootr::new();

loot.add_branch("weapons", Lootr::from(vec![
    Item::a("Staff"),
    Item::an("Uzi")
]));

loot.add_branch("armor", Lootr::from(vec![
    Item::a("Boots"),
    Item::a("Socks")
]));

loot.branch_mut("armor")
    .unwrap()
    .add_branch("leather", Lootr::from(vec![
        Item::a("Belt"),
        Item::a("Hat")
    ]));

寻宝

对以下描述的寻宝表进行寻宝。

use lootr::{ROOT, drops::Drop};

let drops = [
    Drop { path: ROOT, depth: 1, luck: 1.0, stack: 1..=1, modify: false },
];

也提供了一个构建器模式来简化掉落创建。

  • path() 选择此掉落的根
  • depth() 考虑的最大深度
  • luck() 开始时的幸运值,将在每个子树中减少
  • stack() 产生的副本的范围
use lootr::{Lootr, item::Item, drops::DropBuilder};
let mut loot = Lootr::new();

loot.add_branch("weapons", Lootr::from(vec![
    Item::a("Staff"),
    Item::an("Uzi")
]));

loot.add_branch("armor", Lootr::from(vec![
    Item::a("Boots"),
    Item::a("Socks")
]));

let drops = [
    DropBuilder::new()
        .path("armor")
        .luck(1.0)
        .build(),

    DropBuilder::new()
        .path("weapons")
        .luck(1.0)
        .stack(1..=3)
        .build(),
];

// Loot your reward from a dead monster
let rewards = loot.loot(&drops);

// rewards = [ "Berries", "Plates", "Uzi", "Uzi", "Staff" ]

有种子 RNG

Lootr.loot_seeded() 接收一个 PRNG 参数,以一致且可重复的方式产生物品。

use lootr::{Lootr, item::Item, drops::DropBuilder};
use rand_chacha::ChaCha20Rng;
use rand::SeedableRng;

(0..10).for_each(|_f| {
    let mut loot = Lootr::from(vec![
        Item::named("Socks"),
        Item::named("Boots"),
    ]);
    let drops = [DropBuilder::new().build()];

    let rng = &mut ChaCha20Rng::seed_from_u64(123);

    loot.loot_seeded(&drops, rng);
    loot.loot_seeded(&drops, rng);
    // ...

    // Will always loot Boots, then Socks, then Socks, then Boots ..
})

修饰符

Lootr.add_modifier() 允许给一些物品转换器添加修饰符。

修饰符是简单的函数,可以从给定的物品中返回一个新的物品。

use lootr::{Lootr, item::{Item, Props}, drops::DropBuilder};
let mut loot = Lootr::new();
loot.add(Item::a("crown"));

fn with_strength(source: Item) -> Item {
    source.extend(source.name, Props::from([
        ("strength", "10"),
    ]))
}

loot.add_modifier(with_strength);

//
// Then, at loot time:

let drops = [DropBuilder::new().modify().build()];

let rewards = loot.loot(&drops);

// rewards = [ crown{strength=10} ]

宏定义

为了使建筑更容易,您可以使用 bag! 宏。

use lootr::{bag, Lootr, item::{Item, Props}};
let loot = bag! {
    @Weapons
        Knife attack="1" desc="A simple knife",
        @Wooden
            BarkShield attack="0" magic_power="10" desc="A wooden shield reinforced with bark, providing magic power",
            @Staffs
                WoodenStaff attack="5" magic_power="10" desc="A wooden staff imbued with magic power",
                CrystalStaff attack="8" magic_power="15" ice_damage="10" desc="A crystal staff with ice elemental damage",
                ElementalStaff attack="12" magic_power="20" thunder_damage="15" desc="An elemental staff with thunder elemental damage",
                .
            @Bows
                ShortBow attack="10" accuracy="10" desc="A short bow with high accuracy",
                LongBow attack="20" accuracy="20" ice_damage="10" desc="A long bow with ice elemental damage",
                .
            .
        @Swords
            ShortSword attack="10" critical="5" desc="A short sword with increased critical hit rate",
            LongSword attack="15" critical="10" desc="A long sword with a high critical hit rate",
            TwoHandedSword attack="20" critical="15" desc="A two-handed sword with a very high critical hit rate",
            .
        @Axes
            BattleAxe attack="12" critical="8" desc="A battle axe with increased critical hit rate",
            WarAxe attack="14" critical="9" desc="A war axe with a high critical hit rate",
            .
        @Mace
            MorningStar attack="13" critical="7" desc="A mace with increased critical hit rate",
            Flail attack="16" critical="11" desc="A flail with a very high critical hit rate",
            .
        .
    @Armors
        Shirt defense="0" desc="A simple shirt",
        @LightArmor
            LeatherArmor defense="5" agility="2" desc="Armor made of leather with increased agility",
            Chainmail defense="8" agility="1" desc="Armor made of interlocking rings with moderate agility",
            .
        @HeavyArmor
            PlateArmor defense="10" agility="-2" desc="Heavy armor made of plates with decreased agility",
            FullPlateArmor defense="15" agility="-5" desc="Very heavy armor made of plates with greatly decreased agility",
            .
        .
    @Consumables
        Water healing="2" desc="Just water",
        @Potion
            HealthPotion healing="20" desc="A potion that restores a small amount of health",
            GreaterHealthPotion healing="40" desc="A potion that restores a moderate amount of health",
            ManaPotion mana_restoration="20" desc="A potion that restores a small amount of mana",
            GreaterManaPotion mana_restoration="40" desc="A potion that restores a moderate amount of mana",
            .
        @Elixirs
            ElixirOfStrength strength_boost="5" desc="An elixir that boosts strength",
            GreaterElixirOfStrength strength_boost="10" desc="An elixir that greatly boosts strength",
            ElixirOfAgility agility_boost="5" desc="An elixir that boosts agility",
            GreaterElixirOfAgility agility_boost="10" desc="An elixir that greatly boosts agility",
            .
        .
};

println!("{}", loot);
ROOT
 ├─ test{}
 ├─ Armors
 │  ├─ Shirt{defense="0",desc="A simple shirt"}
 │  ├─ HeavyArmor
 │  │  └─ PlateArmor{agility="-2",defense="10",desc="Heavy armor made of plates with decreased agility"}
 │  │     FullPlateArmor{agility="-5",defense="15",desc="Very heavy armor made of plates with greatly decreased agility"}
 │  └─ LightArmor
 │     └─ LeatherArmor{defense="5",desc="Armor made of leather with increased agility",agility="2"}
 │        Chainmail{agility="1",defense="8",desc="Armor made of interlocking rings with moderate agility"}
 ├─ Consumables
 │  ├─ Water{desc="Just water",healing="2"}
 │  ├─ Elixirs
 │  │  └─ ElixirOfStrength{strength_boost="5",desc="An elixir that boosts strength"}
 │  │     GreaterElixirOfStrength{strength_boost="10",desc="An elixir that greatly boosts strength"}
 │  │     ElixirOfAgility{agility_boost="5",desc="An elixir that boosts agility"}
 │  │     GreaterElixirOfAgility{desc="An elixir that greatly boosts agility",agility_boost="10"}
 │  └─ Potion
 │     └─ HealthPotion{desc="A potion that restores a small amount of health",healing="20"}
 │        GreaterHealthPotion{desc="A potion that restores a moderate amount of health",healing="40"}
 │        ManaPotion{mana_restoration="20",desc="A potion that restores a small amount of mana"}
 │        GreaterManaPotion{desc="A potion that restores a moderate amount of mana",mana_restoration="40"}
 └─ Weapons
    ├─ Knife{desc="A simple knife",attack="1"}
    ├─ Axes
    │  └─ BattleAxe{attack="12",critical="8",desc="A battle axe with increased critical hit rate"}
    │     WarAxe{attack="14",desc="A war axe with a high critical hit rate",critical="9"}
    ├─ Mace
    │  └─ MorningStar{attack="13",critical="7",desc="A mace with increased critical hit rate"}
    │     Flail{desc="A flail with a very high critical hit rate",attack="16",critical="11"}
    ├─ Swords
    │  └─ ShortSword{critical="5",desc="A short sword with increased critical hit rate",attack="10"}
    │     LongSword{desc="A long sword with a high critical hit rate",attack="15",critical="10"}
    │     TwoHandedSword{attack="20",desc="A two-handed sword with a very high critical hit rate",critical="15"}
    └─ Wooden
       ├─ BarkShield{attack="0",magic_power="10",desc="A wooden shield reinforced with bark, providing magic power"}
       ├─ Bows
       │  └─ ShortBow{accuracy="10",attack="10",desc="A short bow with high accuracy"}
       │     LongBow{desc="A long bow with ice elemental damage",attack="20",ice_damage="10",accuracy="20"}
       └─ Staffs
          └─ WoodenStaff{desc="A wooden staff imbued with magic power",magic_power="10",attack="5"}
             CrystalStaff{ice_damage="10",desc="A crystal staff with ice elemental damage",magic_power="15",attack="8"}
             ElementalStaff{thunder_damage="15",desc="An elemental staff with thunder elemental damage",magic_power="20",attack="12"}

测试

货物测试

增加版本

货物增加次要版本

依赖项

~455KB