From fc2ca12f8d0a38b5de0b7c62f7b3e341301935b5 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 01:16:21 -0600
Subject: [PATCH 01/20] Fix mistaken changes in README.md
---
README.md | 82 +++++++++++++++++++++++++++----------------------------
1 file changed, 41 insertions(+), 41 deletions(-)
diff --git a/README.md b/README.md
index 015e06a..e17d248 100644
--- a/README.md
+++ b/README.md
@@ -9,9 +9,9 @@
# MafiaCraft
-
MafiaCraft is a plugin for Spigot-based Minecraft servers that recreates the classic hidden roleData game
+
MafiaCraft is a plugin for Spigot-based Minecraft servers that recreates the classic hidden role game
Mafia (also played under the name Werewolf) into Minecraft. This plugin was heavily inspired by those
-games, as well as other online hidden roleData games like Town of Salem.
+games, as well as other online hidden role games like Town of Salem.
This plugin is now heading into final testing, and then will be used on my server. Let's hope it works!
# Gameplay
@@ -46,7 +46,7 @@ Listed below are all the roles and abilities planned, as well as some definition
### Neutral Roles
_Notes:
-Alone and Same Role mean only themselves (or those who share their roleData) and those
+Alone and Same Role mean only themselves (or those who share their role) and those
who win by Surviving remaining alive.
Win by Surviving roles can win with anyone, as long as they survive until the end of the game._
@@ -64,41 +64,41 @@ _* These roles only win if they complete their special task **AND** survive unti
## Abilities
-| Ability | Description | Cooldown |
-|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
-| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
-| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
-| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
-| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
-| Assassination | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
-| Reanimation | Throw a totem of undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
-| Retaliation | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
-| High Noon | Receive Strength II for 60 seconds at noon. | Occurs automatically. |
-| Marksman | Arrows do one additional heart of damage. | |
-| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
-| Watch | Can see invisible players when using a Spyglass. | |
-| Peripherals | Can see invisible players within 20 blocks. | |
-| Clear Sight | Not affected by Blindness. | |
-| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
-| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire or Werewolf back to their original roleData, unless that was their original roleData. | Can be brewed once per in-game week. |
-| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Deacons. | |
-| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
-| This is Fine | Take reduced damage from fire and lava. | |
-| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
-| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
-| Tracking | See whether your targets are dead or alive. | |
-| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
-| Scatter | Using the spell book, effect one person with Speed IV for 20 seconds. Costs 5 levels of experience. | |
-| Toadify | Using the spell book, effect one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
-| Fog of War | Using the spell book, effect everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
-| Vanish | Using the spell book, effect one person with Invisibility for 180 seconds. Costs 10 levels of experience. | |
-| Transform | Transform on full-moon nights. | Occurs automatically. |
-| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
-| Nemesis | Weak to Iron Tools while Transformed. | |
-| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
-| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
-| Staked | Weak to Wooden Tools. | |
-| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither I indefinitely, until they are able to find a cure. The Jester will respawn. | |
+| Ability | Description | Cooldown |
+|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
+| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
+| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
+| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
+| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
+| Assassination | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
+| Reanimation | Throw a totem of undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
+| Retaliation | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
+| High Noon | Receive Strength II for 60 seconds at noon. | Occurs automatically. |
+| Marksman | Arrows do one additional heart of damage. | |
+| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
+| Watch | Can see invisible players when using a Spyglass. | |
+| Peripherals | Can see invisible players within 20 blocks. | |
+| Clear Sight | Not affected by Blindness. | |
+| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
+| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire or Werewolf back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
+| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Deacons. | |
+| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
+| This is Fine | Take reduced damage from fire and lava. | |
+| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
+| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
+| Tracking | See whether your targets are dead or alive. | |
+| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
+| Scatter | Using the spell book, effect one person with Speed IV for 20 seconds. Costs 5 levels of experience. | |
+| Toadify | Using the spell book, effect one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
+| Fog of War | Using the spell book, effect everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
+| Vanish | Using the spell book, effect one person with Invisibility for 180 seconds. Costs 10 levels of experience. | |
+| Transform | Transform on full-moon nights. | Occurs automatically. |
+| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
+| Nemesis | Weak to Iron Tools while Transformed. | |
+| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
+| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
+| Staked | Weak to Wooden Tools. | |
+| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither I indefinitely, until they are able to find a cure. The Jester will respawn. | |
## Rules and Definitions
@@ -113,16 +113,16 @@ _* These roles only win if they complete their special task **AND** survive unti
## Commands
-`/mafiacraft`: Available to all players. Shows information about their roleData.
+`/mafiacraft`: Available to all players. Shows information about their role.
`/mafiacraftadmin`: Available to operators only. Controls all aspects of MafiaCraft that are not controlled in the config.
These commands also have aliases to make them easier to use quickly.
### The `/mafiacraftadmin` command tree
-* `setrole `: Sets a player's roleData. The player must be online. No spaces allowed in roleData name.
+* `setrole `: Sets a player's role. The player must be online. No spaces allowed in role name.
* `removeplayer `: Removes the specified player from the game. The player must be online.
* `randomize`
- * `add `: Adds the player to the list of players who need their roleData randomized. The player must be online. Players can have their roleData re-randomized if they already have one.
+ * `add `: Adds the player to the list of players who need their role randomized. The player must be online. Players can have their role re-randomized if they already have one.
* `addall`: Adds all players who have ever joined this world into the list of players to be randomized. The list is taken from the `world/playerdata` folder.
* `remove `: Removes the specified player from the list of players to be randomized. Use UUID if the player is offline (see `/mafiacraft randomize list`).
* `removeall`: Clears the list of players to be randomized.
From 18e5664ffe6d5a323e9f7a709231772a7ad14102 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 02:03:25 -0600
Subject: [PATCH 02/20] Clear Sight now cancels Darkness
---
README.md | 2 +-
src/mddev0/mafiacraft/abilities/ClearSight.java | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index e17d248..f99eea8 100644
--- a/README.md
+++ b/README.md
@@ -78,7 +78,7 @@ _* These roles only win if they complete their special task **AND** survive unti
| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
| Watch | Can see invisible players when using a Spyglass. | |
| Peripherals | Can see invisible players within 20 blocks. | |
-| Clear Sight | Not affected by Blindness. | |
+| Clear Sight | Not affected by Blindness or Darkness. | |
| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire or Werewolf back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Deacons. | |
diff --git a/src/mddev0/mafiacraft/abilities/ClearSight.java b/src/mddev0/mafiacraft/abilities/ClearSight.java
index e4fd642..de54077 100644
--- a/src/mddev0/mafiacraft/abilities/ClearSight.java
+++ b/src/mddev0/mafiacraft/abilities/ClearSight.java
@@ -20,12 +20,14 @@ public ClearSight(MafiaCraft plugin) {
@SuppressWarnings("unused")
@EventHandler
- public void onBlindnessApplied(EntityPotionEffectEvent potion) {
+ public void onEffectApplied(EntityPotionEffectEvent potion) {
if (!plugin.getActive()) return; // DO NOTHING IF NOT ACTIVE!
MafiaPlayer affected = plugin.getPlayerList().get(potion.getEntity().getUniqueId());
if (potion.getEntity().getType() == EntityType.PLAYER && affected != null &&
- affected.getRole().getAbilities().contains(Ability.CLEAR_SIGHT) &&
- Objects.requireNonNull(potion.getNewEffect()).getType() == PotionEffectType.BLINDNESS)
+ affected.getRole().getAbilities().contains(Ability.CLEAR_SIGHT) && (
+ Objects.requireNonNull(potion.getNewEffect()).getType() == PotionEffectType.BLINDNESS ||
+ Objects.requireNonNull(potion.getNewEffect()).getType() == PotionEffectType.DARKNESS
+ ))
potion.setCancelled(true); // Cancel potion effect if eligible player is being blinded
}
}
From 208f590ad9ad24a4fb8a34ca0ee7eb3da61d573a Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 02:12:22 -0600
Subject: [PATCH 03/20] Added missing Werewolf win announcement
---
src/mddev0/mafiacraft/util/GameFinisher.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/mddev0/mafiacraft/util/GameFinisher.java b/src/mddev0/mafiacraft/util/GameFinisher.java
index 9b6f1b9..b58faef 100644
--- a/src/mddev0/mafiacraft/util/GameFinisher.java
+++ b/src/mddev0/mafiacraft/util/GameFinisher.java
@@ -87,6 +87,8 @@ else if (dayTime > 12786 && dayTime <= 13000 && !checkedTonight) {
subtitle = ChatColor.GRAY + "The " + ChatColor.BLUE + ChatColor.BOLD + "Serial Killer" + ChatColor.RESET + ChatColor.GRAY + " has won!";
else if (winner.getRole() == Role.TRAPPER)
subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_AQUA + ChatColor.BOLD + "Trapper" + ChatColor.RESET + ChatColor.GRAY + " has won!";
+ else if (winner.getRole() == Role.WEREWOLF)
+ subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_RED + ChatColor.BOLD + "Werewolf" + ChatColor.RESET + ChatColor.GRAY + " has won!";
break; // since we only take 1
}
}
From 6c970a15b0dd23bf7b4f1431214fc579a5da4895 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 02:18:09 -0600
Subject: [PATCH 04/20] Werewolves are no longer affected by Ambrosia
---
README.md | 70 +++++++++----------
src/mddev0/mafiacraft/abilities/Ambrosia.java | 3 +-
2 files changed, 36 insertions(+), 37 deletions(-)
diff --git a/README.md b/README.md
index f99eea8..57374e8 100644
--- a/README.md
+++ b/README.md
@@ -64,41 +64,41 @@ _* These roles only win if they complete their special task **AND** survive unti
## Abilities
-| Ability | Description | Cooldown |
-|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
-| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
-| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
-| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
-| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
-| Assassination | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
-| Reanimation | Throw a totem of undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
-| Retaliation | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
-| High Noon | Receive Strength II for 60 seconds at noon. | Occurs automatically. |
-| Marksman | Arrows do one additional heart of damage. | |
-| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
-| Watch | Can see invisible players when using a Spyglass. | |
-| Peripherals | Can see invisible players within 20 blocks. | |
-| Clear Sight | Not affected by Blindness or Darkness. | |
-| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
-| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire or Werewolf back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
-| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Deacons. | |
-| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
-| This is Fine | Take reduced damage from fire and lava. | |
-| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
-| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
-| Tracking | See whether your targets are dead or alive. | |
-| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
-| Scatter | Using the spell book, effect one person with Speed IV for 20 seconds. Costs 5 levels of experience. | |
-| Toadify | Using the spell book, effect one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
-| Fog of War | Using the spell book, effect everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
-| Vanish | Using the spell book, effect one person with Invisibility for 180 seconds. Costs 10 levels of experience. | |
-| Transform | Transform on full-moon nights. | Occurs automatically. |
-| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
-| Nemesis | Weak to Iron Tools while Transformed. | |
-| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
-| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
-| Staked | Weak to Wooden Tools. | |
-| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither I indefinitely, until they are able to find a cure. The Jester will respawn. | |
+| Ability | Description | Cooldown |
+|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
+| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
+| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
+| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
+| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
+| Assassination | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
+| Reanimation | Throw a totem of undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
+| Retaliation | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
+| High Noon | Receive Strength II for 60 seconds at noon. | Occurs automatically. |
+| Marksman | Arrows do one additional heart of damage. | |
+| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
+| Watch | Can see invisible players when using a Spyglass. | |
+| Peripherals | Can see invisible players within 20 blocks. | |
+| Clear Sight | Not affected by Blindness or Darkness. | |
+| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
+| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
+| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Deacons. | |
+| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
+| This is Fine | Take reduced damage from fire and lava. | |
+| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
+| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
+| Tracking | See whether your targets are dead or alive. | |
+| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
+| Scatter | Using the spell book, effect one person with Speed IV for 20 seconds. Costs 5 levels of experience. | |
+| Toadify | Using the spell book, effect one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
+| Fog of War | Using the spell book, effect everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
+| Vanish | Using the spell book, effect one person with Invisibility for 180 seconds. Costs 10 levels of experience. | |
+| Transform | Transform on full-moon nights. | Occurs automatically. |
+| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
+| Nemesis | Weak to Iron Tools while Transformed. | |
+| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
+| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
+| Staked | Weak to Wooden Tools. | |
+| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither I indefinitely, until they are able to find a cure. The Jester will respawn. | |
## Rules and Definitions
diff --git a/src/mddev0/mafiacraft/abilities/Ambrosia.java b/src/mddev0/mafiacraft/abilities/Ambrosia.java
index ed69dee..074a94d 100644
--- a/src/mddev0/mafiacraft/abilities/Ambrosia.java
+++ b/src/mddev0/mafiacraft/abilities/Ambrosia.java
@@ -80,8 +80,7 @@ public void run() {
ambrosiaPotion.setColor(Color.fromRGB(255,200,0));
ambrosiaPotion.setDisplayName(ChatColor.GOLD + "Ambrosia");
List ambrosiaLore = new ArrayList<>();
- ambrosiaLore.add("Splash on any " + ChatColor.DARK_RED + "Werewolf" +
- ChatColor.RESET + " or " + ChatColor.DARK_PURPLE + "Vampire");
+ ambrosiaLore.add("Splash on any " + ChatColor.DARK_PURPLE + "Vampire");
ambrosiaLore.add("to convert them back to their original role.");
ambrosiaPotion.setLore(ambrosiaLore);
ambrosiaItem.setItemMeta(ambrosiaPotion);
From 336942dce4e27b40d00a92f0cb0979952b7c1fff Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 03:17:38 -0600
Subject: [PATCH 05/20] Add option to hide players after death
---
config.yml | 4 ++
src/mddev0/mafiacraft/util/DeathManager.java | 26 +++++++-----
.../mafiacraft/util/JoinLeaveManager.java | 40 +++++++++++--------
3 files changed, 44 insertions(+), 26 deletions(-)
diff --git a/config.yml b/config.yml
index a73c25a..76522b5 100644
--- a/config.yml
+++ b/config.yml
@@ -7,6 +7,10 @@ hardcoreStyle: true
# If true, players in spectator mode will not be able to send messages to chat. Operators bypass this.
blockSpectatorChat: true
+# If true, spectating players will appear to leave the game when they die and will be hidden from the tab list when online.
+# Remember to set the game rule to hide player death messages if true!
+hideDeadPlayers: false
+
# Amount of time in seconds players will be considered as "attacking" after attempting to kill someone
attackDuration: 30
diff --git a/src/mddev0/mafiacraft/util/DeathManager.java b/src/mddev0/mafiacraft/util/DeathManager.java
index c019fa5..a4cea6e 100644
--- a/src/mddev0/mafiacraft/util/DeathManager.java
+++ b/src/mddev0/mafiacraft/util/DeathManager.java
@@ -40,17 +40,25 @@ public void onPlayerDeathLate(PlayerDeathEvent death) {
Bukkit.getLogger().log(Level.INFO, death.getDeathMessage() + " <" + death.getEntity().getWorld().getName() + ": " + loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ() + ">");
}
if (!plugin.getActive()) return;
- MafiaPlayer dead = plugin.getPlayerList().get(death.getEntity().getUniqueId());
- if (dead != null && !dead.isLiving() && death.getEntity().getGameMode() != GameMode.SPECTATOR) {
- Player died = death.getEntity();
- Bukkit.broadcastMessage(ChatColor.YELLOW + died.getName() + " left the game");
- for (Player p : plugin.getServer().getOnlinePlayers()) {
- MafiaPlayer live = plugin.getLivingPlayers().get(p.getUniqueId());
- if (live != null) {
- // player is online and alive
- p.hidePlayer(plugin, died);
+ if (plugin.getConfig().getBoolean("hideDeadPlayers")) {
+ // Execute only if hiding dead players
+ MafiaPlayer dead = plugin.getPlayerList().get(death.getEntity().getUniqueId());
+ if (dead != null && !dead.isLiving() && death.getEntity().getGameMode() != GameMode.SPECTATOR) {
+ Player died = death.getEntity();
+ Bukkit.broadcastMessage(ChatColor.YELLOW + died.getName() + " left the game");
+ for (Player p : plugin.getServer().getOnlinePlayers()) {
+ MafiaPlayer live = plugin.getLivingPlayers().get(p.getUniqueId());
+ if (live != null) {
+ // player is online and alive
+ p.hidePlayer(plugin, died);
+ }
}
}
+ } else {
+ // If not hiding dead players, announce their death BUT NOT THE CAUSE
+ Location loc = death.getEntity().getLocation();
+ Bukkit.getLogger().log(Level.INFO, death.getDeathMessage() + " <" + death.getEntity().getWorld().getName() + ": " + loc.getBlockX() + ", " + loc.getBlockY() + ", " + loc.getBlockZ() + ">");
+ death.setDeathMessage(death.getEntity().getDisplayName() + ChatColor.RESET + " died");
}
}
diff --git a/src/mddev0/mafiacraft/util/JoinLeaveManager.java b/src/mddev0/mafiacraft/util/JoinLeaveManager.java
index 4b2ee80..1c23fcc 100644
--- a/src/mddev0/mafiacraft/util/JoinLeaveManager.java
+++ b/src/mddev0/mafiacraft/util/JoinLeaveManager.java
@@ -35,25 +35,29 @@ public void onPlayerJoin(PlayerJoinEvent join) {
join.getPlayer().teleport(toSpawn);
}
join.getPlayer().setGameMode(GameMode.SURVIVAL);
- // all dead players should be hidden
- for (Player p : plugin.getServer().getOnlinePlayers()) {
- MafiaPlayer spec = plugin.getPlayerList().get(p.getUniqueId());
- if (spec == null || !spec.isLiving()) {
- join.getPlayer().hidePlayer(plugin, p);
+ if (plugin.getConfig().getBoolean("hideDeadPlayers")) {
+ // if true, dead players should be hidden
+ for (Player p : plugin.getServer().getOnlinePlayers()) {
+ MafiaPlayer spec = plugin.getPlayerList().get(p.getUniqueId());
+ if (spec == null || !spec.isLiving()) {
+ join.getPlayer().hidePlayer(plugin, p);
+ }
}
}
}
else { // player is not in game or is dead
- // set spectator and hide join message
+ // TODO: set spectator? Potential for dead players to remain in world?
join.getPlayer().setGameMode(GameMode.SPECTATOR);
- join.setJoinMessage(null);
- // hide player from all living players
- for (Map.Entry living : plugin.getLivingPlayers().entrySet()) {
- OfflinePlayer offp = Bukkit.getOfflinePlayer(living.getKey());
- if (offp.isOnline()) {
- Player p = offp.getPlayer();
- assert p != null;
- p.hidePlayer(plugin, join.getPlayer());
+ if (plugin.getConfig().getBoolean("hideDeadPlayers")) {
+ // if true, hide player from all living players
+ join.setJoinMessage(null);
+ for (Map.Entry living : plugin.getLivingPlayers().entrySet()) {
+ OfflinePlayer offp = Bukkit.getOfflinePlayer(living.getKey());
+ if (offp.isOnline()) {
+ Player p = offp.getPlayer();
+ assert p != null;
+ p.hidePlayer(plugin, join.getPlayer());
+ }
}
}
}
@@ -63,9 +67,11 @@ public void onPlayerJoin(PlayerJoinEvent join) {
@EventHandler
public void onPlayerLeave(PlayerQuitEvent leave) {
if (!plugin.getActive()) return;
- MafiaPlayer left = plugin.getPlayerList().get(leave.getPlayer().getUniqueId());
- if (left == null || !left.isLiving()) {
- leave.setQuitMessage("");
+ if (plugin.getConfig().getBoolean("hideDeadPlayers")) {
+ MafiaPlayer left = plugin.getPlayerList().get(leave.getPlayer().getUniqueId());
+ if (left == null || !left.isLiving()) {
+ leave.setQuitMessage(null);
+ }
}
}
}
From d09885e32e136d12c27b20ad4e2f85be67329500 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 21:30:19 -0600
Subject: [PATCH 06/20] Apply hideDeadPlayers config option
Also fixed cooldown length
---
src/mddev0/mafiacraft/gui/ReanimationGUI.java | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/mddev0/mafiacraft/gui/ReanimationGUI.java b/src/mddev0/mafiacraft/gui/ReanimationGUI.java
index 68bc67d..e282443 100644
--- a/src/mddev0/mafiacraft/gui/ReanimationGUI.java
+++ b/src/mddev0/mafiacraft/gui/ReanimationGUI.java
@@ -60,7 +60,7 @@ public void onHeadClick(final InventoryClickEvent click) {
if (clicked == null || clicked.getType().isAir()) return;
// SCUFFED: So many requireNonNull... am I doing this wrong?
UUID toReanimate = Objects.requireNonNull(((SkullMeta) Objects.requireNonNull(clicked.getItemMeta())).getOwningPlayer()).getUniqueId();
- Long cooldownExpires = (plugin.getWorldFullTime() + 48000L) - (plugin.getWorldFullTime() % 24000);
+ Long cooldownExpires = (plugin.getWorldFullTime() + 168000L) - (plugin.getWorldFullTime() % 24000);
plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getCooldowns().startCooldown(Ability.REANIMATION, cooldownExpires);
plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getStatus().startStatus(StatusData.Status.UNHOLY, plugin.getWorldFullTime() + 48000L);
plugin.getPlayerList().get(toReanimate).makeAlive();
@@ -77,15 +77,17 @@ public void onHeadClick(final InventoryClickEvent click) {
p.teleport(toSpawn);
}
p.setGameMode(GameMode.SURVIVAL);
- // all dead players should be hidden, p should be unhidden
- for (Player other : plugin.getServer().getOnlinePlayers()) {
- other.showPlayer(plugin, p);
- MafiaPlayer spec = plugin.getPlayerList().get(other.getUniqueId());
- if (spec == null || !spec.isLiving()) {
- p.hidePlayer(plugin, other);
+ if (plugin.getConfig().getBoolean("hideDeadPlayers")) {
+ // all dead players should be hidden, p should be unhidden
+ for (Player other : plugin.getServer().getOnlinePlayers()) {
+ other.showPlayer(plugin, p);
+ MafiaPlayer spec = plugin.getPlayerList().get(other.getUniqueId());
+ if (spec == null || !spec.isLiving()) {
+ p.hidePlayer(plugin, other);
+ }
}
+ Bukkit.broadcastMessage(ChatColor.YELLOW + p.getName() + " joined the game");
}
- Bukkit.broadcastMessage(ChatColor.YELLOW + p.getName() + " joined the game");
}
}
From 6850fef9765dbbbaecf2698acd1f94cad1ad7988 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 27 Dec 2023 21:40:53 -0600
Subject: [PATCH 07/20] Jester is more deadly and reveals jester
Ability is one-time use.
---
README.md | 2 +-
.../mafiacraft/abilities/JustAPrank.java | 22 +++++++++++++++----
src/mddev0/mafiacraft/gui/InfoGUI.java | 12 +++++++++-
.../mafiacraft/util/JoinLeaveManager.java | 14 +++++++-----
4 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 57374e8..d610276 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ _* These roles only win if they complete their special task **AND** survive unti
| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
| Staked | Weak to Wooden Tools. | |
-| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither I indefinitely, until they are able to find a cure. The Jester will respawn. | |
+| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither II indefinitely, until they are able to find a cure. The Jester will respawn and have their role revealed. | **One-time use.** |
## Rules and Definitions
diff --git a/src/mddev0/mafiacraft/abilities/JustAPrank.java b/src/mddev0/mafiacraft/abilities/JustAPrank.java
index bd1aba8..5ba23c5 100644
--- a/src/mddev0/mafiacraft/abilities/JustAPrank.java
+++ b/src/mddev0/mafiacraft/abilities/JustAPrank.java
@@ -15,6 +15,8 @@
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
+import java.util.logging.Level;
+
public final class JustAPrank implements Listener {
private final MafiaCraft plugin;
@@ -30,18 +32,30 @@ public void onJesterKill(PlayerDeathEvent death) {
if (death.getEntity().getKiller() != null) {
MafiaPlayer jest = plugin.getPlayerList().get(death.getEntity().getUniqueId());
MafiaPlayer killer = plugin.getLivingPlayers().get(death.getEntity().getKiller().getUniqueId());
- if (jest != null && jest.getRole().getAbilities().contains(Ability.JUST_A_PRANK) && killer != null && killer.getRole().getAlignment() == Role.Team.VILLAGE) {
+ if (jest != null && jest.getRole().getAbilities().contains(Ability.JUST_A_PRANK) &&
+ !(Boolean)jest.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED) &&
+ killer != null && killer.getRole().getAlignment() == Role.Team.VILLAGE) {
if (!jest.getStatus().hasStatus(StatusData.Status.IN_COMBAT)) {
+ // For Jester
jest.makeAlive();
Player jester = Bukkit.getPlayer(jest.getID());
assert jester != null; // jester must be online to have been killed
jester.sendMessage(ChatColor.DARK_GREEN + "You were killed by a member of the Village! You've triggered your effect!");
jest.getRoleData().setData(RoleData.DataType.JESTER_ABILITY_USED, true);
- // TODO: MAKE THIS MORE LETHAL! See notes.
+ death.setKeepInventory(true);
+ death.setKeepLevel(true);
+ // For other player
Player toAffect = death.getEntity().getKiller();
- toAffect.sendMessage(ChatColor.LIGHT_PURPLE + "You killed the Jester! " + ChatColor.DARK_GRAY + "Find some milk to cure their effect!");
- toAffect.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, Integer.MAX_VALUE, 0, false, true, true));
+ toAffect.sendMessage(ChatColor.GRAY + "You killed the " + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.GRAY + "!");
+ jester.getWorld().createExplosion(jester.getLocation(), 5.0f, false, false, jester);
+ toAffect.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, Integer.MAX_VALUE, 1, false, true, true));
toAffect.getWorld().spawnParticle(Particle.VILLAGER_ANGRY, toAffect.getLocation().add(0, 1, 0), 10, 1, 2, 1);
+ // For all others
+ jester.getWorld().strikeLightningEffect(jester.getLocation());
+ plugin.getServer().broadcastMessage(jester.getName() + " has been revealed as the " + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "!");
+ plugin.getLogger().log(Level.INFO, "The jester (" + jester.getName() + ") was killed by " + toAffect.getName());
+ jester.setDisplayName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + jester.getDisplayName());
+ jester.setPlayerListName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + jester.getPlayerListName());
}
}
}
diff --git a/src/mddev0/mafiacraft/gui/InfoGUI.java b/src/mddev0/mafiacraft/gui/InfoGUI.java
index d46aa60..455afc3 100644
--- a/src/mddev0/mafiacraft/gui/InfoGUI.java
+++ b/src/mddev0/mafiacraft/gui/InfoGUI.java
@@ -120,7 +120,17 @@ private void fillInventory() {
for (Ability abil : caller.getRole().getAbilities()) {
ItemStack abilItem;
ItemMeta abilMeta;
- if (caller.getCooldowns().isOnCooldown(abil)) { // On Cooldown
+ if (abil == Ability.JUST_A_PRANK && (Boolean)caller.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED)) {
+ // One-time use (this ability only)
+ abilItem = new ItemStack(Material.GRAY_CONCRETE);
+ abilMeta = abilItem.getItemMeta();
+ assert abilMeta != null;
+ abilMeta.setDisplayName(ChatColor.DARK_GRAY + abil.fullName());
+ ArrayList abilLore = new ArrayList<>();
+ abilLore.add(ChatColor.RESET + "" + ChatColor.GRAY + "This ability may only be used once.");
+ abilMeta.setLore(abilLore);
+ abilItem.setItemMeta(abilMeta);
+ } else if (caller.getCooldowns().isOnCooldown(abil)) { // On Cooldown
abilItem = new ItemStack(Material.YELLOW_CONCRETE);
abilMeta = abilItem.getItemMeta();
assert abilMeta != null;
diff --git a/src/mddev0/mafiacraft/util/JoinLeaveManager.java b/src/mddev0/mafiacraft/util/JoinLeaveManager.java
index 1c23fcc..c3801d4 100644
--- a/src/mddev0/mafiacraft/util/JoinLeaveManager.java
+++ b/src/mddev0/mafiacraft/util/JoinLeaveManager.java
@@ -2,10 +2,8 @@
import mddev0.mafiacraft.MafiaCraft;
import mddev0.mafiacraft.player.MafiaPlayer;
-import org.bukkit.Bukkit;
-import org.bukkit.GameMode;
-import org.bukkit.Location;
-import org.bukkit.OfflinePlayer;
+import mddev0.mafiacraft.player.RoleData;
+import org.bukkit.*;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@@ -44,8 +42,7 @@ public void onPlayerJoin(PlayerJoinEvent join) {
}
}
}
- }
- else { // player is not in game or is dead
+ } else { // player is not in game or is dead
// TODO: set spectator? Potential for dead players to remain in world?
join.getPlayer().setGameMode(GameMode.SPECTATOR);
if (plugin.getConfig().getBoolean("hideDeadPlayers")) {
@@ -61,6 +58,11 @@ public void onPlayerJoin(PlayerJoinEvent join) {
}
}
}
+ // Handle Jester
+ if (joined != null && (Boolean) joined.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED)) {
+ join.getPlayer().setDisplayName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + join.getPlayer().getDisplayName());
+ join.getPlayer().setPlayerListName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + join.getPlayer().getPlayerListName());
+ }
}
@SuppressWarnings("unused")
From 82bb088b9ecd94fb715e5aa764377cb9c95582d6 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Thu, 28 Dec 2023 00:01:00 -0600
Subject: [PATCH 08/20] Added ability desc. and did some renaming
---
README.md | 86 +++++++-------
config.yml | 2 +-
src/mddev0/mafiacraft/MafiaCraft.java | 6 +-
src/mddev0/mafiacraft/abilities/Ability.java | 109 ++++++++++++------
src/mddev0/mafiacraft/abilities/Ambrosia.java | 1 -
.../{Assassination.java => Assassinate.java} | 8 +-
.../{Retaliation.java => Retaliate.java} | 12 +-
.../{Reanimation.java => Revive.java} | 12 +-
.../mafiacraft/abilities/SpellBook.java | 2 +-
src/mddev0/mafiacraft/gui/InfoGUI.java | 9 +-
.../{ReanimationGUI.java => ReviveGUI.java} | 6 +-
src/mddev0/mafiacraft/player/Role.java | 8 +-
12 files changed, 151 insertions(+), 110 deletions(-)
rename src/mddev0/mafiacraft/abilities/{Assassination.java => Assassinate.java} (88%)
rename src/mddev0/mafiacraft/abilities/{Retaliation.java => Retaliate.java} (90%)
rename src/mddev0/mafiacraft/abilities/{Reanimation.java => Revive.java} (78%)
rename src/mddev0/mafiacraft/gui/{ReanimationGUI.java => ReviveGUI.java} (95%)
diff --git a/README.md b/README.md
index d610276..22aee65 100644
--- a/README.md
+++ b/README.md
@@ -28,20 +28,20 @@ Listed below are all the roles and abilities planned, as well as some definition
| *Godfather* | The head of the local crime family. | Protection,
Charisma | Tell the members of the Mafia what to do. |
| Mafioso | A member of the local crime family. | Succession | Follow the orders of the Godfather. |
| Framer | A skilled bookkeeper turned crime-staging genius. | Forgery | Follow the orders of the Godfather. |
-| Assassin | The dedicated killer within the Mafia's ranks. | Assassination | Follow the orders of the Godfather. |
+| Assassin | The dedicated killer within the Mafia's ranks. | Assassinate | Follow the orders of the Godfather. |
### Village Roles
| Role | Description | Abilities | Tasks |
|--------------|------------------------------------------------------------------------------------|-----------------------------------------|-----------------------------------------------------------|
-| *Reanimator* | A Villager who discovered the long lost art of resurrection. | Reanimation | Reanimate players to help the Village survive. |
-| Veteran | A war hero whose defense instincts never left when they retired from the military. | Retaliation | Defend yourself from attackers to help the Villagers win. |
+| *Reanimator* | A Villager who discovered the long lost art of resurrection. | Revive | Reanimate players to help the Village survive. |
+| Veteran | A war hero whose defense instincts never left when they retired from the military. | Retaliate | Defend yourself from attackers to help the Villagers win. |
| Deputy | A fighter with honor and standards, who will always rise to a fair challenge. | High Noon,
Marksman | Take down those who the Village sees as a threat. |
| Investigator | An armchair detective whose skills can finally be put to good use. | Investigate | Discover who is really on the side of the Villagers. |
| Lookout | An eagle-eyed observer who always seems to know who's been where. | Watch,
Peripherals,
Clear Sight | Gather information to help the Village. |
| Doctor | A skilled medic capable of helping those in need. | Rescue | Protect other Villagers. |
| *Apothecary* | A skilled brewer capable of producing special concoctions. | Ambrosia | Brew potions for the Village. |
-| Deacon | A religious devotee who can sense the presence of unholy abilities. | Inquisition | Find out who in the town may be harboring a secret power. |
+| Priest | A religious devotee who can sense the presence of unholy abilities. | Inquisition | Find out who in the town may be harboring a secret power. |
### Neutral Roles
@@ -53,7 +53,7 @@ Win by Surviving roles can win with anyone, as long as they survive until the en
| Role | Description | Abilities | Win Conditions | Tasks |
|---------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------|----------------|----------------------------------------------------------------------------|
| Serial Killer | An insane murderer who wants nothing more than to be alone. | Protection,
Ambush | Alone | Kill everyone without being caught. |
-| Trapper | Some people just want to see the world burn. | This is Fine,
Dodge Roll | Alone | Use traps and fire to kill everyone without being caught. |
+| Trapper | Some people just want to see the world burn. | This is Fine,
Dodge Roll | Alone | Use traps and fire to kill everyone without being caught. |
| Hunter | Ensure that the targets you are given die by the end of the game, and remain dead. | Target,
Tracking | Surviving* | Use any means necessary to ensure your target players die.Avoid dying. |
| Sorcerer | A powerful spell-caster bound by no allegiances. | Scatter,
Toadify,
Fog of War,
Vanish,
Spell Book | Surviving | Use your abilities to survive. |
| *Werewolf* | A regular person who suddenly transforms under the Full Moon. | Transform,
Rampage,
Nemesis | Alone | Kill everyone without being caught. |
@@ -64,50 +64,50 @@ _* These roles only win if they complete their special task **AND** survive unti
## Abilities
-| Ability | Description | Cooldown |
-|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
-| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
-| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
-| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
-| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
-| Assassination | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
-| Reanimation | Throw a totem of undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
-| Retaliation | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
-| High Noon | Receive Strength II for 60 seconds at noon. | Occurs automatically. |
-| Marksman | Arrows do one additional heart of damage. | |
-| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
-| Watch | Can see invisible players when using a Spyglass. | |
-| Peripherals | Can see invisible players within 20 blocks. | |
-| Clear Sight | Not affected by Blindness or Darkness. | |
-| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
-| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
-| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Deacons. | |
-| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
-| This is Fine | Take reduced damage from fire and lava. | |
-| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
-| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
-| Tracking | See whether your targets are dead or alive. | |
-| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
-| Scatter | Using the spell book, effect one person with Speed IV for 20 seconds. Costs 5 levels of experience. | |
-| Toadify | Using the spell book, effect one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
-| Fog of War | Using the spell book, effect everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
-| Vanish | Using the spell book, effect one person with Invisibility for 180 seconds. Costs 10 levels of experience. | |
-| Transform | Transform on full-moon nights. | Occurs automatically. |
-| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
-| Nemesis | Weak to Iron Tools while Transformed. | |
-| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
-| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
-| Staked | Weak to Wooden Tools. | |
-| Just a Prank | Any Villager who kills a Jester who does not fight back will be affected with Wither II indefinitely, until they are able to find a cure. The Jester will respawn and have their role revealed. | **One-time use.** |
+| Ability | Description | Cooldown |
+|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
+| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
+| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
+| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
+| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
+| Assassinate | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
+| Revive | Throw a Totem of Undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
+| Retaliate | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
+| High Noon | Receive Strength II for 60 seconds at noon of the in-game day. | Occurs automatically. |
+| Marksman | Arrows do one additional heart of damage. | |
+| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
+| Watch | Can see invisible players when using a Spyglass. | |
+| Peripherals | Can see invisible players within 20 blocks. | |
+| Clear Sight | Not affected by Blindness or Darkness. | |
+| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
+| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
+| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Priests. | |
+| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
+| This is Fine | Take reduced damage from fire and lava. | |
+| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
+| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
+| Tracking | See whether your targets are dead or alive. | |
+| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
+| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 5 levels of experience. | |
+| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
+| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
+| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 10 levels of experience. | |
+| Transform | Transform on full-moon nights. | Occurs automatically. |
+| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
+| Nemesis | Weak to Iron Tools while Transformed. | |
+| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
+| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
+| Staked | Weak to Wooden Tools. | |
+| Just a Prank | Any Villager who kills a Jester who does not fight back will cause an explosion and various negative effects. The Jester will respawn and have their role revealed. | **One-time use.** |
## Rules and Definitions
* **In-Game Day**: starts and ends at sunrise (tick 0)
-* **Attack**: Hit a player with a Sword, Axe, or Bow. Punches do not count to prevent false triggers.
+* **Attack**: Hit a player with a Sword, Axe, or Bow. Punches do not count (to prevent false triggers).
* **Attacked First**: Be attacked when not attacking anyone for 30 seconds prior.
* **Attacking First**: Attack someone who has not attacked anyone for 30 seconds.
-* **Unholy Abilities**: Reanimation, Ambrosia, Spell Book, Scatter, Toadify, Fog of War, Vanish, Transform, Convert, Hunting Night
- * Unholy Abilities display to Deacons for two complete in-game days (does not reset at sunrise). This is refreshed every time an unholy ability is used.
+* **Unholy Abilities**: Revive, Ambrosia, Spell Book, Scatter, Toadify, Fog of War, Vanish, Transform, Convert, Hunting Night
+ * Unholy Abilities display to Priests for two complete in-game days (does not reset at sunrise). This is refreshed every time an unholy ability is used.
* Wins by Surviving roles win with **anyone**, even Wins Alone roles.
* The game will end at sundown, when the living players have met their win conditions (or failed to, in the case of some neutral roles)
diff --git a/config.yml b/config.yml
index 76522b5..c85fe01 100644
--- a/config.yml
+++ b/config.yml
@@ -54,7 +54,7 @@ requiredRoles:
- "REANIMATOR"
- "INVESTIGATOR"
- "APOTHECARY"
- - "DEACON"
+ - "PRIEST"
- "SERIAL_KILLER"
- "HUNTER"
diff --git a/src/mddev0/mafiacraft/MafiaCraft.java b/src/mddev0/mafiacraft/MafiaCraft.java
index 8254b0e..1c56fe3 100644
--- a/src/mddev0/mafiacraft/MafiaCraft.java
+++ b/src/mddev0/mafiacraft/MafiaCraft.java
@@ -60,9 +60,9 @@ public void onEnable() {
Bukkit.getPluginManager().registerEvents(new Protection(this), this);
Bukkit.getPluginManager().registerEvents(new Succession(this), this);
Bukkit.getPluginManager().registerEvents(new Forgery(this), this);
- Bukkit.getPluginManager().registerEvents(new Assassination(this), this);
- Bukkit.getPluginManager().registerEvents(new Reanimation(this), this);
- Bukkit.getPluginManager().registerEvents(new Retaliation(this), this);
+ Bukkit.getPluginManager().registerEvents(new Assassinate(this), this);
+ Bukkit.getPluginManager().registerEvents(new Revive(this), this);
+ Bukkit.getPluginManager().registerEvents(new Retaliate(this), this);
abilityHighNoon.runTaskTimer(this, 0L, 1L); // checks every tick
Bukkit.getPluginManager().registerEvents(new Marksman(this), this);
Bukkit.getPluginManager().registerEvents(new Investigate(this), this);
diff --git a/src/mddev0/mafiacraft/abilities/Ability.java b/src/mddev0/mafiacraft/abilities/Ability.java
index 3eb83b9..fb06d4e 100644
--- a/src/mddev0/mafiacraft/abilities/Ability.java
+++ b/src/mddev0/mafiacraft/abilities/Ability.java
@@ -2,47 +2,86 @@
@SuppressWarnings("unused")
public enum Ability {
- PROTECTION("Protection"),
- CHARISMA("Charisma"), // Has no class
- SUCCESSION("Succession"),
- FORGERY("Forgery"),
- ASSASSINATION("Assassination"),
- REANIMATION("Reanimation"),
- RETALIATION("Retaliation"),
- HIGH_NOON("High Noon"),
- MARKSMAN("Marksman"),
- INVESTIGATE("Investigate"),
- WATCH("Watch"),
- PERIPHERALS("Peripherals"),
- CLEAR_SIGHT("Clear Sight"),
- RESCUE("Rescue"),
- AMBROSIA("Ambrosia"),
- INQUISITION("Inquisition"),
- AMBUSH("Ambush"),
- THIS_IS_FINE("This is Fine"),
- DODGE_ROLL("Dodge Roll"),
- TARGET("Target"), // Has no class
- TRACKING("Tracking"), // Has no class
- SPELL_BOOK("Spell Book"),
- SCATTER("Scatter"),
- TOADIFY("Toadify"),
- FOG_OF_WAR("Fog of War"),
- VANISH("Vanish"),
- TRANSFORM("Transform"),
- RAMPAGE("Rampage"),
- NEMESIS("Nemesis"),
- CONVERT("Convert"),
- NIGHT_OWL("Night Owl"),
- STAKED("Staked"),
- JUST_A_PRANK("Just a Prank");
+ PROTECTION("Protection",
+ "When attacked first, receive Resistance II for 30 seconds."),
+ CHARISMA("Charisma",
+ "Appear innocent to Investigators, despite being a member of the Mafia."), // Has no class
+ SUCCESSION("Succession",
+ "When the Godfather dies, one Mafioso will be selected at random to become the new Godfather."),
+ FORGERY("Forgery",
+ "Drop a paper named 'Forgery' on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day."),
+ ASSASSINATE("Assassinate",
+ "When attacking first, gains Strength I and Speed I for 60 seconds."),
+ REVIVE("Revive",
+ "Throw a Totem of Undying into a soul flame. Then, choose a dead player to resurrect."),
+ RETALIATE("Retaliate",
+ "When attacked first, receive Strength II and Resistance II for 30 seconds."),
+ HIGH_NOON("High Noon",
+ "Receive Strength II for 60 seconds at noon of the in-game day."),
+ MARKSMAN("Marksman",
+ "Arrows do one additional heart of damage."),
+ INVESTIGATE("Investigate",
+ "Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia."),
+ WATCH("Watch",
+ "Can see invisible players when using a Spyglass."),
+ PERIPHERALS("Peripherals",
+ "Can see invisible players within 20 blocks."),
+ CLEAR_SIGHT("Clear Sight",
+ "Not affected by Blindness or Darkness."),
+ RESCUE("Rescue",
+ "If a player (other than you), would otherwise die within 16 blocks of you, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds."),
+ AMBROSIA("Ambrosia",
+ "Brew a special potion by throwing a Golden Apple, Bottle of Honey, and Bucket of Milk into a heated cauldron."),
+ INQUISITION("Inquisition",
+ "Any player who has is using or has recently used any magical ability will display a subtle particle effect to Priests."),
+ AMBUSH("Ambush",
+ "When attacking first, gains Strength II for 30 seconds."),
+ THIS_IS_FINE("This is Fine",
+ "Take reduced damage from fire and lava."),
+ DODGE_ROLL("Dodge Roll",
+ "Take significantly less damage from explosions and fall damage."),
+ TARGET("Target",
+ "Receive a list at the beginning of the game of targets."), // Has no class
+ TRACKING("Tracking",
+ "See whether your targets are dead or alive."), // Has no class
+ SPELL_BOOK("Spell Book",
+ "Craft a spell book by throwing any enchanted book into normal fire. Use to switch spells."),
+ SCATTER("Scatter",
+ "Grant one person Speed IV for 20 seconds. Costs 5 levels of experience."),
+ TOADIFY("Toadify",
+ "Inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience."),
+ FOG_OF_WAR("Fog of War",
+ "Inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience."),
+ VANISH("Vanish",
+ "Grant one person Invisibility for 3 minutes. Costs 10 levels of experience."),
+ TRANSFORM("Transform",
+ "Transform on full-moon nights."),
+ RAMPAGE("Rampage",
+ "For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V)."),
+ NEMESIS("Nemesis",
+ "Weak to Iron Tools while Transformed."),
+ CONVERT("Convert",
+ "All kills will not permanently kill the player, instead they will respawn as a Vampire."),
+ NIGHT_OWL("Night Owl",
+ "Affected by Weakness II during the day."),
+ STAKED("Staked",
+ "Weak to Wooden Tools."),
+ JUST_A_PRANK("Just a Prank","Be killed by a member of the Village without fighting back to respawn.");
private final String NAME;
- Ability(String name) {
+ private final String DESCRIPTION;
+
+ Ability(String name, String desc) {
this.NAME = name;
+ this.DESCRIPTION = desc;
}
- public String fullName() {
+ public String toString() {
return NAME;
}
+
+ public String getDesc() {
+ return DESCRIPTION;
+ }
}
diff --git a/src/mddev0/mafiacraft/abilities/Ambrosia.java b/src/mddev0/mafiacraft/abilities/Ambrosia.java
index 074a94d..584b50f 100644
--- a/src/mddev0/mafiacraft/abilities/Ambrosia.java
+++ b/src/mddev0/mafiacraft/abilities/Ambrosia.java
@@ -101,7 +101,6 @@ public void run() {
}
}
- // TODO: Make this take werewolves out of transformation?
// When potion lands
@EventHandler
public void onPotionLand(PotionSplashEvent splash) {
diff --git a/src/mddev0/mafiacraft/abilities/Assassination.java b/src/mddev0/mafiacraft/abilities/Assassinate.java
similarity index 88%
rename from src/mddev0/mafiacraft/abilities/Assassination.java
rename to src/mddev0/mafiacraft/abilities/Assassinate.java
index 9633373..4d6c398 100644
--- a/src/mddev0/mafiacraft/abilities/Assassination.java
+++ b/src/mddev0/mafiacraft/abilities/Assassinate.java
@@ -12,11 +12,11 @@
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-public final class Assassination implements Listener {
+public final class Assassinate implements Listener {
private final MafiaCraft plugin;
- public Assassination(MafiaCraft plugin) {
+ public Assassinate(MafiaCraft plugin) {
this.plugin = plugin;
}
@@ -31,12 +31,12 @@ public void onAttackPlayer(EntityDamageByEntityEvent damage) {
if (damager != null) {
// Only take action if not null
MafiaPlayer attacker = plugin.getLivingPlayers().get(damager.getUniqueId());
- if (attacker != null && attacker.getRole().getAbilities().contains(Ability.ASSASSINATION) && !attacker.getCooldowns().isOnCooldown(Ability.ASSASSINATION)) {
+ if (attacker != null && attacker.getRole().getAbilities().contains(Ability.ASSASSINATE) && !attacker.getCooldowns().isOnCooldown(Ability.ASSASSINATE)) {
damager.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 1200, 0, false, false, true));
damager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 1200, 0, false, false, true));
long waitUntil = plugin.getWorldFullTime() + 24000L;
waitUntil = waitUntil - (waitUntil % 24000);
- attacker.getCooldowns().startCooldown(Ability.ASSASSINATION, waitUntil);
+ attacker.getCooldowns().startCooldown(Ability.ASSASSINATE, waitUntil);
}
}
}
diff --git a/src/mddev0/mafiacraft/abilities/Retaliation.java b/src/mddev0/mafiacraft/abilities/Retaliate.java
similarity index 90%
rename from src/mddev0/mafiacraft/abilities/Retaliation.java
rename to src/mddev0/mafiacraft/abilities/Retaliate.java
index 43b5f4e..9074b5c 100644
--- a/src/mddev0/mafiacraft/abilities/Retaliation.java
+++ b/src/mddev0/mafiacraft/abilities/Retaliate.java
@@ -12,11 +12,11 @@
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
-public final class Retaliation implements Listener {
+public final class Retaliate implements Listener {
private final MafiaCraft plugin;
- public Retaliation(MafiaCraft plugin) {
+ public Retaliate(MafiaCraft plugin) {
this.plugin = plugin;
}
@@ -26,9 +26,9 @@ public void onPlayerAttacked(EntityDamageByEntityEvent damage) {
if (!plugin.getActive()) return; // DO NOTHING IF NOT ACTIVE!
MafiaPlayer attacked = plugin.getLivingPlayers().get(damage.getEntity().getUniqueId());
if (damage.getEntityType() == EntityType.PLAYER && attacked != null &&
- attacked.getRole().getAbilities().contains(Ability.RETALIATION)) {
- // Player attacked has retaliation ability
- if (!attacked.getStatus().hasStatus(StatusData.Status.IN_COMBAT) && !attacked.getCooldowns().isOnCooldown(Ability.RETALIATION)) {
+ attacked.getRole().getAbilities().contains(Ability.RETALIATE)) {
+ // Player attacked has Retaliate ability
+ if (!attacked.getStatus().hasStatus(StatusData.Status.IN_COMBAT) && !attacked.getCooldowns().isOnCooldown(Ability.RETALIATE)) {
// Does not trigger if player was the attacker or if ability is on cooldown
if (CombatState.findAttackingPlayer(damage) != null) {
// was attacked by a player
@@ -37,7 +37,7 @@ public void onPlayerAttacked(EntityDamageByEntityEvent damage) {
toRetaliate.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE,600,1,false,false,true));
long waitUntil = plugin.getWorldFullTime() + 24000L;
waitUntil = waitUntil - (waitUntil % 24000); // Cooldown ends at dawn
- attacked.getCooldowns().startCooldown(Ability.RETALIATION, waitUntil);
+ attacked.getCooldowns().startCooldown(Ability.RETALIATE, waitUntil);
}
}
}
diff --git a/src/mddev0/mafiacraft/abilities/Reanimation.java b/src/mddev0/mafiacraft/abilities/Revive.java
similarity index 78%
rename from src/mddev0/mafiacraft/abilities/Reanimation.java
rename to src/mddev0/mafiacraft/abilities/Revive.java
index 8d7524d..1cced6d 100644
--- a/src/mddev0/mafiacraft/abilities/Reanimation.java
+++ b/src/mddev0/mafiacraft/abilities/Revive.java
@@ -1,7 +1,7 @@
package mddev0.mafiacraft.abilities;
import mddev0.mafiacraft.MafiaCraft;
-import mddev0.mafiacraft.gui.ReanimationGUI;
+import mddev0.mafiacraft.gui.ReviveGUI;
import mddev0.mafiacraft.player.MafiaPlayer;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -13,12 +13,12 @@
import java.util.Objects;
-// XXX: There is probably a bug somewhere in the Reanimation ability. We'll see during testing
-public final class Reanimation implements Listener {
+// XXX: There is probably a bug somewhere in the Revive ability. We'll see during testing
+public final class Revive implements Listener {
private final MafiaCraft plugin;
- public Reanimation(MafiaCraft plugin) {
+ public Revive(MafiaCraft plugin) {
this.plugin = plugin;
}
@@ -32,9 +32,9 @@ public void onItemDestroy(EntityCombustByBlockEvent damage) {
// Valid item, check player and cooldown
if (item.getThrower() == null) return;
MafiaPlayer thrower = plugin.getLivingPlayers().get(item.getThrower());
- if (thrower.getRole().getAbilities().contains(Ability.REANIMATION) && !thrower.getCooldowns().isOnCooldown(Ability.REANIMATION)) {
+ if (thrower.getRole().getAbilities().contains(Ability.REVIVE) && !thrower.getCooldowns().isOnCooldown(Ability.REVIVE)) {
item.remove();
- ReanimationGUI gui = new ReanimationGUI(plugin);
+ ReviveGUI gui = new ReviveGUI(plugin);
gui.open(Objects.requireNonNull(Bukkit.getPlayer(item.getThrower())));
}
}
diff --git a/src/mddev0/mafiacraft/abilities/SpellBook.java b/src/mddev0/mafiacraft/abilities/SpellBook.java
index 55f1b60..d910079 100644
--- a/src/mddev0/mafiacraft/abilities/SpellBook.java
+++ b/src/mddev0/mafiacraft/abilities/SpellBook.java
@@ -80,7 +80,7 @@ public void onBookClick(PlayerInteractEvent click) {
} while (sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED) == Ability.SPELL_BOOK);
click.getPlayer().sendMessage(ChatColor.LIGHT_PURPLE +
"Changed spells to " + ChatColor.GRAY +
- ((Ability) sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED)).fullName());
+ (sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED)).toString());
}
}
}
diff --git a/src/mddev0/mafiacraft/gui/InfoGUI.java b/src/mddev0/mafiacraft/gui/InfoGUI.java
index 455afc3..642133f 100644
--- a/src/mddev0/mafiacraft/gui/InfoGUI.java
+++ b/src/mddev0/mafiacraft/gui/InfoGUI.java
@@ -125,27 +125,30 @@ private void fillInventory() {
abilItem = new ItemStack(Material.GRAY_CONCRETE);
abilMeta = abilItem.getItemMeta();
assert abilMeta != null;
- abilMeta.setDisplayName(ChatColor.DARK_GRAY + abil.fullName());
+ abilMeta.setDisplayName(ChatColor.DARK_GRAY + abil.toString());
ArrayList abilLore = new ArrayList<>();
abilLore.add(ChatColor.RESET + "" + ChatColor.GRAY + "This ability may only be used once.");
+ abilLore.add(ChatColor.DARK_AQUA + "" + ChatColor.ITALIC + abil.getDesc());
abilMeta.setLore(abilLore);
abilItem.setItemMeta(abilMeta);
} else if (caller.getCooldowns().isOnCooldown(abil)) { // On Cooldown
abilItem = new ItemStack(Material.YELLOW_CONCRETE);
abilMeta = abilItem.getItemMeta();
assert abilMeta != null;
- abilMeta.setDisplayName(ChatColor.GOLD + abil.fullName());
+ abilMeta.setDisplayName(ChatColor.GOLD + abil.toString());
ArrayList abilLore = new ArrayList<>();
abilLore.add(ChatColor.RESET + "" + ChatColor.YELLOW + "This ability is on cooldown.");
+ abilLore.add(ChatColor.DARK_AQUA + "" + ChatColor.ITALIC + abil.getDesc());
abilMeta.setLore(abilLore);
abilItem.setItemMeta(abilMeta);
} else { // Not On Cooldown
abilItem = new ItemStack(Material.WHITE_CONCRETE);
abilMeta = abilItem.getItemMeta();
assert abilMeta != null;
- abilMeta.setDisplayName(ChatColor.AQUA + abil.fullName());
+ abilMeta.setDisplayName(ChatColor.AQUA + abil.toString());
ArrayList abilLore = new ArrayList<>();
abilLore.add(ChatColor.RESET + "" + ChatColor.WHITE + "This ability is available!");
+ abilLore.add(ChatColor.DARK_AQUA + "" + ChatColor.ITALIC + abil.getDesc());
abilMeta.setLore(abilLore);
abilItem.setItemMeta(abilMeta);
}
diff --git a/src/mddev0/mafiacraft/gui/ReanimationGUI.java b/src/mddev0/mafiacraft/gui/ReviveGUI.java
similarity index 95%
rename from src/mddev0/mafiacraft/gui/ReanimationGUI.java
rename to src/mddev0/mafiacraft/gui/ReviveGUI.java
index e282443..f05de83 100644
--- a/src/mddev0/mafiacraft/gui/ReanimationGUI.java
+++ b/src/mddev0/mafiacraft/gui/ReviveGUI.java
@@ -18,12 +18,12 @@
import java.util.Objects;
import java.util.UUID;
-public final class ReanimationGUI implements Listener {
+public final class ReviveGUI implements Listener {
private final MafiaCraft plugin;
private final Inventory inv;
- public ReanimationGUI(MafiaCraft plugin) {
+ public ReviveGUI(MafiaCraft plugin) {
this.plugin = plugin;
Bukkit.getPluginManager().registerEvents(this, plugin);
@@ -61,7 +61,7 @@ public void onHeadClick(final InventoryClickEvent click) {
// SCUFFED: So many requireNonNull... am I doing this wrong?
UUID toReanimate = Objects.requireNonNull(((SkullMeta) Objects.requireNonNull(clicked.getItemMeta())).getOwningPlayer()).getUniqueId();
Long cooldownExpires = (plugin.getWorldFullTime() + 168000L) - (plugin.getWorldFullTime() % 24000);
- plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getCooldowns().startCooldown(Ability.REANIMATION, cooldownExpires);
+ plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getCooldowns().startCooldown(Ability.REVIVE, cooldownExpires);
plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getStatus().startStatus(StatusData.Status.UNHOLY, plugin.getWorldFullTime() + 48000L);
plugin.getPlayerList().get(toReanimate).makeAlive();
click.getWhoClicked().sendMessage(ChatColor.GREEN + Bukkit.getOfflinePlayer(toReanimate).getName() + " has been revived.");
diff --git a/src/mddev0/mafiacraft/player/Role.java b/src/mddev0/mafiacraft/player/Role.java
index af7c281..2a86e80 100644
--- a/src/mddev0/mafiacraft/player/Role.java
+++ b/src/mddev0/mafiacraft/player/Role.java
@@ -8,16 +8,16 @@ public enum Role {
GODFATHER("Godfather", true, Team.MAFIA, Ability.PROTECTION, Ability.AMBUSH),
MAFIOSO("Mafioso", false, Team.MAFIA, Ability.SUCCESSION),
FRAMER("Framer", false, Team.MAFIA, Ability.FORGERY),
- ASSASSIN("Assassin", false, Team.MAFIA, Ability.ASSASSINATION),
+ ASSASSIN("Assassin", false, Team.MAFIA, Ability.ASSASSINATE),
// TODO: BREWER("Brewer", false, Team.MAFIA, ???),
- REANIMATOR("Reanimator", true, Team.VILLAGE, Ability.REANIMATION),
- VETERAN("Veteran", false, Team.VILLAGE, Ability.RETALIATION),
+ REANIMATOR("Reanimator", true, Team.VILLAGE, Ability.REVIVE),
+ VETERAN("Veteran", false, Team.VILLAGE, Ability.RETALIATE),
DEPUTY("Deputy", false, Team.VILLAGE, Ability.HIGH_NOON, Ability.MARKSMAN),
INVESTIGATOR("Investigator", false, Team.VILLAGE, Ability.INVESTIGATE),
LOOKOUT("Lookout", false, Team.VILLAGE, Ability.WATCH, Ability.PERIPHERALS, Ability.CLEAR_SIGHT),
DOCTOR("Doctor", false, Team.VILLAGE, Ability.RESCUE),
APOTHECARY("Apothecary", true, Team.VILLAGE, Ability.AMBROSIA),
- DEACON("Deacon", false, Team.VILLAGE, Ability.INQUISITION),
+ PRIEST("Priest", false, Team.VILLAGE, Ability.INQUISITION),
SERIAL_KILLER("Serial Killer", false, Team.SOLO, Ability.PROTECTION, Ability.AMBUSH),
TRAPPER("Trapper", false, Team.SOLO, Ability.THIS_IS_FINE, Ability.DODGE_ROLL),
HUNTER("Hunter", false, Team.NONE, Ability.TARGET, Ability.TRACKING),
From c099e67e984b120b2d793bc666b167a82e5015f5 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Sat, 30 Dec 2023 03:09:08 -0600
Subject: [PATCH 09/20] hideDeadPlayers now applies to revive command.
---
.../mafiacraft/commands/MafiaCraftAdminCMD.java | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java b/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java
index 5fed3de..06ed508 100644
--- a/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java
+++ b/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java
@@ -255,15 +255,17 @@ else if (p.getRole().toString().equals("Trapper"))
p.teleport(toSpawn);
}
p.setGameMode(GameMode.SURVIVAL);
- // all dead players should be hidden, p should be unhidden
- for (Player other : plugin.getServer().getOnlinePlayers()) {
- other.showPlayer(plugin, p);
- MafiaPlayer spec = plugin.getPlayerList().get(other.getUniqueId());
- if (spec == null || !spec.isLiving()) {
- p.hidePlayer(plugin, other);
+ if (plugin.getConfig().getBoolean("hideDeadPlayers")){
+ // all dead players should be hidden, p should be unhidden
+ for (Player other : plugin.getServer().getOnlinePlayers()) {
+ other.showPlayer(plugin, p);
+ MafiaPlayer spec = plugin.getPlayerList().get(other.getUniqueId());
+ if (spec == null || !spec.isLiving()) {
+ p.hidePlayer(plugin, other);
+ }
}
+ Bukkit.broadcastMessage(ChatColor.YELLOW + p.getName() + " joined the game");
}
- Bukkit.broadcastMessage(ChatColor.YELLOW + p.getName() + " joined the game");
sender.sendMessage(ChatColor.GREEN + args[1] + " has been revived.");
return true;
}
From 9b30fec7ced3c9a5543e4d210529bc8b83a9ff59 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Sat, 30 Dec 2023 03:31:40 -0600
Subject: [PATCH 10/20] Tweaked effects and cooldowns
Now works better for servers which are online at all times
---
README.md | 74 +++++++++----------
src/mddev0/mafiacraft/abilities/Ambrosia.java | 3 +-
src/mddev0/mafiacraft/abilities/Ambush.java | 4 +-
.../mafiacraft/abilities/Assassinate.java | 6 +-
src/mddev0/mafiacraft/abilities/HighNoon.java | 2 +-
.../mafiacraft/abilities/Protection.java | 4 +-
src/mddev0/mafiacraft/abilities/Rescue.java | 2 +-
.../mafiacraft/abilities/Retaliate.java | 2 +-
src/mddev0/mafiacraft/gui/ReviveGUI.java | 2 +-
9 files changed, 49 insertions(+), 50 deletions(-)
diff --git a/README.md b/README.md
index 22aee65..ab055ef 100644
--- a/README.md
+++ b/README.md
@@ -34,8 +34,8 @@ Listed below are all the roles and abilities planned, as well as some definition
| Role | Description | Abilities | Tasks |
|--------------|------------------------------------------------------------------------------------|-----------------------------------------|-----------------------------------------------------------|
-| *Reanimator* | A Villager who discovered the long lost art of resurrection. | Revive | Reanimate players to help the Village survive. |
-| Veteran | A war hero whose defense instincts never left when they retired from the military. | Retaliate | Defend yourself from attackers to help the Villagers win. |
+| *Reanimator* | A Villager who discovered the long lost art of resurrection. | Revive | Reanimate players to help the Village survive. |
+| Veteran | A war hero whose defense instincts never left when they retired from the military. | Retaliate | Defend yourself from attackers to help the Villagers win. |
| Deputy | A fighter with honor and standards, who will always rise to a fair challenge. | High Noon,
Marksman | Take down those who the Village sees as a threat. |
| Investigator | An armchair detective whose skills can finally be put to good use. | Investigate | Discover who is really on the side of the Villagers. |
| Lookout | An eagle-eyed observer who always seems to know who's been where. | Watch,
Peripherals,
Clear Sight | Gather information to help the Village. |
@@ -64,41 +64,41 @@ _* These roles only win if they complete their special task **AND** survive unti
## Abilities
-| Ability | Description | Cooldown |
-|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
-| Protection | When attacked first, receive Resistance II for 30 seconds. | Once per in-game day. |
-| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
-| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
-| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
-| Assassinate | When attacking first, gains Strength I and Speed I for 60 seconds. | Once per in-game day. |
-| Revive | Throw a Totem of Undying into a soul flame. Then, choose a dead player to resurrect. | Once per in-game week. |
-| Retaliate | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once per in-game day. |
-| High Noon | Receive Strength II for 60 seconds at noon of the in-game day. | Occurs automatically. |
-| Marksman | Arrows do one additional heart of damage. | |
-| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
-| Watch | Can see invisible players when using a Spyglass. | |
-| Peripherals | Can see invisible players within 20 blocks. | |
-| Clear Sight | Not affected by Blindness or Darkness. | |
-| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once per in-game day. |
-| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be brewed once per in-game week. |
-| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Priests. | |
-| Ambush | When attacking first, gains Strength II for 30 seconds. | Once per in-game day. |
-| This is Fine | Take reduced damage from fire and lava. | |
-| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
-| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
-| Tracking | See whether your targets are dead or alive. | |
-| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
-| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 5 levels of experience. | |
-| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
-| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
-| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 10 levels of experience. | |
-| Transform | Transform on full-moon nights. | Occurs automatically. |
-| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
-| Nemesis | Weak to Iron Tools while Transformed. | |
-| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
-| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
-| Staked | Weak to Wooden Tools. | |
-| Just a Prank | Any Villager who kills a Jester who does not fight back will cause an explosion and various negative effects. The Jester will respawn and have their role revealed. | **One-time use.** |
+| Ability | Description | Cooldown |
+|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------|
+| Protection | When attacked first, receive Resistance II for 60 seconds. | Once every 3 in-game days. |
+| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
+| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
+| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
+| Assassinate | When attacking first, gains Strength I and Speed I for 2 minutes. | Once every 3 in-game days. |
+| Revive | Throw a Totem of Undying into a soul flame. Then, choose a dead player to resurrect. | Once every 24 (real) hours. |
+| Retaliate | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once every 3 in-game days. |
+| High Noon | Receive Strength II for 30 seconds at noon of the in-game day. | Occurs automatically. |
+| Marksman | Arrows do one additional heart of damage. | |
+| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
+| Watch | Can see invisible players when using a Spyglass. | |
+| Peripherals | Can see invisible players within 20 blocks. | |
+| Clear Sight | Not affected by Blindness or Darkness. | |
+| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once every 3 in-game days. |
+| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be *brewed* every 12 (real) hours. |
+| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Priests. | |
+| Ambush | When attacking first, gains Strength II for 60 seconds. | Once every 3 in-game days. |
+| This is Fine | Take reduced damage from fire and lava. | |
+| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
+| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
+| Tracking | See whether your targets are dead or alive. | |
+| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
+| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 5 levels of experience. | |
+| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
+| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
+| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 10 levels of experience. | |
+| Transform | Transform on full-moon nights. | Occurs automatically. |
+| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
+| Nemesis | Weak to Iron Tools while Transformed. | |
+| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
+| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
+| Staked | Weak to Wooden Tools. | |
+| Just a Prank | Any Villager who kills a Jester who does not fight back will cause an explosion and various negative effects. The Jester will respawn and have their role revealed. | **One-time use.** |
## Rules and Definitions
diff --git a/src/mddev0/mafiacraft/abilities/Ambrosia.java b/src/mddev0/mafiacraft/abilities/Ambrosia.java
index 584b50f..eab4308 100644
--- a/src/mddev0/mafiacraft/abilities/Ambrosia.java
+++ b/src/mddev0/mafiacraft/abilities/Ambrosia.java
@@ -87,8 +87,7 @@ public void run() {
Item spawned = (Item) i.getWorld().spawnEntity(b.getLocation(), EntityType.DROPPED_ITEM);
spawned.setItemStack(ambrosiaItem);
// Add cooldown to thrower
- long waitUntil = plugin.getWorldFullTime() + (24000L * 7); // 7 days later
- waitUntil = waitUntil - (waitUntil % 24000); // Round to earliest morning
+ long waitUntil = plugin.getWorldFullTime() + 864000L; // 12 real hours later
thrower.getCooldowns().startCooldown(Ability.AMBROSIA, waitUntil);
thrower.getStatus().startStatus(StatusData.Status.UNHOLY, plugin.getWorldFullTime() + 48000L); // Two days of unholy
}
diff --git a/src/mddev0/mafiacraft/abilities/Ambush.java b/src/mddev0/mafiacraft/abilities/Ambush.java
index 4f37541..275baf0 100644
--- a/src/mddev0/mafiacraft/abilities/Ambush.java
+++ b/src/mddev0/mafiacraft/abilities/Ambush.java
@@ -33,8 +33,8 @@ public void onAttackPlayer(EntityDamageByEntityEvent damage) {
if (damager != null) {
// Only take action if not null
if (damagerMP.getRole().getAbilities().contains(Ability.AMBUSH) && !damagerMP.getCooldowns().isOnCooldown(Ability.AMBUSH)) {
- damager.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 600, 1, false, false, true));
- long waitUntil = plugin.getWorldFullTime() + 24000L;
+ damager.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 1200, 1, false, false, true));
+ long waitUntil = plugin.getWorldFullTime() + 24000L * 3;
waitUntil = waitUntil - (waitUntil % 24000);
damagerMP.getCooldowns().startCooldown(Ability.AMBUSH, waitUntil);
}
diff --git a/src/mddev0/mafiacraft/abilities/Assassinate.java b/src/mddev0/mafiacraft/abilities/Assassinate.java
index 4d6c398..0e6f643 100644
--- a/src/mddev0/mafiacraft/abilities/Assassinate.java
+++ b/src/mddev0/mafiacraft/abilities/Assassinate.java
@@ -32,9 +32,9 @@ public void onAttackPlayer(EntityDamageByEntityEvent damage) {
// Only take action if not null
MafiaPlayer attacker = plugin.getLivingPlayers().get(damager.getUniqueId());
if (attacker != null && attacker.getRole().getAbilities().contains(Ability.ASSASSINATE) && !attacker.getCooldowns().isOnCooldown(Ability.ASSASSINATE)) {
- damager.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 1200, 0, false, false, true));
- damager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 1200, 0, false, false, true));
- long waitUntil = plugin.getWorldFullTime() + 24000L;
+ damager.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 2400, 0, false, false, true));
+ damager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 2400, 0, false, false, true));
+ long waitUntil = plugin.getWorldFullTime() + 24000L * 3;
waitUntil = waitUntil - (waitUntil % 24000);
attacker.getCooldowns().startCooldown(Ability.ASSASSINATE, waitUntil);
}
diff --git a/src/mddev0/mafiacraft/abilities/HighNoon.java b/src/mddev0/mafiacraft/abilities/HighNoon.java
index 28de090..f1da811 100644
--- a/src/mddev0/mafiacraft/abilities/HighNoon.java
+++ b/src/mddev0/mafiacraft/abilities/HighNoon.java
@@ -30,7 +30,7 @@ public void run() {
if (p.getValue().getRole().getAbilities().contains(Ability.HIGH_NOON)) {
Player affected = Bukkit.getPlayer(p.getKey());
if (affected != null && affected.isOnline()) {
- affected.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 1200, 1, false, false, true));
+ affected.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 600, 1, false, false, true));
}
}
}
diff --git a/src/mddev0/mafiacraft/abilities/Protection.java b/src/mddev0/mafiacraft/abilities/Protection.java
index 6b00c36..1f7fd7f 100644
--- a/src/mddev0/mafiacraft/abilities/Protection.java
+++ b/src/mddev0/mafiacraft/abilities/Protection.java
@@ -33,8 +33,8 @@ public void onPlayerAttacked(EntityDamageByEntityEvent damage) {
if (CombatState.findAttackingPlayer(damage) != null) {
// TRIGGER ABILITY
Player toProtect = (Player) damage.getEntity();
- toProtect.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,600,1,false,false,true));
- long waitUntil = plugin.getWorldFullTime() + 24000L;
+ toProtect.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,1200,1,false,false,true));
+ long waitUntil = plugin.getWorldFullTime() + 24000L * 3;
waitUntil = waitUntil - (waitUntil % 24000);
attacked.getCooldowns().startCooldown(Ability.PROTECTION, waitUntil);
}
diff --git a/src/mddev0/mafiacraft/abilities/Rescue.java b/src/mddev0/mafiacraft/abilities/Rescue.java
index df712c8..31ba6e0 100644
--- a/src/mddev0/mafiacraft/abilities/Rescue.java
+++ b/src/mddev0/mafiacraft/abilities/Rescue.java
@@ -45,7 +45,7 @@ public void onPlayerDamaged(EntityDamageEvent damage) {
damaged.sendMessage(ChatColor.AQUA + "You were saved from death!");
// Handle the rescuer
e.sendMessage(ChatColor.AQUA + "You saved " + ChatColor.GREEN + damaged.getName() + ChatColor.AQUA + " from death!");
- long waitUntil = plugin.getWorldFullTime() + 24000L;
+ long waitUntil = plugin.getWorldFullTime() + 24000L * 3;
waitUntil = waitUntil - (waitUntil % 24000); // Cooldown ends at dawn
plugin.getLivingPlayers().get(e.getUniqueId()).getCooldowns().startCooldown(Ability.RESCUE, waitUntil);
}
diff --git a/src/mddev0/mafiacraft/abilities/Retaliate.java b/src/mddev0/mafiacraft/abilities/Retaliate.java
index 9074b5c..4448f58 100644
--- a/src/mddev0/mafiacraft/abilities/Retaliate.java
+++ b/src/mddev0/mafiacraft/abilities/Retaliate.java
@@ -35,7 +35,7 @@ public void onPlayerAttacked(EntityDamageByEntityEvent damage) {
Player toRetaliate = (Player) damage.getEntity();
toRetaliate.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE,600,1,false,false,true));
toRetaliate.addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE,600,1,false,false,true));
- long waitUntil = plugin.getWorldFullTime() + 24000L;
+ long waitUntil = plugin.getWorldFullTime() + 24000L * 3;
waitUntil = waitUntil - (waitUntil % 24000); // Cooldown ends at dawn
attacked.getCooldowns().startCooldown(Ability.RETALIATE, waitUntil);
}
diff --git a/src/mddev0/mafiacraft/gui/ReviveGUI.java b/src/mddev0/mafiacraft/gui/ReviveGUI.java
index f05de83..7449945 100644
--- a/src/mddev0/mafiacraft/gui/ReviveGUI.java
+++ b/src/mddev0/mafiacraft/gui/ReviveGUI.java
@@ -60,7 +60,7 @@ public void onHeadClick(final InventoryClickEvent click) {
if (clicked == null || clicked.getType().isAir()) return;
// SCUFFED: So many requireNonNull... am I doing this wrong?
UUID toReanimate = Objects.requireNonNull(((SkullMeta) Objects.requireNonNull(clicked.getItemMeta())).getOwningPlayer()).getUniqueId();
- Long cooldownExpires = (plugin.getWorldFullTime() + 168000L) - (plugin.getWorldFullTime() % 24000);
+ Long cooldownExpires = (plugin.getWorldFullTime() + 864000L);
plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getCooldowns().startCooldown(Ability.REVIVE, cooldownExpires);
plugin.getLivingPlayers().get(click.getWhoClicked().getUniqueId()).getStatus().startStatus(StatusData.Status.UNHOLY, plugin.getWorldFullTime() + 48000L);
plugin.getPlayerList().get(toReanimate).makeAlive();
From b95e80913fd2196420b57f223306c31d1a62bc85 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Sat, 30 Dec 2023 22:59:35 -0600
Subject: [PATCH 11/20] Lower Sorcerer spell costs
---
README.md | 10 +++++-----
config.yml | 8 ++++----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index ab055ef..bc136f3 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Listed below are all the roles and abilities planned, as well as some definition
| *Godfather* | The head of the local crime family. | Protection,
Charisma | Tell the members of the Mafia what to do. |
| Mafioso | A member of the local crime family. | Succession | Follow the orders of the Godfather. |
| Framer | A skilled bookkeeper turned crime-staging genius. | Forgery | Follow the orders of the Godfather. |
-| Assassin | The dedicated killer within the Mafia's ranks. | Assassinate | Follow the orders of the Godfather. |
+| Assassin | The dedicated killer within the Mafia's ranks. | Assassinate | Follow the orders of the Godfather. |
### Village Roles
@@ -88,10 +88,10 @@ _* These roles only win if they complete their special task **AND** survive unti
| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
| Tracking | See whether your targets are dead or alive. | |
| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
-| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 5 levels of experience. | |
-| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 5 levels of experience. | |
-| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience. | |
-| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 10 levels of experience. | |
+| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 4 levels of experience. | |
+| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 4 levels of experience. | |
+| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 8 levels of experience. | |
+| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 8 levels of experience. | |
| Transform | Transform on full-moon nights. | Occurs automatically. |
| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
| Nemesis | Weak to Iron Tools while Transformed. | |
diff --git a/config.yml b/config.yml
index c85fe01..8cebc55 100644
--- a/config.yml
+++ b/config.yml
@@ -32,15 +32,15 @@ peripheralsRange: 10
rescueRange: 8.0
# Cost (in levels) to trigger Scatter
-scatterCost: 5
+scatterCost: 4
# Cost (in levels) to trigger Toadify
-toadifyCost: 15
+toadifyCost: 4
# Cost (in levels) to trigger Fog of War
-fogOfWarCost: 10
+fogOfWarCost: 8
# Effective range of Fog of War
fogOfWarRange: 30
# Cost (in levels) to trigger Vanish
-vanishCost: 10
+vanishCost: 8
# Number of targets hunters will be given
hunterNumTargets: 3
From 1b350fc343d56cf2f2efdfccea5f0adfdea611e2 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Wed, 3 Jan 2024 01:52:22 -0600
Subject: [PATCH 12/20] Change version (beta release)
---
plugin.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugin.yml b/plugin.yml
index 6ee883c..b6e6a5e 100644
--- a/plugin.yml
+++ b/plugin.yml
@@ -1,6 +1,6 @@
name: MafiaCraft
main: mddev0.mafiacraft.MafiaCraft
-version: 1.1
+version: b1.1.0
api-version: 1.19
depend: [ProtocolLib]
commands:
From a0dc7969d94aada771a41c930c664eab095aa2c5 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Thu, 4 Jan 2024 05:12:45 -0600
Subject: [PATCH 13/20] Fix runtime errors and other miscellaneous fixes
* Fixed issues with Sorcerer and game saving
* Fixed null checks in ClearSight
* Updated Peripherals to use new packet protocol
* Changed Werewolf to Solo as listed in README.md
* Updated API Version
---
plugin.yml | 2 +-
.../mafiacraft/abilities/ClearSight.java | 8 ++-
.../mafiacraft/abilities/Peripherals.java | 52 ++++++++++++-------
src/mddev0/mafiacraft/player/Role.java | 2 +-
src/mddev0/mafiacraft/util/GameSaver.java | 23 ++++++--
5 files changed, 56 insertions(+), 31 deletions(-)
diff --git a/plugin.yml b/plugin.yml
index b6e6a5e..36a6585 100644
--- a/plugin.yml
+++ b/plugin.yml
@@ -1,7 +1,7 @@
name: MafiaCraft
main: mddev0.mafiacraft.MafiaCraft
version: b1.1.0
-api-version: 1.19
+api-version: 1.20
depend: [ProtocolLib]
commands:
mafiacraftadmin:
diff --git a/src/mddev0/mafiacraft/abilities/ClearSight.java b/src/mddev0/mafiacraft/abilities/ClearSight.java
index de54077..a12a317 100644
--- a/src/mddev0/mafiacraft/abilities/ClearSight.java
+++ b/src/mddev0/mafiacraft/abilities/ClearSight.java
@@ -8,8 +8,6 @@
import org.bukkit.event.entity.EntityPotionEffectEvent;
import org.bukkit.potion.PotionEffectType;
-import java.util.Objects;
-
public final class ClearSight implements Listener {
private final MafiaCraft plugin;
@@ -23,10 +21,10 @@ public ClearSight(MafiaCraft plugin) {
public void onEffectApplied(EntityPotionEffectEvent potion) {
if (!plugin.getActive()) return; // DO NOTHING IF NOT ACTIVE!
MafiaPlayer affected = plugin.getPlayerList().get(potion.getEntity().getUniqueId());
- if (potion.getEntity().getType() == EntityType.PLAYER && affected != null &&
+ if (potion.getEntity().getType() == EntityType.PLAYER && affected != null && potion.getNewEffect() != null &&
affected.getRole().getAbilities().contains(Ability.CLEAR_SIGHT) && (
- Objects.requireNonNull(potion.getNewEffect()).getType() == PotionEffectType.BLINDNESS ||
- Objects.requireNonNull(potion.getNewEffect()).getType() == PotionEffectType.DARKNESS
+ potion.getNewEffect().getType() == PotionEffectType.BLINDNESS ||
+ potion.getNewEffect().getType() == PotionEffectType.DARKNESS
))
potion.setCancelled(true); // Cancel potion effect if eligible player is being blinded
}
diff --git a/src/mddev0/mafiacraft/abilities/Peripherals.java b/src/mddev0/mafiacraft/abilities/Peripherals.java
index c80e0f7..302b924 100644
--- a/src/mddev0/mafiacraft/abilities/Peripherals.java
+++ b/src/mddev0/mafiacraft/abilities/Peripherals.java
@@ -3,7 +3,10 @@
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.wrappers.WrappedDataValue;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
+import com.google.common.collect.Lists;
import mddev0.mafiacraft.MafiaCraft;
import mddev0.mafiacraft.player.MafiaPlayer;
import org.bukkit.Bukkit;
@@ -15,6 +18,7 @@
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.potion.PotionEffectType;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
@@ -35,37 +39,45 @@ public Peripherals(MafiaCraft plugin, ProtocolManager manager) {
public void onPlayerApproach(PlayerMoveEvent move) {
if (!plugin.getActive()) return; // DO NOTHING IF NOT ACTIVE!
// Scuffed: Yeah it just checks all players every time someone moves. "This is terrible. Oh well."
- for (Map.Entry executor : plugin.getLivingPlayers().entrySet()) {
- if (!Bukkit.getOfflinePlayer(executor.getKey()).isOnline()) continue; // Do nothing for offline players!
- if (executor.getValue().getRole().getAbilities().contains(Ability.PERIPHERALS)) {
+ for (Map.Entry viewer : plugin.getLivingPlayers().entrySet()) {
+ if (!Bukkit.getOfflinePlayer(viewer.getKey()).isOnline()) continue; // Do nothing for offline players!
+ if (viewer.getValue().getRole().getAbilities().contains(Ability.PERIPHERALS)) {
// Reset all players first
for (Player p : plugin.getServer().getOnlinePlayers()) {
if (p.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
- PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
- packet.getIntegers().write(0, p.getEntityId());
- WrappedDataWatcher watcher = new WrappedDataWatcher();
- WrappedDataWatcher.Serializer serializer = WrappedDataWatcher.Registry.get(Byte.class);
- watcher.setEntity(p);
- watcher.setObject(0, serializer, (byte) (0x20)); // 0x20 set invis
- packet.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
- manager.sendServerPacket(Bukkit.getPlayer(executor.getKey()), packet);
+ PacketContainer packet = manager.createPacket(PacketType.Play.Server.ENTITY_METADATA); // Create packet
+ packet.getIntegers().write(0, p.getEntityId()); // Set player to modify
+
+ // Lists which contain metadata values to modify
+ // SEE:
+ // https://wiki.vg/Entity_metadata#Entity_Metadata
+ // https://github.com/dmulloy2/ProtocolLib/issues/2032
+ StructureModifier> watchableAccessor = packet.getDataValueCollectionModifier();
+ List values = Lists.newArrayList(
+ new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte)0x20) // 0x20 sets as invisible
+ );
+
+ watchableAccessor.write(0, values);
+ manager.sendServerPacket(Bukkit.getPlayer(viewer.getKey()), packet);
}
}
// Now remove invis for nearby players
int range = plugin.getConfig().getInt("peripheralsRange");
- for (Entity ent : Objects.requireNonNull(Bukkit.getPlayer(executor.getKey()))
+ for (Entity ent : Objects.requireNonNull(Bukkit.getPlayer(viewer.getKey()))
.getNearbyEntities(range,range,range)) {
if (ent.getType() != EntityType.PLAYER) continue;
Player found = (Player) ent;
if (found.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
- PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
- packet.getIntegers().write(0, found.getEntityId());
- WrappedDataWatcher watcher = new WrappedDataWatcher();
- WrappedDataWatcher.Serializer serializer = WrappedDataWatcher.Registry.get(Byte.class);
- watcher.setEntity(found);
- watcher.setObject(0, serializer, (byte) (0)); // 0 remove invis
- packet.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
- manager.sendServerPacket(Bukkit.getPlayer(executor.getKey()), packet);
+ PacketContainer packet = manager.createPacket(PacketType.Play.Server.ENTITY_METADATA); // Create packet
+ packet.getIntegers().write(0, ent.getEntityId()); // Set player to modify
+
+ StructureModifier> watchableAccessor = packet.getDataValueCollectionModifier();
+ List values = Lists.newArrayList(
+ new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte)0x00) // 0 sets as visible
+ );
+
+ watchableAccessor.write(0, values);
+ manager.sendServerPacket(Bukkit.getPlayer(viewer.getKey()), packet);
}
}
}
diff --git a/src/mddev0/mafiacraft/player/Role.java b/src/mddev0/mafiacraft/player/Role.java
index 2a86e80..c591bae 100644
--- a/src/mddev0/mafiacraft/player/Role.java
+++ b/src/mddev0/mafiacraft/player/Role.java
@@ -22,7 +22,7 @@ public enum Role {
TRAPPER("Trapper", false, Team.SOLO, Ability.THIS_IS_FINE, Ability.DODGE_ROLL),
HUNTER("Hunter", false, Team.NONE, Ability.TARGET, Ability.TRACKING),
SORCERER("Sorcerer", false, Team.NONE, Ability.SCATTER, Ability.TOADIFY, Ability.FOG_OF_WAR, Ability.VANISH, Ability.SPELL_BOOK),
- WEREWOLF("Werewolf", false, Team.NONE, Ability.TRANSFORM, Ability.RAMPAGE, Ability.NEMESIS),
+ WEREWOLF("Werewolf", false, Team.SOLO, Ability.TRANSFORM, Ability.RAMPAGE, Ability.NEMESIS),
VAMPIRE("Vampire", true, Team.VAMPIRES, Ability.CONVERT, Ability.NIGHT_OWL, Ability.STAKED),
JESTER("Jester", true, Team.NONE, Ability.JUST_A_PRANK);
diff --git a/src/mddev0/mafiacraft/util/GameSaver.java b/src/mddev0/mafiacraft/util/GameSaver.java
index 6d949f3..0586ce3 100644
--- a/src/mddev0/mafiacraft/util/GameSaver.java
+++ b/src/mddev0/mafiacraft/util/GameSaver.java
@@ -74,14 +74,20 @@ public static void saveGame() {
for (Map.Entry roleDataEntry : playerData.roleData().dataMap().entrySet())
if (roleDataEntry.getKey() == RoleData.DataType.HUNTER_TARGETS) { // Treat this as a collection
data.set("roleData." + roleDataEntry.getKey().name(), ((Collection>)roleDataEntry.getValue()).stream().toList());
- } else
+ } else if (roleDataEntry.getKey() == RoleData.DataType.SORCERER_SELECTED) {
+ data.set("roleData." + roleDataEntry.getKey().name(), ((Ability)roleDataEntry.getValue()).name());
+ } else {
data.set("roleData." + roleDataEntry.getKey().name(), roleDataEntry.getValue());
+ }
data.set("originalRole", playerData.originalRole().name());
for (Map.Entry originalRoleDataEntry : playerData.roleData().dataMap().entrySet())
if (originalRoleDataEntry.getKey() == RoleData.DataType.HUNTER_TARGETS) { // Treat this as a collection
data.set("originalRoleData." + originalRoleDataEntry.getKey().name(), ((Collection>)originalRoleDataEntry.getValue()).stream().toList());
- } else
+ } else if (originalRoleDataEntry.getKey() == RoleData.DataType.SORCERER_SELECTED) {
+ data.set("originalRoleData." + originalRoleDataEntry.getKey().name(), ((Ability)originalRoleDataEntry.getValue()).name());
+ } else {
data.set("originalRoleData." + originalRoleDataEntry.getKey().name(), originalRoleDataEntry.getValue());
+ }
// Cooldown Data
for (Map.Entry cooldownDataEntry : playerData.cooldowns().cooldownMap().entrySet())
data.set("cooldowns." + cooldownDataEntry.getKey().name(), cooldownDataEntry.getValue());
@@ -150,10 +156,12 @@ public static void loadGame() {
if (RoleData.DataType.valueOf(rd) == RoleData.DataType.HUNTER_TARGETS) { // SCUFFED: this is crude but it'll work
List> targets = roleDataSection.getList(RoleData.DataType.HUNTER_TARGETS.name());
if (targets == null) {
- Bukkit.getLogger().log(Level.SEVERE, "NOPE, IT'S BROKEN");
+ Bukkit.getLogger().log(Level.SEVERE, "FAILED TO GET HUNTER TARGETS FROM " + dataFile.getName());
continue;
}
roleDataMap.put(RoleData.DataType.HUNTER_TARGETS, new HashSet<>(targets));
+ } else if (RoleData.DataType.valueOf(rd) == RoleData.DataType.SORCERER_SELECTED) {
+ roleDataMap.put(RoleData.DataType.SORCERER_SELECTED, Ability.valueOf(roleDataSection.getString(RoleData.DataType.SORCERER_SELECTED.name())));
} else {
roleDataMap.put(RoleData.DataType.valueOf(rd), roleDataSection.get(rd));
}
@@ -168,7 +176,14 @@ public static void loadGame() {
Set rdEntries = originalRoleDataSection.getKeys(false);
for (String rd : rdEntries) {
if (RoleData.DataType.valueOf(rd) == RoleData.DataType.HUNTER_TARGETS) { // SCUFFED: this is crude but it'll work
- originalRoleDataMap.put(RoleData.DataType.HUNTER_TARGETS, new HashSet<>(originalRoleDataSection.getList(RoleData.DataType.HUNTER_TARGETS.name())));
+ List> targets = originalRoleDataSection.getList(RoleData.DataType.HUNTER_TARGETS.name());
+ if (targets == null) {
+ Bukkit.getLogger().log(Level.SEVERE, "FAILED TO GET HUNTER TARGETS FROM " + dataFile.getName());
+ continue;
+ }
+ originalRoleDataMap.put(RoleData.DataType.HUNTER_TARGETS, new HashSet<>(targets));
+ } else if (RoleData.DataType.valueOf(rd) == RoleData.DataType.SORCERER_SELECTED) {
+ originalRoleDataMap.put(RoleData.DataType.SORCERER_SELECTED, Ability.valueOf(originalRoleDataSection.getString(RoleData.DataType.SORCERER_SELECTED.name())));
} else {
originalRoleDataMap.put(RoleData.DataType.valueOf(rd), originalRoleDataSection.get(rd));
}
From e17b8ed7740fa718e64ae611d4504e664a680e68 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Thu, 4 Jan 2024 21:56:34 -0600
Subject: [PATCH 14/20] Fix issues with role randomization
---
.../mafiacraft/util/GameRandomizer.java | 33 ++++++++++++++-----
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/src/mddev0/mafiacraft/util/GameRandomizer.java b/src/mddev0/mafiacraft/util/GameRandomizer.java
index 13ca73a..e470ec8 100644
--- a/src/mddev0/mafiacraft/util/GameRandomizer.java
+++ b/src/mddev0/mafiacraft/util/GameRandomizer.java
@@ -137,23 +137,29 @@ else if (!bannedRoles.contains(r.name()))
// This loop could go on for ages... oh well
// and by ages I mean worst case is potentially infinite
final Random rand = new Random();
+ int consecutiveFailures = 0;
while (!playersToRoll.isEmpty()) {
+ if (consecutiveFailures > 100)
+ throw new RandomizationException("Stopping randomization due to possible infinite loop. This may be a fluke, " +
+ "or may be because there are more required roles of one type than the role ratios can fill.");
+
// Get random player
OfflinePlayer player = playersToRoll.get(rand.nextInt(playersToRoll.size()));
Role role = null; // this will store the assigned role
// Restock roles if there are none left
- for (Role r : Role.values())
- if (!r.isUnique() && !bannedRoles.contains(r.name())) // Role is not unique/banned
- availableRoles.add(r);
+ if (availableRoles.isEmpty()) {
+ for (Role r : Role.values())
+ if (!r.isUnique() && !bannedRoles.contains(r.name())) // Role is not unique/banned
+ availableRoles.add(r);
+ }
// If there are required roles outstanding, assign them first
if (!requiredRoles.isEmpty())
do {
try {
role = Role.valueOf(requiredRoles.get(0));
-
} catch (IllegalArgumentException ex) {
Bukkit.getLogger().log(Level.WARNING, "Skipping an invalid entry in the list of required roles: " + requiredRoles.remove(0));
}
@@ -166,20 +172,29 @@ else if (!bannedRoles.contains(r.name()))
if (numMafia > 0 || numVillage > 0 || numNeutral > 0) {
switch (role.getAlignment()) {
case MAFIA -> {
- if (numMafia <= 0) // Finish others before adding more mafia
+ if (numMafia <= 0) { // Finish others before adding more mafia
+ availableRoles.remove(role);
+ consecutiveFailures++;
continue; // Just skip this iteration :)
+ }
else // keep going, and update number of mafia
numMafia--;
}
case VILLAGE -> {
- if (numVillage <= 0) // Finish others before adding more villagers
+ if (numVillage <= 0) { // Finish others before adding more villagers
+ availableRoles.remove(role);
+ consecutiveFailures++;
continue; // Just skip this iteration :)
+ }
else // keep going, and update number of villagers
numVillage--;
}
default -> {
- if (numNeutral <= 0) // Finish others before adding more neutrals
+ if (numNeutral <= 0) { // Finish others before adding more neutrals
+ availableRoles.remove(role);
+ consecutiveFailures++;
continue; // Just skip this iteration :)
+ }
else // keep going, and update number of neutrals
numNeutral--;
}
@@ -187,6 +202,7 @@ else if (!bannedRoles.contains(r.name()))
}
// at this point we know the player can be added to the role
+ consecutiveFailures = 0;
// Prevent reselect of role
requiredRoles.remove(role.name());
availableRoles.remove(role);
@@ -198,14 +214,13 @@ else if (!bannedRoles.contains(r.name()))
plugin.getPlayerList().put(mafiaPlayer.getID(), mafiaPlayer);
if (plugin.getPlayerList().containsKey(mafiaPlayer.getID())){
playersToRoll.remove(player);
- // I think the logger is thread safe
Bukkit.getLogger().log(Level.INFO, "[MafiaCraft] Set random role for player " + player.getName() + " (" + player.getUniqueId() + ")");
} else {
Bukkit.getLogger().log(Level.WARNING, "[MafiaCraft] Could not add " + player.getName() + " (" + player.getUniqueId() + ") to the MafiaCraft player list");
}
}
- // All players should have been set up by this point do hunter targets
+ // All players should have been set up by this point, do hunter targets
for (MafiaPlayer mp : plugin.getPlayerList().values()) {
if (mp.getRole() == Role.HUNTER) {
Set targets = new HashSet<>();
From d03e2d3ba18f3de29f46931623f68e519e227786 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Thu, 4 Jan 2024 22:17:54 -0600
Subject: [PATCH 15/20] Decrease Rampage strength limit from V to III
---
README.md | 2 +-
src/mddev0/mafiacraft/abilities/Rampage.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index bc136f3..6bc37bf 100644
--- a/README.md
+++ b/README.md
@@ -93,7 +93,7 @@ _* These roles only win if they complete their special task **AND** survive unti
| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 8 levels of experience. | |
| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 8 levels of experience. | |
| Transform | Transform on full-moon nights. | Occurs automatically. |
-| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength V). | |
+| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength III). | |
| Nemesis | Weak to Iron Tools while Transformed. | |
| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
diff --git a/src/mddev0/mafiacraft/abilities/Rampage.java b/src/mddev0/mafiacraft/abilities/Rampage.java
index 17844c1..c44c609 100644
--- a/src/mddev0/mafiacraft/abilities/Rampage.java
+++ b/src/mddev0/mafiacraft/abilities/Rampage.java
@@ -46,7 +46,7 @@ public void run() {
for (MafiaPlayer p : plugin.getLivingPlayers().values()) {
if (p.getRole().getAbilities().contains(Ability.RAMPAGE)) {
if ((Boolean)p.getRoleData().getData(RoleData.DataType.WEREWOLF_TRANSFORM)) {
- int level = Math.min(5, (Integer)p.getRoleData().getData(RoleData.DataType.WEREWOLF_KILLS) - 1);
+ int level = Math.min(3, (Integer)p.getRoleData().getData(RoleData.DataType.WEREWOLF_KILLS) - 1);
if (level >= 0)
Objects.requireNonNull(Bukkit.getPlayer(p.getID())).addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 120, level, false, false, true));
}
From e568a5018a6e3a3fb8ed9e8e0d17eacd935de701 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Fri, 5 Jan 2024 01:27:48 -0600
Subject: [PATCH 16/20] Change Trapper to Bodyguard
---
README.md | 31 ++++++------
src/mddev0/mafiacraft/abilities/Ability.java | 2 +
src/mddev0/mafiacraft/gui/InfoGUI.java | 3 +-
src/mddev0/mafiacraft/player/Role.java | 2 +-
src/mddev0/mafiacraft/player/RoleData.java | 3 +-
src/mddev0/mafiacraft/util/GameFinisher.java | 50 ++++++++++---------
.../mafiacraft/util/GameRandomizer.java | 10 +++-
7 files changed, 58 insertions(+), 43 deletions(-)
diff --git a/README.md b/README.md
index 6bc37bf..7c6a7a8 100644
--- a/README.md
+++ b/README.md
@@ -40,27 +40,25 @@ Listed below are all the roles and abilities planned, as well as some definition
| Investigator | An armchair detective whose skills can finally be put to good use. | Investigate | Discover who is really on the side of the Villagers. |
| Lookout | An eagle-eyed observer who always seems to know who's been where. | Watch,
Peripherals,
Clear Sight | Gather information to help the Village. |
| Doctor | A skilled medic capable of helping those in need. | Rescue | Protect other Villagers. |
-| *Apothecary* | A skilled brewer capable of producing special concoctions. | Ambrosia | Brew potions for the Village. |
+| *Apothecary* | A skilled brewer capable of producing special concoctions. | Ambrosia | Stop the spread of the Vampires and protect the Village. |
| Priest | A religious devotee who can sense the presence of unholy abilities. | Inquisition | Find out who in the town may be harboring a secret power. |
### Neutral Roles
_Notes:
-Alone and Same Role mean only themselves (or those who share their role) and those
-who win by Surviving remaining alive.
-Win by Surviving roles can win with anyone, as long as they survive until the end of the game._
-
-| Role | Description | Abilities | Win Conditions | Tasks |
-|---------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------|----------------|----------------------------------------------------------------------------|
-| Serial Killer | An insane murderer who wants nothing more than to be alone. | Protection,
Ambush | Alone | Kill everyone without being caught. |
-| Trapper | Some people just want to see the world burn. | This is Fine,
Dodge Roll | Alone | Use traps and fire to kill everyone without being caught. |
-| Hunter | Ensure that the targets you are given die by the end of the game, and remain dead. | Target,
Tracking | Surviving* | Use any means necessary to ensure your target players die.Avoid dying. |
-| Sorcerer | A powerful spell-caster bound by no allegiances. | Scatter,
Toadify,
Fog of War,
Vanish,
Spell Book | Surviving | Use your abilities to survive. |
-| *Werewolf* | A regular person who suddenly transforms under the Full Moon. | Transform,
Rampage,
Nemesis | Alone | Kill everyone without being caught. |
-| *Vampire* | A mythical creature whose only goal is to spread their reach to as many people as possible. | Convert,
Night Owl,
Staked | Same Role | Convert or kill all others.Do not get caught. |
-| *Jester* | A clown who just wants to trick the Village into making a grave mistake. | Just a Prank | Surviving* | Be killed by a member of the Village without fighting back. |
-
-_* These roles only win if they complete their special task **AND** survive until the end of the game._
+Players who win Alone win only if there are no Mafia, Village, or Vampires remaining.
+Vampires must kill all players with the alignments the Mafia, Village, or Alone.
+Those with no alignment can win with any team, as long as their tasks and win conditions are complete._
+
+| Role | Description | Abilities | Alignment | Tasks and Win Conditions |
+|---------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------|-----------|-------------------------------------------------------------|
+| Serial Killer | An insane murderer who wants nothing more than to be alone. | Protection,
Ambush | Alone | Kill everyone without being caught. |
+| Bodyguard | Someone who's willing to put their life on the line to save another. | Protectee,
This is Fine,
Dodge Roll,Protection | None | Keep your protectee alive at any cost. |
+| Hunter | Ensure that the targets you are given die by the end of the game, and remain dead. | Target,
Tracking | None | Use any means necessary to ensure your target players die. |
+| Sorcerer | A powerful spell-caster bound by no allegiances. | Scatter,
Toadify,
Fog of War,
Vanish,
Spell Book | None | Use your abilities to survive. |
+| *Werewolf* | A regular person who suddenly transforms under the Full Moon. | Transform,
Rampage,
Nemesis | Alone | Kill everyone without being caught. |
+| *Vampire* | A mythical creature whose only goal is to spread their reach to as many people as possible. | Convert,
Night Owl,
Staked | Vampires | Convert or kill all others.
Do not get caught. |
+| *Jester* | A clown who just wants to trick the Village into making a grave mistake. | Just a Prank | None | Be killed by a member of the Village without fighting back. |
## Abilities
@@ -83,6 +81,7 @@ _* These roles only win if they complete their special task **AND** survive unti
| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be *brewed* every 12 (real) hours. |
| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Priests. | |
| Ambush | When attacking first, gains Strength II for 60 seconds. | Once every 3 in-game days. |
+| Protectee | Assigned one player to protect at the beginning of the game. | At the start of the game. |
| This is Fine | Take reduced damage from fire and lava. | |
| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
diff --git a/src/mddev0/mafiacraft/abilities/Ability.java b/src/mddev0/mafiacraft/abilities/Ability.java
index fb06d4e..ea1ec04 100644
--- a/src/mddev0/mafiacraft/abilities/Ability.java
+++ b/src/mddev0/mafiacraft/abilities/Ability.java
@@ -36,6 +36,8 @@ public enum Ability {
"Any player who has is using or has recently used any magical ability will display a subtle particle effect to Priests."),
AMBUSH("Ambush",
"When attacking first, gains Strength II for 30 seconds."),
+ PROTECTEE("Protectee",
+ "Assigned one player to protect at the beginning of the game."), // Has no class
THIS_IS_FINE("This is Fine",
"Take reduced damage from fire and lava."),
DODGE_ROLL("Dodge Roll",
diff --git a/src/mddev0/mafiacraft/gui/InfoGUI.java b/src/mddev0/mafiacraft/gui/InfoGUI.java
index 642133f..fbfc3b6 100644
--- a/src/mddev0/mafiacraft/gui/InfoGUI.java
+++ b/src/mddev0/mafiacraft/gui/InfoGUI.java
@@ -80,7 +80,7 @@ private void fillInventory() {
yield "if " + ChatColor.LIGHT_PURPLE + "killed" +
ChatColor.GRAY + " by a member of the " + ChatColor.DARK_GREEN + "Village";
else
- yield ChatColor.YELLOW + "by surviving";
+ yield ChatColor.GRAY + " by completing all " + ChatColor.YELLOW + "tasks and win conditions";
}
case VAMPIRES -> "by " + ChatColor.DARK_AQUA + "Converting all players to Vampires";
});
@@ -92,6 +92,7 @@ private void fillInventory() {
headLore.add(ChatColor.GRAY + "The names and status of your");
headLore.add(ChatColor.GRAY + "targets are listed below.");
}
+ headLore.add(ChatColor.DARK_GRAY + "See the Role List if you're still confused.");
headMeta.setLore(headLore);
head.setItemMeta(headMeta);
inv.setItem(4,head);
diff --git a/src/mddev0/mafiacraft/player/Role.java b/src/mddev0/mafiacraft/player/Role.java
index c591bae..59e3417 100644
--- a/src/mddev0/mafiacraft/player/Role.java
+++ b/src/mddev0/mafiacraft/player/Role.java
@@ -19,7 +19,7 @@ public enum Role {
APOTHECARY("Apothecary", true, Team.VILLAGE, Ability.AMBROSIA),
PRIEST("Priest", false, Team.VILLAGE, Ability.INQUISITION),
SERIAL_KILLER("Serial Killer", false, Team.SOLO, Ability.PROTECTION, Ability.AMBUSH),
- TRAPPER("Trapper", false, Team.SOLO, Ability.THIS_IS_FINE, Ability.DODGE_ROLL),
+ BODYGUARD("Bodyguard", false, Team.NONE, Ability.PROTECTEE, Ability.THIS_IS_FINE, Ability.DODGE_ROLL, Ability.PROTECTION),
HUNTER("Hunter", false, Team.NONE, Ability.TARGET, Ability.TRACKING),
SORCERER("Sorcerer", false, Team.NONE, Ability.SCATTER, Ability.TOADIFY, Ability.FOG_OF_WAR, Ability.VANISH, Ability.SPELL_BOOK),
WEREWOLF("Werewolf", false, Team.SOLO, Ability.TRANSFORM, Ability.RAMPAGE, Ability.NEMESIS),
diff --git a/src/mddev0/mafiacraft/player/RoleData.java b/src/mddev0/mafiacraft/player/RoleData.java
index 90bdd9b..0f58cc5 100644
--- a/src/mddev0/mafiacraft/player/RoleData.java
+++ b/src/mddev0/mafiacraft/player/RoleData.java
@@ -45,7 +45,8 @@ public enum DataType {
WEREWOLF_KILLS(Integer.class),
SORCERER_SELECTED(Ability.class),
JESTER_ABILITY_USED(Boolean.class),
- HUNTER_TARGETS(HashSet.class);
+ HUNTER_TARGETS(HashSet.class),
+ BODYGUARD_PROTECTEE(String.class);
private final Type TYPENAME;
DataType(Type typename) {
diff --git a/src/mddev0/mafiacraft/util/GameFinisher.java b/src/mddev0/mafiacraft/util/GameFinisher.java
index b58faef..e314bfe 100644
--- a/src/mddev0/mafiacraft/util/GameFinisher.java
+++ b/src/mddev0/mafiacraft/util/GameFinisher.java
@@ -42,19 +42,18 @@ else if (dayTime > 12786 && dayTime <= 13000 && !checkedTonight) {
// Should check if the game should end by counting each win condition
// Count remaining players
- int mafiaRemaining, villageRemaining, soloRemaining, vampRemaining, freeRemaining;
- mafiaRemaining = villageRemaining = soloRemaining = vampRemaining = freeRemaining = 0;
+ int mafiaRemaining, villageRemaining, soloRemaining, vampRemaining;
+ mafiaRemaining = villageRemaining = soloRemaining = vampRemaining = 0;
for (MafiaPlayer mp : plugin.getLivingPlayers().values()) {
switch (mp.getRole().getAlignment()) {
case VILLAGE -> villageRemaining++;
case MAFIA -> mafiaRemaining++;
case SOLO -> soloRemaining++;
case VAMPIRES -> vampRemaining++;
- case NONE -> freeRemaining++;
}
}
- // If there are no opposing groups remaining
+ // If there are no opposing groups remaining the game might be ready to end
if (mafiaRemaining + villageRemaining + soloRemaining + vampRemaining == Math.max(Math.max(mafiaRemaining, villageRemaining), Math.max(soloRemaining, vampRemaining))) {
// if that super complicated expression clears then the game might be ready to end
// Essentially checks if sum of all groups alive is equal to the number of the largest group alive (only true if all but one of them are 0)
@@ -85,7 +84,7 @@ else if (dayTime > 12786 && dayTime <= 13000 && !checkedTonight) {
winnerSet.add(winner);
if (winner.getRole() == Role.SERIAL_KILLER)
subtitle = ChatColor.GRAY + "The " + ChatColor.BLUE + ChatColor.BOLD + "Serial Killer" + ChatColor.RESET + ChatColor.GRAY + " has won!";
- else if (winner.getRole() == Role.TRAPPER)
+ else if (winner.getRole() == Role.BODYGUARD)
subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_AQUA + ChatColor.BOLD + "Trapper" + ChatColor.RESET + ChatColor.GRAY + " has won!";
else if (winner.getRole() == Role.WEREWOLF)
subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_RED + ChatColor.BOLD + "Werewolf" + ChatColor.RESET + ChatColor.GRAY + " has won!";
@@ -101,28 +100,32 @@ else if (winner.getRole() == Role.WEREWOLF)
}
subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Vampires" + ChatColor.RESET + ChatColor.GRAY + " have won!";
}
- } else if (mafiaRemaining + villageRemaining + soloRemaining + vampRemaining == 0) { // only survivors left somehow
+ } else if (mafiaRemaining + villageRemaining + soloRemaining + vampRemaining == 0) { // only unaligned left somehow
endGame = true;
subtitle = ChatColor.GRAY + "The " + ChatColor.YELLOW + ChatColor.BOLD + "Survivors" + ChatColor.RESET + ChatColor.GRAY + " have won!";
+ } else if (plugin.getLivingPlayers().isEmpty()) {
+ endGame = true;
+ subtitle = ChatColor.GRAY + "Everyone died!";
}
- // Survivor roles
- if (freeRemaining > 0) {
- // Now check if any survivor roles have reached their win conditions and are alive
- for (MafiaPlayer mp : plugin.getLivingPlayers().values()) { // survivors ONLY win if alive
- if (mp.getRole() == Role.HUNTER) {
- // Check if targets are killed
- boolean hunterWin = true;
- // SCUFFED: Yes, this next line is an unchecked cast. Guess I just have to be careful.
- for (String id : (Set)mp.getRoleData().getData(RoleData.DataType.HUNTER_TARGETS)) {
- hunterWin = hunterWin && !plugin.getPlayerList().get(UUID.fromString(id)).isLiving();
- }
- if (hunterWin) winnerSet.add(mp);
- } else if (mp.getRole() == Role.JESTER && (Boolean)mp.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED)) {
+ // Unaligned roles
+ for (MafiaPlayer mp : plugin.getLivingPlayers().values()) { // survivors ONLY win if alive
+ if (mp.getRole() == Role.HUNTER) {
+ // Check if targets are killed
+ boolean hunterWin = true;
+ // SCUFFED: Yes, this next line is an unchecked cast. Guess I just have to be careful.
+ for (String id : (Set)mp.getRoleData().getData(RoleData.DataType.HUNTER_TARGETS)) {
+ hunterWin = hunterWin && !plugin.getPlayerList().get(UUID.fromString(id)).isLiving();
+ }
+ if (hunterWin) winnerSet.add(mp);
+ } else if (mp.getRole() == Role.JESTER)
+ if ((Boolean)mp.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED)) {
winnerSet.add(mp);
- } else { // Other surviving roles have no special win conditions
+ } else if (mp.getRole() == Role.BODYGUARD)
+ if (plugin.getLivingPlayers().containsKey(UUID.fromString((String)mp.getRoleData().getData(RoleData.DataType.BODYGUARD_PROTECTEE)))) {
winnerSet.add(mp);
- }
+ } else if (mp.isLiving()) { // Other surviving roles have no special win conditions, win if alive
+ winnerSet.add(mp);
}
}
@@ -150,6 +153,7 @@ else if (winner.getRole() == Role.WEREWOLF)
winnersMessage = winnersMessage.concat(" and " + winners.get(winners.size()-1) + " are the winners!");
}
Bukkit.broadcastMessage(winnersMessage);
+
// List of all players
List playerList = new ArrayList<>();
String playerListHeader = ChatColor.GOLD + "All of the players who played in this game:";
@@ -170,7 +174,7 @@ else if (winner.getRole() == Role.WEREWOLF)
case VILLAGE -> ChatColor.DARK_GREEN;
case SOLO-> {
if (p.getRole() == Role.SERIAL_KILLER) yield ChatColor.BLUE;
- else if (p.getRole() == Role.TRAPPER) yield ChatColor.DARK_AQUA;
+ else if (p.getRole() == Role.BODYGUARD) yield ChatColor.DARK_AQUA;
else yield ChatColor.DARK_GRAY; // Should never be used
}
case NONE -> {
@@ -190,7 +194,7 @@ else if (winner.getRole() == Role.WEREWOLF)
case VILLAGE -> ChatColor.DARK_GREEN;
case SOLO -> {
if (p.getOriginalRole() == Role.SERIAL_KILLER) yield ChatColor.BLUE;
- else if (p.getOriginalRole() == Role.TRAPPER) yield ChatColor.DARK_AQUA;
+ else if (p.getOriginalRole() == Role.BODYGUARD) yield ChatColor.DARK_AQUA;
else yield ChatColor.DARK_GRAY; // Should never be used
}
case NONE -> {
diff --git a/src/mddev0/mafiacraft/util/GameRandomizer.java b/src/mddev0/mafiacraft/util/GameRandomizer.java
index e470ec8..42e548c 100644
--- a/src/mddev0/mafiacraft/util/GameRandomizer.java
+++ b/src/mddev0/mafiacraft/util/GameRandomizer.java
@@ -1,6 +1,7 @@
package mddev0.mafiacraft.util;
import mddev0.mafiacraft.MafiaCraft;
+import mddev0.mafiacraft.abilities.Ability;
import mddev0.mafiacraft.player.MafiaPlayer;
import mddev0.mafiacraft.player.Role;
import mddev0.mafiacraft.player.RoleData;
@@ -221,8 +222,9 @@ else if (!bannedRoles.contains(r.name()))
}
// All players should have been set up by this point, do hunter targets
+ // FIXME: If all roles are manually assigned, this process will never happen.
for (MafiaPlayer mp : plugin.getPlayerList().values()) {
- if (mp.getRole() == Role.HUNTER) {
+ if (mp.getRole().getAbilities().contains(Ability.TARGET)) {
Set targets = new HashSet<>();
List allLiving = new ArrayList<>(plugin.getLivingPlayers().keySet().stream().toList());
allLiving.remove(mp.getID());
@@ -231,6 +233,12 @@ else if (!bannedRoles.contains(r.name()))
targets.add(allLiving.remove(rand.nextInt(allLiving.size())).toString());
mp.getRoleData().setData(RoleData.DataType.HUNTER_TARGETS, targets);
}
+ if (mp.getRole().getAbilities().contains(Ability.PROTECTEE)) {
+ List allLiving = new ArrayList<>(plugin.getLivingPlayers().keySet().stream().toList());
+ allLiving.remove(mp.getID());
+ String protectee = allLiving.get(rand.nextInt(allLiving.size())).toString();
+ mp.getRoleData().setData(RoleData.DataType.BODYGUARD_PROTECTEE, protectee);
+ }
}
}
From b8cb8a05f6925377b750f28bb7b4a87bb6d6081c Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Fri, 5 Jan 2024 02:25:34 -0600
Subject: [PATCH 17/20] Bugfixes from multiplayer testing
---
src/mddev0/mafiacraft/MafiaCraft.java | 2 +-
src/mddev0/mafiacraft/abilities/Ambrosia.java | 5 ++++-
src/mddev0/mafiacraft/abilities/Inquisition.java | 4 ++--
src/mddev0/mafiacraft/abilities/Rampage.java | 2 +-
src/mddev0/mafiacraft/abilities/Rescue.java | 7 +++++--
src/mddev0/mafiacraft/player/MafiaPlayer.java | 4 ++--
6 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/mddev0/mafiacraft/MafiaCraft.java b/src/mddev0/mafiacraft/MafiaCraft.java
index 1c56fe3..2c56d6c 100644
--- a/src/mddev0/mafiacraft/MafiaCraft.java
+++ b/src/mddev0/mafiacraft/MafiaCraft.java
@@ -72,7 +72,7 @@ public void onEnable() {
Bukkit.getPluginManager().registerEvents(new Rescue(this), this);
abilityAmbrosia.runTaskTimer(this, 0L, 100L); // checks every 5 seconds
Bukkit.getPluginManager().registerEvents(abilityAmbrosia, this);
- abilityInquisition.runTaskTimer(this, 0L, 600L); // show particles every 10 seconds
+ abilityInquisition.runTaskTimer(this, 0L, 200L); // show particles every 10 seconds
Bukkit.getPluginManager().registerEvents(new Ambush(this), this);
Bukkit.getPluginManager().registerEvents(new ThisIsFine(this), this);
Bukkit.getPluginManager().registerEvents(new DodgeRoll(this), this);
diff --git a/src/mddev0/mafiacraft/abilities/Ambrosia.java b/src/mddev0/mafiacraft/abilities/Ambrosia.java
index eab4308..951c604 100644
--- a/src/mddev0/mafiacraft/abilities/Ambrosia.java
+++ b/src/mddev0/mafiacraft/abilities/Ambrosia.java
@@ -49,7 +49,10 @@ public void run() {
if (b.getType() == Material.WATER_CAULDRON) {
// check block below
if (i.getLocation().add(0, -1, 0).getBlock().getType() == Material.FIRE ||
- i.getLocation().add(0, -1, 0).getBlock().getType() == Material.SOUL_FIRE) {
+ i.getLocation().add(0, -1, 0).getBlock().getType() == Material.SOUL_FIRE ||
+ i.getLocation().add(0, -1, 0).getBlock().getType() == Material.CAMPFIRE ||
+ i.getLocation().add(0, -1, 0).getBlock().getType() == Material.SOUL_CAMPFIRE ||
+ i.getLocation().add(0, -1, 0).getBlock().getType() == Material.LAVA) {
// Check cauldron level
Levelled bdata = (Levelled) b.getBlockData();
if (bdata.getLevel() == bdata.getMaximumLevel()) {
diff --git a/src/mddev0/mafiacraft/abilities/Inquisition.java b/src/mddev0/mafiacraft/abilities/Inquisition.java
index 0134f78..276711d 100644
--- a/src/mddev0/mafiacraft/abilities/Inquisition.java
+++ b/src/mddev0/mafiacraft/abilities/Inquisition.java
@@ -30,8 +30,8 @@ public void run() {
if (target.getValue().getStatus().hasStatus(StatusData.Status.UNHOLY)) {
Player t = Bukkit.getPlayer(target.getKey());
assert t != null;
- s.spawnParticle(Particle.TOWN_AURA, t.getLocation().add(0,1,0), 20, 1, 1, 1);
- s.spawnParticle(Particle.SCULK_SOUL, t.getLocation().add(0,1,0), 2, 2, 2, 2);
+ s.spawnParticle(Particle.TOWN_AURA, t.getLocation().add(0,1,0), 15, 0.7, 0.7, 0.7, 0.0);
+ s.spawnParticle(Particle.SCULK_SOUL, t.getLocation().add(0,1,0), 2, 1.5, 1.5, 1.5, 0.0);
}
}
}
diff --git a/src/mddev0/mafiacraft/abilities/Rampage.java b/src/mddev0/mafiacraft/abilities/Rampage.java
index c44c609..8e36550 100644
--- a/src/mddev0/mafiacraft/abilities/Rampage.java
+++ b/src/mddev0/mafiacraft/abilities/Rampage.java
@@ -46,7 +46,7 @@ public void run() {
for (MafiaPlayer p : plugin.getLivingPlayers().values()) {
if (p.getRole().getAbilities().contains(Ability.RAMPAGE)) {
if ((Boolean)p.getRoleData().getData(RoleData.DataType.WEREWOLF_TRANSFORM)) {
- int level = Math.min(3, (Integer)p.getRoleData().getData(RoleData.DataType.WEREWOLF_KILLS) - 1);
+ int level = Math.min(3, (Integer)p.getRoleData().getData(RoleData.DataType.WEREWOLF_KILLS)) - 1;
if (level >= 0)
Objects.requireNonNull(Bukkit.getPlayer(p.getID())).addPotionEffect(new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 120, level, false, false, true));
}
diff --git a/src/mddev0/mafiacraft/abilities/Rescue.java b/src/mddev0/mafiacraft/abilities/Rescue.java
index 31ba6e0..2c2f53e 100644
--- a/src/mddev0/mafiacraft/abilities/Rescue.java
+++ b/src/mddev0/mafiacraft/abilities/Rescue.java
@@ -1,6 +1,7 @@
package mddev0.mafiacraft.abilities;
import mddev0.mafiacraft.MafiaCraft;
+import mddev0.mafiacraft.player.MafiaPlayer;
import org.bukkit.ChatColor;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -33,8 +34,10 @@ public void onPlayerDamaged(EntityDamageEvent damage) {
double range = plugin.getConfig().getDouble("rescueRange");
List nearbyEntities = damaged.getNearbyEntities(range,range,range);
for (Entity e : nearbyEntities) {
+ MafiaPlayer rescuer = plugin.getLivingPlayers().get(e.getUniqueId());
if (e.getType() == EntityType.PLAYER &&
- plugin.getLivingPlayers().get(e.getUniqueId()).getRole().getAbilities().contains(Ability.RESCUE)) {
+ rescuer.getRole().getAbilities().contains(Ability.RESCUE) &&
+ !rescuer.getCooldowns().isOnCooldown(Ability.RESCUE)) {
// a player nearby has the rescue ability
if (e.getUniqueId() != damaged.getUniqueId()) { // Can't dataMap yourself
// the player is able to be saved
@@ -47,7 +50,7 @@ public void onPlayerDamaged(EntityDamageEvent damage) {
e.sendMessage(ChatColor.AQUA + "You saved " + ChatColor.GREEN + damaged.getName() + ChatColor.AQUA + " from death!");
long waitUntil = plugin.getWorldFullTime() + 24000L * 3;
waitUntil = waitUntil - (waitUntil % 24000); // Cooldown ends at dawn
- plugin.getLivingPlayers().get(e.getUniqueId()).getCooldowns().startCooldown(Ability.RESCUE, waitUntil);
+ rescuer.getCooldowns().startCooldown(Ability.RESCUE, waitUntil);
}
}
}
diff --git a/src/mddev0/mafiacraft/player/MafiaPlayer.java b/src/mddev0/mafiacraft/player/MafiaPlayer.java
index 48473c3..9539c35 100644
--- a/src/mddev0/mafiacraft/player/MafiaPlayer.java
+++ b/src/mddev0/mafiacraft/player/MafiaPlayer.java
@@ -108,7 +108,7 @@ public void changeRole(Role newRole) {
roleData.setData(RoleData.DataType.WEREWOLF_TRANSFORM, false);
roleData.setData(RoleData.DataType.WEREWOLF_KILLS, 0);
}
- case HUNTER -> {
+ case HUNTER -> { // TODO: Deal with no players in game
Set targets = new HashSet<>();
List allLiving = new ArrayList<>(plugin.getLivingPlayers().keySet().stream().toList());
allLiving.remove(uuid);
@@ -116,7 +116,7 @@ public void changeRole(Role newRole) {
for (int i = 0; i < num; i++)
targets.add(allLiving.remove(new Random().nextInt(allLiving.size())).toString()); // SCUFFED: oops terrible practice
roleData.setData(RoleData.DataType.HUNTER_TARGETS, targets);
- }
+ } // TODO: add condition for Bodyguard
}
From 3ccae308976b8a830d1da8407da1b181b3233b37 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Fri, 5 Jan 2024 02:51:36 -0600
Subject: [PATCH 18/20] Updated Watch ability to new Protocol version
---
src/mddev0/mafiacraft/abilities/Watch.java | 42 ++++++++++++++--------
1 file changed, 28 insertions(+), 14 deletions(-)
diff --git a/src/mddev0/mafiacraft/abilities/Watch.java b/src/mddev0/mafiacraft/abilities/Watch.java
index 0add08b..9f4dd8f 100644
--- a/src/mddev0/mafiacraft/abilities/Watch.java
+++ b/src/mddev0/mafiacraft/abilities/Watch.java
@@ -3,9 +3,13 @@
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.PacketContainer;
+import com.comphenix.protocol.reflect.StructureModifier;
+import com.comphenix.protocol.wrappers.WrappedDataValue;
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
+import com.google.common.collect.Lists;
import mddev0.mafiacraft.MafiaCraft;
import mddev0.mafiacraft.player.MafiaPlayer;
+import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -15,6 +19,8 @@
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
+import java.util.List;
+
public final class Watch implements Listener {
private final MafiaCraft plugin;
@@ -48,13 +54,19 @@ public void run() {
// if spyglass is active, keep setting all players inside the spyglass as visible
for (Player p : plugin.getServer().getOnlinePlayers()) {
if (!p.equals(click.getPlayer()) && p.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
- PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
- packet.getIntegers().write(0, p.getEntityId());
- WrappedDataWatcher watcher = new WrappedDataWatcher();
- WrappedDataWatcher.Serializer serializer = WrappedDataWatcher.Registry.get(Byte.class);
- watcher.setEntity(p);
- watcher.setObject(0, serializer, (byte) (0)); // 0 remove invis
- packet.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
+ PacketContainer packet = manager.createPacket(PacketType.Play.Server.ENTITY_METADATA); // Create packet
+ packet.getIntegers().write(0, p.getEntityId()); // Set player to modify
+
+ // Lists which contain metadata values to modify
+ // SEE:
+ // https://wiki.vg/Entity_metadata#Entity_Metadata
+ // https://github.com/dmulloy2/ProtocolLib/issues/2032
+ StructureModifier> watchableAccessor = packet.getDataValueCollectionModifier();
+ List values = Lists.newArrayList(
+ new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte)0x00) // 0 sets as visible
+ );
+
+ watchableAccessor.write(0, values);
manager.sendServerPacket(click.getPlayer(), packet);
}
}
@@ -62,13 +74,15 @@ public void run() {
// spyglass is down, reset all invis players to invis
for (Player p : plugin.getServer().getOnlinePlayers()) {
if (!p.equals(click.getPlayer()) && p.hasPotionEffect(PotionEffectType.INVISIBILITY)) {
- PacketContainer packet = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
- packet.getIntegers().write(0, p.getEntityId());
- WrappedDataWatcher watcher = new WrappedDataWatcher();
- WrappedDataWatcher.Serializer serializer = WrappedDataWatcher.Registry.get(Byte.class);
- watcher.setEntity(p);
- watcher.setObject(0, serializer, (byte) (0x20)); // 0x20 set invis
- packet.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
+ PacketContainer packet = manager.createPacket(PacketType.Play.Server.ENTITY_METADATA); // Create packet
+ packet.getIntegers().write(0, p.getEntityId()); // Set player to modify
+
+ StructureModifier> watchableAccessor = packet.getDataValueCollectionModifier();
+ List values = Lists.newArrayList(
+ new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte)0x20) // 0x20 sets as invisible
+ );
+
+ watchableAccessor.write(0, values);
manager.sendServerPacket(click.getPlayer(), packet);
}
}
From 5d7d664dd97b759fe0eb62286eb475db85418270 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Fri, 5 Jan 2024 02:51:57 -0600
Subject: [PATCH 19/20] Updated Watch ability to new Protocol version
---
src/mddev0/mafiacraft/abilities/Watch.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/mddev0/mafiacraft/abilities/Watch.java b/src/mddev0/mafiacraft/abilities/Watch.java
index 9f4dd8f..5b9054e 100644
--- a/src/mddev0/mafiacraft/abilities/Watch.java
+++ b/src/mddev0/mafiacraft/abilities/Watch.java
@@ -9,7 +9,6 @@
import com.google.common.collect.Lists;
import mddev0.mafiacraft.MafiaCraft;
import mddev0.mafiacraft.player.MafiaPlayer;
-import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
From f681df3b637c169ce84e0270ce780f8addb97a75 Mon Sep 17 00:00:00 2001
From: MDdev0 <85643297+MDdev0@users.noreply.github.com>
Date: Fri, 5 Jan 2024 05:43:25 -0600
Subject: [PATCH 20/20] Overhaul of Sorcerer win condition, tweaks, bug fixes
* Sorcerer wins with either mafia or village randomly
* Made SpyglassUtil ray tracing ignore passable blocks
* Null checking error in JoinLeaveManager
* Marksman ability fixed (was not working at all)
* Changed and unified role colors in announcements and GUIs
* Bodyguard protectee shows on info GUI
* Sorcerer now unique, Jester no longer unique
* Tweaks to Just a Prank effects
* Probably more that I forgot
---
README.md | 91 ++++++++++---------
src/mddev0/mafiacraft/abilities/Ability.java | 7 +-
.../mafiacraft/abilities/JustAPrank.java | 4 +-
src/mddev0/mafiacraft/abilities/Marksman.java | 5 +-
.../mafiacraft/abilities/SpellBook.java | 3 +-
src/mddev0/mafiacraft/abilities/Vanish.java | 2 +-
.../commands/MafiaCraftAdminCMD.java | 10 +-
src/mddev0/mafiacraft/gui/InfoGUI.java | 53 +++++++++--
src/mddev0/mafiacraft/player/MafiaPlayer.java | 14 ++-
src/mddev0/mafiacraft/player/Role.java | 6 +-
src/mddev0/mafiacraft/player/RoleData.java | 1 +
src/mddev0/mafiacraft/util/GameFinisher.java | 61 ++++++++-----
.../mafiacraft/util/GameRandomizer.java | 4 +
.../mafiacraft/util/JoinLeaveManager.java | 9 +-
src/mddev0/mafiacraft/util/SpyglassUtil.java | 10 +-
15 files changed, 184 insertions(+), 96 deletions(-)
diff --git a/README.md b/README.md
index 7c6a7a8..02278f4 100644
--- a/README.md
+++ b/README.md
@@ -50,54 +50,55 @@ Players who win Alone win only if there are no Mafia, Village, or Vampires remai
Vampires must kill all players with the alignments the Mafia, Village, or Alone.
Those with no alignment can win with any team, as long as their tasks and win conditions are complete._
-| Role | Description | Abilities | Alignment | Tasks and Win Conditions |
-|---------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------|-----------|-------------------------------------------------------------|
-| Serial Killer | An insane murderer who wants nothing more than to be alone. | Protection,
Ambush | Alone | Kill everyone without being caught. |
-| Bodyguard | Someone who's willing to put their life on the line to save another. | Protectee,
This is Fine,
Dodge Roll,Protection | None | Keep your protectee alive at any cost. |
-| Hunter | Ensure that the targets you are given die by the end of the game, and remain dead. | Target,
Tracking | None | Use any means necessary to ensure your target players die. |
-| Sorcerer | A powerful spell-caster bound by no allegiances. | Scatter,
Toadify,
Fog of War,
Vanish,
Spell Book | None | Use your abilities to survive. |
-| *Werewolf* | A regular person who suddenly transforms under the Full Moon. | Transform,
Rampage,
Nemesis | Alone | Kill everyone without being caught. |
-| *Vampire* | A mythical creature whose only goal is to spread their reach to as many people as possible. | Convert,
Night Owl,
Staked | Vampires | Convert or kill all others.
Do not get caught. |
-| *Jester* | A clown who just wants to trick the Village into making a grave mistake. | Just a Prank | None | Be killed by a member of the Village without fighting back. |
+| Role | Description | Abilities | Alignment | Tasks and Win Conditions |
+|---------------|---------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|-----------|-------------------------------------------------------------|
+| Serial Killer | An insane murderer who wants nothing more than to be alone. | Protection,
Ambush | Alone | Kill everyone without being caught. |
+| Bodyguard | Someone who's willing to put their life on the line to save another. | Protectee,
Tracking,
This is Fine,
Dodge Roll | None | Keep your protectee alive at any cost. |
+| Hunter | Ensure that the targets you are given die by the end of the game, and remain dead. | Target,
Tracking | None | Use any means necessary to ensure your target players die. |
+| *Sorcerer* | A powerful spell-caster bound by an unknown allegiance. | Scatter,
Toadify,
Fog of War,
Vanish,
Spell Book,
Shadow Pledge | None | Survive to see your secret allegiance win the game. |
+| *Werewolf* | A regular person who suddenly transforms under the Full Moon. | Transform,
Rampage,
Nemesis | Alone | Kill everyone without being caught. |
+| *Vampire* | A mythical creature whose only goal is to spread their reach to as many people as possible. | Convert,
Night Owl,
Staked | Vampires | Convert or kill all others.
Do not get caught. |
+| Jester | A clown who just wants to trick the Village into making a grave mistake. | Just a Prank | None | Be killed by a member of the Village without fighting back. |
## Abilities
-| Ability | Description | Cooldown |
-|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------|
-| Protection | When attacked first, receive Resistance II for 60 seconds. | Once every 3 in-game days. |
-| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
-| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
-| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
-| Assassinate | When attacking first, gains Strength I and Speed I for 2 minutes. | Once every 3 in-game days. |
-| Revive | Throw a Totem of Undying into a soul flame. Then, choose a dead player to resurrect. | Once every 24 (real) hours. |
-| Retaliate | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once every 3 in-game days. |
-| High Noon | Receive Strength II for 30 seconds at noon of the in-game day. | Occurs automatically. |
-| Marksman | Arrows do one additional heart of damage. | |
-| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
-| Watch | Can see invisible players when using a Spyglass. | |
-| Peripherals | Can see invisible players within 20 blocks. | |
-| Clear Sight | Not affected by Blindness or Darkness. | |
-| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once every 3 in-game days. |
-| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be *brewed* every 12 (real) hours. |
-| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Priests. | |
-| Ambush | When attacking first, gains Strength II for 60 seconds. | Once every 3 in-game days. |
-| Protectee | Assigned one player to protect at the beginning of the game. | At the start of the game. |
-| This is Fine | Take reduced damage from fire and lava. | |
-| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
-| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
-| Tracking | See whether your targets are dead or alive. | |
-| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
-| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 4 levels of experience. | |
-| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 4 levels of experience. | |
-| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 8 levels of experience. | |
-| Vanish | Using the spell book, grant one person with Invisibility for 3 minutes. Costs 8 levels of experience. | |
-| Transform | Transform on full-moon nights. | Occurs automatically. |
-| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength III). | |
-| Nemesis | Weak to Iron Tools while Transformed. | |
-| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
-| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
-| Staked | Weak to Wooden Tools. | |
-| Just a Prank | Any Villager who kills a Jester who does not fight back will cause an explosion and various negative effects. The Jester will respawn and have their role revealed. | **One-time use.** |
+| Ability | Description | Cooldown |
+|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------|
+| Protection | When attacked first, receive Resistance II for 60 seconds. | Once every 3 in-game days. |
+| Charisma | Appear innocent to Investigators, despite being a member of the Mafia. | |
+| Succession | When the Godfather dies, one Mafioso will be selected at random to become the new Godfather. | |
+| Forgery | Drop a paper named *Forgery* on a player to make them appear suspicious to Investigators. Resets at the end of the in-game day. | |
+| Assassinate | When attacking first, gains Strength I and Speed I for 2 minutes. | Once every 3 in-game days. |
+| Revive | Throw a Totem of Undying into a soul flame. Then, choose a dead player to resurrect. | Once every 24 (real) hours. |
+| Retaliate | When attacked first, receive Strength II and Resistance II for 30 seconds. | Once every 3 in-game days. |
+| High Noon | Receive Strength II for 30 seconds at noon of the in-game day. | Occurs automatically. |
+| Marksman | Arrows do one additional heart of damage. | |
+| Investigate | Use a spyglass to spy on a player for 10 seconds to learn if they are suspected of being in the Mafia. *Note this only applies to Mafia roles.* | |
+| Watch | Can see invisible players when using a Spyglass. | |
+| Peripherals | Can see invisible players within 20 blocks. | |
+| Clear Sight | Not affected by Blindness or Darkness. | |
+| Rescue | If a player (other than the medic themselves), would otherwise die within 16 blocks of the medic, they will be placed at 0.5 hearts and receive Regeneration III for 15 seconds. | Once every 3 in-game days. |
+| Ambrosia | Brew a special splash potion by throwing a golden apple, bottle of honey, and bucket of milk into a heated cauldron. This will revert a Vampire back to their original role, unless that was their original role. | Can be *brewed* every 12 (real) hours. |
+| Inquisition | Any player who has is using or has recently used an Unholy Ability will display a subtle particle effect to Priests. | |
+| Ambush | When attacking first, gains Strength II for 60 seconds. | Once every 3 in-game days. |
+| Protectee | Assigned one player to protect at the beginning of the game. | At the start of the game. |
+| This is Fine | Take reduced damage from fire and lava. | |
+| Dodge Roll | Take significantly less damage from explosions and fall damage. | |
+| Target | Receive a list at the beginning of the game of targets. | At the start of the game. |
+| Tracking | See whether your targets are dead or alive. | |
+| Spell Book | Craft a spell book by throwing any enchanted book into normal fire. | |
+| Scatter | Using the spell book, grant one person Speed IV for 20 seconds. Costs 4 levels of experience. | |
+| Toadify | Using the spell book, inflict one person with Slowness V and Jump Boost V for 15 seconds. Costs 4 levels of experience. | |
+| Fog of War | Using the spell book, inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 8 levels of experience. | |
+| Vanish | Using the spell book, grant one person with Invisibility for 2 minutes. Costs 8 levels of experience. | |
+| Shadow Pledge | At the beginning of the game, you are randomly assigned alignment with the Village or Mafia. You win with this team, but they do not know this. | At the start of the game. |
+| Transform | Transform on full-moon nights. | Occurs automatically. |
+| Rampage | For every kill while Transformed, gain one level of strength for the rest of the night (maximum Strength III). | |
+| Nemesis | Weak to Iron Tools while Transformed. | |
+| Convert | All kills will not permanently kill the player, instead they will respawn as a Vampire. | |
+| Night Owl | Affected by Weakness II during the day. | Occurs automatically. |
+| Staked | Weak to Wooden Tools. | |
+| Just a Prank | Any Villager who kills a Jester who does not fight back will cause an explosion and various negative effects. The Jester will respawn and have their role revealed. | **One-time use.** |
## Rules and Definitions
diff --git a/src/mddev0/mafiacraft/abilities/Ability.java b/src/mddev0/mafiacraft/abilities/Ability.java
index ea1ec04..a20a72f 100644
--- a/src/mddev0/mafiacraft/abilities/Ability.java
+++ b/src/mddev0/mafiacraft/abilities/Ability.java
@@ -45,7 +45,7 @@ public enum Ability {
TARGET("Target",
"Receive a list at the beginning of the game of targets."), // Has no class
TRACKING("Tracking",
- "See whether your targets are dead or alive."), // Has no class
+ "See whether your targets or protectee are dead or alive."), // Has no class
SPELL_BOOK("Spell Book",
"Craft a spell book by throwing any enchanted book into normal fire. Use to switch spells."),
SCATTER("Scatter",
@@ -56,6 +56,8 @@ public enum Ability {
"Inflict everyone within 30 blocks with Blindness I for 30 seconds. Costs 10 levels of experience."),
VANISH("Vanish",
"Grant one person Invisibility for 3 minutes. Costs 10 levels of experience."),
+ SHADOW_PLEDGE("Shadow Pledge",
+ "At the beginning of the game, you are randomly assigned alignment with the Village or Mafia. You win with this team, but they do not know this."), // Has no class
TRANSFORM("Transform",
"Transform on full-moon nights."),
RAMPAGE("Rampage",
@@ -68,7 +70,8 @@ public enum Ability {
"Affected by Weakness II during the day."),
STAKED("Staked",
"Weak to Wooden Tools."),
- JUST_A_PRANK("Just a Prank","Be killed by a member of the Village without fighting back to respawn.");
+ JUST_A_PRANK("Just a Prank",
+ "Be killed by a member of the Village without fighting back to respawn.");
private final String NAME;
diff --git a/src/mddev0/mafiacraft/abilities/JustAPrank.java b/src/mddev0/mafiacraft/abilities/JustAPrank.java
index 5ba23c5..5684c58 100644
--- a/src/mddev0/mafiacraft/abilities/JustAPrank.java
+++ b/src/mddev0/mafiacraft/abilities/JustAPrank.java
@@ -47,8 +47,8 @@ public void onJesterKill(PlayerDeathEvent death) {
// For other player
Player toAffect = death.getEntity().getKiller();
toAffect.sendMessage(ChatColor.GRAY + "You killed the " + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.GRAY + "!");
- jester.getWorld().createExplosion(jester.getLocation(), 5.0f, false, false, jester);
- toAffect.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, Integer.MAX_VALUE, 1, false, true, true));
+ jester.getWorld().createExplosion(jester.getLocation(), 3.0f, false, false, jester);
+ toAffect.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, PotionEffect.INFINITE_DURATION, 2, false, true, true));
toAffect.getWorld().spawnParticle(Particle.VILLAGER_ANGRY, toAffect.getLocation().add(0, 1, 0), 10, 1, 2, 1);
// For all others
jester.getWorld().strikeLightningEffect(jester.getLocation());
diff --git a/src/mddev0/mafiacraft/abilities/Marksman.java b/src/mddev0/mafiacraft/abilities/Marksman.java
index 705fc9e..807c72c 100644
--- a/src/mddev0/mafiacraft/abilities/Marksman.java
+++ b/src/mddev0/mafiacraft/abilities/Marksman.java
@@ -20,11 +20,10 @@ public Marksman(MafiaCraft plugin) {
@EventHandler
public void onArrowShoot(EntityShootBowEvent shot) {
if (!plugin.getActive()) return; // DO NOTHING IF NOT ACTIVE!
- if (shot.getEntity().getType() != EntityType.ARROW) return;
+ if (shot.getEntity().getType() != EntityType.PLAYER) return;
// Only shots from players allowed
MafiaPlayer shooter = plugin.getLivingPlayers().get(shot.getEntity().getUniqueId());
- if (shooter != null && shooter.getRole().getAbilities().contains(Ability.MARKSMAN)
- && shot.getProjectile().getType() != EntityType.ARROW) {
+ if (shooter != null && shooter.getRole().getAbilities().contains(Ability.MARKSMAN)) {
Arrow arrow = (Arrow) shot.getProjectile();
arrow.setDamage(arrow.getDamage() + 2.0); // Add one heart
// SCUFFED: Probably make that a config value at some point
diff --git a/src/mddev0/mafiacraft/abilities/SpellBook.java b/src/mddev0/mafiacraft/abilities/SpellBook.java
index d910079..a2afdf8 100644
--- a/src/mddev0/mafiacraft/abilities/SpellBook.java
+++ b/src/mddev0/mafiacraft/abilities/SpellBook.java
@@ -77,7 +77,8 @@ public void onBookClick(PlayerInteractEvent click) {
selectedIndex += 1;
selectedIndex %= abilities.size();
sorcerer.getRoleData().setData(RoleData.DataType.SORCERER_SELECTED, abilities.stream().toList().get(selectedIndex));
- } while (sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED) == Ability.SPELL_BOOK);
+ } while (sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED) == Ability.SPELL_BOOK ||
+ sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED) == Ability.SHADOW_PLEDGE);
click.getPlayer().sendMessage(ChatColor.LIGHT_PURPLE +
"Changed spells to " + ChatColor.GRAY +
(sorcerer.getRoleData().getData(RoleData.DataType.SORCERER_SELECTED)).toString());
diff --git a/src/mddev0/mafiacraft/abilities/Vanish.java b/src/mddev0/mafiacraft/abilities/Vanish.java
index e5eec1a..c3b84b6 100644
--- a/src/mddev0/mafiacraft/abilities/Vanish.java
+++ b/src/mddev0/mafiacraft/abilities/Vanish.java
@@ -49,7 +49,7 @@ public void onItemSwing(PlayerInteractEvent click) {
}
if (p == null) p = click.getPlayer();
// apply effect
- p.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 3600, 0, false, false, true));
+ p.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 2400, 0, false, false, true));
click.getPlayer().setLevel(click.getPlayer().getLevel() - plugin.getConfig().getInt("vanishCost"));
click.getPlayer().sendMessage(ChatColor.GREEN + "You used " + ChatColor.LIGHT_PURPLE + "Vanish" +
ChatColor.GREEN + " on " + ChatColor.AQUA + p.getName());
diff --git a/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java b/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java
index 06ed508..79e69ab 100644
--- a/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java
+++ b/src/mddev0/mafiacraft/commands/MafiaCraftAdminCMD.java
@@ -195,15 +195,17 @@ public boolean onCommand(CommandSender sender, @SuppressWarnings("NullableProble
case MAFIA -> ChatColor.RED;
case VILLAGE -> ChatColor.DARK_GREEN;
case SOLO -> {
- if (p.getRole().toString().equals("Serial Killer"))
+ if (p.getRole() == Role.SERIAL_KILLER)
yield ChatColor.BLUE;
- else if (p.getRole().toString().equals("Trapper"))
- yield ChatColor.DARK_AQUA;
+ else if (p.getRole() == Role.WEREWOLF)
+ yield ChatColor.DARK_RED;
else yield ChatColor.DARK_GRAY; // Should never be used
}
case NONE -> {
- if (p.getRole().toString().equals("Jester"))
+ if (p.getRole() == Role.JESTER)
yield ChatColor.LIGHT_PURPLE;
+ if (p.getRole() == Role.SORCERER)
+ yield ChatColor.DARK_AQUA;
else yield ChatColor.YELLOW; // Will be used
}
case VAMPIRES -> ChatColor.DARK_PURPLE;
diff --git a/src/mddev0/mafiacraft/gui/InfoGUI.java b/src/mddev0/mafiacraft/gui/InfoGUI.java
index fbfc3b6..462b6a3 100644
--- a/src/mddev0/mafiacraft/gui/InfoGUI.java
+++ b/src/mddev0/mafiacraft/gui/InfoGUI.java
@@ -62,7 +62,12 @@ private void fillInventory() {
case MAFIA -> ChatColor.RED;
case VILLAGE -> ChatColor.DARK_GREEN;
case SOLO -> ChatColor.BLUE;
- case NONE -> ChatColor.YELLOW;
+ case NONE ->
+ switch (caller.getRole()) {
+ case JESTER -> ChatColor.LIGHT_PURPLE;
+ case SORCERER -> ChatColor.DARK_AQUA;
+ default -> ChatColor.YELLOW;
+ };
case VAMPIRES -> ChatColor.DARK_PURPLE;
} + Objects.requireNonNull(Bukkit.getPlayer(caller.getID())).getName() + " | "
+ caller.getRole().toString();
@@ -79,10 +84,12 @@ private void fillInventory() {
if (caller.getRole() == Role.JESTER)
yield "if " + ChatColor.LIGHT_PURPLE + "killed" +
ChatColor.GRAY + " by a member of the " + ChatColor.DARK_GREEN + "Village";
+ else if (caller.getRole() == Role.SORCERER)
+ yield ChatColor.GRAY + "by surviving to see " + ChatColor.DARK_AQUA + "your secret allegiance" + ChatColor.GRAY + " win";
else
- yield ChatColor.GRAY + " by completing all " + ChatColor.YELLOW + "tasks and win conditions";
+ yield ChatColor.GRAY + "by completing all " + ChatColor.YELLOW + "tasks and win conditions";
}
- case VAMPIRES -> "by " + ChatColor.DARK_AQUA + "Converting all players to Vampires";
+ case VAMPIRES -> "by " + ChatColor.DARK_PURPLE + "Converting all players to Vampires";
});
headLore.add(ChatColor.GRAY + "See all your abilities below.");
if (caller.getRole().getAlignment() == Role.Team.MAFIA || caller.getRole().getAlignment() == Role.Team.VAMPIRES) {
@@ -91,8 +98,11 @@ private void fillInventory() {
} else if (caller.getRole() == Role.HUNTER) {
headLore.add(ChatColor.GRAY + "The names and status of your");
headLore.add(ChatColor.GRAY + "targets are listed below.");
+ } else if (caller.getRole() == Role.BODYGUARD) {
+ headLore.add(ChatColor.GRAY + "The name and status of your");
+ headLore.add(ChatColor.GRAY + "protectee is listed below.");
}
- headLore.add(ChatColor.DARK_GRAY + "See the Role List if you're still confused.");
+ headLore.add(ChatColor.DARK_GRAY + "See the role descriptions online if you're still confused.");
headMeta.setLore(headLore);
head.setItemMeta(headMeta);
inv.setItem(4,head);
@@ -159,7 +169,8 @@ private void fillInventory() {
abilityNumber++;
}
- // List of Teammates
+ // TODO: Switchify
+ // List of Teammates or other attributes
if (caller.getRole().getAlignment() == Role.Team.MAFIA) { // If Mafia
int teammateNumber = 0;
for (MafiaPlayer other : plugin.getLivingPlayers().values()) {
@@ -191,7 +202,7 @@ private void fillInventory() {
teamMeta = (SkullMeta) teamHead.getItemMeta();
assert teamMeta != null;
teamMeta.setOwningPlayer(Bukkit.getOfflinePlayer(other.getID()));
- teamTitle = ChatColor.DARK_AQUA + Bukkit.getOfflinePlayer(other.getID()).getName() + " | " + other.getRole().toString();
+ teamTitle = ChatColor.DARK_PURPLE + Bukkit.getOfflinePlayer(other.getID()).getName() + " | " + other.getRole().toString();
teamMeta.setDisplayName(teamTitle);
teamHead.setItemMeta(teamMeta);
// Set Item
@@ -224,6 +235,36 @@ private void fillInventory() {
inv.setItem(targetPos, targetHead);
targetNumber++;
}
+ } else if (caller.getRole() == Role.BODYGUARD) {
+ String uuid = (String)caller.getRoleData().getData(RoleData.DataType.BODYGUARD_PROTECTEE);
+ MafiaPlayer protectee = plugin.getPlayerList().get(UUID.fromString(uuid));
+ ItemStack protecteeHead = new ItemStack(Material.PLAYER_HEAD);
+ SkullMeta protecteeMeta = (SkullMeta) protecteeHead.getItemMeta();
+ assert protecteeMeta != null;
+ protecteeMeta.setOwningPlayer(Bukkit.getOfflinePlayer(UUID.fromString(uuid)));
+ String protecteeTitle;
+ if (protectee.isLiving())
+ protecteeTitle = ChatColor.AQUA + Bukkit.getOfflinePlayer(UUID.fromString(uuid)).getName() + " | Alive";
+ else
+ protecteeTitle = ChatColor.DARK_GRAY + Bukkit.getOfflinePlayer(UUID.fromString(uuid)).getName() + " | Dead";
+ protecteeMeta.setDisplayName(protecteeTitle);
+ protecteeHead.setItemMeta(protecteeMeta);
+ inv.setItem(17, protecteeHead);
+ } else if (caller.getRole() == Role.SORCERER) {
+ ItemStack indicator;
+ String indicatorTitle = ChatColor.GRAY + "Secret Alignment: ";
+ if (Role.Team.valueOf((String)caller.getRoleData().getData(RoleData.DataType.SORCERER_ALIGNMENT)) == Role.Team.VILLAGE) {
+ indicator = new ItemStack(Material.LIME_WOOL);
+ indicatorTitle += ChatColor.DARK_GREEN + "Village";
+ } else { // aligned to Mafia
+ indicator = new ItemStack(Material.RED_WOOL);
+ indicatorTitle += ChatColor.RED + "Mafia";
+ }
+ ItemMeta indicatorMeta = indicator.getItemMeta();
+ assert indicatorMeta != null;
+ indicatorMeta.setDisplayName(indicatorTitle);
+ indicator.setItemMeta(indicatorMeta);
+ inv.setItem(17, indicator);
}
// TODO: Add indicators for Jester and Werewolves
}
diff --git a/src/mddev0/mafiacraft/player/MafiaPlayer.java b/src/mddev0/mafiacraft/player/MafiaPlayer.java
index 9539c35..c14be3e 100644
--- a/src/mddev0/mafiacraft/player/MafiaPlayer.java
+++ b/src/mddev0/mafiacraft/player/MafiaPlayer.java
@@ -103,7 +103,12 @@ public void changeRole(Role newRole) {
// If this role has added attributes, set defaults if needed
switch (role) {
case JESTER -> roleData.setData(RoleData.DataType.JESTER_ABILITY_USED, false);
- case SORCERER -> roleData.setData(RoleData.DataType.SORCERER_SELECTED, Ability.SPELL_BOOK);
+ case SORCERER -> {
+ roleData.setData(RoleData.DataType.SORCERER_SELECTED, Ability.SPELL_BOOK);
+ // Ternary operator to randomly pick if they are Village or Mafia
+ Role.Team alignment = (new Random().nextInt(2) == 0) ? Role.Team.VILLAGE : Role.Team.MAFIA;
+ roleData.setData(RoleData.DataType.SORCERER_ALIGNMENT, alignment.name());
+ }
case WEREWOLF -> {
roleData.setData(RoleData.DataType.WEREWOLF_TRANSFORM, false);
roleData.setData(RoleData.DataType.WEREWOLF_KILLS, 0);
@@ -116,7 +121,12 @@ public void changeRole(Role newRole) {
for (int i = 0; i < num; i++)
targets.add(allLiving.remove(new Random().nextInt(allLiving.size())).toString()); // SCUFFED: oops terrible practice
roleData.setData(RoleData.DataType.HUNTER_TARGETS, targets);
- } // TODO: add condition for Bodyguard
+ }
+ case BODYGUARD -> {
+ List allLiving = new ArrayList<>(plugin.getLivingPlayers().keySet().stream().toList());
+ allLiving.remove(uuid);
+ roleData.setData(RoleData.DataType.BODYGUARD_PROTECTEE, allLiving.get(new Random().nextInt(allLiving.size())).toString());
+ }
}
diff --git a/src/mddev0/mafiacraft/player/Role.java b/src/mddev0/mafiacraft/player/Role.java
index 59e3417..554698f 100644
--- a/src/mddev0/mafiacraft/player/Role.java
+++ b/src/mddev0/mafiacraft/player/Role.java
@@ -19,12 +19,12 @@ public enum Role {
APOTHECARY("Apothecary", true, Team.VILLAGE, Ability.AMBROSIA),
PRIEST("Priest", false, Team.VILLAGE, Ability.INQUISITION),
SERIAL_KILLER("Serial Killer", false, Team.SOLO, Ability.PROTECTION, Ability.AMBUSH),
- BODYGUARD("Bodyguard", false, Team.NONE, Ability.PROTECTEE, Ability.THIS_IS_FINE, Ability.DODGE_ROLL, Ability.PROTECTION),
+ BODYGUARD("Bodyguard", false, Team.NONE, Ability.PROTECTEE, Ability.THIS_IS_FINE, Ability.DODGE_ROLL, Ability.TRACKING),
HUNTER("Hunter", false, Team.NONE, Ability.TARGET, Ability.TRACKING),
- SORCERER("Sorcerer", false, Team.NONE, Ability.SCATTER, Ability.TOADIFY, Ability.FOG_OF_WAR, Ability.VANISH, Ability.SPELL_BOOK),
+ SORCERER("Sorcerer", true, Team.NONE, Ability.SCATTER, Ability.TOADIFY, Ability.FOG_OF_WAR, Ability.VANISH, Ability.SPELL_BOOK, Ability.SHADOW_PLEDGE),
WEREWOLF("Werewolf", false, Team.SOLO, Ability.TRANSFORM, Ability.RAMPAGE, Ability.NEMESIS),
VAMPIRE("Vampire", true, Team.VAMPIRES, Ability.CONVERT, Ability.NIGHT_OWL, Ability.STAKED),
- JESTER("Jester", true, Team.NONE, Ability.JUST_A_PRANK);
+ JESTER("Jester", false, Team.NONE, Ability.JUST_A_PRANK);
private final String NAME;
private final boolean UNIQUE;
diff --git a/src/mddev0/mafiacraft/player/RoleData.java b/src/mddev0/mafiacraft/player/RoleData.java
index 0f58cc5..07ae71f 100644
--- a/src/mddev0/mafiacraft/player/RoleData.java
+++ b/src/mddev0/mafiacraft/player/RoleData.java
@@ -44,6 +44,7 @@ public enum DataType {
WEREWOLF_TRANSFORM(Boolean.class),
WEREWOLF_KILLS(Integer.class),
SORCERER_SELECTED(Ability.class),
+ SORCERER_ALIGNMENT(String.class),
JESTER_ABILITY_USED(Boolean.class),
HUNTER_TARGETS(HashSet.class),
BODYGUARD_PROTECTEE(String.class);
diff --git a/src/mddev0/mafiacraft/util/GameFinisher.java b/src/mddev0/mafiacraft/util/GameFinisher.java
index e314bfe..88199bb 100644
--- a/src/mddev0/mafiacraft/util/GameFinisher.java
+++ b/src/mddev0/mafiacraft/util/GameFinisher.java
@@ -84,8 +84,6 @@ else if (dayTime > 12786 && dayTime <= 13000 && !checkedTonight) {
winnerSet.add(winner);
if (winner.getRole() == Role.SERIAL_KILLER)
subtitle = ChatColor.GRAY + "The " + ChatColor.BLUE + ChatColor.BOLD + "Serial Killer" + ChatColor.RESET + ChatColor.GRAY + " has won!";
- else if (winner.getRole() == Role.BODYGUARD)
- subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_AQUA + ChatColor.BOLD + "Trapper" + ChatColor.RESET + ChatColor.GRAY + " has won!";
else if (winner.getRole() == Role.WEREWOLF)
subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_RED + ChatColor.BOLD + "Werewolf" + ChatColor.RESET + ChatColor.GRAY + " has won!";
break; // since we only take 1
@@ -100,32 +98,45 @@ else if (winner.getRole() == Role.WEREWOLF)
}
subtitle = ChatColor.GRAY + "The " + ChatColor.DARK_PURPLE + ChatColor.BOLD + "Vampires" + ChatColor.RESET + ChatColor.GRAY + " have won!";
}
- } else if (mafiaRemaining + villageRemaining + soloRemaining + vampRemaining == 0) { // only unaligned left somehow
+ } else if (mafiaRemaining + villageRemaining + soloRemaining + vampRemaining == 0 && !plugin.getLivingPlayers().isEmpty()) { // only unaligned left somehow
endGame = true;
- subtitle = ChatColor.GRAY + "The " + ChatColor.YELLOW + ChatColor.BOLD + "Survivors" + ChatColor.RESET + ChatColor.GRAY + " have won!";
+ subtitle = ChatColor.GRAY + "Only " + ChatColor.YELLOW + ChatColor.BOLD + "Neutral" + ChatColor.RESET + ChatColor.GRAY + " players are alive!";
} else if (plugin.getLivingPlayers().isEmpty()) {
endGame = true;
subtitle = ChatColor.GRAY + "Everyone died!";
}
// Unaligned roles
- for (MafiaPlayer mp : plugin.getLivingPlayers().values()) { // survivors ONLY win if alive
- if (mp.getRole() == Role.HUNTER) {
- // Check if targets are killed
- boolean hunterWin = true;
- // SCUFFED: Yes, this next line is an unchecked cast. Guess I just have to be careful.
- for (String id : (Set)mp.getRoleData().getData(RoleData.DataType.HUNTER_TARGETS)) {
- hunterWin = hunterWin && !plugin.getPlayerList().get(UUID.fromString(id)).isLiving();
+ for (MafiaPlayer mp : plugin.getPlayerList().values()) {
+ switch (mp.getRole()) {
+ case HUNTER -> {
+ // Check if targets are killed
+ boolean hunterWin = true;
+ // SCUFFED: Yes, this next line is an unchecked cast. Guess I just have to be careful.
+ for (String id : (Set)mp.getRoleData().getData(RoleData.DataType.HUNTER_TARGETS)) {
+ hunterWin = hunterWin && !plugin.getPlayerList().get(UUID.fromString(id)).isLiving();
+ }
+ if (hunterWin) winnerSet.add(mp);
+ }
+ case JESTER -> {
+ if ((Boolean)mp.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED))
+ winnerSet.add(mp);
+ }
+ case BODYGUARD -> {
+ if (plugin.getLivingPlayers().containsKey(UUID.fromString((String)mp.getRoleData().getData(RoleData.DataType.BODYGUARD_PROTECTEE))))
+ winnerSet.add(mp);
+ }
+ case SORCERER -> {
+ if (Role.Team.valueOf((String) mp.getRoleData().getData(RoleData.DataType.SORCERER_ALIGNMENT)) == Role.Team.VILLAGE) {
+ if (villageRemaining > 0) winnerSet.add(mp);
+ }
+ else { // they're aligned to Mafia
+ if (mafiaRemaining > 0) winnerSet.add(mp);
+ }
+ }
+ default -> {
+ if (mp.isLiving()) winnerSet.add(mp);
}
- if (hunterWin) winnerSet.add(mp);
- } else if (mp.getRole() == Role.JESTER)
- if ((Boolean)mp.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED)) {
- winnerSet.add(mp);
- } else if (mp.getRole() == Role.BODYGUARD)
- if (plugin.getLivingPlayers().containsKey(UUID.fromString((String)mp.getRoleData().getData(RoleData.DataType.BODYGUARD_PROTECTEE)))) {
- winnerSet.add(mp);
- } else if (mp.isLiving()) { // Other surviving roles have no special win conditions, win if alive
- winnerSet.add(mp);
}
}
@@ -141,7 +152,10 @@ else if (winner.getRole() == Role.WEREWOLF)
}
// Winner list
String winnersMessage = ChatColor.GREEN + "";
- if (winners.size() == 1) {
+ if (winners.isEmpty()) {
+ winnersMessage = winnersMessage.concat("Nobody wins!");
+ }
+ else if (winners.size() == 1) {
winnersMessage = winnersMessage.concat(Bukkit.getOfflinePlayer(winners.get(0).getID()).getName() + " is the winner!");
} else if (winners.size() == 2) {
winnersMessage = winnersMessage.concat(Bukkit.getOfflinePlayer(winners.get(0).getID()).getName() + " and " +
@@ -174,11 +188,12 @@ else if (winner.getRole() == Role.WEREWOLF)
case VILLAGE -> ChatColor.DARK_GREEN;
case SOLO-> {
if (p.getRole() == Role.SERIAL_KILLER) yield ChatColor.BLUE;
- else if (p.getRole() == Role.BODYGUARD) yield ChatColor.DARK_AQUA;
+ else if (p.getRole() == Role.WEREWOLF) yield ChatColor.DARK_RED;
else yield ChatColor.DARK_GRAY; // Should never be used
}
case NONE -> {
if (p.getRole() == Role.JESTER) yield ChatColor.LIGHT_PURPLE;
+ if (p.getRole() == Role.SORCERER) yield ChatColor.DARK_AQUA;
else yield ChatColor.YELLOW; // Will be used
}
case VAMPIRES -> {
@@ -194,7 +209,7 @@ else if (winner.getRole() == Role.WEREWOLF)
case VILLAGE -> ChatColor.DARK_GREEN;
case SOLO -> {
if (p.getOriginalRole() == Role.SERIAL_KILLER) yield ChatColor.BLUE;
- else if (p.getOriginalRole() == Role.BODYGUARD) yield ChatColor.DARK_AQUA;
+ else if (p.getOriginalRole() == Role.WEREWOLF) yield ChatColor.DARK_RED;
else yield ChatColor.DARK_GRAY; // Should never be used
}
case NONE -> {
diff --git a/src/mddev0/mafiacraft/util/GameRandomizer.java b/src/mddev0/mafiacraft/util/GameRandomizer.java
index 42e548c..cd3802a 100644
--- a/src/mddev0/mafiacraft/util/GameRandomizer.java
+++ b/src/mddev0/mafiacraft/util/GameRandomizer.java
@@ -238,6 +238,10 @@ else if (!bannedRoles.contains(r.name()))
allLiving.remove(mp.getID());
String protectee = allLiving.get(rand.nextInt(allLiving.size())).toString();
mp.getRoleData().setData(RoleData.DataType.BODYGUARD_PROTECTEE, protectee);
+ } if (mp.getRole().getAbilities().contains(Ability.SHADOW_PLEDGE)) {
+ // Ternary operator to randomly pick if they are Village or Mafia
+ Role.Team alignment = (new Random().nextInt(2) == 0) ? Role.Team.VILLAGE : Role.Team.MAFIA;
+ mp.getRoleData().setData(RoleData.DataType.SORCERER_ALIGNMENT, alignment.name());
}
}
}
diff --git a/src/mddev0/mafiacraft/util/JoinLeaveManager.java b/src/mddev0/mafiacraft/util/JoinLeaveManager.java
index c3801d4..7732f44 100644
--- a/src/mddev0/mafiacraft/util/JoinLeaveManager.java
+++ b/src/mddev0/mafiacraft/util/JoinLeaveManager.java
@@ -59,9 +59,12 @@ public void onPlayerJoin(PlayerJoinEvent join) {
}
}
// Handle Jester
- if (joined != null && (Boolean) joined.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED)) {
- join.getPlayer().setDisplayName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + join.getPlayer().getDisplayName());
- join.getPlayer().setPlayerListName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + join.getPlayer().getPlayerListName());
+ if (joined != null) {
+ Boolean jestStatus = (Boolean) joined.getRoleData().getData(RoleData.DataType.JESTER_ABILITY_USED);
+ if (jestStatus != null && jestStatus) {
+ join.getPlayer().setDisplayName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + join.getPlayer().getDisplayName());
+ join.getPlayer().setPlayerListName("[" + ChatColor.LIGHT_PURPLE + "Jester" + ChatColor.RESET + "] " + join.getPlayer().getPlayerListName());
+ }
}
}
diff --git a/src/mddev0/mafiacraft/util/SpyglassUtil.java b/src/mddev0/mafiacraft/util/SpyglassUtil.java
index 040ad96..cc9b62f 100644
--- a/src/mddev0/mafiacraft/util/SpyglassUtil.java
+++ b/src/mddev0/mafiacraft/util/SpyglassUtil.java
@@ -31,6 +31,7 @@ public SpyglassUtil(MafiaCraft plugin, @Nonnull OfflinePlayer p) {
targeted = null;
}
+ // TODO: Update to use World.rayTraceEntities()
@Override
public void run() {
if (!holder.isOnline()) return; // holder is offline
@@ -55,7 +56,14 @@ public void run() {
if (active) {
// If line of sight between player and target is interrupted, then false. otherwise true
double lineDistance = holder.getPlayer().getEyeLocation().distance(targeted.getEyeLocation());
- RayTraceResult lineOfSight = holder.getPlayer().rayTraceBlocks(lineDistance, FluidCollisionMode.NEVER);
+ Player play = holder.getPlayer();
+ RayTraceResult lineOfSight = play.getWorld().rayTraceBlocks(
+ play.getLocation(),
+ play.getEyeLocation().toVector().subtract(targeted.getEyeLocation().toVector()).normalize(),
+ lineDistance,
+ FluidCollisionMode.NEVER,
+ true
+ );
active = (lineOfSight == null);
}
}