mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: burst compatiblity
This commit is contained in:
1 parent
339663adaf
commit
8033e8f7cc
8 files changed
+78
-50
No files matched your search
@@ -136,7 +136,6 @@ message GunDefinitionAutoLoader {
|
|||||||
required float clip_reload = 1;
|
required float clip_reload = 1;
|
||||||
required float intra_clip = 2;
|
required float intra_clip = 2;
|
||||||
required float shell_count = 3;
|
required float shell_count = 3;
|
||||||
optional Burst burst = 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Burst {
|
message Burst {
|
||||||
|
|||||||
@@ -408,7 +408,6 @@ export interface GunDefinitionAutoLoader {
|
|||||||
clip_reload: number;
|
clip_reload: number;
|
||||||
intra_clip: number;
|
intra_clip: number;
|
||||||
shell_count: number;
|
shell_count: number;
|
||||||
burst?: Burst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Burst {
|
export interface Burst {
|
||||||
@@ -3023,7 +3022,7 @@ export const GunDefinitionRegular: MessageFns<GunDefinitionRegular> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function createBaseGunDefinitionAutoLoader(): GunDefinitionAutoLoader {
|
function createBaseGunDefinitionAutoLoader(): GunDefinitionAutoLoader {
|
||||||
return { clip_reload: 0, intra_clip: 0, shell_count: 0, burst: undefined };
|
return { clip_reload: 0, intra_clip: 0, shell_count: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
||||||
@@ -3040,9 +3039,6 @@ export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
|||||||
if (message.shell_count !== 0) {
|
if (message.shell_count !== 0) {
|
||||||
writer.uint32(29).float(message.shell_count);
|
writer.uint32(29).float(message.shell_count);
|
||||||
}
|
}
|
||||||
if (message.burst !== undefined) {
|
|
||||||
Burst.encode(message.burst, writer.uint32(34).fork()).join();
|
|
||||||
}
|
|
||||||
return writer;
|
return writer;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3081,14 +3077,6 @@ export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
|||||||
message.shell_count = reader.float();
|
message.shell_count = reader.float();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case 4: {
|
|
||||||
if (tag !== 34) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
message.burst = Burst.decode(reader, reader.uint32());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((tag & 7) === 4 || tag === 0) {
|
if ((tag & 7) === 4 || tag === 0) {
|
||||||
break;
|
break;
|
||||||
@@ -3109,7 +3097,6 @@ export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
|||||||
shell_count: isSet(object.shell_count)
|
shell_count: isSet(object.shell_count)
|
||||||
? globalThis.Number(object.shell_count)
|
? globalThis.Number(object.shell_count)
|
||||||
: 0,
|
: 0,
|
||||||
burst: isSet(object.burst) ? Burst.fromJSON(object.burst) : undefined,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3124,9 +3111,6 @@ export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
|||||||
if (message.shell_count !== 0) {
|
if (message.shell_count !== 0) {
|
||||||
obj.shell_count = message.shell_count;
|
obj.shell_count = message.shell_count;
|
||||||
}
|
}
|
||||||
if (message.burst !== undefined) {
|
|
||||||
obj.burst = Burst.toJSON(message.burst);
|
|
||||||
}
|
|
||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3142,10 +3126,6 @@ export const GunDefinitionAutoLoader: MessageFns<GunDefinitionAutoLoader> = {
|
|||||||
message.clip_reload = object.clip_reload ?? 0;
|
message.clip_reload = object.clip_reload ?? 0;
|
||||||
message.intra_clip = object.intra_clip ?? 0;
|
message.intra_clip = object.intra_clip ?? 0;
|
||||||
message.shell_count = object.shell_count ?? 0;
|
message.shell_count = object.shell_count ?? 0;
|
||||||
message.burst =
|
|
||||||
object.burst !== undefined && object.burst !== null
|
|
||||||
? Burst.fromPartial(object.burst)
|
|
||||||
: undefined;
|
|
||||||
return message;
|
return message;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1155,7 +1155,9 @@
|
|||||||
"shellRange": "Shell range",
|
"shellRange": "Shell range",
|
||||||
"shellCapacity": "Shell capacity",
|
"shellCapacity": "Shell capacity",
|
||||||
"gunType": "Gun type",
|
"gunType": "Gun type",
|
||||||
"penetrationAt250m": "Penetration at 250m"
|
"penetrationAt250m": "Penetration at 250m",
|
||||||
|
"burstShells": "Burst shell count",
|
||||||
|
"burstInterShell": "Burst inter-shell"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1324,7 +1324,13 @@ export async function definitions() {
|
|||||||
unlocks: resolveUnlocks(gun.unlocks),
|
unlocks: resolveUnlocks(gun.unlocks),
|
||||||
shell_capacity: gun.maxAmmo ?? gunListEntry.maxAmmo,
|
shell_capacity: gun.maxAmmo ?? gunListEntry.maxAmmo,
|
||||||
assault_ranges,
|
assault_ranges,
|
||||||
|
burst:
|
||||||
|
gun.burst && gun.burst.count > 1
|
||||||
|
? {
|
||||||
|
count: gun.burst.count,
|
||||||
|
interval: 60 / gun.burst.rate,
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
gun_type:
|
gun_type:
|
||||||
gunType === 'regular'
|
gunType === 'regular'
|
||||||
? {
|
? {
|
||||||
@@ -1350,13 +1356,6 @@ export async function definitions() {
|
|||||||
intra_clip: 60 / gun.clip!.rate,
|
intra_clip: 60 / gun.clip!.rate,
|
||||||
clip_reload: gun.reloadTime,
|
clip_reload: gun.reloadTime,
|
||||||
shell_count: gunClipCount,
|
shell_count: gunClipCount,
|
||||||
burst:
|
|
||||||
gun.burst && gun.burst.count > 1
|
|
||||||
? {
|
|
||||||
count: gun.burst.count,
|
|
||||||
interval: 60 / gun.burst.rate,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} satisfies GunDefinition);
|
} satisfies GunDefinition);
|
||||||
|
|||||||
+3
-1
@@ -41,7 +41,9 @@ export function Firepower({
|
|||||||
const setPenetrationDistanceDebounced = debounce((value: number) => {
|
const setPenetrationDistanceDebounced = debounce((value: number) => {
|
||||||
setPenetrationDistance(value);
|
setPenetrationDistance(value);
|
||||||
}, 500);
|
}, 500);
|
||||||
const { gun, shell, turret } = Duel.use((state) => state.protagonist);
|
const turret = Duel.use((state) => state.protagonist.turret);
|
||||||
|
const gun = Duel.use((state) => state.protagonist.gun);
|
||||||
|
const shell = Duel.use((state) => state.protagonist.shell);
|
||||||
const penetrationDistanceInput = useRef<HTMLInputElement>(null);
|
const penetrationDistanceInput = useRef<HTMLInputElement>(null);
|
||||||
const hasSupercharger = useEquipment(107);
|
const hasSupercharger = useEquipment(107);
|
||||||
const hasCalibratedShells = useEquipment(103);
|
const hasCalibratedShells = useEquipment(103);
|
||||||
|
|||||||
+58
-18
@@ -1,5 +1,4 @@
|
|||||||
import { type Datum, type Serie } from '@nivo/line';
|
import { Box, Code } from '@radix-ui/themes';
|
||||||
import { Box } from '@radix-ui/themes';
|
|
||||||
import { times } from 'lodash-es';
|
import { times } from 'lodash-es';
|
||||||
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
import { Quicklime, type QuicklimeCallback } from 'quicklime';
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
@@ -9,6 +8,8 @@ import { VisualizerCard } from '../VisualizerCard';
|
|||||||
import { Shell } from './components/Shell';
|
import { Shell } from './components/Shell';
|
||||||
import { Target } from './components/Target';
|
import { Target } from './components/Target';
|
||||||
|
|
||||||
|
const PRECISION = 2;
|
||||||
|
|
||||||
export interface ReloadUpdateData {
|
export interface ReloadUpdateData {
|
||||||
reload: number;
|
reload: number;
|
||||||
shells: number[];
|
shells: number[];
|
||||||
@@ -16,12 +17,12 @@ export interface ReloadUpdateData {
|
|||||||
|
|
||||||
export const reloadUpdate = new Quicklime<ReloadUpdateData>();
|
export const reloadUpdate = new Quicklime<ReloadUpdateData>();
|
||||||
|
|
||||||
const T = 60;
|
|
||||||
|
|
||||||
export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
||||||
const reloadCircle = useRef<HTMLDivElement>(null);
|
const reloadCircle = useRef<HTMLDivElement>(null);
|
||||||
const reloadCore = useRef<HTMLDivElement>(null);
|
const reloadCore = useRef<HTMLDivElement>(null);
|
||||||
const reloadGlow = useRef<HTMLDivElement>(null);
|
const reloadGlow = useRef<HTMLDivElement>(null);
|
||||||
|
const totalTime = useRef<HTMLSpanElement>(null);
|
||||||
|
const progressTime = useRef<HTMLSpanElement>(null);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 3-shell gun example:
|
* 3-shell gun example:
|
||||||
@@ -38,7 +39,6 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
const state = useRef(0);
|
const state = useRef(0);
|
||||||
const dpm = useRef(0);
|
const dpm = useRef(0);
|
||||||
const shotPool = useRef(new Set<number>());
|
const shotPool = useRef(new Set<number>());
|
||||||
const data = useRef<Serie[]>([{ id: 'value', data: [] }]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancel = false;
|
let cancel = false;
|
||||||
@@ -52,6 +52,8 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function frame() {
|
function frame() {
|
||||||
|
if (!totalTime.current || !progressTime.current) return;
|
||||||
|
|
||||||
const now = Date.now() / 1000;
|
const now = Date.now() / 1000;
|
||||||
const dt = now - lastT;
|
const dt = now - lastT;
|
||||||
let reload;
|
let reload;
|
||||||
@@ -68,15 +70,30 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
reload = state.current;
|
reload = state.current;
|
||||||
shells = shellArray.fill(reload);
|
shells = shellArray.fill(reload);
|
||||||
|
|
||||||
|
totalTime.current.innerHTML = stats.shellReload!.toFixed(PRECISION);
|
||||||
|
progressTime.current.innerHTML = (
|
||||||
|
(1 - reload) *
|
||||||
|
stats.shellReload!
|
||||||
|
).toFixed(PRECISION);
|
||||||
|
|
||||||
if (state.current >= 1) shoot();
|
if (state.current >= 1) shoot();
|
||||||
} else if (state.current < stats.shells) {
|
} else if (state.current < stats.shells) {
|
||||||
state.current = Math.min(
|
const interval =
|
||||||
stats.shells,
|
stats.burstShells === 1
|
||||||
state.current + dt / stats.intraClip!,
|
? stats.intraClip!
|
||||||
);
|
: Math.floor(state.current) % stats.burstShells === 0
|
||||||
|
? stats.intraClip!
|
||||||
|
: stats.burstInterShell!;
|
||||||
|
|
||||||
|
state.current = Math.min(stats.shells, state.current + dt / interval);
|
||||||
shells = times(stats.shells, (index) => index > state.current - 1);
|
shells = times(stats.shells, (index) => index > state.current - 1);
|
||||||
reload = state.current % 1;
|
reload = state.current % 1;
|
||||||
|
|
||||||
|
totalTime.current.innerHTML = interval.toFixed(PRECISION);
|
||||||
|
progressTime.current.innerHTML = ((1 - reload) * interval).toFixed(
|
||||||
|
PRECISION,
|
||||||
|
);
|
||||||
|
|
||||||
if (lastState % 1 > state.current % 1) shoot();
|
if (lastState % 1 > state.current % 1) shoot();
|
||||||
} else {
|
} else {
|
||||||
state.current = 0;
|
state.current = 0;
|
||||||
@@ -90,15 +107,6 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
|
|
||||||
lastT = now;
|
lastT = now;
|
||||||
lastState = state.current;
|
lastState = state.current;
|
||||||
|
|
||||||
(data.current[0].data as Datum[]).push({
|
|
||||||
x: now,
|
|
||||||
y: dpm.current / (stats.dpm + stats.damage),
|
|
||||||
});
|
|
||||||
(data.current[0].data as Datum[]).splice(
|
|
||||||
0,
|
|
||||||
data.current[0].data.findIndex((d) => now - (d.x as number) < T),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frame();
|
frame();
|
||||||
@@ -216,6 +224,38 @@ export function ReloadVisualizer({ stats }: StatsAcceptorProps) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Code
|
||||||
|
ref={progressTime}
|
||||||
|
size="1"
|
||||||
|
variant="ghost"
|
||||||
|
weight="bold"
|
||||||
|
color="gray"
|
||||||
|
highContrast
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
right: 'calc(50% + var(--space-8))',
|
||||||
|
transform: 'translateX(50%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
6.9s
|
||||||
|
</Code>
|
||||||
|
<Code
|
||||||
|
ref={totalTime}
|
||||||
|
size="1"
|
||||||
|
variant="ghost"
|
||||||
|
weight="bold"
|
||||||
|
color="gray"
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: 'calc(50% + var(--space-8))',
|
||||||
|
transform: 'translateX(-50%)',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
10.0s
|
||||||
|
</Code>
|
||||||
|
|
||||||
{stats.shells > 1 &&
|
{stats.shells > 1 &&
|
||||||
times(stats.shells, (index) => (
|
times(stats.shells, (index) => (
|
||||||
<Shell stats={stats} index={index} key={index} />
|
<Shell stats={stats} index={index} key={index} />
|
||||||
|
|||||||
+2
@@ -87,6 +87,8 @@ export function Characteristics({ skeleton }: MaybeSkeletonComponentProps) {
|
|||||||
modelTransformEvent.dispatch({ pitch, yaw });
|
modelTransformEvent.dispatch({ pitch, yaw });
|
||||||
}, [hasImprovedVerticalStabilizer, hasDownImprovedVerticalStabilizer]);
|
}, [hasImprovedVerticalStabilizer, hasDownImprovedVerticalStabilizer]);
|
||||||
|
|
||||||
|
console.log(tank.slug, gun.burst, stats.burstShells);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
gap="8"
|
gap="8"
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ export function tankCharacteristics(
|
|||||||
commanderMastery *
|
commanderMastery *
|
||||||
(tank.crew.some(({ type }) => type === CrewType.DRIVER) ? 1.1 : 1.05);
|
(tank.crew.some(({ type }) => type === CrewType.DRIVER) ? 1.1 : 1.05);
|
||||||
const intraClipCoefficient = coefficient([hasShellReloadBoost, -0.3]);
|
const intraClipCoefficient = coefficient([hasShellReloadBoost, -0.3]);
|
||||||
|
const burstShells = gun.burst?.count ?? 1;
|
||||||
|
const burstInterShell = gun.burst?.interval;
|
||||||
const armorDamageCoefficient =
|
const armorDamageCoefficient =
|
||||||
coefficient([hasTungsten, 0.15]) *
|
coefficient([hasTungsten, 0.15]) *
|
||||||
coefficient(
|
coefficient(
|
||||||
@@ -581,6 +583,8 @@ export function tankCharacteristics(
|
|||||||
shellCapacity,
|
shellCapacity,
|
||||||
gunType,
|
gunType,
|
||||||
penetrationAt250m,
|
penetrationAt250m,
|
||||||
|
burstShells,
|
||||||
|
burstInterShell,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user