001package com.fs.starfarer.api.impl.combat;
002
003import java.util.List;
004
005import org.lwjgl.util.vector.Vector2f;
006
007import com.fs.starfarer.api.combat.BeamAPI;
008import com.fs.starfarer.api.combat.BeamEffectPlugin;
009import com.fs.starfarer.api.combat.CombatEngineAPI;
010import com.fs.starfarer.api.combat.CombatEntityAPI;
011import com.fs.starfarer.api.combat.DamageAPI;
012import com.fs.starfarer.api.combat.ShipAPI;
013import com.fs.starfarer.api.combat.WeaponAPI;
014import com.fs.starfarer.api.combat.listeners.AdvanceableListener;
015import com.fs.starfarer.api.util.TimeoutTracker;
016
017public class GravitonBeamEffect implements BeamEffectPlugin {
018
019        public static float EFFECT_DUR = 1f;
020        
021        public static float DAMAGE_PERCENT_ONE = 5f;
022        public static float DAMAGE_PERCENT_TWO = 8f;
023        public static float DAMAGE_PERCENT_THREE = 10f;
024        
025        protected boolean wasZero = true;
026        
027        
028        public void advance(float amount, CombatEngineAPI engine, BeamAPI beam) {
029                CombatEntityAPI target = beam.getDamageTarget();
030                if (target instanceof ShipAPI && beam.getBrightness() >= 1f && beam.getWeapon() != null) {
031                        float dur = beam.getDamage().getDpsDuration();
032                        // needed because when the ship is in fast-time, dpsDuration will not be reset every frame as it should be
033                        if (!wasZero) dur = 0;
034                        wasZero = beam.getDamage().getDpsDuration() <= 0;
035                        
036                        // beam tick, apply damage modifier effect if needed
037                        if (dur > 0) {
038                                boolean hitShield = target.getShield() != null && target.getShield().isWithinArc(beam.getTo());
039                                if (hitShield) {
040                                        ShipAPI ship = (ShipAPI) target;
041                                        if (!ship.hasListenerOfClass(GravitonBeamDamageTakenMod.class)) {
042                                                ship.addListener(new GravitonBeamDamageTakenMod(ship));
043                                        }
044                                        List<GravitonBeamDamageTakenMod> listeners = ship.getListeners(GravitonBeamDamageTakenMod.class);
045                                        if (listeners.isEmpty()) return; // ???
046                                        
047                                        GravitonBeamDamageTakenMod listener = listeners.get(0);
048                                        listener.notifyHit(beam.getWeapon());
049                                }
050                        }
051                }
052        }
053        
054
055        public static String DAMAGE_MOD_ID = "gravitonbeam_dam_mod";
056
057        public static class GravitonBeamDamageTakenMod implements AdvanceableListener {
058                                                        //implements DamageTakenModifier, AdvanceableListener {
059                protected ShipAPI ship;
060                protected TimeoutTracker<WeaponAPI> recentHits = new TimeoutTracker<WeaponAPI>();
061                public GravitonBeamDamageTakenMod(ShipAPI ship) {
062                        this.ship = ship;
063                        //ship.addListener(new GravitonBeamDamageTakenModRemover(ship));
064                }
065                
066                public void notifyHit(WeaponAPI w) {
067                        recentHits.add(w, EFFECT_DUR, EFFECT_DUR);
068                        
069                }
070                
071                public void advance(float amount) {
072                        recentHits.advance(amount);
073                        
074                        int beams = recentHits.getItems().size();
075
076                        float bonus = 0;
077                        if (beams == 1) {
078                                bonus = DAMAGE_PERCENT_ONE;
079                        } else if (beams == 2) {
080                                bonus = DAMAGE_PERCENT_TWO;
081                        } else if (beams >= 3) {
082                                bonus = DAMAGE_PERCENT_THREE;
083                        }
084                        
085                        if (bonus > 0) {
086                                ship.getMutableStats().getShieldDamageTakenMult().modifyMult(DAMAGE_MOD_ID, 1f + bonus * 0.01f);
087                        } else {
088                                ship.removeListener(this);
089                                ship.getMutableStats().getShieldDamageTakenMult().unmodify(DAMAGE_MOD_ID);
090                        }
091                }
092
093                public String modifyDamageTaken(Object param,
094                                                                                CombatEntityAPI target, DamageAPI damage,
095                                                                                Vector2f point, boolean shieldHit) {
096                        return null;
097                }
098
099        }
100
101}