第九批:邀请系统计数修复+绑定显示邀请人+双向奖励+配置懒更新
1. 计数修复:monthly_invite_count 改为绑定邀请码时由 onInviteeBind 计入 (旧逻辑在被邀请人签到才计数,导致绑定成功但未签到时 GUI 恒显示已邀请0人); onInviteeCheckIn 清空计数逻辑避免重复累加。 2. B端显示:新增 invited_at 列(毫秒时间戳落库),邀请数据GUI slot16 已绑定时改显示「邀请成功时间(yyyy-MM-dd HH:mm)+邀请人名字」, 未绑定才显示输入邀请码按钮;点击已绑定则拦截。 3. 双向奖励:CommissionManager 适配新规则md 4键(邀请人单次奖励/ 被邀请人单次奖励/单日邀请奖励上限/单日邀请翻倍额度); payInviteBond 给邀请人(含每邀请X人翻Y倍)、payInviteeBond 给被邀请人。 4. 配置懒更新:玩家绑定邀请码时调用 loadRules() 实时重载规则md, 不再依赖启动加载或定时热重载。
This commit is contained in:
@@ -662,15 +662,35 @@ public class ChatInputManager {
|
||||
u.get("player_name");
|
||||
db.setField(myName,
|
||||
"invited_by", inv);
|
||||
// ★ 第九批:绑定时间落库(供邀请GUI显示
|
||||
// 「邀请成功时间+邀请人」)
|
||||
db.setField(myName, "invited_at",
|
||||
System.currentTimeMillis());
|
||||
// ★ 第九批(配置懒更新):玩家绑定邀请码时
|
||||
// 自动重载 规则.md,实时刷新奖励信息
|
||||
// (不再依赖启动加载或定时热重载)
|
||||
mainPlugin.getCommission().loadRules();
|
||||
// ★ 第九批:绑定即计入邀请人「本月邀请」
|
||||
// (修复旧逻辑在签到才计数导致恒 0 人)
|
||||
mainPlugin.getInvite().onInviteeBind(
|
||||
inv, myName);
|
||||
// ★ 第八批(2026-10-12):绑定奖励改按
|
||||
// 邀请好友赢债券/规则.md 发债券;
|
||||
// 旧 addPoints(inv,50) 积分随提成规则体系废弃
|
||||
// ★ 第九批:奖励单向改双向——邀请人 + 被邀请人
|
||||
int bondGive = mainPlugin
|
||||
.getCommission()
|
||||
.payInviteBond(inv, myName);
|
||||
p.sendMessage(
|
||||
"§a邀请成功!邀请人: "
|
||||
+ inv);
|
||||
int bondGet = mainPlugin
|
||||
.getCommission()
|
||||
.payInviteeBond(myName, inv);
|
||||
String bMsg =
|
||||
"§a邀请成功!邀请人: " + inv;
|
||||
if (bondGet > 0) {
|
||||
bMsg += "§7,你获得 §e" + bondGet
|
||||
+ " §a债券";
|
||||
}
|
||||
p.sendMessage(bMsg);
|
||||
Player ip =
|
||||
Bukkit.getPlayerExact(inv);
|
||||
if (ip != null
|
||||
|
||||
@@ -7,27 +7,38 @@ import java.sql.ResultSet;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 邀请好友赢债券奖励(配置:邀请好友赢债券/规则.md)。
|
||||
*
|
||||
* <p>★ 2026-10-12 第八批(用户决策):旧「提成规则.txt」(邀请人数:提成百分比)
|
||||
* 体系整体废弃——其 payCommission 因 Economy 移除早已是无调用死代码,
|
||||
* 签到链路奖励计算 (int)(1*rate) 恒为 0 从未生效(「邀请好友无效」根因)。
|
||||
* 代码层面删除旧 txt(启动时清理而非 SFTP 手删——否则 writeDefault
|
||||
* 会再次释放,写文件逻辑已一并移除),奖励改由新 md 规则控制:
|
||||
* 绑定邀请码成功时立即结算债券,受「单次邀请奖励上限」「单日邀请奖励上限」
|
||||
* 双重限制(当日累计按 bond_transaction type='invite_reward' 汇总,自然日重置)。</p>
|
||||
* <p>★ 2026-10-12 第八批(用户决策):旧「提成规则.txt」体系整体废弃,
|
||||
* 奖励改由新 md 规则控制,绑定邀请码成功时立即结算债券。</p>
|
||||
*
|
||||
* <p>★ 2026-10-12 第九批(用户需求)三点改造:
|
||||
* ① 解析键改用新 md 4 键(旧「单次邀请奖励上限」→「邀请人单次奖励」),
|
||||
* 新增「被邀请人单次奖励」「单日邀请翻倍额度」;
|
||||
* ② 奖励单向改<b>双向</b>——payInviteBond 给邀请人、payInviteeBond 给被邀请人;
|
||||
* 翻倍额度作用于邀请人(每邀请 X 人,奖金翻 Y 倍);
|
||||
* ③ 支持<b>懒更新</b>——玩家绑定邀请码时调用 loadRules() 实时重载规则,
|
||||
* 不再依赖启动时一次性加载或定时热重载。</p>
|
||||
*/
|
||||
public class CommissionManager {
|
||||
|
||||
private final Main main;
|
||||
private final Logger logger;
|
||||
|
||||
/** 单次邀请奖励(债券数,绑定成功立即结算) */
|
||||
/** 邀请人单次奖励(债券数,绑定成功立即结算) */
|
||||
private volatile int perInviteReward = 10;
|
||||
/** 单日邀请奖励上限(债券数,自然日重置) */
|
||||
/** 被邀请人单次奖励(债券数,绑定成功立即结算) */
|
||||
private volatile int perInviteeReward = 5;
|
||||
/** 单日邀请奖励上限(债券数,自然日重置,仅针对邀请人) */
|
||||
private volatile int dailyInviteCap = 100;
|
||||
/** 单日邀请翻倍额度:每邀请 X 人(>0 生效,0=关闭翻倍) */
|
||||
private volatile int doubleEveryX = 0;
|
||||
/** 单日邀请翻倍额度:奖金翻 Y 倍(翻 Y 倍 = 每满 X 人基数加 Y 倍) */
|
||||
private volatile int doubleByY = 0;
|
||||
|
||||
public CommissionManager(Main main) {
|
||||
this.main = main;
|
||||
@@ -35,6 +46,9 @@ public class CommissionManager {
|
||||
loadRules();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重载规则(★ 第九批:绑定邀请码时懒调用,实时刷新奖励信息)。
|
||||
*/
|
||||
public void loadRules() {
|
||||
// ★ 代码层面删除旧提成规则.txt(手删会被再次释放,故写文件
|
||||
// 逻辑已移除,这里负责清理存量文件)
|
||||
@@ -58,7 +72,8 @@ public class CommissionManager {
|
||||
}
|
||||
if (!f.exists()) {
|
||||
logger.warning("[Commission] 规则文件缺失,使用默认值"
|
||||
+ " 单次=" + perInviteReward
|
||||
+ " 邀请人=" + perInviteReward
|
||||
+ " 被邀请人=" + perInviteeReward
|
||||
+ " 单日=" + dailyInviteCap);
|
||||
return;
|
||||
}
|
||||
@@ -85,22 +100,52 @@ public class CommissionManager {
|
||||
String key = cols[1].trim();
|
||||
String val = cols[cols.length - 2].trim()
|
||||
.replace("`", "");
|
||||
if ("单次邀请奖励上限".equals(key)) {
|
||||
// ★ 第九批:适配新 md 4 键
|
||||
if ("邀请人单次奖励".equals(key)) {
|
||||
perInviteReward = parseIntSafe(val,
|
||||
perInviteReward);
|
||||
} else if ("被邀请人单次奖励".equals(key)) {
|
||||
perInviteeReward = parseIntSafe(val,
|
||||
perInviteeReward);
|
||||
} else if ("单日邀请奖励上限".equals(key)) {
|
||||
dailyInviteCap = parseIntSafe(val,
|
||||
dailyInviteCap);
|
||||
} else if ("单日邀请翻倍额度".equals(key)) {
|
||||
parseDoubleRule(val);
|
||||
}
|
||||
}
|
||||
logger.info("[Commission] 邀请债券规则: 单次="
|
||||
+ perInviteReward + " 单日=" + dailyInviteCap);
|
||||
logger.info("[Commission] 邀请债券规则: 邀请人="
|
||||
+ perInviteReward
|
||||
+ " 被邀请人=" + perInviteeReward
|
||||
+ " 单日=" + dailyInviteCap
|
||||
+ " 翻倍=" + (doubleEveryX > 0
|
||||
? ("每" + doubleEveryX + "人翻"
|
||||
+ doubleByY + "倍")
|
||||
: "关闭"));
|
||||
} catch (Exception e) {
|
||||
logger.warning("[Commission] 规则解析失败: "
|
||||
+ e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** 解析「每邀请X人,奖金翻Y倍」格式 */
|
||||
private void parseDoubleRule(String v) {
|
||||
// 默认关闭
|
||||
doubleEveryX = 0;
|
||||
doubleByY = 0;
|
||||
if (v == null) return;
|
||||
Matcher m = Pattern.compile(
|
||||
"每邀请\\s*(\\d+)\\s*人\\s*[,,]\\s*奖金翻\\s*(\\d+)\\s*倍")
|
||||
.matcher(v);
|
||||
if (m.find()) {
|
||||
doubleEveryX = parseIntSafe(m.group(1), 0);
|
||||
doubleByY = parseIntSafe(m.group(2), 0);
|
||||
} else {
|
||||
logger.warning("[Commission] 翻倍额度格式无法解析: "
|
||||
+ v + "(示例:每邀请2人,奖金翻1倍)");
|
||||
}
|
||||
}
|
||||
|
||||
private static int parseIntSafe(String s, int def) {
|
||||
try {
|
||||
return (int) Double.parseDouble(s.trim());
|
||||
@@ -109,19 +154,24 @@ public class CommissionManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** 单次邀请奖励(债券) */
|
||||
/** 邀请人单次奖励(债券) */
|
||||
public int getPerInviteReward() {
|
||||
return perInviteReward;
|
||||
}
|
||||
|
||||
/** 被邀请人单次奖励(债券) */
|
||||
public int getPerInviteeReward() {
|
||||
return perInviteeReward;
|
||||
}
|
||||
|
||||
/** 单日邀请奖励上限(债券) */
|
||||
public int getDailyInviteCap() {
|
||||
return dailyInviteCap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请绑定成功 → 给邀请人发债券。
|
||||
* 规则见 邀请好友赢债券/规则.md:每次按单次上限结算,
|
||||
* 邀请绑定成功 → 给<b>邀请人</b>发债券(★ 第九批:含翻倍额度)。
|
||||
* 规则见 邀请好友赢债券/规则.md:每次按单次上限结算(每满 X 人翻 Y 倍),
|
||||
* 当日累计不超单日上限。
|
||||
*
|
||||
* @param inviter 邀请人(收款方)
|
||||
@@ -139,18 +189,51 @@ public class CommissionManager {
|
||||
+ " 今日邀请债券已达上限(" + dailyInviteCap + ")");
|
||||
return 0;
|
||||
}
|
||||
int give = Math.min(perInviteReward, room);
|
||||
// ★ 第九批:单日邀请翻倍额度——每邀请 X 人,奖金翻 Y 倍
|
||||
// nToday = 今日已发放的邀请奖励笔数(≈已成功邀请人数)
|
||||
// mult = 1 + (nToday / X) * Y(整数除法,每满 X 人加 Y 倍)
|
||||
int nToday = inviteBondCountToday(inviter);
|
||||
int mult = 1;
|
||||
if (doubleEveryX > 0) {
|
||||
mult = 1 + (nToday / doubleEveryX) * doubleByY;
|
||||
if (mult < 1) mult = 1;
|
||||
}
|
||||
int base = perInviteReward * mult;
|
||||
int give = Math.min(base, room);
|
||||
int after = main.getBonds().addBonds(inviter, give,
|
||||
"invite_reward", invitee, "system",
|
||||
"邀请好友绑定奖励(" + invitee + ")");
|
||||
if (after < 0) return -1; // 冻结期未入账
|
||||
logger.info("[Commission] 邀请债券: " + inviter + " ← "
|
||||
+ invitee + " | +" + give + "(今日累计 "
|
||||
+ invitee + " | +" + give + "(基数"
|
||||
+ perInviteReward + "×" + mult + ",今日累计 "
|
||||
+ (used + give) + "/" + dailyInviteCap + ")");
|
||||
return give;
|
||||
}
|
||||
|
||||
/** 今日 0 点起该玩家已发放的邀请债券总数 */
|
||||
/**
|
||||
* 邀请绑定成功 → 给<b>被邀请人</b>发债券(★ 第九批:双向奖励)。
|
||||
* 被邀请人奖励为固定单次数额,不受单日上限约束(上限仅针对邀请人)。
|
||||
*
|
||||
* @param invitee 被邀请人(绑定者,收款方)
|
||||
* @param inviter 邀请人(被邀请人的邀请来源)
|
||||
* @return >0 实发债券数;0 = 规则为0;-1 = 异常/冻结未发
|
||||
*/
|
||||
public int payInviteeBond(String invitee, String inviter) {
|
||||
if (invitee == null || invitee.isEmpty()) return -1;
|
||||
if (perInviteeReward <= 0) return 0;
|
||||
// 用独立 type='invitee_reward',避免污染邀请人日上限统计
|
||||
int after = main.getBonds().addBonds(invitee,
|
||||
perInviteeReward, "invitee_reward", inviter,
|
||||
"system",
|
||||
"被邀请人绑定奖励(邀请人:" + inviter + ")");
|
||||
if (after < 0) return -1; // 冻结期未入账
|
||||
logger.info("[Commission] 被邀请人债券: " + invitee
|
||||
+ " ← " + inviter + " | +" + perInviteeReward);
|
||||
return perInviteeReward;
|
||||
}
|
||||
|
||||
/** 今日 0 点起该玩家已发放的邀请债券总数(金额) */
|
||||
private int inviteBondToday(String inviter) {
|
||||
long dayStart = LocalDate.now()
|
||||
.atStartOfDay(ZoneId.systemDefault())
|
||||
@@ -177,6 +260,33 @@ public class CommissionManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** 今日 0 点起该玩家已成功邀请人数(发奖笔数,用于翻倍档位) */
|
||||
private int inviteBondCountToday(String inviter) {
|
||||
long dayStart = LocalDate.now()
|
||||
.atStartOfDay(ZoneId.systemDefault())
|
||||
.toInstant().toEpochMilli();
|
||||
try {
|
||||
PreparedStatement ps = main.getDb()
|
||||
.getConnection().prepareStatement(
|
||||
"SELECT COUNT(*) "
|
||||
+ "FROM bond_transaction "
|
||||
+ "WHERE player_name=? "
|
||||
+ "AND type='invite_reward' "
|
||||
+ "AND time>=?");
|
||||
ps.setString(1, inviter);
|
||||
ps.setLong(2, dayStart);
|
||||
ResultSet rs = ps.executeQuery();
|
||||
int v = rs.next() ? rs.getInt(1) : 0;
|
||||
rs.close();
|
||||
ps.close();
|
||||
return v;
|
||||
} catch (Exception e) {
|
||||
logger.warning("[Commission] 查询当日邀请人数失败: "
|
||||
+ e.getMessage());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断金额是否包含经济内容
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,7 @@ public class DatabaseManager {
|
||||
+ "gift_claimed TEXT DEFAULT '',"
|
||||
+ "invite_code TEXT DEFAULT '',"
|
||||
+ "invited_by TEXT DEFAULT '',"
|
||||
+ "invited_at INTEGER DEFAULT 0,"
|
||||
+ "monthly_invite_count INTEGER DEFAULT 0,"
|
||||
+ "invite_month TEXT DEFAULT '',"
|
||||
+ "points INTEGER DEFAULT 0,"
|
||||
@@ -92,6 +93,10 @@ public class DatabaseManager {
|
||||
"TEXT DEFAULT ''");
|
||||
safeAdd(st, "last_login_ip",
|
||||
"TEXT DEFAULT ''");
|
||||
// ★ 第九批:邀请绑定时间(毫秒时间戳),
|
||||
// 供「我的邀请码」GUI 显示邀请成功时间
|
||||
safeAdd(st, "invited_at",
|
||||
"INTEGER DEFAULT 0");
|
||||
// UI偏好:1=CLI(默认), 0=GUI
|
||||
safeAdd(st, "ui_mode",
|
||||
"INTEGER DEFAULT 1");
|
||||
|
||||
@@ -2431,11 +2431,31 @@ public class GUIManager implements Listener {
|
||||
g.setItem(12, mkItem(Material.PLAYER_HEAD,
|
||||
"§a本月邀请",
|
||||
"§7已邀请 §e" + monthly + " §7人"));
|
||||
g.setItem(16, mkItem(Material.BOOK,
|
||||
"§e输入邀请码",
|
||||
"§7绑定他人的邀请码",
|
||||
"",
|
||||
"§e点击输入"));
|
||||
// ★ 第九批:已绑定邀请人则显示「邀请成功时间+邀请人」,
|
||||
// 否则显示「输入邀请码」按钮
|
||||
String invitedBy = (String) plugin.getDb()
|
||||
.getField(p.getName(), "invited_by");
|
||||
if (invitedBy != null && !invitedBy.isEmpty()) {
|
||||
Object tsObj = plugin.getDb().getField(
|
||||
p.getName(), "invited_at");
|
||||
long ts = (tsObj instanceof Number)
|
||||
? ((Number) tsObj).longValue() : 0L;
|
||||
String timeStr = ts > 0
|
||||
? new java.text.SimpleDateFormat(
|
||||
"yyyy-MM-dd HH:mm")
|
||||
.format(new java.util.Date(ts))
|
||||
: "未知";
|
||||
g.setItem(16, mkItem(Material.WRITTEN_BOOK,
|
||||
"§a邀请已绑定",
|
||||
"§7邀请人: §e" + invitedBy,
|
||||
"§7绑定时间: §e" + timeStr));
|
||||
} else {
|
||||
g.setItem(16, mkItem(Material.BOOK,
|
||||
"§e输入邀请码",
|
||||
"§7绑定他人的邀请码",
|
||||
"",
|
||||
"§e点击输入"));
|
||||
}
|
||||
String ugLabel = "§7(玩家)";
|
||||
UserGroupManager.UserGroupConfig ugCfg =
|
||||
plugin.getUserGroup().getHighestGroup(p.getName());
|
||||
|
||||
@@ -21,37 +21,51 @@ public class InviteManager {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void onInviteeCheckIn(String inviteeName) {
|
||||
String invitedBy = (String) plugin.getDb()
|
||||
.getField(inviteeName, "invited_by");
|
||||
if (invitedBy == null || invitedBy.isEmpty())
|
||||
return;
|
||||
/**
|
||||
* ★ 第九批(2026-10-12):绑定邀请码成功时立即计入邀请人
|
||||
* 「本月邀请」计数(带月度重置)。
|
||||
*
|
||||
* <p>旧逻辑把计数放在 onInviteeCheckIn(被邀请人签到)里,
|
||||
* 导致「绑定成功但未签到」时 GUI 恒显示「已邀请 0 人」(用户反馈
|
||||
* 的计数 bug 根因)。现改为绑定即计数——绑定才是「邀请成功」
|
||||
* 的真正时点,与债券发放同一时机,语义一致。</p>
|
||||
*
|
||||
* @param inviter 邀请人(被计数方)
|
||||
* @param invitee 被邀请人(绑定者)
|
||||
*/
|
||||
public void onInviteeBind(String inviter, String invitee) {
|
||||
if (inviter == null || inviter.isEmpty()) return;
|
||||
|
||||
String month = new SimpleDateFormat("yyyy-MM")
|
||||
.format(new Date());
|
||||
String lastMonth = (String) plugin.getDb()
|
||||
.getField(invitedBy, "invite_month");
|
||||
.getField(inviter, "invite_month");
|
||||
|
||||
if (!month.equals(lastMonth)) {
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "invite_month", month);
|
||||
inviter, "invite_month", month);
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "monthly_invite_count", 0);
|
||||
inviter, "monthly_invite_count", 0);
|
||||
}
|
||||
|
||||
int count = ((Number) plugin.getDb()
|
||||
.getField(invitedBy,
|
||||
.getField(inviter,
|
||||
"monthly_invite_count"))
|
||||
.intValue();
|
||||
plugin.getDb().setField(
|
||||
invitedBy, "monthly_invite_count",
|
||||
inviter, "monthly_invite_count",
|
||||
count + 1);
|
||||
}
|
||||
|
||||
// ★ 第八批(2026-10-12):旧「签到给邀请人积分提成」废弃——
|
||||
// 原 bonus=(int)(1*rate) 恒为 0(rate 最大 0.60,截断后为 0),
|
||||
// 奖励从未实际发放,即用户反馈「邀请好友无效」的根因;
|
||||
// 邀请奖励统一在绑定邀请码时按 邀请好友赢债券/规则.md 发债券
|
||||
// (CommissionManager.payInviteBond)。此处只保留月度邀请计数。
|
||||
/**
|
||||
* ★ 第九批:签到链路不再重复计数——「本月邀请」计数已在
|
||||
* 绑定邀请码时由 onInviteeBind 完成(见上)。若此处再 +1,
|
||||
* 同一被邀请人每签到一次都会重复累加,造成计数虚高。
|
||||
* 方法保留以兼容既有三处签到调用点(Main.dailySign 等),
|
||||
* 但已清空计数逻辑。
|
||||
*/
|
||||
public void onInviteeCheckIn(String inviteeName) {
|
||||
// 计数已迁移至 onInviteeBind(绑定时),签到不再计数
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getAllInviteData() {
|
||||
|
||||
@@ -7256,11 +7256,21 @@ public class Main extends JavaPlugin
|
||||
p.sendMessage("§e邀请码: " + code);
|
||||
gui.openInvite(p);
|
||||
} else if (slot == 16) {
|
||||
chatInput.getState(p).type =
|
||||
ChatInputManager.InputType
|
||||
.INVITE_INPUT_CODE;
|
||||
p.closeInventory();
|
||||
p.sendMessage("§e请输入邀请码:");
|
||||
// ★ 第九批:已绑定邀请人则拦截,不再进入输入
|
||||
Object boundInvite = db.getField(
|
||||
p.getName(), "invited_by");
|
||||
if (boundInvite != null && !boundInvite
|
||||
.toString().isEmpty()) {
|
||||
p.sendMessage("§c你已绑定邀请人("
|
||||
+ boundInvite
|
||||
+ "),邀请码仅能使用一次");
|
||||
} else {
|
||||
chatInput.getState(p).type =
|
||||
ChatInputManager.InputType
|
||||
.INVITE_INPUT_CODE;
|
||||
p.closeInventory();
|
||||
p.sendMessage("§e请输入邀请码:");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
# 邀好友赢债券活动配置
|
||||
|
||||
## ----配置区开始----
|
||||
|
||||
| 键 | 解释说明 | 值 |
|
||||
|:---|:---|:---:|
|
||||
| 单次邀请奖励上限 | 单个玩家每次成功邀请一位好友时,**立即结算**可获得的债券数量上限。支持小数或整数,填写纯数字即可,单位默认为"个"。适用于"马上邀、马上结账"的场景。 | `10` |
|
||||
| 单日邀请奖励上限 | 单个玩家在**一天内**通过邀请好友累计可领取的债券最大总数。超出后当日不再发放奖励,次日自动重置。适合控制薅羊毛行为。 | `100` |
|
||||
| 项目 | 解释 | 值 |
|
||||
| :---: | :---: | :---: |
|
||||
| 邀请人单次奖励 | 邀请人每次成功邀请一位好友后,立即结算获得的债券数量。数值填写为纯数字,单位默认为"个"。适用于"马上邀、马上结账"的场景。 | 10 |
|
||||
| 被邀请人单次奖励 | 被邀请人在注册并首次上线后,立即结算获得的债券数量。数值填写为纯数字,用于吸引新玩家加入。 | 5 |
|
||||
| 单日邀请奖励上限 | 单个邀请人在**一天内**通过邀请好友累计可获得的债券总数上限。达到上限后当日不再发放奖励,次日自动重置。适合控制薅羊毛行为。 | 100 |
|
||||
| 单日邀请翻倍额度 | 拉了多少个人以后,给邀请人的奖励。参数值为:"每邀请X人,奖金翻Y倍" | 每邀请2人,奖金翻1倍 |
|
||||
|
||||
## ----配置区域结束----
|
||||
|
||||
## 邀好友赢债券活动说明书
|
||||
- 什么是邀好友赢债券:玩家通过邀请新玩家加入服务器,完成任务后获得债券奖励,激励玩家拉新。<br>
|
||||
- 两种上限的区别:
|
||||
- **单次邀请奖励上限**:每次邀请成功结算时的单次奖励额度,不会累积
|
||||
- **单日邀请奖励上限**:当天所有邀请累计的总奖励上限,达到后当天不再发奖
|
||||
## 邀好友赢债券说明书
|
||||
- 什么是邀好友赢债券:玩家邀请新玩家加入服务器,双方完成任务后分别获得债券奖励,激励玩家拉新。<br>
|
||||
- 三种配置的区别:
|
||||
- **邀请人单次奖励**:每次成功邀请后,邀请人立即获得的债券数,不累积
|
||||
- **被邀请人单次奖励**:被邀请人注册并首次上线后,自己立即获得的债券数
|
||||
- **单日邀请奖励上限**:邀请人一天内累计获得的总奖励上限(仅针对邀请人),达到后当日停止发放,次日重置
|
||||
- 计算公式示例:
|
||||
- 单次邀请奖励上限 = 5,单人当天邀请 3 人 → 累计获得 5 × 3 = 15 债券
|
||||
- 单日邀请奖励上限 = 30,单人当天邀请 7 人 → 理论应得 5 × 7 = 35,但被单日上限卡住,实际获得 30 债券,当日不再发放
|
||||
- 邀请人单次奖励 = 10,单人当天邀请 3 人 → 累计获得 10 × 3 = **30 债券**(未超单日上限)
|
||||
- 邀请人单次奖励 = 10,单人当天邀请 11 人 → 理论应得 10 × 11 = 110,但被单日上限卡住,实际获得 **100 债券**,当日不再发放
|
||||
- 被邀请人单次奖励 = 5,新玩家注册首次上线 → 立即获得 **5 债券**
|
||||
|
||||
|
||||
Reference in New Issue
Block a user