Last active
April 8, 2023 21:38
-
-
Save mihaild/731dd7f385b853b610f64624a78bb117 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
const DEFAULT_SESSION_POINTS = 5; | |
const GM_HAS_RESTRICTIONS = true; | |
const DEFAULT_MIN_REPEAT_INTERVAL_SECONDS = 60; | |
function resetPoints() { | |
const players = findObjs({ _type: "player" }); | |
log(state.FunPoints); | |
if (!state.FunPoints) { | |
state.FunPoints = {}; | |
} | |
state.FunPoints.SESSION_POINTS = DEFAULT_SESSION_POINTS; | |
state.FunPoints.MIN_REPEAT_INTERVAL_SECONDS = DEFAULT_MIN_REPEAT_INTERVAL_SECONDS; | |
state.FunPoints.points = {}; | |
state.FunPoints.president = null; | |
if (state.FunPoints.macros) { | |
state.FunPoints.macros.forEach((x) => { getObj("macro", x).remove(); }); | |
} | |
state.FunPoints.macros = []; | |
log(state.FunPoints); | |
var gm_ids = players.map((x) => { return x.id; }).filter(playerIsGM).join(","); | |
var first_gm = gm_ids.split(",")[0]; | |
state.FunPoints.macros.push(createObj("macro", { | |
"name": "display_points", | |
"action": "!points-display", | |
"visibleto": "all", | |
"_playerid": first_gm | |
}).id); | |
state.FunPoints.macros.push(createObj("macro", { | |
"name": "reset_points", | |
"action": "!points-force reset-points", | |
"visibleto": gm_ids, | |
"_playerid": first_gm | |
}).id); | |
players.forEach((player) => { | |
if (!GM_HAS_RESTRICTIONS && playerIsGM(player.id)) { | |
return; | |
} | |
state.FunPoints.points[player.id] = { | |
"points_active": 0, | |
"points_supply": state.FunPoints.SESSION_POINTS, | |
"last_given": {}, | |
} | |
if (GM_HAS_RESTRICTIONS && playerIsGM(player.id)) { | |
return; | |
} | |
state.FunPoints.macros.push(createObj("macro", { | |
"name": "👏" + player.get("_displayname").replace(" ", "_"), | |
"action": "!points-give " + player.id, | |
"visibleto": "all", | |
"_playerid": first_gm | |
}).id); | |
}); | |
sendChat("PointSystem", "Candies reset at " + String(Date())); | |
} | |
function givePoints(msg, target) { | |
const giver = getObj("player", msg.playerid); | |
const receiver = getObj("player", target); | |
if (!receiver) { | |
sendChat("PointSystem", "/w " + msg.who + " " + target + " not found."); | |
return; | |
} | |
log(giver.id + " -> " + receiver.id); | |
if (receiver.id == giver.id) { | |
sendChat("PointSystem", "/w " + msg.who + " can't give candies to yourself."); | |
return; | |
} | |
var p_to = state.FunPoints.points[receiver.id]; | |
if (!p_to) { | |
sendChat("PointSystem", target + " is valid player id, but not registered for candies, this is probably a bug."); | |
return; | |
} | |
if (receiver.id === state.FunPoints.president) { | |
sendChat("PointSystem", "/w " + msg.who + "can't give candies to current leader."); | |
return; | |
} | |
if (GM_HAS_RESTRICTIONS || !playerIsGM(giver.id)) { | |
var p_from = state.FunPoints.points[giver.id]; | |
var n = Date.now(); | |
var diff = (n - p_from.last_given[receiver.id]) / 1000.0; | |
if (p_from.last_given[receiver.id] && diff < state.FunPoints.MIN_REPEAT_INTERVAL_SECONDS) { | |
sendChat("PointSystem", "/w " + msg.who + " you gave candies to " + receiver.get("_displayname") + " " + diff + " seconds ago, wait at least " + state.FunPoints.MIN_REPEAT_INTERVAL_SECONDS); | |
return; | |
} | |
if (p_from.points_supply == 0) { | |
sendChat("PointSystem", "/w " + msg.who + " you are out of candies."); | |
return; | |
} | |
p_from.last_given[receiver.id] = n; | |
p_from.points_supply -= 1; | |
} | |
p_to.points_active += 1; | |
sendChat("player|" + giver.id, "/em gave a candy to " + receiver.get("_displayname") + "."); | |
} | |
function endSession(msg) { | |
showEditor(msg); | |
var best_players = []; | |
var max_points = -1; | |
for (var player_id in state.FunPoints.points) { | |
if (playerIsGM(player_id)) { | |
continue; | |
} | |
var p = state.FunPoints.points[player_id].points_active; | |
if (p > max_points) { | |
max_points = p; | |
best_players = [player_id]; | |
} else if (p == max_points) { | |
best_players.push(player_id); | |
} | |
} | |
function set_president(player_id) { | |
log(player_id); | |
state.FunPoints.president = player_id; | |
state.FunPoints.points[player_id].points_active = 0; | |
sendChat("PointSystem", "Player " + getObj("player", player_id).get("_displayname") + " is the new leader."); | |
for (var player_id in state.FunPoints.points) { | |
state.FunPoints.points[player_id].points_supply = state.FunPoints.SESSION_POINTS; | |
} | |
} | |
if (best_players.length == 1) { | |
sendChat("PointSystem", "Player " + getObj("player", best_players[0]).get("_displayname") + " has " + max_points + " candies."); | |
set_president(best_players[0]); | |
} else { | |
sendChat( | |
"PointSystem", | |
"Players " + best_players.map((x) => { return getObj("player", x).get("_displayname"); }).join(", ") + " have " + max_points | |
+ " candies each." | |
); | |
while (true) { | |
var r = best_players[randomInteger(best_players.length) - 1]; | |
if (state.FunPoints.president != r) { | |
set_president(r); | |
break; | |
} | |
} | |
} | |
} | |
function pointsForce(msg, args) { | |
if (!playerIsGM(msg.playerid)) { | |
sendChat("PointSystem", "/w " + msg.who + " only gm can do this"); | |
return; | |
} | |
if (args[1] == "modify") { | |
var p = state.FunPoints.points[args[3]]; | |
if (!p) { | |
sendChat("PointSystem", "/w " + msg.who + " no such player."); | |
return; | |
} | |
if (args[2] == "active-plus") { | |
p.points_active += 1; | |
} else if (args[2] == "active-minus") { | |
p.points_active -= 1; | |
} else if (args[2] == "supply-plus") { | |
p.points_supply += 1; | |
} else if (args[2] == "supply-minus") { | |
p.points_supply -= 1; | |
} else if (args[2] == "make-president") { | |
state.FunPoints.president = args[3]; | |
} | |
showEditor(msg); | |
return; | |
} | |
if (args[1] == "display-public") { | |
return showEditor(null); | |
} | |
if (args[1] == "end-session" || args[1] == "reset-points") { | |
if (args.length == 2) { | |
var x = String(Date.now()); | |
sendChat("PointSystem", "/w " + msg.who + " are you sure? <a href='!points-force " + args[1] + " " + x +"'>YES</a>", null, {noarchive: true}); | |
state.FunPoints.idempotency_key = x; | |
return; | |
} else if (state.FunPoints.idempotency_key != args[2] || parseInt(args[2]) + 60000 < Date.now()) { | |
sendChat("PointSystem", "/w " + msg.who + " wrong idempotency key. Try reuse interface again.", null, {noarchive: true}); | |
state.FunPoints.idempotency_key = null; | |
return; | |
} else { | |
state.FunPoints.idempotency_key = null; | |
if (args[1] == "end-session") { | |
return endSession(); | |
} else if (args[1] == "reset-points") { | |
return resetPoints(); | |
} | |
return; | |
} | |
} | |
if (args[1] == "modify-settings") { | |
if (args[2] == "points") { | |
if (args[3] == "plus") { | |
++state.FunPoints.SESSION_POINTS; | |
} else { | |
++state.FunPoints.SESSION_POINTS; | |
} | |
} else if (args[2] == "time") { | |
if (args[3] == "plus") { | |
state.FunPoints.MIN_REPEAT_INTERVAL_SECONDS += 60; | |
} else { | |
state.FunPoints.MIN_REPEAT_INTERVAL_SECONDS -= 60; | |
} | |
} | |
showEditor(msg); | |
return; | |
} | |
} | |
function showEditor(msg) { | |
var response = "<table><tr><th style='width: 30%;'>Player</th><th style='width: 30%;'>Candies</th><th style='width: 30%;'>Supply</th><th style='width: 30%;'>Leader</th></tr>"; | |
var is_gm = msg && playerIsGM(msg.playerid); | |
if (is_gm) { | |
response = "Points per session: " + state.FunPoints.SESSION_POINTS | |
+ "<a href='!points-force modify-settings points plus'>+</a>" | |
+ "<a href='!points-force modify-settings points minus'>-</a>" | |
+ "<br />" + "Min interval: " + state.FunPoints.MIN_REPEAT_INTERVAL_SECONDS | |
+ "<a href='!points-force modify-settings time plus'>+</a>" | |
+ "<a href='!points-force modify-settings time minus'>-</a>" | |
+ "<br />" | |
+ response; | |
} | |
for (var player_id in state.FunPoints.points) { | |
var p = state.FunPoints.points[player_id]; | |
var player = getObj("player", player_id); | |
response += "<tr>"; | |
if (player_id == state.FunPoints.president) { | |
response += "<td><b>" + player.get("_displayname") + "</b></td>"; | |
} else { | |
response += "<td>" + player.get("_displayname") + "</td>"; | |
} | |
response += "<td>" + p.points_active; | |
if (is_gm) { | |
response += "<a href='!points-force modify active-plus " + player_id + "'>+</a>" | |
+ "<a href='!points-force modify active-minus " + player_id + "'>-</a>"; | |
} | |
response += "</td>"; | |
response += "<td>" + p.points_supply; | |
if (is_gm) { | |
response += "<a href='!points-force modify supply-plus " + player_id + "'>+</a>" | |
+ "<a href='!points-force modify supply-minus " + player_id + "'>-</a>"; | |
} | |
response += "</td>"; | |
if (state.FunPoints.president != player_id) { | |
if (is_gm) { | |
response += "<td>" + "<a href='!points-force modify make-president " + player_id + "'>make</a></td>"; | |
} else { | |
response += "<td></td>"; | |
} | |
} else { | |
response += "<td>+</td>"; | |
} | |
response += "</tr>"; | |
}; | |
response += "</table>"; | |
if (is_gm) { | |
response += "<a href='!points-force display-public'>Display</a><br />"; | |
response += "<a href='!points-force end-session'>End session</a><br />"; | |
//response += "<a href='!points-force reset-points'>Reset all</a><br />"; | |
} | |
if (msg) { | |
sendChat("PointSystem", "/w " + msg.who + " " + response, null, {noarchive: true}); | |
} else { | |
sendChat("PointSystem", response); | |
} | |
} | |
function handleApiCommands(msg) { | |
if (msg.type !== "api") return; | |
const args = msg.content.split(" "); | |
const command = args[0]; | |
if (command == "!points-display") { | |
return showEditor(msg); | |
} else if (command == "!points-force") { | |
return pointsForce(msg, args); | |
} else if (command == "!points-give") { | |
return givePoints(msg, msg.content.substring(msg.content.indexOf(' ')+1)); | |
} | |
} | |
on("ready", () => { | |
on("chat:message", handleApiCommands); | |
if (!state.FunPoints) { | |
resetPoints(); | |
} | |
log(state.FunPoints); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment