Skip to content

Commit

Permalink
Role Sharing Game Settings. Complex, Simple, Vain, and Weak Fixes. Lo…
Browse files Browse the repository at this point in the history
…udmouth only reveals 1 Mafia Member from the Mafia Kill. (#1769)

Role Sharing, Allows All players during the day to Offer Role Shares
with each other. If accepted they will reveal their roles to each other.
Alignment Sharing, Same as above but with Alignments.

Private Reveal, A Player will reveal their role to another player no
consent needed.
Public Reveal, A player will reveal there role to All Players.

A player may offer to each other player once per day. (No offer
spamming) (If an offer is made in one type it counts for all types)

Complex Simple, Vain, and Weak work with Mafia Kill.

Loudmoouth only reveals 1 Mafia from the Mafia Kill.

---------

Co-authored-by: SawJester <[email protected]>
  • Loading branch information
SawJester and SawJester authored Nov 22, 2024
1 parent 5f62850 commit 3ec11e8
Show file tree
Hide file tree
Showing 14 changed files with 515 additions and 105 deletions.
7 changes: 7 additions & 0 deletions Games/types/Mafia/Game.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,13 @@ module.exports = class MafiaGame extends Game {
this.alivePlayers()[0].holdItem("EventManager", 1);
this.events.emit("ManageRandomEvents");
}
if(this.getStateName() == "Day" && (this.setup.RoleShare || this.setup.AlignmentShare || this.setup.PrivateShare || this.setup.PublicShare)){
for(let player of this.alivePlayers()){
if(player.items.filter((i) => i.name == "RoleSharing").length <= 0){
player.holdItem("RoleSharing", 1, this.setup.RoleShare, this.setup.AlignmentShare, this.setup.PrivateShare,this.setup.PublicShare);
}
}
}
}

getStateInfo(state) {
Expand Down
61 changes: 61 additions & 0 deletions Games/types/Mafia/items/RoleShareAccept.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
const Item = require("../Item");

module.exports = class RoleShareAccept extends Item {
constructor(proposer, type, accepter) {
super("RoleShareAccept");

this.proposer = proposer;
this.type = type;
this.cannotBeStolen = true;
this.cannotBeSnooped = true;
let meetingName;
if(this.type == "Role Share"){
meetingName = "Role Share between " + accepter.name + " and " + this.proposer.name;
}
else{
meetingName = "Alignment Share between " + accepter.name + " and " + this.proposer.name;
}

this.meetings[meetingName] = {
states: ["Day"],
flags: ["voting", "instant"],
inputType: "boolean",
action: {
labels: ["marriage"],
item: this,
run: function () {
if (this.target == "Yes") {
if(this.item.type == "Role Share"){
this.actor.role.revealToPlayer(this.item.proposer);
this.item.proposer.role.revealToPlayer(this.actor);
this.game.events.emit("ShareRole", this.actor, this.item.proposer, false);
}
else if(this.item.type == "Alignment Share"){

var roleActor = this.actor.getAppearance("reveal", true);
var alignmentActor = this.game.getRoleAlignment(roleActor);
var roleProposer = this.item.proposer.getAppearance("reveal", true);
var alignmentProposer = this.game.getRoleAlignment(roleProposer);


this.actor.queueAlert(
`${this.item.proposer.name}'s Alignment is ${alignmentProposer}.`
);
this.item.proposer.queueAlert(
`${this.actor.name}'s Alignment is ${alignmentActor}.`
);
this.game.events.emit("ShareRole", this.actor, this.item.proposer, true);
}

}
else{
this.item.proposer.queueAlert(
`${this.actor.name} has declined to Share.`
);
}
this.item.drop();
},
},
};
}
};
155 changes: 155 additions & 0 deletions Games/types/Mafia/items/RoleSharing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
const Item = require("../Item");
const Random = require("../../../../lib/Random");
const Action = require("../Action");
const { PRIORITY_INVESTIGATIVE_DEFAULT } = require("../const/Priority");

module.exports = class RoleSharing extends Item {
constructor(lifespan, roleShare, alignmentShare, privateShare, publicShare) {
super("RoleSharing");

//this.magicCult = options?.magicCult;
//this.broken = options?.broken;
this.canRoleShare = roleShare;
this.canAlignmentShare = alignmentShare;
this.canPrivateReveal = privateShare;
this.canPublicReveal = privateShare;
this.cannotBeStolen = true;
this.cannotBeSnooped = true;
this.lifespan = lifespan || Infinity;

this.shareTypes = [
"None",
];

if(this.canRoleShare == true){
this.shareTypes.push("Role Share");
}
if( this.canAlignmentShare == true){
this.shareTypes.push("Alignment Share");
}
if(this.canPrivateReveal == true){
this.shareTypes.push("Private Reveal");
}
if(this.canPublicReveal == true){
this.shareTypes.push("Public Reveal");
}

this.meetings = {
"Choose Share Method": {
states: ["Day"],
flags: ["voting"],
inputType: "custom",
targets: this.shareTypes,
},
"Share With Target": {
states: ["Day"],
flags: ["voting"],
},
};


this.listeners = {
state: function (stateInfo) {
this.hasSharedWith = [];
//var currentFungusList = this.shareTypes.filter((h));

//this.meetings["Choose Share Method"].targets = currentFungusList;
},
vote: function (vote) {
if (
(vote.meeting.name === "Choose Share Method") &&
vote.voter === this.holder
) {
this.currentShareMethod = vote.target;
}
else if((vote.meeting.name === "Share With Target") &&
vote.voter === this.holder && vote.target){


let targetPlayer = this.game.alivePlayers().filter((p) => p.id == vote.target);
if(targetPlayer.length > 0){
targetPlayer = targetPlayer[0];
}
else{
return;
}
if(this.currentShareMethod == null || this.currentShareMethod == "None") return;


if(this.hasSharedWith.includes(targetPlayer)) return;
this.hasSharedWith.push(targetPlayer);

if(this.currentShareMethod == "Role Share" || this.currentShareMethod == "Alignment Share"){
var action = new Action({
actor: this.holder,
target: targetPlayer,
game: this.game,
item: this,
labels: ["hidden"],
run: function () {
this.target.queueAlert(
`${this.actor.name} wants to ${this.item.currentShareMethod}.`
);
this.actor.queueAlert(
`You offer to ${this.item.currentShareMethod} with ${this.target.name}.`
);
},
});
this.game.instantAction(action);

let ShareWith = targetPlayer.holdItem("RoleShareAccept", this.holder,this.currentShareMethod,targetPlayer);
this.game.instantMeeting(ShareWith.meetings, [targetPlayer]);
}
else if(this.currentShareMethod == "Private Reveal"){
//this.holder.role.revealToPlayer(targetPlayer);
var action = new Action({
actor: this.holder,
target: targetPlayer,
game: this.game,
item: this,
labels: ["hidden"],
run: function () {
this.target.queueAlert(
`${this.actor.name} ${this.item.currentShareMethod}s to you.`
);
this.actor.queueAlert(
`You ${this.item.currentShareMethod} to ${this.target.name}.`
);
this.actor.role.revealToPlayer(targetPlayer);
},
});
this.game.instantAction(action);
}
else if(this.currentShareMethod == "Public Reveal"){
//this.holder.role.revealToAll();
var action = new Action({
actor: this.holder,
target: targetPlayer,
game: this.game,
item: this,
labels: ["hidden"],
run: function () {
this.game.queueAlert(
`${this.actor.name} ${this.item.currentShareMethod}s to everyone.`
);
this.actor.role.revealToAll();
},
});
this.game.instantAction(action);
}

}
},
};



}

hold(player) {


super.hold(player);
//this.data.currentShareMethod = null;
}
};
46 changes: 40 additions & 6 deletions Games/types/Mafia/roles/cards/Complex.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const Card = require("../../Card");
const Player = require("../../../../core/Player");
const { PRIORITY_NIGHT_ROLE_BLOCKER } = require("../../const/Priority");

module.exports = class Complex extends Card {
Expand All @@ -10,15 +11,48 @@ module.exports = class Complex extends Card {
priority: PRIORITY_NIGHT_ROLE_BLOCKER,
labels: ["block", "hidden"],
run: function () {
if (this.game.getStateName() != "Night") return;
if (
this.game.getStateName() != "Night" &&
this.game.getStateName() != "Dawn"
)
return;

if (!this.actor.alive) return;

const vanillaVisits = this.getVisits(this.actor).filter((p) =>
this.isVanillaRole(p)
);
if (vanillaVisits.length > 0) {
this.blockActions(this.actor);
for (let action of this.game.actions[0]) {
if (action.hasLabel("absolute")) {
continue;
}
if (action.hasLabel("mafia")) {
continue;
}
if (action.hasLabel("hidden")) {
continue;
}

let toCheck = action.target;
if (!Array.isArray(action.target)) {
toCheck = [action.target];
}

if (
action.actors.indexOf(this.actor) != -1 &&
!action.hasLabel("hidden") &&
action.target &&
toCheck[0] instanceof Player
) {
for (let y = 0; y < toCheck.length; y++) {
if (this.isVanillaRole(toCheck[y])) {
if (
action.priority > this.priority &&
!action.hasLabel("absolute")
) {
action.cancelActor(this.actor);
break;
}
}
}
}
}
},
},
Expand Down
6 changes: 5 additions & 1 deletion Games/types/Mafia/roles/cards/Disloyal.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ module.exports = class Disloyal extends Card {
priority: PRIORITY_NIGHT_ROLE_BLOCKER - 1,
labels: ["block", "hidden", "absolute"],
run: function () {
if (this.game.getStateName() != "Night") return;
if (
this.game.getStateName() != "Night" &&
this.game.getStateName() != "Dawn"
)
return;

if (!this.actor.alive) return;

Expand Down
6 changes: 5 additions & 1 deletion Games/types/Mafia/roles/cards/Loyal.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ module.exports = class Loyal extends Card {
priority: PRIORITY_NIGHT_ROLE_BLOCKER - 1,
labels: ["block", "hidden", "absolute"],
run: function () {
if (this.game.getStateName() != "Night") return;
if (
this.game.getStateName() != "Night" &&
this.game.getStateName() != "Dawn"
)
return;

if (!this.actor.alive) return;

Expand Down
8 changes: 8 additions & 0 deletions Games/types/Mafia/roles/cards/ModifierLoud.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ module.exports = class ModifierLoud extends Card {
if (this.game.getStateName() != "Night") return;

let visitors = this.getVisitors();
let MafiaKill = this.getVisitors(this.actor, "mafia");

if (MafiaKill && MafiaKill.length > 1) {
for (let x = 1; x < MafiaKill.length; x++) {
visitors.splice(visitors.indexOf(MafiaKill[x]), 1);
}
}

if (visitors?.length) {
let names = visitors?.map((visitor) => visitor.name);

Expand Down
46 changes: 40 additions & 6 deletions Games/types/Mafia/roles/cards/Simple.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const Card = require("../../Card");
const Player = require("../../../../core/Player");
const { PRIORITY_NIGHT_ROLE_BLOCKER } = require("../../const/Priority");

module.exports = class Simple extends Card {
Expand All @@ -10,15 +11,48 @@ module.exports = class Simple extends Card {
priority: PRIORITY_NIGHT_ROLE_BLOCKER,
labels: ["block", "hidden"],
run: function () {
if (this.game.getStateName() != "Night") return;
if (
this.game.getStateName() != "Night" &&
this.game.getStateName() != "Dawn"
)
return;

if (!this.actor.alive) return;

const nonVanillaVisits = this.getVisits(this.actor).filter(
(p) => !this.isVanillaRole(p)
);
if (nonVanillaVisits.length > 0) {
this.blockActions(this.actor);
for (let action of this.game.actions[0]) {
if (action.hasLabel("absolute")) {
continue;
}
if (action.hasLabel("mafia")) {
continue;
}
if (action.hasLabel("hidden")) {
continue;
}

let toCheck = action.target;
if (!Array.isArray(action.target)) {
toCheck = [action.target];
}

if (
action.actors.indexOf(this.actor) != -1 &&
!action.hasLabel("hidden") &&
action.target &&
toCheck[0] instanceof Player
) {
for (let y = 0; y < toCheck.length; y++) {
if (!this.isVanillaRole(toCheck[y])) {
if (
action.priority > this.priority &&
!action.hasLabel("absolute")
) {
action.cancelActor(this.actor);
break;
}
}
}
}
}
},
},
Expand Down
Loading

0 comments on commit 3ec11e8

Please sign in to comment.