Add 3D dice roll animation for thrown rocks
Emit the individual rock-die faces (0/0/1/1/2/2) from the battle resolver so the client can render a real CSS 3D cube per die that tumbles and settles on the rolled face, replacing the flat random damage number. Falls back to the flying-rock cue for older battle logs without per-die data.
This commit is contained in:
@@ -943,6 +943,95 @@ h3 {
|
||||
animation: rock-fly-left 700ms ease-in forwards;
|
||||
}
|
||||
|
||||
/* --- 3D rock dice --- */
|
||||
|
||||
.dice-tray {
|
||||
position: absolute;
|
||||
z-index: 8;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
perspective: 420px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.die {
|
||||
--size: 34px;
|
||||
--half: 17px;
|
||||
position: relative;
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
/* A filter here would flatten the cube, so it only carries the shadow. */
|
||||
filter: drop-shadow(0 4px 5px rgba(0, 0, 0, 0.45));
|
||||
}
|
||||
|
||||
.die-cube {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
transform-style: preserve-3d;
|
||||
/* From a heavily-spun start, settle onto this die's rolled face. */
|
||||
animation: die-roll 720ms cubic-bezier(0.2, 0.8, 0.3, 1) both;
|
||||
animation-delay: var(--delay, 0ms);
|
||||
}
|
||||
|
||||
@keyframes die-roll {
|
||||
0% {
|
||||
transform: rotateX(calc(var(--rx) - 900deg)) rotateY(calc(var(--ry) - 1080deg));
|
||||
}
|
||||
100% {
|
||||
transform: rotateX(var(--rx)) rotateY(var(--ry));
|
||||
}
|
||||
}
|
||||
|
||||
.die-face {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 6px;
|
||||
background: linear-gradient(145deg, var(--cream), var(--cream-dark));
|
||||
border: 2px solid var(--cocoa);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.die-front {
|
||||
transform: translateZ(var(--half));
|
||||
}
|
||||
.die-back {
|
||||
transform: rotateY(180deg) translateZ(var(--half));
|
||||
}
|
||||
.die-right {
|
||||
transform: rotateY(90deg) translateZ(var(--half));
|
||||
}
|
||||
.die-left {
|
||||
transform: rotateY(-90deg) translateZ(var(--half));
|
||||
}
|
||||
.die-top {
|
||||
transform: rotateX(90deg) translateZ(var(--half));
|
||||
}
|
||||
.die-bottom {
|
||||
transform: rotateX(-90deg) translateZ(var(--half));
|
||||
}
|
||||
|
||||
.die-pips {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
padding: 5px;
|
||||
}
|
||||
.die-pips-1 {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.die-pips-2 {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
|
||||
.die-pip {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 30%, #6b7075, #2c2f33);
|
||||
box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.35);
|
||||
}
|
||||
|
||||
@keyframes fx-pop {
|
||||
0% {
|
||||
opacity: 0;
|
||||
|
||||
Reference in New Issue
Block a user