package fruitymod; import basemod.BaseMod; import basemod.abstracts.CustomCard; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.megacrit.cardcrawl.actions.AbstractGameAction; import com.megacrit.cardcrawl.actions.common.ApplyPowerAction; import com.megacrit.cardcrawl.actions.common.DamageAllEnemiesAction; import com.megacrit.cardcrawl.actions.common.DrawCardAction; import com.megacrit.cardcrawl.actions.common.GainBlockAction; import com.megacrit.cardcrawl.actions.utility.WaitAction; import com.megacrit.cardcrawl.cards.AbstractCard; import com.megacrit.cardcrawl.cards.DamageInfo; import com.megacrit.cardcrawl.cards.status.Dazed; import com.megacrit.cardcrawl.characters.AbstractPlayer; import com.megacrit.cardcrawl.core.Settings; import com.megacrit.cardcrawl.dungeons.AbstractDungeon; import com.megacrit.cardcrawl.helpers.CardHelper; import com.megacrit.cardcrawl.localization.CardStrings; import com.megacrit.cardcrawl.localization.RelicStrings; import com.megacrit.cardcrawl.powers.DexterityPower; import com.megacrit.cardcrawl.powers.StrengthPower; import com.megacrit.cardcrawl.rooms.AbstractRoom; import com.megacrit.cardcrawl.unlock.UnlockTracker; import fruitymod.seeker.actions.unique.ConvergenceAction; import fruitymod.seeker.cards.*; import fruitymod.seeker.characters.TheSeeker; import fruitymod.seeker.patches.AbstractCardEnum; import fruitymod.seeker.patches.TheSeekerEnum; import fruitymod.seeker.relics.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; public class SeekerMod implements CharacterMod { public static final Logger logger = LogManager.getLogger(FruityMod.class.getName()); public static final Color PURPLE = CardHelper.getColor(139.0f, 0.0f, 139.0f); public static final String SEEKER_SHOULDER_1 = "char/shoulder.png"; public static final String SEEKER_SHOULDER_2 = "char/shoulder2.png"; public static final String SEEKER_CORPSE = "char/corpse.png"; private static final String FRUITY_MOD_ASSETS_FOLDER = "img"; // card backgrounds private static final String ATTACK_PURPLE = "512/bg_attack_purple.png"; private static final String SKILL_PURPLE = "512/bg_skill_purple.png"; private static final String POWER_PURPLE = "512/bg_power_purple.png"; private static final String ENERGY_ORB_PURPLE = "512/card_purple_orb.png"; private static final String CARD_ENERGY_ORB_PURPLE = "512/card_purple_small_orb.png"; private static final String ATTACK_PURPLE_PORTRAIT = "1024/bg_attack_purple.png"; private static final String SKILL_PURPLE_PORTRAIT = "1024/bg_skill_purple.png"; private static final String POWER_PURPLE_PORTRAIT = "1024/bg_power_purple.png"; private static final String ENERGY_ORB_PURPLE_PORTRAIT = "1024/card_purple_orb.png"; // seeker assets private static final String SEEKER_BUTTON = "charSelect/seeker_select_button.png"; private static final String SEEKER_PORTRAIT = "charSelect/SeekerPortraitBG.jpg"; private boolean isApplyingPaperPengwin = false; public SeekerMod() { /* * Note that for now when installing FruityMod, in the `mods/` folder another folder named * the value of FRUITY_MOD_ASSETS_FOLDER must be created into which all the contents of the * `images/` folder must be relocated */ logger.info("creating the color " + AbstractCardEnum.SEEKER_PURPLE.toString()); BaseMod.addColor(AbstractCardEnum.SEEKER_PURPLE, PURPLE, PURPLE, PURPLE, PURPLE, PURPLE, PURPLE, PURPLE, makePath(ATTACK_PURPLE), makePath(SKILL_PURPLE), makePath(POWER_PURPLE), makePath(ENERGY_ORB_PURPLE), makePath(ATTACK_PURPLE_PORTRAIT), makePath(SKILL_PURPLE_PORTRAIT), makePath(POWER_PURPLE_PORTRAIT), makePath(ENERGY_ORB_PURPLE_PORTRAIT), makePath(CARD_ENERGY_ORB_PURPLE)); } // used by fruitymod.seeker.patches.com.megacrit.cardcrawl.cards.AbstractCard.CanUsedDazed public static boolean hasRelicCustom(String relicID, AbstractCard card) { System.out.println("I was checked!"); // if it's checking for relicID.equals("Medical Kit") then we know we're in the block where // we are saying if we can use a status card so also check if we have enigma and the card is Dazed if (relicID.equals("Medical Kit") && AbstractDungeon.player.hasPower("EnigmaPower") && card.cardID.equals("Dazed")) { return true; } else { // otherwise leave normal behavior intact return AbstractDungeon.player.hasRelic(relicID); } } // used by fruitmod.patches.com.megacrit.cardcrawl.cards.status.Dazed.UseDazed public static void maybeUseDazed(Dazed dazed) { System.out.println("maybe use dazed"); if (!AbstractDungeon.player.hasPower("EnigmaPower")) { System.out.println("do use dazed"); AbstractDungeon.actionManager.addToTop(new com.megacrit.cardcrawl.actions.utility.UseCardAction(dazed)); } else { System.out.println("don't use dazed"); } } public static final String makeCardImagePath(String cardName) { return makePath("cards/" + cardName); } public static final String makeRelicImagePath(String power) { return makePath("relics/" + power); } // // Relic code // (yes we're doing the exact same things the devs did where relic code // isn't in the actual relics - oh well) // public static final String makePowerImagePath(String power) { return makePath("powers/" + power); } /** * Makes a full path for a resource path * * @param resource the resource, must *NOT* have a leading "/" * @return the full path */ public static final String makePath(String resource) { String result = FRUITY_MOD_ASSETS_FOLDER + "/seeker/" + resource; if (!hasExtension(resource)) { result += ".png"; } return result; } @Override public void receivePostExhaust(AbstractCard abstractCard) { } private static boolean hasExtension(String filename) { return filename.lastIndexOf('.') > 0; } @Override public void receiveEditCharacters() { logger.info("add " + TheSeekerEnum.THE_SEEKER.toString()); BaseMod.addCharacter(new TheSeeker("the Seeker", TheSeekerEnum.THE_SEEKER), makePath(SEEKER_BUTTON), makePath(SEEKER_PORTRAIT), TheSeekerEnum.THE_SEEKER); } @Override public void receiveEditRelics() { // Add relics BaseMod.addRelicToCustomPool(new Arcanosphere(), AbstractCardEnum.SEEKER_PURPLE); BaseMod.addRelicToCustomPool(new Blueberries(), AbstractCardEnum.SEEKER_PURPLE); BaseMod.addRelicToCustomPool(new PaperPengwin(), AbstractCardEnum.SEEKER_PURPLE); BaseMod.addRelicToCustomPool(new CosmicSieve(), AbstractCardEnum.SEEKER_PURPLE); BaseMod.addRelicToCustomPool(new SolarEgg(), AbstractCardEnum.SEEKER_PURPLE); BaseMod.addRelicToCustomPool(new RodOfNegation(), AbstractCardEnum.SEEKER_PURPLE); BaseMod.addRelicToCustomPool(new Telescope(), AbstractCardEnum.SEEKER_PURPLE); } @Override public void receiveEditCards() { logger.info("add cards for " + TheSeekerEnum.THE_SEEKER.toString()); List<CustomCard> cards = new ArrayList<CustomCard>(); cards.add(new Dazed_P()); cards.add(new Strike_Purple()); cards.add(new Defend_Purple()); cards.add(new Starburst()); cards.add(new Irradiate()); cards.add(new AstralHaze()); cards.add(new Brainstorm()); cards.add(new DarkMatter()); cards.add(new ArcaneArmor()); cards.add(new Entropy()); cards.add(new EssenceDart()); cards.add(new Flicker()); cards.add(new PlasmaWave()); cards.add(new PulseBarrier()); cards.add(new Nebula()); cards.add(new EtherBlast()); cards.add(new Flare()); cards.add(new NullStorm()); cards.add(new VoidRay()); cards.add(new DisruptionField()); cards.add(new UnstableOrb()); cards.add(new Hypothesis()); cards.add(new Comet()); cards.add(new ForceRipple()); cards.add(new PhaseCoil()); cards.add(new Overload()); cards.add(new Syzygy()); cards.add(new SiphonPower()); cards.add(new Shimmer()); cards.add(new ThoughtRaze()); cards.add(new Retrograde()); cards.add(new Singularity()); cards.add(new Umbra()); cards.add(new Genesis()); cards.add(new PrismaticSphere()); cards.add(new Flux()); cards.add(new Channel()); cards.add(new Implosion()); cards.add(new ChaosForm()); cards.add(new Vacuum()); cards.add(new DimensionDoor()); cards.add(new Wormhole()); cards.add(new Eureka()); cards.add(new Eclipse()); cards.add(new Echo()); cards.add(new EventHorizon()); cards.add(new Zenith()); cards.add(new ReflectionWard()); cards.add(new Creativity()); cards.add(new Transference()); cards.add(new Surge()); cards.add(new StrokeOfGenius()); cards.add(new SiphonSpeed()); cards.add(new Convergence()); cards.add(new GravityWell()); cards.add(new Coalescence()); cards.add(new PeriaptOfCelerity()); cards.add(new PeriaptOfPotency()); cards.add(new MeteorShower()); cards.add(new PowerOverwhelming()); cards.add(new MindOverMatter()); cards.add(new Disperse()); cards.add(new Magnetize()); cards.add(new Illuminate()); cards.add(new Flow()); cards.add(new Equinox()); cards.add(new Corona()); cards.add(new Archives()); cards.add(new MagicMissile()); cards.add(new Enigma()); cards.add(new Feedback()); cards.add(new Premonitions()); cards.add(new Anomaly()); cards.add(new Nova()); cards.add(new Vortex()); cards.add(new Nexus()); for (CustomCard card : cards) { BaseMod.addCard(card); UnlockTracker.unlockCard(card.cardID); } } @Override public void receiveEditStrings() { // RelicStrings String relicStrings = Gdx.files.internal("localization/Seeker-RelicStrings.json").readString( String.valueOf(StandardCharsets.UTF_8)); BaseMod.loadCustomStrings(RelicStrings.class, relicStrings); // CardStrings String cardStrings = Gdx.files.internal("localization/Seeker-CardStrings.json").readString( String.valueOf(StandardCharsets.UTF_8)); BaseMod.loadCustomStrings(CardStrings.class, cardStrings); logger.info("done editting strings"); } @Override public void receiveEditKeywords() { logger.info("setting up custom keywords"); BaseMod.addKeyword(new String[]{"reflect", "Reflect"}, "Whenever you are attacked this turn, deal this amount of damage back to ALL enemies."); BaseMod.addKeyword(new String[]{"top-cycle", "Top-Cycle"}, "When you Top-Cycle a card, place it on top of your draw pile."); BaseMod.addKeyword(new String[]{"recycle", "Recycle"}, "When you Recycle a card, shuffle it randomly into your draw pile."); } // // Enigma hooks and functionality // private boolean moreThanXStacks(AbstractPlayer player, String powerID, int stacksWanted) { if (player != null && player.hasPower(powerID) && player.getPower(powerID).amount >= stacksWanted) { return true; } else { return false; } } private void resetPaperPengwin() { isApplyingPaperPengwin = false; if (AbstractDungeon.player.hasRelic("PaperPengwin")) { ((PaperPengwin) AbstractDungeon.player.getRelic("PaperPengwin")).setPulse(false); } } @Override public void receivePowersModified() { AbstractPlayer p = AbstractDungeon.player; if (p != null && p.hasRelic("PaperPengwin")) { if (moreThanXStacks(p, "Weakened", PaperPengwin.MIN_STACKS) || moreThanXStacks(p, "Vulnerable", PaperPengwin.MIN_STACKS) || moreThanXStacks(p, "Frail", PaperPengwin.MIN_STACKS)) { if (!isApplyingPaperPengwin) { AbstractDungeon.actionManager.addToTop( new ApplyPowerAction(p, p, new DexterityPower(p, PaperPengwin.MIN_STACKS), PaperPengwin.MIN_STACKS)); AbstractDungeon.actionManager.addToTop( new ApplyPowerAction(p, p, new StrengthPower(p, PaperPengwin.MIN_STACKS), PaperPengwin.MIN_STACKS)); isApplyingPaperPengwin = true; p.getRelic("PaperPengwin").flash(); ((PaperPengwin) p.getRelic("PaperPengwin")).setPulse(true); } } else { if (isApplyingPaperPengwin) { AbstractDungeon.actionManager.addToTop( new ApplyPowerAction(p, p, new DexterityPower(p, -1 * PaperPengwin.MIN_STACKS), -1 * PaperPengwin.MIN_STACKS)); AbstractDungeon.actionManager.addToTop( new ApplyPowerAction(p, p, new StrengthPower(p, -1 * PaperPengwin.MIN_STACKS), -1 * PaperPengwin.MIN_STACKS)); isApplyingPaperPengwin = false; ((PaperPengwin) p.getRelic("PaperPengwin")).setPulse(false); } } } } @Override public void receivePostBattle(AbstractRoom arg0) { resetPaperPengwin(); } @Override public void receivePostDungeonInitialize() { resetPaperPengwin(); } @Override public void receivePostDraw(AbstractCard c) { if (c instanceof Convergence) { c.superFlash(); if (c.upgraded) { AbstractDungeon.actionManager.addToTop(new DrawCardAction(AbstractDungeon.player, 1)); } AbstractDungeon.actionManager.addToBottom(new WaitAction(Settings.ACTION_DUR_FAST)); AbstractDungeon.actionManager.addToBottom(new ConvergenceAction(c.upgraded)); } } @Override public void receiveCardUsed(AbstractCard c) { AbstractPlayer p = AbstractDungeon.player; if (p.hasPower("EnigmaPower") && c.cardID.equals("Dazed")) { AbstractDungeon.actionManager.addToTop(new GainBlockAction(p, p, c.block)); AbstractDungeon.actionManager.addToTop(new DamageAllEnemiesAction(AbstractDungeon.player, c.multiDamage, DamageInfo.DamageType.NORMAL, AbstractGameAction.AttackEffect.FIRE, true)); c.exhaustOnUseOnce = false; } } }