Add Changelog to README; Remove /world announcements

This commit is contained in:
Jeff 2024-09-02 01:11:47 -04:00
parent 68e7b675ef
commit ed2fc13217
44 changed files with 750 additions and 529 deletions

703
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -33,12 +33,13 @@ The bot is able to respond to the following commands, which must be sent via "/t
search term.
- `admin_access`: Admin-only, prompts the bot to send a trade invite to the sender, after which it
will give away and accept any items until the trade ends.
- `announce`: Admin-only, sends the announcement message to "/world". This will reset the
- `announce`: Admin-only, sends the announcement message to "/region". This will reset the
announcement timer to 45 minutes.
- `location`: Returns the bot's current town or, if it is not in a town, its current position.
- `sort [count (optional)]`: Admin-only, sorts the inventory once or the given number of times.
- `pos [x] [y] [z]`: Admin-only, sets the bot's desired position where it will try to stand (must
be close to the bot's current position)
- `ori [0-360]`: Admin-only, sets the bot's desired orientation (or facing direction)
be close to the bot's current position).
- `ori [0-360]`: Admin-only, sets the bot's desired orientation (or facing direction).
## Prerequisites
@ -94,10 +95,8 @@ position = [0, 0, 0]
# Its orientation can be changed in-game with the "ori" command.
orientation = 0
# Optional. Announcements are sent every 45 minutes. Use {location} to insert the bot's current
# location. If not set, the bot will not send /world announcements but will still send /region
# announcements with usage instructions.
announcement = "I love cheese! I am at {location}."
# Optional. Announcements are sent every 45 minutes. If not set, the bot will not make announcements.
announcement = "I love cheese!"
# The buy_prices and sell_prices tables are required. The keys are item definition IDs and the
# values are the price in coins. You may type in-game "/give_item common.items." and press Tab to
@ -143,6 +142,17 @@ podman build . -t trade_bot
Then follow the [above](#running) steps with the tag "trade_bot" instead of
"git.jeffa.io/jeff/trade_bot".
## Changelog
- 9/2/2024:
- Added the "location" command.
- Removed the "{location}" feature from the announcement message. Announcements are now sent to
"/region" so this feature is now used by the "location" command.
- Changed announcements to be sent to "/region" instead of "/world". The moderators on the official
server have asked for this, so please don't run an old version to circumvent the change.
- Removed the "Ouch!" and "That hurt!" messages when the bot is attacked. The moderators have also
asked for this.
## License
This project is licensed under the GPL-3.0 license. See the [LICENSE](LICENSE) file for details.

View File

@ -771,8 +771,9 @@
primary: Simple(None, "common.abilities.custom.harvester.scythe"),
secondary: Simple(None, "common.abilities.custom.harvester.firebreath"),
abilities: [
Simple(None, "common.abilities.custom.harvester.ensnaringvines"),
Simple(None, "common.abilities.custom.harvester.explodingpumpkin"),
Simple(None, "common.abilities.custom.harvester.ensnaringvines_sparse"),
Simple(None, "common.abilities.custom.harvester.ensnaringvines_dense"),
],
),
// TODO: Allow ability sets to expand other ability sets

View File

@ -0,0 +1,10 @@
SpriteSummon(
buildup_duration: 0.9,
cast_duration: 0.6,
recover_duration: 0.5,
sprite: EnsnaringVines,
del_timeout: None,
summon_distance: (0, 25),
sparseness: 0.6,
angle: 360,
)

View File

@ -0,0 +1,10 @@
SpriteSummon(
buildup_duration: 0.6,
cast_duration: 0.4,
recover_duration: 0.3,
sprite: EnsnaringVines,
del_timeout: None,
summon_distance: (0, 30),
sparseness: 0.8,
angle: 360,
)

View File

@ -1,21 +1,21 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.75,
buildup_duration: 1.0,
recover_duration: 1.6,
projectile: (
kind: Explosive(
radius: 5,
radius: 7.2,
min_falloff: 0.6,
reagent: Some(Red),
terrain: Some((5, Black)),
),
attack: Some((
damage: 37.5,
knockback: Some(25),
damage: 20,
knockback: Some(22),
energy: 0,
buff: Some((
kind: Burning,
dur_secs: 5,
dur_secs: 4,
strength: DamageFraction(0.2),
chance: 1.0,
)),

View File

@ -2,18 +2,18 @@ BasicBeam(
buildup_duration: 1.4,
recover_duration: 0.9,
beam_duration: 1.0,
damage: 9.0,
damage: 5.0,
tick_rate: 1.5,
range: 20.0,
max_angle: 15.0,
damage_effect: Some(Buff((
kind: Burning,
dur_secs: 10.0,
strength: DamageFraction(1.0),
dur_secs: 3.0,
strength: DamageFraction(0.8),
chance: 1.0,
))),
energy_regen: 0,
energy_drain: 0,
ori_rate: 0.3,
ori_rate: 0.7,
specifier: Flamethrower,
)

View File

@ -1,19 +1,19 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 0.9,
swing_duration: 0.1,
buildup_duration: 1.0,
swing_duration: 0.2,
hit_timing: 0.5,
recover_duration: 1.2,
recover_duration: 1.0,
melee_constructor: (
kind: Slash(
damage: 21.0,
damage: 15.0,
poise: 10.0,
knockback: 10.0,
energy_regen: 0.0,
),
range: 4.0,
angle: 60.0,
range: 4.5,
angle: 50.0,
multi_target: Some(Normal),
),
ori_modifier: 1.0,
ori_modifier: 0.5,
)

View File

@ -7,7 +7,7 @@ BasicMelee(
melee_constructor: (
kind: Bash(
damage: 8,
poise: 5,
poise: 10,
knockback: 0,
energy_regen: 0,
),

View File

@ -7,7 +7,7 @@ BasicMelee(
melee_constructor: (
kind: SonicWave(
damage: 10,
poise: 100,
poise: 75,
knockback: 20,
energy_regen: 0,
),

View File

@ -1,20 +1,20 @@
Shockwave(
energy_cost: 0,
buildup_duration: 3.0,
buildup_duration: 1.2,
swing_duration: 0.12,
recover_duration: 2.4,
damage: 60.0,
recover_duration: 1.5,
damage: 22.0,
poise_damage: 30,
knockback: (strength: 30.0, direction: TowardsUp),
knockback: (strength: 20.0, direction: TowardsUp),
shockwave_angle: 90.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 15.0,
shockwave_duration: 2.0,
shockwave_duration: 1.9,
dodgeable: Jump,
move_efficiency: 0.0,
damage_kind: Crushing,
specifier: Ground,
ori_rate: 1.0,
ori_rate: 0.9,
timing: PostBuildup,
emit_outcome: true,
)

View File

@ -1,18 +1,18 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 0.9,
buildup_duration: 1.2,
swing_duration: 0.3,
hit_timing: 0.6,
recover_duration: 0.6,
recover_duration: 1.2,
melee_constructor: (
kind: Bash(
damage: 45,
damage: 18,
poise: 30,
knockback: 20,
energy_regen: 0,
),
range: 7.5,
range: 5.0,
angle: 360,
),
ori_modifier: 1.0,
ori_modifier: 0.75,
)

View File

@ -1,18 +1,18 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 1.6,
swing_duration: 0.1,
buildup_duration: 1.0,
swing_duration: 0.2,
hit_timing: 0.6,
recover_duration: 1.0,
melee_constructor: (
kind: Bash(
damage: 30.0,
damage: 12.0,
poise: 25.0,
knockback: 15.0,
energy_regen: 0.0,
),
range: 4.0,
angle: 45.0,
angle: 55.0,
),
ori_modifier: 0.4,
ori_modifier: 0.7,
)

View File

@ -1,28 +1,28 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.825,
buildup_duration: 1.0,
recover_duration: 0.6,
projectile: (
kind: Explosive(
radius: 2,
min_falloff: 0.5,
radius: 3,
min_falloff: 0.7,
reagent: Some(Red),
terrain: Some((2, Black))
),
attack: Some((
damage: 13.5,
damage: 5.5,
energy: 10,
buff: Some((
kind: Burning,
dur_secs: 5,
strength: DamageFraction(0.1),
dur_secs: 3,
strength: DamageFraction(0.3),
chance: 0.1,
)),
)),
),
projectile_body: Object(BoltFire),
projectile_speed: 25,
num_projectiles: 8,
num_projectiles: 5,
projectile_spread: 0.125,
move_efficiency: 0.3,
)

View File

@ -1,16 +1,16 @@
Shockwave(
energy_cost: 0,
buildup_duration: 0.975,
buildup_duration: 1.2,
swing_duration: 0.1,
recover_duration: 0.6,
damage: 30,
recover_duration: 0.8,
damage: 16,
poise_damage: 0,
knockback: ( strength: 25, direction: Away),
knockback: ( strength: 15, direction: Away),
shockwave_angle: 360,
shockwave_vertical_angle: 90,
shockwave_speed: 10,
shockwave_duration: 1,
dodgeable: Roll,
shockwave_speed: 12,
shockwave_duration: 1.0,
dodgeable: Jump,
move_efficiency: 0,
damage_kind: Energy,
specifier: Fire,

View File

@ -1,21 +1,21 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 0.6,
swing_duration: 0.1,
buildup_duration: 0.75,
swing_duration: 0.4,
hit_timing: 0.5,
recover_duration: 0.45,
recover_duration: 0.6,
melee_constructor: (
kind: Bash(
damage: 12,
damage: 9,
poise: 10,
knockback: 0,
energy_regen: 0,
),
range: 7.5,
angle: 60.0,
range: 3.0,
angle: 40.0,
damage_effect: Some(Buff((
kind: Burning,
dur_secs: 10.0,
dur_secs: 4.0,
strength: DamageFraction(0.5),
chance: 0.5,
))),

View File

@ -1,24 +1,24 @@
BasicAura(
buildup_duration: 0.375,
cast_duration: 0.5,
recover_duration: 0.375,
buildup_duration: 0.2,
cast_duration: 0.4,
recover_duration: 0.2,
targets: InGroup,
auras: [
(
kind: Regeneration,
strength: 7.5,
duration: Some(5),
strength: 1,
duration: Some(1),
category: Magical,
),
(
kind: ProtectingWard,
strength: 0.75,
duration: Some(5),
strength: 0.5,
duration: Some(1),
category: Magical,
),
],
aura_duration: Some(2),
range: 50,
aura_duration: Some(1),
range: 15,
energy_cost: 0,
scales_with_combo: false,
)

View File

@ -1,18 +1,18 @@
BasicAura(
buildup_duration: 0.375,
cast_duration: 0.5,
recover_duration: 0.375,
buildup_duration: 0.2,
cast_duration: 0.4,
recover_duration: 0.2,
targets: OutOfGroup,
auras: [
(
kind: Burning,
strength: 0.75,
duration: Some(5),
strength: 1.2,
duration: Some(1),
category: Magical,
),
],
aura_duration: Some(2),
range: 50,
aura_duration: Some(1),
range: 15,
energy_cost: 0,
scales_with_combo: false,
)

View File

@ -1,18 +1,18 @@
BasicAura(
buildup_duration: 0.375,
cast_duration: 0.5,
recover_duration: 0.375,
buildup_duration: 0.2,
cast_duration: 0.4,
recover_duration: 0.2,
targets: InGroup,
auras: [
(
kind: Hastened,
strength: 0.75,
duration: Some(5),
strength: 0.4,
duration: Some(1),
category: Magical,
),
],
aura_duration: Some(2),
range: 50,
aura_duration: Some(1),
range: 15,
energy_cost: 0,
scales_with_combo: false,
)

View File

@ -2,7 +2,7 @@
#![enable(implicit_some)]
(
name: Name("Gnarling Chieftain"),
body: RandomWith("gnarling"),
body: RandomWith("gnarling_chieftain"),
alignment: Alignment(Enemy),
loot: LootTable("common.loot_tables.dungeon.gnarling.chieftain"),
inventory: (

View File

@ -3183,6 +3183,9 @@
Simple(
"common.items.consumable.potion_minor",
): "object-potion_minor",
Simple(
"common.items.consumable.potion_freezing",
): "object-potion_freezing",
Simple(
"common.items.lantern.black_0",
): "lantern-black",

View File

@ -6,10 +6,10 @@ ItemDef(
stats: Direct((
protection: Some(Normal(3.0)),
poise_resilience: Some(Normal(1.0)),
energy_max: Some(14.0),
energy_max: Some(6.0),
)),
)),
quality: High,
quality: Moderate,
tags: [
Gnarling,
SalvageInto(Lifecloth, 1),

View File

@ -17,5 +17,5 @@ ItemDef(
])
),
quality: Legendary,
tags: [],
tags: [Charm],
)

View File

@ -17,5 +17,5 @@ ItemDef(
])
),
quality: Legendary,
tags: [],
tags: [Charm],
)

View File

@ -16,5 +16,5 @@ ItemDef(
])
),
quality: Legendary,
tags: [],
tags: [Charm],
)

View File

@ -11,7 +11,15 @@ ItemDef(
duration: Some(10)
),
cat_ids: [Natural],
))
)),
Buff((
kind: PotionSickness,
data: (
strength: 0.15,
duration: Some(30),
),
cat_ids: [Natural],
)),
])
),
quality: Moderate,

View File

@ -0,0 +1,27 @@
ItemDef(
legacy_name: "Freezing Potion",
legacy_description: "Freezes the user's brain",
kind: Consumable(
kind: Drink,
effects: All([
Buff((
kind: Frozen,
data: (
strength: 0.1,
duration: Some(30)
),
cat_ids: [Natural],
)),
Buff((
kind: PotionSickness,
data: (
strength: 0.15,
duration: Some(30),
),
cat_ids: [Natural],
)),
])
),
quality: Moderate,
tags: [Potion],
)

View File

@ -2,6 +2,6 @@ ItemDef(
legacy_name: "Green Luna",
legacy_description: "The delicate wings flutter faintly.",
kind: Glider,
quality: High,
quality: Moderate,
tags: [],
)

View File

@ -8,6 +8,6 @@ ItemDef(
flicker_thousandths: 600,
),
),
quality: High,
quality: Moderate,
tags: [Utility],
)

View File

@ -4,6 +4,7 @@ ItemDef(
kind: RecipeGroup(
recipes: [
"potion_combustion",
"potion_freezing",
"potion_agility",
"potion_minor",
"potion_medium",

View File

@ -1,12 +1,14 @@
[
// Weapons
(5.0, LootTable("common.loot_tables.weapons.tier-1")),
// Armor
(5.0, LootTable("common.loot_tables.armor.tier-1")),
// Misc
(3.0, Item("common.items.armor.misc.neck.scratched")),
(2.0, Item("common.items.armor.misc.head.wanderers_hat")),
(3.0, Item("common.items.armor.misc.head.bamboo_twig")),
// Chieftain Mask
(1.0, Item("common.items.armor.misc.head.gnarling_mask")),
(1, All([
All([
LootTable("common.loot_tables.armor.tier-1"),
LootTable("common.loot_tables.weapons.tier-1"),
]),
Lottery([
(2.0, Nothing),
(1.0, Item("common.items.armor.misc.neck.scratched")),
(1.0, Item("common.items.armor.misc.head.gnarling_mask")),
(1.0, Item("common.items.glider.moth")),
]),
])),
]

View File

@ -1,10 +1,13 @@
[
// Weapons
(5.0, LootTable("common.loot_tables.weapons.tier-3")),
// Armor
(5.0, LootTable("common.loot_tables.armor.tier-3")),
// Misc
(3.0, Item("common.items.armor.misc.neck.scratched")),
(2.0, Item("common.items.lantern.pumpkin")),
(1.0, Item("common.items.glider.moth")),
(1, All([
All([
LootTable("common.loot_tables.armor.tier-2"),
LootTable("common.loot_tables.weapons.tier-2"),
]),
Lottery([
(3.0, Nothing),
(1.0, Item("common.items.lantern.pumpkin")),
(1.0, Item("common.items.armor.misc.head.wanderers_hat")),
]),
])),
]

View File

@ -1,6 +1,16 @@
[
// Crafting ingredients
(2.4, MultiDrop(Item("common.items.log.wood"), 5, 10)),
(0.1, MultiDrop(Item("common.items.log.hardwood"), 1, 2)),
(0.5, LootTable("common.loot_tables.weapons.components.secondary.sceptre")),
(1, Lottery([
(0.7, All([
MultiDrop(Item("common.items.log.wood"), 3, 4),
MultiDrop(Item("common.items.crafting_ing.twigs"), 1, 2),
Lottery([
(0.6, MultiDrop(Item("common.items.log.bamboo"), 1, 2)),
(0.4, LootTable("common.loot_tables.weapons.components.secondary.sceptre")),
]),
])),
(0.3, All([
MultiDrop(Item("common.items.log.wood"), 5, 7),
MultiDrop(Item("common.items.crafting_ing.twigs"), 3, 5),
])),
]))
]

View File

@ -4,7 +4,7 @@
// Ingredients
(2.0, Item("common.items.crafting_ing.coral_branch")),
(0.5, Item("common.items.crafting_ing.pearl")),
(0.25, Item("common.items.recipes.unique.seashell_necklace")),
(0.5, Item("common.items.recipes.armor.brinestone")),
(0.25, Item("common.items.recipes.unique.winged_coronet")),
(0.25, Item("common.items.recipes.unique.abyssal_ring")),
]),

View File

@ -1,3 +1,5 @@
[
(1.0, Item("common.items.recipes.armor.brinestone")),
(1.0, Nothing),
(1.0, LootTable("common.loot_tables.food.prepared")),
(0.5, Item("common.items.recipes.unique.seashell_necklace")),
]

View File

@ -1,5 +1,5 @@
[
(1.0, LootTable("common.loot_tables.weapons.components.tier-1")),
(1.0, LootTable("common.loot_tables.weapons.components.tier-0")),
(1.0, LootTable("common.loot_tables.armor.cloth")),
(0.5, Item("common.items.recipes.explosives")),
]

View File

@ -1,7 +1,16 @@
[
(1.0, LootTable("common.loot_tables.weapons.components.tier-0")),
(1.0, LootTable("common.loot_tables.weapons.components.tier-1")),
(1.0, LootTable("common.loot_tables.armor.cloth")),
(0.5, LootTable("common.loot_tables.weapons.components.tier-0")),
(0.25, LootTable("common.loot_tables.weapons.tier-0")),
(0.25, LootTable("common.loot_tables.armor.tier-0")),
(0.25, Item("common.items.armor.misc.head.bamboo_twig")),
// Currency
(3.0, MultiDrop(Item("common.items.utility.coins"), 25, 50)),
// Materials
(0.5, MultiDrop(Item("common.items.mineral.ore.veloritefrag"), 5, 10)),
// Consumables
(2.0, MultiDrop(Item("common.items.consumable.potion_minor"), 2, 5)),
// Food
(1.0, MultiDrop(LootTable("common.loot_tables.food.prepared"), 1, 2)),
(0.2, Item("common.items.recipes.explosives")),
(0.5, Item("common.items.recipes.instruments")),
(0.2, Item("common.items.recipes.charms")),

View File

@ -1233,6 +1233,10 @@
keyword: "treasure_egg",
generic: "Treasure Egg",
),
gnarling_chieftain: (
keyword: "gnarling_chieftain",
generic: "Gnarling Chieftain"
),
)
),
fish_small: (

View File

@ -31,6 +31,15 @@
],
craft_sprite: Some(Anvil),
),
"potion_freezing": (
output: ("common.items.consumable.potion_freezing", 1),
inputs: [
(Item("common.items.crafting_ing.empty_vial"), 1, false),
(Item("common.items.crafting_ing.animal_misc.icy_fang"), 3, false),
(Item("common.items.crafting_ing.animal_misc.viscous_ooze"), 1, false),
],
craft_sprite: Some(Cauldron),
),
"potion_combustion": (
output: ("common.items.consumable.potion_combustion", 1),
inputs: [

View File

@ -24,8 +24,8 @@ loot_tables: [
(20.375, true, "common.trading.food"),
// Recipes
(1.0, true, "common.trading.sellable_recipe"),
(1.0, false, "common.trading.unsellable_recipe"),
(1.8, true, "common.trading.sellable_recipe"),
(1.5, false, "common.trading.unsellable_recipe"),
// Potions
//
@ -50,5 +50,6 @@ good_scaling: [
(Armor, 0.025), // common.items.armor.misc.pants.worker_blue
(Tools, 0.015487), // common.items.weapons.staff.starter_staff
(Ingredients, 0.034626), // common.items.crafting_ing.leather_scraps
(Wood, 0.034626), // common.items.log.wood
(Recipe, 0.01), // common.items.recipes
])

View File

@ -1,7 +1,50 @@
[
// Legendary sceptres
// Purple Linen set
Set([
"common.items.weapons.sceptre.root_evil",
"common.items.weapons.sceptre.caduceus",
"common.items.armor.cloth_purple.belt",
"common.items.armor.cloth_purple.chest",
"common.items.armor.cloth_purple.foot",
"common.items.armor.cloth_purple.hand",
"common.items.armor.cloth_purple.pants",
"common.items.armor.cloth_purple.shoulder",
]),
// Green Linen set
Set([
"common.items.armor.cloth_green.belt",
"common.items.armor.cloth_green.chest",
"common.items.armor.cloth_green.foot",
"common.items.armor.cloth_green.hand",
"common.items.armor.cloth_green.pants",
"common.items.armor.cloth_green.shoulder",
]),
// Blue Linen set
Set([
"common.items.armor.cloth_blue.belt",
"common.items.armor.cloth_blue.chest",
"common.items.armor.cloth_blue.foot",
"common.items.armor.cloth_blue.hand",
"common.items.armor.cloth_blue.pants",
"common.items.armor.cloth_blue.shoulder_0",
"common.items.armor.cloth_blue.shoulder_1",
]),
// Worker/starter clothing
Set([
"common.items.armor.misc.chest.worker_green_0",
"common.items.armor.misc.chest.worker_green_1",
"common.items.armor.misc.chest.worker_orange_0",
"common.items.armor.misc.chest.worker_orange_1",
"common.items.armor.misc.chest.worker_purple_0",
"common.items.armor.misc.chest.worker_purple_1",
"common.items.armor.misc.chest.worker_purple_brown",
"common.items.armor.misc.chest.worker_red_0",
"common.items.armor.misc.chest.worker_red_1",
"common.items.armor.misc.chest.worker_yellow_0",
"common.items.armor.misc.chest.worker_yellow_1",
"common.items.armor.misc.pants.worker_blue",
"common.items.armor.misc.pants.worker_brown",
"common.items.armor.misc.foot.sandals",
]),
]

View File

@ -6,40 +6,40 @@
[
// Recipes
// Misc Groups
(1.0, Item("common.items.recipes.charms")),
(1.0, Item("common.items.recipes.explosives")),
(1.0, Item("common.items.recipes.gliders")),
(1.0, Item("common.items.recipes.instruments")),
(1.25, Item("common.items.recipes.charms")),
(1.25, Item("common.items.recipes.explosives")),
(1.25, Item("common.items.recipes.gliders")),
(1.25, Item("common.items.recipes.instruments")),
// Equipment
(1.0, Item("common.items.recipes.equipment.moderate")),
(0.2, Item("common.items.recipes.equipment.advanced")),
(0.3, Item("common.items.recipes.equipment.advanced")),
// Armors
(0.7, Item("common.items.recipes.armor.steel")),
(0.7, Item("common.items.recipes.armor.silken")),
(0.7, Item("common.items.recipes.armor.scale")),
(0.7, Item("common.items.recipes.weapons.steel")),
(0.7, Item("common.items.recipes.weapons.hardwood")),
(0.4, Item("common.items.recipes.armor.cobalt")),
(0.4, Item("common.items.recipes.armor.druid")),
(0.4, Item("common.items.recipes.armor.carapace")),
(0.4, Item("common.items.recipes.weapons.cobalt")),
(0.4, Item("common.items.recipes.weapons.ironwood")),
(0.2, Item("common.items.recipes.armor.bloodsteel")),
(0.2, Item("common.items.recipes.armor.moonweave")),
(0.2, Item("common.items.recipes.armor.primal")),
(0.2, Item("common.items.recipes.weapons.bloodsteel")),
(0.2, Item("common.items.recipes.weapons.frostwood")),
(0.1, Item("common.items.recipes.armor.orichalcum")),
(0.1, Item("common.items.recipes.armor.sunsilk")),
(0.1, Item("common.items.recipes.armor.dragonscale")),
(0.1, Item("common.items.recipes.armor.brinestone")),
(0.1, Item("common.items.recipes.weapons.orichalcum")),
(0.1, Item("common.items.recipes.weapons.eldwood")),
(1.25, Item("common.items.recipes.armor.steel")),
(1.25, Item("common.items.recipes.armor.silken")),
(1.25, Item("common.items.recipes.armor.scale")),
(1.25, Item("common.items.recipes.weapons.steel")),
(1.25, Item("common.items.recipes.weapons.hardwood")),
(0.65, Item("common.items.recipes.armor.cobalt")),
(0.65, Item("common.items.recipes.armor.druid")),
(0.65, Item("common.items.recipes.armor.carapace")),
(0.65, Item("common.items.recipes.weapons.cobalt")),
(0.65, Item("common.items.recipes.weapons.ironwood")),
(0.38, Item("common.items.recipes.armor.bloodsteel")),
(0.38, Item("common.items.recipes.armor.moonweave")),
(0.38, Item("common.items.recipes.armor.primal")),
(0.38, Item("common.items.recipes.weapons.bloodsteel")),
(0.38, Item("common.items.recipes.weapons.frostwood")),
(0.25, Item("common.items.recipes.armor.sunsilk")),
(0.25, Item("common.items.recipes.armor.orichalcum")),
(0.25, Item("common.items.recipes.armor.dragonscale")),
(0.25, Item("common.items.recipes.weapons.orichalcum")),
(0.25, Item("common.items.recipes.weapons.eldwood")),
(0.25, Item("common.items.recipes.armor.brinestone")),
// Unique items
(1.0, Item("common.items.recipes.unique.seashell_necklace")),
(0.8, Item("common.items.recipes.unique.winged_coronet")),
(1.25, Item("common.items.recipes.unique.seashell_necklace")),
(0.6, Item("common.items.recipes.unique.winged_coronet")),
(0.5, Item("common.items.recipes.unique.troll_hide_pack")),
(0.3, Item("common.items.recipes.unique.abyssal_gorget")),
(0.1, Item("common.items.recipes.unique.mindflayer_spellbag")),
(0.2, Item("common.items.recipes.unique.abyssal_gorget")),
(0.15, Item("common.items.recipes.unique.mindflayer_spellbag")),
(0.1, Item("common.items.recipes.unique.polaris")),
]

View File

@ -1,3 +1,4 @@
announcement = "Beep Boop!"
position = [17720.0, 14951.0, 237.0]
orientation = 0

View File

@ -21,12 +21,11 @@ use veloren_common::{
tool::AbilityMap,
ChatType, ControllerInputs, Item, Ori, Pos,
},
outcome::Outcome,
time::DayPeriod,
trade::{PendingTrade, TradeAction, TradeResult},
uid::Uid,
uuid::Uuid,
DamageSource, ViewDistances,
ViewDistances,
};
use veloren_common_net::sync::WorldSyncExt;
@ -37,12 +36,10 @@ const COINS: ItemDefinitionId =
const CLIENT_TPS: Duration = Duration::from_millis(33);
const TRADE_ACTION_DELAY: Duration = Duration::from_millis(300);
const ACCOUNCEMENT_DELAY: Duration = Duration::from_mins(45);
const OUCH_DELAY: Duration = Duration::from_secs(2);
/// An active connection to the Veloren server that will attempt to run every time the `tick`
/// function is called.
pub struct Bot {
username: String,
position: Pos,
orientation: Ori,
admins: Vec<String>,
@ -63,7 +60,6 @@ pub struct Bot {
previous_trade_receipt: Option<Reciept>,
last_trade_action: Instant,
last_announcement: Instant,
last_ouch: Instant,
sort_count: u8,
}
@ -140,7 +136,6 @@ impl Bot {
let now = Instant::now();
Ok(Bot {
username,
position,
orientation,
admins,
@ -157,7 +152,6 @@ impl Bot {
previous_trade_receipt: None,
last_trade_action: now,
last_announcement: now,
last_ouch: now,
sort_count: 0,
announcement,
})
@ -284,6 +278,11 @@ impl Bot {
Some(price_correction_message)
}
}
"location" => {
self.send_location_info(&sender)?;
None
}
"ori" => {
if self.is_user_admin(&sender)? {
if let Some(new_rotation) = split_content.next() {
@ -366,36 +365,6 @@ impl Bot {
);
}
}
VelorenEvent::Outcome(Outcome::ProjectileHit {
target: Some(target),
..
}) => {
if let Some(uid) = self.client.uid() {
if uid == target && self.last_ouch.elapsed() > OUCH_DELAY {
self.client
.send_command("say".to_string(), vec!["Ouch!".to_string()]);
self.last_ouch = Instant::now();
}
}
}
VelorenEvent::Outcome(Outcome::HealthChange { info, .. }) => {
if let Some(DamageSource::Buff(_)) = info.cause {
return Ok(true);
}
if let Some(uid) = self.client.uid() {
if uid == info.target
&& info.amount.is_sign_negative()
&& self.last_ouch.elapsed() > OUCH_DELAY
{
self.client
.send_command("say".to_string(), vec!["That hurt!".to_string()]);
self.last_ouch = Instant::now();
}
}
}
VelorenEvent::TradeComplete { result, trade } => {
let my_party = trade
.which_party(self.client.uid().ok_or("Failed to find uid")?)
@ -439,47 +408,46 @@ impl Bot {
Ok(true)
}
fn send_location_info(&mut self, target: &Uid) -> Result<(), String> {
let player_name = self
.find_player_alias(target)
.ok_or("Failed to find player alias")?
.to_string();
let location = self
.client
.sites()
.into_iter()
.find_map(|(_, SiteInfoRich { site, .. })| {
let x_difference = self.position.0[0] - site.wpos[0] as f32;
let y_difference = self.position.0[1] - site.wpos[1] as f32;
if x_difference.abs() < 100.0 && y_difference.abs() < 100.0 {
site.name.clone()
} else {
None
}
})
.unwrap_or(format!("{:?}", self.position));
self.client.send_command(
"tell".to_string(),
vec![player_name, format!("I am at {location}.")],
);
Ok(())
}
/// Make the bot's trading and help accouncements
///
/// Currently, this can make two announcements: one in /region with basic usage instructions
/// is always made. If an announcement was provided when the bot was created, it will make it
/// in /world.
fn handle_announcement(&mut self) -> Result<(), String> {
debug!("Making an announcement");
self.client.send_command(
"region".to_string(),
vec![format!(
"I'm a bot. You can trade with me or check prices: '/tell {} price [search_term]'.",
self.username
)],
);
if let Some(announcement) = &self.announcement {
let announcement = if announcement.contains("{location}") {
let location = self
.client
.sites()
.into_iter()
.find_map(|(_, SiteInfoRich { site, .. })| {
let x_difference = self.position.0[0] - site.wpos[0] as f32;
let y_difference = self.position.0[1] - site.wpos[1] as f32;
if x_difference.abs() < 100.0 && y_difference.abs() < 100.0 {
site.name.clone()
} else {
None
}
})
.unwrap_or(format!("{:?}", self.position));
announcement.replace("{location}", &location)
} else {
announcement.clone()
};
debug!("Making an announcement");
self.client
.send_command("world".to_string(), vec![announcement]);
.send_command("region".to_string(), vec![announcement.to_string()]);
}
Ok(())