polats Claude Opus 4.8 (1M context) commited on
Commit
044958d
·
1 Parent(s): 3e1a2a0

Fix: roam ranged ranges were whole-screen — scale to ~8 tiles

Browse files

Ranged basic attacks + ranged skills used arena GW ranges (BOW_GW=1000 ~ 37 roam tiles)
because the roam map is far smaller in field units. Apply ROAM_RANGE_MUL (0.22) to the
hero + enemies so bow reach ~ 8 tiles and kite ~ 5 tiles. Melee + sandboxes untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

web/classesSandbox.js CHANGED
@@ -979,7 +979,10 @@ function makeActor(unit, team, id, slot) {
979
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
980
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
981
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
982
- const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)) };
 
 
 
983
  const p = FORMATION[slot % FORMATION.length];
984
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
985
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
@@ -997,7 +1000,7 @@ function makeActor(unit, team, id, slot) {
997
  armor: tpl.armor ?? 0,
998
  weapon,
999
  moveSpeed: tpl.moveSpeed,
1000
- preferredRange: tpl.preferredRange,
1001
  radius: radiusOf(unit, tpl),
1002
  maxEnergy: tpl.maxEnergy,
1003
  energyRegen: tpl.energyRegen,
@@ -1126,6 +1129,10 @@ function healActor(b, a, amount, empowered) {
1126
  }
1127
  function dealDamage(b, src, tgt, amount, label, opts = {}) {
1128
  if (!tgt.alive) return 0;
 
 
 
 
1129
  const { damageType = "physical", delivery = "spell", armorIgnoring = false, empowered = false } = opts;
1130
  const physical = delivery === "melee" || delivery === "projectile";
1131
  if (physical) {
@@ -2592,12 +2599,16 @@ async function createCombatRenderer({ pixi, defsById = {}, layers, coords, getBa
2592
  const v = view[e.who];
2593
  if (v) v.flash = 130;
2594
  playHurt(e.who, actorOf(e.who));
 
2595
  e.empowered ? floatText(e.who, "-" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "-" + e.amount, 16743018);
2596
  } else if (e.kind === "heal" && e.amount > 0) e.empowered ? floatText(e.who, "+" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "+" + e.amount, 9429896);
2597
  else if (e.kind === "cond" && e.empowered) floatText(e.who, (e.cond === "interrupted" ? "INTERRUPT" : String(e.cond).toUpperCase()) + "!", GOLD, { big: true });
2598
  else if (e.kind === "empower") flagEmpower(e.who);
2599
  else if (e.kind === "miss") floatText(e.who, "dodge", 10405352);
2600
- else if (e.kind === "death") playDie(e.who, actorOf(e.who));
 
 
 
2601
  }
2602
  }
2603
  return {
 
979
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
980
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
981
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
982
+ const rangeMul = unit.rangeMul ?? 1;
983
+ const ranged = tpl.role === "ranged";
984
+ const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)), range: Math.round((tpl.weapon.range ?? 0) * (ranged ? rangeMul : 1)) };
985
+ const preferredRange = tpl.preferredRange != null ? Math.round(tpl.preferredRange * rangeMul) : void 0;
986
  const p = FORMATION[slot % FORMATION.length];
987
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
988
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
 
1000
  armor: tpl.armor ?? 0,
1001
  weapon,
1002
  moveSpeed: tpl.moveSpeed,
1003
+ preferredRange,
1004
  radius: radiusOf(unit, tpl),
1005
  maxEnergy: tpl.maxEnergy,
1006
  energyRegen: tpl.energyRegen,
 
1129
  }
1130
  function dealDamage(b, src, tgt, amount, label, opts = {}) {
1131
  if (!tgt.alive) return 0;
1132
+ if (tgt.invulnUntil && b.t < tgt.invulnUntil) {
1133
+ log(b, "miss", tgt, { name: label });
1134
+ return 0;
1135
+ }
1136
  const { damageType = "physical", delivery = "spell", armorIgnoring = false, empowered = false } = opts;
1137
  const physical = delivery === "melee" || delivery === "projectile";
1138
  if (physical) {
 
2599
  const v = view[e.who];
2600
  if (v) v.flash = 130;
2601
  playHurt(e.who, actorOf(e.who));
2602
+ hooks.onHit?.(e);
2603
  e.empowered ? floatText(e.who, "-" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "-" + e.amount, 16743018);
2604
  } else if (e.kind === "heal" && e.amount > 0) e.empowered ? floatText(e.who, "+" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "+" + e.amount, 9429896);
2605
  else if (e.kind === "cond" && e.empowered) floatText(e.who, (e.cond === "interrupted" ? "INTERRUPT" : String(e.cond).toUpperCase()) + "!", GOLD, { big: true });
2606
  else if (e.kind === "empower") flagEmpower(e.who);
2607
  else if (e.kind === "miss") floatText(e.who, "dodge", 10405352);
2608
+ else if (e.kind === "death") {
2609
+ playDie(e.who, actorOf(e.who));
2610
+ hooks.onDeath?.(e);
2611
+ }
2612
  }
2613
  }
2614
  return {
web/comboBattler.js CHANGED
@@ -5063,7 +5063,10 @@ function makeActor(unit, team, id, slot) {
5063
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
5064
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
5065
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
5066
- const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)) };
 
 
 
5067
  const p = FORMATION[slot % FORMATION.length];
5068
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
5069
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
@@ -5081,7 +5084,7 @@ function makeActor(unit, team, id, slot) {
5081
  armor: tpl.armor ?? 0,
5082
  weapon,
5083
  moveSpeed: tpl.moveSpeed,
5084
- preferredRange: tpl.preferredRange,
5085
  radius: radiusOf(unit, tpl),
5086
  maxEnergy: tpl.maxEnergy,
5087
  energyRegen: tpl.energyRegen,
 
5063
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
5064
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
5065
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
5066
+ const rangeMul = unit.rangeMul ?? 1;
5067
+ const ranged = tpl.role === "ranged";
5068
+ const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)), range: Math.round((tpl.weapon.range ?? 0) * (ranged ? rangeMul : 1)) };
5069
+ const preferredRange = tpl.preferredRange != null ? Math.round(tpl.preferredRange * rangeMul) : void 0;
5070
  const p = FORMATION[slot % FORMATION.length];
5071
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
5072
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
 
5084
  armor: tpl.armor ?? 0,
5085
  weapon,
5086
  moveSpeed: tpl.moveSpeed,
5087
+ preferredRange,
5088
  radius: radiusOf(unit, tpl),
5089
  maxEnergy: tpl.maxEnergy,
5090
  energyRegen: tpl.energyRegen,
web/enemiesSandbox.js CHANGED
@@ -812,7 +812,10 @@ function makeActor(unit, team, id, slot) {
812
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
813
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
814
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
815
- const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)) };
 
 
 
816
  const p = FORMATION[slot % FORMATION.length];
817
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
818
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
@@ -830,7 +833,7 @@ function makeActor(unit, team, id, slot) {
830
  armor: tpl.armor ?? 0,
831
  weapon,
832
  moveSpeed: tpl.moveSpeed,
833
- preferredRange: tpl.preferredRange,
834
  radius: radiusOf(unit, tpl),
835
  maxEnergy: tpl.maxEnergy,
836
  energyRegen: tpl.energyRegen,
@@ -959,6 +962,10 @@ function healActor(b, a, amount, empowered) {
959
  }
960
  function dealDamage(b, src, tgt, amount, label, opts = {}) {
961
  if (!tgt.alive) return 0;
 
 
 
 
962
  const { damageType = "physical", delivery = "spell", armorIgnoring = false, empowered = false } = opts;
963
  const physical = delivery === "melee" || delivery === "projectile";
964
  if (physical) {
@@ -2555,12 +2562,16 @@ async function createCombatRenderer({ pixi, defsById = {}, layers, coords, getBa
2555
  const v = view[e.who];
2556
  if (v) v.flash = 130;
2557
  playHurt(e.who, actorOf(e.who));
 
2558
  e.empowered ? floatText(e.who, "-" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "-" + e.amount, 16743018);
2559
  } else if (e.kind === "heal" && e.amount > 0) e.empowered ? floatText(e.who, "+" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "+" + e.amount, 9429896);
2560
  else if (e.kind === "cond" && e.empowered) floatText(e.who, (e.cond === "interrupted" ? "INTERRUPT" : String(e.cond).toUpperCase()) + "!", GOLD, { big: true });
2561
  else if (e.kind === "empower") flagEmpower(e.who);
2562
  else if (e.kind === "miss") floatText(e.who, "dodge", 10405352);
2563
- else if (e.kind === "death") playDie(e.who, actorOf(e.who));
 
 
 
2564
  }
2565
  }
2566
  return {
 
812
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
813
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
814
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
815
+ const rangeMul = unit.rangeMul ?? 1;
816
+ const ranged = tpl.role === "ranged";
817
+ const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)), range: Math.round((tpl.weapon.range ?? 0) * (ranged ? rangeMul : 1)) };
818
+ const preferredRange = tpl.preferredRange != null ? Math.round(tpl.preferredRange * rangeMul) : void 0;
819
  const p = FORMATION[slot % FORMATION.length];
820
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
821
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
 
833
  armor: tpl.armor ?? 0,
834
  weapon,
835
  moveSpeed: tpl.moveSpeed,
836
+ preferredRange,
837
  radius: radiusOf(unit, tpl),
838
  maxEnergy: tpl.maxEnergy,
839
  energyRegen: tpl.energyRegen,
 
962
  }
963
  function dealDamage(b, src, tgt, amount, label, opts = {}) {
964
  if (!tgt.alive) return 0;
965
+ if (tgt.invulnUntil && b.t < tgt.invulnUntil) {
966
+ log(b, "miss", tgt, { name: label });
967
+ return 0;
968
+ }
969
  const { damageType = "physical", delivery = "spell", armorIgnoring = false, empowered = false } = opts;
970
  const physical = delivery === "melee" || delivery === "projectile";
971
  if (physical) {
 
2562
  const v = view[e.who];
2563
  if (v) v.flash = 130;
2564
  playHurt(e.who, actorOf(e.who));
2565
+ hooks.onHit?.(e);
2566
  e.empowered ? floatText(e.who, "-" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "-" + e.amount, 16743018);
2567
  } else if (e.kind === "heal" && e.amount > 0) e.empowered ? floatText(e.who, "+" + e.amount + "!", GOLD, { big: true }) : floatText(e.who, "+" + e.amount, 9429896);
2568
  else if (e.kind === "cond" && e.empowered) floatText(e.who, (e.cond === "interrupted" ? "INTERRUPT" : String(e.cond).toUpperCase()) + "!", GOLD, { big: true });
2569
  else if (e.kind === "empower") flagEmpower(e.who);
2570
  else if (e.kind === "miss") floatText(e.who, "dodge", 10405352);
2571
+ else if (e.kind === "death") {
2572
+ playDie(e.who, actorOf(e.who));
2573
+ hooks.onDeath?.(e);
2574
+ }
2575
  }
2576
  }
2577
  return {
web/engine.js CHANGED
@@ -786,7 +786,10 @@ function makeActor(unit, team, id, slot) {
786
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
787
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
788
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
789
- const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)) };
 
 
 
790
  const p = FORMATION[slot % FORMATION.length];
791
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
792
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
@@ -804,7 +807,7 @@ function makeActor(unit, team, id, slot) {
804
  armor: tpl.armor ?? 0,
805
  weapon,
806
  moveSpeed: tpl.moveSpeed,
807
- preferredRange: tpl.preferredRange,
808
  radius: radiusOf(unit, tpl),
809
  maxEnergy: tpl.maxEnergy,
810
  energyRegen: tpl.energyRegen,
 
786
  const hpMul = unit.hpMul ?? unit.statMul ?? 1;
787
  const dmgMul = unit.dmgMul ?? unit.statMul ?? 1;
788
  const maxHp = Math.max(1, Math.round(tpl.maxHp * hpMul));
789
+ const rangeMul = unit.rangeMul ?? 1;
790
+ const ranged = tpl.role === "ranged";
791
+ const weapon = { ...tpl.weapon, min: Math.max(1, Math.round(tpl.weapon.min * dmgMul)), max: Math.max(1, Math.round(tpl.weapon.max * dmgMul)), range: Math.round((tpl.weapon.range ?? 0) * (ranged ? rangeMul : 1)) };
792
+ const preferredRange = tpl.preferredRange != null ? Math.round(tpl.preferredRange * rangeMul) : void 0;
793
  const p = FORMATION[slot % FORMATION.length];
794
  const pt = team === "player" ? { x: p.x, y: p.y } : { x: 1 - p.x, y: 1 - p.y };
795
  const bar = (unit.skills || []).map((s) => s && typeof s === "object" ? s : skillById(s)).filter(Boolean);
 
807
  armor: tpl.armor ?? 0,
808
  weapon,
809
  moveSpeed: tpl.moveSpeed,
810
+ preferredRange,
811
  radius: radiusOf(unit, tpl),
812
  maxEnergy: tpl.maxEnergy,
813
  energyRegen: tpl.energyRegen,