Use separate textures for each race icon, display the number of spells active in the hud, and change the spell dismiss screen to reflect the location of placed spells
|
@ -115,6 +115,11 @@ public final class Race implements Affine {
|
|||
return String.format("%s.race.%s", id.getNamespace(), id.getPath().toLowerCase());
|
||||
}
|
||||
|
||||
public Identifier getIcon() {
|
||||
Identifier id = REGISTRY.getId(this);
|
||||
return new Identifier(id.getNamespace(), "textures/gui/race/" + id.getPath() + ".png");
|
||||
}
|
||||
|
||||
public boolean isPermitted(@Nullable PlayerEntity sender) {
|
||||
if (isOp() && (sender == null || !sender.getAbilities().creativeMode)) {
|
||||
return false;
|
||||
|
|
|
@ -64,6 +64,8 @@ public interface SpellContainer {
|
|||
|
||||
Stream<Spell> stream(boolean update);
|
||||
|
||||
Stream<Spell> stream(@Nullable SpellPredicate<?> type, boolean update);
|
||||
|
||||
/**
|
||||
* Removes all effects currently active in this slot.
|
||||
*/
|
||||
|
|
|
@ -168,6 +168,10 @@ public class PlaceableSpell extends AbstractDelegatingSpell implements OrientedS
|
|||
return getWorld(source).map(castEntity::get);
|
||||
}
|
||||
|
||||
public Optional<Vec3d> getPosition() {
|
||||
return castEntity.getPosition();
|
||||
}
|
||||
|
||||
public Optional<Attachment> getParticleEffectAttachment(Caster<?> source) {
|
||||
return particlEffect.update(getUuid(), source, spawner -> {
|
||||
source.getOriginVector().add(0, 5, 0);
|
||||
|
|
|
@ -11,11 +11,8 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
|||
import com.minelittlepony.unicopia.item.UItems;
|
||||
import com.minelittlepony.unicopia.network.Channel;
|
||||
import com.minelittlepony.unicopia.network.MsgRemoveSpell;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Drawable;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.Selectable;
|
||||
import net.minecraft.client.gui.*;
|
||||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||
import net.minecraft.client.sound.PositionedSoundInstance;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
@ -24,7 +21,7 @@ import net.minecraft.sound.SoundEvents;
|
|||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.StringHelper;
|
||||
import net.minecraft.util.math.Vector4f;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
public class DismissSpellScreen extends GameGui {
|
||||
private final Pony pony = Pony.of(MinecraftClient.getInstance().player);
|
||||
|
@ -41,11 +38,35 @@ public class DismissSpellScreen extends GameGui {
|
|||
double azimuth = 0;
|
||||
double ring = 2;
|
||||
|
||||
List<PlaceableSpell> placeableSpells = new ArrayList<>();
|
||||
|
||||
for (Spell spell : pony.getSpellSlot().stream(true).toList()) {
|
||||
addDrawableChild(new Entry(spell, 75 * ring - 25, azimuth));
|
||||
|
||||
if (spell instanceof PlaceableSpell placeable) {
|
||||
if (placeable.getPosition().isPresent()) {
|
||||
placeableSpells.add(placeable);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
addDrawableChild(new Entry(spell).ofRadial(75 * ring - 25, azimuth));
|
||||
ring *= 1 + 0.03 / ring;
|
||||
azimuth += Math.PI / (8 * ring);
|
||||
}
|
||||
|
||||
double minimalDistance = 75 * (ring - 1) - 25;
|
||||
Vec3d origin = pony.getOriginVector();
|
||||
|
||||
placeableSpells.forEach(placeable -> {
|
||||
placeable.getPosition().ifPresent(position -> {
|
||||
Vec3d relativePos = position.subtract(origin);
|
||||
Vec3d cartesian = relativePos
|
||||
.normalize()
|
||||
.multiply(minimalDistance + relativePos.length())
|
||||
.rotateY((pony.getEntity().getYaw() - 180) * MathHelper.RADIANS_PER_DEGREE);
|
||||
addDrawableChild(new Entry(placeable).ofCartesian(cartesian));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,8 +84,7 @@ public class DismissSpellScreen extends GameGui {
|
|||
DrawableUtil.drawArc(matrices, 160, 1600, 0, DrawableUtil.TAU, 0x00000020, false);
|
||||
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
|
||||
DrawableUtil.drawCircle(matrices, 2, 0, DrawableUtil.TAU, 0xFFAAFF99, false);
|
||||
DrawableUtil.renderRaceIcon(matrices, pony.getSpecies(), 0, 0, 16);
|
||||
matrices.pop();
|
||||
|
||||
DrawableUtil.drawLine(matrices, mouseX, mouseY - 4, mouseX, mouseY + 4, 0xFFAAFF99);
|
||||
|
@ -96,12 +116,20 @@ public class DismissSpellScreen extends GameGui {
|
|||
|
||||
private final Vector4f copy = new Vector4f();
|
||||
|
||||
public Entry(Spell spell, double radius, double azimuth) {
|
||||
public Entry(Spell spell) {
|
||||
this.spell = spell;
|
||||
this.actualSpell = getActualSpell();
|
||||
}
|
||||
|
||||
public Entry ofRadial(double radius, double azimuth) {
|
||||
SphereModel.convertToCartesianCoord(this, radius, azimuth, azimuth);
|
||||
add(0, -(float)radius / 2F, 0, 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Entry ofCartesian(Vec3d pos) {
|
||||
add((float)pos.x, (float)pos.z, (float)pos.y, 1);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Spell getActualSpell() {
|
||||
|
@ -135,17 +163,18 @@ public class DismissSpellScreen extends GameGui {
|
|||
|
||||
var type = actualSpell.getType().withTraits(actualSpell.getTraits());
|
||||
|
||||
DrawableUtil.drawLine(matrices, 0, 0, (int)getX(), (int)getY(), 0xFFAAFF99);
|
||||
DrawableUtil.renderItemIcon(actualSpell.isDead() ? UItems.BOTCHED_GEM.getDefaultStack() : type.getDefaultStack(),
|
||||
copy.getX() - 8 + (copy.getX() - mouseX - 5) / 60D,
|
||||
copy.getY() - 8 + (copy.getY() - mouseY - 5) / 60D,
|
||||
copy.getX() - 8 + copy.getZ() / 20F,
|
||||
copy.getY() - 8 + copy.getZ() / 20F,
|
||||
1
|
||||
);
|
||||
|
||||
int color = actualSpell.getType().getColor() << 2;
|
||||
|
||||
matrices.push();
|
||||
matrices.translate(getX(), getY(), 0);
|
||||
|
||||
int color = actualSpell.getType().getColor() << 2;
|
||||
|
||||
DrawableUtil.drawArc(matrices, 7, 8, 0, DrawableUtil.TAU, color | 0x00000088, false);
|
||||
|
||||
if (isMouseOver(relativeMouseX, relativeMouseY)) {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package com.minelittlepony.unicopia.client.gui;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.DrawableHelper;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.BufferRenderer;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
|
@ -44,6 +46,11 @@ public interface DrawableUtil {
|
|||
RenderSystem.applyModelViewMatrix();
|
||||
}
|
||||
|
||||
static void renderRaceIcon(MatrixStack matrices, Race race, int x, int y, int size) {
|
||||
RenderSystem.setShaderTexture(0, race.getIcon());
|
||||
DrawableHelper.drawTexture(matrices, x - size / 2, y - size / 2, 0, 0, 0, size, size, size, size);
|
||||
}
|
||||
|
||||
static void drawLine(MatrixStack matrices, int x1, int y1, int x2, int y2, int color) {
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.disableTexture();
|
||||
|
@ -64,7 +71,7 @@ public interface DrawableUtil {
|
|||
bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES, VertexFormats.POSITION_COLOR);
|
||||
bufferBuilder.vertex(matrix, x1, y1, 0).color(r, g, b, k).next();
|
||||
bufferBuilder.vertex(matrix, x2, y2, 0).color(r, g, b, k).next();
|
||||
BufferRenderer.drawWithoutShader(bufferBuilder.end());
|
||||
BufferRenderer.drawWithShader(bufferBuilder.end());
|
||||
RenderSystem.enableTexture();
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
|
|
@ -146,14 +146,7 @@ public class LanSettingsScreen extends GameGui {
|
|||
}
|
||||
|
||||
public static Style createStyle(Race race) {
|
||||
int ordinal = Race.REGISTRY.getRawId(race);
|
||||
return new Style()
|
||||
.setIcon(new TextureSprite()
|
||||
.setPosition(2, 2)
|
||||
.setSize(16, 16)
|
||||
.setTexture(TribeSelectionScreen.ICONS)
|
||||
.setTextureOffset((16 * ordinal) % 256, (ordinal / 256) * 16)
|
||||
)
|
||||
return new Style().setIcon(TribeButton.createSprite(race, 2, 2, 15))
|
||||
.setTooltip(race.getTranslationKey(), 0, 10);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.minelittlepony.unicopia.client.gui;
|
||||
|
||||
import com.minelittlepony.common.client.gui.element.Button;
|
||||
import com.minelittlepony.common.client.gui.sprite.ISprite;
|
||||
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
|
@ -22,19 +23,8 @@ public class TribeButton extends Button {
|
|||
super(x, y, 70, 70);
|
||||
this.screenWidth = screenWidth;
|
||||
this.race = race;
|
||||
int size = 32;
|
||||
int textureSize = 512;
|
||||
int ordinal = Race.REGISTRY.getRawId(race);
|
||||
|
||||
getStyle()
|
||||
.setIcon(new TextureSprite()
|
||||
.setPosition((70 - size) / 2, 0)
|
||||
.setSize(size, size)
|
||||
.setTextureSize(textureSize, textureSize)
|
||||
.setTexture(TribeSelectionScreen.ICONS)
|
||||
.setTextureOffset((size * ordinal) % textureSize, (ordinal / textureSize) * size)
|
||||
)
|
||||
.setText(race.getTranslationKey());
|
||||
getStyle().setIcon(createSprite(race, (70 - 32) / 2, 0, 32)).setText(race.getTranslationKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -77,4 +67,12 @@ public class TribeButton extends Button {
|
|||
|
||||
renderForground(matrices, mc, mouseX, mouseY, foreColor | MathHelper.ceil(alpha * 255.0F) << 24);
|
||||
}
|
||||
|
||||
public static ISprite createSprite(Race race, int x, int y, int size) {
|
||||
return new TextureSprite()
|
||||
.setPosition(x, y)
|
||||
.setSize(size, size)
|
||||
.setTextureSize(size, size)
|
||||
.setTexture(race.getIcon());
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ import net.minecraft.util.Formatting;
|
|||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class TribeSelectionScreen extends GameGui implements HidesHud {
|
||||
static final Identifier ICONS = Unicopia.id("textures/gui/icons.png");
|
||||
static final Identifier TEXTURE = Unicopia.id("textures/gui/tribe_selection.png");
|
||||
|
||||
final Set<Race> allowedRaces;
|
||||
|
|
|
@ -156,29 +156,40 @@ public class UHud extends DrawableHelper {
|
|||
}
|
||||
|
||||
public void renderSpell(CustomisedSpellType<?> spell, double x, double y) {
|
||||
if (!spell.isEmpty()) {
|
||||
Pony pony = Pony.of(client.player);
|
||||
if (spell.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (spell.isOn(pony)) {
|
||||
MatrixStack modelStack = new MatrixStack();
|
||||
Pony pony = Pony.of(client.player);
|
||||
|
||||
if (spell.isOn(pony)) {
|
||||
MatrixStack modelStack = new MatrixStack();
|
||||
|
||||
modelStack.push();
|
||||
modelStack.translate(x + 5.5, y + 5.5, 0);
|
||||
|
||||
int color = spell.type().getColor() | 0x000000FF;
|
||||
double radius = 2 + Math.sin(client.player.age / 9D) / 4;
|
||||
|
||||
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU, color & 0xFFFFFF2F, false);
|
||||
DrawableUtil.drawArc(modelStack, radius + 3, radius + 4, 0, DrawableUtil.TAU, color & 0xFFFFFFAF, false);
|
||||
pony.getSpellSlot().get(spell.and(SpellPredicate.IS_TIMED), false).map(TimedSpell::getTimer).ifPresent(timer -> {
|
||||
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU * timer.getPercentTimeRemaining(client.getTickDelta()), 0xFFFFFFFF, false);
|
||||
});
|
||||
|
||||
long count = pony.getSpellSlot().stream(spell, false).count();
|
||||
if (count > 1) {
|
||||
modelStack.push();
|
||||
modelStack.translate(x + 5.5, y + 5.5, 0);
|
||||
|
||||
int color = spell.type().getColor() | 0x000000FF;
|
||||
double radius = 2 + Math.sin(client.player.age / 9D) / 4;
|
||||
|
||||
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU, color & 0xFFFFFF2F, false);
|
||||
DrawableUtil.drawArc(modelStack, radius + 3, radius + 4, 0, DrawableUtil.TAU, color & 0xFFFFFFAF, false);
|
||||
pony.getSpellSlot().get(spell.and(SpellPredicate.IS_TIMED), false).map(TimedSpell::getTimer).ifPresent(timer -> {
|
||||
DrawableUtil.drawArc(modelStack, radius, radius + 3, 0, DrawableUtil.TAU * timer.getPercentTimeRemaining(client.getTickDelta()), 0xFFFFFFFF, false);
|
||||
});
|
||||
|
||||
modelStack.translate(1, 1, 900);
|
||||
modelStack.scale(0.8F, 0.8F, 0.8F);
|
||||
font.drawWithShadow(modelStack, count > 64 ? "64+" : String.valueOf(count), 0, 0, 0xFFFFFFFF);
|
||||
modelStack.pop();
|
||||
}
|
||||
|
||||
DrawableUtil.renderItemIcon(spell.getDefaultStack(), x, y, EQUIPPED_GEMSTONE_SCALE);
|
||||
modelStack.pop();
|
||||
}
|
||||
|
||||
DrawableUtil.renderItemIcon(spell.getDefaultStack(), x, y, EQUIPPED_GEMSTONE_SCALE);
|
||||
}
|
||||
|
||||
private void renderMessage(MatrixStack matrices, float tickDelta) {
|
||||
|
|
|
@ -2,9 +2,6 @@ package com.minelittlepony.unicopia.client.gui.spellbook;
|
|||
|
||||
import com.minelittlepony.common.client.gui.IViewRoot;
|
||||
import com.minelittlepony.common.client.gui.dimension.Bounds;
|
||||
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.client.gui.*;
|
||||
import com.minelittlepony.unicopia.entity.player.*;
|
||||
|
||||
|
@ -31,25 +28,15 @@ public class SpellbookProfilePageContent extends DrawableHelper implements Spell
|
|||
|
||||
@Override
|
||||
public void init(SpellbookScreen screen, Identifier pageId) {
|
||||
|
||||
Bounds bounds = screen.getFrameBounds();
|
||||
Race race = pony.getSpecies();
|
||||
int size = 32;
|
||||
int textureSize = 512;
|
||||
int ordinal = Race.REGISTRY.getRawId(race);
|
||||
|
||||
int x = screen.getX() + bounds.left + bounds.width / 4 - size + 10;
|
||||
int y = screen.getY() + bounds.top + bounds.height / 2;
|
||||
|
||||
|
||||
screen.addDrawable(new SpellbookScreen.ImageButton(x, y, size, size))
|
||||
.getStyle()
|
||||
.setIcon(new TextureSprite()
|
||||
.setPosition(0, 0)
|
||||
.setSize(size, size)
|
||||
.setTextureSize(textureSize, textureSize)
|
||||
.setTexture(Unicopia.id("textures/gui/icons.png"))
|
||||
.setTextureOffset((size * ordinal) % textureSize, (ordinal / textureSize) * size)
|
||||
)
|
||||
.setIcon(TribeButton.createSprite(pony.getSpecies(), 0, 0, size))
|
||||
.setTooltip(ProfileTooltip.get(pony));
|
||||
|
||||
|
||||
|
|
|
@ -91,7 +91,12 @@ public class EffectSync implements SpellContainer {
|
|||
|
||||
@Override
|
||||
public Stream<Spell> stream(boolean update) {
|
||||
return read(null, update, true);
|
||||
return stream(null, update);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Spell> stream(@Nullable SpellPredicate<?> type, boolean update) {
|
||||
return read(type, update, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Before Width: | Height: | Size: 37 KiB |
BIN
src/main/resources/assets/unicopia/textures/gui/race/alicorn.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
src/main/resources/assets/unicopia/textures/gui/race/bat.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
BIN
src/main/resources/assets/unicopia/textures/gui/race/earth.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/main/resources/assets/unicopia/textures/gui/race/human.png
Normal file
After Width: | Height: | Size: 1,010 B |
BIN
src/main/resources/assets/unicopia/textures/gui/race/pegasus.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
src/main/resources/assets/unicopia/textures/gui/race/unicorn.png
Normal file
After Width: | Height: | Size: 1.7 KiB |