-
Notifications
You must be signed in to change notification settings - Fork 0
Milestones
Three related systems that fire when a player crosses a multiplier threshold:
- Milestone commands - run console commands on tier-up (keys, titles, broadcasts, ...).
- Threshold scaling - donor ranks unlock tiers earlier via permission nodes.
- Discord webhooks - announce milestones to a channel, as a classic embed or a Components V2 message.
All of it lives in config.yml and reloads with /pm reload.
Every milestone command and every Discord text field accepts:
| Placeholder | Value |
|---|---|
{player} |
Player name |
{uuid} |
Player UUID (handy for avatar services) |
{name} |
The ladder's display name (group display name, or item name) |
{item} |
Item name, e.g. Gold Ingot
|
{item_raw} |
Bukkit material name, e.g. GOLD_INGOT
|
{group} |
Group display name (empty on item ladders) |
{ladder} |
item or group
|
{tier} / {tiers}
|
Tier number reached / total tiers in the ladder |
{threshold} |
The threshold that was crossed (after scaling) |
{threshold_formatted} |
Same, with thousands separators |
{total} / {total_formatted}
|
The player's new sold total on that ladder |
{multiplier} |
The multiplier unlocked, e.g. 1.25
|
Commands are run by the console, on the main thread, at the moment the tier is crossed. A bulk sale that jumps several tiers at once fires each crossed tier in order.
milestones:
commands:
on-tier:
- "crates give {player} key vote 1"
- "broadcast &6{player} &ereached &b{multiplier}x &eon &b{name}&e!"
on-max-tier:
- "lp user {player} permission set rank.grinder true"
- "titles give {player} grinder"-
on-tierruns for every tier a player unlocks, on any ladder. -
on-max-tieradditionally runs when the unlocked tier is the final tier of its ladder. - Empty lists disable them. No extra toggle needed.
Any group or items ladder can carry its own milestones block - it fires for that ladder
only, without repeating commands on every tier:
items:
DIAMOND:
tiers:
- threshold: 20
multiplier: 1.1
- threshold: 100
multiplier: 1.5
milestones:
on-tier:
- "say {player} stepped up their Diamond game ({tier}/{tiers})"
on-max-tier:
- "crates give {player} key diamond 1"
groups:
crops:
tiers:
- threshold: 10000
multiplier: 1.1
- threshold: 1000000
multiplier: 1.3
milestones:
on-max-tier:
- "broadcast &a{player} mastered Crops!"
- "lp user {player} permission set titles.farmer true"For tier-specific rewards, any single tier can also carry a commands list:
groups:
crops:
tiers:
- threshold: 1000000
multiplier: 1.3
commands:
- "broadcast &a{player} sold a MILLION crops!"All matching lists run, in this order: the tier's own commands, the ladder's
milestones.on-tier (and on-max-tier if it is the final tier), then the global
milestones.commands lists.
The single-threshold default ladder (unlisted items) does not fire milestones unless
you set milestones.include-default-ladder: true - it counts as a 1-tier ladder, so every
crossing would be a "max tier", which gets noisy fast.
Let ranked players unlock tiers with fewer lifetime sales. scale multiplies every
threshold: 0.8 means 20% less is needed. When a player matches several ranks, the
lowest scale wins. Values above 1.0 are allowed (harder, not easier).
threshold-scaling:
enabled: true
ranks:
vip:
permission: profitmultiplier.scale.vip
scale: 0.8
mvp:
permission: profitmultiplier.scale.mvp
scale: 0.65Grant the permission node through your permissions plugin (LuckPerms etc.). The node names are free-form - define whatever fits your rank layout.
Scaling applies everywhere consistently: the sale boost itself, threshold-reached messages,
milestone commands, Discord announcements, /pm stats, menu progress bars, and
PlaceholderAPI values (for online players). The Developer API reports
unscaled base values.
milestones:
discord:
enabled: true
webhook-url: "https://discord.com/api/webhooks/..."
username: "ProfitMultiplier"
avatar-url: ""
announce: max-tier # max-tier or every-tier
style: embed # embed or components-v2| Key | Meaning |
|---|---|
webhook-url |
The webhook URL from your Discord channel settings. |
username / avatar-url
|
Optional overrides for the webhook's name and avatar. |
announce |
max-tier (default) posts only final-tier milestones; every-tier posts all. |
style |
embed for a classic rich embed, components-v2 for the new component layout. |
Webhook requests are sent asynchronously - they never block the server thread.
embed:
title: "🏆 Milestone reached!"
description: "**{player}** unlocked **{multiplier}x** on **{name}**!"
color: "#FFD700"
thumbnail: "https://mc-heads.net/avatar/{uuid}"
footer: "ProfitMultiplier"
timestamp: true
fields:
- name: "Tier"
value: "{tier}/{tiers}"
inline: true
- name: "Total sold"
value: "{total_formatted}"
inline: trueEvery key is optional. color accepts #RRGGBB, 0xRRGGBB, or a decimal integer.
Discord markdown works in description and field values.
Uses Discord's Components V2
message layout (sent with the IS_COMPONENTS_V2 flag and with_components=true). The
message is one container (with optional accent-color) holding your components in
order:
style: components-v2
components-v2:
accent-color: "#FFD700"
components:
- type: section
text: "## 🏆 Milestone reached\n**{player}** unlocked **{multiplier}x** on **{name}**"
thumbnail: "https://mc-heads.net/avatar/{uuid}"
- type: separator
- type: text
text: "-# Tier {tier}/{tiers} • Total sold: {total_formatted}"
- type: image
url: "https://example.com/banner.png"| Component | Keys | Renders as |
|---|---|---|
text |
text |
A text display (Discord markdown, \n for line breaks). |
section |
text, thumbnail
|
Text with a thumbnail accessory on the right. Without thumbnail it falls back to plain text. |
separator |
divider (default true), spacing (small/large) |
A horizontal divider / spacing gap. |
image |
url |
A full-width image (media gallery). |
Components V2 is supported by regular channel webhooks - no bot application needed. Interactive components (buttons, selects) are not available to plain webhooks, so they are intentionally not offered here.
- Nothing posts to Discord: check the console for
Discord webhook returned HTTP ...warnings - the body of the warning includes Discord's error message. - Commands don't run: they execute as console - test them in the console first, and
remember placeholders like
{player}are replaced before dispatch. - A player tier-ups twice after a reset: milestones fire on crossing a threshold, so
after
/pm resetthe progression (and its milestones) starts over by design.
ProfitMultiplier by DocDrewskii - Repository - Issues - Developer API
Getting started
Configuration
- Overview
- Items
- Groups
- Stacking Multipliers
- Custom Currencies
- Milestones & Discord
- Auto-Reset
- Messages (lang.yml)
Shops
Menus (GUI)
Placeholders
Developers
Help