/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

package com.skelril.skree.content.zone.global.theforge;

import com.skelril.nitro.combat.PlayerCombatParser;
import com.skelril.nitro.probability.Probability;
import org.spongepowered.api.entity.living.Living;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.entity.projectile.Projectile;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.cause.entity.damage.DamageModifier;
import org.spongepowered.api.event.entity.CollideEntityEvent;
import org.spongepowered.api.event.entity.DamageEntityEvent;
import org.spongepowered.api.event.entity.DestructEntityEvent;
import org.spongepowered.api.event.filter.Getter;
import org.spongepowered.api.event.filter.cause.First;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.util.Tuple;

import java.util.Optional;
import java.util.function.Function;

public class TheForgeListener {
  private final TheForgeManager manager;

  public TheForgeListener(TheForgeManager manager) {
    this.manager = manager;
  }

  @Listener
  public void onPlayerCombat(DamageEntityEvent event) {
    Optional<TheForgeInstance> optInst = manager.getApplicableZone(event.getTargetEntity());
    if (!optInst.isPresent()) {
      return;
    }

    new PlayerCombatParser() {
      @Override
      public void processPlayerAttack(Player attacker, Living defender) {
        if (attacker.getLocation().getY() != attacker.getLocation().getBlockY()) {
          event.setBaseDamage(Probability.getCompoundRandom(event.getBaseDamage(), 4));
        }
      }
    }.parse(event);
  }

  @Listener
  public void onPlayerCombat(CollideEntityEvent.Impact event, @First Projectile projectile) {
    Optional<TheForgeInstance> optInst = manager.getApplicableZone(projectile);
    if (!optInst.isPresent()) {
      return;
    }

    new PlayerCombatParser() {
      @Override
      public void processMonsterAttack(Living attacker, Player defender) {
        if (!(event instanceof DamageEntityEvent)) {
          return;
        }

        DamageEntityEvent dEvent = (DamageEntityEvent) event;
        for (Tuple<DamageModifier, Function<? super Double, Double>> modifier : dEvent.getModifiers()) {
          dEvent.setDamage(modifier.getFirst(), (a) -> Math.floor(a * .5));
        }
      }
    }.parse(event);
  }

  @Listener
  public void onPlayerDeath(DestructEntityEvent.Death event, @Getter("getTargetEntity") Player player) {
    Optional<TheForgeInstance> optInst = manager.getApplicableZone(player);
    if (optInst.isPresent()) {
      if (event.getMessage().toPlain().contains("died")) {
        event.setMessage(Text.of(player.getName(), " was incinerated at The Forge"));
      }
    }
  }
}

@@ -530,16 +530,58 @@
 ectile;%0A
+import org.spongepowered.api.event.Event;%0A
 import o
@@ -1291,203 +1291,73 @@
 %0A%0A  
-@Listener%0A  public void onPlayerCombat(DamageEntityEvent event) %7B%0A    Optional%3CTheForgeInstance%3E optInst = manager.getApplicableZone(event.getTargetEntity());%0A    if (!optInst.isPres
+private PlayerCombatParser createCombatParser(Event ev
 ent
-()
 ) %7B%0A    
   re
@@ -1352,36 +1352,22 @@
 ) %7B%0A    
- 
- 
 return
-;%0A    %7D%0A%0A   
  new Pla
@@ -1492,479 +1492,333 @@
 if (
-attacker.getLocation().getY() != attacker.getLocation().getBlockY()) %7B%0A          event.setBaseDamage(Probability.getCompoundRandom(event.getBaseDamage(), 4));%0A        %7D%0A      %7D%0A    %7D.parse(event);%0A  %7D%0A%0A  @Listener%0A  public void onPlayerCombat(CollideEntityEvent.Impact event, @First Projectile projectile) %7B%0A    Optional%3CTheForgeInstance%3E optInst = manager.getApplicableZone(projectile);%0A    if (!optInst.isPresent()) %7B%0A      return;%0A
+!(event instanceof DamageEntityEvent)) %7B%0A          return;%0A        %7D%0A%0A        if (attacker.getLocation().getY() != attacker.getLocation().getBlockY()) %7B%0A          DamageEntityEvent dEvent = (DamageEntityEvent) event;%0A          dEvent.setBaseDamage(Probability.getCompoundRandom(dEvent.getBaseDamage(), 4));%0A    
     %7D%0A
-%0A
     
-new PlayerCombatParser() %7B
+  %7D%0A
 %0A   
@@ -1979,32 +1979,74 @@
 urn;%0A        %7D%0A%0A
+        if (Probability.getChance(5)) %7B%0A  
         DamageEn
@@ -2099,16 +2099,18 @@
         
+ 
+ 
 for (Tup
@@ -2200,32 +2200,34 @@
 ()) %7B%0A          
+  
 dEvent.setDamage
@@ -2259,52 +2259,586 @@
  -%3E 
-Math.floor(a * .5));%0A        %7D%0A      %7D%0A    %7D
+0D);%0A          %7D%0A        %7D%0A      %7D%0A    %7D;%0A  %7D%0A%0A  @Listener%0A  public void onPlayerCombat(DamageEntityEvent event) %7B%0A    Optional%3CTheForgeInstance%3E optInst = manager.getApplicableZone(event.getTargetEntity());%0A    if (!optInst.isPresent()) %7B%0A      return;%0A    %7D%0A%0A    createCombatParser(event).parse(event);%0A  %7D%0A%0A  @Listener%0A  public void onPlayerCombat(CollideEntityEvent.Impact event, @First Projectile projectile) %7B%0A    Optional%3CTheForgeInstance%3E optInst = manager.getApplicableZone(projectile);%0A    if (!optInst.isPresent()) %7B%0A      return;%0A    %7D%0A%0A    createCombatParser(event)
 .par

Change forge combat again