Skip to content

Instantly share code, notes, and snippets.

@mihaild
Last active April 8, 2023 21:38
Show Gist options
  • Save mihaild/731dd7f385b853b610f64624a78bb117 to your computer and use it in GitHub Desktop.
Save mihaild/731dd7f385b853b610f64624a78bb117 to your computer and use it in GitHub Desktop.
(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