Allow factionless vs factionless PvP
This commit is contained in:
		@@ -22,6 +22,7 @@ import com.massivecraft.factions.chat.tag.ChatTagRoleprefixforce;
 | 
				
			|||||||
import com.massivecraft.factions.chat.tag.ChatTagTitle;
 | 
					import com.massivecraft.factions.chat.tag.ChatTagTitle;
 | 
				
			||||||
import com.massivecraft.factions.cmd.*;
 | 
					import com.massivecraft.factions.cmd.*;
 | 
				
			||||||
import com.massivecraft.factions.engine.EngineChat;
 | 
					import com.massivecraft.factions.engine.EngineChat;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.engine.EngineCombat;
 | 
				
			||||||
import com.massivecraft.factions.engine.EngineEcon;
 | 
					import com.massivecraft.factions.engine.EngineEcon;
 | 
				
			||||||
import com.massivecraft.factions.engine.EngineExploit;
 | 
					import com.massivecraft.factions.engine.EngineExploit;
 | 
				
			||||||
import com.massivecraft.factions.engine.EngineMain;
 | 
					import com.massivecraft.factions.engine.EngineMain;
 | 
				
			||||||
@@ -149,6 +150,7 @@ public class Factions extends MassivePlugin
 | 
				
			|||||||
			// Engines
 | 
								// Engines
 | 
				
			||||||
			EngineMain.class,
 | 
								EngineMain.class,
 | 
				
			||||||
			EngineChat.class,
 | 
								EngineChat.class,
 | 
				
			||||||
 | 
								EngineCombat.class,
 | 
				
			||||||
			EngineExploit.class,
 | 
								EngineExploit.class,
 | 
				
			||||||
			EngineSeeChunk.class,
 | 
								EngineSeeChunk.class,
 | 
				
			||||||
			EngineEcon.class, // TODO: Take an extra look and make sure all economy stuff is handled using events. 
 | 
								EngineEcon.class, // TODO: Take an extra look and make sure all economy stuff is handled using events. 
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										257
									
								
								src/com/massivecraft/factions/engine/EngineCombat.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								src/com/massivecraft/factions/engine/EngineCombat.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,257 @@
 | 
				
			|||||||
 | 
					package com.massivecraft.factions.engine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.text.MessageFormat;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bukkit.entity.Arrow;
 | 
				
			||||||
 | 
					import org.bukkit.entity.Entity;
 | 
				
			||||||
 | 
					import org.bukkit.entity.LivingEntity;
 | 
				
			||||||
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
 | 
					import org.bukkit.event.EventHandler;
 | 
				
			||||||
 | 
					import org.bukkit.event.EventPriority;
 | 
				
			||||||
 | 
					import org.bukkit.event.entity.EntityCombustByEntityEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.entity.EntityDamageByEntityEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.entity.EntityDamageEvent;
 | 
				
			||||||
 | 
					import org.bukkit.event.entity.PotionSplashEvent;
 | 
				
			||||||
 | 
					import org.bukkit.projectiles.ProjectileSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.massivecraft.factions.Rel;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.entity.BoardColl;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.entity.Faction;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.entity.MConf;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.entity.MFlag;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.entity.MPlayer;
 | 
				
			||||||
 | 
					import com.massivecraft.factions.event.EventFactionsPvpDisallowed;
 | 
				
			||||||
 | 
					import com.massivecraft.massivecore.Engine;
 | 
				
			||||||
 | 
					import com.massivecraft.massivecore.ps.PS;
 | 
				
			||||||
 | 
					import com.massivecraft.massivecore.util.MUtil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class EngineCombat extends Engine
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 | 
						// INSTANCE & CONSTRUCT
 | 
				
			||||||
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						private static EngineCombat i = new EngineCombat();
 | 
				
			||||||
 | 
						public static EngineCombat get() { return i; }
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 | 
						// CAN COMBAT DAMAGE HAPPEN
 | 
				
			||||||
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
 | 
				
			||||||
 | 
						public void canCombatDamageHappen(EntityDamageByEntityEvent event)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (this.canCombatDamageHappen(event, true)) return;
 | 
				
			||||||
 | 
							event.setCancelled(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Entity damager = event.getDamager();
 | 
				
			||||||
 | 
							if ( ! (damager instanceof Arrow)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							damager.remove();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled
 | 
				
			||||||
 | 
						@SuppressWarnings("deprecation")
 | 
				
			||||||
 | 
						@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
 | 
				
			||||||
 | 
						public void canCombatDamageHappen(EntityCombustByEntityEvent event)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0D);
 | 
				
			||||||
 | 
							if (this.canCombatDamageHappen(sub, false)) return;
 | 
				
			||||||
 | 
							event.setCancelled(true);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@SuppressWarnings("deprecation")
 | 
				
			||||||
 | 
						@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
 | 
				
			||||||
 | 
						public void canCombatDamageHappen(PotionSplashEvent event)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// If a harmful potion is splashing ...
 | 
				
			||||||
 | 
							if (!MUtil.isHarmfulPotion(event.getPotion())) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							ProjectileSource projectileSource = event.getPotion().getShooter();
 | 
				
			||||||
 | 
							if (! (projectileSource instanceof Entity)) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							Entity thrower = (Entity)projectileSource;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ... scan through affected entities to make sure they're all valid targets.
 | 
				
			||||||
 | 
							for (LivingEntity affectedEntity : event.getAffectedEntities())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(thrower, affectedEntity, EntityDamageEvent.DamageCause.CUSTOM, 0D);
 | 
				
			||||||
 | 
								if (this.canCombatDamageHappen(sub, true)) continue;
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								// affected entity list doesn't accept modification (iter.remove() is a no-go), but this works
 | 
				
			||||||
 | 
								event.setIntensity(affectedEntity, 0.0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Utility method used in "canCombatDamageHappen" below.
 | 
				
			||||||
 | 
						public static boolean falseUnlessDisallowedPvpEventCancelled(Player attacker, Player defender, EntityDamageByEntityEvent event)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							EventFactionsPvpDisallowed dpe = new EventFactionsPvpDisallowed(attacker, defender, event);
 | 
				
			||||||
 | 
							dpe.run();
 | 
				
			||||||
 | 
							return dpe.isCancelled();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						public boolean canCombatDamageHappen(EntityDamageByEntityEvent event, boolean notify)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							boolean ret = true;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// If the defender is a player ...
 | 
				
			||||||
 | 
							Entity edefender = event.getEntity();
 | 
				
			||||||
 | 
							if (MUtil.isntPlayer(edefender)) return true;
 | 
				
			||||||
 | 
							Player defender = (Player)edefender;
 | 
				
			||||||
 | 
							MPlayer mdefender = MPlayer.get(edefender);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... and the attacker is someone else ...
 | 
				
			||||||
 | 
							Entity eattacker = MUtil.getLiableDamager(event);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// (we check null here since there may not be an attacker)
 | 
				
			||||||
 | 
							// (lack of attacker situations can be caused by other bukkit plugins)
 | 
				
			||||||
 | 
							if (eattacker != null && eattacker.equals(edefender)) return true;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... gather defender PS and faction information ...
 | 
				
			||||||
 | 
							PS defenderPs = PS.valueOf(defender.getLocation());
 | 
				
			||||||
 | 
							Faction defenderPsFaction = BoardColl.get().getFactionAt(defenderPs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ... fast evaluate if the attacker is overriding ...
 | 
				
			||||||
 | 
							MPlayer mplayer = MPlayer.get(eattacker);
 | 
				
			||||||
 | 
							if (mplayer != null && mplayer.isOverriding()) return true;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... PVP flag may cause a damage block ...
 | 
				
			||||||
 | 
							if (defenderPsFaction.getFlag(MFlag.getFlagPvp()) == false)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (eattacker == null)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									// No attacker?
 | 
				
			||||||
 | 
									// Let's behave as if it were a player
 | 
				
			||||||
 | 
									return falseUnlessDisallowedPvpEventCancelled(null, defender, event);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if (MUtil.isPlayer(eattacker))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									ret = falseUnlessDisallowedPvpEventCancelled((Player)eattacker, defender, event);
 | 
				
			||||||
 | 
									if (!ret && notify)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										MPlayer attacker = MPlayer.get(eattacker);
 | 
				
			||||||
 | 
										attacker.msg("<i>PVP is disabled in %s.", defenderPsFaction.describeTo(attacker));
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return defenderPsFaction.getFlag(MFlag.getFlagMonsters());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ... and if the attacker is a player ...
 | 
				
			||||||
 | 
							if (MUtil.isntPlayer(eattacker)) return true;
 | 
				
			||||||
 | 
							Player attacker = (Player)eattacker;
 | 
				
			||||||
 | 
							MPlayer uattacker = MPlayer.get(attacker);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... does this player bypass all protection? ...
 | 
				
			||||||
 | 
							if (MConf.get().playersWhoBypassAllProtection.contains(attacker.getName())) return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ... gather attacker PS and faction information ...
 | 
				
			||||||
 | 
							PS attackerPs = PS.valueOf(attacker.getLocation());
 | 
				
			||||||
 | 
							Faction attackerPsFaction = BoardColl.get().getFactionAt(attackerPs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ... PVP flag may cause a damage block ...
 | 
				
			||||||
 | 
							// (just checking the defender as above isn't enough. What about the attacker? It could be in a no-pvp area)
 | 
				
			||||||
 | 
							// NOTE: This check is probably not that important but we could keep it anyways.
 | 
				
			||||||
 | 
							if (attackerPsFaction.getFlag(MFlag.getFlagPvp()) == false)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
				
			||||||
 | 
								if (!ret && notify) uattacker.msg("<i>PVP is disabled in %s.", attackerPsFaction.describeTo(uattacker));
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ... are PVP rules completely ignored in this world? ...
 | 
				
			||||||
 | 
							if (!MConf.get().worldsPvpRulesEnabled.contains(defenderPs.getWorld())) return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Faction defendFaction = mdefender.getFaction();
 | 
				
			||||||
 | 
							Faction attackFaction = uattacker.getFaction();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (attackFaction.isNone() && MConf.get().disablePVPForFactionlessPlayers)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
				
			||||||
 | 
								if (!ret && notify) uattacker.msg("<i>You can't hurt other players until you join a faction.");
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (defendFaction.isNone())
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (defenderPsFaction == attackFaction && MConf.get().enablePVPAgainstFactionlessInAttackersLand)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									// Allow PVP vs. Factionless in attacker's faction territory
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (MConf.get().disablePVPForFactionlessPlayers)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
				
			||||||
 | 
									if (!ret && notify) uattacker.msg("<i>You can't hurt players who are not currently in a faction.");
 | 
				
			||||||
 | 
									return ret;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else if (attackFaction.isNone() && MConf.get().enablePVPBetweenFactionlessPlayers)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									// Allow factionless vs factionless
 | 
				
			||||||
 | 
									return true;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Rel relation = defendFaction.getRelationTo(attackFaction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Check the relation
 | 
				
			||||||
 | 
							if (relation.isFriend() && defenderPsFaction.getFlag(MFlag.getFlagFriendlyire()) == false)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
				
			||||||
 | 
								if (!ret && notify) uattacker.msg("<i>You can't hurt %s<i>.", relation.getDescPlayerMany());
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// You can not hurt neutrals in their own territory.
 | 
				
			||||||
 | 
							boolean ownTerritory = mdefender.isInOwnTerritory();
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if (mdefender.hasFaction() && ownTerritory && relation == Rel.NEUTRAL)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
				
			||||||
 | 
								if (!ret && notify)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									uattacker.msg("<i>You can't hurt %s<i> in their own territory unless you declare them as an enemy.", mdefender.describeTo(uattacker));
 | 
				
			||||||
 | 
									mdefender.msg("%s<i> tried to hurt you.", uattacker.describeTo(mdefender, true));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return ret;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 | 
						// TERRITORY SHIELD
 | 
				
			||||||
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
 | 
				
			||||||
 | 
						public void territoryShield(EntityDamageByEntityEvent event)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// If the entity is a player ...
 | 
				
			||||||
 | 
							Entity entity = event.getEntity();
 | 
				
			||||||
 | 
							if (MUtil.isntPlayer(entity)) return;
 | 
				
			||||||
 | 
							Player player = (Player)entity;
 | 
				
			||||||
 | 
							MPlayer mplayer = MPlayer.get(player);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... and the attacker is a player ...
 | 
				
			||||||
 | 
							Entity attacker = MUtil.getLiableDamager(event);
 | 
				
			||||||
 | 
							if (! (attacker instanceof Player)) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... and that player has a faction ...
 | 
				
			||||||
 | 
							if ( ! mplayer.hasFaction()) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... and that player is in their own territory ...
 | 
				
			||||||
 | 
							if ( ! mplayer.isInOwnTerritory()) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... and a territoryShieldFactor is configured ...
 | 
				
			||||||
 | 
							if (MConf.get().territoryShieldFactor <= 0) return;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... then scale the damage ...
 | 
				
			||||||
 | 
							double factor = 1D - MConf.get().territoryShieldFactor;
 | 
				
			||||||
 | 
							MUtil.scaleDamage(event, factor);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// ... and inform.
 | 
				
			||||||
 | 
							String perc = MessageFormat.format("{0,number,#%}", (MConf.get().territoryShieldFactor));
 | 
				
			||||||
 | 
							mplayer.msg("<i>Enemy damage reduced by <rose>%s<i>.", perc);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,5 @@
 | 
				
			|||||||
package com.massivecraft.factions.engine;
 | 
					package com.massivecraft.factions.engine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.text.MessageFormat;
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.EnumSet;
 | 
					import java.util.EnumSet;
 | 
				
			||||||
@@ -20,11 +19,9 @@ import org.bukkit.Material;
 | 
				
			|||||||
import org.bukkit.block.Block;
 | 
					import org.bukkit.block.Block;
 | 
				
			||||||
import org.bukkit.block.BlockFace;
 | 
					import org.bukkit.block.BlockFace;
 | 
				
			||||||
import org.bukkit.command.CommandSender;
 | 
					import org.bukkit.command.CommandSender;
 | 
				
			||||||
import org.bukkit.entity.Arrow;
 | 
					 | 
				
			||||||
import org.bukkit.entity.Enderman;
 | 
					import org.bukkit.entity.Enderman;
 | 
				
			||||||
import org.bukkit.entity.Entity;
 | 
					import org.bukkit.entity.Entity;
 | 
				
			||||||
import org.bukkit.entity.EntityType;
 | 
					import org.bukkit.entity.EntityType;
 | 
				
			||||||
import org.bukkit.entity.LivingEntity;
 | 
					 | 
				
			||||||
import org.bukkit.entity.Player;
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
import org.bukkit.entity.Wither;
 | 
					import org.bukkit.entity.Wither;
 | 
				
			||||||
import org.bukkit.entity.Zombie;
 | 
					import org.bukkit.entity.Zombie;
 | 
				
			||||||
@@ -47,13 +44,11 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
 | 
				
			|||||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
 | 
					import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
 | 
				
			||||||
import org.bukkit.event.entity.EntityBreakDoorEvent;
 | 
					import org.bukkit.event.entity.EntityBreakDoorEvent;
 | 
				
			||||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
 | 
					import org.bukkit.event.entity.EntityChangeBlockEvent;
 | 
				
			||||||
import org.bukkit.event.entity.EntityCombustByEntityEvent;
 | 
					 | 
				
			||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
 | 
					import org.bukkit.event.entity.EntityDamageByEntityEvent;
 | 
				
			||||||
import org.bukkit.event.entity.EntityDamageEvent;
 | 
					import org.bukkit.event.entity.EntityDamageEvent;
 | 
				
			||||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
 | 
					import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
 | 
				
			||||||
import org.bukkit.event.entity.EntityExplodeEvent;
 | 
					import org.bukkit.event.entity.EntityExplodeEvent;
 | 
				
			||||||
import org.bukkit.event.entity.PlayerDeathEvent;
 | 
					import org.bukkit.event.entity.PlayerDeathEvent;
 | 
				
			||||||
import org.bukkit.event.entity.PotionSplashEvent;
 | 
					 | 
				
			||||||
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
 | 
					import org.bukkit.event.hanging.HangingBreakByEntityEvent;
 | 
				
			||||||
import org.bukkit.event.hanging.HangingBreakEvent;
 | 
					import org.bukkit.event.hanging.HangingBreakEvent;
 | 
				
			||||||
import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
 | 
					import org.bukkit.event.hanging.HangingBreakEvent.RemoveCause;
 | 
				
			||||||
@@ -67,7 +62,6 @@ import org.bukkit.event.player.PlayerJoinEvent;
 | 
				
			|||||||
import org.bukkit.event.player.PlayerKickEvent;
 | 
					import org.bukkit.event.player.PlayerKickEvent;
 | 
				
			||||||
import org.bukkit.event.player.PlayerMoveEvent;
 | 
					import org.bukkit.event.player.PlayerMoveEvent;
 | 
				
			||||||
import org.bukkit.event.player.PlayerRespawnEvent;
 | 
					import org.bukkit.event.player.PlayerRespawnEvent;
 | 
				
			||||||
import org.bukkit.projectiles.ProjectileSource;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.massivecraft.factions.Const;
 | 
					import com.massivecraft.factions.Const;
 | 
				
			||||||
import com.massivecraft.factions.Factions;
 | 
					import com.massivecraft.factions.Factions;
 | 
				
			||||||
@@ -88,7 +82,6 @@ import com.massivecraft.factions.event.EventFactionsChunksChange;
 | 
				
			|||||||
import com.massivecraft.factions.event.EventFactionsFactionShowAsync;
 | 
					import com.massivecraft.factions.event.EventFactionsFactionShowAsync;
 | 
				
			||||||
import com.massivecraft.factions.event.EventFactionsPowerChange;
 | 
					import com.massivecraft.factions.event.EventFactionsPowerChange;
 | 
				
			||||||
import com.massivecraft.factions.event.EventFactionsPowerChange.PowerChangeReason;
 | 
					import com.massivecraft.factions.event.EventFactionsPowerChange.PowerChangeReason;
 | 
				
			||||||
import com.massivecraft.factions.event.EventFactionsPvpDisallowed;
 | 
					 | 
				
			||||||
import com.massivecraft.factions.integration.Econ;
 | 
					import com.massivecraft.factions.integration.Econ;
 | 
				
			||||||
import com.massivecraft.factions.integration.spigot.IntegrationSpigot;
 | 
					import com.massivecraft.factions.integration.spigot.IntegrationSpigot;
 | 
				
			||||||
import com.massivecraft.factions.util.VisualizeUtil;
 | 
					import com.massivecraft.factions.util.VisualizeUtil;
 | 
				
			||||||
@@ -825,221 +818,6 @@ public class EngineMain extends Engine
 | 
				
			|||||||
		mplayer.msg("<i>Your power is now <h>%.2f / %.2f", newPower, mplayer.getPowerMax());
 | 
							mplayer.msg("<i>Your power is now <h>%.2f / %.2f", newPower, mplayer.getPowerMax());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// -------------------------------------------- //
 | 
					 | 
				
			||||||
	// CAN COMBAT DAMAGE HAPPEN
 | 
					 | 
				
			||||||
	// -------------------------------------------- //
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
 | 
					 | 
				
			||||||
	public void canCombatDamageHappen(EntityDamageByEntityEvent event)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (this.canCombatDamageHappen(event, true)) return;
 | 
					 | 
				
			||||||
		event.setCancelled(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Entity damager = event.getDamager();
 | 
					 | 
				
			||||||
		if ( ! (damager instanceof Arrow)) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		damager.remove();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// mainly for flaming arrows; don't want allies or people in safe zones to be ignited even after damage event is cancelled
 | 
					 | 
				
			||||||
	@SuppressWarnings("deprecation")
 | 
					 | 
				
			||||||
	@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
 | 
					 | 
				
			||||||
	public void canCombatDamageHappen(EntityCombustByEntityEvent event)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(event.getCombuster(), event.getEntity(), EntityDamageEvent.DamageCause.FIRE, 0D);
 | 
					 | 
				
			||||||
		if (this.canCombatDamageHappen(sub, false)) return;
 | 
					 | 
				
			||||||
		event.setCancelled(true);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@SuppressWarnings("deprecation")
 | 
					 | 
				
			||||||
	@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
 | 
					 | 
				
			||||||
	public void canCombatDamageHappen(PotionSplashEvent event)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// If a harmful potion is splashing ...
 | 
					 | 
				
			||||||
		if (!MUtil.isHarmfulPotion(event.getPotion())) return;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		ProjectileSource projectileSource = event.getPotion().getShooter();
 | 
					 | 
				
			||||||
		if (! (projectileSource instanceof Entity)) return;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		Entity thrower = (Entity)projectileSource;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ... scan through affected entities to make sure they're all valid targets.
 | 
					 | 
				
			||||||
		for (LivingEntity affectedEntity : event.getAffectedEntities())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			EntityDamageByEntityEvent sub = new EntityDamageByEntityEvent(thrower, affectedEntity, EntityDamageEvent.DamageCause.CUSTOM, 0D);
 | 
					 | 
				
			||||||
			if (this.canCombatDamageHappen(sub, true)) continue;
 | 
					 | 
				
			||||||
			
 | 
					 | 
				
			||||||
			// affected entity list doesn't accept modification (iter.remove() is a no-go), but this works
 | 
					 | 
				
			||||||
			event.setIntensity(affectedEntity, 0.0);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Utility method used in "canCombatDamageHappen" below.
 | 
					 | 
				
			||||||
	public static boolean falseUnlessDisallowedPvpEventCancelled(Player attacker, Player defender, EntityDamageByEntityEvent event)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		EventFactionsPvpDisallowed dpe = new EventFactionsPvpDisallowed(attacker, defender, event);
 | 
					 | 
				
			||||||
		dpe.run();
 | 
					 | 
				
			||||||
		return dpe.isCancelled();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	public boolean canCombatDamageHappen(EntityDamageByEntityEvent event, boolean notify)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		boolean ret = true;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// If the defender is a player ...
 | 
					 | 
				
			||||||
		Entity edefender = event.getEntity();
 | 
					 | 
				
			||||||
		if (MUtil.isntPlayer(edefender)) return true;
 | 
					 | 
				
			||||||
		Player defender = (Player)edefender;
 | 
					 | 
				
			||||||
		MPlayer mdefender = MPlayer.get(edefender);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... and the attacker is someone else ...
 | 
					 | 
				
			||||||
		Entity eattacker = MUtil.getLiableDamager(event);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// (we check null here since there may not be an attacker)
 | 
					 | 
				
			||||||
		// (lack of attacker situations can be caused by other bukkit plugins)
 | 
					 | 
				
			||||||
		if (eattacker != null && eattacker.equals(edefender)) return true;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... gather defender PS and faction information ...
 | 
					 | 
				
			||||||
		PS defenderPs = PS.valueOf(defender.getLocation());
 | 
					 | 
				
			||||||
		Faction defenderPsFaction = BoardColl.get().getFactionAt(defenderPs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ... fast evaluate if the attacker is overriding ...
 | 
					 | 
				
			||||||
		MPlayer mplayer = MPlayer.get(eattacker);
 | 
					 | 
				
			||||||
		if (mplayer != null && mplayer.isOverriding()) return true;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... PVP flag may cause a damage block ...
 | 
					 | 
				
			||||||
		if (defenderPsFaction.getFlag(MFlag.getFlagPvp()) == false)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (eattacker == null)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// No attacker?
 | 
					 | 
				
			||||||
				// Let's behave as if it were a player
 | 
					 | 
				
			||||||
				return falseUnlessDisallowedPvpEventCancelled(null, defender, event);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if (MUtil.isPlayer(eattacker))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				ret = falseUnlessDisallowedPvpEventCancelled((Player)eattacker, defender, event);
 | 
					 | 
				
			||||||
				if (!ret && notify)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					MPlayer attacker = MPlayer.get(eattacker);
 | 
					 | 
				
			||||||
					attacker.msg("<i>PVP is disabled in %s.", defenderPsFaction.describeTo(attacker));
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return ret;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return defenderPsFaction.getFlag(MFlag.getFlagMonsters());
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ... and if the attacker is a player ...
 | 
					 | 
				
			||||||
		if (MUtil.isntPlayer(eattacker)) return true;
 | 
					 | 
				
			||||||
		Player attacker = (Player)eattacker;
 | 
					 | 
				
			||||||
		MPlayer uattacker = MPlayer.get(attacker);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... does this player bypass all protection? ...
 | 
					 | 
				
			||||||
		if (MConf.get().playersWhoBypassAllProtection.contains(attacker.getName())) return true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ... gather attacker PS and faction information ...
 | 
					 | 
				
			||||||
		PS attackerPs = PS.valueOf(attacker.getLocation());
 | 
					 | 
				
			||||||
		Faction attackerPsFaction = BoardColl.get().getFactionAt(attackerPs);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ... PVP flag may cause a damage block ...
 | 
					 | 
				
			||||||
		// (just checking the defender as above isn't enough. What about the attacker? It could be in a no-pvp area)
 | 
					 | 
				
			||||||
		// NOTE: This check is probably not that important but we could keep it anyways.
 | 
					 | 
				
			||||||
		if (attackerPsFaction.getFlag(MFlag.getFlagPvp()) == false)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
					 | 
				
			||||||
			if (!ret && notify) uattacker.msg("<i>PVP is disabled in %s.", attackerPsFaction.describeTo(uattacker));
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ... are PVP rules completely ignored in this world? ...
 | 
					 | 
				
			||||||
		if (!MConf.get().worldsPvpRulesEnabled.contains(defenderPs.getWorld())) return true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Faction defendFaction = mdefender.getFaction();
 | 
					 | 
				
			||||||
		Faction attackFaction = uattacker.getFaction();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (attackFaction.isNone() && MConf.get().disablePVPForFactionlessPlayers)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
					 | 
				
			||||||
			if (!ret && notify) uattacker.msg("<i>You can't hurt other players until you join a faction.");
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else if (defendFaction.isNone())
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			if (defenderPsFaction == attackFaction && MConf.get().enablePVPAgainstFactionlessInAttackersLand)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// Allow PVP vs. Factionless in attacker's faction territory
 | 
					 | 
				
			||||||
				return true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			else if (MConf.get().disablePVPForFactionlessPlayers)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
					 | 
				
			||||||
				if (!ret && notify) uattacker.msg("<i>You can't hurt players who are not currently in a faction.");
 | 
					 | 
				
			||||||
				return ret;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Rel relation = defendFaction.getRelationTo(attackFaction);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Check the relation
 | 
					 | 
				
			||||||
		if (relation.isFriend() && defenderPsFaction.getFlag(MFlag.getFlagFriendlyire()) == false)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
					 | 
				
			||||||
			if (!ret && notify) uattacker.msg("<i>You can't hurt %s<i>.", relation.getDescPlayerMany());
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// You can not hurt neutrals in their own territory.
 | 
					 | 
				
			||||||
		boolean ownTerritory = mdefender.isInOwnTerritory();
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		if (mdefender.hasFaction() && ownTerritory && relation == Rel.NEUTRAL)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ret = falseUnlessDisallowedPvpEventCancelled(attacker, defender, event);
 | 
					 | 
				
			||||||
			if (!ret && notify)
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				uattacker.msg("<i>You can't hurt %s<i> in their own territory unless you declare them as an enemy.", mdefender.describeTo(uattacker));
 | 
					 | 
				
			||||||
				mdefender.msg("%s<i> tried to hurt you.", uattacker.describeTo(mdefender, true));
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return ret;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return true;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// -------------------------------------------- //
 | 
					 | 
				
			||||||
	// TERRITORY SHIELD
 | 
					 | 
				
			||||||
	// -------------------------------------------- //
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
 | 
					 | 
				
			||||||
	public void territoryShield(EntityDamageByEntityEvent event)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		// If the entity is a player ...
 | 
					 | 
				
			||||||
		Entity entity = event.getEntity();
 | 
					 | 
				
			||||||
		if (MUtil.isntPlayer(entity)) return;
 | 
					 | 
				
			||||||
		Player player = (Player)entity;
 | 
					 | 
				
			||||||
		MPlayer mplayer = MPlayer.get(player);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... and the attacker is a player ...
 | 
					 | 
				
			||||||
		Entity attacker = MUtil.getLiableDamager(event);
 | 
					 | 
				
			||||||
		if (! (attacker instanceof Player)) return;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... and that player has a faction ...
 | 
					 | 
				
			||||||
		if ( ! mplayer.hasFaction()) return;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... and that player is in their own territory ...
 | 
					 | 
				
			||||||
		if ( ! mplayer.isInOwnTerritory()) return;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... and a territoryShieldFactor is configured ...
 | 
					 | 
				
			||||||
		if (MConf.get().territoryShieldFactor <= 0) return;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... then scale the damage ...
 | 
					 | 
				
			||||||
		double factor = 1D - MConf.get().territoryShieldFactor;
 | 
					 | 
				
			||||||
		MUtil.scaleDamage(event, factor);
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// ... and inform.
 | 
					 | 
				
			||||||
		String perc = MessageFormat.format("{0,number,#%}", (MConf.get().territoryShieldFactor));
 | 
					 | 
				
			||||||
		mplayer.msg("<i>Enemy damage reduced by <rose>%s<i>.", perc);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	// -------------------------------------------- //
 | 
						// -------------------------------------------- //
 | 
				
			||||||
	// REMOVE PLAYER DATA WHEN BANNED
 | 
						// REMOVE PLAYER DATA WHEN BANNED
 | 
				
			||||||
	// -------------------------------------------- //
 | 
						// -------------------------------------------- //
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -305,6 +305,10 @@ public class MConf extends Entity<MConf>
 | 
				
			|||||||
	// It works in both directions. Meaning you must join a faction to hurt players and get hurt by players.
 | 
						// It works in both directions. Meaning you must join a faction to hurt players and get hurt by players.
 | 
				
			||||||
	public boolean disablePVPForFactionlessPlayers = false;
 | 
						public boolean disablePVPForFactionlessPlayers = false;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
						// If you set this option to true then factionless players cant damage each other.
 | 
				
			||||||
 | 
						// So two factionless can't PvP, but they can PvP with others if that is allowed.
 | 
				
			||||||
 | 
						public boolean enablePVPBetweenFactionlessPlayers = true;
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	// Set this option to true to create an exception to the rule above.
 | 
						// Set this option to true to create an exception to the rule above.
 | 
				
			||||||
	// Players inside their own faction territory can then hurt facitonless players.
 | 
						// Players inside their own faction territory can then hurt facitonless players.
 | 
				
			||||||
	// This way you may "evict" factionless trolls messing around in your home base.
 | 
						// This way you may "evict" factionless trolls messing around in your home base.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user