/* * Copyright (C) 2022 Linnea Gräf * * This file is part of NotEnoughUpdates. * * NotEnoughUpdates is free software: you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation, either * version 3 of the License, or (at your option) any later version. * * NotEnoughUpdates is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with NotEnoughUpdates. If not, see . */ package io.github.moulberry.notenoughupdates.recipes import com.google.gson.JsonObject import com.google.gson.JsonPrimitive import io.github.moulberry.notenoughupdates.NEUManager import io.github.moulberry.notenoughupdates.core.util.GuiElementSlider import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay.Pet import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe import io.github.moulberry.notenoughupdates.util.ItemUtils import io.github.moulberry.notenoughupdates.util.PetLeveling import io.github.moulberry.notenoughupdates.util.Utils import io.github.moulberry.notenoughupdates.util.toJsonArray import net.minecraft.client.Minecraft import net.minecraft.client.renderer.GlStateManager import net.minecraft.util.ResourceLocation import java.time.Duration import kotlin.math.PI import kotlin.math.cos import kotlin.math.roundToInt import kotlin.math.sin data class KatRecipe( val manager: NEUManager, val inputPet: Ingredient, val outputPet: Ingredient, val items: List, val coins: Long, val time: Duration, ) : NeuRecipe { var inputLevel = 1 val radius get() = 50 / 2 val circleCenter get() = 33 + 110 / 2 to 19 + 110 / 2 val textPosition get() = circleCenter.first to circleCenter.second + 90 / 2 val sliderPos get() = 40 to 15 val levelTextPos get() = sliderPos.first - 4 - Minecraft.getMinecraft().fontRendererObj.getStringWidth("100") to sliderPos.second + 16 / 2 - Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT / 2 val levelSlider = GuiElementSlider(0, 0, 100, 1F, 100F, 1F, inputLevel.toFloat()) { inputLevel = it.toInt() } val coinsAdjustedForLevel: Int get() = (coins.toInt() * (1 - 0.003F * (getOutputPetForCurrentLevel()?.petLevel?.currentLevel ?: 0))).toInt() private val basicIngredients = items.toSet() + setOf(inputPet, Ingredient.coinIngredient(manager, coins.toInt())) override fun getIngredients(): Set = basicIngredients override fun getOutputs(): Set { return setOf(outputPet) } fun getInputPetForCurrentLevel(): Pet? { return PetInfoOverlay.getPetFromStack(inputPet.itemStack.tagCompound)?.also { val petLeveling = PetLeveling.getPetLevelingForPet(it.petType, it.rarity) it.petLevel = petLeveling.getPetLevel(petLeveling.getPetExpForLevel(inputLevel).toDouble()) } } fun getOutputPetForCurrentLevel(): Pet? { return PetInfoOverlay.getPetFromStack(outputPet.itemStack.tagCompound)?.also { val petLeveling = PetLeveling.getPetLevelingForPet(it.petType, it.rarity) it.petLevel = petLeveling.getPetLevel(getInputPetForCurrentLevel()?.petLevel?.expTotal?.toDouble() ?: 0.0) } } private fun positionOnCircle(i: Int, max: Int): Pair { val radians = PI * 2 * i / max val offsetX = cos(radians) * radius val offsetY = sin(radians) * radius return (circleCenter.first + offsetX).roundToInt() to (circleCenter.second + offsetY).roundToInt() } override fun drawExtraInfo(gui: GuiItemRecipe, mouseX: Int, mouseY: Int) { levelSlider.x = gui.guiLeft + sliderPos.first levelSlider.y = gui.guiTop + sliderPos.second levelSlider.render() Minecraft.getMinecraft().fontRendererObj.drawString( "$inputLevel", gui.guiLeft + levelTextPos.first, gui.guiTop + levelTextPos.second, 0xFF0000 ) Utils.drawStringCentered( Utils.prettyTime(time), gui.guiLeft + textPosition.first.toFloat(), gui.guiTop + textPosition.second.toFloat(), false, 0xff00ff ) GlStateManager.color(1F, 1F, 1F, 1F) } override fun genericMouseInput(mouseX: Int, mouseY: Int) { levelSlider.mouseInput(mouseX, mouseY) } override fun getSlots(): List { val advancedIngredients = items.map { it.itemStack } + listOf( ItemUtils.createPetItemstackFromPetInfo(getInputPetForCurrentLevel()), Ingredient.coinIngredient( manager, coinsAdjustedForLevel ).itemStack ) return advancedIngredients.mapIndexed { index, itemStack -> val (x, y) = positionOnCircle(index, advancedIngredients.size) RecipeSlot(x - 18 / 2, y - 18 / 2, itemStack) } + listOf( RecipeSlot( circleCenter.first - 9, circleCenter.second - 9, ItemUtils.createPetItemstackFromPetInfo(getOutputPetForCurrentLevel()) ) ) } override fun getType(): RecipeType = RecipeType.KAT_UPGRADE override fun hasVariableCost(): Boolean = false override fun serialize(): JsonObject { return JsonObject().apply { addProperty("type", type.id) addProperty("coins", coins) addProperty("input", inputPet.serialize()) addProperty("output", outputPet.serialize()) addProperty("time", time.seconds) add("items", items.map { JsonPrimitive(it.serialize()) }.toJsonArray()) } } companion object { @JvmStatic fun parseRecipe(manager: NEUManager, recipe: JsonObject, output: JsonObject): NeuRecipe { return KatRecipe( manager, Ingredient(manager, recipe["input"].asString), Ingredient(manager, recipe["output"].asString), recipe["items"]?.asJsonArray?.map { Ingredient(manager, it.asString) } ?: emptyList(), recipe["coins"].asLong, Duration.ofSeconds(recipe["time"].asLong) ) } } override fun getBackground(): ResourceLocation { return ResourceLocation("notenoughupdates:textures/gui/katting_tall.png") } override fun shouldUseForCraftCost() = false }