From 5c37e0f1d3f747644bc3a0e51900af5e991f1dc2 Mon Sep 17 00:00:00 2001 From: Kli Kli Date: Sat, 20 Jan 2024 18:06:40 +0100 Subject: [PATCH] feat: add demonic partner --- .../assets/occultism/lang/en_us.json | 20 + .../ritual_dummy/summon_demonic_husband.json | 3 + .../ritual_dummy/summon_demonic_wife.json | 3 + .../item/spawn_egg/demonic_husband.json | 3 + .../models/item/spawn_egg/demonic_wife.json | 3 + .../familiar_rituals/demonic_partner.json | 99 +++ .../familiar_shub_niggurath.json | 2 +- .../com/klikli_dev/occultism/Occultism.java | 5 + .../spirit/demonicpartner/DemonicPartner.java | 211 +++++ .../DemonicPartnerLieNextToPartnerGoal.java | 161 ++++ .../husband/DemonicHusband.java | 66 ++ .../husband/DemonicHusbandModel.java | 43 + .../husband/DemonicHusbandRenderer.java | 33 + .../demonicpartner/wife/DemonicWife.java | 66 ++ .../demonicpartner/wife/DemonicWifeModel.java | 43 + .../wife/DemonicWifeRenderer.java | 33 + .../datagen/ItemModelsGenerator.java | 12 +- .../datagen/OccultismBookProvider.java | 699 +-------------- .../datagen/book/FamiliarRitualsCategory.java | 713 ++++++++++++++++ .../familiarrituals/DemonicPartnerEntry.java | 121 +++ .../occultism/datagen/lang/ENUSProvider.java | 17 +- .../handlers/ClientSetupEventHandler.java | 8 + .../occultism/registry/OccultismEntities.java | 5 + .../occultism/registry/OccultismItems.java | 8 + .../resources/META-INF/accesstransformer.cfg | 3 +- .../entity/demonic_husband.animation.json | 798 ++++++++++++++++++ .../entity/demonic_wife.animation.json | 301 +++++++ .../geo/entity/demonic_husband.geo.json | 182 ++++ .../geo/entity/demonic_wife.geo.json | 141 ++++ .../textures/entity/demonic_husband.png | Bin 0 -> 3822 bytes .../textures/entity/demonic_wife.png | Bin 0 -> 1533 bytes .../textures/gui/book/demonic_partner.png | Bin 0 -> 6453 bytes .../ritual/summon_demonic_husband.json | 48 ++ .../recipes/ritual/summon_demonic_wife.json | 48 ++ 34 files changed, 3197 insertions(+), 701 deletions(-) create mode 100644 src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_husband.json create mode 100644 src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_wife.json create mode 100644 src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_husband.json create mode 100644 src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_wife.json create mode 100644 src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/demonic_partner.json create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartner.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartnerLieNextToPartnerGoal.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusband.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandModel.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandRenderer.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWife.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeModel.java create mode 100644 src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeRenderer.java create mode 100644 src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java create mode 100644 src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java create mode 100644 src/main/resources/assets/occultism/animations/entity/demonic_husband.animation.json create mode 100644 src/main/resources/assets/occultism/animations/entity/demonic_wife.animation.json create mode 100644 src/main/resources/assets/occultism/geo/entity/demonic_husband.geo.json create mode 100644 src/main/resources/assets/occultism/geo/entity/demonic_wife.geo.json create mode 100644 src/main/resources/assets/occultism/textures/entity/demonic_husband.png create mode 100644 src/main/resources/assets/occultism/textures/entity/demonic_wife.png create mode 100644 src/main/resources/assets/occultism/textures/gui/book/demonic_partner.png create mode 100644 src/main/resources/data/occultism/recipes/ritual/summon_demonic_husband.json create mode 100644 src/main/resources/data/occultism/recipes/ritual/summon_demonic_wife.json diff --git a/src/generated/resources/assets/occultism/lang/en_us.json b/src/generated/resources/assets/occultism/lang/en_us.json index 6a7098de2..986a1fa33 100644 --- a/src/generated/resources/assets/occultism/lang/en_us.json +++ b/src/generated/resources/assets/occultism/lang/en_us.json @@ -154,6 +154,18 @@ "book.occultism.dictionary_of_spirits.crafting_rituals.overview.intro.title": "Binding Rituals", "book.occultism.dictionary_of_spirits.crafting_rituals.overview.name": "Binding Rituals", "book.occultism.dictionary_of_spirits.crafting_rituals.return_to_rituals.name": "Return to Rituals Category", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.about.text": "The Demonic Partner - a Husband or Wife - can fight for you and help with household chores.\n\\\n\\\nRight-Click with any cookable food and they will use their magic to cook it.\n\\\n\\\nRight-Click with a potion to get the effect for a significantly longer time.\n", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.about.title": "Demonic Partner", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description": "A demonic Household?", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description.text": "Magicians practicing the occult are a diverse crowd, coming from all creeds and all corners of the world. However one thing unites them all - they are as lonely as any human without a partner.\n\\\n\\\nOf course being a magician, there is a way to solve this problem once and for all.\n", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description.title": "Demonic Partner", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description2.text": "As beings of immense powers Demons can have it all ... except love.\\\nNo demon will freely admit this, but at times they are impressed by the power and strength that some mortal occultists acquire. And in such cases, the impossible can happen - the demon can fall in love with a mortal.\n", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description2.title": "Demonic Partner", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description3.text": "Demons, of course, deal in contracts, and what better contract than a marriage contract?\n", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description3.title": "Demonic Partner", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.husband.title": "Demonic Husband", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.name": "Demonic Partner", + "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.wife.title": "Demonic Wife", "book.occultism.dictionary_of_spirits.familiar_rituals.familiar_bat.description.text": "**Upgrade Behaviour**\\\nWhen upgraded by a blacksmith familiar, the bat familiar will give a life steal effect to it's master.\n", "book.occultism.dictionary_of_spirits.familiar_rituals.familiar_bat.description.title": "Description", "book.occultism.dictionary_of_spirits.familiar_rituals.familiar_bat.entity.text": "**Provides**: [#](ad03fc)Night Vision[#]()\n", @@ -774,6 +786,8 @@ "entity.occultism.chimera_familiar": "Chimera Familiar", "entity.occultism.cthulhu_familiar": "Cthulhu Familiar", "entity.occultism.deer_familiar": "Deer Familiar", + "entity.occultism.demonic_husband": "Demonic Husband", + "entity.occultism.demonic_wife": "Demonic Wife", "entity.occultism.devil_familiar": "Devil Familiar", "entity.occultism.djinni": "Djinni", "entity.occultism.dragon_familiar": "Dragon Familiar", @@ -1055,6 +1069,10 @@ "item.occultism.ritual_dummy.summon_afrit_rain_weather.tooltip": "Summons an bound Afrit that creates rain.", "item.occultism.ritual_dummy.summon_afrit_thunder_weather": "Ritual: Thunderstorm", "item.occultism.ritual_dummy.summon_afrit_thunder_weather.tooltip": "Summons an bound Afrit that creates a thunderstorm.", + "item.occultism.ritual_dummy.summon_demonic_husband": "Ritual: Summon Demonic Husband", + "item.occultism.ritual_dummy.summon_demonic_husband.tooltip": "Summons a Demonic Husband to support you: He will fight for you, help with cooking, and extend potion durations.", + "item.occultism.ritual_dummy.summon_demonic_wife": "Ritual: Summon Demonic Wife", + "item.occultism.ritual_dummy.summon_demonic_wife.tooltip": "Summons a Demonic Wife to support you: She will fight for you, help with cooking, and extend potion durations.", "item.occultism.ritual_dummy.summon_djinni_clear_weather": "Ritual: Clear Weather", "item.occultism.ritual_dummy.summon_djinni_clear_weather.tooltip": "Summons a Djinni that clears the weather.", "item.occultism.ritual_dummy.summon_djinni_crusher": "Ritual: Summon Djinni Crusher", @@ -1099,6 +1117,8 @@ "item.occultism.soul_gem_empty": "Empty Soul Gem", "item.occultism.spawn_egg.afrit": "Afrit Spawn Egg", "item.occultism.spawn_egg.afrit_wild": "Unbound Afrit Spawn Egg", + "item.occultism.spawn_egg.demonic_husband": "Demonic Husband Spawn Egg", + "item.occultism.spawn_egg.demonic_wife": "Demonic Wife Spawn Egg", "item.occultism.spawn_egg.djinni": "Djinni Spawn Egg", "item.occultism.spawn_egg.familiar_bat": "Bat Familiar Spawn Egg", "item.occultism.spawn_egg.familiar_beaver": "Beaver Familiar Spawn Egg", diff --git a/src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_husband.json b/src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_husband.json new file mode 100644 index 000000000..1a5442cc2 --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_husband.json @@ -0,0 +1,3 @@ +{ + "parent": "occultism:item/ritual_dummy" +} \ No newline at end of file diff --git a/src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_wife.json b/src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_wife.json new file mode 100644 index 000000000..1a5442cc2 --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/ritual_dummy/summon_demonic_wife.json @@ -0,0 +1,3 @@ +{ + "parent": "occultism:item/ritual_dummy" +} \ No newline at end of file diff --git a/src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_husband.json b/src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_husband.json new file mode 100644 index 000000000..d1aaa9d6e --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_husband.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} \ No newline at end of file diff --git a/src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_wife.json b/src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_wife.json new file mode 100644 index 000000000..d1aaa9d6e --- /dev/null +++ b/src/generated/resources/assets/occultism/models/item/spawn_egg/demonic_wife.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/demonic_partner.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/demonic_partner.json new file mode 100644 index 000000000..d83603b6c --- /dev/null +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/demonic_partner.json @@ -0,0 +1,99 @@ +{ + "background_u_index": 0, + "background_v_index": 0, + "category": "occultism:familiar_rituals", + "condition": { + "type": "modonomicon:true" + }, + "description": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description", + "hide_while_locked": false, + "icon": { + "height": 16, + "texture": "occultism:textures/gui/book/demonic_partner.png", + "width": 16 + }, + "name": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.name", + "pages": [ + { + "type": "modonomicon:text", + "anchor": "", + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description.text", + "title": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description.title", + "use_markdown_in_title": false + }, + { + "type": "modonomicon:text", + "anchor": "", + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description2.text", + "title": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description2.title", + "use_markdown_in_title": false + }, + { + "type": "modonomicon:text", + "anchor": "", + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description3.text", + "title": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.description3.title", + "use_markdown_in_title": false + }, + { + "type": "modonomicon:text", + "anchor": "", + "show_title_separator": true, + "text": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.about.text", + "title": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.about.title", + "use_markdown_in_title": false + }, + { + "type": "modonomicon:entity", + "anchor": "", + "default_rotation": -45.0, + "entity_id": "occultism:demonic_wife", + "name": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.wife.title", + "offset": 0.0, + "rotate": true, + "scale": 1.0, + "text": "" + }, + { + "type": "occultism:ritual_recipe", + "anchor": "", + "recipe_id_1": "occultism:ritual/summon_demonic_wife", + "text": "", + "title1": "", + "title2": "" + }, + { + "type": "modonomicon:entity", + "anchor": "", + "default_rotation": -45.0, + "entity_id": "occultism:demonic_husband", + "name": "book.occultism.dictionary_of_spirits.familiar_rituals.demonic_partner.husband.title", + "offset": 0.0, + "rotate": true, + "scale": 1.0, + "text": "" + }, + { + "type": "occultism:ritual_recipe", + "anchor": "", + "recipe_id_1": "occultism:ritual/summon_demonic_husband", + "text": "", + "title1": "", + "title2": "" + } + ], + "parents": [ + { + "draw_arrow": true, + "entry": "occultism:familiar_rituals/overview", + "line_enabled": true, + "line_reversed": false + } + ], + "show_when_any_parent_unlocked": false, + "x": 2, + "y": -2 +} \ No newline at end of file diff --git a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/familiar_shub_niggurath.json b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/familiar_shub_niggurath.json index d65704ab4..20321e9a1 100644 --- a/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/familiar_shub_niggurath.json +++ b/src/generated/resources/data/occultism/modonomicon/books/dictionary_of_spirits/entries/familiar_rituals/familiar_shub_niggurath.json @@ -52,5 +52,5 @@ ], "show_when_any_parent_unlocked": false, "x": 2, - "y": 0 + "y": 2 } \ No newline at end of file diff --git a/src/main/java/com/klikli_dev/occultism/Occultism.java b/src/main/java/com/klikli_dev/occultism/Occultism.java index 9bcdf90f2..2d5176ef3 100644 --- a/src/main/java/com/klikli_dev/occultism/Occultism.java +++ b/src/main/java/com/klikli_dev/occultism/Occultism.java @@ -28,6 +28,8 @@ import com.klikli_dev.occultism.common.entity.familiar.*; import com.klikli_dev.occultism.common.entity.possessed.*; import com.klikli_dev.occultism.common.entity.spirit.*; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.husband.DemonicHusband; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.wife.DemonicWife; import com.klikli_dev.occultism.config.OccultismClientConfig; import com.klikli_dev.occultism.config.OccultismCommonConfig; import com.klikli_dev.occultism.config.OccultismServerConfig; @@ -154,6 +156,9 @@ private void onEntityAttributeCreation(final EntityAttributeCreationEvent event) event.put(OccultismEntities.MUMMY_FAMILIAR_TYPE.get(), MummyFamiliarEntity.createAttributes().build()); event.put(OccultismEntities.BEAVER_FAMILIAR_TYPE.get(), BeaverFamiliarEntity.createAttributes().build()); event.put(OccultismEntities.SHUB_NIGGURATH_SPAWN_TYPE.get(), ShubNiggurathSpawnEntity.createAttributes().build()); + + event.put(OccultismEntities.DEMONIC_WIFE.get(), DemonicWife.createAttributes().build()); + event.put(OccultismEntities.DEMONIC_HUSBAND.get(), DemonicHusband.createAttributes().build()); } private void serverSetup(final FMLDedicatedServerSetupEvent event) { diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartner.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartner.java new file mode 100644 index 000000000..72dfae0b1 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartner.java @@ -0,0 +1,211 @@ +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner; + +import com.klikli_dev.occultism.common.entity.familiar.FamiliarEntity; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.network.syncher.EntityDataAccessor; +import net.minecraft.network.syncher.EntityDataSerializers; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.entity.AgeableMob; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.ai.goal.*; +import net.minecraft.world.entity.ai.goal.target.OwnerHurtByTargetGoal; +import net.minecraft.world.entity.ai.goal.target.OwnerHurtTargetGoal; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.SmokingRecipe; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.phys.Vec3; +import net.neoforged.neoforge.items.ItemHandlerHelper; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class DemonicPartner extends TamableAnimal { + + private static final EntityDataAccessor IS_LYING = SynchedEntityData.defineId(DemonicPartner.class, EntityDataSerializers.BOOLEAN); + protected Optional> lastRecipe = Optional.empty(); + + protected DemonicPartner(EntityType pEntityType, Level pLevel) { + super(pEntityType, pLevel); + } + + public static AttributeSupplier.Builder createAttributes() { + return FamiliarEntity.createAttributes().add(Attributes.ATTACK_DAMAGE, 3.0D); + } + + protected void defineSynchedData() { + super.defineSynchedData(); + this.entityData.define(IS_LYING, false); + } + + public boolean isLying() { + return this.entityData.get(IS_LYING); + } + + public void setLying(boolean pLying) { + this.entityData.set(IS_LYING, pLying); + } + + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this)); + this.goalSelector.addGoal(3, new DemonicPartnerLieNextToPartnerGoal(this)); + this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0D, 10.0F, 5.0F, false)); + this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0D, true)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Player.class, 8.0F)); + + this.targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); + this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); + } + + @Nullable + @Override + public AgeableMob getBreedOffspring(ServerLevel pLevel, AgeableMob pOtherParent) { + return null; + } + + @Override + public boolean isFood(ItemStack pStack) { + //Demons eat meat + Item item = pStack.getItem(); + return item.isEdible() && pStack.getFoodProperties(this).isMeat(); + } + + public Optional> getRecipe(ItemStack pStack) { + return this.level().getRecipeManager().getAllRecipesFor(RecipeType.SMOKING).stream().filter(r -> + r.value().ingredient.test(pStack) + ).findFirst(); + } + + @Override + public void aiStep() { + super.aiStep(); + this.updateSwingTime(); + + if (this.level().isClientSide && this.swinging) { + Vec3 direction = Vec3.directionFromRotation(this.getRotationVector()).scale(0.6); + for (int i = 0; i < 5; i++) { + Vec3 pos = this.position().add(direction.x + (this.getRandom().nextFloat() - 0.5f) * 0.7, + 1.5 + (this.getRandom().nextFloat() - 0.5f) * 0.7, direction.z + (this.getRandom().nextFloat() - 0.5f) * 0.7); + this.level().addParticle(ParticleTypes.FLAME, pos.x, pos.y, pos.z, direction.x * 0.25, 0, direction.z * 0.25); + } + } + } + + @Override + public InteractionResult mobInteract(Player pPlayer, InteractionHand pHand) { + ItemStack itemstack = pPlayer.getItemInHand(pHand); + + if (this.level().isClientSide) { + boolean willInteract = this.isOwnedBy(pPlayer) || this.isTame() || itemstack.is(Items.DIAMOND) && !this.isTame(); + return willInteract ? InteractionResult.CONSUME : InteractionResult.PASS; + } + + if (this.isTame()) { + var effects = PotionUtils.getMobEffects(itemstack); + if (!effects.isEmpty()) { + for (var instance : effects) { + if (instance.getEffect().isInstantenous()) { + instance.getEffect().applyInstantenousEffect(this, this, pPlayer, instance.getAmplifier(), 1.0D); + } else { + pPlayer.addEffect(new MobEffectInstance(instance.getEffect(), instance.getDuration() * 5, instance.getAmplifier(), instance.isAmbient(), instance.isVisible())); + } + } + + if (!pPlayer.getAbilities().instabuild) { + itemstack.shrink(1); + ItemHandlerHelper.giveItemToPlayer(pPlayer, new ItemStack(Items.GLASS_BOTTLE)); + } + + return InteractionResult.SUCCESS; + } + + //cook raw food + var recipe = this.lastRecipe.isPresent() ? this.lastRecipe.get().value().ingredient.test(itemstack) ? this.lastRecipe : this.getRecipe(itemstack) : this.getRecipe(itemstack); + if (recipe.isPresent()) { + this.lastRecipe = recipe; + var result = recipe.get().value().getResultItem(this.level().registryAccess()); + if (!pPlayer.getAbilities().instabuild) { + itemstack.shrink(1); + } + ItemHandlerHelper.giveItemToPlayer(pPlayer, result); + + for (int i = 0; i < 2; i++) { + Vec3 pos = this.position().add((this.getRandom().nextFloat() - 0.5f) * 0.7, + 1.5 + (this.getRandom().nextFloat() - 0.5f) * 0.7, (this.getRandom().nextFloat() - 0.5f) * 0.7); + ((ServerLevel) this.level()).sendParticles(ParticleTypes.FLAME, pos.x, pos.y, pos.z, 1, 0, 0, 0, 0); + } + + + return InteractionResult.SUCCESS; + } + + //heal with food + if (this.isFood(itemstack) && this.getHealth() < this.getMaxHealth()) { + this.heal((float) itemstack.getFoodProperties(this).getNutrition()); + if (!pPlayer.getAbilities().instabuild) { + itemstack.shrink(1); + } + + this.gameEvent(GameEvent.EAT, this); + return InteractionResult.SUCCESS; + } + + //sit/stand + InteractionResult interactionresult = super.mobInteract(pPlayer, pHand); + if ((!interactionresult.consumesAction() || this.isBaby()) && this.isOwnedBy(pPlayer)) { + this.setOrderedToSit(!this.isOrderedToSit()); + this.jumping = false; + this.navigation.stop(); + this.setTarget(null); + return InteractionResult.SUCCESS; + } else { + return interactionresult; + } + } else if (itemstack.is(Items.DIAMOND)) { + //tame with a diamond + if (!pPlayer.getAbilities().instabuild) { + itemstack.shrink(1); + } + + if (!net.neoforged.neoforge.event.EventHooks.onAnimalTame(this, pPlayer)) { + this.tame(pPlayer); + this.navigation.stop(); + this.setTarget(null); + this.setOrderedToSit(true); + this.level().broadcastEntityEvent(this, (byte) 7); + } else { + this.level().broadcastEntityEvent(this, (byte) 6); + } + + return InteractionResult.SUCCESS; + } else { + return super.mobInteract(pPlayer, pHand); + } + } + + @Override + public boolean doHurtTarget(Entity pEntity) { + boolean flag = pEntity.hurt(this.damageSources().mobAttack(this), (float) ((int) this.getAttributeValue(Attributes.ATTACK_DAMAGE))); + if (flag) { + this.doEnchantDamageEffects(this, pEntity); + } + + return flag; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartnerLieNextToPartnerGoal.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartnerLieNextToPartnerGoal.java new file mode 100644 index 000000000..17f95ac86 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/DemonicPartnerLieNextToPartnerGoal.java @@ -0,0 +1,161 @@ +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.tags.BlockTags; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.BedBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BedPart; +import net.minecraft.world.level.storage.loot.BuiltInLootTables; +import net.minecraft.world.level.storage.loot.LootParams; +import net.minecraft.world.level.storage.loot.LootTable; +import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; +import net.minecraft.world.level.storage.loot.parameters.LootContextParams; +import net.minecraft.world.phys.AABB; + +import javax.annotation.Nullable; + +public class DemonicPartnerLieNextToPartnerGoal extends Goal { + private final DemonicPartner entity; + @Nullable + private Player ownerPlayer; + @Nullable + private BlockPos goalPos; + + public DemonicPartnerLieNextToPartnerGoal(DemonicPartner pCat) { + this.entity = pCat; + } + + /** + * Returns whether execution should begin. You can also read and cache any state necessary for execution in this + * method as well. + */ + public boolean canUse() { + if (!this.entity.isTame()) { + return false; + } else if (this.entity.isOrderedToSit()) { + return false; + } else { + LivingEntity livingentity = this.entity.getOwner(); + if (livingentity instanceof Player) { + this.ownerPlayer = (Player) livingentity; + if (!livingentity.isSleeping()) { + return false; + } + + if (this.entity.distanceToSqr(this.ownerPlayer) > 100.0D) { + return false; + } + + + BlockPos blockpos = this.ownerPlayer.blockPosition(); + BlockState blockstate = this.entity.level().getBlockState(blockpos); + if (blockstate.is(BlockTags.BEDS)) { + Direction facing = blockstate.getValue(BedBlock.FACING); + BlockPos leftPos = blockpos.relative(facing.getClockWise()); + BlockPos rightPos = blockpos.relative(facing.getCounterClockWise()); + BlockState leftState = this.entity.level().getBlockState(leftPos); + BlockState rightState = this.entity.level().getBlockState(rightPos); + + if (leftState.is(BlockTags.BEDS) && leftState.getValue(BedBlock.FACING) == facing) { + this.goalPos = this.getHeadPos(leftPos, leftState, facing); + } else if (rightState.is(BlockTags.BEDS) && rightState.getValue(BedBlock.FACING) == facing) { + this.goalPos = this.getHeadPos(rightPos, rightState, facing); + } + return this.goalPos != null && !this.spaceIsOccupied(); + } + } + + return false; + } + } + + private BlockPos getHeadPos(BlockPos pos, BlockState state, Direction facing) { + if (state.getValue(BedBlock.PART) == BedPart.FOOT) { + return pos.relative(facing); + } + return pos; + } + + private boolean spaceIsOccupied() { + for (var partner : this.entity.level().getEntitiesOfClass(DemonicPartner.class, (new AABB(this.goalPos)).inflate(2.0D))) { + if (partner != this.entity && (partner.isLying())) { + return true; + } + } + + return false; + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean canContinueToUse() { + return this.entity.isTame() && !this.entity.isOrderedToSit() && this.ownerPlayer != null && this.ownerPlayer.isSleeping() && this.goalPos != null && !this.spaceIsOccupied(); + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void start() { + if (this.goalPos != null) { + this.entity.setInSittingPose(false); + this.entity.getNavigation().moveTo(this.goalPos.getX(), this.goalPos.getY(), this.goalPos.getZ(), 1.1F); + } + + } + + /** + * Reset the task's internal state. Called when this task is interrupted by another one + */ + public void stop() { + this.entity.stopSleeping(); + this.entity.setLying(false); + float f = this.entity.level().getTimeOfDay(1.0F); + if (this.ownerPlayer.getSleepTimer() >= 100 && (double) f > 0.77D && (double) f < 0.8D && (double) this.entity.level().getRandom().nextFloat() < 0.7D) { +// this.giveMorningGift(); + } + + this.entity.getNavigation().stop(); + } + + private void giveMorningGift() { + RandomSource randomsource = this.entity.getRandom(); + BlockPos.MutableBlockPos blockpos$mutableblockpos = new BlockPos.MutableBlockPos(); + blockpos$mutableblockpos.set(this.entity.isLeashed() ? this.entity.getLeashHolder().blockPosition() : this.entity.blockPosition()); + this.entity.randomTeleport(blockpos$mutableblockpos.getX() + randomsource.nextInt(11) - 5, blockpos$mutableblockpos.getY() + randomsource.nextInt(5) - 2, blockpos$mutableblockpos.getZ() + randomsource.nextInt(11) - 5, false); + blockpos$mutableblockpos.set(this.entity.blockPosition()); + LootTable loottable = this.entity.level().getServer().getLootData().getLootTable(BuiltInLootTables.CAT_MORNING_GIFT); + LootParams lootparams = (new LootParams.Builder((ServerLevel) this.entity.level())).withParameter(LootContextParams.ORIGIN, this.entity.position()).withParameter(LootContextParams.THIS_ENTITY, this.entity).create(LootContextParamSets.GIFT); + + for (ItemStack itemstack : loottable.getRandomItems(lootparams)) { + this.entity.level().addFreshEntity(new ItemEntity(this.entity.level(), (double) blockpos$mutableblockpos.getX() - (double) Mth.sin(this.entity.yBodyRot * ((float) Math.PI / 180F)), blockpos$mutableblockpos.getY(), (double) blockpos$mutableblockpos.getZ() + (double) Mth.cos(this.entity.yBodyRot * ((float) Math.PI / 180F)), itemstack)); + } + + } + + /** + * Keep ticking a continuous task that has already been started + */ + public void tick() { + if (this.ownerPlayer != null && this.goalPos != null) { + this.entity.setInSittingPose(false); + this.entity.getNavigation().moveTo(this.goalPos.getX(), this.goalPos.getY(), this.goalPos.getZ(), 1.1F); + if (this.entity.distanceToSqr(this.ownerPlayer) < 2.5D) { + this.entity.startSleeping(this.goalPos); + this.entity.setLying(true); + } else { + this.entity.setLying(false); + } + } + + } +} \ No newline at end of file diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusband.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusband.java new file mode 100644 index 000000000..f87a1cb8d --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusband.java @@ -0,0 +1,66 @@ +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner.husband; + +import com.klikli_dev.occultism.Occultism; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.DemonicPartner; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.common.util.NonNullLazy; +import software.bernie.geckolib.animatable.GeoEntity; +import software.bernie.geckolib.core.animatable.GeoAnimatable; +import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache; +import software.bernie.geckolib.core.animation.AnimatableManager; +import software.bernie.geckolib.core.animation.AnimationController; +import software.bernie.geckolib.core.animation.AnimationState; +import software.bernie.geckolib.core.animation.RawAnimation; +import software.bernie.geckolib.core.object.PlayState; +import software.bernie.geckolib.util.GeckoLibUtil; + +public class DemonicHusband extends DemonicPartner implements GeoEntity { + + public static final ResourceLocation ID = new ResourceLocation(Occultism.MODID, "demonic_husband"); + public static final NonNullLazy> ENTITY_TYPE = + NonNullLazy.of(() -> EntityType.Builder.of(DemonicHusband::new, MobCategory.CREATURE) + .sized(0.6F, 2) + .fireImmune() + .clientTrackingRange(8) + .build(ID.toString())); + AnimatableInstanceCache animatableInstanceCache = GeckoLibUtil.createInstanceCache(this); + + protected DemonicHusband(EntityType pEntityType, Level pLevel) { + super(pEntityType, pLevel); + } + + @Override + public int getCurrentSwingDuration() { + return 11; //to match our attack animation speed + 1 tick + } + + @Override + public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { + var mainController = new AnimationController<>(this, "mainController", 0, this::animPredicate); + controllers.add(mainController); + } + + private PlayState animPredicate(AnimationState tAnimationState) { + + if (this.swinging) { + return tAnimationState.setAndContinue(RawAnimation.begin().thenPlay("attack")); + } + + if (this.isInSittingPose()) + return tAnimationState.setAndContinue(RawAnimation.begin().thenPlay("sitting")); + + if (this.isLying()) + return tAnimationState.setAndContinue(RawAnimation.begin().thenPlay("lies")); + + return tAnimationState.setAndContinue(tAnimationState.isMoving() ? RawAnimation.begin().thenPlay("walk") : RawAnimation.begin().thenPlay("idle")); + } + + @Override + public AnimatableInstanceCache getAnimatableInstanceCache() { + return this.animatableInstanceCache; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandModel.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandModel.java new file mode 100644 index 000000000..8549c7f92 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandModel.java @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright 2020 klikli-dev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner.husband; + +import software.bernie.geckolib.model.DefaultedGeoModel; + + +public class DemonicHusbandModel extends DefaultedGeoModel { + + public DemonicHusbandModel() { + super(DemonicHusband.ID); + } + + @Override + protected String subtype() { + return "entity"; + } +// +// @Override +// public RenderType getRenderType(AfritEntity animatable, ResourceLocation texture) { +// return RenderType.entityTranslucent(this.getTextureResource(animatable)); +// } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandRenderer.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandRenderer.java new file mode 100644 index 000000000..d27fb327c --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/husband/DemonicHusbandRenderer.java @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright 2020 klikli-dev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner.husband; + +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import software.bernie.geckolib.renderer.GeoEntityRenderer; + +public class DemonicHusbandRenderer extends GeoEntityRenderer { + + public DemonicHusbandRenderer(EntityRendererProvider.Context renderManager) { + super(renderManager, new DemonicHusbandModel()); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWife.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWife.java new file mode 100644 index 000000000..ae77803e4 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWife.java @@ -0,0 +1,66 @@ +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner.wife; + +import com.klikli_dev.occultism.Occultism; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.DemonicPartner; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.common.util.NonNullLazy; +import software.bernie.geckolib.animatable.GeoEntity; +import software.bernie.geckolib.core.animatable.GeoAnimatable; +import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache; +import software.bernie.geckolib.core.animation.AnimatableManager; +import software.bernie.geckolib.core.animation.AnimationController; +import software.bernie.geckolib.core.animation.AnimationState; +import software.bernie.geckolib.core.animation.RawAnimation; +import software.bernie.geckolib.core.object.PlayState; +import software.bernie.geckolib.util.GeckoLibUtil; + +public class DemonicWife extends DemonicPartner implements GeoEntity { + + public static final ResourceLocation ID = new ResourceLocation(Occultism.MODID, "demonic_wife"); + public static final NonNullLazy> ENTITY_TYPE = + NonNullLazy.of(() -> EntityType.Builder.of(DemonicWife::new, MobCategory.CREATURE) + .sized(0.6F, 2) + .fireImmune() + .clientTrackingRange(8) + .build(ID.toString())); + AnimatableInstanceCache animatableInstanceCache = GeckoLibUtil.createInstanceCache(this); + + protected DemonicWife(EntityType pEntityType, Level pLevel) { + super(pEntityType, pLevel); + } + + @Override + public int getCurrentSwingDuration() { + return 11; //to match our attack animation speed + 1 tick + } + + @Override + public void registerControllers(AnimatableManager.ControllerRegistrar controllers) { + var mainController = new AnimationController<>(this, "mainController", 0, this::animPredicate); + controllers.add(mainController); + } + + private PlayState animPredicate(AnimationState tAnimationState) { + + if (this.swinging) { + return tAnimationState.setAndContinue(RawAnimation.begin().thenPlay("attack")); + } + + if (this.isInSittingPose()) + return tAnimationState.setAndContinue(RawAnimation.begin().thenPlay("sit")); + + if (this.isLying()) + return tAnimationState.setAndContinue(RawAnimation.begin().thenPlay("lies")); + + return tAnimationState.setAndContinue(tAnimationState.isMoving() ? RawAnimation.begin().thenPlay("walk") : RawAnimation.begin().thenPlay("idle")); + } + + @Override + public AnimatableInstanceCache getAnimatableInstanceCache() { + return this.animatableInstanceCache; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeModel.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeModel.java new file mode 100644 index 000000000..d998e87ab --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeModel.java @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright 2020 klikli-dev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner.wife; + +import software.bernie.geckolib.model.DefaultedGeoModel; + + +public class DemonicWifeModel extends DefaultedGeoModel { + + public DemonicWifeModel() { + super(DemonicWife.ID); + } + + @Override + protected String subtype() { + return "entity"; + } +// +// @Override +// public RenderType getRenderType(AfritEntity animatable, ResourceLocation texture) { +// return RenderType.entityTranslucent(this.getTextureResource(animatable)); +// } +} diff --git a/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeRenderer.java b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeRenderer.java new file mode 100644 index 000000000..f08fa3300 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/common/entity/spirit/demonicpartner/wife/DemonicWifeRenderer.java @@ -0,0 +1,33 @@ +/* + * MIT License + * + * Copyright 2020 klikli-dev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and + * associated documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT + * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +package com.klikli_dev.occultism.common.entity.spirit.demonicpartner.wife; + +import net.minecraft.client.renderer.entity.EntityRendererProvider; +import software.bernie.geckolib.renderer.GeoEntityRenderer; + +public class DemonicWifeRenderer extends GeoEntityRenderer { + + public DemonicWifeRenderer(EntityRendererProvider.Context renderManager) { + super(renderManager, new DemonicWifeModel()); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java b/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java index 170684806..c71bd5712 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/ItemModelsGenerator.java @@ -23,12 +23,15 @@ package com.klikli_dev.occultism.datagen; import com.klikli_dev.occultism.Occultism; +import com.klikli_dev.occultism.registry.OccultismItems; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; +import net.minecraft.world.item.Item; import net.neoforged.neoforge.client.model.generators.ItemModelBuilder; import net.neoforged.neoforge.client.model.generators.ItemModelProvider; import net.neoforged.neoforge.client.model.generators.ModelFile; import net.neoforged.neoforge.common.data.ExistingFileHelper; +import net.neoforged.neoforge.registries.DeferredItem; import java.util.ArrayList; import java.util.List; @@ -46,14 +49,21 @@ protected void registerModels() { this.registerRitualDummy("item/" + key.getPath()); } }); - this.registerAdvancementItem(); + + + this.registerSpawnEgg(OccultismItems.SPAWN_EGG_DEMONIC_WIFE); + this.registerSpawnEgg(OccultismItems.SPAWN_EGG_DEMONIC_HUSBAND); } private void registerRitualDummy(String name) { this.getBuilder(name).parent(new ModelFile.UncheckedModelFile("occultism:item/ritual_dummy")); } + private void registerSpawnEgg(DeferredItem spawnEgg) { + this.getBuilder("item/" + spawnEgg.getId().getPath()).parent(new ModelFile.UncheckedModelFile("item/template_spawn_egg")); + } + private void registerAdvancementItem() { String[] textures = {"cthulhu_icon", "bat_icon", "deer_icon", "devil_icon", "greedy_icon", "hat_icon", "dragon_icon", "blacksmith_icon", "guardian_icon", "headless_icon", "chimera_icon", diff --git a/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java b/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java index b3e3e953f..3d281d2f9 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/OccultismBookProvider.java @@ -13,13 +13,13 @@ import com.klikli_dev.modonomicon.api.datagen.book.condition.BookModLoadedConditionModel; import com.klikli_dev.modonomicon.api.datagen.book.condition.BookTrueConditionModel; import com.klikli_dev.modonomicon.api.datagen.book.page.*; +import com.klikli_dev.occultism.datagen.book.FamiliarRitualsCategory; import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; import com.klikli_dev.occultism.integration.modonomicon.pages.BookSpiritFireRecipePageModel; import com.klikli_dev.occultism.integration.modonomicon.pages.BookSpiritTradeRecipePageModel; import com.klikli_dev.occultism.registry.OccultismBlocks; import com.klikli_dev.occultism.registry.OccultismItems; import com.klikli_dev.theurgy.registry.ItemRegistry; -import net.minecraft.client.gui.GuiGraphics; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Items; @@ -57,7 +57,7 @@ protected BookModel generateBook() { var summoningRitualsCategory = this.makeSummoningRitualsSubcategory().withSortNumber(sortNum++); var possessionRitualsCategory = this.makePossessionRitualsSubcategory().withSortNumber(sortNum++); var craftingRitualsCategory = this.makeCraftingRitualsSubcategory().withSortNumber(sortNum++); - var familiarRitualsCategory = this.makeFamiliarRitualsSubcategory().withSortNumber(sortNum++); + var familiarRitualsCategory = new FamiliarRitualsCategory(this).generate().withSortNumber(sortNum++); var pentaclesCategory = this.makePentaclesCategory().withSortNumber(sortNum++); @@ -5041,701 +5041,6 @@ private BookEntryModel makePossessElderGuardianEntry(CategoryEntryMap entryMap, } //endregion - //region Familiar Rituals - private BookCategoryModel makeFamiliarRitualsSubcategory() { - this.context().category("familiar_rituals"); - - var entryMap = ModonomiconAPI.get().getEntryMap(); - entryMap.setMap( - "________R_T_V_X____________", - "___________________________", - "_______Q_S_U_W_____________", - "___________________________", - "___r_o_________Y___________", - "___________________________", - "_______I_K_M_O_____________", - "___________________________", - "________J_L_N_P____________" - ); - - var overview = this.makeFamiliarsRitualsOverviewEntry(entryMap, 'o'); - var returnToRituals = this.makeReturnToRitualsEntry(entryMap, 'r'); - returnToRituals.withParent(BookEntryParentModel.create(overview.getId())); - returnToRituals.withCondition(BookTrueConditionModel.builder().build()); - - var familiarBat = this.makeFamiliarBatEntry(entryMap, 'I'); - familiarBat.withParent(BookEntryParentModel.create(overview.getId())); - var familiarBeaver = this.makeFamiliarBeaverEntry(entryMap, 'J'); - familiarBeaver.withParent(BookEntryParentModel.create(overview.getId())); - var familiarBeholder = this.makeFamiliarBeholderEntry(entryMap, 'K'); - familiarBeholder.withParent(BookEntryParentModel.create(overview.getId())); - var familiarBlacksmith = this.makeFamiliarBlacksmithEntry(entryMap, 'L'); - familiarBlacksmith.withParent(BookEntryParentModel.create(overview.getId())); - var familiarChimera = this.makeFamiliarChimeraEntry(entryMap, 'M'); - familiarChimera.withParent(BookEntryParentModel.create(overview.getId())); - var familiarCthulhu = this.makeFamiliarCthulhuEntry(entryMap, 'N'); - familiarCthulhu.withParent(BookEntryParentModel.create(overview.getId())); - var familiarDeer = this.makeFamiliarDeerEntry(entryMap, 'O'); - familiarDeer.withParent(BookEntryParentModel.create(overview.getId())); - var familiarDevil = this.makeFamiliarDevilEntry(entryMap, 'P'); - familiarDevil.withParent(BookEntryParentModel.create(overview.getId())); - var familiarDragon = this.makeFamiliarDragonEntry(entryMap, 'Q'); - familiarDragon.withParent(BookEntryParentModel.create(overview.getId())); - var familiarFairy = this.makeFamiliarFairyEntry(entryMap, 'R'); - familiarFairy.withParent(BookEntryParentModel.create(overview.getId())); - var familiarGreedy = this.makeFamiliarGreedyEntry(entryMap, 'S'); - familiarGreedy.withParent(BookEntryParentModel.create(overview.getId())); - var familiarGuardian = this.makeFamiliarGuardianEntry(entryMap, 'T'); - familiarGuardian.withParent(BookEntryParentModel.create(overview.getId())); - var familiarHeadlessRatman = this.makeFamiliarHeadlessRatmanEntry(entryMap, 'U'); - familiarHeadlessRatman.withParent(BookEntryParentModel.create(overview.getId())); - var familiarMummy = this.makeFamiliarMummyEntry(entryMap, 'V'); - familiarMummy.withParent(BookEntryParentModel.create(overview.getId())); - var familiarOtherworldBird = this.makeFamiliarOtherworldBirdEntry(entryMap, 'W'); - familiarOtherworldBird.withParent(BookEntryParentModel.create(overview.getId())); - var familiarParrot = this.makeFamiliarParrotEntry(entryMap, 'X'); - familiarParrot.withParent(BookEntryParentModel.create(overview.getId())); - var familiarShubNiggurath = this.makeFamiliarShubNiggurathEntry(entryMap, 'Y'); - familiarShubNiggurath.withParent(BookEntryParentModel.create(overview.getId())); - - //add true condition to all entries to enable them by default - overview.withCondition(BookTrueConditionModel.builder().build()); - familiarBat.withCondition(BookTrueConditionModel.builder().build()); - familiarBeaver.withCondition(BookTrueConditionModel.builder().build()); - familiarBeholder.withCondition(BookTrueConditionModel.builder().build()); - familiarBlacksmith.withCondition(BookTrueConditionModel.builder().build()); - familiarChimera.withCondition(BookTrueConditionModel.builder().build()); - familiarCthulhu.withCondition(BookTrueConditionModel.builder().build()); - familiarDeer.withCondition(BookTrueConditionModel.builder().build()); - familiarDevil.withCondition(BookTrueConditionModel.builder().build()); - familiarDragon.withCondition(BookTrueConditionModel.builder().build()); - familiarFairy.withCondition(BookTrueConditionModel.builder().build()); - familiarGreedy.withCondition(BookTrueConditionModel.builder().build()); - familiarGuardian.withCondition(BookTrueConditionModel.builder().build()); - familiarHeadlessRatman.withCondition(BookTrueConditionModel.builder().build()); - familiarMummy.withCondition(BookTrueConditionModel.builder().build()); - familiarOtherworldBird.withCondition(BookTrueConditionModel.builder().build()); - familiarParrot.withCondition(BookTrueConditionModel.builder().build()); - familiarShubNiggurath.withCondition(BookTrueConditionModel.builder().build()); - - return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) - .withIcon(this.modLoc("textures/gui/book/parrot.png")) - .withShowCategoryButton(false) - .withEntries( - overview, - returnToRituals, - familiarBat, - familiarBeaver, - familiarBeholder, - familiarBlacksmith, - familiarChimera, - familiarCthulhu, - familiarDeer, - familiarDevil, - familiarDragon, - familiarFairy, - familiarGreedy, - familiarGuardian, - familiarHeadlessRatman, - familiarMummy, - familiarOtherworldBird, - familiarParrot, - familiarShubNiggurath - ); - } - - private BookEntryModel makeFamiliarsRitualsOverviewEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("overview"); - - this.context().page("intro"); - var intro = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("ring"); - var ring = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("trading"); - var trading = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/parrot.png")) - .withLocation(entryMap.get(icon)) - .withEntryBackground(0, 1) - .withPages( - intro, - ring, - trading - ); - } - - private BookEntryModel makeFamiliarBatEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_bat"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:bat_familiar") - .withText(this.context().pageText()) - .withScale(0.7f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_bat")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/bat_familiar.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarBeaverEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_beaver"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:beaver_familiar") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_beaver")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_beaver.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarBeholderEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_beholder"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:beholder_familiar") - .withText(this.context().pageText()) - .withScale(0.7f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_beholder")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_beholder.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarBlacksmithEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_blacksmith"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:blacksmith_familiar") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_blacksmith")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("description2"); - var description2 = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_blacksmith.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description, - description2 - ); - } - - private BookEntryModel makeFamiliarChimeraEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_chimera"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:chimera_familiar") - .withText(this.context().pageText()) - .withScale(0.7f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_chimera")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("description2"); - var description2 = BookTextPageModel.builder() - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_chimera.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description, - description2 - ); - } - - private BookEntryModel makeFamiliarCthulhuEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_cthulhu"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:cthulhu_familiar") - .withText(this.context().pageText()) - .withScale(0.5f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_cthulhu")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_cthulhu.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarDeerEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_deer"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:deer_familiar") - .withText(this.context().pageText()) - .withScale(0.7f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_deer")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_deer.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarDevilEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_devil"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:devil_familiar") - .withText(this.context().pageText()) - .withScale(0.5f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_devil")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_devil.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarDragonEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_dragon"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:dragon_familiar") - .withText(this.context().pageText()) - .withScale(0.7f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_dragon")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_dragon.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarFairyEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_fairy"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:fairy_familiar") - .withText(this.context().pageText()) - .withScale(0.8f) - .withOffset(0.3f) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_fairy")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_fairy.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarGreedyEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_greedy"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:greedy_familiar") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_greedy")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_greedy.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarGuardianEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_guardian"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:guardian_familiar{for_book:true}") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_guardian")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("description2"); - var description2 = BookTextPageModel.builder() - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_guardian.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description, - description2 - ); - } - - private BookEntryModel makeFamiliarHeadlessRatmanEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_headless"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:headless_familiar") - .withScale(0.7f) - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_headless")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_headless_ratman.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarMummyEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_mummy"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:mummy_familiar") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_mummy")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_mummy.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - - private BookEntryModel makeFamiliarOtherworldBirdEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_otherworld_bird"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:otherworld_bird") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_otherworld_bird")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("description2"); - var description2 = BookTextPageModel.builder() - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/otherworld_bird.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description, - description2 - ); - } - - private BookEntryModel makeFamiliarParrotEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_parrot"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("minecraft:parrot") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookRitualRecipePageModel.builder() - .withRecipeId1(this.modLoc("ritual/familiar_parrot")) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("description2"); - var description2 = BookTextPageModel.builder() - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/parrot.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description, - description2 - ); - } - - private BookEntryModel makeFamiliarShubNiggurathEntry(CategoryEntryMap entryMap, char icon) { - this.context().entry("familiar_shub_niggurath"); - - this.context().page("entity"); - var entity = BookEntityPageModel.builder() - .withEntityId("occultism:shub_niggurath_familiar") - .withText(this.context().pageText()) - .build(); - - this.context().page("ritual"); - var ritual = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - this.context().page("description"); - var description = BookTextPageModel.builder() - .withTitle(this.context().pageTitle()) - .withText(this.context().pageText()) - .build(); - - return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) - .withIcon(this.modLoc("textures/gui/book/familiar_shub_niggurath.png")) - .withLocation(entryMap.get(icon)) - .withPages( - entity, - ritual, - description - ); - } - //endregion - private BookCategoryModel makeStorageCategory() { this.context().category("storage"); diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java b/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java new file mode 100644 index 000000000..684565b5f --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/FamiliarRitualsCategory.java @@ -0,0 +1,713 @@ +package com.klikli_dev.occultism.datagen.book; + +import com.klikli_dev.modonomicon.api.datagen.BookProvider; +import com.klikli_dev.modonomicon.api.datagen.CategoryEntryMap; +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.book.BookCategoryModel; +import com.klikli_dev.modonomicon.api.datagen.book.BookEntryModel; +import com.klikli_dev.modonomicon.api.datagen.book.BookEntryParentModel; +import com.klikli_dev.modonomicon.api.datagen.book.condition.BookTrueConditionModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookEntityPageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; +import com.klikli_dev.occultism.datagen.book.familiarrituals.DemonicPartnerEntry; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; + +public class FamiliarRitualsCategory extends CategoryProvider { + + public static final String CATEGORY_ID = "familiar_rituals"; + public FamiliarRitualsCategory(BookProvider parent) { + super(parent, CATEGORY_ID); + } + + @Override + public String[] generateEntryMap() { + return new String[]{ + "________R_T_V_X____________", + "___________________________", + "_______Q_S_U_W_Z___________", + "___________________________", + "___r_o_____________________", + "___________________________", + "_______I_K_M_O_Y___________", + "___________________________", + "________J_L_N_P____________" + }; + } + + @Override + protected void generateEntries() { + var overview = this.add(this.makeFamiliarsRitualsOverviewEntry(entryMap, 'o')); + var returnToRituals = this.add(this.makeReturnToRitualsEntry(entryMap, 'r')); + returnToRituals.withParent(BookEntryParentModel.create(overview.getId())); + returnToRituals.withCondition(BookTrueConditionModel.builder().build()); + + var familiarBat = this.add(this.makeFamiliarBatEntry(entryMap, 'I')); + familiarBat.withParent(BookEntryParentModel.create(overview.getId())); + var familiarBeaver = this.add(this.makeFamiliarBeaverEntry(entryMap, 'J')); + familiarBeaver.withParent(BookEntryParentModel.create(overview.getId())); + var familiarBeholder = this.add(this.makeFamiliarBeholderEntry(entryMap, 'K')); + familiarBeholder.withParent(BookEntryParentModel.create(overview.getId())); + var familiarBlacksmith = this.add(this.makeFamiliarBlacksmithEntry(entryMap, 'L')); + familiarBlacksmith.withParent(BookEntryParentModel.create(overview.getId())); + var familiarChimera = this.add(this.makeFamiliarChimeraEntry(entryMap, 'M')); + familiarChimera.withParent(BookEntryParentModel.create(overview.getId())); + var familiarCthulhu = this.add(this.makeFamiliarCthulhuEntry(entryMap, 'N')); + familiarCthulhu.withParent(BookEntryParentModel.create(overview.getId())); + var familiarDeer = this.add(this.makeFamiliarDeerEntry(entryMap, 'O')); + familiarDeer.withParent(BookEntryParentModel.create(overview.getId())); + var familiarDevil = this.add(this.makeFamiliarDevilEntry(entryMap, 'P')); + familiarDevil.withParent(BookEntryParentModel.create(overview.getId())); + var familiarDragon = this.add(this.makeFamiliarDragonEntry(entryMap, 'Q')); + familiarDragon.withParent(BookEntryParentModel.create(overview.getId())); + var familiarFairy = this.add(this.makeFamiliarFairyEntry(entryMap, 'R')); + familiarFairy.withParent(BookEntryParentModel.create(overview.getId())); + var familiarGreedy = this.add(this.makeFamiliarGreedyEntry(entryMap, 'S')); + familiarGreedy.withParent(BookEntryParentModel.create(overview.getId())); + var familiarGuardian = this.add(this.makeFamiliarGuardianEntry(entryMap, 'T')); + familiarGuardian.withParent(BookEntryParentModel.create(overview.getId())); + var familiarHeadlessRatman = this.add(this.makeFamiliarHeadlessRatmanEntry(entryMap, 'U')); + familiarHeadlessRatman.withParent(BookEntryParentModel.create(overview.getId())); + var familiarMummy = this.add(this.makeFamiliarMummyEntry(entryMap, 'V')); + familiarMummy.withParent(BookEntryParentModel.create(overview.getId())); + var familiarOtherworldBird = this.add(this.makeFamiliarOtherworldBirdEntry(entryMap, 'W')); + familiarOtherworldBird.withParent(BookEntryParentModel.create(overview.getId())); + var familiarParrot = this.add(this.makeFamiliarParrotEntry(entryMap, 'X')); + familiarParrot.withParent(BookEntryParentModel.create(overview.getId())); + var familiarShubNiggurath = this.add(this.makeFamiliarShubNiggurathEntry(entryMap, 'Y')); + familiarShubNiggurath.withParent(BookEntryParentModel.create(overview.getId())); + + //add true condition to all entries to enable them by default + overview.withCondition(BookTrueConditionModel.builder().build()); + familiarBat.withCondition(BookTrueConditionModel.builder().build()); + familiarBeaver.withCondition(BookTrueConditionModel.builder().build()); + familiarBeholder.withCondition(BookTrueConditionModel.builder().build()); + familiarBlacksmith.withCondition(BookTrueConditionModel.builder().build()); + familiarChimera.withCondition(BookTrueConditionModel.builder().build()); + familiarCthulhu.withCondition(BookTrueConditionModel.builder().build()); + familiarDeer.withCondition(BookTrueConditionModel.builder().build()); + familiarDevil.withCondition(BookTrueConditionModel.builder().build()); + familiarDragon.withCondition(BookTrueConditionModel.builder().build()); + familiarFairy.withCondition(BookTrueConditionModel.builder().build()); + familiarGreedy.withCondition(BookTrueConditionModel.builder().build()); + familiarGuardian.withCondition(BookTrueConditionModel.builder().build()); + familiarHeadlessRatman.withCondition(BookTrueConditionModel.builder().build()); + familiarMummy.withCondition(BookTrueConditionModel.builder().build()); + familiarOtherworldBird.withCondition(BookTrueConditionModel.builder().build()); + familiarParrot.withCondition(BookTrueConditionModel.builder().build()); + familiarShubNiggurath.withCondition(BookTrueConditionModel.builder().build()); + + var demonicPartner = new DemonicPartnerEntry(this).generate('Z'); + demonicPartner.withParent(BookEntryParentModel.create(overview.getId())); + demonicPartner.withCondition(BookTrueConditionModel.builder().build()); + } + + @Override + protected BookCategoryModel generateCategory() { + this.add(this.context().categoryName(), "Familiar Rituals"); + + return BookCategoryModel.create(this.modLoc(this.context().categoryId()), this.context().categoryName()) + .withIcon(this.modLoc("textures/gui/book/parrot.png")) + .withShowCategoryButton(false); + } + + private BookEntryModel makeFamiliarsRitualsOverviewEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("overview"); + + this.context().page("intro"); + var intro = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("ring"); + var ring = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("trading"); + var trading = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/parrot.png")) + .withLocation(entryMap.get(icon)) + .withEntryBackground(0, 1) + .withPages( + intro, + ring, + trading + ); + } + + private BookEntryModel makeFamiliarBatEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_bat"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:bat_familiar") + .withText(this.context().pageText()) + .withScale(0.7f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_bat")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/bat_familiar.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarBeaverEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_beaver"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:beaver_familiar") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_beaver")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_beaver.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarBeholderEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_beholder"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:beholder_familiar") + .withText(this.context().pageText()) + .withScale(0.7f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_beholder")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_beholder.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarBlacksmithEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_blacksmith"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:blacksmith_familiar") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_blacksmith")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("description2"); + var description2 = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_blacksmith.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description, + description2 + ); + } + + private BookEntryModel makeFamiliarChimeraEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_chimera"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:chimera_familiar") + .withText(this.context().pageText()) + .withScale(0.7f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_chimera")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("description2"); + var description2 = BookTextPageModel.builder() + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_chimera.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description, + description2 + ); + } + + private BookEntryModel makeFamiliarCthulhuEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_cthulhu"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:cthulhu_familiar") + .withText(this.context().pageText()) + .withScale(0.5f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_cthulhu")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_cthulhu.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarDeerEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_deer"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:deer_familiar") + .withText(this.context().pageText()) + .withScale(0.7f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_deer")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_deer.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarDevilEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_devil"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:devil_familiar") + .withText(this.context().pageText()) + .withScale(0.5f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_devil")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_devil.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarDragonEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_dragon"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:dragon_familiar") + .withText(this.context().pageText()) + .withScale(0.7f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_dragon")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_dragon.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarFairyEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_fairy"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:fairy_familiar") + .withText(this.context().pageText()) + .withScale(0.8f) + .withOffset(0.3f) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_fairy")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_fairy.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarGreedyEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_greedy"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:greedy_familiar") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_greedy")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_greedy.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarGuardianEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_guardian"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:guardian_familiar{for_book:true}") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_guardian")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("description2"); + var description2 = BookTextPageModel.builder() + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_guardian.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description, + description2 + ); + } + + private BookEntryModel makeFamiliarHeadlessRatmanEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_headless"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:headless_familiar") + .withScale(0.7f) + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_headless")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_headless_ratman.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarMummyEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_mummy"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:mummy_familiar") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_mummy")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_mummy.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeFamiliarOtherworldBirdEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_otherworld_bird"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:otherworld_bird") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_otherworld_bird")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("description2"); + var description2 = BookTextPageModel.builder() + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/otherworld_bird.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description, + description2 + ); + } + + private BookEntryModel makeFamiliarParrotEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_parrot"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("minecraft:parrot") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/familiar_parrot")) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("description2"); + var description2 = BookTextPageModel.builder() + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/parrot.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description, + description2 + ); + } + + private BookEntryModel makeFamiliarShubNiggurathEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("familiar_shub_niggurath"); + + this.context().page("entity"); + var entity = BookEntityPageModel.builder() + .withEntityId("occultism:shub_niggurath_familiar") + .withText(this.context().pageText()) + .build(); + + this.context().page("ritual"); + var ritual = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + this.context().page("description"); + var description = BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build(); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/familiar_shub_niggurath.png")) + .withLocation(entryMap.get(icon)) + .withPages( + entity, + ritual, + description + ); + } + + private BookEntryModel makeReturnToRitualsEntry(CategoryEntryMap entryMap, char icon) { + this.context().entry("return_to_rituals"); + + return BookEntryModel.create(this.modLoc(this.context().categoryId() + "/" + this.context().entryId()), this.context().entryName()) + .withIcon(this.modLoc("textures/gui/book/robe.png")) + .withCategoryToOpen(this.modLoc("rituals")) + .withEntryBackground(1, 2) + .withLocation(entryMap.get(icon)); + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java b/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java new file mode 100644 index 000000000..40e56fc96 --- /dev/null +++ b/src/main/java/com/klikli_dev/occultism/datagen/book/familiarrituals/DemonicPartnerEntry.java @@ -0,0 +1,121 @@ +package com.klikli_dev.occultism.datagen.book.familiarrituals; + +import com.klikli_dev.modonomicon.api.datagen.CategoryProvider; +import com.klikli_dev.modonomicon.api.datagen.EntryBackground; +import com.klikli_dev.modonomicon.api.datagen.EntryProvider; +import com.klikli_dev.modonomicon.api.datagen.book.BookIconModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookEntityPageModel; +import com.klikli_dev.modonomicon.api.datagen.book.page.BookTextPageModel; +import com.klikli_dev.occultism.integration.modonomicon.pages.BookRitualRecipePageModel; +import com.mojang.datafixers.util.Pair; + +public class DemonicPartnerEntry extends EntryProvider { + + public static final String ENTRY_ID = "demonic_partner"; + + + public DemonicPartnerEntry(CategoryProvider parent) { + super(parent); + } + + @Override + protected void generatePages() { + + + this.page("description", () -> BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build()); + this.pageTitle("Demonic Partner"); + this.pageText(""" + Magicians practicing the occult are a diverse crowd, coming from all creeds and all corners of the world. However one thing unites them all - they are as lonely as any human without a partner. + \\ + \\ + Of course being a magician, there is a way to solve this problem once and for all. + """); + + this.page("description2", () -> BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build()); + this.pageTitle("Demonic Partner"); + this.pageText(""" + As beings of immense powers Demons can have it all ... except love.\\ + No demon will freely admit this, but at times they are impressed by the power and strength that some mortal occultists acquire. And in such cases, the impossible can happen - the demon can fall in love with a mortal. + """); + + this.page("description3", () -> BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build()); + this.pageTitle("Demonic Partner"); + this.pageText(""" + Demons, of course, deal in contracts, and what better contract than a marriage contract? + """); + + this.page("about", () -> BookTextPageModel.builder() + .withTitle(this.context().pageTitle()) + .withText(this.context().pageText()) + .build()); + this.pageTitle("Demonic Partner"); + this.pageText(""" + The Demonic Partner - a Husband or Wife - can fight for you and help with household chores. + \\ + \\ + Right-Click with any cookable food and they will use their magic to cook it. + \\ + \\ + Right-Click with a potion to get the effect for a significantly longer time. + """); + + this.page("wife", () -> BookEntityPageModel.builder() + .withEntityId("occultism:demonic_wife") + .withEntityName(this.context().pageTitle()) + .build() + ); + this.pageTitle("Demonic Wife"); + + + this.page("ritual1", () -> BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/summon_demonic_wife")) + .build() + ); + + this.page("husband", () -> BookEntityPageModel.builder() + .withEntityId("occultism:demonic_husband") + .withEntityName(this.context().pageTitle()) + .build() + ); + this.pageTitle("Demonic Husband"); + + this.page("ritual2", () -> BookRitualRecipePageModel.builder() + .withRecipeId1(this.modLoc("ritual/summon_demonic_husband")) + .build() + ); + } + + @Override + protected String entryName() { + return "Demonic Partner"; + } + + @Override + protected String entryDescription() { + return "A demonic Household?"; + } + + @Override + protected Pair entryBackground() { + return EntryBackground.DEFAULT; + } + + @Override + protected BookIconModel entryIcon() { + return BookIconModel.create(this.modLoc("textures/gui/book/demonic_partner.png")); + } + + @Override + protected String entryId() { + return ENTRY_ID; + } +} diff --git a/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java b/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java index fa2e5e051..c5a2af47a 100644 --- a/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java +++ b/src/main/java/com/klikli_dev/occultism/datagen/lang/ENUSProvider.java @@ -37,6 +37,7 @@ import net.minecraft.data.PackOutput; import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.ItemLike; public class ENUSProvider extends AbstractModonomiconLanguageProvider { @@ -246,6 +247,8 @@ private void addItems() { this.addItem(OccultismItems.SPAWN_EGG_MUMMY_FAMILIAR, "Mummy Familiar Spawn Egg"); this.addItem(OccultismItems.SPAWN_EGG_BEAVER_FAMILIAR, "Beaver Familiar Spawn Egg"); this.addItem(OccultismItems.SPAWN_EGG_PARROT_FAMILIAR, "Parrot Familiar Spawn Egg"); + this.addItem(OccultismItems.SPAWN_EGG_DEMONIC_WIFE, "Demonic Wife Spawn Egg"); + this.addItem(OccultismItems.SPAWN_EGG_DEMONIC_HUSBAND, "Demonic Husband Spawn Egg"); } private void addBlocks() { @@ -331,6 +334,8 @@ private void addEntities() { this.addEntityType(OccultismEntities.BEAVER_FAMILIAR, "Beaver Familiar"); this.addEntityType(OccultismEntities.SHUB_NIGGURATH_SPAWN, "Shub Niggurath Spawn"); this.addEntityType(OccultismEntities.THROWN_SWORD, "Thrown Sword"); + this.addEntityType(OccultismEntities.DEMONIC_WIFE, "Demonic Wife"); + this.addEntityType(OccultismEntities.DEMONIC_HUSBAND, "Demonic Husband"); } private void addMiscTranslations() { @@ -2059,7 +2064,6 @@ private void addCraftingRitualsCategory(BookContextHelper helper) { private void addFamiliarRitualsCategory(BookContextHelper helper) { helper.category("familiar_rituals"); - this.add(helper.categoryName(), "Familiar Rituals"); helper.entry("return_to_rituals"); this.add(helper.entryName(), "Return to Rituals Category"); @@ -2959,6 +2963,17 @@ private void addRitualDummies() { this.add("item.occultism.ritual_dummy.summon_wild_otherworld_bird.tooltip", "Summons a Drikwing Familiar that can be tamed by anyone, not just the summoner."); this.add("item.occultism.ritual_dummy.summon_wild_parrot", "Ritual: Summon Wild Parrot"); this.add("item.occultism.ritual_dummy.summon_wild_parrot.tooltip", "Summons a Parrot that can be tamed by anyone, not just the summoner."); + + + this.add(OccultismItems.RITUAL_DUMMY_SUMMON_DEMONIC_WIFE.get(), "Ritual: Summon Demonic Wife"); + this.addTooltip(OccultismItems.RITUAL_DUMMY_SUMMON_DEMONIC_WIFE.get(), "Summons a Demonic Wife to support you: She will fight for you, help with cooking, and extend potion durations."); + + this.add(OccultismItems.RITUAL_DUMMY_SUMMON_DEMONIC_HUSBAND.get(), "Ritual: Summon Demonic Husband"); + this.addTooltip(OccultismItems.RITUAL_DUMMY_SUMMON_DEMONIC_HUSBAND.get(), "Summons a Demonic Husband to support you: He will fight for you, help with cooking, and extend potion durations."); + } + + public void addTooltip(ItemLike key, String value) { + this.add(key.asItem().getDescriptionId() + ".tooltip", value); } private void addDialogs() { diff --git a/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java b/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java index 8d36a8b5d..ffa2789b6 100644 --- a/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java +++ b/src/main/java/com/klikli_dev/occultism/handlers/ClientSetupEventHandler.java @@ -39,6 +39,8 @@ import com.klikli_dev.occultism.client.render.entity.*; import com.klikli_dev.occultism.common.capability.FamiliarSettingsData; import com.klikli_dev.occultism.common.container.spirit.SpiritContainer; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.husband.DemonicHusbandRenderer; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.wife.DemonicWifeRenderer; import com.klikli_dev.occultism.integration.modonomicon.PageRenderers; import com.klikli_dev.occultism.registry.*; import com.mojang.blaze3d.platform.InputConstants; @@ -141,6 +143,12 @@ public static void onRegisterEntityRenderers(EntityRenderersEvent.RegisterRender event.registerEntityRenderer(OccultismEntities.WILD_HUNT_SKELETON.get(), SkeletonRenderer::new); event.registerEntityRenderer(OccultismEntities.WILD_HUNT_WITHER_SKELETON.get(), WitherSkeletonRenderer::new); event.registerEntityRenderer(OccultismEntities.OTHERWORLD_BIRD.get(), OtherworldBirdRenderer::new); + + + event.registerEntityRenderer(OccultismEntities.DEMONIC_WIFE.get(), DemonicWifeRenderer::new); + event.registerEntityRenderer(OccultismEntities.DEMONIC_HUSBAND.get(), DemonicHusbandRenderer::new); + + } @SubscribeEvent diff --git a/src/main/java/com/klikli_dev/occultism/registry/OccultismEntities.java b/src/main/java/com/klikli_dev/occultism/registry/OccultismEntities.java index 513003c68..8f0ae29cb 100644 --- a/src/main/java/com/klikli_dev/occultism/registry/OccultismEntities.java +++ b/src/main/java/com/klikli_dev/occultism/registry/OccultismEntities.java @@ -22,10 +22,13 @@ package com.klikli_dev.occultism.registry; +import com.klikli_dev.modonomicon.registry.RegistryObject; import com.klikli_dev.occultism.Occultism; import com.klikli_dev.occultism.common.entity.familiar.*; import com.klikli_dev.occultism.common.entity.possessed.*; import com.klikli_dev.occultism.common.entity.spirit.*; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.husband.DemonicHusband; +import com.klikli_dev.occultism.common.entity.spirit.demonicpartner.wife.DemonicWife; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.EntityType; @@ -298,4 +301,6 @@ public class OccultismEntities { public static final Supplier> SHUB_NIGGURATH_SPAWN = ENTITIES.register("shub_niggurath_spawn", SHUB_NIGGURATH_SPAWN_TYPE::get); + public static final Supplier> DEMONIC_WIFE = ENTITIES.register(DemonicWife.ID.getPath(), DemonicWife.ENTITY_TYPE::get); + public static final Supplier> DEMONIC_HUSBAND = ENTITIES.register(DemonicHusband.ID.getPath(), DemonicHusband.ENTITY_TYPE::get); } diff --git a/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java b/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java index 2ec752996..6b5cc176c 100644 --- a/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java +++ b/src/main/java/com/klikli_dev/occultism/registry/OccultismItems.java @@ -22,6 +22,7 @@ package com.klikli_dev.occultism.registry; +import com.klikli_dev.modonomicon.registry.RegistryObject; import com.klikli_dev.occultism.Occultism; import com.klikli_dev.occultism.TranslationKeys; import com.klikli_dev.occultism.api.common.misc.OccultismItemTier; @@ -368,6 +369,13 @@ public class OccultismItems { public static final DeferredItem SPAWN_EGG_PARROT_FAMILIAR = ITEMS.register("spawn_egg/familiar_parrot", () -> new DeferredSpawnEggItem(() -> EntityType.PARROT, 894731, 16711680, defaultProperties())); + public static final DeferredItem SPAWN_EGG_DEMONIC_WIFE = ITEMS.register("spawn_egg/demonic_wife", () -> new DeferredSpawnEggItem(OccultismEntities.DEMONIC_WIFE::get, 0xf2f0d7, 0xa01d1d, defaultProperties())); + public static final DeferredItem SPAWN_EGG_DEMONIC_HUSBAND = ITEMS.register("spawn_egg/demonic_husband", () -> new DeferredSpawnEggItem(OccultismEntities.DEMONIC_HUSBAND::get, 0xf2f0d7, 0xa01d1d, defaultProperties())); + + + public static final DeferredItem RITUAL_DUMMY_SUMMON_DEMONIC_WIFE = ITEMS.register("ritual_dummy/summon_demonic_wife", () -> new DummyTooltipItem(defaultProperties())); + public static final DeferredItem RITUAL_DUMMY_SUMMON_DEMONIC_HUSBAND = ITEMS.register("ritual_dummy/summon_demonic_husband", () -> new DummyTooltipItem(defaultProperties())); + //Ritual Dummy Items static { ITEMS.register("ritual_dummy/custom_ritual", () -> new DummyTooltipItem(defaultProperties())); diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index f6445f50d..4458f456a 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -9,4 +9,5 @@ public net.minecraft.world.inventory.TransientCraftingContainer items # items public net.minecraft.client.gui.GuiGraphics flushIfUnmanaged()V # flushIfUnmanaged public net.minecraft.world.entity.Entity setLevel(Lnet/minecraft/world/level/Level;)V # setLevel public net.minecraft.world.entity.LivingEntity getCurrentSwingDuration()I # getCurrentSwingDuration -public-f net.minecraft.world.level.block.TorchBlock flameParticle \ No newline at end of file +public-f net.minecraft.world.level.block.TorchBlock flameParticle +public net.minecraft.world.item.crafting.AbstractCookingRecipe ingredient \ No newline at end of file diff --git a/src/main/resources/assets/occultism/animations/entity/demonic_husband.animation.json b/src/main/resources/assets/occultism/animations/entity/demonic_husband.animation.json new file mode 100644 index 000000000..ee4c6d382 --- /dev/null +++ b/src/main/resources/assets/occultism/animations/entity/demonic_husband.animation.json @@ -0,0 +1,798 @@ +{ + "format_version": "1.8.0", + "animations": { + "idle": { + "loop": true, + "animation_length": 4, + "bones": { + "all": { + "position": { + "0.0": { + "vector": [0, 0, 0] + }, + "2.0": { + "vector": [0, 1, 0] + }, + "4.0": { + "vector": [0, 0, 0] + } + } + }, + "Larm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "2.0": { + "vector": [5, 0, 0] + }, + "4.0": { + "vector": [0, 0, 0] + } + } + }, + "Rarm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "2.0": { + "vector": [5, 0, 0] + }, + "4.0": { + "vector": [0, 0, 0] + } + } + }, + "torso": { + "scale": { + "0.0": { + "vector": [1, 1, 1] + }, + "2.0": { + "vector": [1.05, 1, 1] + }, + "4.0": { + "vector": [1, 1, 1] + } + } + }, + "Lleg": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "2.0": { + "vector": [-7.5, 0, 0] + }, + "4.0": { + "vector": [0, 0, 0] + } + } + }, + "Head": { + "position": { + "vector": [0, 0.7, 0] + } + }, + "RWing": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 60, 0] + }, + "0.25": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [0, 60, 0] + }, + "0.5": { + "vector": [0, 0, 0] + }, + "0.625": { + "vector": [0, 60, 0] + }, + "0.75": { + "vector": [0, 0, 0] + }, + "0.875": { + "vector": [0, 60, 0] + }, + "1.0": { + "vector": [0, 0, 0] + }, + "1.125": { + "vector": [0, 60, 0] + }, + "1.25": { + "vector": [0, 0, 0] + }, + "1.375": { + "vector": [0, 60, 0] + }, + "1.5": { + "vector": [0, 0, 0] + }, + "1.625": { + "vector": [0, 60, 0] + }, + "1.75": { + "vector": [0, 0, 0] + }, + "1.875": { + "vector": [0, 60, 0] + }, + "2.0": { + "vector": [0, 0, 0] + }, + "2.125": { + "vector": [0, 60, 0] + }, + "2.25": { + "vector": [0, 0, 0] + }, + "2.375": { + "vector": [0, 60, 0] + }, + "2.5": { + "vector": [0, 0, 0] + }, + "2.625": { + "vector": [0, 60, 0] + }, + "2.75": { + "vector": [0, 0, 0] + }, + "2.875": { + "vector": [0, 60, 0] + }, + "3.0": { + "vector": [0, 0, 0] + }, + "3.125": { + "vector": [0, 60, 0] + }, + "3.25": { + "vector": [0, 0, 0] + }, + "3.375": { + "vector": [0, 60, 0] + }, + "3.5": { + "vector": [0, 0, 0] + }, + "3.625": { + "vector": [0, 60, 0] + }, + "3.75": { + "vector": [0, 0, 0] + }, + "3.875": { + "vector": [0, 60, 0] + }, + "4.0": { + "vector": [0, 0, 0] + } + } + }, + "Lwing": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, -55, 0] + }, + "0.25": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [0, -55, 0] + }, + "0.5": { + "vector": [0, 0, 0] + }, + "0.625": { + "vector": [0, -55, 0] + }, + "0.75": { + "vector": [0, 0, 0] + }, + "0.875": { + "vector": [0, -55, 0] + }, + "1.0": { + "vector": [0, 0, 0] + }, + "1.125": { + "vector": [0, -55, 0] + }, + "1.25": { + "vector": [0, 0, 0] + }, + "1.375": { + "vector": [0, -55, 0] + }, + "1.5": { + "vector": [0, 0, 0] + }, + "1.625": { + "vector": [0, -55, 0] + }, + "1.75": { + "vector": [0, 0, 0] + }, + "1.875": { + "vector": [0, -55, 0] + }, + "2.0": { + "vector": [0, 0, 0] + }, + "2.125": { + "vector": [0, -55, 0] + }, + "2.25": { + "vector": [0, 0, 0] + }, + "2.375": { + "vector": [0, -55, 0] + }, + "2.5": { + "vector": [0, 0, 0] + }, + "2.625": { + "vector": [0, -55, 0] + }, + "2.75": { + "vector": [0, 0, 0] + }, + "2.875": { + "vector": [0, -55, 0] + }, + "3.0": { + "vector": [0, 0, 0] + }, + "3.125": { + "vector": [0, -55, 0] + }, + "3.25": { + "vector": [0, 0, 0] + }, + "3.375": { + "vector": [0, -55, 0] + }, + "3.5": { + "vector": [0, 0, 0] + }, + "3.625": { + "vector": [0, -55, 0] + }, + "3.75": { + "vector": [0, 0, 0] + }, + "3.875": { + "vector": [0, -55, 0] + }, + "4.0": { + "vector": [0, 0, 0] + } + } + } + } + }, + "lies": { + "loop": true, + "animation_length": 4, + "bones": { + "all": { + "rotation": { + "vector": [0, 0, 0] + }, + "position": { + "vector": [0, -14, 0] + } + }, + "Larm": { + "rotation": { + "vector": [15, 0, 0] + } + }, + "Rarm": { + "rotation": { + "vector": [15, 0, 0] + } + }, + "torso": { + "rotation": { + "vector": [-25, 0, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "Lleg": { + "rotation": { + "vector": [0, 0, 0] + } + }, + "Head": { + "rotation": { + "vector": [27.5, 0, 0] + }, + "position": { + "vector": [0, 0.7, 0] + } + }, + "RWing": { + "rotation": { + "vector": [0, 0, 0] + }, + "scale": { + "vector": [0, 0, 0] + } + }, + "Lwing": { + "scale": { + "vector": [0, 0, 0] + } + }, + "Rleg": { + "rotation": { + "vector": [-5, 0, 0] + } + } + } + }, + "attack": { + "loop": "hold_on_last_frame", + "animation_length": 0.5, + "bones": { + "all": { + "rotation": { + "vector": [0, 0, 0] + }, + "position": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.25": { + "vector": [0, 0, 2] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "arms": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [-72.5, 0, 0] + }, + "0.375": { + "vector": [-72.5, 0, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "position": { + "vector": [0, 0, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "Larm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 0, -15] + }, + "0.25": { + "vector": [0, 0, -15] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "position": { + "vector": [0, 0, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "Rarm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 0, 12.5] + }, + "0.25": { + "vector": [0, 0, 12.5] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "position": { + "vector": [0, 0, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "torso": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.25": { + "vector": [10, 0, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "position": { + "vector": [0, 0, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "legs": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [-32.5, 0, 0] + }, + "0.25": { + "vector": [-32.5, 0, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "position": { + "vector": [0, 0, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "Lleg": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 0, 0] + }, + "0.25": { + "vector": [-12.5, 0, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + } + }, + "Head": { + "rotation": { + "vector": [0, 0, 0] + }, + "position": { + "vector": [0, 0.7, 0] + }, + "scale": { + "vector": [1, 1, 1] + } + }, + "RWing": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 60, 0] + }, + "0.25": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [0, 60, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + } + }, + "Lwing": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, -55, 0] + }, + "0.25": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [0, -55, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + } + } + } + }, + "sitting": { + "loop": true, + "animation_length": 4, + "bones": { + "all": { + "rotation": { + "vector": [-60, 0, 0] + }, + "position": { + "0.0": { + "vector": [0, -7, 0] + }, + "2.0": { + "vector": [0, -8, 0] + }, + "4.0": { + "vector": [0, -7, 0] + } + } + }, + "Larm": { + "rotation": { + "vector": [-158.02113, -4.93842, 12.04044] + } + }, + "Rarm": { + "rotation": { + "vector": [60, 0, 27.5] + } + }, + "Lleg": { + "rotation": { + "vector": [-34.72047, 7.8274, -32.30727] + } + }, + "Rleg": { + "rotation": { + "vector": [0, 0, 15] + } + }, + "Head": { + "rotation": { + "vector": [52.5, 0, 0] + }, + "position": { + "vector": [0, 0.8, -1.2] + } + } + } + }, + "walk": { + "loop": true, + "animation_length": 2, + "bones": { + "all": { + "rotation": { + "vector": [10, 0, 0] + }, + "position": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [0, -1, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "Larm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [7.5, 0, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "Rarm": { + "rotation": { + "0.0": { + "vector": [27.5, 0, 0] + }, + "1.0": { + "vector": [22.5, 0, 0] + }, + "2.0": { + "vector": [27.5, 0, 0] + } + } + }, + "legs": { + "rotation": { + "vector": [12.5, 0, 0] + } + }, + "Lleg": { + "rotation": { + "0.0": { + "vector": [12.5, 0, 0] + }, + "1.0": { + "vector": [7.5, 0, 0] + }, + "2.0": { + "vector": [12.5, 0, 0] + } + }, + "position": { + "vector": [0, 0.5, 0] + } + }, + "Rleg": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [7.5, 0, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "Head": { + "rotation": { + "vector": [-10, 0, 0] + }, + "position": { + "vector": [0, 0.3, -0.5] + } + }, + "RWing": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 60, 0] + }, + "0.25": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [0, 60, 0] + }, + "0.5": { + "vector": [0, 0, 0] + }, + "0.625": { + "vector": [0, 60, 0] + }, + "0.75": { + "vector": [0, 0, 0] + }, + "0.875": { + "vector": [0, 60, 0] + }, + "1.0": { + "vector": [0, 0, 0] + }, + "1.125": { + "vector": [0, 60, 0] + }, + "1.25": { + "vector": [0, 0, 0] + }, + "1.375": { + "vector": [0, 60, 0] + }, + "1.5": { + "vector": [0, 0, 0] + }, + "1.625": { + "vector": [0, 60, 0] + }, + "1.75": { + "vector": [0, 0, 0] + }, + "1.875": { + "vector": [0, 60, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "Lwing": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, -55, 0] + }, + "0.25": { + "vector": [0, 0, 0] + }, + "0.375": { + "vector": [0, -55, 0] + }, + "0.5": { + "vector": [0, 0, 0] + }, + "0.625": { + "vector": [0, -55, 0] + }, + "0.75": { + "vector": [0, 0, 0] + }, + "0.875": { + "vector": [0, -55, 0] + }, + "1.0": { + "vector": [0, 0, 0] + }, + "1.125": { + "vector": [0, -55, 0] + }, + "1.25": { + "vector": [0, 0, 0] + }, + "1.375": { + "vector": [0, -55, 0] + }, + "1.5": { + "vector": [0, 0, 0] + }, + "1.625": { + "vector": [0, -55, 0] + }, + "1.75": { + "vector": [0, 0, 0] + }, + "1.875": { + "vector": [0, -55, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + } + } + } + }, + "geckolib_format_version": 2 +} \ No newline at end of file diff --git a/src/main/resources/assets/occultism/animations/entity/demonic_wife.animation.json b/src/main/resources/assets/occultism/animations/entity/demonic_wife.animation.json new file mode 100644 index 000000000..664198d3f --- /dev/null +++ b/src/main/resources/assets/occultism/animations/entity/demonic_wife.animation.json @@ -0,0 +1,301 @@ +{ + "format_version": "1.8.0", + "animations": { + "idle": { + "loop": true, + "animation_length": 2, + "bones": { + "_": { + "position": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [0, 1.1, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "right_arm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [5.99184, -0.31344, 2.9836] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "left_arm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [4, 0, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + } + } + }, + "attack": { + "loop": "hold_on_last_frame", + "animation_length": 0.5, + "bones": { + "_": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.0833": { + "vector": [0, 0, 0] + }, + "0.25": { + "vector": [-17.5, 0, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + }, + "position": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.125": { + "vector": [0, 0, 0] + }, + "0.25": { + "vector": [0, 0, 2.5] + }, + "0.5": { + "vector": [0, 0, 0] + } + } + }, + "right_arm": { + "rotation": { + "0.0": { + "vector": [0, 0, 10] + }, + "0.125": { + "vector": [0, 0, 40] + }, + "0.25": { + "vector": [-54.90112, -23.27104, 13.32769] + }, + "0.375": { + "vector": [-54.90112, -23.27104, 13.32769] + }, + "0.5": { + "vector": [0, 0, 10] + } + } + }, + "left_arm": { + "rotation": { + "0.0": { + "vector": [0, 0, -7.5] + }, + "0.125": { + "vector": [0, 0, -40] + }, + "0.25": { + "vector": [-62.73421, 15.69986, -23.67505] + }, + "0.375": { + "vector": [-62.73421, 15.69986, -23.67505] + }, + "0.5": { + "vector": [0, 0, -7.5] + } + } + }, + "bone7": { + "rotation": { + "vector": [0, 0, 0] + } + }, + "head": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "0.25": { + "vector": [26, 0, 0] + }, + "0.5": { + "vector": [0, 0, 0] + } + } + } + } + }, + "walk": { + "loop": true, + "animation_length": 2, + "bones": { + "_": { + "rotation": { + "vector": [19, 0, 0] + }, + "position": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [0, 1.1, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "right_arm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [5.99184, -0.31344, 2.9836] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "left_arm": { + "rotation": { + "0.0": { + "vector": [0, 0, 0] + }, + "1.0": { + "vector": [4, 0, 0] + }, + "2.0": { + "vector": [0, 0, 0] + } + } + }, + "head": { + "rotation": { + "vector": [-16, 0, 0] + } + } + } + }, + "sit": { + "loop": true, + "bones": { + "_": { + "position": { + "vector": [0, -8, 0] + } + }, + "right_arm": { + "rotation": { + "vector": [-11.72268, -5.65925, -25.41856] + } + }, + "bone8": { + "rotation": { + "vector": [0, 0, -4] + } + }, + "left_arm": { + "rotation": { + "vector": [-7.48052, 5.01848, 33.67172] + } + }, + "left_leg": { + "rotation": { + "vector": [18.04111, 3.80393, 1.23789] + }, + "position": { + "vector": [0, -0.6, 0] + } + }, + "bone": { + "rotation": { + "vector": [-41.68163, 9.40134, -8.27535] + }, + "position": { + "vector": [0, -1.5, 0] + } + }, + "bone2": { + "rotation": { + "vector": [0, 8, 0] + } + }, + "bone3": { + "position": { + "vector": [0, -0.2, 0] + } + } + } + }, + "lies": { + "loop": true, + "bones": { + "_": { + "rotation": { + "vector": [0, 0, 0] + }, + "position": { + "vector": [0, -7, 0] + } + }, + "right_arm": { + "rotation": { + "vector": [-11.72268, -5.65925, -25.41856] + } + }, + "bone8": { + "rotation": { + "vector": [0, 0, -4] + } + }, + "left_arm": { + "rotation": { + "vector": [-7.48052, 5.01848, 33.67172] + } + }, + "left_leg": { + "rotation": { + "vector": [18.04111, 3.80393, 1.23789] + }, + "position": { + "vector": [0, -0.6, 0] + } + }, + "bone": { + "rotation": { + "vector": [-41.68163, 9.40134, -8.27535] + }, + "position": { + "vector": [0, -1.5, 0] + } + }, + "bone2": { + "rotation": { + "vector": [0, 8, 0] + } + }, + "bone3": { + "position": { + "vector": [0, -0.2, 0] + } + } + } + } + }, + "geckolib_format_version": 2 +} \ No newline at end of file diff --git a/src/main/resources/assets/occultism/geo/entity/demonic_husband.geo.json b/src/main/resources/assets/occultism/geo/entity/demonic_husband.geo.json new file mode 100644 index 000000000..64f327fa1 --- /dev/null +++ b/src/main/resources/assets/occultism/geo/entity/demonic_husband.geo.json @@ -0,0 +1,182 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.demonic_husband", + "texture_width": 64, + "texture_height": 64, + "visible_bounds_width": 3, + "visible_bounds_height": 3.5, + "visible_bounds_offset": [0, 1.25, 0] + }, + "bones": [ + { + "name": "all", + "pivot": [0, 21, 0] + }, + { + "name": "arms", + "parent": "all", + "pivot": [0, 26.4, -1.1] + }, + { + "name": "Larm", + "parent": "arms", + "pivot": [-3, 26.3, -1.2], + "rotation": [0, 0, 12.5], + "cubes": [ + {"origin": [-4.35172, 20.09807, -2], "size": [1.5, 7, 2], "uv": [6, 18]} + ] + }, + { + "name": "Rarm", + "parent": "arms", + "pivot": [3, 26, -1.1], + "rotation": [0, 0, -12.5], + "cubes": [ + {"origin": [2.91665, 20.09096, -2], "size": [1.5, 7, 2], "uv": [0, 17]} + ] + }, + { + "name": "torso", + "parent": "all", + "pivot": [0, 22, 1], + "rotation": [27.5, 0, 0], + "cubes": [ + {"origin": [-3, 24.12278, -1.50176], "size": [6, 4, 4], "uv": [0, 0]}, + {"origin": [-2, 21.12278, -1.20176], "size": [4, 6, 3.4], "uv": [0, 8]} + ] + }, + { + "name": "Head", + "parent": "torso", + "pivot": [0, 27.42278, 0.89824], + "rotation": [-27.5, 0, 0], + "cubes": [ + {"origin": [-1.7, 30.15984, -0.52136], "size": [1, 2.5, 1], "pivot": [-1, 30.15984, 0.47864], "rotation": [32.5, 15, 0], "uv": [16, 0]}, + { + "origin": [1, 28.08524, 2.46542], + "size": [0.4, 2.5, 0.7], + "pivot": [1, 30.15984, 0.47864], + "rotation": [122.5, -15, 0], + "uv": { + "north": {"uv": [1, 1], "uv_size": [0, 2]}, + "east": {"uv": [1, 1], "uv_size": [0, 2]}, + "south": {"uv": [1, 0.5], "uv_size": [0.5, 2.5]}, + "west": {"uv": [1, 1], "uv_size": [0, 2]}, + "up": {"uv": [1, 1], "uv_size": [0, 0]}, + "down": {"uv": [1, 1], "uv_size": [0, 0]} + } + }, + { + "origin": [-1.4, 28.08524, 2.46542], + "size": [0.4, 2.5, 0.7], + "pivot": [-1, 30.15984, 0.47864], + "rotation": [122.5, 15, 0], + "uv": { + "north": {"uv": [17, 1], "uv_size": [0, 2]}, + "east": {"uv": [17, 1], "uv_size": [0, 2]}, + "south": {"uv": [17, 1], "uv_size": [0.5, 2]}, + "west": {"uv": [17, 1], "uv_size": [0, 2]}, + "up": {"uv": [17, 1], "uv_size": [0, 0]}, + "down": {"uv": [17, 1], "uv_size": [0, 0]} + } + }, + {"origin": [-1.5, 27.15984, -0.52136], "size": [3, 3.5, 3], "uv": [11, 14]}, + {"origin": [0.7, 30.15984, -0.52136], "size": [1, 2.5, 1], "pivot": [1, 30.15984, 0.47864], "rotation": [32.5, -15, 0], "uv": [0, 0]} + ] + }, + { + "name": "RWing", + "parent": "torso", + "pivot": [-1.3, 25.3, 2.6], + "cubes": [ + {"origin": [-1.7, 25.9, 1.6], "size": [1, 6.7, 0.7], "pivot": [-1, 25, 1], "rotation": [-19, 0, -35], "uv": [35, 0], "mirror": true}, + {"origin": [-5.47697, 23.22936, 4.00105], "size": [1, 6.7, 0.7], "pivot": [-4.8, 30, 3.9], "rotation": [13.20171, 13.19075, 7.89696], "uv": [35, 0], "mirror": true}, + {"origin": [-5.04677, 23.29364, 4.08641], "size": [1, 6.7, 0.7], "pivot": [-4.9, 31, 3.9], "rotation": [-2.57336, 18.83131, 47.07319], "uv": [34, 0], "mirror": true}, + { + "origin": [-4.79677, 23.29364, 4.08641], + "size": [6, 6.7, 0.2], + "pivot": [-4.9, 31, 3.9], + "rotation": [-2.57034, -18.63356, 48.72608], + "uv": { + "north": {"uv": [40, 10], "uv_size": [-6, 6]}, + "east": {"uv": [40, 10], "uv_size": [0, 6]}, + "south": {"uv": [46, 10], "uv_size": [-6, 6]}, + "west": {"uv": [34, 10], "uv_size": [0, 6]}, + "up": {"uv": [40, 10], "uv_size": [-6, 0]}, + "down": {"uv": [46, 10], "uv_size": [-6, 0]} + } + }, + { + "origin": [-5.04677, 23.29364, 4.08641], + "size": [6, 6.7, 0.1], + "pivot": [-4.9, 31, 3.9], + "rotation": [14.60312, 32.53551, 15.14171], + "uv": { + "north": {"uv": [46, 3], "uv_size": [-6, 6]}, + "east": {"uv": [46, 3], "uv_size": [0, 6]}, + "south": {"uv": [52, 3], "uv_size": [-6, 6]}, + "west": {"uv": [40, 3], "uv_size": [0, 6]}, + "up": {"uv": [46, 3], "uv_size": [-6, 0]}, + "down": {"uv": [52, 3], "uv_size": [-6, 0]} + } + } + ] + }, + { + "name": "Lwing", + "parent": "torso", + "pivot": [1.2, 25.5, 2.5], + "cubes": [ + {"origin": [0.7, 25.9, 1.6], "size": [1, 6.7, 0.7], "pivot": [1, 25, 1], "rotation": [-19, 0, 35], "uv": [35, 0]}, + {"origin": [4.47697, 23.22936, 4.00105], "size": [1, 6.7, 0.7], "pivot": [4.8, 30, 3.9], "rotation": [13.20171, -13.19075, -7.89696], "uv": [35, 0]}, + { + "origin": [-1.20323, 23.04364, 4.08641], + "size": [6, 6.7, 0.2], + "pivot": [4.9, 31, 3.9], + "rotation": [-2.57034, 18.63356, -48.72608], + "uv": { + "north": {"uv": [34, 10], "uv_size": [6, 6]}, + "east": {"uv": [34, 10], "uv_size": [0, 6]}, + "south": {"uv": [40, 10], "uv_size": [6, 6]}, + "west": {"uv": [40, 10], "uv_size": [0, 6]}, + "up": {"uv": [34, 10], "uv_size": [6, 0]}, + "down": {"uv": [40, 10], "uv_size": [6, 0]} + } + }, + {"origin": [-0.95323, 23.29364, 4.08641], "size": [6, 6.7, 0.1], "pivot": [4.9, 31, 3.9], "rotation": [14.60312, -32.53551, -15.14171], "uv": [40, 3]}, + {"origin": [4.04677, 23.29364, 4.08641], "size": [1, 6.7, 0.7], "pivot": [4.9, 31, 3.9], "rotation": [-2.57336, -18.83131, -47.07319], "uv": [34, 0]} + ] + }, + { + "name": "legs", + "parent": "all", + "pivot": [0, 21, 0.9], + "rotation": [-25, 0, 0] + }, + { + "name": "Lleg", + "parent": "legs", + "pivot": [-2, 20.81964, 0.68432], + "rotation": [0, 0, 5], + "cubes": [ + {"origin": [-3.0259, 15.92845, -0.08908], "size": [2, 5, 2], "uv": [12, 20]}, + {"origin": [-3.2259, 12.3297, 1.22546], "size": [2.3, 3.8, 2.6], "pivot": [-0.0259, 14.96308, 0.57782], "rotation": [58, 0, 0], "uv": [20, 20]} + ] + }, + { + "name": "Rleg", + "parent": "legs", + "pivot": [2, 20.61964, 1.68432], + "rotation": [0, 0, -5], + "cubes": [ + {"origin": [0.92045, 16.79776, 0.08432], "size": [2, 5, 2], "uv": [20, 0]}, + {"origin": [0.72045, 13.19901, 1.39887], "size": [2.3, 3.8, 2.6], "pivot": [-0.07955, 15.83239, 0.75123], "rotation": [58, 0, 0], "uv": [20, 12]} + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/occultism/geo/entity/demonic_wife.geo.json b/src/main/resources/assets/occultism/geo/entity/demonic_wife.geo.json new file mode 100644 index 000000000..06e0c71f4 --- /dev/null +++ b/src/main/resources/assets/occultism/geo/entity/demonic_wife.geo.json @@ -0,0 +1,141 @@ +{ + "format_version": "1.12.0", + "minecraft:geometry": [ + { + "description": { + "identifier": "geometry.demonic_wife", + "texture_width": 64, + "texture_height": 64, + "visible_bounds_width": 2, + "visible_bounds_height": 3.5, + "visible_bounds_offset": [0, 1.25, 0] + }, + "bones": [ + { + "name": "_", + "pivot": [0, 18, 0] + }, + { + "name": "right_arm", + "parent": "_", + "pivot": [-4, 25.5, -1] + }, + { + "name": "bone7", + "parent": "right_arm", + "pivot": [-4, 22.5, -1], + "cubes": [ + {"origin": [-5.7, 22, -3], "size": [2.4, 5, 3], "pivot": [-4.5, 22, -1], "rotation": [0, 0, 10], "uv": [35, 32]} + ] + }, + { + "name": "bone8", + "parent": "right_arm", + "pivot": [-4, 22.5, -1], + "cubes": [ + {"origin": [-5.6, 17, -3], "size": [2.2, 5, 3], "pivot": [-4.5, 22, -1], "rotation": [0, 0, 10], "uv": [21, 31]} + ] + }, + { + "name": "left_arm", + "parent": "_", + "pivot": [4, 25.5, -1] + }, + { + "name": "bone5", + "parent": "left_arm", + "pivot": [4.5, 24.5, -1], + "cubes": [ + {"origin": [3.3, 22, -3], "size": [2.4, 5, 3], "pivot": [4.5, 22, -1], "rotation": [0, 0, -15], "uv": [17, 40]} + ] + }, + { + "name": "bone6", + "parent": "left_arm", + "pivot": [0, 4, 0], + "cubes": [ + {"origin": [3.4, 17, -3], "size": [2.2, 5, 3], "pivot": [4.5, 22, -1], "rotation": [0, 0, -15], "uv": [1, 41]} + ] + }, + { + "name": "left_leg", + "parent": "_", + "pivot": [1.5, 17.25, -1] + }, + { + "name": "bone", + "parent": "left_leg", + "pivot": [1.5, 13.5, -3], + "cubes": [ + {"origin": [0, 10.75, -3], "size": [3, 4, 4], "pivot": [1.5, 10, -1], "rotation": [22.5, -12.5, 0], "uv": [37, 23]} + ] + }, + { + "name": "bone2", + "parent": "left_leg", + "pivot": [1.5, 14.5, -1], + "cubes": [ + {"origin": [0.3, 12.4, -4], "size": [2.4, 5, 4], "pivot": [1.5, 14.5, -1], "rotation": [-22.5, -12.5, 0], "uv": [36, 2]} + ] + }, + { + "name": "right_leg", + "parent": "_", + "pivot": [-1.5, 16.25, -1] + }, + { + "name": "bone3", + "parent": "right_leg", + "pivot": [0, 4, 0], + "cubes": [ + {"origin": [-3, 8, -3.5], "size": [3, 4, 4], "pivot": [-1.5, 12.25, -1.5], "rotation": [2.981, 4.98093, -0.43688], "uv": [37, 23]} + ] + }, + { + "name": "bone4", + "parent": "right_leg", + "pivot": [-1.5, 14.5, -1], + "cubes": [ + {"origin": [-2.7, 12, -3.5], "size": [2.4, 5, 4], "pivot": [-1.5, 12.25, -1.5], "rotation": [-5.019, 4.98093, -0.43688], "uv": [36, 14]} + ] + }, + { + "name": "head", + "parent": "_", + "pivot": [0, 26.25, -1.75], + "rotation": [5, 0, 0], + "cubes": [ + {"origin": [0.5, 30.30666, -0.07183], "size": [4, 4, 4], "uv": [20, 22]}, + { + "origin": [-3, 26.80666, -3.57183], + "size": [6, 6, 6], + "uv": { + "north": {"uv": [35, 42], "uv_size": [8, 6]}, + "east": {"uv": [0, 20], "uv_size": [6, 6]}, + "south": {"uv": [18, 20], "uv_size": [6, 6]}, + "west": {"uv": [12, 20], "uv_size": [6, 6]}, + "up": {"uv": [6, 14], "uv_size": [6, 6]}, + "down": {"uv": [12, 20], "uv_size": [6, -6]} + } + }, + {"origin": [-3.5, 25.90666, -4.07183], "size": [7, 7, 7], "uv": [0, 0]}, + {"origin": [-3, 32.30666, -3.57183], "size": [2, 2, 2], "pivot": [-2, 33.80666, -2.57183], "rotation": [0, 0, -22.5], "uv": [24, 18]}, + {"origin": [-2.32403, 34.19248, -3.07183], "size": [1, 2, 1], "pivot": [-2.57403, 35.19248, -2.57183], "rotation": [0, 0, 15], "uv": [19, 17], "mirror": true}, + {"origin": [1, 32.40666, -3.57183], "size": [2, 2, 2], "pivot": [2, 33.90666, -2.57183], "rotation": [0, 0, 22.5], "uv": [18, 16]}, + {"origin": [1.32403, 34.29248, -3.07183], "size": [1, 2, 1], "pivot": [2.57403, 35.29248, -2.57183], "rotation": [0, 0, -15], "uv": [19, 17]}, + {"origin": [-4.5, 30.30666, -0.07183], "size": [4, 4, 4], "uv": [24, 10]} + ] + }, + { + "name": "body", + "parent": "_", + "pivot": [0, 23.07322, -1.95711], + "cubes": [ + {"origin": [-2.6, 17, -3], "size": [5.2, 10, 4], "uv": [0, 26]}, + {"origin": [-3, 21.75, -3.75], "size": [6, 3, 3], "pivot": [0, 24.5, -1.5], "rotation": [-45, 0, 0], "uv": [21, 0]} + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/occultism/textures/entity/demonic_husband.png b/src/main/resources/assets/occultism/textures/entity/demonic_husband.png new file mode 100644 index 0000000000000000000000000000000000000000..873edb232cb03856440f1c99da22d472172f8a5e GIT binary patch literal 3822 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/occultism/textures/entity/demonic_wife.png b/src/main/resources/assets/occultism/textures/entity/demonic_wife.png new file mode 100644 index 0000000000000000000000000000000000000000..d73741c735071cd9ae6e00cf937d541b6aa4bec1 GIT binary patch literal 1533 zcmV|<-tYH* zzu)`4-x~%2x;jb#pt2m=RO|Wg!7ee}0XlR4H8(c?-aA zFxW@cX60x5Z@p$805WV)>YA>OlGmTixMdKUTV9)>Hq`*Q-9Tijd2PZP;A?|pxL^MZ zE5#`QUDH3Kzk$E^H+z2LRMgyR1=ZFD;|Uv=s|XvhcWw%9ey+AQq!f^0gE*ai1$Tcc zqh4>|{N?xXu(6E}?fVX{9|}-~HyyJcmWPdP9Q*k6!ME+u?IeMe3wS9asc7w-@vJh8 zhOz7WyRhR??Mod1m!Q08%~Ou^w^0=*Bm7En3RiA#1!>kowGU3#%$>P_Q%O9Rky+-< zU}?w98N8I?^?VRi0%|JD<(xugn0^<)y9%-EP3$e%XHHi~sZBK~OoM?I6lfq|Q)Rg^ ztKoyT6gB_?MOxzzg*+a*4IV77O^|^$3~G7}lG;>bJhOGK5&%Fjz#QoX!2rmBfetb( zYpo!0uIHg+KzD@RGo-fIu`0Hn`Zc0J>i`A;ifX`kkbyD@Py=Au4mCjNKxI0JngHA> zb{v9)g$=1=q_B+hx&eSyTN}QaqA85RG$>F3FiR)~r91oR3QI81p?%@9+HVD@cHu?I z4G(j`R`NsG0Wi}2Xjsp6sEG_4h&I{;;0nBSb~=!MUcdLdZ=48%eOdORFPY#-Zm8$` zPHj(k-H&>Ei<{bpc`gp5c7s7EFWjK=!VTBpg9z0x;eiAcz(ZCj1_dh9lOB$(KMqT0 zrzwaFynpecRENdI&!l&tcKr4P(eeNeJl~e}`MAg`!}wzQIP96=+-e1YeEQCV1&#JW zF)ib1t7Tm)XqxreX%Sw#!LIOb=2k0Mo*Bn%c|Dp11daA#RtLM#B7$sg%qmi(-5~Eq zv2+y+*RJ96sYw99caI)m@#amGzx*mt2Nyp7+FAi*3M;eab>aQE;VNLLP=IcmHC@v% zR49b%#H<~NN?ayhrkrG1jJpi3mF98jgtfcHr4wUVE6s=QsGrGA5LCcBsz1@QKyAz&#jpl88*o_F0e`=cm4;E@M>d;WrJpyrZehqrMO2`VbGipuRtx_~ebh#S8EXl{VQ zrp#d!5;_&u)lst7|7GE=1Z}ECPHMu?x4i(+Et=SQ9%q40RHx5>^M~Pil=aCwhq}7= zWDno}vxDWCam=lPX5V}j<1cgrMEnc4UW#ul}G_VuYV_5Ci4t}VX`r=mE!+EUt_>g#M1@5-rSH4SYac%)6Ac%3p9*f zO9?V(b9O`l%-L4Yvnt3`vU!$ZBFYP*Du)qKEGg=X1Ks2AB-Zi_8|1!E5LE%HIdBu6 z0J1Ky@b)Q;BN3tM4M{pP(ALU0`Lfe z88+zYt1_>&0KFCz#5`XbIKy>CQSA7)c|TeV5Z#o`-0bu#ddCIV1(Gh79u@k!9rnXd z>AdsDC`49(XpPp@QBs%&gIcb8N5wrMtpZ zrK`C0_?-3q*5h+1maZn&pUVY;roPf0NhUHwg#u3ICjs060G!NEhAziTjccViAWHF3s*FjX0oB%*vuN=iyf jN=iyfN=iyfN{WkT`Lh}+89bdW00000NkvXXu0mjf3k%;W literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/occultism/textures/gui/book/demonic_partner.png b/src/main/resources/assets/occultism/textures/gui/book/demonic_partner.png new file mode 100644 index 0000000000000000000000000000000000000000..1692349458ffc4f46aeaf159fd164290decb3b8b GIT binary patch literal 6453 zcmV-58Or8~P)StO&>uS)ve<0AYj>5AR{$W90N^4L=L-RlQUJ&DC0@ZjPh;=*jPLSYvv5M~MFBAl0-BNIsH z15C~g000{K(ZT*WKal6<?_01!^k@7iDG<<3=fuAC~28EsPoqkpK{9G%|Vj005J}`Hw&=0RYXHq~ibpyyzHQsFW8>#s~laM4*8xut5h5 z!4#~(4xGUqyucR%VFpA%3?#rj5JCpzfE)^;7?wd9RKPme1hudO8lVxH;SjXJF*pt9 z;1XPc>u?taU>Kgl7`%oF1VP9M6Ja4bh!J9r*dopd7nzO(B4J20l7OTj>4+3jBE`sZ zqynizYLQ(?Bl0bB6giDtK>Co|$RIL`{EECsF_eL_Q3KQhbwIhO9~z3rpmWi5G!I>X zmZEFX8nhlgfVQHi(M#xcbO3#dj$?q)F%D*o*1Pf{>6$SWH+$s3q(pv=X`qR|$iJF~TPzlc-O$C3+J1 z#CT#lv5;6stS0Uu9wDA3UMCI{Uz12A4#|?_P6{CkNG+sOq(0IRX`DyT~9-sA|ffUF>wk++Z!kWZ5P$;0Hg6gtI-;!FvmBvPc55=u2?Kjj3apE5$3psG>L zsh-pbs)#zDT1jo7c2F-(3)vyY4>O^>2$gY-Gd%Qm(Z8e zYv>2*=jns=cMJ`N4THx>VkjAF8G9M07`GWOnM|ey)0dgZR4~^v8<}UA514ONSSt1^ zd=-((5|uiYR+WC0=c-gyb5%dpd8!Lkt5pxHURHgkMpd&=fR^vEcAI*_=wwAG2sV%zY%w@v@XU~7=xdm1xY6*0;iwVIXu6TaXrs|dqbIl~ z?uTdNHFy_3W~^@g_pF#!K2~{F^;XxcN!DEJEbDF7 zS8PxlSDOr*I-AS3sI8l=#CDr)-xT5$k15hA^;2%zG3@;83hbKf2JJcaVfH2VZT8O{ z%p4LO);n}Nd~$Sk%yw*Wyz8XlG{dRHsl(}4XB%gsbDi@w7p6;)%MzD%mlsoQr;4X; zpL)xc%+^yMd)ZNTI#eJ*$O)i@o$z8)e??LqN_gLa_%;TM>o2SC_ zkmoO6c3xRt`@J4dvz#WL)-Y|z+r(Soy~}%GIzByR`p)SCKE^%*pL(B%zNWq+-#xw~ ze%5}Oeh2)X`#bu}{g3#+;d$~F@lFL`0l@*~0lk45fwKc^10MvL1f>Tx1&sx}1}_Xg z6+#RN4Ot&@lW)Km@*DYMGu&q^n$Z=?2%QyL8~QNJCQKgI5srq>2;UHXZ>IT7>CCnW zh~P(Th`1kV8JQRPeH1AwGO8}>QM6NZadh`A)~w`N`)9q5@sFvDxjWlxwsLl7tZHmh zY-8-3xPZ8-xPf?w_(k!T5_A(J3GIpG#Ms0=iQ{tu=WLoYoaCBRmULsT<=mpV7v|~C z%bs^USv6UZd^m-e5|^?+<%1wXP%juy<)>~<9TW0|n}ttBzM_qyQL(qUN<5P0omQ3h zINdvaL;7fjPeygdGYL;pD|wL_lDQ-EO;$wK-mK5raoH_7l$?~Dqf!lNmb5F^Ft;eT zPi8AClMUo~=55LwlZVRpxOiFd;3B_8yA~shQx|tGF!j;$toK>JuS&gYLDkTP@C~gS@r~shUu{a>bfJ1` z^^VQ7&C1OKHDNXFTgC{M|V%fo{xK_dk6MK@9S!GZ*1JJzrV5xZBjOk z9!NTH<(q(S+MDf~ceQX@Dh|Ry<-sT4rhI$jQ0Sq~!`#Eo-%($2E^vo}is5J@NVEf|KK?WT&2;PCq@=ncR8z zO#GQ^T~S@VXG71PKNocFOt)Y6$@AXlk6rM*aP%VgV%sIRORYVwJx6|U{ozQjTW{-S z_si{9Jg#)~P3t?+@6&(!YQWWV*Z9{iU7vZq@5byKw{9lg9JnRA_4s!7?H6|n?o8ZW zdXIRo{Jz@#>IeD{>VLHUv1Pz*;P_y`V9&!@5AO~Mho1hF|I>%z(nrik)gwkDjgOrl z9~%uCz4Bzvli{bbrxVZ0epdf^>vOB;-~HnIOV3#R*zgPai_gEVd8zYq@2jb=I>#f& zAH2?aJ@KaetuYS09#vZFtKlmO2VvVkJ?$w<$|NTE}@4fc_zeZG*ALlSXXaGOx z_^~G-DC@@m_@NK&UZ;7+;>0w^4=hf(*lb;0U#HdUkSp_PyZgvSlD@l0(#MN#`}56u z4J*pueB(5iJL_14&`c5pmb7S*d!;V(IMZQJtlcus(g>JncK{GTy{9MP-=CFhzmcYc z%P;r3e{MVN#}}%#UyG;b9<6AbPLbbJsWm=7*{JjB@0{jxXN$;2IG2|N5h!sAq$VIW zmdpfb5TVAr_0rmE^Qlv(Pki(0t9SYH=c$}J`B>^5VGy8VZ(EpZ-1cv0UgX(J=Lt}@WG>pAr5(QeS@#Bt|L*j zujd?xW@ed-g3mp=G5Gd_`xoDJA_{G%F@fTd+mHSA3u~LdbNb~glZ8(L5fel~vkJbR z7QLpGibU3t=_aBE#*hZ(tpT&s5LMZixTWpY*54L|J18R5q6iyBOLs2K|EkFouCyG@ zT8;HipGL(T{FMjZc<|!NDy?3h*v1$MP%ZEjSVFE(3A*FJSzZQw^0NeiOnx&qeDtMncHsOD$dd}K#O&ZsT`_@)nlzekJg~eFlz?{)Y(c? zH0=NZmH=xEmI%e5D1yNd!YK8Pgg8x69OK-*OCz8#4lDkApim1UcJ}c?K`_J;QfQUo zzP?lJSezE9dW={C3GwVa@!=Fu1ObeMb{sfMBcLh=Q1M+)4hSNGsv&bZ;7PGS4k)qp z7y@pd){0`pFv|ViPX&v?)W(6cGy?kWGS*c4p`AjtAafa!g|{#4r)mQ-F9;3RlY|$x z`gj~7iijQMibF7fIEIfu5HXa=B^nHiicX`{wB1dXX z+Ad=<@O@3b+eHZWo(}s{-yN`O!o>m%T!C4vsp^s3J4pvEh zpT&K1%+_Ad#g?OH`fO*gDivgAKZiCmHacDEQH8#P)Hw{pEHGjx4FQVc@fgC}1$kO@ zJZFLO4nu5F(CZlq$ov*l^9|nf_FrbJy@1mmMeg~pYlk@cuJ`l%zxX!ZH68Qt!ZeLQ zD11H|?#;E1Lx_7q9UT+&@-o280bI>p!i=eM$LthoY>1*NUIlBx=SuDZn)NEN5mFef z@xzzJctO0P0$5PgXePSzy<3mcG9YoQByMdrb%W&f67YeC?q%_=6U1hY+!a{knF(i! z?IctJ3J>V0#2Gz#!Ho95ogKhnv5Q75M#i!WmbeI-5Rk3H%atUww_m$(iR{oaVMXy8 zAmR~cP*W$GZh{O48Cydj77_63jHodpB7(t6Naovfh3}6IXK4hWySEmZoTPK|0@-)Z zaddVT;~V6@U}^s;w!eCTwseV_lWY|^5AJKwnXK~kt6SvWOK2DgAj2|P)TV}bY%t3! zh1COcM3CEBgN$>1&qS_FH&WUBRtbz94f=Zd>v0#HFWx)cANB|%w-luj;MHS9CPh7gZL(Pm=;u}b z@|T+Y-p^lQW%X6Qb1LEsk0r!3xqs?TmXq^rtHVmbjRRCX0(XKK#d~FZN^yx90E(N6 zOcRkRtppxAROOF9xIu8d%R~Z?K6wvwoIonqc&>Mb#I=Ye+H;5N_mifGe@NATbDRoB ziEDsjC0>l|3D{R9ztyI23s zal$Nd8w3$KR`@Q$a9`i-30K=8PzMZ^V1rmJq6tQZI-uTA{t9w^9Z*FuN5@qG?nG$> z1g3^Hl{=iKsOH0Ct{7?ofI%>bSezG}AMEb+uN5OvFx12(4inABc+Ft@^f7T^&=f^u~p=JOb!T=DY@`LMS!7<`jNF zxGUti(NG0Xu_JUb6wHR#M(i#Dg271G$TfY)sr%}5y})UT*A%ZFM-S(_ zH&`0;L=0tbV=P_^)GJ~Gyyn9f1xk)rkE+LMDjqjBoFz_ym8O+B0;!W09dcdgqkr%x z+$d)-)ELtU*9631wI8JC!r>@c+H0E#0|oTkpLsXJu=2Zpfmy!-<{8L zLoKMH9y|#@_sGM%^PTSm!1;`G=g#xu#h1DE>NQTDJWZ>$L6)aH@x&KL(;);bmJl;C zNDv-&l8y~$X$0IkF?Vda*Q1;F0SknD z?QV;&e&s2?@}+Ol%MwB}!B7v;-EGo~yT^;40^J%1&e90@nT6)--(hC>{zjkk?M))n zWO?}v%gbj*->5P*(d6)vB_4Ro{oH-`3D(wDc=p-n2uy{#tzyLt=RFCI3{bol)@gr9 z^@p5*3~oDGukz-7vwZtnNIOe-ZZqV?_JB|fxn^v2HrP6|!l^Ug+w;3syFg$gBLS)NOoWd296rEI9JA19vO4H$U-&Z<=%j2u51I<>52_%P90tynTtrA zqn)pix)eJ)3I_sSbGCBNk!F*Ap3%utCT&PnEUEYO&~JG48{@!PS_WM1C4B4h3g6vm z10k`g%sR4IwMt|n-ZW#V1$8d>5>^HoxmSz~Pk;bd2MOLQjVQ{Jet)fRx>3SX=Bi#orsG|l^t zR_GL-&2(t}_X`IMNSr5i7O#*w;mTn9>3>G8-Rbxs$Ro=(3pxq+W2o@scYt9=mv%_s-6- z(5P_*@MCQ3Dvf~Ox@+==cZxM;{?$RjX69IKCuB}Zyk{z~+&9#Huf2MzVRiO_{qx*0QDvcO zdFIs?PrS6wvB^4QH`FLome|mhf!R-@O{&Q`c)xm)461WEfj0hq*0Rc|)&lH+{aIZ(;0AZ;y z!ONY^TgO=z0fF53gp|NmK9za-uxiHeJP;6>U^K4b0CV-AIYxGxB>Yw92M7211Tqpx zJmbJ#o+fxxFS8|hTg6sTVpJ8S!0WJu4u(>w6?cOhSP+={VnF=Up5mFZaF*8~Avb&Y zqFxIab%82-tuNix`DAoXh_Dipvz3ff1H3uP>k*RaJ@1u#d&kt!k=D1@;JEG!07SNq z_xfjrmv8I;W18GblqZPz&fY&{!eprP?`e7eKddlMU>c~p^Mz~wRaokQwM={bCiBKq zPxshgssyHiAiGV_io-}qC{+f<+OHSmGk{(*N+X~aEZ+2qwysOvL(|h~f|Uw^RCkZZ zB9Qy;KNOmO7b<1J+l>-CMQ?277sU9?*%aqfyyiGEycP%