crimsonland 0.1.0.dev4__py3-none-any.whl → 0.1.0.dev6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
crimson/demo.py CHANGED
@@ -690,8 +690,8 @@ class DemoView:
690
690
  rl.draw_circle(int(sx), int(sy), radius, rl.Color(200, 120, 255, 255))
691
691
  continue
692
692
  if proj.type_id == 3:
693
- t = _clamp(proj.lifetime, 0.0, 1.0)
694
- radius = proj.speed * t * 80.0
693
+ t = _clamp(proj.vel_x, 0.0, 1.0)
694
+ radius = proj.vel_y * t * 80.0
695
695
  alpha = int((1.0 - t) * 180.0)
696
696
  color = rl.Color(200, 120, 255, alpha)
697
697
  rl.draw_circle_lines(int(sx), int(sy), max(1.0, radius * scale), color)
crimson/effects.py CHANGED
@@ -261,7 +261,7 @@ class ParticlePool:
261
261
  entry.age = alpha
262
262
  entry.scale_x = shade
263
263
  entry.scale_y = shade
264
- entry.scale_z = shade
264
+ # Native only updates scale_x/scale_y; scale_z stays at its spawn value (1.0).
265
265
 
266
266
  alive = entry.intensity > (0.0 if style == 0 else 0.8)
267
267
  if not alive:
crimson/game_world.py CHANGED
@@ -31,7 +31,7 @@ from .render.world_renderer import WorldRenderer
31
31
  from .audio_router import AudioRouter
32
32
  from .perks import PerkId
33
33
  from .projectiles import ProjectileTypeId
34
- from .sim.world_defs import BEAM_TYPES, CREATURE_ASSET
34
+ from .sim.world_defs import BEAM_TYPES, CREATURE_ASSET, ION_TYPES
35
35
  from .sim.world_state import ProjectileHit, WorldState
36
36
  from .weapons import WEAPON_TABLE
37
37
  from .game_modes import GameMode
@@ -510,19 +510,8 @@ class GameWorld:
510
510
  pos_y=float(target_y) + dir_y * dist * 20.0,
511
511
  rand=rand,
512
512
  )
513
- elif type_id in BEAM_TYPES:
514
- if self.ground is not None and self.fx_textures is not None:
515
- size = float(int(rand()) % 18 + 18)
516
- rotation = float(int(rand()) % 628) * 0.01
517
- self.fx_queue.add(
518
- effect_id=0x01,
519
- pos_x=float(hit_x),
520
- pos_y=float(hit_y),
521
- width=size,
522
- height=size,
523
- rotation=rotation,
524
- rgba=(0.7, 0.9, 1.0, 1.0),
525
- )
513
+ elif type_id in ION_TYPES:
514
+ pass
526
515
  elif not freeze_active:
527
516
  for _ in range(3):
528
517
  spread = float(int(rand()) % 0x14 - 10) * 0.1
crimson/gameplay.py CHANGED
@@ -64,8 +64,8 @@ class PlayerState:
64
64
  health: float = 100.0
65
65
  size: float = 50.0
66
66
 
67
- move_speed_multiplier: float = 2.0
68
- long_distance_runner_timer: float = 0.0
67
+ speed_multiplier: float = 2.0
68
+ move_speed: float = 0.0
69
69
  move_phase: float = 0.0
70
70
  heading: float = 0.0
71
71
  death_timer: float = 16.0
@@ -1592,6 +1592,7 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1592
1592
 
1593
1593
  firing_during_reload = False
1594
1594
  ammo_cost = 1.0
1595
+ is_fire_bullets = float(player.fire_bullets_timer) > 0.0
1595
1596
  if player.reload_timer > 0.0:
1596
1597
  if player.ammo <= 0 and player.experience > 0:
1597
1598
  if perk_active(player, PerkId.REGRESSION_BULLETS):
@@ -1616,7 +1617,7 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1616
1617
  else:
1617
1618
  return
1618
1619
 
1619
- if player.ammo <= 0 and not firing_during_reload:
1620
+ if player.ammo <= 0 and not firing_during_reload and not is_fire_bullets:
1620
1621
  player_start_reload(player, state)
1621
1622
  return
1622
1623
 
@@ -1624,20 +1625,18 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1624
1625
  fire_bullets_weapon = weapon_entry_for_projectile_type_id(int(ProjectileTypeId.FIRE_BULLETS))
1625
1626
 
1626
1627
  shot_cooldown = float(weapon.shot_cooldown) if weapon.shot_cooldown is not None else 0.0
1627
- spread_inc = float(weapon.spread_heat_inc) if weapon.spread_heat_inc is not None else 0.0
1628
- spread_inc *= 1.3
1629
- if player.fire_bullets_timer > 0.0 and pellet_count == 1 and fire_bullets_weapon is not None:
1628
+ spread_heat_base = float(weapon.spread_heat_inc) if weapon.spread_heat_inc is not None else 0.0
1629
+ if is_fire_bullets and pellet_count == 1 and fire_bullets_weapon is not None and fire_bullets_weapon.spread_heat_inc is not None:
1630
+ spread_heat_base = float(fire_bullets_weapon.spread_heat_inc)
1631
+
1632
+ if is_fire_bullets and pellet_count == 1 and fire_bullets_weapon is not None:
1630
1633
  shot_cooldown = (
1631
1634
  float(fire_bullets_weapon.shot_cooldown)
1632
1635
  if fire_bullets_weapon.shot_cooldown is not None
1633
1636
  else 0.0
1634
1637
  )
1635
- spread_inc = (
1636
- float(fire_bullets_weapon.spread_heat_inc)
1637
- if fire_bullets_weapon.spread_heat_inc is not None
1638
- else 0.0
1639
- )
1640
- spread_inc *= 1.3
1638
+
1639
+ spread_inc = spread_heat_base * 1.3
1641
1640
 
1642
1641
  if perk_active(player, PerkId.FASTSHOT):
1643
1642
  shot_cooldown *= 0.88
@@ -1657,6 +1656,7 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1657
1656
  aim_jitter_x = aim_x + math.cos(dir_angle) * offset
1658
1657
  aim_jitter_y = aim_y + math.sin(dir_angle) * offset
1659
1658
  shot_angle = math.atan2(aim_jitter_y - float(player.pos_y), aim_jitter_x - float(player.pos_x)) + math.pi / 2.0
1659
+ particle_angle = shot_angle - math.pi / 2.0
1660
1660
 
1661
1661
  muzzle_x = player.pos_x + player.aim_dir_x * 16.0
1662
1662
  muzzle_y = player.pos_y + player.aim_dir_y * 16.0
@@ -1676,14 +1676,12 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1676
1676
  return 0.0013
1677
1677
  return 0.0015
1678
1678
 
1679
- if player.fire_bullets_timer > 0.0:
1679
+ if is_fire_bullets:
1680
1680
  pellets = max(1, int(pellet_count))
1681
1681
  shot_count = pellets
1682
1682
  meta = _projectile_meta_for_type_id(ProjectileTypeId.FIRE_BULLETS)
1683
1683
  for _ in range(pellets):
1684
- angle = shot_angle
1685
- if pellets > 1:
1686
- angle += float(int(state.rng.rand()) % 200 - 100) * 0.0015
1684
+ angle = shot_angle + float(int(state.rng.rand()) % 200 - 100) * 0.0015
1687
1685
  state.projectiles.spawn(
1688
1686
  pos_x=muzzle_x,
1689
1687
  pos_y=muzzle_y,
@@ -1713,16 +1711,16 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1713
1711
  state.secondary_projectiles.spawn(pos_x=muzzle_x, pos_y=muzzle_y, angle=shot_angle, type_id=4, owner_id=owner_id)
1714
1712
  elif weapon_id == WeaponId.FLAMETHROWER:
1715
1713
  # Flamethrower -> fast particle weapon (style 0), fractional ammo drain.
1716
- state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=dir_angle, intensity=1.0, owner_id=owner_id)
1714
+ state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=particle_angle, intensity=1.0, owner_id=owner_id)
1717
1715
  ammo_cost = 0.1
1718
1716
  elif weapon_id == WeaponId.BLOW_TORCH:
1719
1717
  # Blow Torch -> fast particle weapon (style 1), fractional ammo drain.
1720
- particle_id = state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=dir_angle, intensity=1.0, owner_id=owner_id)
1718
+ particle_id = state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=particle_angle, intensity=1.0, owner_id=owner_id)
1721
1719
  state.particles.entries[particle_id].style_id = 1
1722
1720
  ammo_cost = 0.05
1723
1721
  elif weapon_id == WeaponId.HR_FLAMER:
1724
1722
  # HR Flamer -> fast particle weapon (style 2), fractional ammo drain.
1725
- particle_id = state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=dir_angle, intensity=1.0, owner_id=owner_id)
1723
+ particle_id = state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=particle_angle, intensity=1.0, owner_id=owner_id)
1726
1724
  state.particles.entries[particle_id].style_id = 2
1727
1725
  ammo_cost = 0.1
1728
1726
  elif weapon_id == WeaponId.BUBBLEGUN:
@@ -1833,15 +1831,17 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
1833
1831
  player.spread_heat = min(0.48, max(0.0, player.spread_heat + spread_inc))
1834
1832
 
1835
1833
  muzzle_inc = float(weapon.spread_heat_inc) if weapon.spread_heat_inc is not None else 0.0
1834
+ if is_fire_bullets and pellet_count == 1 and fire_bullets_weapon is not None and fire_bullets_weapon.spread_heat_inc is not None:
1835
+ muzzle_inc = float(fire_bullets_weapon.spread_heat_inc)
1836
1836
  player.muzzle_flash_alpha = min(1.0, player.muzzle_flash_alpha)
1837
1837
  player.muzzle_flash_alpha = min(1.0, player.muzzle_flash_alpha + muzzle_inc)
1838
1838
  player.muzzle_flash_alpha = min(0.8, player.muzzle_flash_alpha)
1839
1839
 
1840
1840
  player.shot_seq += 1
1841
- if not firing_during_reload and state.bonuses.reflex_boost <= 0.0:
1841
+ if (not firing_during_reload) and state.bonuses.reflex_boost <= 0.0 and not is_fire_bullets:
1842
1842
  player.ammo = max(0.0, float(player.ammo) - float(ammo_cost))
1843
- if player.ammo <= 0.0:
1844
- player_start_reload(player, state)
1843
+ if (not firing_during_reload) and player.ammo <= 0.0 and player.reload_timer <= 0.0:
1844
+ player_start_reload(player, state)
1845
1845
 
1846
1846
 
1847
1847
  def player_update(player: PlayerState, input_state: PlayerInput, dt: float, state: GameplayState, *, world_size: float = 1024.0) -> None:
@@ -1885,35 +1885,50 @@ def player_update(player: PlayerState, input_state: PlayerInput, dt: float, stat
1885
1885
  player.aim_heading = math.atan2(aim_dir_y, aim_dir_x) + math.pi / 2.0
1886
1886
 
1887
1887
  # Movement.
1888
- move_x, move_y = _normalize(float(input_state.move_x), float(input_state.move_y))
1889
- moving = move_x != 0.0 or move_y != 0.0
1890
- runner_bonus = 0.0
1891
- if perk_active(player, PerkId.LONG_DISTANCE_RUNNER):
1892
- if moving:
1893
- player.long_distance_runner_timer = min(1.2, float(player.long_distance_runner_timer) + dt)
1888
+ raw_move_x = float(input_state.move_x)
1889
+ raw_move_y = float(input_state.move_y)
1890
+ raw_mag = math.hypot(raw_move_x, raw_move_y)
1891
+ moving_input = raw_mag > 0.2
1892
+
1893
+ if moving_input:
1894
+ inv = 1.0 / raw_mag if raw_mag > 1e-9 else 0.0
1895
+ move_x = raw_move_x * inv
1896
+ move_y = raw_move_y * inv
1897
+ player.heading = math.atan2(move_y, move_x) + math.pi / 2.0
1898
+ if perk_active(player, PerkId.LONG_DISTANCE_RUNNER):
1899
+ if player.move_speed < 2.0:
1900
+ player.move_speed = float(player.move_speed + dt * 4.0)
1901
+ player.move_speed = float(player.move_speed + dt)
1902
+ if player.move_speed > 2.8:
1903
+ player.move_speed = 2.8
1894
1904
  else:
1895
- player.long_distance_runner_timer = max(0.0, float(player.long_distance_runner_timer) - dt * 15.0)
1896
- runner_bonus = max(0.0, min(0.8, float(player.long_distance_runner_timer) - 0.4))
1905
+ player.move_speed = float(player.move_speed + dt * 5.0)
1906
+ if player.move_speed > 2.0:
1907
+ player.move_speed = 2.0
1897
1908
  else:
1898
- player.long_distance_runner_timer = 0.0
1909
+ player.move_speed = float(player.move_speed - dt * 15.0)
1910
+ if player.move_speed < 0.0:
1911
+ player.move_speed = 0.0
1912
+ move_x = math.cos(player.heading - math.pi / 2.0)
1913
+ move_y = math.sin(player.heading - math.pi / 2.0)
1899
1914
 
1900
- speed_multiplier = float(player.move_speed_multiplier + runner_bonus)
1915
+ if player.weapon_id == WeaponId.MEAN_MINIGUN and player.move_speed > 0.8:
1916
+ player.move_speed = 0.8
1917
+
1918
+ speed_multiplier = float(player.speed_multiplier)
1901
1919
  if player.speed_bonus_timer > 0.0:
1902
1920
  speed_multiplier += 1.0
1903
- speed = 120.0 * speed_multiplier
1921
+
1922
+ speed = player.move_speed * speed_multiplier * 25.0
1923
+ if moving_input:
1924
+ speed *= min(1.0, raw_mag)
1904
1925
  if perk_active(player, PerkId.ALTERNATE_WEAPON):
1905
1926
  speed *= 0.8
1927
+
1906
1928
  player.pos_x = _clamp(player.pos_x + move_x * speed * dt, 0.0, float(world_size))
1907
1929
  player.pos_y = _clamp(player.pos_y + move_y * speed * dt, 0.0, float(world_size))
1908
1930
 
1909
- if moving:
1910
- player.heading = math.atan2(move_y, move_x) + math.pi / 2.0
1911
-
1912
- move_dist = math.hypot(player.pos_x - prev_x, player.pos_y - prev_y)
1913
- if move_dist > 1e-9:
1914
- # Port of `move_phase += frame_dt * move_speed * 19.0` (player_update).
1915
- move_speed = move_dist / dt / 120.0
1916
- player.move_phase += dt * move_speed * 19.0
1931
+ player.move_phase += dt * player.move_speed * 19.0
1917
1932
 
1918
1933
  stationary = abs(player.pos_x - prev_x) <= 1e-9 and abs(player.pos_y - prev_y) <= 1e-9
1919
1934
  reload_scale = 1.0