mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-25 08:36:24 -04:00
Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86d48df9fe | ||
|
|
3401ba9cbb | ||
|
|
dac9ccb461 | ||
|
|
191a62f693 | ||
|
|
d8d410e539 | ||
|
|
b7c6e1ea77 | ||
|
|
0af4588a14 | ||
|
|
186812d6fd | ||
|
|
1c0bdc766a | ||
|
|
c697bcd2e9 | ||
|
|
9d6ff01d80 | ||
|
|
1691853a19 | ||
|
|
4e9a4e1e5a | ||
|
|
6450255a0b |
@@ -1,3 +0,0 @@
|
||||
### Additions
|
||||
|
||||
- Added the ability to ride Pokémon by shift-right clicking and selecting the ride option.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Cobblemon
|
||||
|
||||
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and Forge.
|
||||
An open-source Pokémon mod for Minecraft Java Edition, written in Kotlin for Fabric and NeoForge.
|
||||
|
||||
## Getting started
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
{
|
||||
"lastSavedVersion": "1.7.0",
|
||||
"maxPokemonLevel": 100,
|
||||
"maxPokemonFriendship": 255,
|
||||
"announceDropItems": true,
|
||||
"defaultDropItemMethod": "on-entity",
|
||||
"ambientPokemonCryTicks": 1080,
|
||||
"defaultBoxCount": 30,
|
||||
"pokemonSaveIntervalSeconds": 30,
|
||||
"storageFormat": "nbt",
|
||||
"preventCompletePartyDeposit": false,
|
||||
"mongoDBConnectionString": "mongodb://localhost:27017",
|
||||
"mongoDBDatabaseName": "cobblemon",
|
||||
"maxVerticalCorrectionBlocks": 64,
|
||||
"minimumLevelRangeMax": 10,
|
||||
"enableSpawning": true,
|
||||
"minimumDistanceBetweenEntities": 8.0,
|
||||
"maxNearbyBlocksHorizontalRange": 4,
|
||||
"maxNearbyBlocksVerticalRange": 2,
|
||||
"maxVerticalSpace": 8,
|
||||
"worldSliceDiameter": 8,
|
||||
"worldSliceHeight": 16,
|
||||
"ticksBetweenSpawnAttempts": 20.0,
|
||||
"minimumSliceDistanceFromPlayer": 16.0,
|
||||
"maximumSliceDistanceFromPlayer": 64.0,
|
||||
"exportSpawnConfig": false,
|
||||
"savePokemonToWorld": true,
|
||||
"exportStarterConfig": false,
|
||||
"autoUpdateShowdown": true,
|
||||
"defaultFleeDistance": 32.0,
|
||||
"allowExperienceFromPvP": true,
|
||||
"experienceShareMultiplier": 0.5,
|
||||
"luckyEggMultiplier": 1.5,
|
||||
"allowSpectating": true,
|
||||
"experienceMultiplier": 2.0,
|
||||
"pokemonPerChunk": 1.0,
|
||||
"passiveStatuses": {
|
||||
"cobblemon:poison": "180-300",
|
||||
"cobblemon:poisonbadly": "180-300",
|
||||
"cobblemon:paralysis": "180-300",
|
||||
"cobblemon:frozen": "180-300",
|
||||
"cobblemon:sleep": "180-300",
|
||||
"cobblemon:burn": "180-300"
|
||||
},
|
||||
"infiniteHealerCharge": false,
|
||||
"maxHealerCharge": 6.0,
|
||||
"secondsToChargeHealingMachine": 900.0,
|
||||
"defaultFaintTimer": 300,
|
||||
"faintAwakenHealthPercent": 0.2,
|
||||
"healPercent": 0.05,
|
||||
"healTimer": 60,
|
||||
"baseApricornTreeGenerationChance": 0.1,
|
||||
"displayEntityLevelLabel": true,
|
||||
"displayEntityNameLabel": true,
|
||||
"displayNameForUnknownPokemon": false,
|
||||
"displayEntityLabelsWhenCrouchingOnly": false,
|
||||
"shinyRate": 8192.0,
|
||||
"shinyNoticeParticlesDistance": 24.0,
|
||||
"captureCalculator": "cobblemon",
|
||||
"playerDamagePokemon": true,
|
||||
"appleLeftoversChance": 0.025,
|
||||
"maxRootsInArea": 5,
|
||||
"bigRootPropagationChance": 0.1,
|
||||
"energyRootChance": 0.25,
|
||||
"maxDynamaxLevel": 10,
|
||||
"teraTypeRate": 20.0,
|
||||
"defaultPasturedPokemonLimit": 16,
|
||||
"pastureBlockUpdateTicks": 40,
|
||||
"pastureMaxWanderDistance": 64,
|
||||
"pastureMaxPerChunk": 4.0,
|
||||
"maxInsertedFossilItems": 2,
|
||||
"walkingInBattleAnimations": false,
|
||||
"battleWildMaxDistance": 12.0,
|
||||
"tradeMaxDistance": 12.0,
|
||||
"battlePvPMaxDistance": 32.0,
|
||||
"battleSpectateMaxDistance": 64.0,
|
||||
"maxPokedexScanningDetectionRange": 10.0,
|
||||
"hideUnimplementedPokemonInThePokedex": false,
|
||||
"summaryPokemonFollowCursor": true,
|
||||
"enableDebugKeys": false
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common;
|
||||
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface Rollable {
|
||||
|
||||
// From Minecraft's Camera
|
||||
Vector3f FORWARDS = new Vector3f(0.0F, 0.0F, -1.0F);
|
||||
Vector3f UP = new Vector3f(0.0F, 1.0F, 0.0F);
|
||||
Vector3f LEFT = new Vector3f(-1.0F, 0.0F, 0.0F);
|
||||
|
||||
@Nullable Matrix3f getOrientation();
|
||||
|
||||
Rollable updateOrientation(Function<Matrix3f, Matrix3f> update);
|
||||
|
||||
/**
|
||||
* @return The forward vector (0, 0, -1) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getForwardVector() {
|
||||
if (getOrientation() == null) return new Vector3f(FORWARDS);
|
||||
return getOrientation().transform(FORWARDS, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The left vector (-1, 0, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getLeftVector() {
|
||||
if (getOrientation() == null) return new Vector3f(LEFT);
|
||||
return getOrientation().transform(LEFT, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The up vector (0, 1, 0) after the rotation matrix is applied.
|
||||
*/
|
||||
default Vector3f getUpVector() {
|
||||
if (getOrientation() == null) return new Vector3f(UP);
|
||||
return getOrientation().transform(UP, new Vector3f());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotateYaw(float yaw) {
|
||||
return updateOrientation(prev -> prev.rotateY((float) Math.toRadians(-yaw)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param pitch change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
|
||||
default Rollable rotatePitch(float pitch) {
|
||||
return updateOrientation(prev -> prev.rotateX((float) Math.toRadians(-pitch)));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotateRoll(float roll) {
|
||||
return updateOrientation(prev -> prev.rotateZ((float) Math.toRadians(-roll)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Order matters when rotating an object. If you need a different order, individually call rotateYaw, rotatePitch, and rotateRoll
|
||||
*
|
||||
* @param yaw change in degrees
|
||||
* @param pitch change in degrees
|
||||
* @param roll change in degrees
|
||||
* @return The Rollable object this method was called on
|
||||
*/
|
||||
default Rollable rotate(float yaw, float pitch, float roll) {
|
||||
return rotateYaw(yaw).rotatePitch(pitch).rotateRoll(roll);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The pitch angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being South, 90 being West, 180/-180 being North, and -90 being East
|
||||
*/
|
||||
default float getYaw() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(FORWARDS.angleSigned(getForwardVector(), UP)) + 180);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The yaw angle in degrees as a float.
|
||||
* Value is between [-90, 90] with 0 being straight forward, 90 being straight down, and -90 being straight up
|
||||
*/
|
||||
default float getPitch() {
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(Math.asin(getForwardVector().y)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The roll angle in degrees as a float.
|
||||
* Value is between [-180, 180] with 0 being no roll (normal), 90 being 90 degrees CW, 180/-180 being 180 degrees CW/CCW, and -90 being 90 degrees CCW
|
||||
*/
|
||||
default float getRoll() {
|
||||
//Cobblemon.LOGGER.info("{}", (float) Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
return (float) Mth.wrapDegrees(-Math.toDegrees(getUpVector().angleSigned(UP, getForwardVector())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the angular velocity in degrees per second as a Vec3
|
||||
*/
|
||||
Vec3 angRollVel( double deltaTime );
|
||||
|
||||
public Vec3 rotationOnMouseXY(double yMouse,
|
||||
double xMouse,
|
||||
SmoothDouble yMouseSmoother,
|
||||
SmoothDouble xMouseSmoother,
|
||||
double sensitivity,
|
||||
double deltaTime );
|
||||
|
||||
boolean shouldRoll();
|
||||
|
||||
boolean useAngVelSmoothing();
|
||||
|
||||
void clearRotation();
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Camera.class)
|
||||
public abstract class CameraMixin {
|
||||
@Shadow @Final private static float DEFAULT_CAMERA_DISTANCE;
|
||||
|
||||
@Shadow private Entity entity;
|
||||
@Shadow @Final private Quaternionf rotation;
|
||||
@Shadow @Final private Vector3f forwards;
|
||||
@Shadow @Final private Vector3f up;
|
||||
@Shadow @Final private Vector3f left;
|
||||
@Shadow private float xRot;
|
||||
@Shadow private float yRot;
|
||||
|
||||
@Shadow public abstract float getXRot();
|
||||
|
||||
@Shadow public abstract float getYRot();
|
||||
|
||||
@Unique private float returnTimer = 0;
|
||||
@Unique private float rollAngleStart = 0;
|
||||
@Unique Minecraft minecraft = Minecraft.getInstance();
|
||||
|
||||
@Unique boolean disableRollableCameraDebug = false;
|
||||
|
||||
@Inject(method = "setRotation", at = @At("HEAD"), cancellable = true)
|
||||
public void open_camera$setRotation(float f, float g, CallbackInfo ci) {
|
||||
if (!(this.entity instanceof Rollable rollable) || disableRollableCameraDebug) return;
|
||||
if (!rollable.shouldRoll() && rollable.getOrientation() != null) {
|
||||
if(this.returnTimer < 1) {
|
||||
//Rotation is taken from entity since we no longer handle mouse ourselves
|
||||
//Stops a period of time when you can't input anything.
|
||||
rollable.getOrientation().set(
|
||||
new Matrix3f()
|
||||
.rotateY((float) Math.toRadians(180 - this.entity.getYRot()))
|
||||
.rotateX((float) Math.toRadians(-this.entity.getXRot()))
|
||||
);
|
||||
if(rollAngleStart == 0){
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
return;
|
||||
}
|
||||
rollable.getOrientation().rotateZ((float) Math.toRadians(-rollAngleStart*(1-returnTimer)));
|
||||
applyRotation();
|
||||
this.returnTimer += .05F;
|
||||
ci.cancel();
|
||||
} else {
|
||||
this.returnTimer = 1;
|
||||
rollable.clearRotation();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rollable.getOrientation() == null) return;
|
||||
applyRotation();
|
||||
|
||||
this.returnTimer = 0;
|
||||
this.rollAngleStart = rollable.getRoll();
|
||||
ci.cancel();
|
||||
}
|
||||
|
||||
@Unique
|
||||
private void applyRotation(){
|
||||
if (!(this.entity instanceof Rollable rollable) || rollable.getOrientation() == null) return;
|
||||
var newRotation = rollable.getOrientation().normal(new Matrix3f()).getNormalizedRotation(new Quaternionf());
|
||||
if (this.minecraft.options.getCameraType().isMirrored()) {
|
||||
newRotation.rotateY((float)Math.toRadians(180));
|
||||
}
|
||||
this.rotation.set(newRotation);
|
||||
this.xRot = rollable.getPitch();
|
||||
this.yRot = rollable.getYaw();
|
||||
this.forwards.set(rollable.getForwardVector());
|
||||
this.up.set(rollable.getUpVector());
|
||||
this.left.set(rollable.getLeftVector());
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.HumanoidModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Mixin(HumanoidModel.class)
|
||||
public class HumanoidModelMixin {
|
||||
@Unique HashMap<String, ModelPart> relevantPartsByName = new HashMap<>();
|
||||
|
||||
@Shadow @Final
|
||||
public ModelPart head;
|
||||
@Shadow @Final
|
||||
public ModelPart rightArm;
|
||||
@Shadow @Final
|
||||
public ModelPart leftArm;
|
||||
@Shadow @Final
|
||||
public ModelPart rightLeg;
|
||||
@Shadow @Final
|
||||
public ModelPart leftLeg;
|
||||
|
||||
@Inject(method = "setupAnim*", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/geom/ModelPart;copyFrom(Lnet/minecraft/client/model/geom/ModelPart;)V", shift = At.Shift.BEFORE))
|
||||
public void cobblemon$animateRiders(
|
||||
LivingEntity entity,
|
||||
float limbSwing,
|
||||
float limbSwingAmount,
|
||||
float ageInTicks,
|
||||
float netHeadYaw,
|
||||
float headPitch,
|
||||
CallbackInfo ci
|
||||
) {
|
||||
if (relevantPartsByName.isEmpty()) {
|
||||
relevantPartsByName.put("arm_left", leftArm);
|
||||
relevantPartsByName.put("arm_right", rightArm);
|
||||
relevantPartsByName.put("leg_left", leftLeg);
|
||||
relevantPartsByName.put("leg_right", rightLeg);
|
||||
relevantPartsByName.put("head", head);
|
||||
}
|
||||
|
||||
Entity vehicle = entity.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity && entity instanceof AbstractClientPlayer) {
|
||||
MountedPlayerRenderer.INSTANCE.animate((PokemonEntity) vehicle, (AbstractClientPlayer) entity, relevantPartsByName, netHeadYaw, headPitch, ageInTicks, limbSwing, limbSwingAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,21 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.item.PokedexItem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Axis;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.ItemInHandRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.joml.Quaternionf;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(ItemInHandRenderer.class)
|
||||
@@ -32,15 +27,5 @@ public class ItemInHandRendererMixin {
|
||||
if (abstractClientPlayer.isUsingItem() && abstractClientPlayer.getUseItem().getItem() instanceof PokedexItem) {
|
||||
ci.cancel();
|
||||
}
|
||||
else if (abstractClientPlayer instanceof Rollable rollable && rollable.shouldRoll()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(method = "renderHandsWithItems", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;mulPose(Lorg/joml/Quaternionf;)V", ordinal = 1))
|
||||
private void cobblemon$renderHandswithItems(PoseStack instance, Quaternionf quaternion) {
|
||||
if (!(Minecraft.getInstance().player instanceof Rollable rollable && rollable.shouldRoll())) {
|
||||
instance.mulPose(quaternion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,15 +12,9 @@ import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffectRegistry;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LivingEntity.class)
|
||||
@@ -34,70 +28,4 @@ public abstract class LivingEntityMixin {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@Inject(method = "travelRidden", at = @At(value = "HEAD"))
|
||||
private void cobblemon$altTravelRidden(Player player, Vec3 travelVector)
|
||||
{
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(vec3);
|
||||
}
|
||||
|
||||
/*
|
||||
// Shadow the original method so we can call it.
|
||||
@Shadow
|
||||
protected abstract boolean isControlledByLocalInstance();
|
||||
|
||||
/**
|
||||
* Redirect the call to isControlledByLocalInstance() within travelRidden.
|
||||
* When travelRidden calls isControlledByLocalInstance(), it will get our modified result.
|
||||
*/
|
||||
|
||||
/*
|
||||
@Redirect(
|
||||
method = "travelRidden(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/phys/Vec3;)V",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/world/entity/LivingEntity;isControlledByLocalInstance()Z"
|
||||
)
|
||||
)
|
||||
private boolean redirectIsControlledByLocalInstance(LivingEntity instance) {
|
||||
// Return true if either the original method returns true or our custom condition is true.
|
||||
return this.isControlledByLocalInstance() || this.b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Overwrite
|
||||
private void travelRidden(Player player, Vec3 travelVector) {
|
||||
Vec3 vec3 = this.getRiddenInput(player, travelVector);
|
||||
this.tickRidden(player, vec3);
|
||||
if (this.isControlledByLocalInstance()) {
|
||||
this.setSpeed(this.getRiddenSpeed(player));
|
||||
this.travel(vec3);
|
||||
} else {
|
||||
this.calculateEntityAnimation(false);
|
||||
this.setDeltaMovement(Vec3.ZERO);
|
||||
this.tryCheckInsideBlocks();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ModifyArg(
|
||||
method = "travelRidden",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V"
|
||||
),
|
||||
index = 0 // the first (and only) argument
|
||||
)
|
||||
private Vec3 modifyDeltaMovementArgument(Vec3 original) {
|
||||
// Optionally, check if original is Vec3.ZERO, to only replace that call:
|
||||
if (original.equals(Vec3.ZERO)) {
|
||||
// Return your custom vector instead of Vec3.ZERO
|
||||
return original;
|
||||
}
|
||||
// Otherwise, return the original value
|
||||
return original;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public abstract class LocalPlayerMixin {
|
||||
@Shadow
|
||||
private float jumpRidingScale;
|
||||
|
||||
@Inject(method = "getJumpRidingScale", at = @At("HEAD"), cancellable = true)
|
||||
public void modifyJumpRidingScale(CallbackInfoReturnable<Float> cir) {
|
||||
|
||||
LocalPlayer player = (LocalPlayer) (Object) this;
|
||||
if (player.isPassenger() && player.getVehicle() instanceof PokemonEntity) {
|
||||
PokemonEntity ride = (PokemonEntity) player.getVehicle();
|
||||
//ride.getRiding().canJump()
|
||||
if( !ride.getRiding().canJump(ride, player))
|
||||
{
|
||||
cir.setReturnValue(0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if the player is riding your custom entity (for example, a Pokemon)
|
||||
/*
|
||||
if (player.isRiding() && player.getVehicle() instanceof PokemonEntity) {
|
||||
PokemonEntity rideable = (PokemonEntity) player.getVehicle();
|
||||
// Get your custom fuel ratio (a value from 0.0 to 1.0)
|
||||
float fuelRatio = rideable.getRidingFuelRatio();
|
||||
cir.setReturnValue(fuelRatio);
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -8,38 +8,30 @@
|
||||
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext;
|
||||
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import com.mojang.blaze3d.Blaze3D;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.MouseHandler;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(MouseHandler.class)
|
||||
public class MouseHandlerMixin {
|
||||
@Shadow private double accumulatedScrollY;
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
@Shadow
|
||||
private double accumulatedScrollY;
|
||||
|
||||
@Unique SmoothDouble xMouseSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble yMouseSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble pitchSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble rollSmoother = new SmoothDouble();
|
||||
@Unique SmoothDouble yawSmoother = new SmoothDouble();
|
||||
@Shadow @Final private Minecraft minecraft;
|
||||
|
||||
@Shadow @Final private SmoothDouble smoothTurnY;
|
||||
|
||||
@@ -49,8 +41,6 @@ public class MouseHandlerMixin {
|
||||
|
||||
@Shadow private double accumulatedDY;
|
||||
|
||||
@Shadow private double accumulatedScrollX;
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
@@ -102,12 +92,8 @@ public class MouseHandlerMixin {
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;turn(DD)V"
|
||||
)
|
||||
)
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player,
|
||||
double cursorDeltaX,
|
||||
double cursorDeltaY,
|
||||
@Local(argsOnly = true) double d,
|
||||
@Local(argsOnly = true) double movementTime
|
||||
) {
|
||||
public boolean cobblemon$modifyRotation(LocalPlayer player, double cursorDeltaX, double cursorDeltaY, @Local(argsOnly = true) double d) {
|
||||
// I know this technically doesn't need to be a WrapWithCondition, but it'll make things easier later for riding.
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
@@ -119,106 +105,7 @@ public class MouseHandlerMixin {
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(player instanceof Rollable rollable)) return true;
|
||||
|
||||
if (!rollable.shouldRoll()) {
|
||||
xMouseSmoother.reset();
|
||||
yMouseSmoother.reset();
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
yawSmoother.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
//maybe have a rollable x mouse and rollable y mouse that take the xmousesmoother
|
||||
//and y mouse smoother ( which are right now named pichsmoother and roll smoother)
|
||||
// values and feed it to those rollable functions which will be called by the
|
||||
//specific ride controller where rollable.rotate can then be called and used
|
||||
//controller specific.
|
||||
|
||||
//return a vec3 of the yaw pitch and roll that are wanted.
|
||||
//multiply by sensitivity before passing it in
|
||||
|
||||
//var xMouse = xMouseSmoother.getNewDeltaValue(cursorDeltaX * 0.05f, d);
|
||||
//var yMouse = yMouseSmoother.getNewDeltaValue(cursorDeltaY * 0.05f, d);
|
||||
|
||||
var defaultSensitivity = this.minecraft.options.sensitivity().get() * 0.6000000238418579 + 0.20000000298023224;
|
||||
var ridingSensitivity = Math.pow(defaultSensitivity, 3);
|
||||
|
||||
Vec3 angVecMouse = rollable.rotationOnMouseXY
|
||||
( cursorDeltaY,
|
||||
cursorDeltaX ,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
ridingSensitivity,
|
||||
movementTime );
|
||||
|
||||
//make this configurable maybe?
|
||||
|
||||
//var mRoll = rollSmoother.getNewDeltaValue(angVecMouse.z * 0.15f, d);
|
||||
|
||||
rollable.rotate((float) angVecMouse.x,
|
||||
(float) angVecMouse.y,
|
||||
(float) angVecMouse.z);
|
||||
|
||||
//var yMouse = yMouseSmoother.getNewDeltaValue(angVecMouse.y * 0.15f, d);
|
||||
//var xMouse = xMouseSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
|
||||
//get the current angular velocity requested to be applied
|
||||
//by the ride controller
|
||||
var angRot = rollable.angRollVel(movementTime);
|
||||
|
||||
if( rollable.useAngVelSmoothing() )
|
||||
{
|
||||
//get the current angular velocity requested to be applied
|
||||
//by the ride controller
|
||||
|
||||
//Multiply against deltatime to get a consistent turn
|
||||
//independent of framerate
|
||||
if( angRot != null ) {
|
||||
//var yaw = angRot.x * d;
|
||||
//Add the yaw to the mouse here... this all needs changed. It should
|
||||
//just map which 0 1 or 2 of the three it is going to modulate with
|
||||
//what
|
||||
|
||||
var yaw = yawSmoother.getNewDeltaValue(angRot.x * 0.5f, d);
|
||||
var pitch = pitchSmoother.getNewDeltaValue(angRot.y * 0.5f, d);
|
||||
var roll = rollSmoother.getNewDeltaValue(angRot.z * 0.5f, d);
|
||||
rollable.rotate((float) yaw, (float) pitch, (float) roll);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//Multiply against deltatime to get a consistent turn
|
||||
//independent of framerate
|
||||
if( angRot != null ) {
|
||||
//var yaw = angRot.x * d;
|
||||
//Add the yaw to the mouse here... this all needs changed. It should
|
||||
//just map which 0 1 or 2 of the three it is going to modulate with
|
||||
//what
|
||||
|
||||
rollable.rotate((float) (angRot.x * 10 * d),
|
||||
(float) (angRot.y * 10 * d),
|
||||
(float) (angRot.z * 10 * d));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Inject(method = "handleAccumulatedMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;isMouseGrabbed()Z", ordinal = 0))
|
||||
private void cobblemon$maintainMovementWhenInScreens(CallbackInfo ci, @Local(ordinal = 1) double e) {
|
||||
if (minecraft.player == null) return;
|
||||
if (!(minecraft.player instanceof Rollable rollable)) return;
|
||||
if (!rollable.shouldRoll()) return;
|
||||
if (minecraft.isPaused()) return;
|
||||
|
||||
var pitch = pitchSmoother.getNewDeltaValue(0, e);
|
||||
var roll = rollSmoother.getNewDeltaValue(0, e);
|
||||
rollable.rotate(0.0F, (float)pitch, (float)roll);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,15 +10,12 @@ package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.CobblemonItems;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents;
|
||||
import com.cobblemon.mod.common.api.events.item.LeftoversCreatedEvent;
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore;
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore;
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
@@ -29,16 +26,11 @@ import com.cobblemon.mod.common.util.CompoundTagExtensionsKt;
|
||||
import com.cobblemon.mod.common.util.CompoundTagUtilities;
|
||||
import com.cobblemon.mod.common.util.DataKeys;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.SmoothDouble;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
@@ -46,18 +38,14 @@ import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.food.FoodProperties;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
@@ -65,11 +53,10 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity implements Rollable, ScannableEntity {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity {
|
||||
|
||||
@Shadow public abstract CompoundTag getShoulderEntityLeft();
|
||||
|
||||
@@ -87,7 +74,6 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
|
||||
@Shadow public abstract void displayClientMessage(Component message, boolean overlay);
|
||||
|
||||
@Unique private Matrix3f orientation = null;
|
||||
|
||||
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
|
||||
super(p_20966_, p_20967_);
|
||||
@@ -239,137 +225,4 @@ public abstract class PlayerMixin extends LivingEntity implements Rollable, Scan
|
||||
public LivingEntity resolveEntityScan() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void absMoveTo(double x, double y, double z, float yaw, float pitch) {
|
||||
if (shouldRoll()) {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.setYRot(yaw % 360.0f);
|
||||
this.setXRot(pitch % 360.0f);
|
||||
this.yRotO = this.getYRot();
|
||||
this.xRotO = this.getXRot();
|
||||
}
|
||||
else {
|
||||
this.absMoveTo(x, y, z);
|
||||
this.absRotateTo(yaw, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At("HEAD"))
|
||||
public void tick(CallbackInfo ci) {
|
||||
if (this.shouldRoll()) {
|
||||
// Proof of concept for yaw movement
|
||||
if (this.getMainHandItem().is(Items.STICK)) {
|
||||
this.rotateYaw(2);
|
||||
}
|
||||
else if (this.getMainHandItem().is(Items.BLAZE_ROD)) {
|
||||
this.rotateYaw(-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix3f getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rollable updateOrientation(Function<Matrix3f, Matrix3f> update) {
|
||||
//Disabled to allow non mouse inputs to modify roll
|
||||
if (!shouldRoll()) return this;
|
||||
|
||||
if (this.orientation == null) {
|
||||
this.orientation = new Matrix3f();
|
||||
this.rotate(getYRot() - 180, getXRot(), 0);
|
||||
}
|
||||
this.orientation = update.apply(this.orientation);
|
||||
setYRot(this.getYaw());
|
||||
setXRot(this.getPitch());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldRoll() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return false;
|
||||
if (player.isHolding(Items.DIAMOND)) return true;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return false;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return false;
|
||||
|
||||
return pokemonEntity.getRiding().shouldRoll(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 rotationOnMouseXY(double yMouse,
|
||||
double xMouse,
|
||||
SmoothDouble yMouseSmoother,
|
||||
SmoothDouble xMouseSmoother,
|
||||
double sensitivity,
|
||||
double deltaTime )
|
||||
{
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return Vec3.ZERO;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return Vec3.ZERO;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return Vec3.ZERO;
|
||||
|
||||
//this is ridiculous. There likely needs to be some sort of mouseInfo class.
|
||||
return pokemonEntity.getRiding().rotationOnMouseXY
|
||||
(
|
||||
pokemonEntity,
|
||||
player,
|
||||
yMouse,
|
||||
xMouse,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAngVelSmoothing() {
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return true;
|
||||
if (player.isHolding(Items.DIAMOND)) return false;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return true;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return true;
|
||||
|
||||
return pokemonEntity.getRiding().useAngVelSmoothing(pokemonEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3 angRollVel( double deltaTime ) {
|
||||
var ret = new Vec3(0.0, 0.0, 0.0);
|
||||
LocalPlayer player = Minecraft.getInstance().player;
|
||||
if (!this.equals(player)) return ret;
|
||||
|
||||
var playerVehicle = player.getVehicle();
|
||||
if (playerVehicle == null) return ret;
|
||||
if (!(playerVehicle instanceof PokemonEntity pokemonEntity)) return ret;
|
||||
|
||||
return pokemonEntity.getRiding().angRollVel( pokemonEntity, player, deltaTime );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void clearRotation() {
|
||||
this.orientation = null;
|
||||
}
|
||||
|
||||
@WrapOperation(
|
||||
method = "rideTick()V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Player;wantsToStopRiding()Z")
|
||||
)
|
||||
public boolean delegateDismountToController(Player instance, Operation<Boolean> original) {
|
||||
if (this.getVehicle() instanceof Rideable vehicle) {
|
||||
return vehicle.getRiding().dismountOnShift() && original.call(instance);
|
||||
}
|
||||
return original.call(instance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,14 +9,10 @@
|
||||
package com.cobblemon.mod.common.mixin;
|
||||
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon;
|
||||
import com.cobblemon.mod.common.client.render.player.MountedPlayerRenderer;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.player.AbstractClientPlayer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -24,21 +20,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerRenderer.class)
|
||||
public class PlayerRendererMixin {
|
||||
@Inject(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", at = @At(value = "TAIL"))
|
||||
public void cobblemon$clientPlayerIcon(LivingEntity entity, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource buffer, int packedLight, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer((Player) entity);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "setupRotations(Lnet/minecraft/client/player/AbstractClientPlayer;Lcom/mojang/blaze3d/vertex/PoseStack;FFFF)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void cobblemon$modifyRoll(AbstractClientPlayer player, PoseStack poseStack, float a, float b, float partialTicks, float i, CallbackInfo ci) {
|
||||
if (player.isPassenger()) {
|
||||
var vehicle = player.getVehicle();
|
||||
if (vehicle instanceof PokemonEntity entity) {
|
||||
MountedPlayerRenderer.INSTANCE.render(player, entity, poseStack, a, b, partialTicks, i);
|
||||
}
|
||||
}
|
||||
@Inject(method = "render", at = @At(value = "TAIL"))
|
||||
public void renderPlayer(AbstractClientPlayer player, float f, float g, PoseStack poseStack, MultiBufferSource multiBufferSource, int i, CallbackInfo ci) {
|
||||
ClientPlayerIcon.Companion.onRenderPlayer(player);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork;
|
||||
import com.cobblemon.mod.common.Rollable;
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.joml.Matrix3f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class LocalPlayerMixin {
|
||||
|
||||
@Unique Matrix3f cobblemon$lastOrientation;
|
||||
|
||||
@Inject(method = "sendPosition", at = @At("TAIL"))
|
||||
private void cobblemon_updateRotationMatrix(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientPacketListener;send(Lnet/minecraft/network/protocol/Packet;)V"))
|
||||
private void cobblemon_updateRotationMatrixPassenger(CallbackInfo ci) {
|
||||
if (!(this instanceof Rollable rollable)) return;
|
||||
if (rollable.getOrientation() == cobblemon$lastOrientation) return;
|
||||
cobblemon$lastOrientation = rollable.getOrientation() != null ? new Matrix3f(rollable.getOrientation()) : null;
|
||||
CobblemonNetwork.INSTANCE.sendToServer(new C2SUpdateOrientationPacket(rollable.getOrientation()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.client;
|
||||
import com.cobblemon.mod.common.api.riding.Rideable;
|
||||
import com.cobblemon.mod.common.api.riding.RidingManager;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(PlayerModel.class)
|
||||
public class PlayerModelMixin {
|
||||
@Inject(method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", at = @At(value = "HEAD"))
|
||||
private void cobblemon$setHeadRotation(LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci){
|
||||
if (!(entity instanceof Player)) return;
|
||||
Entity vehicle = entity.getVehicle();
|
||||
|
||||
if (!(vehicle instanceof PokemonEntity)) return;
|
||||
RidingManager ridingManager = ((Rideable) vehicle).getRiding();
|
||||
if (ridingManager.shouldRotatePlayerHead((PokemonEntity) vehicle)) return;
|
||||
|
||||
netHeadYaw = 0f;
|
||||
headPitch = 0f;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.entity;
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(Entity.class)
|
||||
public abstract class EntityMixin {
|
||||
|
||||
@Shadow @Nullable public abstract Entity getVehicle();
|
||||
|
||||
@Inject(method = "updateInWaterStateAndDoWaterCurrentPushing", at = @At(value = "FIELD", target = "Lnet/minecraft/world/entity/Entity;wasTouchingWater:Z", ordinal = 1), cancellable = true)
|
||||
public void cobblemon$verifyActuallyTouchingWater(CallbackInfo ci) {
|
||||
if(this.getVehicle() instanceof PokemonEntity) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.renderer;
|
||||
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
/**
|
||||
* @author landonjw
|
||||
*/
|
||||
@Mixin(LivingEntityRenderer.class)
|
||||
public abstract class LivingEntityRendererMixin {
|
||||
// @Redirect(
|
||||
// method = "render(Lnet/minecraft/entity/LivingEntity;FFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V",
|
||||
// at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;hasVehicle()Z"),
|
||||
// slice = @Slice(
|
||||
// from = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;lerpAngleDegrees(FFF)F"),
|
||||
// to = @At(value = "TAIL")
|
||||
// )
|
||||
// )
|
||||
// private boolean dodgeRenderer(LivingEntity instance) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/*@WrapOperation(
|
||||
method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
|
||||
at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Mth;wrapDegrees(F)F")
|
||||
)
|
||||
private float replaceWrapValue(float angle, Operation<Float> original){
|
||||
if(origin){
|
||||
return 0f;
|
||||
} else {
|
||||
return original.call(angle);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.mixin.riding;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class JetMixin {
|
||||
|
||||
@Shadow private int jumpRidingTicks;
|
||||
@Shadow private float jumpRidingScale;
|
||||
|
||||
private float jetStrength;
|
||||
|
||||
// @Redirect(method = "tickMovement", at = @At(target = "Lnet/minecraft/entity/JumpingMount;getJumpCooldown()I", value = "INVOKE"))
|
||||
// public int cobblemon$tryHandlingJet(JumpingMount mount) {
|
||||
// if(mount instanceof PokemonEntity pokemon) {
|
||||
//// if(pokemon.getDataTracker().get(PokemonEntity.MOVING)) {
|
||||
//// ++this.field_3938;
|
||||
//// if (this.field_3938 < 11) {
|
||||
//// this.jetStrength = (float) this.field_3938 * 0.1F;
|
||||
//// } else {
|
||||
// this.mountJumpStrength = 0.8F + 2.0F / (float) (this.field_3938 - 9) * 0.1F;
|
||||
//// }
|
||||
//// } else {
|
||||
//// this.field_3938 = 0;
|
||||
//// this.jetStrength = 0;
|
||||
//// }
|
||||
//
|
||||
//// return -1;
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
@Inject(
|
||||
method = "aiStep",
|
||||
at = @At(
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;jumpRidingScale:F",
|
||||
value = "FIELD",
|
||||
ordinal = 4,
|
||||
shift = At.Shift.AFTER
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
||||
)
|
||||
public void cobblemon$applyCachedJumpStrength(CallbackInfo ci) {
|
||||
this.jumpRidingScale = this.jetStrength;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,14 +12,6 @@ object CobblemonBuildDetails {
|
||||
const val BRANCH = "{{ branch | default("Not Specified") }}"
|
||||
|
||||
fun smallCommitHash(): String {
|
||||
if(this.GIT_COMMIT.equals("Not Specified")) {
|
||||
return "Unknown"
|
||||
}
|
||||
|
||||
return this.GIT_COMMIT.substring(0, 7)
|
||||
}
|
||||
|
||||
fun version(): String {
|
||||
return this.VERSION + if(this.SNAPSHOT) "+${this.smallCommitHash()}" else ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ object CobblemonBlockEntities : PlatformRegistry<Registry<BlockEntityType<*>>, R
|
||||
@JvmField
|
||||
val PC: BlockEntityType<PCBlockEntity> = this.create("pc", BlockEntityType.Builder.of(::PCBlockEntity, CobblemonBlocks.PC).build(null))
|
||||
|
||||
@JvmField
|
||||
val STADIUM: BlockEntityType<StadiumBlockEntity> = this.create("stadium_terminal", BlockEntityType.Builder.of(::StadiumBlockEntity, CobblemonBlocks.STADIUM).build(null))
|
||||
|
||||
@JvmField
|
||||
val LECTERN: BlockEntityType<LecternBlockEntity> = this.create("lectern", BlockEntityType.Builder.of(::LecternBlockEntity, CobblemonBlocks.LECTERN).build(null))
|
||||
|
||||
|
||||
@@ -354,6 +354,9 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val PC = create("pc", PCBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F).noOcclusion().lightLevel { if ((it.getValue(PCBlock.ON) as Boolean) && (it.getValue(PCBlock.PART) == PCBlock.PCPart.TOP)) 10 else 0 }))
|
||||
|
||||
@JvmField
|
||||
val STADIUM = create("stadium_terminal", StadiumBlock(BlockBehaviour.Properties.of().mapColor(MapColor.METAL).sound(SoundType.METAL).pushReaction(PushReaction.BLOCK).strength(2F)))
|
||||
|
||||
@JvmField
|
||||
val LECTERN = create("lectern", LecternBlock(BlockBehaviour.Properties.of().mapColor(MapColor.WOOD).instrument(NoteBlockInstrument.BASS).sound(SoundType.WOOD).strength(2.5F).ignitedByLava()))
|
||||
|
||||
|
||||
@@ -272,6 +272,8 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val PC = blockItem("pc", CobblemonBlocks.PC)
|
||||
@JvmField
|
||||
val STADIUM = blockItem("stadium_terminal", CobblemonBlocks.STADIUM)
|
||||
@JvmField
|
||||
val PASTURE = blockItem("pasture", CobblemonBlocks.PASTURE)
|
||||
@JvmField
|
||||
val DISPLAY_CASE = blockItem("display_case", CobblemonBlocks.DISPLAY_CASE)
|
||||
|
||||
@@ -47,14 +47,7 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.*
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
@@ -94,41 +87,17 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
@@ -139,7 +108,6 @@ import com.cobblemon.mod.common.net.messages.server.callback.partymove.PartyPoke
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.EscapeDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.PasturePokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpastureAllPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPacket
|
||||
@@ -153,22 +121,19 @@ import com.cobblemon.mod.common.net.messages.server.storage.SwapPCPartyPokemonPa
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePCPokemonToPartyPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.MovePartyPokemonToPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.PCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.ReleasePCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.RequestRenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SortPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.SwapPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.UnlinkPlayerFromPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectCancelledHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.callback.move.MoveSelectedHandler
|
||||
@@ -180,7 +145,6 @@ import com.cobblemon.mod.common.net.serverhandling.dialogue.EscapeDialogueHandle
|
||||
import com.cobblemon.mod.common.net.serverhandling.dialogue.InputToDialogueHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.evolution.AcceptEvolutionHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.npc.SaveNPCHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.orientation.OrientationPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.PasturePokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpastureAllPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandler
|
||||
@@ -198,12 +162,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.MovePartyPokemo
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -216,11 +175,13 @@ import net.minecraft.server.level.ServerPlayer
|
||||
* @since November 27th, 2021
|
||||
*/
|
||||
object CobblemonNetwork {
|
||||
//private val logger = LogUtils.getLogger()
|
||||
|
||||
fun ServerPlayer.sendPacket(packet: NetworkPacket<*>) {
|
||||
sendPacketToPlayer(this, packet)
|
||||
}
|
||||
fun sendToServer(packet: NetworkPacket<*>) {
|
||||
//logger.info("[C->S] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendToServer(packet)
|
||||
}
|
||||
fun sendToAllPlayers(packet: NetworkPacket<*>) = sendPacketToPlayers(server()!!.playerList.players, packet)
|
||||
@@ -494,13 +455,11 @@ object CobblemonNetwork {
|
||||
// NPC packets
|
||||
list.add(PacketRegisterInfo(SaveNPCPacket.ID, SaveNPCPacket::decode, SaveNPCHandler))
|
||||
|
||||
// Orientation packet(s)
|
||||
list.add(PacketRegisterInfo(C2SUpdateOrientationPacket.ID, C2SUpdateOrientationPacket::decode, OrientationPacketHandler))
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
fun sendPacketToPlayer(player: ServerPlayer, packet: NetworkPacket<*>) {
|
||||
//logger.info("[S->C] ${packet.type()}")
|
||||
Cobblemon.implementation.networkManager.sendPacketToPlayer(player, packet)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,12 @@ package com.cobblemon.mod.common.api.berry
|
||||
* @author Licious
|
||||
* @since November 28th, 2022
|
||||
*/
|
||||
enum class Flavor(val colour: Int) {
|
||||
SPICY(0x00FF00),
|
||||
DRY(0xFF0000),
|
||||
SWEET(0x0000FF),
|
||||
BITTER(0xFFFF00),
|
||||
SOUR(0xFF00FF);
|
||||
enum class Flavor {
|
||||
|
||||
SPICY,
|
||||
DRY,
|
||||
SWEET,
|
||||
BITTER,
|
||||
SOUR
|
||||
|
||||
}
|
||||
@@ -11,8 +11,6 @@ package com.cobblemon.mod.common.api.entity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.Entity.MoveFunction
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
interface PokemonSideDelegate : EntitySideDelegate<PokemonEntity> {
|
||||
|
||||
@@ -52,7 +52,6 @@ import com.cobblemon.mod.common.api.reactive.EventObservable
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.filter
|
||||
import com.cobblemon.mod.common.api.reactive.Observable.Companion.map
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -254,12 +253,4 @@ object CobblemonEvents {
|
||||
val HATCH_EGG_PRE = CancelableObservable<HatchEggEvent.Pre>()
|
||||
@JvmField
|
||||
val HATCH_EGG_POST = EventObservable<HatchEggEvent.Post>()
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
//
|
||||
// Riding
|
||||
//
|
||||
// -------------------------------------------------------------------------------------
|
||||
@JvmField
|
||||
val SELECT_DRIVER = EventObservable<SelectDriverEvent>()
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokemon
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityPool
|
||||
import com.cobblemon.mod.common.api.abilities.AbilityTemplate
|
||||
@@ -33,7 +32,6 @@ import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.spawning.TimeRange
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.adapters.ElementalTypeAdapter
|
||||
@@ -47,7 +45,6 @@ import com.cobblemon.mod.common.pokemon.evolution.adapters.CobblemonRequirementA
|
||||
import com.cobblemon.mod.common.pokemon.evolution.adapters.LegacyItemConditionWrapperAdapter
|
||||
import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.util.adapters.*
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.HashBasedTable
|
||||
import com.google.gson.Gson
|
||||
@@ -56,7 +53,6 @@ import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.advancements.critereon.ItemPredicate
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
@@ -97,7 +93,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(DropEntry::class.java, DropEntryAdapter)
|
||||
.registerTypeAdapter(CompoundTag::class.java, NbtCompoundAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Biome::class.java).type, BiomeLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Block::class.java).type, BlockLikeConditionAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(RegistryLikeCondition::class.java, Item::class.java).type, ItemLikeConditionAdapter)
|
||||
@@ -105,8 +100,6 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
.registerTypeAdapter(EggGroup::class.java, EggGroupAdapter)
|
||||
.registerTypeAdapter(MobEffect::class.java, RegistryElementAdapter<MobEffect>(BuiltInRegistries::MOB_EFFECT))
|
||||
.registerTypeAdapter(ItemPredicate::class.java, LegacyItemConditionWrapperAdapter)
|
||||
.registerTypeAdapter(RideController::class.java, RideControllerAdapter)
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.disableHtmlEscaping()
|
||||
.enableComplexMapKeySerialization()
|
||||
.create()
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import net.minecraft.world.entity.PlayerRideableJumping
|
||||
|
||||
/**
|
||||
* Represents an entity that supports riding.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
interface Rideable : PlayerRideableJumping {
|
||||
|
||||
/**
|
||||
* Denotes the manager responsible for handling any instance of riding taking place on an entity
|
||||
*/
|
||||
val riding: RidingManager
|
||||
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.sin
|
||||
|
||||
data class RidingManager(val entity: PokemonEntity) {
|
||||
var lastSpeed = 0F
|
||||
var states: MutableMap<ResourceLocation, RidingState> = mutableMapOf()
|
||||
var deltaRotation = Vec2.ZERO
|
||||
|
||||
val runtime: MoLangRuntime by lazy {
|
||||
MoLangRuntime()
|
||||
.setup()
|
||||
.withQueryValue("entity", entity.struct)
|
||||
.also {
|
||||
it.environment.query.addFunction("passenger_count") { DoubleValue(entity.passengers.size.toDouble()) }
|
||||
}
|
||||
}
|
||||
|
||||
fun <T : RidingState> getState(id: ResourceLocation, constructor: (PokemonEntity) -> T): T {
|
||||
val storedState = states[id]
|
||||
if (storedState == null) {
|
||||
val newState = constructor(entity)
|
||||
states[id] = newState
|
||||
return newState
|
||||
}
|
||||
|
||||
return storedState as T
|
||||
}
|
||||
|
||||
fun getController(entity: PokemonEntity): RideController? {
|
||||
return entity.pokemon.riding.controller?.takeIf { it.condition.invoke(entity) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for handling riding conditions and transitions amongst controllers. This will tick
|
||||
* whenever the entity receives a tickControlled interaction.
|
||||
*/
|
||||
fun tick(entity: PokemonEntity, driver: Player, input: Vec3) {
|
||||
val controller = getController(entity) ?: return
|
||||
|
||||
val pose = controller.pose(entity)
|
||||
entity.entityData.set(PokemonEntity.POSE_TYPE, pose)
|
||||
//val speedPlayer = driver.deltaMovement.horizontalDistance()
|
||||
//driver.displayClientMessage(Component.literal("Speed player: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("$speedPlayer b/t")), true)
|
||||
//val speedEntity = entity.deltaMovement.length() //* 20 * 60 * 60) / ( 1000 )
|
||||
//println(speedEntity)
|
||||
//driver.displayClientMessage(Component.literal("Speed: ").withStyle { it.withColor(ChatFormatting.GREEN) }.append(Component.literal("${String.format("%.2f", speedEntity)} km/h")), true)
|
||||
|
||||
}
|
||||
|
||||
fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
val controller = getController(entity) ?: return 0.05F
|
||||
this.lastSpeed = controller.speed(entity, driver)
|
||||
return this.lastSpeed
|
||||
}
|
||||
|
||||
fun controlledRotation(entity: PokemonEntity, driver: Player): Vec2 {
|
||||
val controller = getController(entity) ?: return entity.rotationVector
|
||||
val previousRotation = entity.rotationVector
|
||||
val rotation = controller.rotation(entity, driver)
|
||||
this.deltaRotation = Vec2(rotation.x - previousRotation.x, rotation.y - previousRotation.y)
|
||||
return rotation
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.clampPassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val controller = getController(entity) ?: return
|
||||
return controller.updatePassengerRotation(entity, driver)
|
||||
}
|
||||
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
fun fuelBar(entity: PokemonEntity, driver: Player): Float {
|
||||
val controller = getController(entity) ?: return 0.0f
|
||||
return controller.fuelBar(entity, driver)
|
||||
}
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.canJump(entity, driver)
|
||||
}
|
||||
|
||||
fun jumpVelocity(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to supply the dela for the lerp() between velocity
|
||||
* vectors. Called inertia for now as the way it feels when
|
||||
* affecting the ride is somewhat akin to inertia.
|
||||
*/
|
||||
fun inertia(entity: PokemonEntity): Double {
|
||||
val controller = getController(entity) ?: return 0.5
|
||||
return controller.inertia(entity)
|
||||
}
|
||||
|
||||
//Can be accomplished through the velocity controls
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
val controller = getController(entity) ?: return null
|
||||
return controller.gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
//Maybe should be changed to be a function that conveys:
|
||||
// "turn on use our camera system function"
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRoll(entity)
|
||||
}
|
||||
|
||||
fun shouldRotatePlayerHead(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRotatePlayerHead()
|
||||
}
|
||||
|
||||
fun shouldRotatePokemonHead(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.shouldRotatePokemonHead()
|
||||
}
|
||||
|
||||
//this is called just as often as
|
||||
fun rotationOnMouseXY
|
||||
( entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
val controller = getController(entity) ?: return Vec3.ZERO
|
||||
return controller.rotationOnMouseXY( entity,
|
||||
driver,
|
||||
yMouse,
|
||||
xMouse,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime )
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether mouse input will affect the rotation of
|
||||
* the rollable object. Need to remove this as it's not used anymore
|
||||
*/
|
||||
//I think this might better serve as a "use smoothing on angular velocity"useAngVelSmoothing
|
||||
fun useAngVelSmoothing(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return true
|
||||
return controller.useAngVelSmoothing(entity)
|
||||
}
|
||||
|
||||
fun turnOffOnGround(entity: PokemonEntity): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.turnOffOnGround(entity)
|
||||
}
|
||||
|
||||
fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
val controller = getController(entity) ?: return Vec3(0.0, 0.0, 0.0)
|
||||
return controller.angRollVel(entity, driver, deltaTime)
|
||||
}
|
||||
|
||||
fun dismountOnShift(): Boolean {
|
||||
val controller = getController(entity) ?: return false
|
||||
return controller.dismountOnShift(entity)
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinitions
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingProperties(
|
||||
val stats: Map<RidingStat, RidingStatDefinitions> = mapOf(),
|
||||
val seats: List<Seat> = listOf(),
|
||||
val conditions: List<Expression> = listOf(),
|
||||
val controller: RideController? = null
|
||||
) {
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingProperties {
|
||||
val stats: Map<RidingStat, RidingStatDefinitions> = buffer.readMap(
|
||||
{ buffer.readEnum<RidingStat>(RidingStat::class.java) },
|
||||
{ RidingStatDefinitions.decode(buffer) }
|
||||
)
|
||||
val seats: List<Seat> = buffer.readList { _ -> Seat.decode(buffer) }
|
||||
val conditions = buffer.readList { buffer.readString().asExpression() }
|
||||
val controller = buffer.readNullable { _ ->
|
||||
val key = buffer.readIdentifier()
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
return@readNullable controller
|
||||
}
|
||||
|
||||
return RidingProperties(stats = stats, seats = seats, conditions = conditions, controller = controller)
|
||||
}
|
||||
}
|
||||
|
||||
val canRide: Boolean
|
||||
get() = seats.isNotEmpty() && controller != null
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeMap(
|
||||
stats,
|
||||
{ _, stat -> buffer.writeEnum(stat) },
|
||||
{ _, stat -> stat.encode(buffer) }
|
||||
)
|
||||
buffer.writeCollection(seats) { _, seat -> seat.encode(buffer) }
|
||||
buffer.writeCollection(conditions) { _, condition -> buffer.writeString(condition.getString()) }
|
||||
buffer.writeNullable(controller) { _, controller -> controller.encode(buffer) }
|
||||
}
|
||||
|
||||
fun calculate(stat: RidingStat, style: RidingStyle, boosts: Int): Float {
|
||||
val definitions = stats[stat] ?: return 0F
|
||||
return definitions.calculate(style, boosts)
|
||||
}
|
||||
|
||||
fun hasStat(stat: RidingStat, style: RidingStyle): Boolean {
|
||||
return stats[stat]?.ranges?.containsKey(style) == true
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
/**
|
||||
* Honestly having a base interface is probably unnecessary I'm just considering whether there's going to be some
|
||||
* kind of shared state later.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since October 6th, 2024
|
||||
*/
|
||||
interface RidingState
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
/**
|
||||
* A general medium for riding. Mainly used for categorizing which stats to pull from and for
|
||||
* presenting a simplified view of riding to users.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
enum class RidingStyle {
|
||||
LAND,
|
||||
LIQUID,
|
||||
AIR
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RidingAnimation
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Seat Properties are responsible for the base information that would then be used to construct a Seat on an entity.
|
||||
*/
|
||||
data class Seat(
|
||||
val locator: String = "seat_1",
|
||||
val offset: Vec3 = Vec3.ZERO,
|
||||
val poseOffsets: MutableList<SeatPoseOffset> = mutableListOf(),
|
||||
val poseAnimations: MutableList<SeatPoseAnimations> = mutableListOf()
|
||||
) : Encodable {
|
||||
fun getOffset(poseType: PoseType) : Vec3 {
|
||||
return poseOffsets.firstOrNull { poseType in it.poseTypes }?.offset ?: offset
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(locator)
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
buffer.writeCollection(poseOffsets) { _, offset -> offset.encode(buffer) }
|
||||
buffer.writeCollection(poseAnimations) { _, animations -> animations.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : Seat {
|
||||
return Seat(
|
||||
buffer.readString(),
|
||||
Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()),
|
||||
buffer.readList { SeatPoseOffset.decode(buffer) },
|
||||
buffer.readList { SeatPoseAnimations.decode(buffer) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseOffset {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var offset = Vec3.ZERO
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeDouble(offset.x)
|
||||
buffer.writeDouble(offset.y)
|
||||
buffer.writeDouble(offset.z)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseOffset {
|
||||
val offset = SeatPoseOffset()
|
||||
offset.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
offset.offset = Vec3(buffer.readDouble(), buffer.readDouble(), buffer.readDouble())
|
||||
return offset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeatPoseAnimations {
|
||||
val poseTypes = mutableSetOf<PoseType>()
|
||||
var animations = mutableListOf<RidingAnimation>()
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeCollection(poseTypes) { _, poseType -> buffer.writeString(poseType.name) }
|
||||
buffer.writeCollection(animations) { _, animation -> animation.encode(buffer) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : SeatPoseAnimations {
|
||||
val animations = SeatPoseAnimations()
|
||||
animations.poseTypes.addAll(buffer.readList { buffer.readString().let { PoseType.valueOf(it) } })
|
||||
animations.animations = buffer.readList { RidingAnimation.decode(buffer) }
|
||||
return animations
|
||||
}
|
||||
}
|
||||
}
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.net.Decodable
|
||||
import com.cobblemon.mod.common.api.net.Encodable
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* A riding controller is the internal control mechanism for determining how a pokemon
|
||||
* handles during riding. Controllers come into play once the pokemon being ridden has
|
||||
* established the path it's capable of. For instance, a land based controller could have
|
||||
* the pokemon experience drifting after movement, or generic movement. It's up to the
|
||||
* controller to decide how the pokemon behaves.
|
||||
*
|
||||
* @since x.x.x
|
||||
*/
|
||||
interface RideController : Encodable, Decodable {
|
||||
|
||||
/** A reference key used to denote the individual controller */
|
||||
val key: ResourceLocation
|
||||
|
||||
/**
|
||||
* Specifies the provider of poses which helps control updating the current pose on the pokemon
|
||||
* being ridden. Controllers are expected to define the pose types responsible for posing the entity
|
||||
* through all expected conditions. It should define a default pose, that will be used in all cases
|
||||
* where a pose does not meet the current conditions for the current mount. Typically, this will be
|
||||
* an idle pose.
|
||||
*/
|
||||
val poseProvider: PoseProvider
|
||||
|
||||
/**
|
||||
* Represents a condition that must be met for this controller to be active. For instance, this can be used
|
||||
* to evaluate things such as current velocity or block state of the entity.
|
||||
*/
|
||||
val condition: (PokemonEntity) -> Boolean
|
||||
|
||||
/**
|
||||
* Specifies the pose the ridden mount should be positioned in. This queries the pose provider using
|
||||
* the entity as a means of determining the conditions the entity is currently under. This allows for
|
||||
* dynamic pose updates.
|
||||
*/
|
||||
fun pose(entity: PokemonEntity) : PoseType {
|
||||
return this.poseProvider.select(entity)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the current speed of the mount.
|
||||
*/
|
||||
fun speed(entity: PokemonEntity, driver: Player) : Float
|
||||
|
||||
/**
|
||||
* Sets the rotation of the mount. This is typically based on the controlling driver and is manipulated as
|
||||
* necessary.
|
||||
*/
|
||||
fun rotation(entity: PokemonEntity, driver: LivingEntity) : Vec2
|
||||
|
||||
/**
|
||||
* Sets the change current change in rotation for that tick in three
|
||||
* dimensions
|
||||
*/
|
||||
fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {}
|
||||
|
||||
fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
driver.yRot = entity.yRot
|
||||
}
|
||||
|
||||
/**
|
||||
* Manipulates the movement input as necessary by the controller. This is primarily used to apply limits
|
||||
* to the types of movements. For instance, we can apply limits to any sort of sideways movement input, so that
|
||||
* it would otherwise be slower than normal forward movement.
|
||||
*/
|
||||
fun velocity(entity: PokemonEntity, driver: Player, input: Vec3) : Vec3
|
||||
|
||||
fun fuelBar(entity: PokemonEntity, driver: Player): Float = 0.0f
|
||||
|
||||
fun canJump(entity: PokemonEntity, driver: Player) : Boolean
|
||||
|
||||
fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int) : Vec3
|
||||
|
||||
fun gravity(entity: PokemonEntity, regularGravity: Double) : Double? = null
|
||||
|
||||
fun inertia(entity: PokemonEntity ) : Double = 0.5
|
||||
|
||||
fun shouldRoll(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun useAngVelSmoothing(entity: PokemonEntity): Boolean = false
|
||||
|
||||
//If function is not overwritten by controllers then just perform the defualt
|
||||
//rolling function which is roll on mousex and pitch on mousey
|
||||
fun rotationOnMouseXY
|
||||
(entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
if(driver !is Rollable) return Vec3.ZERO
|
||||
|
||||
//Might need to add the somothing here for default.
|
||||
val rollable = driver as Rollable
|
||||
return Vec3(0.0, yMouse, xMouse )
|
||||
}
|
||||
|
||||
fun turnOffOnGround(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun dismountOnShift(entity: PokemonEntity): Boolean = false
|
||||
|
||||
fun getRuntime(entity: PokemonEntity) = entity.riding.runtime
|
||||
|
||||
fun shouldRotatePokemonHead(): Boolean = false
|
||||
fun shouldRotatePlayerHead(): Boolean = false
|
||||
|
||||
fun <T : RidingState> getState(entity: PokemonEntity, constructor: (PokemonEntity) -> T): T {
|
||||
return entity.riding.getState(key, constructor)
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(this.key)
|
||||
}
|
||||
}
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller
|
||||
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class RidingAnimation(
|
||||
val fileName: String,
|
||||
val animationName: String
|
||||
) {
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeString(fileName)
|
||||
buffer.writeString(animationName)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) : RidingAnimation {
|
||||
return RidingAnimation(
|
||||
buffer.readString(),
|
||||
buffer.readString()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import java.util.function.Predicate
|
||||
|
||||
data class PoseOption(val pose: PoseType, val condition: Predicate<PokemonEntity>)
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.controller.posing
|
||||
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
class PoseProvider(private val fallback: PoseType) {
|
||||
|
||||
private val options = mutableListOf<PoseOption>()
|
||||
|
||||
fun select(entity: PokemonEntity) : PoseType {
|
||||
return this.options.stream()
|
||||
.filter { it.condition.test(entity) }
|
||||
.map { it.pose }
|
||||
.findFirst()
|
||||
.orElse(this.fallback)
|
||||
}
|
||||
|
||||
fun with(option: PoseOption) : PoseProvider {
|
||||
this.options.add(option)
|
||||
return this
|
||||
}
|
||||
|
||||
}
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.events
|
||||
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
data class SelectDriverEvent(val options: Set<LivingEntity>) {
|
||||
|
||||
private var result: DriverSuggestion? = null
|
||||
|
||||
fun result(): LivingEntity? {
|
||||
return this.result?.entity
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests a particular living entity as a potential driver. Only non-negative
|
||||
* values are permitted by this function. All priority values with lesser priorities
|
||||
* will be outright ignored.
|
||||
*/
|
||||
fun suggest(target: LivingEntity, priority: Int) {
|
||||
if (priority >= 0 && priority > (this.result?.priority ?: -1)) {
|
||||
this.result = DriverSuggestion(target, priority)
|
||||
}
|
||||
}
|
||||
|
||||
data class DriverSuggestion(val entity: LivingEntity, val priority: Int)
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.berry.Flavor
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* A stat that is used for riding Pokémon. The exact implementation of each of these depends on the [com.cobblemon.mod.common.api.riding.controller.RideController].
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
enum class RidingStat(
|
||||
val flavour: Flavor
|
||||
) {
|
||||
SPEED(Flavor.SWEET),
|
||||
ACCELERATION(Flavor.SPICY),
|
||||
SKILL(Flavor.DRY),
|
||||
JUMP(Flavor.BITTER),
|
||||
STAMINA(Flavor.SOUR);
|
||||
|
||||
companion object {
|
||||
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
|
||||
}
|
||||
|
||||
val displayName: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.name")
|
||||
val description: Component
|
||||
get() = lang("riding.stat.${name.lowercase()}.desc")
|
||||
}
|
||||
-68
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.stats
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.readText
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
/**
|
||||
* The definition of all the different information related to a specific [RidingStat] on a Pokémon species.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since February 17th, 2025
|
||||
*/
|
||||
class RidingStatDefinitions {
|
||||
/** A map from [RidingStyle] to a minimum and maximum value for this stat. */
|
||||
val ranges = mutableMapOf<RidingStyle, IntRange>()
|
||||
/** Display name for the stat, if null falls back to [RidingStat.displayName]. */
|
||||
var displayName: Component? = null
|
||||
/** Description for the stat, if null falls back to [RidingStat.description]. */
|
||||
var description: Component? = null
|
||||
|
||||
fun calculate(style: RidingStyle, aprijuiceBoost: Int): Float {
|
||||
val range = ranges[style] ?: ranges[RidingStyle.LAND] ?: return 0F
|
||||
val boostQuotient = aprijuiceBoost / 255F
|
||||
return range.first + (range.last - range.first) * boostQuotient
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeNullable(displayName) { _, it -> buffer.writeText(it) }
|
||||
buffer.writeNullable(description) { _, it -> buffer.writeText(it) }
|
||||
buffer.writeMap(
|
||||
ranges,
|
||||
{ _, it -> buffer.writeEnum(it) },
|
||||
{ _, it ->
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, it.first)
|
||||
buffer.writeSizedInt(IntSize.U_BYTE, it.last)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RidingStatDefinitions {
|
||||
val displayName = buffer.readNullable { buffer.readText() }
|
||||
val description = buffer.readNullable { buffer.readText() }
|
||||
val ranges = buffer.readMap<RidingStyle, IntRange>(
|
||||
{ buffer.readEnum<RidingStyle>(RidingStyle::class.java) },
|
||||
{ IntRange(buffer.readSizedInt(IntSize.U_BYTE), buffer.readSizedInt(IntSize.U_BYTE)) }
|
||||
)
|
||||
return RidingStatDefinitions().apply {
|
||||
this.displayName = displayName
|
||||
this.description = description
|
||||
this.ranges.putAll(ranges)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.spawning.rules.component
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.ast.BooleanExpression
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
import com.cobblemon.mod.common.api.spawning.detail.SpawnDetail
|
||||
@@ -34,7 +33,7 @@ class FilterRuleComponent : SpawnRuleComponent {
|
||||
|
||||
val spawnSelector: SpawnDetailSelector = AllSpawnDetailSelector
|
||||
val contextSelector: SpawningContextSelector = AllSpawningContextSelector
|
||||
val allow: Expression = BooleanExpression(false)
|
||||
val allow: Expression = BooleanExpression(true)
|
||||
|
||||
override fun affectSpawnable(detail: SpawnDetail, ctx: SpawningContext): Boolean {
|
||||
return if (spawnSelector.selects(detail) && contextSelector.selects(ctx)) {
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.level.block.state.StateDefinition
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
|
||||
class StadiumBlock(properties: Properties): BaseEntityBlock(properties) {
|
||||
companion object {
|
||||
val CODEC = simpleCodec(::StadiumBlock)
|
||||
}
|
||||
|
||||
init {
|
||||
registerDefaultState(stateDefinition.any().setValue(HorizontalDirectionalBlock.FACING, Direction.NORTH))
|
||||
}
|
||||
|
||||
override fun codec() = CODEC
|
||||
|
||||
override fun newBlockEntity(pos: BlockPos, state: BlockState): BlockEntity {
|
||||
return StadiumBlockEntity(pos, state)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(blockPlaceContext: BlockPlaceContext): BlockState {
|
||||
return this.defaultBlockState().setValue(HorizontalDirectionalBlock.FACING, blockPlaceContext.horizontalDirection)
|
||||
}
|
||||
|
||||
override fun createBlockStateDefinition(builder: StateDefinition.Builder<Block, BlockState>) {
|
||||
builder.add(HorizontalDirectionalBlock.FACING)
|
||||
}
|
||||
|
||||
override fun rotate(blockState: BlockState, rotation: Rotation): BlockState {
|
||||
return blockState.setValue(
|
||||
HorizontalDirectionalBlock.FACING, rotation.rotate(blockState.getValue(
|
||||
HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun mirror(blockState: BlockState, mirror: Mirror): BlockState {
|
||||
return blockState.rotate(mirror.getRotation(blockState.getValue(HorizontalDirectionalBlock.FACING)))
|
||||
}
|
||||
|
||||
override fun onRemove(state: BlockState, world: Level, pos: BlockPos, newState: BlockState, moved: Boolean) {
|
||||
if (!state.`is`(newState.block)) super.onRemove(state, world, pos, newState, moved)
|
||||
}
|
||||
|
||||
//TODO: override getTicker
|
||||
|
||||
override fun getRenderShape(state: BlockState) = RenderShape.MODEL
|
||||
|
||||
override fun useWithoutItem(
|
||||
blockState: BlockState,
|
||||
world: Level,
|
||||
blockPos: BlockPos,
|
||||
player: Player,
|
||||
blockHitResult: BlockHitResult
|
||||
): InteractionResult {
|
||||
if (player !is ServerPlayer) return InteractionResult.SUCCESS
|
||||
|
||||
val blockEntity = world.getBlockEntity(blockPos)
|
||||
if (blockEntity !is StadiumBlockEntity) return InteractionResult.SUCCESS
|
||||
|
||||
// Toggle isInUse state
|
||||
blockEntity.isInUse = !blockEntity.isInUse
|
||||
|
||||
// debug
|
||||
val activateMessage = if (blockEntity.isInUse) "Stadium Activated!" else "Stadium Deactivated!"
|
||||
player.sendSystemMessage(text(activateMessage).red())
|
||||
|
||||
if (blockEntity.isInUse) {
|
||||
// Generate flight path when activated
|
||||
blockEntity.generateFlightPath(world, radiusX = 5.0, radiusZ = 3.0, height = 10.0, steps = 20)
|
||||
|
||||
} else {
|
||||
// Clear path when deactivated
|
||||
blockEntity.pathPoints.clear()
|
||||
}
|
||||
|
||||
val message = "Stadium Pos: " + blockEntity.blockPos +
|
||||
"\nPlayer 1 Pos: " + blockEntity.getPlayer1Pos() +
|
||||
"\nPoke 1 Pos: " + blockEntity.getPoke1Pos() +
|
||||
"\nPlayer 2 Pos: " + blockEntity.getPlayer2Pos() +
|
||||
"\nPoke 2 Pos: " + blockEntity.getPoke2Pos()
|
||||
player.sendSystemMessage(text(message).red())
|
||||
|
||||
blockEntity.setChanged()
|
||||
world.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS)
|
||||
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package com.cobblemon.mod.common.block.entity
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.network.protocol.Packet
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener
|
||||
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerLookAtPacket
|
||||
import net.minecraft.network.protocol.game.ClientboundSetCarriedItemPacket
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class StadiumBlockEntity(
|
||||
pos: BlockPos,
|
||||
blockState: BlockState
|
||||
): BlockEntity(
|
||||
CobblemonBlockEntities.STADIUM,
|
||||
pos,
|
||||
blockState
|
||||
) {
|
||||
var isInUse = false
|
||||
|
||||
val droneState = DroneState()
|
||||
|
||||
val pathPoints: MutableList<Vec3> = mutableListOf()
|
||||
|
||||
fun generateFlightPath(world: Level, radiusX: Double, radiusZ: Double, height: Double, steps: Int) {
|
||||
pathPoints.clear()
|
||||
|
||||
for (i in 0 until steps) {
|
||||
val angle = (i.toDouble() / steps) * Math.PI * 2
|
||||
val xOffset = radiusX * Math.cos(angle)
|
||||
val zOffset = radiusZ * Math.sin(angle)
|
||||
|
||||
val basePos = Vec3(blockPos.x + xOffset, blockPos.y + height, blockPos.z + zOffset)
|
||||
val adjustedPos = getValidPoint(world, basePos)
|
||||
|
||||
pathPoints.add(adjustedPos)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getValidPoint(world: Level, start: Vec3): Vec3 {
|
||||
val maxHeight = 40 // Max height for drone path
|
||||
val stepHeight = 1.0 // Step size for raycast
|
||||
|
||||
var adjustedHeight = start.y
|
||||
for (h in 0..maxHeight step stepHeight.toInt()) {
|
||||
val checkPos = BlockPos(start.x.toInt(), start.y.toInt() - h, start.z.toInt()) // Convert to BlockPos
|
||||
if (!world.getBlockState(checkPos).isAir) { // Check if block is solid
|
||||
return Vec3(start.x, start.y - h - 1, start.z) // Adjust position
|
||||
}
|
||||
}
|
||||
return start // No obstruction found
|
||||
}
|
||||
|
||||
|
||||
fun getPlayer1Pos(): BlockPos {
|
||||
return blockPos.north(10)
|
||||
}
|
||||
fun getPlayer2Pos(): BlockPos {
|
||||
return blockPos.south(10)
|
||||
}
|
||||
fun getPoke1Pos(): BlockPos {
|
||||
return blockPos.north(5)
|
||||
}
|
||||
fun getPoke2Pos(): BlockPos {
|
||||
return blockPos.south(5)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Saves data to NBT.
|
||||
*/
|
||||
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registries)
|
||||
|
||||
// Save the isInUse state
|
||||
tag.putBoolean("IsInUse", isInUse)
|
||||
|
||||
// Save path points
|
||||
val pathTag = ListTag()
|
||||
for (point in pathPoints) {
|
||||
val pointTag = CompoundTag()
|
||||
pointTag.putDouble("x", point.x)
|
||||
pointTag.putDouble("y", point.y)
|
||||
pointTag.putDouble("z", point.z)
|
||||
pathTag.add(pointTag)
|
||||
}
|
||||
tag.put("PathPoints", pathTag)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from NBT.
|
||||
*/
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
|
||||
// Load the isInUse state
|
||||
isInUse = tag.getBoolean("IsInUse")
|
||||
|
||||
// Load path points
|
||||
pathPoints.clear()
|
||||
val pathTag = tag.getList("PathPoints", 10) // 10 is the ID for CompoundTag
|
||||
for (i in 0 until pathTag.size) {
|
||||
val pointTag = pathTag.getCompound(i)
|
||||
val point = Vec3(pointTag.getDouble("x"), pointTag.getDouble("y"), pointTag.getDouble("z"))
|
||||
pathPoints.add(point)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getUpdatePacket(): Packet<ClientGamePacketListener>? {
|
||||
//println("getUpdatePacket called for NestBlockEntity at $blockPos with egg: $eggComponent")
|
||||
return ClientboundBlockEntityDataPacket.create(this)
|
||||
}
|
||||
|
||||
override fun getUpdateTag(registryLookup: HolderLookup.Provider): CompoundTag {
|
||||
val tag = saveWithoutMetadata(registryLookup)
|
||||
//println("getUpdateTag called for NestBlockEntity at $blockPos with tag: $tag")
|
||||
return tag
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -25,13 +25,7 @@ import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.entity.PokeBobberEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.generic.GenericBedrockRenderer
|
||||
@@ -256,7 +250,8 @@ object CobblemonClient {
|
||||
CobblemonBlocks.SKY_TUMBLESTONE_CLUSTER,
|
||||
CobblemonBlocks.GIMMIGHOUL_CHEST,
|
||||
CobblemonBlocks.DISPLAY_CASE,
|
||||
CobblemonBlocks.LECTERN
|
||||
CobblemonBlocks.LECTERN,
|
||||
CobblemonBlocks.STADIUM
|
||||
)
|
||||
|
||||
this.createBoatModelLayers()
|
||||
@@ -290,6 +285,7 @@ object CobblemonClient {
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.GILDED_CHEST, ::GildedChestBlockRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.DISPLAY_CASE, ::DisplayCaseRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.LECTERN, ::LecternBlockEntityRenderer)
|
||||
this.implementation.registerBlockEntityRenderer(CobblemonBlockEntities.STADIUM, ::StadiumBlockRenderer)
|
||||
}
|
||||
|
||||
private fun registerEntityRenderers() {
|
||||
|
||||
+1
-4
@@ -13,8 +13,8 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addEntityFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
@@ -42,11 +42,8 @@ import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
|
||||
class PokemonClientDelegate : PosableState(), PokemonSideDelegate {
|
||||
companion object {
|
||||
|
||||
+4
-21
@@ -21,18 +21,18 @@ import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.ArrayListMultimap
|
||||
import com.google.common.collect.Multimap
|
||||
import java.util.UUID
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import java.util.*
|
||||
import org.joml.Vector3f
|
||||
|
||||
fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canRide: Boolean): InteractWheelGUI {
|
||||
fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean): InteractWheelGUI {
|
||||
val mountShoulder = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_shoulder.png"),
|
||||
tooltipText = "cobblemon.ui.interact.mount.shoulder",
|
||||
onPress = {
|
||||
if (canMountShoulder) {
|
||||
InteractPokemonPacket(pokemonID, true, false).sendToServer()
|
||||
InteractPokemonPacket(pokemonID, true).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
}
|
||||
@@ -41,32 +41,15 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canRide
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_held_item.png"),
|
||||
tooltipText = "cobblemon.ui.interact.give.item",
|
||||
onPress = {
|
||||
InteractPokemonPacket(pokemonID, false, false).sendToServer()
|
||||
InteractPokemonPacket(pokemonID, false).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
)
|
||||
|
||||
val ride = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/icon_held_item.png"),
|
||||
tooltipText = "cobblemon.ui.interact.ride",
|
||||
onPress = {
|
||||
if (canRide) {
|
||||
InteractPokemonPacket(pokemonID, false, true).sendToServer()
|
||||
closeGUI()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val options: Multimap<Orientation, InteractWheelOption> = ArrayListMultimap.create()
|
||||
options.put(Orientation.TOP_RIGHT, giveItem)
|
||||
if(canRide) {
|
||||
options.put(Orientation.BOTTOM_LEFT, ride)
|
||||
}
|
||||
|
||||
if (canMountShoulder) {
|
||||
options.put(Orientation.TOP_LEFT, mountShoulder)
|
||||
}
|
||||
|
||||
CobblemonEvents.POKEMON_INTERACTION_GUI_CREATION.post(PokemonInteractionGUICreationEvent(pokemonID, canMountShoulder, options))
|
||||
return InteractWheelGUI(options, Component.translatable("cobblemon.ui.interact.pokemon"))
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,6 +15,6 @@ import net.minecraft.client.Minecraft
|
||||
|
||||
object InteractPokemonUIPacketHandler: ClientNetworkPacketHandler<InteractPokemonUIPacket> {
|
||||
override fun handle(packet: InteractPokemonUIPacket, client: Minecraft) {
|
||||
client.setScreen(createPokemonInteractGui(packet.pokemonID, packet.canMountShoulder, packet.canRide))
|
||||
client.setScreen(createPokemonInteractGui(packet.pokemonID, packet.canMountShoulder))
|
||||
}
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.block
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBlocks
|
||||
import com.cobblemon.mod.common.block.entity.StadiumBlockEntity
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.state.BlockState
|
||||
|
||||
class StadiumBlockRenderer(ctx: BlockEntityRendererProvider.Context) : BlockEntityRenderer<StadiumBlockEntity> {
|
||||
val context = RenderContext().also {
|
||||
it.put(RenderContext.DO_QUIRKS, false)
|
||||
it.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
|
||||
}
|
||||
|
||||
private var pathIndex = 0
|
||||
private var animationTime = 0.0
|
||||
private val droneSpeed = 0.10
|
||||
|
||||
override fun render(
|
||||
blockEntity: StadiumBlockEntity,
|
||||
tickDelta: Float,
|
||||
poseStack: PoseStack,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
overlay: Int
|
||||
) {
|
||||
val blockState = blockEntity.blockState
|
||||
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
|
||||
|
||||
val isClientSide = blockEntity.level?.isClientSide == true
|
||||
if (!isClientSide) return
|
||||
|
||||
val stadiumBlockState = blockEntity.level?.getBlockState(blockEntity.blockPos) ?: return
|
||||
if (stadiumBlockState.block != CobblemonBlocks.STADIUM) {
|
||||
return
|
||||
}
|
||||
|
||||
val droneState = blockEntity.droneState
|
||||
|
||||
|
||||
poseStack.pushPose()
|
||||
if (blockEntity.isInUse) {
|
||||
if (blockEntity.pathPoints.isEmpty()) {
|
||||
|
||||
poseStack.popPose()
|
||||
return
|
||||
}
|
||||
|
||||
spawnDebugParticles(blockEntity) // debug particles
|
||||
|
||||
// Center the drone at the block's center
|
||||
poseStack.translate(0.5, -3.0, 0.5)
|
||||
//poseStack.mulPose(Axis.XP.rotationDegrees(180F))
|
||||
//poseStack.mulPose(Axis.YP.rotationDegrees(180F))
|
||||
|
||||
val points = blockEntity.pathPoints
|
||||
val nextIndex = (pathIndex + 1) % points.size
|
||||
|
||||
val currentPoint = points[pathIndex]
|
||||
val nextPoint = points[nextIndex]
|
||||
|
||||
animationTime += tickDelta * droneSpeed
|
||||
if (animationTime >= 1.0) {
|
||||
animationTime = 0.0
|
||||
pathIndex = nextIndex
|
||||
}
|
||||
|
||||
val interpolatedPos = currentPoint.lerp(nextPoint, animationTime.toDouble())
|
||||
|
||||
println("DEBUG: Drone moving between points:")
|
||||
println(" - Current Point: ${currentPoint}")
|
||||
println(" - Next Point: ${nextPoint}")
|
||||
println(" - Interpolated Position: $interpolatedPos")
|
||||
|
||||
poseStack.translate(interpolatedPos.x - blockEntity.blockPos.x,
|
||||
interpolatedPos.y - blockEntity.blockPos.y,
|
||||
interpolatedPos.z - blockEntity.blockPos.z)
|
||||
|
||||
println("DEBUG: Drone position interpolated to: $interpolatedPos")
|
||||
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(-yRot))
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180F)) // flip the drone right side up
|
||||
|
||||
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
|
||||
} else {
|
||||
val yRot = blockState.getValue(HorizontalDirectionalBlock.FACING).toYRot()
|
||||
|
||||
val poseEntry = poseStack.last()
|
||||
val matrix = poseEntry.pose()
|
||||
|
||||
poseStack.translate(0.5, 0.0, 0.5)
|
||||
poseStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
|
||||
val posX = matrix.m03()
|
||||
val posY = matrix.m13()
|
||||
val posZ = matrix.m23()
|
||||
|
||||
println("DEBUG: Drone is NOT in use. Rendering default position at: x=$posX, y=$posY, z=$posZ")
|
||||
|
||||
poseStack.mulPose(Axis.ZP.rotationDegrees(180F))
|
||||
renderDrone(droneState, "sleep", tickDelta, poseStack, 1.0F, multiBufferSource, light)
|
||||
}
|
||||
|
||||
poseStack.popPose()
|
||||
}
|
||||
|
||||
fun renderDrone(
|
||||
state: DroneState,
|
||||
pose: String,
|
||||
tickDelta: Float,
|
||||
poseStack: PoseStack,
|
||||
scale: Float = 1F,
|
||||
multiBufferSource: MultiBufferSource,
|
||||
light: Int,
|
||||
) {
|
||||
state.updatePartialTicks(tickDelta)
|
||||
|
||||
val droneResource: ResourceLocation = cobblemonResource("rotom_drone")
|
||||
|
||||
val model = VaryingModelRepository.getPoser(droneResource, state) as DroneModel
|
||||
val texture = VaryingModelRepository.getTexture(droneResource, state)
|
||||
|
||||
val buffer = multiBufferSource.getBuffer(RenderType.entityCutout(texture))
|
||||
model.bufferProvider = multiBufferSource
|
||||
|
||||
state.currentModel = model
|
||||
state.setPose(pose)
|
||||
|
||||
model.context = context
|
||||
context.put(RenderContext.TEXTURE, texture)
|
||||
context.put(RenderContext.RENDER_STATE, RenderContext.RenderState.BLOCK)
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
|
||||
model.applyAnimations(
|
||||
entity = null,
|
||||
state = state,
|
||||
headYaw = 0F,
|
||||
headPitch = 0F,
|
||||
limbSwing = 0F,
|
||||
limbSwingAmount = 0F,
|
||||
ageInTicks = state.animationSeconds * 20
|
||||
)
|
||||
|
||||
poseStack.scale(scale, scale, scale)
|
||||
|
||||
// TODO: Make drone lighting dynamic (simply using the light arg makes the drone always appear dark)
|
||||
model.withLayerContext(multiBufferSource, state, VaryingModelRepository.getLayers(droneResource, state)) {
|
||||
model.render(context, poseStack, buffer, 200, OverlayTexture.NO_OVERLAY, -0x1)
|
||||
}
|
||||
model.setDefault()
|
||||
}
|
||||
|
||||
private fun spawnDebugParticles(blockEntity: StadiumBlockEntity) {
|
||||
val world = blockEntity.level ?: return
|
||||
if (!world.isClientSide) return // Only run on the client-side
|
||||
|
||||
for (point in blockEntity.pathPoints) {
|
||||
world.addParticle(
|
||||
net.minecraft.core.particles.ParticleTypes.FLAME, // Test particle (changeable)
|
||||
point.x, point.y, point.z, // Position of the particle
|
||||
0.0, 0.02, 0.0 // Slight upward motion
|
||||
)
|
||||
}
|
||||
|
||||
// Spawn a special particle at the next interpolation point
|
||||
if (blockEntity.pathPoints.isNotEmpty()) {
|
||||
val nextPoint = blockEntity.pathPoints[(pathIndex + 1) % blockEntity.pathPoints.size]
|
||||
world.addParticle(
|
||||
net.minecraft.core.particles.ParticleTypes.END_ROD, // Different effect for next point
|
||||
nextPoint.x, nextPoint.y, nextPoint.z,
|
||||
0.0, 0.05, 0.0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-34
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.client.render.models.blockbench
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
@@ -51,11 +50,8 @@ import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderStateShard
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
* A model that can be posed and animated using [PoseAnimation]s and [ActiveAnimation]s. This
|
||||
@@ -566,16 +562,14 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
applyPose(state, pose, 1F)
|
||||
|
||||
val primaryAnimation = state.primaryAnimation
|
||||
val shouldRotateHead = if(entity is PokemonEntity) entity.riding.shouldRotatePokemonHead(entity) else true
|
||||
|
||||
// Quirks will run if there is no primary animation running and quirks are enabled for this context.
|
||||
if (primaryAnimation == null && context.request(RenderContext.DO_QUIRKS) != false) {
|
||||
// Remove any quirk animations that don't exist in our current pose
|
||||
state.quirks.keys.filterNot(pose.quirks::contains).forEach(state.quirks::remove)
|
||||
|
||||
// Tick all the quirks
|
||||
pose.quirks.forEach {
|
||||
it.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, if(shouldRotateHead) headYaw else 0f, if(shouldRotateHead) headPitch else 0f, 1F)
|
||||
it.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch, 1F)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +577,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
// The pose intensity is the complement of the primary animation's curve. This is used to blend the primary.
|
||||
state.poseIntensity = 1 - primaryAnimation.curve((state.animationSeconds - primaryAnimation.started) / primaryAnimation.duration)
|
||||
// If the primary animation is done after running we're going to clean things up.
|
||||
//Set headYaw and headPitch to zero if Pokemon shouldn't move head during riding
|
||||
if (!primaryAnimation.run(
|
||||
context,
|
||||
this,
|
||||
@@ -591,8 +584,8 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
limbSwing,
|
||||
limbSwingAmount,
|
||||
ageInTicks,
|
||||
if(shouldRotateHead) headYaw else 0f,
|
||||
if(shouldRotateHead) headPitch else 0f,
|
||||
headYaw,
|
||||
headPitch,
|
||||
1 - state.poseIntensity
|
||||
)
|
||||
) {
|
||||
@@ -604,11 +597,11 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
|
||||
// Run active animations and return back any that are done and can be removed.
|
||||
val removedActiveAnimations = state.activeAnimations.toList()
|
||||
.filterNot { it.run(context, this, state, limbSwing, limbSwingAmount, ageInTicks, if(shouldRotateHead) headYaw else 0f, if(shouldRotateHead) headPitch else 0f, 1F) }
|
||||
.filterNot { it.run(context, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch, 1F) }
|
||||
state.activeAnimations.removeAll(removedActiveAnimations)
|
||||
// Applies the pose's animations.
|
||||
state.currentPose?.let(poses::get)
|
||||
?.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, if(shouldRotateHead) headYaw else 0f, if(shouldRotateHead) headPitch else 0f)
|
||||
?.apply(context, this, state, limbSwing, limbSwingAmount, ageInTicks, headYaw, headPitch)
|
||||
// Updates the locator positions now that all the animations are in effect. This is the last thing we do!
|
||||
updateLocators(entity, state)
|
||||
}
|
||||
@@ -681,42 +674,24 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
var scale = 1F
|
||||
// We could improve this to be generalized for other entities. First we'd have to figure out wtf is going on, though.
|
||||
if (entity is PokemonEntity) {
|
||||
if(entity.passengers.isNotEmpty() && entity.controllingPassenger is Rollable && (entity.controllingPassenger as Rollable).orientation != null){
|
||||
val controllingPassenger = entity.controllingPassenger
|
||||
val transformationMatrix = Matrix4f()
|
||||
val center = Vector3f(0f, entity.bbHeight/2, 0f)
|
||||
transformationMatrix.translate(center)
|
||||
transformationMatrix.mul(Matrix4f((controllingPassenger as Rollable).orientation!!))
|
||||
transformationMatrix.translate(center.negate())
|
||||
matrixStack.mulPose(transformationMatrix)
|
||||
} else {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yBodyRotO, entity.yBodyRot)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - yRot))
|
||||
}
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - entity.yBodyRot))
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
scale = entity.pokemon.form.baseScale * entity.pokemon.scaleModifier * (entity.delegate as PokemonClientDelegate).entityScaleModifier
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
} else if (entity is EmptyPokeBallEntity) {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yRot, entity.yRotO)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(entity.yRot))
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(1F, -1F, -1F)
|
||||
scale = 0.7F
|
||||
matrixStack.scale(scale, scale, scale)
|
||||
} else if (entity is GenericBedrockEntity) {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yRot, entity.yRotO)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(yRot))
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(entity.yRot))
|
||||
matrixStack.pushPose()
|
||||
// Not 100% convinced we need the -1 on Y but if we needed it for the Poke Ball then probably?
|
||||
matrixStack.scale(1F, -1F, 1F)
|
||||
} else if (entity is NPCEntity) {
|
||||
var yRot = Mth.lerp(state.getPartialTicks(), entity.yBodyRotO, entity.yBodyRot)
|
||||
yRot = Mth.wrapDegrees(yRot)
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - yRot))
|
||||
matrixStack.mulPose(Axis.YP.rotationDegrees(180 - entity.yBodyRot))
|
||||
matrixStack.pushPose()
|
||||
matrixStack.scale(-1F, -1F, 1F)
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ open class BedrockActiveAnimation(
|
||||
headPitch: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
return animation.run(model, state, state.animationSeconds - startedSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity).also {
|
||||
return animation.run(context, model, state, state.animationSeconds - startedSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity).also {
|
||||
if (!it) {
|
||||
afterAction(context, state)
|
||||
}
|
||||
|
||||
+6
-39
@@ -14,17 +14,15 @@ import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.snowstorm.BedrockParticleOptions
|
||||
import com.cobblemon.mod.common.client.particle.ParticleStorm
|
||||
import com.cobblemon.mod.common.client.render.MatrixWrapper
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.RenderContext
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.genericRuntime
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import java.util.SortedMap
|
||||
import java.util.TreeMap
|
||||
import net.minecraft.CrashReport
|
||||
import net.minecraft.ReportedException
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -35,6 +33,8 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import java.util.*
|
||||
|
||||
data class BedrockAnimationGroup(
|
||||
val formatVersion: String,
|
||||
@@ -149,40 +149,7 @@ data class BedrockAnimation(
|
||||
/** Useful to have, gets set after loading the animation. */
|
||||
var name: String = ""
|
||||
|
||||
|
||||
fun run(
|
||||
model: PosableModel,
|
||||
state: PosableState,
|
||||
animationSeconds: Float,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float,
|
||||
ageInTicks: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
return run(
|
||||
model.context,
|
||||
model.relevantPartsByName,
|
||||
model.rootPart,
|
||||
state,
|
||||
animationSeconds,
|
||||
limbSwing,
|
||||
limbSwingAmount,
|
||||
ageInTicks,
|
||||
intensity
|
||||
)
|
||||
}
|
||||
|
||||
fun run(
|
||||
context: RenderContext?,
|
||||
relevantPartsByName: Map<String, ModelPart>,
|
||||
rootPart: Bone?,
|
||||
state: PosableState,
|
||||
animationSeconds: Float,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float,
|
||||
ageInTicks: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
fun run(context: RenderContext, model: PosableModel, state: PosableState, animationSeconds: Float, limbSwing: Float, limbSwingAmount: Float, ageInTicks: Float, intensity: Float): Boolean {
|
||||
var animationSeconds = animationSeconds
|
||||
if (shouldLoop) {
|
||||
animationSeconds %= animationLength.toFloat()
|
||||
@@ -197,7 +164,7 @@ data class BedrockAnimation(
|
||||
runtime.environment.setSimpleVariable("age_in_ticks", DoubleValue(ageInTicks.toDouble()))
|
||||
|
||||
boneTimelines.forEach { (boneName, timeline) ->
|
||||
val part = relevantPartsByName[boneName] ?: if (boneName == "root_part") (rootPart as? ModelPart) else null
|
||||
val part = model.relevantPartsByName[boneName] ?: if (boneName == "root_part") (model.rootPart as ModelPart) else null
|
||||
if (part !== null) {
|
||||
if (!timeline.position.isEmpty()) {
|
||||
val position = timeline.position.resolve(animationSeconds.toDouble(), runtime).scale(intensity.toDouble())
|
||||
@@ -217,7 +184,7 @@ data class BedrockAnimation(
|
||||
zRot += rotation.z.toFloat().toRadians()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
val exception = IllegalStateException("Bad animation for entity: ${(context?.request(RenderContext.ENTITY))?.effectiveName()?.string ?: "unknown entity (riding animation?)"}", e)
|
||||
val exception = IllegalStateException("Bad animation for entity: ${(model.context.request(RenderContext.ENTITY))!!.effectiveName().string}", e)
|
||||
val crash = CrashReport("Cobblemon encountered an unexpected crash", exception)
|
||||
val section = crash.addCategory("Animation Details")
|
||||
section.setDetail("Pose", state.currentPose!!)
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class BedrockPoseAnimation(val animation: BedrockAnimation) : PoseAnimation() {
|
||||
}
|
||||
|
||||
override fun setupAnim(context: RenderContext, model: PosableModel, state: PosableState, limbSwing: Float, limbSwingAmount: Float, ageInTicks: Float, headYaw: Float, headPitch: Float, intensity: Float) {
|
||||
animation.run(model, state, state.animationSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity)
|
||||
animation.run(context, model, state, state.animationSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity)
|
||||
}
|
||||
|
||||
override fun applyEffects(entity: Entity?, state: PosableState, previousSeconds: Float, newSeconds: Float) {
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.drone
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.PoseAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Bone
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.quirk.ModelQuirk
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
|
||||
/**
|
||||
* A model for rendering the Rotom drone used by the stadium block.
|
||||
*
|
||||
* @author Flarkinater
|
||||
* @since February 14th, 2025
|
||||
*/
|
||||
class DroneModel(root: Bone) : PosableModel(root) {
|
||||
@Transient
|
||||
@SerializedName("So this name can be literally anything, huh?")
|
||||
override val rootPart = (root as ModelPart).registerChildWithAllChildren(root.children.entries.first().key)
|
||||
var droneAnimations: Array<PoseAnimation> = emptyArray()
|
||||
var droneQuirks: Array<ModelQuirk<*>> = emptyArray()
|
||||
|
||||
override fun registerPoses() {
|
||||
registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = droneAnimations,
|
||||
quirks = droneQuirks
|
||||
)
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2025 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.drone
|
||||
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
|
||||
/**
|
||||
* State for a drone Rotom attached to a stadium block.
|
||||
*
|
||||
* @author Flarkinater
|
||||
* @since February 12th, 2025
|
||||
*/
|
||||
class DroneState() : PosableState() {
|
||||
init {
|
||||
setPose("sleep")
|
||||
age = 0
|
||||
currentPartialTicks = 0F
|
||||
}
|
||||
|
||||
override fun getEntity() = null
|
||||
|
||||
override fun updatePartialTicks(partialTicks: Float) {
|
||||
currentPartialTicks += partialTicks / 2
|
||||
}
|
||||
|
||||
override val schedulingTracker = SchedulingTracker()
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen3
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.CobblemonPose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class WhiscashModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
override val rootPart = root.registerChildWithAllChildren("whiscash")
|
||||
|
||||
override var portraitScale = 0.8F
|
||||
override var portraitTranslation = Vec3(-0.35, 0.4, 0.0)
|
||||
|
||||
override var profileScale = 0.6F
|
||||
override var profileTranslation = Vec3(-0.1, 0.6, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var walk: CobblemonPose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("whiscash", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
animations = arrayOf(
|
||||
bedrock("whiscash", "water_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
animations = arrayOf(
|
||||
bedrock("whiscash", "water_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
+5
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.client.render.models.blockbench.*
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.blockentity.BlockEntityModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.fossil.FossilModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.drone.DroneModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.AncientPokeBallModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.BeastBallModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokeball.PokeBallModel
|
||||
@@ -79,12 +80,14 @@ object VaryingModelRepository {
|
||||
"poke_balls",
|
||||
"generic",
|
||||
"block_entities",
|
||||
"drone"
|
||||
)
|
||||
|
||||
val poserDirectories: List<Pair<String, Class<out PosableModel>>> = listOf(
|
||||
"bedrock/posers" to PosableModel::class.java,
|
||||
"bedrock/pokemon/posers" to PokemonPosableModel::class.java,
|
||||
"bedrock/fossils/posers" to FossilModel::class.java,
|
||||
"bedrock/drone/posers" to DroneModel::class.java,
|
||||
"bedrock/block_entities/posers" to BlockEntityModel::class.java,
|
||||
"bedrock/npcs/posers" to PosableModel::class.java,
|
||||
"bedrock/poke_balls/posers" to PosableModel::class.java,
|
||||
@@ -116,6 +119,7 @@ object VaryingModelRepository {
|
||||
.registerTypeAdapter(PosableModel::class.java, JsonModelAdapter(::PosableModel))
|
||||
.registerTypeAdapter(PokemonPosableModel::class.java, JsonModelAdapter(::PokemonPosableModel))
|
||||
.registerTypeAdapter(FossilModel::class.java, JsonModelAdapter(::FossilModel))
|
||||
.registerTypeAdapter(DroneModel::class.java, JsonModelAdapter(::DroneModel))
|
||||
.registerTypeAdapter(BlockEntityModel::class.java, JsonModelAdapter(::BlockEntityModel))
|
||||
.registerTypeAdapter(Pose::class.java, PoseAdapter { JsonModelAdapter.model!! })
|
||||
.registerTypeAdapter(ModelPartTransformation::class.java, ModelPartTransformationAdapter)
|
||||
@@ -533,6 +537,7 @@ object VaryingModelRepository {
|
||||
inbuilt("spewpa", ::SpewpaModel)
|
||||
inbuilt("vivillon", ::VivillonModel)
|
||||
inbuilt("barboach", ::BarboachModel)
|
||||
inbuilt("whiscash", ::WhiscashModel)
|
||||
inbuilt("combee", ::CombeeModel)
|
||||
inbuilt("vespiquen", ::VespiquenModel)
|
||||
inbuilt("lillipup", ::LillipupModel)
|
||||
|
||||
-136
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.player
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.riding.Rideable
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.client.player.AbstractClientPlayer
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
* @author landonjw
|
||||
*/
|
||||
object MountedPlayerRenderer {
|
||||
const val disableRollableRenderDebug: Boolean = false
|
||||
|
||||
fun render(player: AbstractClientPlayer, entity: PokemonEntity, stack: PoseStack, bob: Float, yBodyRot: Float, partialTicks: Float, i: Float) {
|
||||
if(player.vehicle !is Rideable) return
|
||||
val matrix = stack.last().pose()
|
||||
|
||||
val vehicle = player.vehicle as Rideable?
|
||||
val entity = vehicle!!.riding.entity
|
||||
val seatIndex = entity.passengers.indexOf(player)
|
||||
val seat = entity.seats[seatIndex]
|
||||
val delegate = entity.delegate as PokemonClientDelegate
|
||||
val locator = delegate.locatorStates[seat.locator]
|
||||
|
||||
//Positions player
|
||||
if (locator != null) {
|
||||
val locatorOffset = locator.matrix.getTranslation(Vector3f())
|
||||
|
||||
val center = Vector3f(0f, entity.bbHeight/2, 0f)
|
||||
var locatorOffsetToCenter = locatorOffset.sub(center, Vector3f())
|
||||
//locatorOffsetToCenter.y -= 0.5f
|
||||
|
||||
val transformationMatrix = Matrix4f()
|
||||
if (player is Rollable && player.shouldRoll()){
|
||||
//transformationMatrix.rotate(Axis.YP.rotationDegrees(-yBodyRot))
|
||||
//transformationMatrix.mulLocal(player.orientation)
|
||||
}
|
||||
|
||||
val rotatedOffset = transformationMatrix.transformPosition(locatorOffsetToCenter, Vector3f()).add(center).sub(Vector3f(0f, player.bbHeight/2, 0f))
|
||||
matrix.translate(rotatedOffset)
|
||||
|
||||
//Undo seat position
|
||||
val playerPos = Vec3(
|
||||
Mth.lerp(partialTicks.toDouble(), player.xOld, player.x),
|
||||
Mth.lerp(partialTicks.toDouble(), player.yOld, player.y),
|
||||
Mth.lerp(partialTicks.toDouble(), player.zOld, player.z),
|
||||
)
|
||||
|
||||
val entityPos = Vec3(
|
||||
Mth.lerp(partialTicks.toDouble(), entity.xOld, entity.x),
|
||||
Mth.lerp(partialTicks.toDouble(), entity.yOld, entity.y),
|
||||
Mth.lerp(partialTicks.toDouble(), entity.zOld, entity.z),
|
||||
)
|
||||
|
||||
matrix.translate(playerPos.subtract(entityPos).toVector3f().negate())
|
||||
}
|
||||
|
||||
//Rotates player
|
||||
if (player is Rollable && player.shouldRoll() && !disableRollableRenderDebug) {
|
||||
val center = Vector3f(0f, player.bbHeight / 2, 0f)
|
||||
val transformationMatrix = Matrix4f()
|
||||
transformationMatrix.translate(center)
|
||||
|
||||
transformationMatrix.mul(Matrix4f(player.orientation))
|
||||
|
||||
transformationMatrix.translate(center.negate(Vector3f()))
|
||||
//Pre-Undo Yaw
|
||||
transformationMatrix.rotate(Axis.YP.rotationDegrees(yBodyRot+180f))
|
||||
matrix.mul(transformationMatrix)
|
||||
}
|
||||
matrix.translate(0f, 0.5f, 0f)
|
||||
}
|
||||
|
||||
fun animate(
|
||||
pokemonEntity: PokemonEntity,
|
||||
player: AbstractClientPlayer,
|
||||
relevantPartsByName: Map<String, ModelPart>,
|
||||
headYaw: Float,
|
||||
headPitch: Float,
|
||||
ageInTicks: Float,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float
|
||||
) {
|
||||
val seatIndex = pokemonEntity.passengers.indexOf(player).takeIf { it != -1 && it < pokemonEntity.seats.size } ?: return
|
||||
val seat = pokemonEntity.seats[seatIndex]
|
||||
val animations = seat.poseAnimations.firstOrNull { it.poseTypes.isEmpty() || it.poseTypes.contains(pokemonEntity.getCurrentPoseType()) }?.animations
|
||||
?: return
|
||||
val state = pokemonEntity.delegate as PokemonClientDelegate
|
||||
|
||||
relevantPartsByName.values.forEach {
|
||||
it.xRot = 0F
|
||||
it.yRot = 0F
|
||||
it.zRot = 0F
|
||||
}
|
||||
|
||||
state.runtime.environment.setSimpleVariable("age_in_ticks", DoubleValue(ageInTicks.toDouble()))
|
||||
state.runtime.environment.setSimpleVariable("limb_swing", DoubleValue(limbSwing.toDouble()))
|
||||
state.runtime.environment.setSimpleVariable("limb_swing_amount", DoubleValue(limbSwingAmount.toDouble()))
|
||||
state.runtime.environment.setSimpleVariable("velocity", DoubleValue(pokemonEntity.deltaMovement.horizontalDistance()))
|
||||
|
||||
// TODO add the q.player reference, requires a cached thing or something on the client idk
|
||||
|
||||
for (animation in animations) {
|
||||
val bedrockAnimation = BedrockAnimationRepository.getAnimationOrNull(animation.fileName, animation.animationName) ?: continue
|
||||
bedrockAnimation.run(
|
||||
context = null,
|
||||
relevantPartsByName = relevantPartsByName,
|
||||
rootPart = null,
|
||||
state = state,
|
||||
animationSeconds = state.animationSeconds,
|
||||
limbSwing = limbSwing,
|
||||
limbSwingAmount = limbSwingAmount,
|
||||
ageInTicks = ageInTicks,
|
||||
intensity = 1F
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+7
-43
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.client.render.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.ClientBallDisplay
|
||||
@@ -41,6 +40,7 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.math.remap
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.math.Axis
|
||||
import kotlin.math.*
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.Font.DisplayMode
|
||||
@@ -56,8 +56,10 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.*
|
||||
import kotlin.math.*
|
||||
import org.joml.Math
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import org.joml.Vector4f
|
||||
|
||||
class PokemonRenderer(
|
||||
context: EntityRendererProvider.Context
|
||||
@@ -78,7 +80,6 @@ class PokemonRenderer(
|
||||
|
||||
private const val SPACE = " "
|
||||
|
||||
private const val DISABLE_ROLLING_DEBUG = false
|
||||
}
|
||||
|
||||
val ballContext = RenderContext().also {
|
||||
@@ -139,12 +140,7 @@ class PokemonRenderer(
|
||||
modelNow.setLayerContext(buffer, clientDelegate, VaryingModelRepository.getLayers(entity.pokemon.species.resourceIdentifier, clientDelegate))
|
||||
|
||||
|
||||
if (entity.passengers.isNotEmpty()) {
|
||||
renderRiding(entity, partialTicks, poseMatrix, buffer, packedLight)
|
||||
}
|
||||
else {
|
||||
super.render(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
}
|
||||
super.render(entity, entityYaw, partialTicks, poseMatrix, buffer, packedLight)
|
||||
|
||||
modelNow.green = 1F
|
||||
modelNow.blue = 1F
|
||||
@@ -155,38 +151,6 @@ class PokemonRenderer(
|
||||
// Minecraft.getInstance().bufferBuilders.entityVertexConsumers.draw()
|
||||
}
|
||||
|
||||
fun renderRiding(
|
||||
entity: PokemonEntity,
|
||||
partialTicks: Float,
|
||||
poseMatrix: PoseStack,
|
||||
buffer: MultiBufferSource,
|
||||
packedLight: Int
|
||||
) {
|
||||
val driver = entity.firstPassenger ?: return
|
||||
val rollable = driver as? Rollable ?: return
|
||||
|
||||
poseMatrix.pushPose()
|
||||
|
||||
if(!DISABLE_ROLLING_DEBUG && rollable.shouldRoll()){
|
||||
val matrix = poseMatrix.last().pose()
|
||||
val yaw = Mth.rotLerp(partialTicks, entity.yBodyRotO, entity.yBodyRot)
|
||||
val center = Vector3f(0f, entity.bbHeight/2, 0f)
|
||||
val transformationMatrix = Matrix4f()
|
||||
//Move origin to center of Pokemon
|
||||
transformationMatrix.translate(center)
|
||||
transformationMatrix.mul(Matrix4f(rollable.orientation))
|
||||
//Move origin to base of the entity
|
||||
transformationMatrix.translate(center.negate(Vector3f()))
|
||||
|
||||
//Pre-undo yaw rotation
|
||||
transformationMatrix.rotate(Axis.YP.rotationDegrees(yaw+180f))
|
||||
matrix.mul(transformationMatrix)
|
||||
}
|
||||
|
||||
super.render(entity, 0f, partialTicks, poseMatrix, buffer, packedLight)
|
||||
poseMatrix.popPose()
|
||||
}
|
||||
|
||||
fun renderTransition(
|
||||
modelNow: PosableModel,
|
||||
beamMode: Int,
|
||||
@@ -492,4 +456,4 @@ class PokemonRenderer(
|
||||
|
||||
matrixStack.popPose()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.entity
|
||||
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import java.util.*
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.util.EnumSet
|
||||
|
||||
/**
|
||||
* The type of a pose. Used for normalizing pose swapping for all models.
|
||||
@@ -26,7 +24,6 @@ enum class PoseType {
|
||||
FLY,
|
||||
FLOAT,
|
||||
SWIM,
|
||||
GLIDE,
|
||||
/** A pose for rendering on the left shoulder. Pose animations are given the player head yaw, pitch, and ageInTicks. */
|
||||
SHOULDER_LEFT,
|
||||
/** A pose for rendering on the right shoulder. Pose animations are given the player head yaw, pitch, and ageInTicks. */
|
||||
@@ -42,18 +39,12 @@ enum class PoseType {
|
||||
|
||||
companion object {
|
||||
val ALL_POSES = EnumSet.allOf(PoseType::class.java)
|
||||
val FLYING_POSES = EnumSet.of(FLY, HOVER, GLIDE)
|
||||
val FLYING_POSES = EnumSet.of(FLY, HOVER)
|
||||
val SWIMMING_POSES = EnumSet.of(SWIM, FLOAT)
|
||||
val STANDING_POSES = EnumSet.of(STAND, WALK)
|
||||
val SHOULDER_POSES = EnumSet.of(SHOULDER_LEFT, SHOULDER_RIGHT)
|
||||
val UI_POSES = EnumSet.of(PROFILE, PORTRAIT)
|
||||
val MOVING_POSES = EnumSet.of(WALK, SWIM, FLY)
|
||||
val STATIONARY_POSES = EnumSet.of(STAND, FLOAT, HOVER)
|
||||
|
||||
fun identified() : List<ResourceLocation> {
|
||||
return ALL_POSES.stream()
|
||||
.map { cobblemonResource(it.name.lowercase(Locale.getDefault())) }
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable → Regular
+18
-358
@@ -8,8 +8,11 @@
|
||||
|
||||
package com.cobblemon.mod.common.entity.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonEntities
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.drop.DropTable
|
||||
import com.cobblemon.mod.common.api.entity.Despawner
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSender
|
||||
@@ -34,10 +37,6 @@ import com.cobblemon.mod.common.api.pokemon.feature.StringSpeciesFeature
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.api.reactive.ObservableSubscription
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.*
|
||||
import com.cobblemon.mod.common.api.riding.events.SelectDriverEvent
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinitions
|
||||
import com.cobblemon.mod.common.api.scheduling.Schedulable
|
||||
import com.cobblemon.mod.common.api.scheduling.SchedulingTracker
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
@@ -80,17 +79,9 @@ import com.cobblemon.mod.common.pokemon.ai.FormPokemonBehaviour
|
||||
import com.cobblemon.mod.common.pokemon.evolution.variants.ItemInteractionEvolution
|
||||
import com.cobblemon.mod.common.pokemon.feature.StashHandler
|
||||
import com.cobblemon.mod.common.pokemon.properties.UncatchableProperty
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.JetAirController.Companion.MAXTOPSPEED
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.JetAirController.Companion.MINTOPSPEED
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
import com.mojang.serialization.Codec
|
||||
import java.util.EnumSet
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import kotlin.math.PI
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
@@ -139,18 +130,16 @@ import net.minecraft.world.level.gameevent.GameEvent
|
||||
import net.minecraft.world.level.material.FluidState
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
import java.util.*
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
@Suppress("unused")
|
||||
open class PokemonEntity(
|
||||
world: Level,
|
||||
pokemon: Pokemon = Pokemon().apply { isClient = world.isClientSide },
|
||||
type: EntityType<out PokemonEntity> = CobblemonEntities.POKEMON,
|
||||
) : ShoulderRidingEntity(type, world), PosableEntity, Shearable, Schedulable, Rideable, ScannableEntity {
|
||||
) : ShoulderRidingEntity(type, world), PosableEntity, Shearable, Schedulable, ScannableEntity {
|
||||
companion object {
|
||||
@JvmStatic val SPECIES = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.STRING)
|
||||
@JvmStatic val NICKNAME = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.COMPONENT)
|
||||
@@ -178,7 +167,7 @@ open class PokemonEntity(
|
||||
const val BATTLE_LOCK = "battle"
|
||||
const val EVOLUTION_LOCK = "evolving"
|
||||
|
||||
fun createAttributes(): AttributeSupplier.Builder = createLivingAttributes()
|
||||
fun createAttributes(): AttributeSupplier.Builder = LivingEntity.createLivingAttributes()
|
||||
.add(Attributes.FOLLOW_RANGE)
|
||||
.add(Attributes.ATTACK_KNOCKBACK)
|
||||
}
|
||||
@@ -228,12 +217,6 @@ open class PokemonEntity(
|
||||
get() = entityData.get(BATTLE_ID).isPresent
|
||||
val friendship: Int
|
||||
get() = entityData.get(FRIENDSHIP)
|
||||
val seats: List<Seat>
|
||||
get() = form.riding.seats
|
||||
val rideProp: RidingProperties
|
||||
get() = form.riding
|
||||
|
||||
|
||||
|
||||
var drops: DropTable? = null
|
||||
|
||||
@@ -243,8 +226,6 @@ open class PokemonEntity(
|
||||
|
||||
var enablePoseTypeRecalculation = true
|
||||
|
||||
override val riding: RidingManager = RidingManager(this)
|
||||
|
||||
/**
|
||||
* The amount of steps this entity has traveled.
|
||||
*/
|
||||
@@ -348,7 +329,7 @@ open class PokemonEntity(
|
||||
SPECIES -> refreshDimensions()
|
||||
POSE_TYPE -> {
|
||||
val value = entityData.get(data) as PoseType
|
||||
if ((value == PoseType.FLY || value == PoseType.HOVER) && passengers.isEmpty()) {
|
||||
if (value == PoseType.FLY || value == PoseType.HOVER) {
|
||||
setNoGravity(true)
|
||||
} else {
|
||||
setNoGravity(false)
|
||||
@@ -458,9 +439,6 @@ open class PokemonEntity(
|
||||
this.tethering = null
|
||||
this.pokemon.recall()
|
||||
}
|
||||
|
||||
jumping = false
|
||||
|
||||
//This is so that pokemon in the pasture block are ALWAYS in sync with the pokemon box
|
||||
//Before, pokemon entities in pastures would hold an old ref to a pokemon obj and changes to that would not appear to the underlying file
|
||||
if (this.tethering != null && age % 20 == 0) {
|
||||
@@ -533,6 +511,10 @@ open class PokemonEntity(
|
||||
return super.isInvulnerableTo(damageSource)
|
||||
}
|
||||
|
||||
override fun canRide(vehicle: Entity): Boolean {
|
||||
return platform == PlatformType.NONE && super.canRide(vehicle)
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method that checks if this Pokémon has the [UncatchableProperty.uncatchable] property.
|
||||
*
|
||||
@@ -935,7 +917,7 @@ open class PokemonEntity(
|
||||
|
||||
if (hand == InteractionHand.MAIN_HAND && player is ServerPlayer && pokemon.getOwnerPlayer() == player) {
|
||||
if (player.isShiftKeyDown) {
|
||||
InteractPokemonUIPacket(this.getUUID(), canSitOnShoulder() && pokemon in player.party(), this.canRide(player)).sendToPlayer(
|
||||
InteractPokemonUIPacket(this.getUUID(), canSitOnShoulder() && pokemon in player.party()).sendToPlayer(
|
||||
player
|
||||
)
|
||||
} else {
|
||||
@@ -1376,75 +1358,10 @@ open class PokemonEntity(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Converted to kotin from the same named private function in entity.
|
||||
private fun getInputVector(relative: Vec3, motionScaler: Float, facing: Float): Vec3 {
|
||||
val d = relative.lengthSqr()
|
||||
if (d < 1.0E-7) {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
// If the squared length is greater than 1, normalize; otherwise, use the vector as-is.
|
||||
// May not want to normalize this
|
||||
//val vec3 = (if (d > 1.0) relative.normalize() else relative).scale(motionScaler.toDouble())
|
||||
val vec3 = relative
|
||||
|
||||
// Convert the facing angle (in degrees) to radians using the factor 0.017453292F.
|
||||
val f = Mth.sin(facing * 0.017453292F)
|
||||
val g = Mth.cos(facing * 0.017453292F)
|
||||
|
||||
// Rotate the vector by the facing angle.
|
||||
return Vec3(
|
||||
vec3.x * g - vec3.z * f,
|
||||
vec3.y,
|
||||
vec3.z * g + vec3.x * f
|
||||
)
|
||||
}
|
||||
|
||||
//override fun moveRelative(amount: Float, relative: Vec3 ) {
|
||||
//super.moveRelative(amount, relative)
|
||||
//val v = this.getInputVector(relative, 1.0f, this.getYRot());
|
||||
//this.setDeltaMovement(v);
|
||||
//}
|
||||
|
||||
override fun handleRelativeFrictionAndCalculateMovement(deltaMovement: Vec3 , friction: Float ): Vec3 {
|
||||
val riders = this.passengers.filterIsInstance<LivingEntity>()
|
||||
if ( riders.isEmpty() ) {
|
||||
super.handleRelativeFrictionAndCalculateMovement(deltaMovement, friction)
|
||||
}
|
||||
//ignore this for now
|
||||
else if( false )
|
||||
{
|
||||
val v = this.getInputVector(deltaMovement, 1.0f, this.getYRot());
|
||||
//changing this will give the ride more or less inertia/handling/drift?
|
||||
//A bit of overlap with other things but.
|
||||
this.setDeltaMovement(this.deltaMovement.lerp(v, riding.inertia(this)));
|
||||
//this.setDeltaMovement(this.deltaMovement.scale(this.speed.toDouble()));
|
||||
|
||||
//maybe move this to the travel function. The jump below never gets used.
|
||||
this.move( MoverType.SELF, this.deltaMovement );
|
||||
}
|
||||
return this.deltaMovement
|
||||
}
|
||||
|
||||
override fun travel(movementInput: Vec3) {
|
||||
val prevBlockPos = this.blockPosition()
|
||||
if (beamMode != 3) { // Don't let Pokémon move during recall
|
||||
//this.deltaMovement = movementInput
|
||||
|
||||
//val riders = this.passengers.filterIsInstance<LivingEntity>()
|
||||
//if ( !riders.isEmpty() ) {
|
||||
//if ( false ) {
|
||||
//val v = this.handleRelativeFrictionAndCalculateMovement(movementInput, 0.6f)
|
||||
//this.moveRelative(this.speed, v);
|
||||
//}
|
||||
val riders = this.passengers.filterIsInstance<LivingEntity>()
|
||||
if ( riders.isEmpty() ) {
|
||||
super.travel(movementInput)
|
||||
}
|
||||
|
||||
//super.travel(movementInput)
|
||||
|
||||
super.travel(movementInput)
|
||||
this.updateBlocksTraveled(prevBlockPos)
|
||||
}
|
||||
if (isBattling && this.isInWater) {
|
||||
@@ -1529,7 +1446,8 @@ open class PokemonEntity(
|
||||
*
|
||||
* @return If the backing [pokemon] has a non-null [Pokemon.nickname].
|
||||
*/
|
||||
override fun hasCustomName(): Boolean = pokemon.nickname != null && pokemon.nickname?.contents != PlainTextContents.EMPTY
|
||||
override fun hasCustomName(): Boolean =
|
||||
pokemon.nickname != null && pokemon.nickname?.contents != PlainTextContents.EMPTY
|
||||
|
||||
/**
|
||||
* This method toggles the visibility of the entity name,
|
||||
@@ -1653,9 +1571,6 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
override fun canBeLeashed() = true
|
||||
// override fun canBeLeashedBy(player: Player): Boolean {
|
||||
// return this.ownerUuid == null || this.ownerUuid == player.uuid
|
||||
// }
|
||||
|
||||
override fun setLeashedTo(entity: Entity, bl: Boolean) {
|
||||
super.setLeashedTo(entity, bl)
|
||||
@@ -1674,262 +1589,6 @@ open class PokemonEntity(
|
||||
*/
|
||||
private fun createSidedPokemon(): Pokemon = Pokemon().apply { isClient = this@PokemonEntity.level().isClientSide }
|
||||
|
||||
override fun canRide(entity: Entity): Boolean {
|
||||
return platform == PlatformType.NONE && super.canRide(entity)
|
||||
}
|
||||
|
||||
// Takes in a requested stat type with a base minimum and base maximum and returns the interpolated
|
||||
// stat based on the boost of that pokemons stat
|
||||
fun getRideStat( stat: RidingStat, style: RidingStyle, baseMin: Double, baseMax: Double ): Double {
|
||||
//Currenlty zero boost since aprijuice isn't implemented yet
|
||||
val stat = this.rideProp.calculate(stat, style, 0 )
|
||||
|
||||
val statVal = (((baseMax - baseMin) / 100) * stat) + baseMin
|
||||
|
||||
return statVal
|
||||
}
|
||||
|
||||
override fun canAddPassenger(passenger: Entity): Boolean {
|
||||
return passengers.size < seats.size
|
||||
}
|
||||
|
||||
fun getIsJumping() = jumping
|
||||
fun setIsJumping(value: Boolean) {
|
||||
jumping = value
|
||||
}
|
||||
|
||||
// override fun moveRelative(amount: Float, relative: Vec3) {
|
||||
// val vec3 = this.getInputVector(relative, amount, this.yRot)
|
||||
// this.deltaMovement = deltaMovement.add(vec3)
|
||||
// }
|
||||
|
||||
override fun tickRidden(driver: Player, movementInput: Vec3) {
|
||||
super.tickRidden(driver, movementInput)
|
||||
this.riding.tick(this, driver, movementInput)
|
||||
val rotation = this.getControlledRotation(driver)
|
||||
setRot(rotation.y, rotation.x)
|
||||
this.yHeadRot = this.yRot
|
||||
this.yBodyRot = this.yRot
|
||||
this.yRotO = this.yRot
|
||||
|
||||
val riders = this.passengers.filterIsInstance<LivingEntity>()
|
||||
|
||||
//These are the only functions that matter and I have isolated them.
|
||||
//I think using speed to scale the movement vector will not be working.
|
||||
|
||||
if ( !riders.isEmpty() ) {
|
||||
val v = this.getInputVector(riding.velocity(this, driver, Vec3.ZERO), 1.0f, this.getYRot());
|
||||
//changing this will give the ride more or less inertia/handling/drift?
|
||||
//A bit of overlap with other things but.
|
||||
this.setDeltaMovement(this.deltaMovement.lerp(v, riding.inertia(this)));
|
||||
//this.setDeltaMovement(this.deltaMovement.scale(this.speed.toDouble()));
|
||||
|
||||
//maybe move this to the travel function. The jump below never gets used.
|
||||
this.move( MoverType.SELF, this.deltaMovement );
|
||||
|
||||
}
|
||||
|
||||
if (this.riding.canJump(this, driver)) {
|
||||
if (this.onGround()) {
|
||||
if (this.jumpInputStrength > 0) {
|
||||
// this.jump(this.jumpStrength, movementInput)
|
||||
// this.jump()
|
||||
val f = PI.toFloat() - this.yRot * PI.toFloat() / 180
|
||||
val jumpVector = riding.jumpVelocity(this, driver, this.jumpInputStrength)
|
||||
val velocity = jumpVector.yRot(f)
|
||||
// Rotate the jump vector f degrees around the Y axis
|
||||
// val velocity = Vec3d(-sin(f) * jumpVector.x, jumpVector.y, cos(f) * jumpVector.z)
|
||||
|
||||
this.addDeltaMovement(velocity)
|
||||
hasImpulse = true
|
||||
jumping = false
|
||||
}
|
||||
|
||||
this.jumpInputStrength = 0
|
||||
}
|
||||
}
|
||||
|
||||
// val lookAngle: Vec3 = driver.getLookAngle()
|
||||
// if (!driver.isNearGround() || lookAngle.y >= 0.3) {
|
||||
// setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
// entityData.set(POSE_TYPE, PoseType.HOVER)
|
||||
//
|
||||
// val deltaMovement = this.deltaMovement
|
||||
// this.setDeltaMovement(
|
||||
// lookAngle.x * 0.1 + (lookAngle.x * 1.5 - deltaMovement.x) * 1,
|
||||
// lookAngle.y * 0.1 + (lookAngle.y * 1.5 - deltaMovement.y) * 1,
|
||||
// lookAngle.z * 0.1 + (lookAngle.z * 1.5 - deltaMovement.z) * 1
|
||||
// )
|
||||
// }
|
||||
// else {
|
||||
// setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
// this.setDeltaMovement(0.0, 0.0, 0.0)
|
||||
// }
|
||||
}
|
||||
|
||||
fun Entity.isNearGround(): Boolean {
|
||||
val blockBelow: BlockPos = this.blockPosition().below()
|
||||
return this.level().getBlockState(blockBelow).isSolid()
|
||||
}
|
||||
|
||||
// override fun jump() {
|
||||
//// val vec3d = this.velocity
|
||||
////
|
||||
////
|
||||
////
|
||||
//// this.setVelocity(vec3d.x, this.jumpVelocity.toDouble(), vec3d.z)
|
||||
//// if (this.isSprinting) {
|
||||
//// val f = this.yaw * 0.017453292f
|
||||
//// this.velocity =
|
||||
//// velocity.add((-MathHelper.sin(f) * 0.2f).toDouble(), 0.0, (MathHelper.cos(f) * 0.2f).toDouble())
|
||||
//// }
|
||||
////
|
||||
//// this.velocityDirty = true
|
||||
// }
|
||||
|
||||
private fun getControlledRotation(controller: LivingEntity): Vec2 {
|
||||
return this.riding.controlledRotation(this, controller as Player)
|
||||
}
|
||||
|
||||
override fun onPassengerTurned(entityToUpdate: Entity) {
|
||||
return this.riding.clampPassengerRotation(this, entityToUpdate as? LivingEntity ?: return)
|
||||
}
|
||||
|
||||
override fun positionRider(passenger: Entity, positionUpdater: MoveFunction) {
|
||||
if (this.hasPassenger(passenger)) {
|
||||
val index = this.passengers.indexOf(passenger).takeIf { it >= 0 && it < this.seats.size } ?: return
|
||||
val seat = this.seats[index]
|
||||
val seatOffset = seat.getOffset(this.getCurrentPoseType()).toVector3f()
|
||||
val center = Vector3f(0f, this.bbHeight/2, 0f)
|
||||
|
||||
val seatToCenter = center.sub(seatOffset, Vector3f())
|
||||
val matrix = (this.passengers.first() as Rollable).orientation ?: Matrix3f().rotate((180f-passenger.yRot).toRadians(), Vector3f(0f, 1f, 0f))
|
||||
val rotatedOffset = matrix.transform(seatToCenter, Vector3f()).add(center).sub(Vector3f(0f, passenger.bbHeight/2, 0f))
|
||||
|
||||
positionUpdater.accept(passenger, this.x + rotatedOffset.x, this.y + rotatedOffset.y, this.z + rotatedOffset.z)
|
||||
if (passenger is LivingEntity) {
|
||||
this.riding.updatePassengerRotation(this, passenger)
|
||||
this.riding.clampPassengerRotation(this, passenger)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getControllingPassenger(): LivingEntity? {
|
||||
val riders = this.passengers.filterIsInstance<LivingEntity>()
|
||||
if (riders.isEmpty()) {
|
||||
riding.states.clear()
|
||||
return null
|
||||
}
|
||||
|
||||
val event = SelectDriverEvent(riders.toSet())
|
||||
val owner = riders.find { it.uuid == ownerUUID }
|
||||
if (owner != null) {
|
||||
event.suggest(owner, 0)
|
||||
}
|
||||
|
||||
CobblemonEvents.SELECT_DRIVER.emit(event)
|
||||
return event.result()
|
||||
}
|
||||
|
||||
override fun getDismountLocationForPassenger(passenger: LivingEntity): Vec3 {
|
||||
// val seat = this.riding.seats.firstOrNull { it.occupant() == passenger }
|
||||
// seat?.dismount()
|
||||
return super.getDismountLocationForPassenger(passenger)
|
||||
}
|
||||
|
||||
override fun getRiddenInput(controller: Player, movementInput: Vec3): Vec3 {
|
||||
return this.riding.velocity(this, controller, movementInput)
|
||||
}
|
||||
|
||||
override fun getRiddenSpeed(controller: Player): Float {
|
||||
return this.riding.speed(this, controller)
|
||||
}
|
||||
|
||||
var jumpInputStrength: Int = 0 // move this
|
||||
override fun onPlayerJump(strength: Int) {
|
||||
// See if this controls the hot bar element
|
||||
var strength = strength
|
||||
if (strength < 0) {
|
||||
strength = 0
|
||||
} else {
|
||||
// this.jumping = true
|
||||
// update anger? hunwah
|
||||
}
|
||||
|
||||
this.jumpInputStrength = strength
|
||||
|
||||
if (strength >= 90) {
|
||||
// this.jumpStrength = 1.0f
|
||||
} else {
|
||||
// this.jumpStrength = 0.4f + 0.4f * strength.toFloat() / 90.0f
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun canJump(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun handleStartJump(height: Int) {
|
||||
this.jumping = true
|
||||
}
|
||||
|
||||
fun side() = if (delegate is PokemonServerDelegate) "SERVER" else "CLIENT"
|
||||
|
||||
override fun handleStopJump() {
|
||||
jumping = false
|
||||
// Set back to land pose type?
|
||||
}
|
||||
|
||||
/*
|
||||
These two functions (fluids and ground) need to become riding configurable and
|
||||
dependent. Also, the onGround() function seems to affect quite a few spots in
|
||||
code and would likely need to be changed to be something more robust instead of
|
||||
just overriding this method.
|
||||
*/
|
||||
|
||||
override fun isAffectedByFluids(): Boolean {
|
||||
var fluidAffected = true
|
||||
|
||||
if( this.hasControllingPassenger() )
|
||||
{
|
||||
//Change this so it calls something from the controller to check
|
||||
//if the specific controller wants to ignore fluid physics since
|
||||
//not every single one will want to
|
||||
fluidAffected = false
|
||||
}
|
||||
|
||||
return fluidAffected
|
||||
}
|
||||
|
||||
|
||||
//this seems a bit hacky to me seeing as how many spots in the base classes its used.
|
||||
//However, there are odd interactions with the controllers when they are meant to be
|
||||
//flying or swimming but they are touching the ground and this needs to be prevented.
|
||||
//Having it be able to be turned off by the flying or swimming controllers is the
|
||||
//temp solution I have found.
|
||||
override fun onGround() : Boolean
|
||||
{
|
||||
if( riding.turnOffOnGround( this ) )
|
||||
{
|
||||
return false
|
||||
}
|
||||
return super.onGround()
|
||||
}
|
||||
|
||||
//I think already mentioned but should maybe be riding controller configurable
|
||||
override fun dismountsUnderwater(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getDefaultGravity(): Double {
|
||||
val regularGravity = super.getDefaultGravity()
|
||||
if (this.passengers.isEmpty()) {
|
||||
return regularGravity
|
||||
}
|
||||
return riding.gravity(this, regularGravity) ?: regularGravity
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to resolve the [Codec] of [Pokemon] aware if the [world] is client sided or not.
|
||||
*
|
||||
@@ -1952,4 +1611,5 @@ open class PokemonEntity(
|
||||
override fun resolveEntityScan(): LivingEntity {
|
||||
return this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -9,9 +9,9 @@
|
||||
package com.cobblemon.mod.common.entity.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSender
|
||||
import com.cobblemon.mod.common.api.entity.PokemonSideDelegate
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
@@ -21,8 +21,8 @@ import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.getIsSubmerged
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.playSoundServer
|
||||
import com.cobblemon.mod.common.util.update
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules
|
||||
@@ -33,12 +33,9 @@ import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.syncher.EntityDataAccessor
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Vector3f
|
||||
|
||||
/** Handles purely server logic for a Pokémon */
|
||||
class PokemonServerDelegate : PokemonSideDelegate {
|
||||
@@ -199,7 +196,7 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
}
|
||||
|
||||
fun updatePoseType() {
|
||||
if (!entity.enablePoseTypeRecalculation || entity.passengers.isNotEmpty()) {
|
||||
if (!entity.enablePoseTypeRecalculation) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.gametest
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonEntities
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonProperties.Companion.parse
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.gametest.framework.GameTest
|
||||
import net.minecraft.gametest.framework.GameTestHelper
|
||||
|
||||
class CobblemonGameTests {
|
||||
|
||||
@GameTest(template = "")
|
||||
fun spawnBidoof(context: GameTestHelper) {
|
||||
context.succeedWhen {
|
||||
val bidoof = parse("bidoof").create()
|
||||
bidoof.ivs[Stats.ATTACK] = 31
|
||||
|
||||
val target = BlockPos(context.relativePos(BlockPos(0, 0, 0)))
|
||||
context.assertEntityPresent(CobblemonEntities.POKEMON)
|
||||
context.assertEntityData(target, CobblemonEntities.POKEMON, PokemonEntity::pokemon, bidoof)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -238,6 +238,7 @@ object CobblemonItemGroups {
|
||||
entries.accept(CobblemonItems.PC)
|
||||
entries.accept(CobblemonItems.HEALING_MACHINE)
|
||||
entries.accept(CobblemonItems.PASTURE)
|
||||
entries.accept(CobblemonItems.STADIUM)
|
||||
|
||||
entries.accept(CobblemonItems.GILDED_CHEST)
|
||||
entries.accept(CobblemonItems.YELLOW_GILDED_CHEST)
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.orientation
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import org.joml.Matrix3f
|
||||
|
||||
class S2CUpdateOrientationPacket internal constructor(val entityId: Int, val orientation: Matrix3f?) : NetworkPacket<S2CUpdateOrientationPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeInt(entityId)
|
||||
buffer.writeBoolean(orientation != null)
|
||||
if (orientation != null) {
|
||||
buffer.writeMatrix3f(orientation)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("s2c_update_orientation")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): S2CUpdateOrientationPacket {
|
||||
val entityId = buffer.readInt()
|
||||
val orientation = if (buffer.readBoolean()) buffer.readMatrix3f() else null
|
||||
return S2CUpdateOrientationPacket(entityId, orientation)
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -24,18 +24,17 @@ import java.util.UUID
|
||||
* @author Village
|
||||
* @since January 7th, 2023
|
||||
*/
|
||||
class InteractPokemonUIPacket(val pokemonID: UUID, val canMountShoulder: Boolean, val canRide: Boolean): NetworkPacket<InteractPokemonUIPacket> {
|
||||
class InteractPokemonUIPacket(val pokemonID: UUID, val canMountShoulder: Boolean): NetworkPacket<InteractPokemonUIPacket> {
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeUUID(pokemonID)
|
||||
buffer.writeBoolean(canMountShoulder)
|
||||
buffer.writeBoolean(canRide)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("interact_pokemon_ui")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = InteractPokemonUIPacket(buffer.readUUID(), buffer.readBoolean(), buffer.readBoolean())
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = InteractPokemonUIPacket(buffer.readUUID(), buffer.readBoolean())
|
||||
}
|
||||
}
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.server.orientation
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readMatrix3f
|
||||
import com.cobblemon.mod.common.util.writeMatrix3f
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import org.joml.Matrix3f
|
||||
|
||||
class C2SUpdateOrientationPacket internal constructor(val orientation: Matrix3f?) : NetworkPacket<C2SUpdateOrientationPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeBoolean(orientation != null)
|
||||
if (orientation != null) {
|
||||
buffer.writeMatrix3f(orientation)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("c2s_update_orientation")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): C2SUpdateOrientationPacket {
|
||||
val orientation = if (buffer.readBoolean()) buffer.readMatrix3f() else null
|
||||
return C2SUpdateOrientationPacket(orientation)
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-3
@@ -24,15 +24,14 @@ import java.util.UUID
|
||||
* @author Village
|
||||
* @since January 7th, 2023
|
||||
*/
|
||||
class InteractPokemonPacket(val pokemonID: UUID, val mountShoulder: Boolean, val ride: Boolean) : NetworkPacket<InteractPokemonPacket> {
|
||||
class InteractPokemonPacket(val pokemonID: UUID, val mountShoulder: Boolean) : NetworkPacket<InteractPokemonPacket> {
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeUUID(pokemonID)
|
||||
buffer.writeBoolean(mountShoulder)
|
||||
buffer.writeBoolean(ride)
|
||||
}
|
||||
companion object {
|
||||
val ID = cobblemonResource("interact_pokemon")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = InteractPokemonPacket(buffer.readUUID(), buffer.readBoolean(), buffer.readBoolean())
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = InteractPokemonPacket(buffer.readUUID(), buffer.readBoolean())
|
||||
}
|
||||
}
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.orientation
|
||||
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.orientation.C2SUpdateOrientationPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object OrientationPacketHandler : ServerNetworkPacketHandler<C2SUpdateOrientationPacket> {
|
||||
override fun handle(packet: C2SUpdateOrientationPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
if (player is Rollable) {
|
||||
player.updateOrientation { _ -> packet.orientation }
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -24,11 +24,9 @@ object InteractPokemonHandler : ServerNetworkPacketHandler<InteractPokemonPacket
|
||||
return
|
||||
}
|
||||
pokemonEntity.tryMountingShoulder(player)
|
||||
} else if (packet.ride) {
|
||||
player.startRiding(pokemonEntity)
|
||||
} else {
|
||||
pokemonEntity.offerHeldItem(player, player.mainHandItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroup
|
||||
import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
|
||||
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.riding.RidingProperties
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
@@ -97,8 +96,6 @@ class FormData(
|
||||
private var _height: Float? = null,
|
||||
@SerializedName("weight")
|
||||
private var _weight: Float? = null,
|
||||
@SerializedName("riding")
|
||||
private var _riding: RidingProperties? = null,
|
||||
val requiredMove: String? = null,
|
||||
val requiredItem: String? = null,
|
||||
/** For forms that can accept different items (e.g. Arceus-Grass: Meadow Plate or Grassium-Z). */
|
||||
@@ -175,8 +172,6 @@ class FormData(
|
||||
|
||||
val eggGroups: Set<EggGroup>
|
||||
get() = _eggGroups ?: species.eggGroups
|
||||
val riding: RidingProperties
|
||||
get() = _riding ?: species.riding
|
||||
|
||||
/**
|
||||
* The height in decimeters
|
||||
@@ -298,7 +293,6 @@ class FormData(
|
||||
pb.writeString(ability.template.name)
|
||||
}
|
||||
}
|
||||
buffer.writeNullable(_riding) { pb, riding -> riding.encode(buffer) }
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -335,7 +329,6 @@ class FormData(
|
||||
}.forEach { add(Priority.NORMAL, it) }
|
||||
}
|
||||
}
|
||||
this._riding = buffer.readNullable { pb -> RidingProperties.decode(buffer) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacketToPlayers
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
@@ -59,8 +58,6 @@ import com.cobblemon.mod.common.api.reactive.Observable
|
||||
import com.cobblemon.mod.common.api.reactive.SettableObservable
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.riding.RidingProperties
|
||||
import com.cobblemon.mod.common.api.storage.StoreCoordinates
|
||||
import com.cobblemon.mod.common.api.storage.party.NPCPartyStore
|
||||
import com.cobblemon.mod.common.api.storage.party.PlayerPartyStore
|
||||
@@ -543,9 +540,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
*/
|
||||
internal var heldItem: ItemStack = ItemStack.EMPTY
|
||||
|
||||
val riding: RidingProperties
|
||||
get() = this.form.riding
|
||||
|
||||
init {
|
||||
storeCoordinates.subscribe { if (it != null && it.store !is PCStore && this.tetheringId != null) afterOnServer(seconds = 0.05F) { this.tetheringId = null } }
|
||||
storeCoordinates.subscribe {
|
||||
@@ -555,7 +549,6 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
open fun getStat(stat: Stat) = Cobblemon.statProvider.getStatForPokemon(this, stat)
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.cobblemon.mod.common.api.pokemon.experience.ExperienceGroups
|
||||
import com.cobblemon.mod.common.api.pokemon.moves.Learnset
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.storage.InvalidSpeciesException
|
||||
import com.cobblemon.mod.common.api.riding.RidingProperties
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.FLYING_POSES
|
||||
@@ -124,9 +123,6 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
|
||||
var forms = mutableListOf<FormData>()
|
||||
private set
|
||||
|
||||
var riding: RidingProperties = RidingProperties()
|
||||
private set
|
||||
|
||||
val standardForm by lazy { FormData(_evolutions = this.evolutions).initialize(this) }
|
||||
|
||||
var labels = hashSetOf<String>()
|
||||
@@ -253,8 +249,6 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
|
||||
pb.writeBoolean(ability is CommonAbility)
|
||||
pb.writeString(ability.template.name)
|
||||
}
|
||||
|
||||
this.riding.encode(buffer)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -296,7 +290,6 @@ class Species : ClientDataSynchronizer<Species>, ShowdownIdentifiable {
|
||||
pool.add(Priority.NORMAL, it)
|
||||
}
|
||||
}
|
||||
this.riding = RidingProperties.decode(buffer)
|
||||
this.initialize()
|
||||
}
|
||||
|
||||
|
||||
-383
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.HelicopterAirController.Companion.ROTATION_LIMIT
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.JetAirController.Companion
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.JetAirController.Companion.MAXTOPSPEED
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.JetAirController.Companion.MINSPEED
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.*
|
||||
|
||||
class BirdAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.GLIDE) {
|
||||
val player = it.passengers.firstOrNull() as? Player ?: return@PoseOption false
|
||||
player.zza == 0.0f && it.deltaMovement.length() > 0.3 })
|
||||
.with(PoseOption(PoseType.FLY) {
|
||||
val player = it.passengers.firstOrNull() as? Player ?: return@PoseOption false
|
||||
player.zza > 0.0f // Checks if the player is actively controlling movement // Checks if the player is actively controlling movement
|
||||
})
|
||||
|
||||
//.with(PoseOption(PoseType.FLY) { entity ->
|
||||
// val player = entity.passengers.firstOrNull() as? Player ?: false
|
||||
// player.// This is the `zza` value })
|
||||
//.with(PoseOption(PoseType.GLIDE) { it.deltaMovement.length() > 0.51 })
|
||||
//.with(PoseOption(PoseType.FLY) { it.deltaMovement.length() > 0.1 && it.deltaMovement.length() <= 0.51 })
|
||||
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
var gravity: Expression = "0".asExpression()
|
||||
private set
|
||||
var horizontalAcceleration: Expression = "0.1".asExpression()
|
||||
private set
|
||||
var verticalAcceleration: Expression = "0.1".asExpression()
|
||||
private set
|
||||
var speed: Expression = "1.0".asExpression()
|
||||
private set
|
||||
var lastVelocity = Vec3(0.0,0.0,0.0)
|
||||
private set
|
||||
|
||||
var currSpeed = 0.0
|
||||
private set
|
||||
|
||||
var lastPitch = 0.0f
|
||||
private set
|
||||
|
||||
//This function might just be good for syncing the ridecontroller speed
|
||||
//with the entity speed?
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
//Set the speed since this will need to be done to transfer speed between rides?
|
||||
//maxSpeed = entity.speed.toDouble()
|
||||
|
||||
|
||||
//retrieve stats
|
||||
val topSpeed = entity.getRideStat( RidingStat.SPEED, RidingStyle.AIR, MINTOPSPEED, MAXTOPSPEED )
|
||||
val accel = entity.getRideStat( RidingStat.ACCELERATION, RidingStyle.AIR, MINACCEL, MAXACCEL )
|
||||
|
||||
val maxGlideSpeed = topSpeed * 2
|
||||
var glideSpeedChange = 0.00
|
||||
|
||||
//speed up and slow down based on input
|
||||
if( driver.zza > 0.0 && currSpeed < topSpeed)
|
||||
{
|
||||
currSpeed = min( currSpeed + accel , topSpeed)
|
||||
}
|
||||
else if ( driver.zza < 0.0 && currSpeed > 0.0)
|
||||
{
|
||||
//Decelerate is now always a constant half of max acceleration.
|
||||
currSpeed = max( currSpeed - (MAXACCEL / 2) , 0.0)
|
||||
}
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
if ( rollable != null )
|
||||
{
|
||||
glideSpeedChange = sin(Math.toRadians( rollable.pitch.toDouble() ))
|
||||
glideSpeedChange = glideSpeedChange.pow(3)
|
||||
|
||||
//TODO: Possibly create a deadzone around parallel where speed isn't taken away from?
|
||||
if( glideSpeedChange <= 0.0 )
|
||||
{
|
||||
//Ensures that a propelling force is still able to be applied when
|
||||
//climbing in height
|
||||
if( driver.zza <= 0 )
|
||||
{
|
||||
//speed decrease should be 2x speed increase?
|
||||
currSpeed = max( currSpeed + (MAXACCEL) * glideSpeedChange , 0.0 )
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// only add to the speed if it hasn't exceeded the current
|
||||
//glide angles maximum amount of speed that it can give.
|
||||
currSpeed = min( currSpeed + ((MAXACCEL * 2) * glideSpeedChange) , topSpeed * 2)
|
||||
}
|
||||
}
|
||||
|
||||
//air resistance
|
||||
currSpeed = max( currSpeed - 0.005, 0.0)
|
||||
|
||||
println(currSpeed)
|
||||
return 0.0f
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
|
||||
var yVel = 0.0
|
||||
var leftForce = 0.0
|
||||
var upForce = 0.0
|
||||
var forwardForce = 0.0
|
||||
val rollable = driver as? Rollable
|
||||
if( rollable != null ) {
|
||||
|
||||
|
||||
//yVel = sin(Math.toRadians(rollable.pitch.toDouble() - lastPitch ))*-10
|
||||
|
||||
|
||||
|
||||
lastPitch = rollable.pitch
|
||||
|
||||
//Need to deadzone this when straight up or down
|
||||
leftForce = -1.0 * sin(Math.toRadians( rollable.roll.toDouble() ) )
|
||||
|
||||
upForce = -1.0 * sin(Math.toRadians( rollable.pitch.toDouble() ))
|
||||
|
||||
forwardForce = cos(Math.toRadians( rollable.pitch.toDouble() ))
|
||||
}
|
||||
|
||||
//TODO: Add in an upwards and downwards force when pressing space maybe?
|
||||
|
||||
//Leave out tap to flap right now
|
||||
/*
|
||||
var jumpVector = Vec3.ZERO
|
||||
if (entity.jumpInputStrength > 0) {
|
||||
val runtime = getRuntime(entity)
|
||||
runtime.environment.query.addFunction("jump_strength") { DoubleValue(entity.jumpInputStrength.toDouble()) }
|
||||
val jumpForces = this.jumpVector.map { runtime.resolveFloat(it) }
|
||||
jumpVector = Vec3(jumpForces[0].toDouble(), jumpForces[1].toDouble(), jumpForces[2].toDouble())
|
||||
jumpVector = jumpVector.toVector3f().mul((driver as Rollable).orientation).toVec3d()
|
||||
entity.jumpInputStrength = 0
|
||||
entity.addDeltaMovement(jumpVector)
|
||||
}
|
||||
*/
|
||||
|
||||
val velocity = Vec3(0.0 , upForce * currSpeed, forwardForce * currSpeed)
|
||||
|
||||
return velocity
|
||||
}
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
|
||||
|
||||
val handling = entity.getRideStat( RidingStat.SKILL, RidingStyle.AIR, MINHANDLING, MAXHANDLING)
|
||||
val rotationChangeRate = 10.0
|
||||
|
||||
if( rollable != null )
|
||||
{
|
||||
var yawForce = rotationChangeRate * sin( Math.toRadians( rollable.roll.toDouble() ))
|
||||
//for a bit of correction on the rolls limit it to a quarter the amount
|
||||
var pitchForce = -0.25 * rotationChangeRate * abs(sin( Math.toRadians( rollable.roll.toDouble() )))
|
||||
|
||||
//limit rotation modulation when pitched up heavily or pitched down heavily
|
||||
yawForce *= abs(cos( Math.toRadians( rollable.pitch.toDouble() )))
|
||||
pitchForce *= abs(cos( Math.toRadians( rollable.pitch.toDouble() ))) * 1.5
|
||||
|
||||
//Create a deadzone for easier leveling out
|
||||
if( rollable.roll <= 0.0 && rollable.roll >= -0.0)
|
||||
{
|
||||
yawForce = 0.0
|
||||
pitchForce = 0.0
|
||||
}
|
||||
return Vec3( yawForce, pitchForce, 0.0)
|
||||
}
|
||||
|
||||
/*
|
||||
val rotLimit = 15.0
|
||||
|
||||
var rollForce = -1.0 * driver.xxa * rotationChangeRate
|
||||
|
||||
//TODO: Fix accumulated movement causing pitch and roll out of set bounds
|
||||
if( rollable != null ) {
|
||||
//If the roll or pitch have exceeded the limit then do not modulate that
|
||||
//rotation in that direction further
|
||||
|
||||
val rotLim = 30.0
|
||||
|
||||
rollForce *= 1.0.pow(-1.0 * (abs(rollable.roll.toDouble()) / rotLimit))
|
||||
|
||||
|
||||
if( rollable.roll >= rotLimit && rollForce > 0.0)
|
||||
{
|
||||
rollForce = 0.0;
|
||||
}
|
||||
if( rollable.roll <= -rotLimit && rollForce < 0.0)
|
||||
{
|
||||
rollForce = 0.0;
|
||||
}
|
||||
|
||||
//Ignore x,y,z its angular velocity:
|
||||
//yaw, pitch, roll
|
||||
return Vec3( 0.0, 0.0, rollForce)
|
||||
}
|
||||
|
||||
|
||||
*/
|
||||
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY
|
||||
(entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
if(driver !is Rollable) return Vec3.ZERO
|
||||
|
||||
val rollable = driver as Rollable
|
||||
|
||||
val handling = entity.getRideStat( RidingStat.SKILL, RidingStyle.AIR, MINHANDLING, MAXHANDLING)
|
||||
|
||||
//var yMouse = yMouseSmoother.getNewDeltaValue(angVecMouse.y * 0.15f, d);
|
||||
//var xMouse = xMouseSmoother.getNewDeltaValue(cursorDeltaX * 0.15f, d);
|
||||
|
||||
var xInput = xMouseSmoother.getNewDeltaValue(xMouse * 0.1, deltaTime * 4);
|
||||
val YInput = yMouseSmoother.getNewDeltaValue(yMouse * 0.1, deltaTime * 4);
|
||||
|
||||
//limit rolling based on healing
|
||||
val rotLimit = handling * 1.5
|
||||
|
||||
if( abs( rollable.roll + xInput ) < rotLimit )
|
||||
{
|
||||
if( sign(xInput) == sign( rollable.roll ).toDouble() ) {
|
||||
val s = sign(rollable.roll)
|
||||
val d = abs(abs(rollable.roll) - rotLimit)
|
||||
xInput *= (d.pow(2)) / (rotLimit.pow(2))
|
||||
}
|
||||
}
|
||||
|
||||
//if( abs(rollable.roll) > rotLimit )
|
||||
else
|
||||
{
|
||||
val s = sign(rollable.roll)
|
||||
val d = abs(rollable.roll) - rotLimit
|
||||
if( sign(xInput) == sign( rollable.roll ).toDouble() ) {
|
||||
xInput = 0.0
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if( xMouse > 0 )
|
||||
{
|
||||
if( rollable.roll > rotLimit )
|
||||
{
|
||||
//val adjustedX = 0.5* xMouse * ( (rotLimit - rollable.roll) / ( rotLimit) )
|
||||
return Vec3(0.0, YInput, 0.0 )
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return Vec3(0.0, YInput, xInput * -0.1 )
|
||||
}
|
||||
|
||||
}else{
|
||||
if( rollable.roll < -1.0 * rotLimit )
|
||||
{
|
||||
//val adjustedX = 0.5* xMouse * ( (rotLimit + rollable.roll) / ( rotLimit) )
|
||||
return Vec3(0.0, YInput, 0.0 )
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return Vec3(0.0, YInput, xInput * -0.1 )
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
//Ignore x,y,z its angular velocity:
|
||||
//yaw, pitch, roll
|
||||
return Vec3(0.0, YInput, xInput )
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
//Going to use my own gravity calculations for now.
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
override fun shouldRoll(entity: PokemonEntity) = true
|
||||
|
||||
override fun useAngVelSmoothing(entity: PokemonEntity): Boolean = false
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(gravity.toString())
|
||||
buffer.writeString(horizontalAcceleration.toString())
|
||||
buffer.writeString(verticalAcceleration.toString())
|
||||
buffer.writeString(speed.toString())
|
||||
buffer.writeDouble(this.lastVelocity.x)
|
||||
buffer.writeDouble(this.lastVelocity.y)
|
||||
buffer.writeDouble(this.lastVelocity.z)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
gravity = buffer.readString().asExpression()
|
||||
horizontalAcceleration = buffer.readString().asExpression()
|
||||
verticalAcceleration = buffer.readString().asExpression()
|
||||
speed = buffer.readString().asExpression()
|
||||
val x = buffer.readDouble()
|
||||
val y = buffer.readDouble()
|
||||
val z = buffer.readDouble()
|
||||
this.lastVelocity = Vec3(x, y, z)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
val KEY = cobblemonResource("air/bird")
|
||||
|
||||
val MAXTOPSPEED = 1.0 // 20 bl/s
|
||||
val MINTOPSPEED = 0.35 // 7 bl/s
|
||||
//val MINSPEED = 0.25 // 5 bl/s
|
||||
|
||||
//Accel will lie between 1.0 second and 5.0 seconds
|
||||
val MAXACCEL = (MAXTOPSPEED ) / (20*3) //3.0 second to max speed
|
||||
val MINACCEL = (MAXTOPSPEED ) / (20*8) // 8 seconds to max speed
|
||||
|
||||
//Can rotate 90 degrees
|
||||
val MAXHANDLING = 90.0
|
||||
val MINHANDLING = 30.0
|
||||
|
||||
|
||||
val MAXYAWHANDLING = 16.0
|
||||
val MINYAWHANDLING = 8.0
|
||||
}
|
||||
}
|
||||
-202
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class DolphinController : RideController {
|
||||
companion object {
|
||||
val KEY: ResourceLocation = cobblemonResource("swim/dolphin")
|
||||
}
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
var speed = "1.0".asExpression()
|
||||
private set
|
||||
var driveFactor = "1.0".asExpression()
|
||||
private set
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
var strafeFactor = "0.2".asExpression()
|
||||
private set
|
||||
var lastVelocity = Vec3(0.0,0.0,0.0)
|
||||
private set
|
||||
|
||||
private val rollSmoother = SmoothDouble()
|
||||
|
||||
override val key: ResourceLocation = KEY
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { it.deltaMovement.length() >= 0.05 })
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
|
||||
//If there are only fluid blocks or air block below the ride
|
||||
//or if the entity is in water then activate the controller
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (it.y.toDouble() == (entity.position().y)) {
|
||||
val blockState = entity.level().getBlockState(it.below())
|
||||
return@any (blockState.isAir || !blockState.fluidState.isEmpty ) ||
|
||||
(entity.isInWater || entity.isUnderWater)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return getRuntime(entity).resolveFloat(speed)
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot )
|
||||
}
|
||||
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
override fun inertia(entity: PokemonEntity ): Double
|
||||
{
|
||||
return 0.05
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
|
||||
if (!entity.isInWater && !entity.isUnderWater)
|
||||
{
|
||||
lastVelocity = Vec3(lastVelocity.x, lastVelocity.y - 0.035, lastVelocity.z)
|
||||
return lastVelocity
|
||||
}
|
||||
|
||||
val driveFactor = runtime.resolveFloat(this.driveFactor)
|
||||
val strafeFactor = runtime.resolveFloat(this.strafeFactor)
|
||||
val f = driver.xxa * strafeFactor
|
||||
var g = driver.zza * driveFactor
|
||||
if (g <= 0.0f) {
|
||||
g *= runtime.resolveFloat(this.reverseDriveFactor)
|
||||
}
|
||||
|
||||
var yComp = 0.0
|
||||
|
||||
//Get roll to add a left and right strafe during roll
|
||||
//Not sure if this is desired? Will need to mess around with this
|
||||
//a bit more
|
||||
var zComp = 0.0
|
||||
val rollable = driver as? Rollable
|
||||
if (rollable != null)
|
||||
{
|
||||
//Can be used again if I better figure out how to deadzone it near the tops?
|
||||
zComp = -1.0 * g.toDouble() * sin(Math.toRadians( rollable.roll.toDouble() ) )
|
||||
yComp = -1.0 * g.toDouble() * sin(Math.toRadians( rollable.pitch.toDouble() ) )
|
||||
}
|
||||
|
||||
val currVelocity = Vec3(0.0, yComp , g.toDouble())
|
||||
lastVelocity = currVelocity
|
||||
return currVelocity
|
||||
}
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
|
||||
if (!entity.isInWater && !entity.isUnderWater)
|
||||
{
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
|
||||
//this should be changed to be speed maybe?
|
||||
val movingForce = driver.zza
|
||||
if( rollable != null ) {
|
||||
var yawAngVel = 3 * sin(Math.toRadians(rollable.roll.toDouble())).toFloat()
|
||||
var pitchAngVel = -1 * Math.abs(sin(Math.toRadians(rollable.roll.toDouble())).toFloat())
|
||||
|
||||
//limit rotation modulation when pitched up heavily or pitched down heavily
|
||||
yawAngVel *= (abs(cos(Math.toRadians(rollable.pitch.toDouble())))).toFloat()
|
||||
pitchAngVel *= (abs(cos(Math.toRadians(rollable.pitch.toDouble())))).toFloat()
|
||||
//if you are not pressing forward then don't turn
|
||||
//yawAngVel *= movingForce
|
||||
//Ignore x,y,z its angular velocity:
|
||||
//yaw, pitch, roll
|
||||
return Vec3(yawAngVel.toDouble(), pitchAngVel.toDouble(), 0.0)
|
||||
}
|
||||
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player) = getRuntime(entity).resolveBoolean(canJump)
|
||||
|
||||
override fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
runtime.environment.query.addFunction("jump_strength") { DoubleValue(jumpStrength.toDouble()) }
|
||||
val jumpVector = jumpVector.map { runtime.resolveFloat(it) }
|
||||
return Vec3(jumpVector[0].toDouble(), jumpVector[1].toDouble(), jumpVector[2].toDouble())
|
||||
}
|
||||
|
||||
override fun shouldRoll(entity: PokemonEntity) = true
|
||||
|
||||
override fun turnOffOnGround(entity: PokemonEntity): Boolean = true
|
||||
|
||||
override fun dismountOnShift(entity: PokemonEntity): Boolean = false
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(this.speed.getString())
|
||||
buffer.writeString(this.canJump.getString())
|
||||
buffer.writeString(this.jumpVector[0].getString())
|
||||
buffer.writeString(this.jumpVector[1].getString())
|
||||
buffer.writeString(this.jumpVector[2].getString())
|
||||
buffer.writeString(this.driveFactor.getString())
|
||||
buffer.writeString(this.reverseDriveFactor.getString())
|
||||
buffer.writeString(this.strafeFactor.getString())
|
||||
buffer.writeDouble(this.lastVelocity.x)
|
||||
buffer.writeDouble(this.lastVelocity.y)
|
||||
buffer.writeDouble(this.lastVelocity.z)
|
||||
}
|
||||
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.speed = buffer.readString().asExpression()
|
||||
this.canJump = buffer.readString().asExpression()
|
||||
this.jumpVector = listOf(
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression()
|
||||
)
|
||||
this.driveFactor = buffer.readString().asExpression()
|
||||
this.reverseDriveFactor = buffer.readString().asExpression()
|
||||
this.strafeFactor = buffer.readString().asExpression()
|
||||
this.strafeFactor = buffer.readString().asExpression()
|
||||
val x = buffer.readDouble()
|
||||
val y = buffer.readDouble()
|
||||
val z = buffer.readDouble()
|
||||
this.lastVelocity = Vec3(x, y, z)
|
||||
}
|
||||
}
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.states.CompositeState
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class FallToFlightCompositeController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var minimumForwardSpeed: Expression = "0.5".asExpression()
|
||||
private set
|
||||
var minimumFallSpeed: Expression = "0.5".asExpression()
|
||||
private set
|
||||
|
||||
var landController: RideController = GenericLandController()
|
||||
private set
|
||||
var flightController: RideController = GliderAirController()
|
||||
private set
|
||||
|
||||
override fun pose(entity: PokemonEntity): PoseType {
|
||||
return getActiveController(entity).poseProvider.select(entity)
|
||||
}
|
||||
|
||||
fun getActiveController(entity: PokemonEntity): RideController {
|
||||
val state = getState(entity, ::CompositeState)
|
||||
return state.activeController ?: let {
|
||||
val controller = if (entity.getCurrentPoseType() in PoseType.FLYING_POSES) {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
flightController
|
||||
} else {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
landController
|
||||
}
|
||||
state.activeController = controller
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
controller
|
||||
}
|
||||
}
|
||||
|
||||
fun checkShouldBeFlying(entity: PokemonEntity, isFlyingAlready: Boolean): Boolean {
|
||||
val runtime = getRuntime(entity)
|
||||
val minFallingSpeed = runtime.resolveFloat(minimumFallSpeed)
|
||||
val minForwardSpeed = runtime.resolveFloat(minimumForwardSpeed)
|
||||
val grounded = entity.onGround()
|
||||
return if (isFlyingAlready) {
|
||||
!grounded
|
||||
} else {
|
||||
entity.deltaMovement.y <= -minFallingSpeed && entity.deltaMovement.horizontalDistance() >= minForwardSpeed
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val state = getState(entity, ::CompositeState)
|
||||
val shouldBeFlying = checkShouldBeFlying(entity, state.activeController == flightController)
|
||||
if (state.activeController == flightController && !shouldBeFlying) { // && entity.onGround() && state.timeTransitioned + 20 < entity.level().gameTime) {
|
||||
state.activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
} else if (state.activeController == landController && shouldBeFlying) {
|
||||
state.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
}
|
||||
|
||||
return getActiveController(entity).speed(entity, driver)
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return getActiveController(entity).rotation(entity, driver)
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
return getActiveController(entity).velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player) = true
|
||||
|
||||
override fun jumpForce(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
val controller = getActiveController(entity)
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
return getActiveController(entity).gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
override fun shouldRoll(entity: PokemonEntity): Boolean = getActiveController(entity).shouldRoll(entity)
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(minimumForwardSpeed.getString())
|
||||
buffer.writeString(minimumFallSpeed.getString())
|
||||
landController.encode(buffer)
|
||||
flightController.encode(buffer)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
minimumForwardSpeed = buffer.readString().asExpression()
|
||||
minimumFallSpeed = buffer.readString().asExpression()
|
||||
landController = buffer.readResourceLocation().let { key ->
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
controller
|
||||
}
|
||||
flightController = buffer.readResourceLocation().let { key ->
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
controller
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KEY = cobblemonResource("composite/fall_to_flight")
|
||||
}
|
||||
}
|
||||
-140
@@ -1,140 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
|
||||
class GenericLandController : RideController {
|
||||
companion object {
|
||||
val KEY: ResourceLocation = cobblemonResource("land/generic")
|
||||
}
|
||||
|
||||
// private var previousVelocity = Vec3d.ZERO
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
var speed = "1.0".asExpression()
|
||||
private set
|
||||
var driveFactor = "1.0".asExpression()
|
||||
private set
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
var strafeFactor = "0.2".asExpression()
|
||||
private set
|
||||
|
||||
@Transient
|
||||
override val key: ResourceLocation = KEY
|
||||
@Transient
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.STAND).with(PoseOption(PoseType.WALK) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
@Transient
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
// Are there any blocks under the mon that aren't air or fluid
|
||||
// Cant just check one block since some mons may be more than one block big
|
||||
// This should be changed so that the any predicate is only ran on blocks under the mon
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (entity.isInWater || entity.isUnderWater) {
|
||||
return@any false
|
||||
}
|
||||
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
|
||||
if (it.y.toDouble() == (entity.position().y)) {
|
||||
val blockState = entity.level().getBlockState(it.below())
|
||||
return@any !blockState.isAir && blockState.fluidState.isEmpty
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return 0.0f
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val currSpeed = 1.0
|
||||
|
||||
val runtime = getRuntime(entity)
|
||||
val driveFactor = runtime.resolveFloat(this.driveFactor)
|
||||
val strafeFactor = runtime.resolveFloat(this.strafeFactor)
|
||||
val f = driver.xxa * strafeFactor
|
||||
var g = driver.zza * driveFactor
|
||||
if (g <= 0.0f) {
|
||||
g *= runtime.resolveFloat(this.reverseDriveFactor)
|
||||
}
|
||||
val gravity = -0.8
|
||||
val velocity = Vec3(f.toDouble() * currSpeed, gravity, g.toDouble()*0.7 * currSpeed)
|
||||
|
||||
return velocity
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player) = getRuntime(entity).resolveBoolean(canJump)
|
||||
|
||||
override fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
runtime.environment.query.addFunction("jump_strength") { DoubleValue(jumpStrength.toDouble()) }
|
||||
val jumpVector = jumpVector.map { runtime.resolveFloat(it) }
|
||||
return Vec3(jumpVector[0].toDouble(), jumpVector[1].toDouble(), jumpVector[2].toDouble())
|
||||
}
|
||||
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
override fun inertia(entity: PokemonEntity ): Double = 0.3
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(this.speed.getString())
|
||||
buffer.writeString(this.canJump.getString())
|
||||
buffer.writeString(this.jumpVector[0].getString())
|
||||
buffer.writeString(this.jumpVector[1].getString())
|
||||
buffer.writeString(this.jumpVector[2].getString())
|
||||
buffer.writeString(this.driveFactor.getString())
|
||||
buffer.writeString(this.reverseDriveFactor.getString())
|
||||
buffer.writeString(this.strafeFactor.getString())
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.speed = buffer.readString().asExpression()
|
||||
this.canJump = buffer.readString().asExpression()
|
||||
this.jumpVector = listOf(
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression()
|
||||
)
|
||||
this.driveFactor = buffer.readString().asExpression()
|
||||
this.reverseDriveFactor = buffer.readString().asExpression()
|
||||
this.strafeFactor = buffer.readString().asExpression()
|
||||
}
|
||||
}
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
|
||||
class GenericLiquidController : RideController {
|
||||
companion object {
|
||||
val KEY: ResourceLocation = cobblemonResource("swim/generic")
|
||||
}
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
var speed = "1.0".asExpression()
|
||||
private set
|
||||
var driveFactor = "1.0".asExpression()
|
||||
private set
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
var strafeFactor = "0.2".asExpression()
|
||||
private set
|
||||
|
||||
override val key: ResourceLocation = KEY
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.FLOAT)
|
||||
.with(PoseOption(PoseType.SWIM) { it.isSwimming && it.entityData.get(PokemonEntity.MOVING) })
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
//This could be kinda weird... what if the top of the mon is in a fluid but the bottom isnt?
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (entity.isInWater || entity.isUnderWater) {
|
||||
return@any true
|
||||
}
|
||||
val blockState = entity.level().getBlockState(it)
|
||||
return@any !blockState.fluidState.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return getRuntime(entity).resolveFloat(speed)
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
val driveFactor = runtime.resolveFloat(this.driveFactor)
|
||||
val strafeFactor = runtime.resolveFloat(this.strafeFactor)
|
||||
val f = driver.xxa * strafeFactor
|
||||
var g = driver.zza * driveFactor
|
||||
if (g <= 0.0f) {
|
||||
g *= runtime.resolveFloat(this.reverseDriveFactor)
|
||||
}
|
||||
|
||||
val velocity = Vec3(f.toDouble(), 0.0, g.toDouble())
|
||||
|
||||
return velocity
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player) = getRuntime(entity).resolveBoolean(canJump)
|
||||
|
||||
override fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
runtime.environment.query.addFunction("jump_strength") { DoubleValue(jumpStrength.toDouble()) }
|
||||
val jumpVector = jumpVector.map { runtime.resolveFloat(it) }
|
||||
return Vec3(jumpVector[0].toDouble(), jumpVector[1].toDouble(), jumpVector[2].toDouble())
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(this.speed.getString())
|
||||
buffer.writeString(this.canJump.getString())
|
||||
buffer.writeString(this.jumpVector[0].getString())
|
||||
buffer.writeString(this.jumpVector[1].getString())
|
||||
buffer.writeString(this.jumpVector[2].getString())
|
||||
buffer.writeString(this.driveFactor.getString())
|
||||
buffer.writeString(this.reverseDriveFactor.getString())
|
||||
buffer.writeString(this.strafeFactor.getString())
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.speed = buffer.readString().asExpression()
|
||||
this.canJump = buffer.readString().asExpression()
|
||||
this.jumpVector = listOf(
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression()
|
||||
)
|
||||
this.driveFactor = buffer.readString().asExpression()
|
||||
this.reverseDriveFactor = buffer.readString().asExpression()
|
||||
this.strafeFactor = buffer.readString().asExpression()
|
||||
}
|
||||
}
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class GliderAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var glideSpeed: Expression = "0.1".asExpression()
|
||||
private set
|
||||
var speed: Expression = "1.0".asExpression()
|
||||
private set
|
||||
var canStrafe: Expression = "false".asExpression()
|
||||
private set
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
return getRuntime(entity).resolveFloat(speed)
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val xVector = if (getRuntime(entity).resolveBoolean(canStrafe)) driver.xxa.toDouble() else 0.0
|
||||
val yVector = -getRuntime(entity).resolveDouble(glideSpeed)
|
||||
val zVector = driver.zza.toDouble()
|
||||
val statSpeed = entity.rideProp.calculate(RidingStat.SPEED, RidingStyle.AIR, 0 )
|
||||
|
||||
return Vec3(xVector, yVector, zVector)
|
||||
}
|
||||
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int) = Vec3.ZERO
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(glideSpeed.toString())
|
||||
buffer.writeString(speed.toString())
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
glideSpeed = buffer.readString().asExpression()
|
||||
speed = buffer.readString().asExpression()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KEY: ResourceLocation = cobblemonResource("air/glider")
|
||||
}
|
||||
}
|
||||
-224
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import java.lang.Math.pow
|
||||
import kotlin.math.*
|
||||
|
||||
/**
|
||||
* Allows for flight like a bird controller, except you don't have to do any "flapping" motion,
|
||||
* you can just go up and down like creative
|
||||
*
|
||||
* @author Apion/Jackowes
|
||||
* @since January 1, 2025
|
||||
*/
|
||||
class HelicopterAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
|
||||
//If there are only fluid blocks or air block below the ride
|
||||
//then activate the controller. If it is in water the ride will
|
||||
//dismount accordingly
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (it.y.toDouble() == (entity.position().y)) {
|
||||
val blockState = entity.level().getBlockState(it.below())
|
||||
return@any (blockState.isAir || !blockState.fluidState.isEmpty )
|
||||
}
|
||||
true
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var gravity: Expression = "1.0".asExpression()
|
||||
private set
|
||||
var horizontalAcceleration: Expression = "0.1".asExpression()
|
||||
private set
|
||||
var verticalVelocity: Expression = "1.0".asExpression()
|
||||
private set
|
||||
var speed: Expression = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
//Increased max speed to exaggerate movement.
|
||||
//This likely just needs to be a static number if it really is just
|
||||
//the scalar for the velocity vector
|
||||
return 2.0f
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
|
||||
//If the player is not modulating height then hover
|
||||
var yVel = if (driver.jumping) runtime.resolveDouble(verticalVelocity)
|
||||
else if (driver.isShiftKeyDown) -runtime.resolveDouble(verticalVelocity)
|
||||
else (0.0)
|
||||
|
||||
yVel *= 0.25
|
||||
var xVel = 0.0
|
||||
var zVel = 0.0
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
|
||||
//Horizontal velocity is based on pitch and roll
|
||||
if( rollable != null ) {
|
||||
xVel = -1.0 * sin(Math.toRadians(rollable.roll.toDouble()))
|
||||
zVel = sin(Math.toRadians(rollable.pitch.toDouble()))
|
||||
}
|
||||
|
||||
return Vec3(xVel, yVel, zVel)
|
||||
}
|
||||
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
|
||||
val rollable = driver as? Rollable
|
||||
|
||||
//In degrees per second? It was supposed to be I think but
|
||||
//I have messed something up
|
||||
val rotationChangeRate = 2.0
|
||||
val rotLimit = 30.0
|
||||
|
||||
var pitchForce = driver.zza * rotationChangeRate
|
||||
var rollForce = -1.0 * driver.xxa * rotationChangeRate
|
||||
|
||||
|
||||
//TODO: Fix accumulated movement causing pitch and roll out of set bounds
|
||||
if( rollable != null ) {
|
||||
//If the roll or pitch have exceeded the limit then do not modulate that
|
||||
//rotation in that direction further
|
||||
|
||||
//modulate the forces so that they trend towards 0 as they approach rotation limit.
|
||||
//The current function has it drop off very quickly which may not be ideal.
|
||||
//Prev function:
|
||||
// pitchForce = pitchForce * max(rotLim - abs( rollable.pitch.toDouble() ), 0.0)
|
||||
|
||||
//The three denotes that the force will be 1/3 what it would have been at
|
||||
//the rotation limit
|
||||
rollForce *= 2.0.pow(-1.0 * (abs(rollable.roll.toDouble()) / ROTATION_LIMIT))
|
||||
|
||||
pitchForce *= 2.0.pow(-1.0 * (abs(rollable.pitch.toDouble()) / ROTATION_LIMIT))
|
||||
|
||||
if( rollable.roll >= ROTATION_LIMIT && rollForce > 0.0)
|
||||
{
|
||||
rollForce = 0.0;
|
||||
}
|
||||
if( rollable.roll <= -ROTATION_LIMIT && rollForce < 0.0)
|
||||
{
|
||||
rollForce = 0.0;
|
||||
}
|
||||
if( rollable.pitch >= ROTATION_LIMIT && pitchForce > 0.0 )
|
||||
{
|
||||
pitchForce = 0.0;
|
||||
}
|
||||
if( rollable.pitch <= -ROTATION_LIMIT && pitchForce < 0.0 )
|
||||
{
|
||||
pitchForce = 0.0;
|
||||
}
|
||||
|
||||
//Ignore x,y,z its angular velocity:
|
||||
//yaw, pitch, roll
|
||||
return Vec3( 0.0, pitchForce.toDouble(), rollForce)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return Vec3(0.0, 0.0, 0.0)
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(entity: PokemonEntity): Boolean = true
|
||||
|
||||
|
||||
override fun inertia(entity: PokemonEntity ): Double = 0.1
|
||||
|
||||
override fun canJump(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
override fun shouldRoll(entity: PokemonEntity): Boolean = true
|
||||
|
||||
override fun rotationOnMouseXY
|
||||
(entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
if(driver !is Rollable) return Vec3.ZERO
|
||||
|
||||
val rollable = driver as Rollable
|
||||
//Ignore x,y,z its angular velocity:
|
||||
//yaw, pitch, roll
|
||||
return Vec3(xMouse, 0.0, 0.0 )
|
||||
}
|
||||
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double {
|
||||
return 0.0
|
||||
}
|
||||
|
||||
//Need to ensure that crouching lowers altitude and doesn't eject the player
|
||||
override fun dismountOnShift(entity: PokemonEntity): Boolean = false
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(gravity.toString())
|
||||
buffer.writeString(horizontalAcceleration.toString())
|
||||
buffer.writeString(verticalVelocity.toString())
|
||||
buffer.writeString(speed.toString())
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
gravity = buffer.readString().asExpression()
|
||||
horizontalAcceleration = buffer.readString().asExpression()
|
||||
verticalVelocity = buffer.readString().asExpression()
|
||||
speed = buffer.readString().asExpression()
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
val KEY = cobblemonResource("air/helicopter")
|
||||
val ROTATION_LIMIT = 30.0f
|
||||
}
|
||||
}
|
||||
-300
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Rollable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.HelicopterAirController.Companion.ROTATION_LIMIT
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.*
|
||||
|
||||
class JetAirController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { it.deltaMovement.length() > 0 })
|
||||
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
var gravity: Expression = "0".asExpression()
|
||||
private set
|
||||
var horizontalAcceleration: Expression = "0.1".asExpression()
|
||||
private set
|
||||
var verticalAcceleration: Expression = "0.1".asExpression()
|
||||
private set
|
||||
var speed: Expression = "1.0".asExpression()
|
||||
private set
|
||||
var lastVelocity = Vec3(0.0,0.0,0.0)
|
||||
private set
|
||||
var maxSpeed = 0.4
|
||||
private set
|
||||
|
||||
var lastPitch = 0.0f
|
||||
private set
|
||||
|
||||
var currSpeed = MINSPEED
|
||||
private set
|
||||
|
||||
var currMouseXForce = 0.0
|
||||
private set
|
||||
|
||||
var currMouseYForce = 0.0
|
||||
private set
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
//0 boost so just the base value.
|
||||
//This should be a function in pokemonEntity.kt so it can easily be called.
|
||||
val speedStat = entity.rideProp.calculate(RidingStat.SPEED, RidingStyle.AIR, 0 )
|
||||
//now calculate the true top speed value using the speed stat
|
||||
val topSpeed = (((MAXTOPSPEED - MINTOPSPEED) / 100) * speedStat) + MINTOPSPEED
|
||||
|
||||
val accelStat = entity.rideProp.calculate(RidingStat.ACCELERATION, RidingStyle.AIR, 0 )
|
||||
val accel = (((MAXACCEL - MINACCEL) / 100) * accelStat) + MINACCEL
|
||||
|
||||
val drivingForce = if ( Minecraft.getInstance().options.keySprint.isDown() ) 1.0
|
||||
else if (driver.isShiftKeyDown) -1.0
|
||||
else(0.0)
|
||||
|
||||
//speed up and slow down based on input
|
||||
if( driver.zza > 0.0 && currSpeed < topSpeed)
|
||||
{
|
||||
currSpeed = min( currSpeed + accel , topSpeed)
|
||||
}
|
||||
else if ( driver.zza < 0.0 && currSpeed > MINSPEED)
|
||||
{
|
||||
//Decelerate is now always a constant half of max acceleration.
|
||||
currSpeed = max( currSpeed - (MAXACCEL / 2) , MINSPEED)
|
||||
}
|
||||
|
||||
return currSpeed.toFloat()
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
|
||||
var yVel = 0.0
|
||||
var leftForce = 0.0
|
||||
var upForce = 0.0
|
||||
var forwardForce = 0.0
|
||||
val rollable = driver as? Rollable
|
||||
if( rollable != null ) {
|
||||
|
||||
|
||||
yVel = sin(Math.toRadians(rollable.pitch.toDouble() - lastPitch ))*-10
|
||||
|
||||
lastPitch = rollable.pitch
|
||||
|
||||
leftForce = -1.0 * sin(Math.toRadians( rollable.roll.toDouble() ) )
|
||||
|
||||
upForce = -1.0 * sin(Math.toRadians( rollable.pitch.toDouble() ))
|
||||
//limit how fast you can descend?
|
||||
upForce *= 1.0
|
||||
forwardForce = cos(Math.toRadians( rollable.pitch.toDouble() ))
|
||||
}
|
||||
val velocity = Vec3(0.0 , (upForce)* currSpeed, forwardForce * currSpeed)
|
||||
|
||||
//entity.setDeltaMovement(velocity)
|
||||
|
||||
return velocity
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(entity: PokemonEntity): Boolean = true
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
|
||||
//Get handling in degrees per second
|
||||
val handlingStat = entity.rideProp.calculate(RidingStat.SKILL, RidingStyle.AIR, 0 )
|
||||
//var handling = (((MAXHANDLING - MINHANDLING) / 100) * handlingStat) + MINHANDLING
|
||||
var handlingYaw = (((MAXYAWHANDLING - MINYAWHANDLING) / 100) * handlingStat) + MINYAWHANDLING
|
||||
|
||||
//convert it to partial ticks
|
||||
handlingYaw *= (deltaTime)
|
||||
|
||||
//A+D to yaw
|
||||
val yawForce = -2.0 * driver.xxa * handlingYaw
|
||||
|
||||
return Vec3( yawForce, 0.0, 0.0)
|
||||
}
|
||||
|
||||
override fun rotationOnMouseXY
|
||||
(entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
if(driver !is Rollable) return Vec3.ZERO
|
||||
|
||||
//Cap at a rate of 5fps so frame skips dont lead to huge jumps
|
||||
val cappedDeltaTime = min( deltaTime, 0.2)
|
||||
|
||||
|
||||
// Accumulate the mouse input
|
||||
currMouseXForce = (currMouseXForce + ( 0.0015 * xMouse )).coerceIn(-1.0, 1.0)
|
||||
currMouseYForce = (currMouseYForce + ( 0.0015 * yMouse )).coerceIn(-1.0, 1.0)
|
||||
|
||||
//Get handling in degrees per second
|
||||
val handlingStat = entity.rideProp.calculate(RidingStat.SKILL, RidingStyle.AIR, 0 )
|
||||
var handling = (((MAXHANDLING - MINHANDLING) / 100) * handlingStat) + MINHANDLING
|
||||
|
||||
//convert it to partial ticks
|
||||
handling *= (deltaTime)
|
||||
|
||||
val poke = driver.vehicle as? PokemonEntity
|
||||
|
||||
|
||||
|
||||
//val pitchRot = min( handling, max(-handling, yMouse ) )
|
||||
|
||||
//increase on an amount.
|
||||
|
||||
//if its below 0.2 it should be zero force.
|
||||
// And then between 0.2-1.0 it should map to a value between 0.0 and 1.0
|
||||
//val yInput = if(currMouseYForce < 0.2) 0.0 else ( ( currMouseYForce - 0.2 ) / 0.8)
|
||||
//val xInput = if(currMouseXForce < 0.2) 0.0 else ( ( currMouseXForce - 0.2 ) / 0.8)
|
||||
|
||||
//create deadzones for the constant input values.
|
||||
val xInput = remapWithDeadzone(currMouseXForce, 0.025, 1.0)
|
||||
val yInput = remapWithDeadzone(currMouseYForce, 0.025, 1.0)
|
||||
|
||||
val pitchRot = handling * currMouseYForce
|
||||
//double roll
|
||||
val rollRot = handling * 1.5 * currMouseXForce
|
||||
|
||||
//mult by 2 so you can roll twice as fast as you can pitch.
|
||||
//val rollRot = min( handling*2, max(-handling*2, xMouse ) )
|
||||
|
||||
//Ignore x,y,z its angular velocity:
|
||||
//yaw, pitch, roll
|
||||
return Vec3(0.0, pitchRot, rollRot)
|
||||
}
|
||||
|
||||
override fun fuelBar(entity: PokemonEntity, driver: Player): Float {
|
||||
return 0.5f
|
||||
}
|
||||
|
||||
override fun canJump(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
return Vec3.ZERO
|
||||
}
|
||||
|
||||
//Going to use my own gravity calculations for now.
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double {
|
||||
|
||||
var grav = 0.0
|
||||
|
||||
if( maxSpeed <= 0.5 ) grav = 0.5 - maxSpeed
|
||||
|
||||
return grav
|
||||
}
|
||||
|
||||
|
||||
override fun shouldRoll(entity: PokemonEntity) = true
|
||||
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(gravity.toString())
|
||||
buffer.writeString(horizontalAcceleration.toString())
|
||||
buffer.writeString(verticalAcceleration.toString())
|
||||
buffer.writeString(speed.toString())
|
||||
buffer.writeDouble(maxSpeed)
|
||||
buffer.writeDouble(this.lastVelocity.x)
|
||||
buffer.writeDouble(this.lastVelocity.y)
|
||||
buffer.writeDouble(this.lastVelocity.z)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
gravity = buffer.readString().asExpression()
|
||||
horizontalAcceleration = buffer.readString().asExpression()
|
||||
verticalAcceleration = buffer.readString().asExpression()
|
||||
speed = buffer.readString().asExpression()
|
||||
this.maxSpeed = buffer.readDouble()
|
||||
val x = buffer.readDouble()
|
||||
val y = buffer.readDouble()
|
||||
val z = buffer.readDouble()
|
||||
this.lastVelocity = Vec3(x, y, z)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
val KEY = cobblemonResource("air/jet")
|
||||
//I need a top and a bottom for the speed stat
|
||||
// I need a minimum speed stat for this ride specifically so that it caps
|
||||
// at this or slows below it and falls
|
||||
// 32 bl/s and 8 bl/s
|
||||
// min is 4 bl/s
|
||||
val MAXTOPSPEED = 2.5 // 50 bl/s
|
||||
val MINTOPSPEED = 0.35 // 7 bl/s
|
||||
val MINSPEED = 0.25 // 5 bl/s
|
||||
|
||||
//Accel will lie between 1.0 second and 5.0 seconds
|
||||
val MAXACCEL = (MAXTOPSPEED - MINSPEED) / 20 //1.0 second to max speed
|
||||
val MINACCEL = (MAXTOPSPEED - MINSPEED) / (20*5) // 5 seconds to max speed
|
||||
|
||||
//full 180 in 1 second.
|
||||
//30 degrees in 1 second.
|
||||
val MAXHANDLING = 140.0
|
||||
val MINHANDLING = 20.0
|
||||
|
||||
|
||||
val MAXYAWHANDLING = 16.0
|
||||
val MINYAWHANDLING = 8.0
|
||||
|
||||
//Fuel measured by seconds at full throttle.
|
||||
//minimum speed will consume a quarter of the fuel.
|
||||
//val MAXSTAMINA =
|
||||
}
|
||||
|
||||
//helper functions
|
||||
|
||||
//Creates a deadzone around zero that extends out to deadzoneLow in both +- and then remaps
|
||||
//the value linearly between -1.0 and 1.0 outside of the deadzone
|
||||
fun remapWithDeadzone(value: Double, deadzoneLow: Double = 0.2, deadzoneHigh: Double = 1.0): Double {
|
||||
// If the absolute value is below the deadzone, return 0.
|
||||
if (kotlin.math.abs(value) < deadzoneLow) return 0.0
|
||||
// Otherwise, subtract the deadzone and remap the remaining range to 0-1 (preserving the sign).
|
||||
val sign = kotlin.math.sign(value)
|
||||
val adjusted = (kotlin.math.abs(value) - deadzoneLow) / (deadzoneHigh - deadzoneLow)
|
||||
//Attach the sign back to the vale
|
||||
return adjusted * sign
|
||||
}
|
||||
}
|
||||
-178
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonBehaviourFlag
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.states.CompositeState
|
||||
import com.cobblemon.mod.common.util.adapters.riding.RideControllerAdapter
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveInt
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class RunUpToFlightCompositeController : RideController {
|
||||
override val key = KEY
|
||||
override val poseProvider = PoseProvider(PoseType.STAND)
|
||||
.with(PoseOption(PoseType.WALK) { it.entityData.get(PokemonEntity.MOVING) })
|
||||
override val condition: (PokemonEntity) -> Boolean = { true }
|
||||
|
||||
var minimumSpeed: Expression = "0.5".asExpression()
|
||||
private set
|
||||
var minimumJump: Expression = "0.5".asExpression()
|
||||
private set
|
||||
|
||||
var landController: RideController = GenericLandController()
|
||||
private set
|
||||
var flightController: RideController = BirdAirController()
|
||||
private set
|
||||
|
||||
override fun pose(entity: PokemonEntity): PoseType {
|
||||
return getActiveController(entity).poseProvider.select(entity)
|
||||
}
|
||||
|
||||
fun getActiveController(entity: PokemonEntity): RideController {
|
||||
val state = getState(entity, ::CompositeState)
|
||||
return state.activeController ?: let {
|
||||
val controller = if (entity.getCurrentPoseType() in PoseType.FLYING_POSES) {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
flightController
|
||||
} else {
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
landController
|
||||
}
|
||||
state.activeController = controller
|
||||
state.timeTransitioned = entity.level().gameTime
|
||||
controller
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(
|
||||
entity: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val state = getState(entity, ::CompositeState)
|
||||
if (state.activeController == flightController && entity.onGround() && state.timeTransitioned + 20 < entity.level().gameTime) {
|
||||
getState(entity, ::CompositeState).activeController = landController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, false)
|
||||
}
|
||||
|
||||
return getActiveController(entity).speed(entity, driver)
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return getActiveController(entity).rotation(entity, driver)
|
||||
}
|
||||
|
||||
override fun velocity(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
return getActiveController(entity).velocity(entity, driver, input)
|
||||
}
|
||||
|
||||
override fun angRollVel(entity: PokemonEntity, driver: Player, deltaTime: Double): Vec3 {
|
||||
return getActiveController(entity).angRollVel(entity, driver, deltaTime)
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
return getActiveController(entity).canJump(entity, driver)
|
||||
}
|
||||
|
||||
override fun jumpForce(
|
||||
entity: PokemonEntity,
|
||||
driver: Player,
|
||||
jumpStrength: Int
|
||||
): Vec3 {
|
||||
val controller = getActiveController(entity)
|
||||
if (controller == landController && jumpStrength >= getRuntime(entity).resolveInt(minimumJump)) {
|
||||
getState(entity, ::CompositeState).let {
|
||||
it.activeController = flightController
|
||||
entity.setBehaviourFlag(PokemonBehaviourFlag.FLYING, true)
|
||||
it.timeTransitioned = entity.level().gameTime
|
||||
}
|
||||
}
|
||||
return controller.jumpForce(entity, driver, jumpStrength)
|
||||
}
|
||||
|
||||
override fun gravity(entity: PokemonEntity, regularGravity: Double): Double? {
|
||||
return getActiveController(entity).gravity(entity, regularGravity)
|
||||
}
|
||||
|
||||
override fun inertia(entity: PokemonEntity): Double {
|
||||
return getActiveController(entity).inertia(entity)
|
||||
}
|
||||
|
||||
override fun shouldRoll(entity: PokemonEntity): Boolean = getActiveController(entity).shouldRoll(entity)
|
||||
|
||||
override fun useAngVelSmoothing(entity: PokemonEntity): Boolean = getActiveController(entity).useAngVelSmoothing(entity)
|
||||
|
||||
override fun rotationOnMouseXY
|
||||
(entity: PokemonEntity,
|
||||
driver: Player,
|
||||
yMouse: Double,
|
||||
xMouse: Double,
|
||||
yMouseSmoother: SmoothDouble,
|
||||
xMouseSmoother: SmoothDouble,
|
||||
sensitivity: Double,
|
||||
deltaTime: Double ): Vec3
|
||||
{
|
||||
return getActiveController(entity).rotationOnMouseXY(entity,
|
||||
driver,
|
||||
yMouse,
|
||||
xMouse,
|
||||
yMouseSmoother,
|
||||
xMouseSmoother,
|
||||
sensitivity,
|
||||
deltaTime )
|
||||
}
|
||||
|
||||
override fun dismountOnShift(entity: PokemonEntity): Boolean = getActiveController(entity).dismountOnShift(entity)
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(minimumSpeed.getString())
|
||||
buffer.writeString(minimumJump.getString())
|
||||
landController.encode(buffer)
|
||||
flightController.encode(buffer)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
minimumSpeed = buffer.readString().asExpression()
|
||||
minimumJump = buffer.readString().asExpression()
|
||||
landController = buffer.readResourceLocation().let { key ->
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
controller
|
||||
}
|
||||
flightController = buffer.readResourceLocation().let { key ->
|
||||
val controller = RideControllerAdapter.types[key]?.getConstructor()?.newInstance() ?: error("Unknown controller key: $key")
|
||||
controller.decode(buffer)
|
||||
controller
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val KEY = cobblemonResource("composite/run_up_to_flight")
|
||||
}
|
||||
}
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
|
||||
class SwimDashController : RideController {
|
||||
companion object {
|
||||
val KEY: ResourceLocation = cobblemonResource("swim/dash")
|
||||
const val DASH_TICKS: Int = 60
|
||||
}
|
||||
|
||||
var dashSpeed = 1F
|
||||
private set
|
||||
override val key: ResourceLocation = KEY
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.FLOAT).with(PoseOption(PoseType.SWIM) { it.isSwimming && it.entityData.get(PokemonEntity.MOVING) })
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
//This could be kinda weird... what if the top of the mon is in a fluid but the bottom isnt?
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
if (entity.isInWater || entity.isUnderWater) {
|
||||
return@any true
|
||||
}
|
||||
val blockState = entity.level().getBlockState(it)
|
||||
return@any !blockState.fluidState.isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates that we are currently enacting a dash, and that further movement inputs should be ignored */
|
||||
private var dashing = false
|
||||
private var ticks = 0
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
if(this.dashing) {
|
||||
if(this.ticks++ >= DASH_TICKS) {
|
||||
this.dashing = false
|
||||
}
|
||||
|
||||
return 0.0F
|
||||
}
|
||||
|
||||
this.dashing = true
|
||||
return this.dashSpeed
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
return Vec2(driver.xRot * 0.5f, driver.yRot)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val f = driver.xxa * 0.05f
|
||||
var g = driver.zza * 0.6f
|
||||
if (g <= 0.0f) {
|
||||
g *= 0.25f
|
||||
}
|
||||
|
||||
return Vec3(f.toDouble(), 0.0, g.toDouble())
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeFloat(this.dashSpeed)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.dashSpeed = buffer.readFloat()
|
||||
}
|
||||
}
|
||||
-204
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.controllers
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.controller.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.BirdAirController.Companion
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import kotlin.math.absoluteValue
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class VehicleLandController : RideController {
|
||||
companion object {
|
||||
val KEY: ResourceLocation = cobblemonResource("land/vehicle")
|
||||
|
||||
val MAXTOPSPEED = 1.0 // 20 bl/s
|
||||
val MINTOPSPEED = 0.35 // 7 bl/s
|
||||
//val MINSPEED = 0.25 // 5 bl/s
|
||||
|
||||
//Accel will lie between 1.0 second and 5.0 seconds
|
||||
val MAXACCEL = (MAXTOPSPEED ) / (20*3) //3.0 second to max speed
|
||||
val MINACCEL = (MAXTOPSPEED ) / (20*8) // 8 seconds to max speed
|
||||
|
||||
//Can rotate 90 degrees
|
||||
val MAXHANDLING = 90.0
|
||||
val MINHANDLING = 30.0
|
||||
|
||||
|
||||
val MAXYAWHANDLING = 16.0
|
||||
val MINYAWHANDLING = 8.0
|
||||
}
|
||||
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
var jumpVector = listOf("0".asExpression(), "0.3".asExpression(), "0".asExpression())
|
||||
private set
|
||||
var speed = "0.3".asExpression()
|
||||
private set
|
||||
var driveFactor = "1.0".asExpression()
|
||||
private set
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
|
||||
var minimumSpeedToTurn = "0.1".asExpression()
|
||||
private set
|
||||
var rotationSpeed = "45/20".asExpression()
|
||||
private set
|
||||
var lookYawLimit = "101".asExpression()
|
||||
private set
|
||||
|
||||
var currSpeed = 0.0
|
||||
private set
|
||||
|
||||
@Transient
|
||||
override val key: ResourceLocation = KEY
|
||||
@Transient
|
||||
override val poseProvider: PoseProvider = PoseProvider(PoseType.STAND).with(PoseOption(PoseType.WALK) { it.deltaMovement.horizontalDistance() > 0.1 })
|
||||
@Transient
|
||||
override val condition: (PokemonEntity) -> Boolean = { entity ->
|
||||
// Are there any blocks under the mon that aren't air or fluid
|
||||
// Cant just check one block since some mons may be more than one block big
|
||||
// This should be changed so that the any predicate is only ran on blocks under the mon
|
||||
Shapes.create(entity.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (entity.isInWater || entity.isUnderWater) {
|
||||
return@any false
|
||||
}
|
||||
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
|
||||
if (it.y.toDouble() == (entity.position().y)) {
|
||||
val blockState = entity.level().getBlockState(it.below())
|
||||
return@any !(!blockState.isAir && blockState.fluidState.isEmpty)
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun speed(entity: PokemonEntity, driver: Player): Float {
|
||||
|
||||
val topSpeed = entity.getRideStat( RidingStat.SPEED, RidingStyle.AIR,
|
||||
VehicleLandController.MINTOPSPEED,
|
||||
VehicleLandController.MAXTOPSPEED
|
||||
)
|
||||
val accel = entity.getRideStat( RidingStat.ACCELERATION, RidingStyle.AIR,
|
||||
VehicleLandController.MINACCEL,
|
||||
VehicleLandController.MAXACCEL
|
||||
)
|
||||
|
||||
//speed up and slow down based on input
|
||||
if( driver.zza > 0.0 && currSpeed < topSpeed)
|
||||
{
|
||||
currSpeed = min( currSpeed + accel , topSpeed)
|
||||
}
|
||||
else if ( driver.zza < 0.0 && currSpeed > 0.0)
|
||||
{
|
||||
//Decelerate is now always a constant half of max acceleration.
|
||||
currSpeed = max( currSpeed - (BirdAirController.MAXACCEL / 2) , 0.0)
|
||||
}
|
||||
|
||||
|
||||
return currSpeed.toFloat()
|
||||
}
|
||||
|
||||
override fun rotation(entity: PokemonEntity, driver: LivingEntity): Vec2 {
|
||||
val rotationDegrees = driver.xxa * getRuntime(entity).resolveFloat(this.rotationSpeed)
|
||||
return Vec2(driver.xRot, entity.yRot - rotationDegrees)
|
||||
}
|
||||
|
||||
override fun velocity(entity: PokemonEntity, driver: Player, input: Vec3): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
val driveFactor = runtime.resolveFloat(this.driveFactor)
|
||||
var g = driver.zza * driveFactor
|
||||
if (g <= 0.0f) {
|
||||
g *= runtime.resolveFloat(this.reverseDriveFactor)
|
||||
}
|
||||
if (driver.xxa != 0F && g.absoluteValue < runtime.resolveFloat(this.minimumSpeedToTurn)) {
|
||||
driver.xxa = 0F
|
||||
}
|
||||
val velocity = Vec3(0.0 /* Maybe do drifting here later */, 0.0, g.toDouble() * currSpeed)
|
||||
|
||||
return velocity
|
||||
}
|
||||
|
||||
override fun updatePassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
driver.yRot += (entity.riding.deltaRotation.y)
|
||||
driver.setYHeadRot(driver.yHeadRot + (entity.riding.deltaRotation.y))
|
||||
}
|
||||
|
||||
override fun clampPassengerRotation(entity: PokemonEntity, driver: LivingEntity) {
|
||||
val f = Mth.wrapDegrees(driver.yRot - entity.yRot)
|
||||
val runtime = getRuntime(entity)
|
||||
val lookYawLimit = runtime.resolveFloat(this.lookYawLimit)
|
||||
val g = Mth.clamp(f, -lookYawLimit, lookYawLimit)
|
||||
driver.yRotO += g - f
|
||||
driver.yRot = driver.yRot + g - f
|
||||
driver.setYHeadRot(driver.yRot)
|
||||
}
|
||||
|
||||
override fun canJump(entity: PokemonEntity, driver: Player) = getRuntime(entity).resolveBoolean(canJump)
|
||||
|
||||
override fun jumpForce(entity: PokemonEntity, driver: Player, jumpStrength: Int): Vec3 {
|
||||
val runtime = getRuntime(entity)
|
||||
runtime.environment.query.addFunction("jump_strength") { DoubleValue(jumpStrength.toDouble()) }
|
||||
val jumpVector = jumpVector.map { runtime.resolveFloat(it) }
|
||||
return Vec3(jumpVector[0].toDouble(), jumpVector[1].toDouble(), jumpVector[2].toDouble())
|
||||
}
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
buffer.writeString(this.speed.getString())
|
||||
buffer.writeString(this.canJump.getString())
|
||||
buffer.writeString(this.jumpVector[0].getString())
|
||||
buffer.writeString(this.jumpVector[1].getString())
|
||||
buffer.writeString(this.jumpVector[2].getString())
|
||||
buffer.writeString(this.driveFactor.getString())
|
||||
buffer.writeString(this.reverseDriveFactor.getString())
|
||||
buffer.writeString(this.minimumSpeedToTurn.getString())
|
||||
buffer.writeString(this.rotationSpeed.getString())
|
||||
buffer.writeString(this.lookYawLimit.getString())
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.speed = buffer.readString().asExpression()
|
||||
this.canJump = buffer.readString().asExpression()
|
||||
this.jumpVector = listOf(
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression(),
|
||||
buffer.readString().asExpression()
|
||||
)
|
||||
this.driveFactor = buffer.readString().asExpression()
|
||||
this.reverseDriveFactor = buffer.readString().asExpression()
|
||||
this.minimumSpeedToTurn = buffer.readString().asExpression()
|
||||
this.rotationSpeed = buffer.readString().asExpression()
|
||||
this.lookYawLimit = buffer.readString().asExpression()
|
||||
}
|
||||
|
||||
}
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.pokemon.riding.states
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.RidingState
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
|
||||
open class CompositeState(pokemonEntity: PokemonEntity) : RidingState {
|
||||
var activeController: RideController? = null
|
||||
var timeTransitioned = -100L
|
||||
}
|
||||
@@ -30,8 +30,6 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.entity.EntityDimensions
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Matrix4f
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
@@ -236,54 +234,4 @@ fun ByteBuf.readBitSet(size: Int): BitSet {
|
||||
return BitSet.valueOf(bs)
|
||||
}
|
||||
|
||||
fun ByteBuf.writeMatrix3f(matrix: Matrix3f) {
|
||||
this.writeFloat(matrix.m00)
|
||||
this.writeFloat(matrix.m01)
|
||||
this.writeFloat(matrix.m02)
|
||||
this.writeFloat(matrix.m10)
|
||||
this.writeFloat(matrix.m11)
|
||||
this.writeFloat(matrix.m12)
|
||||
this.writeFloat(matrix.m20)
|
||||
this.writeFloat(matrix.m21)
|
||||
this.writeFloat(matrix.m22)
|
||||
}
|
||||
|
||||
fun ByteBuf.readMatrix3f(): Matrix3f {
|
||||
return Matrix3f(
|
||||
readFloat(), readFloat(), readFloat(),
|
||||
readFloat(), readFloat(), readFloat(),
|
||||
readFloat(), readFloat(), readFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
fun ByteBuf.writeMatrix4f(matrix: Matrix4f) {
|
||||
this.writeFloat(matrix.m00())
|
||||
this.writeFloat(matrix.m01())
|
||||
this.writeFloat(matrix.m02())
|
||||
this.writeFloat(matrix.m03())
|
||||
|
||||
this.writeFloat(matrix.m10())
|
||||
this.writeFloat(matrix.m11())
|
||||
this.writeFloat(matrix.m12())
|
||||
this.writeFloat(matrix.m13())
|
||||
|
||||
this.writeFloat(matrix.m20())
|
||||
this.writeFloat(matrix.m21())
|
||||
this.writeFloat(matrix.m22())
|
||||
this.writeFloat(matrix.m23())
|
||||
|
||||
this.writeFloat(matrix.m30())
|
||||
this.writeFloat(matrix.m31())
|
||||
this.writeFloat(matrix.m32())
|
||||
this.writeFloat(matrix.m33())
|
||||
}
|
||||
|
||||
fun ByteBuf.readMatrix4f(): Matrix4f {
|
||||
return Matrix4f(
|
||||
readFloat(), readFloat(), readFloat(), readFloat(),
|
||||
readFloat(), readFloat(), readFloat(), readFloat(),
|
||||
readFloat(), readFloat(), readFloat(), readFloat(),
|
||||
readFloat(), readFloat(), readFloat(), readFloat(),
|
||||
)
|
||||
}
|
||||
|
||||
//fun
|
||||
@@ -18,8 +18,6 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.function.Consumer
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.min
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation
|
||||
@@ -87,21 +85,6 @@ fun isUuid(string: String) : Boolean {
|
||||
return Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\$").matches(string)
|
||||
}
|
||||
|
||||
fun VoxelShape.blockPositionsAsListRounded(): List<BlockPos> {
|
||||
val result = mutableListOf<BlockPos>()
|
||||
forAllBoxes { minX, minY, minZ, maxX, maxY, maxZ ->
|
||||
for (x in floor(minX).toInt() until ceil(maxX).toInt()) {
|
||||
for (y in floor(minY).toInt() until ceil(maxY).toInt()) {
|
||||
for (z in floor(minZ).toInt() until ceil(maxZ).toInt()) {
|
||||
result.add(BlockPos(x, y, z))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
fun VoxelShape.blockPositionsAsList(): List<BlockPos> {
|
||||
val result = mutableListOf<BlockPos>()
|
||||
forAllBoxes { minX, minY, minZ, maxX, maxY, maxZ ->
|
||||
|
||||
@@ -37,8 +37,6 @@ object IntRangeAdapter : JsonSerializer<IntRange>, JsonDeserializer<IntRange> {
|
||||
}
|
||||
|
||||
override fun deserialize(json: JsonElement, type: Type, context: JsonDeserializationContext): IntRange {
|
||||
val value = json.asString
|
||||
println("Deserializing IntRange from: $value")
|
||||
val (start, end) = PATTERN.find(json.asString)!!.destructured
|
||||
return if (end.isEmpty()) {
|
||||
IntRange(start.toInt(), start.toInt())
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.util.adapters.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.controller.RideController
|
||||
import com.cobblemon.mod.common.pokemon.riding.controllers.*
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* Adapter for deserializing [RideController] types.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since April 30th, 2024
|
||||
*/
|
||||
object RideControllerAdapter : JsonDeserializer<RideController> {
|
||||
val types: MutableMap<ResourceLocation, Class<out RideController>> = mutableMapOf(
|
||||
GenericLandController.KEY to GenericLandController::class.java,
|
||||
GenericLiquidController.KEY to GenericLiquidController::class.java,
|
||||
SwimDashController.KEY to SwimDashController::class.java,
|
||||
RunUpToFlightCompositeController.KEY to RunUpToFlightCompositeController::class.java,
|
||||
BirdAirController.KEY to BirdAirController::class.java,
|
||||
HelicopterAirController.KEY to HelicopterAirController::class.java,
|
||||
GliderAirController.KEY to GliderAirController::class.java,
|
||||
FallToFlightCompositeController.KEY to FallToFlightCompositeController::class.java,
|
||||
VehicleLandController.KEY to VehicleLandController::class.java,
|
||||
DolphinController.KEY to DolphinController::class.java,
|
||||
JetAirController.KEY to JetAirController::class.java
|
||||
|
||||
)
|
||||
|
||||
override fun deserialize(element: JsonElement, type: Type, context: JsonDeserializationContext): RideController {
|
||||
val root = element.asJsonObject
|
||||
val key = root.get("key").asString
|
||||
val controllerType = types[key.asIdentifierDefaultingNamespace()] ?: throw IllegalArgumentException("Unknown controller: $key")
|
||||
return context.deserialize(element, controllerType)
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.rotom_drone.sleep": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": [
|
||||
"math.sin(query.anim_time * 120) * 6",
|
||||
0,
|
||||
"math.cos(query.anim_time * 100) * 4"
|
||||
],
|
||||
"position": [
|
||||
0,
|
||||
"18 + math.sin(query.anim_time * 90) * 1",
|
||||
0
|
||||
]
|
||||
},
|
||||
"head": {
|
||||
"relative_to": {
|
||||
"rotation": "entity"
|
||||
},
|
||||
"rotation": [
|
||||
0,
|
||||
0,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.rotom_drone.circle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"rotom_drone": {
|
||||
"rotation": [30, "90 - q.anim_time*90", 0],
|
||||
"position": ["48*math.cos(q.anim_time*90)", 64, "48*math.sin(q.anim_time*90)"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
{
|
||||
"format_version": "1.12.0",
|
||||
"minecraft:geometry": [
|
||||
{
|
||||
"description": {
|
||||
"identifier": "geometry.drone_rotom",
|
||||
"texture_width": 64,
|
||||
"texture_height": 32,
|
||||
"visible_bounds_width": 8,
|
||||
"visible_bounds_height": 6.5,
|
||||
"visible_bounds_offset": [0, 2.75, 0]
|
||||
},
|
||||
"bones": [
|
||||
{
|
||||
"name": "rotom_drone",
|
||||
"pivot": [0, 0, 0]
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"parent": "rotom_drone",
|
||||
"pivot": [0, 8, 0]
|
||||
},
|
||||
{
|
||||
"name": "head",
|
||||
"parent": "body",
|
||||
"pivot": [0, 6.5, 0],
|
||||
"cubes": [
|
||||
{"origin": [-5.5, 6.5, -3.5], "size": [11, 6, 7], "uv": [0, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "eyes",
|
||||
"parent": "head",
|
||||
"pivot": [0.5, 6.5, -2.5]
|
||||
},
|
||||
{
|
||||
"name": "eye_right",
|
||||
"parent": "eyes",
|
||||
"pivot": [-2.9, 9.5, -3.5],
|
||||
"rotation": [0, 0, -7.5],
|
||||
"cubes": [
|
||||
{"origin": [-3.9, 7.5, -3.5], "size": [2, 4, 0], "inflate": 0.01, "uv": [0, 0], "mirror": true},
|
||||
{"origin": [-3.9, 9, -3.5], "size": [2, 1, 0], "inflate": 0.02, "uv": [0, 6], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pupil_right",
|
||||
"parent": "eye_right",
|
||||
"pivot": [-2.9, 9.5, -3.5],
|
||||
"cubes": [
|
||||
{"origin": [-3.4, 8, -3.5], "size": [1, 3, 0], "inflate": 0.03, "uv": [5, 0], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "eye_left",
|
||||
"parent": "eyes",
|
||||
"pivot": [2.9, 9.5, -3.5],
|
||||
"rotation": [0, 0, 7.5],
|
||||
"cubes": [
|
||||
{"origin": [1.9, 7.5, -3.5], "size": [2, 4, 0], "inflate": 0.01, "uv": [0, 13]},
|
||||
{"origin": [1.9, 9, -3.5], "size": [2, 1, 0], "inflate": 0.02, "uv": [0, 5]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "pupil_left",
|
||||
"parent": "eye_left",
|
||||
"pivot": [2.9, 9.5, -3.5],
|
||||
"cubes": [
|
||||
{"origin": [2.4, 8, -3.5], "size": [1, 3, 0], "inflate": 0.03, "uv": [6, 13]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mouth_smile",
|
||||
"parent": "head",
|
||||
"pivot": [0, 7.55, -3.5],
|
||||
"cubes": [
|
||||
{"origin": [-1, 6.95, -3.5], "size": [2, 1, 0], "inflate": 0.02, "uv": [36, 7]},
|
||||
{"origin": [-1.5, 7.25, -3.5], "size": [1, 1, 0], "inflate": 0.01, "uv": [40, 7]},
|
||||
{"origin": [0.5, 7.25, -3.5], "size": [1, 1, 0], "inflate": 0.01, "uv": [42, 7]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mouth_closed",
|
||||
"parent": "head",
|
||||
"pivot": [0, 7.45, -3.4],
|
||||
"cubes": [
|
||||
{"origin": [-0.5, 6.95, -3.4], "size": [1, 1, 0], "inflate": 0.02, "uv": [38, 8]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mouth_open",
|
||||
"parent": "head",
|
||||
"pivot": [0, 7.45, -3.4],
|
||||
"cubes": [
|
||||
{"origin": [-0.5, 6.95, -3.4], "size": [1, 1, 0], "inflate": 0.02, "uv": [36, 8]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "mouth_sad",
|
||||
"parent": "head",
|
||||
"pivot": [0, 7.6, -3.3],
|
||||
"cubes": [
|
||||
{"origin": [-1, 7.3, -3.3], "size": [2, 1, 0], "inflate": 0.02, "uv": [36, 9]},
|
||||
{"origin": [-1.5, 7, -3.3], "size": [1, 1, 0], "inflate": 0.01, "uv": [40, 9]},
|
||||
{"origin": [0.5, 7, -3.3], "size": [1, 1, 0], "inflate": 0.01, "uv": [42, 9]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "head_spike1",
|
||||
"parent": "head",
|
||||
"pivot": [0, 12.5, 0],
|
||||
"cubes": [
|
||||
{"origin": [-1.5, 11.5, -1.5], "size": [3, 4, 3], "uv": [29, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "head_spike2",
|
||||
"parent": "head_spike1",
|
||||
"pivot": [0, 15.5, 0],
|
||||
"cubes": [
|
||||
{"origin": [-1, 14.5, -1], "size": [2, 4, 2], "uv": [8, 13]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "head_spike3",
|
||||
"parent": "head_spike2",
|
||||
"pivot": [0, 18.5, 0],
|
||||
"cubes": [
|
||||
{"origin": [-0.5, 17.5, -0.5], "size": [1, 3, 1], "uv": [44, 6]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "torso",
|
||||
"parent": "body",
|
||||
"pivot": [0, 7, 0],
|
||||
"cubes": [
|
||||
{"origin": [-2, 3, -1.5], "size": [4, 4, 3], "uv": [34, 10]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "camera",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 4.65, -1.25],
|
||||
"cubes": [
|
||||
{"origin": [-1, 3.65, -2.75], "size": [2, 2, 2], "uv": [24, 13]},
|
||||
{"origin": [-0.5, 4.15, -2.75], "size": [1, 1, 0], "inflate": 0.01, "uv": [38, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "propeller_front_right",
|
||||
"parent": "torso",
|
||||
"pivot": [-1.5, 5, -1],
|
||||
"rotation": [0, 45, 0],
|
||||
"cubes": [
|
||||
{"origin": [-2, 5, -3.5], "size": [1, 0, 3], "uv": [37, 0]},
|
||||
{"origin": [-5.5, 5, -11.5], "size": [8, 0, 8], "uv": [40, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "propeller_front_left",
|
||||
"parent": "torso",
|
||||
"pivot": [1.5, 5, -1],
|
||||
"rotation": [0, -45, 0],
|
||||
"cubes": [
|
||||
{"origin": [1, 5, -3.5], "size": [1, 0, 3], "uv": [27, 0]},
|
||||
{"origin": [-2.5, 5, -11.5], "size": [8, 0, 8], "uv": [40, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "propeller_back_right",
|
||||
"parent": "torso",
|
||||
"pivot": [-1.5, 5, 1],
|
||||
"rotation": [0, -45, 0],
|
||||
"cubes": [
|
||||
{"origin": [-2, 5, 0.5], "size": [1, 0, 3], "uv": [39, 0]},
|
||||
{"origin": [-5.5, 5, 3.5], "size": [8, 0, 8], "uv": [40, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "propeller_back_left",
|
||||
"parent": "torso",
|
||||
"pivot": [1.5, 5, 1],
|
||||
"rotation": [0, 45, 0],
|
||||
"cubes": [
|
||||
{"origin": [1, 5, 0.5], "size": [1, 0, 3], "uv": [42, 3]},
|
||||
{"origin": [-2.5, 5, 3.5], "size": [8, 0, 8], "uv": [40, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tail1",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 3, 0],
|
||||
"cubes": [
|
||||
{"origin": [-1, 1, -1], "size": [2, 3, 2], "uv": [16, 13]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "tail2",
|
||||
"parent": "tail1",
|
||||
"pivot": [0, 1, 0],
|
||||
"cubes": [
|
||||
{"origin": [-0.5, -1, -0.5], "size": [1, 3, 1], "uv": [41, 3]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"poses": {
|
||||
"sleep": {
|
||||
"poseTypes": ["SLEEP"],
|
||||
"animations": ["q.bedrock('rotom_drone', 'sleep')"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "cobblemon:rotom_drone",
|
||||
"order": 0,
|
||||
"variations": [
|
||||
{
|
||||
"aspects": [],
|
||||
"poser": "cobblemon:rotom_drone",
|
||||
"model": "cobblemon:rotom_drone.geo",
|
||||
"texture": "cobblemon:textures/drone/rotom_drone.png",
|
||||
"layers": []
|
||||
}
|
||||
]
|
||||
}
|
||||
+13
-34
@@ -6,32 +6,26 @@
|
||||
"bones": {
|
||||
"arm_left": {
|
||||
"rotation": [
|
||||
"-23.2941+math.r2d(-math.cos(v.limb_swing * 38.17) * v.limb_swing_amount - math.sin(v.age_in_ticks * 5.16) * 0.05)",
|
||||
3.57079,
|
||||
"6.5998-math.r2d(math.cos(v.age_in_ticks * 5.16) * 0.05 + 0.05)"
|
||||
"math.r2d(-math.cos(v.limb_swing * 38.17) * v.limb_swing_amount - math.sin(v.age_in_ticks * 5.16) * 0.05)",
|
||||
0,
|
||||
"-math.r2d(math.cos(v.age_in_ticks * 5.16) * 0.05 + 0.05)"
|
||||
]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [
|
||||
"-20.8359+math.r2d(math.cos(v.limb_swing * 38.17) * v.limb_swing_amount + math.sin(v.age_in_ticks * 5.16) * 0.05)",
|
||||
-2.68108,
|
||||
"-7.007+math.r2d(math.cos(v.age_in_ticks * 5.16) * 0.05 + 0.05)"
|
||||
"math.r2d(math.cos(v.limb_swing * 38.17) * v.limb_swing_amount + math.sin(v.age_in_ticks * 5.16) * 0.05)",
|
||||
0,
|
||||
"math.r2d(math.cos(v.age_in_ticks * 5.16) * 0.05 + 0.05)"
|
||||
]
|
||||
},
|
||||
"pokeball": {
|
||||
"scale": 0
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": ["-87.8218+math.r2d(math.cos(v.limb_swing * 38.17 + 180) * v.limb_swing_amount * 1.4)", 8.11827, 0.65893]
|
||||
"rotation": ["math.r2d(math.cos(v.limb_swing * 38.17 + 180) * v.limb_swing_amount * 1.4)", 0, 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": ["-88.8357+math.r2d(math.cos(v.limb_swing * 38.17) * v.limb_swing_amount * 1.4)", -8.23239, 1.90829]
|
||||
},
|
||||
"body": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["7.5-v.velocity*10", 0, 0]
|
||||
"rotation": ["math.r2d(math.cos(v.limb_swing * 38.17) * v.limb_swing_amount * 1.4)", 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -130,14 +124,8 @@
|
||||
},
|
||||
"pokeball": {
|
||||
"scale": {
|
||||
"0.4583": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.3, 0.3, 0.3]
|
||||
},
|
||||
"0.5417": {
|
||||
"pre": [0.3, 0.3, 0.3],
|
||||
"post": [0.3, 0.3, 0.3]
|
||||
},
|
||||
"0.4583": {"pre": [0, 0, 0], "post": [0.3, 0.3, 0.3]},
|
||||
"0.5417": {"pre": [0.3, 0.3, 0.3], "post": [0.3, 0.3, 0.3]},
|
||||
"0.7083": [1, 1, 1]
|
||||
}
|
||||
},
|
||||
@@ -634,21 +622,12 @@
|
||||
},
|
||||
"pokeball": {
|
||||
"scale": {
|
||||
"0.9375": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.3, 0.3, 0.3]
|
||||
},
|
||||
"1.0": {
|
||||
"pre": [0.3, 0.3, 0.3],
|
||||
"post": [0.3, 0.3, 0.3]
|
||||
},
|
||||
"0.9375": {"pre": [0, 0, 0], "post": [0.3, 0.3, 0.3]},
|
||||
"1.0": {"pre": [0.3, 0.3, 0.3], "post": [0.3, 0.3, 0.3]},
|
||||
"1.1875": [1, 1, 1],
|
||||
"3.0625": [1, 1, 1],
|
||||
"3.25": [0.4, 0.4, 0.4],
|
||||
"3.375": {
|
||||
"pre": [0.4, 0.4, 0.4],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"3.375": {"pre": [0.4, 0.4, 0.4], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"leg_right": {
|
||||
|
||||
+91
-364
@@ -2272,59 +2272,23 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"0.5833": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.375": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"3.0": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"5.875": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.4167": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"0.5833": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.0417": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.375": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"3.0": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"5.875": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"0.5833": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.375": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"3.0": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"5.875": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.4167": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"0.5833": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.0417": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.375": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"3.0": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"5.875": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2589,27 +2553,15 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"3.6667": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"1.25": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"3.6667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"3.6667": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"3.6667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
@@ -8811,43 +8763,19 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.4583": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.25": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"0.5": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.25": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.4583": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.4583": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.25": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"0.5": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.25": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.4583": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11293,59 +11221,23 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"0.4167": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"0.8333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"1.125": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.6667": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.25": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"0.4167": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"0.8333": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"1.125": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.5417": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.6667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"0.4167": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"0.8333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"1.125": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.6667": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.25": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"0.4167": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"0.8333": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"1.125": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.5417": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.6667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"locator_target": {
|
||||
@@ -13637,43 +13529,19 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"1.2083": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.7083": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"1.2083": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.5417": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.7083": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"1.2083": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.7083": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"1.2083": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.5417": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.7083": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"locator_mouth": {
|
||||
@@ -13872,20 +13740,14 @@
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.125": [-0.1, 0.1, 0],
|
||||
"0.1667": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.125": [0.1, 0.1, 0],
|
||||
"0.1667": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
@@ -19235,59 +19097,23 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"0.5833": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.5833": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"3.9167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"4.0833": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.4167": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"0.5833": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.4167": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.5833": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"3.9167": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"4.0833": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"0.5833": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.5833": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"3.9167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"4.0833": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.4167": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"0.5833": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.4167": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.5833": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"3.9167": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"4.0833": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22632,10 +22458,7 @@
|
||||
},
|
||||
"0.5": [0.78, -10.13, 0.45],
|
||||
"0.5417": [-0.45, -8.03, 0.45],
|
||||
"0.5833": {
|
||||
"pre": [-0.45, -8.03, 0.45],
|
||||
"post": [-0.45, "-7.79+360", 0.45]
|
||||
},
|
||||
"0.5833": {"pre": [-0.45, -8.03, 0.45], "post": [-0.45, "-7.79+360", 0.45]},
|
||||
"0.625": [-2.7, 355.37, 0.45],
|
||||
"1.0": {
|
||||
"pre": [-9.46, "10.71+360", 0.5],
|
||||
@@ -26306,59 +26129,23 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.625": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"1.8333": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.625": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"0.3333": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"1.625": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"1.8333": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.625": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0833": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.625": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"1.8333": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.625": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.0833": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"0.3333": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"1.625": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"1.8333": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.625": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"locator_root": {
|
||||
@@ -29598,15 +29385,9 @@
|
||||
"brow": {
|
||||
"position": {
|
||||
"0.9583": [0, 0, 0],
|
||||
"1.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, -0.3]
|
||||
},
|
||||
"1.1667": {"pre": [0, 0, 0], "post": [0, 0, -0.3]},
|
||||
"2.2917": [0, 0, -0.3],
|
||||
"2.5417": {
|
||||
"pre": [0, 0, -0.3],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"2.5417": {"pre": [0, 0, -0.3], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
@@ -29941,43 +29722,19 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"1.2083": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.375": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.6667": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"1.2083": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.375": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.6667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"1.2083": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.375": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.6667": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"1.2083": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.375": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.6667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"locator_root": {
|
||||
@@ -33237,43 +32994,19 @@
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"1.2083": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.2083": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0.1, 0]
|
||||
},
|
||||
"2.4583": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"1.2083": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.2083": {"pre": [0, 0, 0], "post": [-0.1, 0.1, 0]},
|
||||
"2.4583": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"1.2083": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.2083": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0.1, 0]
|
||||
},
|
||||
"2.4583": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"1.2083": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]},
|
||||
"2.2083": {"pre": [0, 0, 0], "post": [0.1, 0.1, 0]},
|
||||
"2.4583": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"locator_root": {
|
||||
@@ -34699,20 +34432,14 @@
|
||||
"position": {
|
||||
"0.0": [-0.1, 0.1, 0],
|
||||
"0.125": [-0.1, 0.1, 0],
|
||||
"0.1667": {
|
||||
"pre": [-0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.1667": {"pre": [-0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0.1, 0],
|
||||
"0.125": [0.1, 0.1, 0],
|
||||
"0.1667": {
|
||||
"pre": [0.1, 0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
"0.1667": {"pre": [0.1, 0.1, 0], "post": [0, 0, 0]}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-11
@@ -105,7 +105,7 @@
|
||||
},
|
||||
"animation.pidgeot.air_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 1.3333,
|
||||
"animation_length": 1.33333,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": ["-10+math.sin(q.anim_time*90*3-60)*-1", 0, 0],
|
||||
@@ -116,8 +116,7 @@
|
||||
},
|
||||
"wing_closed_left": {
|
||||
"rotation": [-93.47882, -7.48957, -87.29442],
|
||||
"position": [-3.8, -1, 6],
|
||||
"scale": 0.1
|
||||
"position": [0, -1, 6]
|
||||
},
|
||||
"wing_closed_left2": {
|
||||
"rotation": [5.08957, -4.43385, -2.31336]
|
||||
@@ -382,8 +381,7 @@
|
||||
},
|
||||
"wing_closed_right": {
|
||||
"rotation": [-93.47882, 7.48957, 87.29442],
|
||||
"position": [3.8, -1, 6],
|
||||
"scale": 0.1
|
||||
"position": [0, -1, 6]
|
||||
},
|
||||
"wing_closed_right2": {
|
||||
"rotation": [5.08957, 4.43385, 2.31336]
|
||||
@@ -550,9 +548,8 @@
|
||||
"rotation": ["-17.5+math.sin(q.anim_time*90*0.8-90)*-1", 0, "0+math.sin(q.anim_time*90*0.5-120)*1"]
|
||||
},
|
||||
"wing_closed_left": {
|
||||
"rotation": [-93.47882, -7.48957, -87.29442],
|
||||
"position": [-3.8, -1, 6],
|
||||
"scale": 0.1
|
||||
"rotation": [-92.46677, -7.8791, -94.85228],
|
||||
"position": [0, -1, 6]
|
||||
},
|
||||
"wing_closed_left2": {
|
||||
"rotation": [5.08145, 3.03671, -1.64897]
|
||||
@@ -690,9 +687,8 @@
|
||||
"rotation": [0, 0, "-7.5+math.sin(q.anim_time*90*0.8-240)*10+math.sin(q.anim_time*90*12-120)*-0.4"]
|
||||
},
|
||||
"wing_closed_right": {
|
||||
"rotation": [-93.47882, 7.48957, 87.29442],
|
||||
"position": [3.8, -1, 6],
|
||||
"scale": 0.1
|
||||
"rotation": [-92.46677, 7.8791, 94.85228],
|
||||
"position": [0, -1, 6]
|
||||
},
|
||||
"wing_closed_right2": {
|
||||
"rotation": [5.08145, -3.03671, 1.64897]
|
||||
|
||||
+8
-8
@@ -1152,13 +1152,13 @@
|
||||
"rotation": [-7.32417, 1.61888, "12.3963+math.sin(q.anim_time*90*1-120)*6"]
|
||||
},
|
||||
"tail1": {
|
||||
"rotation": [-52.5, "-math.sin(q.anim_time*90*2-40)*4", 0]
|
||||
"rotation": [-47.5, "0-math.sin(q.anim_time*90*2-40)*4", 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": ["math.sin(q.anim_time*90*2-200)*2", "-math.sin(q.anim_time*90*2-80)*4", 0]
|
||||
"rotation": ["5+math.sin(q.anim_time*90*2-200)*2", "0-math.sin(q.anim_time*90*2-80)*4", 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": ["7.5+math.sin(q.anim_time*90*2-240)*2", "-math.sin(q.anim_time*90*2-120)*4", 0]
|
||||
"rotation": ["10+math.sin(q.anim_time*90*2-240)*2", "-math.sin(q.anim_time*90*2-120)*4", 0]
|
||||
},
|
||||
"tail4": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*2-280)*2", "0-math.sin(q.anim_time*90*2-160)*8", 0]
|
||||
@@ -1207,16 +1207,16 @@
|
||||
"rotation": [-7.32417, -1.61888, "-12.3963-math.sin(q.anim_time*90*1-120)*6"]
|
||||
},
|
||||
"wing_left2": {
|
||||
"rotation": [0, "27.5+math.sin(q.anim_time*90*2-60)*10", 0]
|
||||
"rotation": [0, "27.5+math.sin(q.anim_time*90*2-60)*40", 0]
|
||||
},
|
||||
"wing_right2": {
|
||||
"rotation": [0, "-27.5+math.sin(q.anim_time*90*2-60)*-10", 0]
|
||||
"rotation": [0, "-27.5-math.sin(q.anim_time*90*2-60)*40", 0]
|
||||
},
|
||||
"wing_left": {
|
||||
"rotation": ["0.1201+math.cos(q.anim_time*90*2+60)*5", "-19.9232+math.sin(q.anim_time*90*2+60)*10", 4.11867]
|
||||
"rotation": ["0.1201+math.cos(q.anim_time*90*2+60)*20", "-19.9232+math.sin(q.anim_time*90*2+60)*40", 4.11867]
|
||||
},
|
||||
"wing_right": {
|
||||
"rotation": ["0.1201+math.cos(q.anim_time*90*2+60)*5", "19.9232+math.sin(q.anim_time*90*2+60)*-10", -4.11867]
|
||||
"rotation": ["0.1201+math.cos(q.anim_time*90*2+60)*20", "19.9232-math.sin(q.anim_time*90*2+60)*40", -4.11867]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*2-160)*3", 0, 0]
|
||||
@@ -1234,7 +1234,7 @@
|
||||
"rotation": [0, 0, "math.sin(q.anim_time*90*1-360)*9"]
|
||||
},
|
||||
"body": {
|
||||
"rotation": ["15-math.sin(q.anim_time*90*2-120)*4", 0, 0],
|
||||
"rotation": ["-math.sin(q.anim_time*90*2-120)*4", 0, 0],
|
||||
"position": [0, "7.8+math.sin(q.anim_time*90*2)*2", -5.6]
|
||||
}
|
||||
}
|
||||
|
||||
+64
-1595
File diff suppressed because it is too large
Load Diff
+1
-4
@@ -26,10 +26,7 @@
|
||||
"pivot": [0, 7.75, -0.5],
|
||||
"cubes": [
|
||||
{"origin": [-4, 4.25, -4], "size": [8, 8, 7], "uv": [0, 44]}
|
||||
],
|
||||
"locators": {
|
||||
"seat_1": [0, 12, -4]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "upper_torso",
|
||||
|
||||
+3
-5
@@ -6,7 +6,7 @@
|
||||
"identifier": "geometry.dragonite",
|
||||
"texture_width": 256,
|
||||
"texture_height": 128,
|
||||
"visible_bounds_width": 9,
|
||||
"visible_bounds_width": 8,
|
||||
"visible_bounds_height": 5.5,
|
||||
"visible_bounds_offset": [0, 2.25, 0]
|
||||
},
|
||||
@@ -34,10 +34,7 @@
|
||||
"pivot": [0, 21, -0.5],
|
||||
"cubes": [
|
||||
{"origin": [-8, 19.5, -8], "size": [16, 9, 15], "inflate": 0.01, "uv": [33, 35]}
|
||||
],
|
||||
"locators": {
|
||||
"seat_1": [0, 26, 7]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "chest2",
|
||||
@@ -199,6 +196,7 @@
|
||||
"name": "head",
|
||||
"parent": "neck",
|
||||
"pivot": [0, 46, 1],
|
||||
"rotation": [0, 0, 0],
|
||||
"cubes": [
|
||||
{"origin": [-5, 41, -6], "size": [10, 11, 11], "inflate": 0.01, "uv": [0, 0]}
|
||||
]
|
||||
|
||||
+5
-6
@@ -7,8 +7,8 @@
|
||||
"texture_width": 128,
|
||||
"texture_height": 128,
|
||||
"visible_bounds_width": 9,
|
||||
"visible_bounds_height": 3,
|
||||
"visible_bounds_offset": [0, 0.5, 0]
|
||||
"visible_bounds_height": 2.5,
|
||||
"visible_bounds_offset": [0, 0.75, 0]
|
||||
},
|
||||
"bones": [
|
||||
{
|
||||
@@ -27,10 +27,7 @@
|
||||
"cubes": [
|
||||
{"origin": [-12, 0, -20], "size": [24, 16, 23], "uv": [0, 0]},
|
||||
{"origin": [-11, 6, -22.5], "size": [22, 2, 3], "inflate": 0.01, "uv": [50, 44]}
|
||||
],
|
||||
"locators": {
|
||||
"seat_1": [0, 16, -11]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "whisker_right",
|
||||
@@ -239,6 +236,7 @@
|
||||
"name": "tail",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 6, 1],
|
||||
"rotation": [0, 0, 0],
|
||||
"cubes": [
|
||||
{"origin": [-8, 0.5, 1], "size": [16, 11, 9], "uv": [0, 39]}
|
||||
]
|
||||
@@ -263,6 +261,7 @@
|
||||
"name": "tail4",
|
||||
"parent": "tail3",
|
||||
"pivot": [0, 5, 18],
|
||||
"rotation": [0, 0, 0],
|
||||
"cubes": [
|
||||
{"origin": [-6.5, 5, 17], "size": [13, 0, 8], "uv": [42, 49]}
|
||||
]
|
||||
|
||||
+1
-4
@@ -34,10 +34,7 @@
|
||||
"pivot": [0, 26.2, 0],
|
||||
"cubes": [
|
||||
{"origin": [-5, 25.2, -4], "size": [10, 7, 8], "inflate": 0.01, "uv": [26, 32]}
|
||||
],
|
||||
"locators": {
|
||||
"seat_1": [0, 29, 2]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fin",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user