// Click tracking if (!clickCounts.has(voteId)) clickCounts.set(voteId, { yes: 0, no: 0 }); const clicks = clickCounts.get(voteId)!; if (votedYes && clicks.yes >= LOCK_AT) return; if (!votedYes && clicks.no >= LOCK_AT) return; // Ignore same vote if (votedYes && state.yes.has(voteId)) return; if (!votedYes && state.no.has(voteId)) return; if (votedYes) clicks.yes += 1; else clicks.no += 1; const clickCount = votedYes ? clicks.yes : clicks.no; // Resolve messages — officer override takes priority const publicMsg = getPublicOverride(voteId, votedYes ? "yes" : "no") ?? resolveMessage("public", votedYes ? "yes" : "no", clickCount, lookupUsername, user.serverNickname, user.globalNickname); const ephemeralMsg = getEphemeralOverride(voteId, votedYes ? "yes" : "no") ?? resolveMessage("ephemeral", votedYes ? "yes" : "no", clickCount, lookupUsername, user.serverNickname, user.globalNickname); const baseEntry = createVoteEntry(voteId, member, user.userKey, lookupUsername); // Check if character is already in use by another voter if (baseEntry.characterName) { console.log(`[vote] voteId=${voteId} yes keys:`, [...state.yes.keys()], 'no keys:', [...state.no.keys()]); for (const [otherId, entry] of [...state.yes.entries(), ...state.no.entries()]) { if (otherId !== voteId && otherId !== userId && entry.characterName === baseEntry.characterName) { // Check if this user is the owner of the character const ownerKey = entry.borrowedFrom ?? entry.userKey; const isOwner = user.userKey === ownerKey || // Also check if voter is the actual owner via characters.json (() => { const chars = getCharacters(user.userKey ?? ""); return chars.some((c) => c.name === entry.characterName); })(); console.log(`[conflict] user.userKey=${user.userKey} entry.userKey=${entry.userKey} borrowedFrom=${entry.borrowedFrom} ownerKey=${ownerKey} isOwner=${isOwner}`); if (isOwner && baseEntry.userKey) { // Owner trying to reclaim — show conflict embed const allChars = getCharacters(baseEntry.userKey); const borrowedChar = allChars.find((c) => c.name === baseEntry.characterName); if (borrowedChar) { await showConflictEmbed(interaction, baseEntry.userKey, entry.userKey, borrowedChar, allChars); return; } } await pollReplyAndDelete(interaction, `❌ **${baseEntry.characterName}** is already in the poll by another player.` ); return; }