Scale meteor impacts by size
This commit is contained in:
+4
-1
@@ -132,11 +132,14 @@ export const PROJECTILE = {
|
||||
export const WORLD_EFFECT = {
|
||||
INTERVAL: 4000,
|
||||
AREA_TILES: 15,
|
||||
SIZE_SCALE_VARIANCE: 3,
|
||||
FRAMES: 7,
|
||||
FRAME_RATE: 14,
|
||||
FALL_DURATION: 920,
|
||||
FALL_TRAVEL_TILES: 8,
|
||||
VISUAL_SCALE: 50,
|
||||
METEOR_SHAKE_DURATION_MS: 150,
|
||||
METEOR_SHAKE_INTENSITY: 0.004,
|
||||
// 0 keeps target selection proportional to living units.
|
||||
// 1 adds pressure when a team's living share exceeds its paid spawn share.
|
||||
DOMINANCE_TARGETING_MULTIPLIER: 0.5,
|
||||
@@ -144,7 +147,7 @@ export const WORLD_EFFECT = {
|
||||
FROST_DAMAGE: 45,
|
||||
FROST_STUN_DURATION: 2000,
|
||||
FROST_STUN_TINT: 0x82e9ff,
|
||||
FROST_DURATION: 20000,
|
||||
FROST_DURATION: 2000,
|
||||
FROST_SPEED_MULTIPLIER: 0.55,
|
||||
SUDDEN_DEATH: {
|
||||
ENABLED: false,
|
||||
|
||||
@@ -125,7 +125,7 @@ function triggerWorldEffect(scene) {
|
||||
}
|
||||
|
||||
const target = chooseWorldEffectTarget(livingFighters);
|
||||
const zone = createEffectZone(target);
|
||||
const zone = createEffectZone(target, resolveWorldEffectSizeScale());
|
||||
|
||||
// Sudden Death 상태이고 냉기 고정 설정이 되어있으면 무조건 냉기 메테오
|
||||
if ((scene.isSuddenDeath && WORLD_EFFECT.SUDDEN_DEATH.FORCE_FROST) || Phaser.Math.Between(0, 1) === 0) {
|
||||
@@ -218,7 +218,7 @@ function spawnMeteor(scene, zone) {
|
||||
onImpact: () => {
|
||||
scene.tweens.killTweensOf(marker);
|
||||
marker.setAlpha(1);
|
||||
scene.cameras.main.shake(150, 0.004);
|
||||
applyMeteorImpactShake(scene, zone);
|
||||
resolveImpactDamage(scene, zone, WORLD_EFFECT.METEOR_DAMAGE);
|
||||
},
|
||||
onAnimationComplete: () => {
|
||||
@@ -239,6 +239,7 @@ function spawnFrostZone(scene, zone) {
|
||||
disposeCombatObject(scene, marker);
|
||||
},
|
||||
onImpact: () => {
|
||||
applyMeteorImpactShake(scene, zone);
|
||||
resolveImpactDamage(scene, zone, WORLD_EFFECT.FROST_DAMAGE, (fighter) => {
|
||||
applyFrostStun(scene, fighter);
|
||||
});
|
||||
@@ -261,7 +262,7 @@ function dropWorldEffectSprite(
|
||||
const sprite = scene.add
|
||||
.sprite(trajectory.startX, trajectory.startY, effectKey, 0)
|
||||
.setDepth(3)
|
||||
.setScale(WORLD_EFFECT.VISUAL_SCALE)
|
||||
.setScale(resolveWorldEffectVisualScale(zone))
|
||||
.setFlipX(trajectory.flipX)
|
||||
.setAngle(trajectory.angle)
|
||||
.setAlpha(0.9);
|
||||
@@ -300,6 +301,40 @@ function worldEffectAnimationKey(effectKey) {
|
||||
return `${effectKey}-anim`;
|
||||
}
|
||||
|
||||
function resolveWorldEffectSizeScale() {
|
||||
const variance = Math.max(0, Number(WORLD_EFFECT.SIZE_SCALE_VARIANCE) || 0);
|
||||
|
||||
if (variance === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const minScale = Math.max(0.1, 1 - variance);
|
||||
const maxScale = 1 + variance;
|
||||
|
||||
return Phaser.Math.FloatBetween(minScale, maxScale);
|
||||
}
|
||||
|
||||
function resolveWorldEffectVisualScale(zone) {
|
||||
const baseScale = Math.max(0.01, Number(WORLD_EFFECT.VISUAL_SCALE) || 1);
|
||||
return baseScale * Math.max(0.1, Number(zone?.sizeScale) || 1);
|
||||
}
|
||||
|
||||
function applyMeteorImpactShake(scene, zone) {
|
||||
const sizeScale = Math.max(0.1, Number(zone?.sizeScale) || 1);
|
||||
const duration = Math.round(
|
||||
Math.max(0, Number(WORLD_EFFECT.METEOR_SHAKE_DURATION_MS) || 0)
|
||||
* Math.sqrt(sizeScale),
|
||||
);
|
||||
const intensity =
|
||||
Math.max(0, Number(WORLD_EFFECT.METEOR_SHAKE_INTENSITY) || 0) * sizeScale;
|
||||
|
||||
if (duration <= 0 || intensity <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
scene.cameras.main.shake(duration, intensity);
|
||||
}
|
||||
|
||||
function createFallTrajectory(zone) {
|
||||
const distance = ARENA.TILE_SIZE * WORLD_EFFECT.FALL_TRAVEL_TILES;
|
||||
const isLeftHalf = zone.centerX < ARENA.SIZE / 2;
|
||||
@@ -313,16 +348,22 @@ function createFallTrajectory(zone) {
|
||||
};
|
||||
}
|
||||
|
||||
function createEffectZone(target) {
|
||||
const size = ARENA.TILE_SIZE * WORLD_EFFECT.AREA_TILES;
|
||||
function createEffectZone(target, sizeScale = 1) {
|
||||
const areaTiles = Math.max(
|
||||
1,
|
||||
(Number(WORLD_EFFECT.AREA_TILES) || 1) * Math.max(0.1, Number(sizeScale) || 1),
|
||||
);
|
||||
const size = ARENA.TILE_SIZE * areaTiles;
|
||||
const centerX = target.body?.center.x ?? target.x;
|
||||
const centerY = target.body?.center.y ?? target.y;
|
||||
|
||||
return {
|
||||
areaTiles,
|
||||
bounds: new Phaser.Geom.Rectangle(centerX - size / 2, centerY - size / 2, size, size),
|
||||
centerX,
|
||||
centerY,
|
||||
marker: null,
|
||||
sizeScale,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -336,7 +377,7 @@ function createZoneMarker(scene, zone, color) {
|
||||
marker.strokeRect(x, y, width, height);
|
||||
marker.lineStyle(1, color, 0.34);
|
||||
|
||||
for (let index = 1; index < WORLD_EFFECT.AREA_TILES; index += 1) {
|
||||
for (let index = 1; index < zone.areaTiles; index += 1) {
|
||||
const offset = index * ARENA.TILE_SIZE;
|
||||
marker.lineBetween(x + offset, y, x + offset, y + height);
|
||||
marker.lineBetween(x, y + offset, x + width, y + offset);
|
||||
|
||||
Reference in New Issue
Block a user