crimsonland 0.1.0.dev3__tar.gz → 0.1.0.dev5__tar.gz
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.
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/PKG-INFO +1 -1
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/pyproject.toml +1 -1
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/game_world.py +3 -14
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/gameplay.py +55 -38
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/projectiles.py +93 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/render/world_renderer.py +420 -154
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/sim/world_state.py +1 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/arsenal_debug.py +11 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/player.py +1 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/projectile_fx.py +1 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/projectile_render_debug.py +9 -2
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/assets_fetch.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/atlas.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/audio_router.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/bonuses.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/camera.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/cli.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/creatures/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/creatures/ai.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/creatures/anim.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/creatures/damage.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/creatures/runtime.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/creatures/spawn.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/demo.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/demo_trial.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/effects.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/effects_atlas.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/assets.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/boot.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/menu.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/base.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/controls.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/mods.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/options.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/play_game.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/panels/stats.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/frontend/transitions.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/game.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/game_modes.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/input_codes.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/base_gameplay_mode.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/quest_mode.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/rush_mode.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/survival_mode.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/tutorial_mode.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/modes/typo_mode.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/paths.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/perks.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/persistence/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/persistence/highscores.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/persistence/save_status.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/player_damage.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/helpers.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/registry.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/results.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/runtime.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/tier1.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/tier2.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/tier3.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/tier4.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/tier5.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/timeline.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/quests/types.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/render/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/render/terrain_fx.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/sim/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/sim/world_defs.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/terrain_assets.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/tutorial/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/tutorial/timeline.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/typo/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/typo/names.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/typo/player.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/typo/spawns.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/typo/typing.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/ui/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/ui/cursor.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/ui/demo_trial_overlay.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/ui/game_over.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/ui/hud.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/ui/perk_menu.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/aim_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/animations.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/audio_bootstrap.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/bonuses.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/camera_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/camera_shake.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/corpse_stamp_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/decals_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/empty.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/fonts.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/game_over.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/ground.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/lighting_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/particles.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/perk_menu_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/perks.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/player_sprite_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/projectiles.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/quest_title_overlay.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/registry.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/rush.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/small_font_debug.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/spawn_plan.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/sprites.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/survival.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/terrain.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/ui.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/views/wicons.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/weapon_sfx.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/crimson/weapons.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/app.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/assets.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/audio.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/config.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/console.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/fonts/__init__.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/fonts/grim_mono.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/fonts/small.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/input.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/jaz.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/math.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/music.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/paq.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/rand.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/sfx.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/sfx_map.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/terrain_render.py +0 -0
- {crimsonland-0.1.0.dev3 → crimsonland-0.1.0.dev5}/src/grim/view.py +0 -0
|
@@ -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
|
|
514
|
-
|
|
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
|
|
@@ -64,8 +64,8 @@ class PlayerState:
|
|
|
64
64
|
health: float = 100.0
|
|
65
65
|
size: float = 50.0
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
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 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
|
-
|
|
1636
|
-
|
|
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,7 +1676,7 @@ 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
|
|
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)
|
|
@@ -1713,16 +1713,16 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
|
|
|
1713
1713
|
state.secondary_projectiles.spawn(pos_x=muzzle_x, pos_y=muzzle_y, angle=shot_angle, type_id=4, owner_id=owner_id)
|
|
1714
1714
|
elif weapon_id == WeaponId.FLAMETHROWER:
|
|
1715
1715
|
# Flamethrower -> fast particle weapon (style 0), fractional ammo drain.
|
|
1716
|
-
state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=
|
|
1716
|
+
state.particles.spawn_particle(pos_x=muzzle_x, pos_y=muzzle_y, angle=particle_angle, intensity=1.0, owner_id=owner_id)
|
|
1717
1717
|
ammo_cost = 0.1
|
|
1718
1718
|
elif weapon_id == WeaponId.BLOW_TORCH:
|
|
1719
1719
|
# 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=
|
|
1720
|
+
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
1721
|
state.particles.entries[particle_id].style_id = 1
|
|
1722
1722
|
ammo_cost = 0.05
|
|
1723
1723
|
elif weapon_id == WeaponId.HR_FLAMER:
|
|
1724
1724
|
# 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=
|
|
1725
|
+
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
1726
|
state.particles.entries[particle_id].style_id = 2
|
|
1727
1727
|
ammo_cost = 0.1
|
|
1728
1728
|
elif weapon_id == WeaponId.BUBBLEGUN:
|
|
@@ -1833,15 +1833,17 @@ def player_fire_weapon(player: PlayerState, input_state: PlayerInput, dt: float,
|
|
|
1833
1833
|
player.spread_heat = min(0.48, max(0.0, player.spread_heat + spread_inc))
|
|
1834
1834
|
|
|
1835
1835
|
muzzle_inc = float(weapon.spread_heat_inc) if weapon.spread_heat_inc is not None else 0.0
|
|
1836
|
+
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:
|
|
1837
|
+
muzzle_inc = float(fire_bullets_weapon.spread_heat_inc)
|
|
1836
1838
|
player.muzzle_flash_alpha = min(1.0, player.muzzle_flash_alpha)
|
|
1837
1839
|
player.muzzle_flash_alpha = min(1.0, player.muzzle_flash_alpha + muzzle_inc)
|
|
1838
1840
|
player.muzzle_flash_alpha = min(0.8, player.muzzle_flash_alpha)
|
|
1839
1841
|
|
|
1840
1842
|
player.shot_seq += 1
|
|
1841
|
-
if not firing_during_reload and state.bonuses.reflex_boost <= 0.0:
|
|
1843
|
+
if (not firing_during_reload) and state.bonuses.reflex_boost <= 0.0 and not is_fire_bullets:
|
|
1842
1844
|
player.ammo = max(0.0, float(player.ammo) - float(ammo_cost))
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
+
if (not firing_during_reload) and player.ammo <= 0.0 and player.reload_timer <= 0.0:
|
|
1846
|
+
player_start_reload(player, state)
|
|
1845
1847
|
|
|
1846
1848
|
|
|
1847
1849
|
def player_update(player: PlayerState, input_state: PlayerInput, dt: float, state: GameplayState, *, world_size: float = 1024.0) -> None:
|
|
@@ -1885,35 +1887,50 @@ def player_update(player: PlayerState, input_state: PlayerInput, dt: float, stat
|
|
|
1885
1887
|
player.aim_heading = math.atan2(aim_dir_y, aim_dir_x) + math.pi / 2.0
|
|
1886
1888
|
|
|
1887
1889
|
# Movement.
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1890
|
+
raw_move_x = float(input_state.move_x)
|
|
1891
|
+
raw_move_y = float(input_state.move_y)
|
|
1892
|
+
raw_mag = math.hypot(raw_move_x, raw_move_y)
|
|
1893
|
+
moving_input = raw_mag > 0.2
|
|
1894
|
+
|
|
1895
|
+
if moving_input:
|
|
1896
|
+
inv = 1.0 / raw_mag if raw_mag > 1e-9 else 0.0
|
|
1897
|
+
move_x = raw_move_x * inv
|
|
1898
|
+
move_y = raw_move_y * inv
|
|
1899
|
+
player.heading = math.atan2(move_y, move_x) + math.pi / 2.0
|
|
1900
|
+
if perk_active(player, PerkId.LONG_DISTANCE_RUNNER):
|
|
1901
|
+
if player.move_speed < 2.0:
|
|
1902
|
+
player.move_speed = float(player.move_speed + dt * 4.0)
|
|
1903
|
+
player.move_speed = float(player.move_speed + dt)
|
|
1904
|
+
if player.move_speed > 2.8:
|
|
1905
|
+
player.move_speed = 2.8
|
|
1894
1906
|
else:
|
|
1895
|
-
player.
|
|
1896
|
-
|
|
1907
|
+
player.move_speed = float(player.move_speed + dt * 5.0)
|
|
1908
|
+
if player.move_speed > 2.0:
|
|
1909
|
+
player.move_speed = 2.0
|
|
1897
1910
|
else:
|
|
1898
|
-
player.
|
|
1911
|
+
player.move_speed = float(player.move_speed - dt * 15.0)
|
|
1912
|
+
if player.move_speed < 0.0:
|
|
1913
|
+
player.move_speed = 0.0
|
|
1914
|
+
move_x = math.cos(player.heading - math.pi / 2.0)
|
|
1915
|
+
move_y = math.sin(player.heading - math.pi / 2.0)
|
|
1916
|
+
|
|
1917
|
+
if player.weapon_id == WeaponId.MEAN_MINIGUN and player.move_speed > 0.8:
|
|
1918
|
+
player.move_speed = 0.8
|
|
1899
1919
|
|
|
1900
|
-
speed_multiplier = float(player.
|
|
1920
|
+
speed_multiplier = float(player.speed_multiplier)
|
|
1901
1921
|
if player.speed_bonus_timer > 0.0:
|
|
1902
1922
|
speed_multiplier += 1.0
|
|
1903
|
-
|
|
1923
|
+
|
|
1924
|
+
speed = player.move_speed * speed_multiplier * 25.0
|
|
1925
|
+
if moving_input:
|
|
1926
|
+
speed *= min(1.0, raw_mag)
|
|
1904
1927
|
if perk_active(player, PerkId.ALTERNATE_WEAPON):
|
|
1905
1928
|
speed *= 0.8
|
|
1929
|
+
|
|
1906
1930
|
player.pos_x = _clamp(player.pos_x + move_x * speed * dt, 0.0, float(world_size))
|
|
1907
1931
|
player.pos_y = _clamp(player.pos_y + move_y * speed * dt, 0.0, float(world_size))
|
|
1908
1932
|
|
|
1909
|
-
|
|
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
|
|
1933
|
+
player.move_phase += dt * player.move_speed * 19.0
|
|
1917
1934
|
|
|
1918
1935
|
stationary = abs(player.pos_x - prev_x) <= 1e-9 and abs(player.pos_y - prev_y) <= 1e-9
|
|
1919
1936
|
reload_scale = 1.0
|
|
@@ -220,6 +220,7 @@ class ProjectilePool:
|
|
|
220
220
|
damage_scale_by_type: dict[int, float] | None = None,
|
|
221
221
|
damage_scale_default: float = 1.0,
|
|
222
222
|
ion_aoe_scale: float = 1.0,
|
|
223
|
+
detail_preset: int = 5,
|
|
223
224
|
rng: Callable[[], int] | None = None,
|
|
224
225
|
runtime_state: object | None = None,
|
|
225
226
|
players: list[PlayerDamageable] | None = None,
|
|
@@ -280,6 +281,12 @@ class ProjectilePool:
|
|
|
280
281
|
if rng is None:
|
|
281
282
|
rng = _rng_zero
|
|
282
283
|
|
|
284
|
+
effects = None
|
|
285
|
+
sfx_queue = None
|
|
286
|
+
if runtime_state is not None:
|
|
287
|
+
effects = getattr(runtime_state, "effects", None)
|
|
288
|
+
sfx_queue = getattr(runtime_state, "sfx_queue", None)
|
|
289
|
+
|
|
283
290
|
hits: list[tuple[int, float, float, float, float, float, float]] = []
|
|
284
291
|
margin = 64.0
|
|
285
292
|
|
|
@@ -292,6 +299,90 @@ class ProjectilePool:
|
|
|
292
299
|
def _damage_type_for() -> int:
|
|
293
300
|
return 1
|
|
294
301
|
|
|
302
|
+
def _spawn_ion_hit_effects(type_id: int, pos_x: float, pos_y: float) -> None:
|
|
303
|
+
if effects is None or not hasattr(effects, "spawn"):
|
|
304
|
+
return
|
|
305
|
+
|
|
306
|
+
ring_scale = 0.0
|
|
307
|
+
ring_strength = 0.0
|
|
308
|
+
burst_scale = 0.0
|
|
309
|
+
if type_id == int(ProjectileTypeId.ION_MINIGUN):
|
|
310
|
+
ring_scale = 1.5
|
|
311
|
+
ring_strength = 0.1
|
|
312
|
+
burst_scale = 0.8
|
|
313
|
+
elif type_id == int(ProjectileTypeId.ION_RIFLE):
|
|
314
|
+
ring_scale = 1.2
|
|
315
|
+
ring_strength = 0.4
|
|
316
|
+
burst_scale = 1.2
|
|
317
|
+
elif type_id == int(ProjectileTypeId.ION_CANNON):
|
|
318
|
+
ring_scale = 1.0
|
|
319
|
+
ring_strength = 1.0
|
|
320
|
+
burst_scale = 2.2
|
|
321
|
+
if isinstance(sfx_queue, list):
|
|
322
|
+
sfx_queue.append("sfx_shockwave")
|
|
323
|
+
else:
|
|
324
|
+
return
|
|
325
|
+
|
|
326
|
+
detail = int(detail_preset)
|
|
327
|
+
|
|
328
|
+
# Port of `FUN_0042f270(pos, ring_scale, ring_strength)`: ring burst (effect_id=1).
|
|
329
|
+
effects.spawn(
|
|
330
|
+
effect_id=1,
|
|
331
|
+
pos_x=float(pos_x),
|
|
332
|
+
pos_y=float(pos_y),
|
|
333
|
+
vel_x=0.0,
|
|
334
|
+
vel_y=0.0,
|
|
335
|
+
rotation=0.0,
|
|
336
|
+
scale=1.0,
|
|
337
|
+
half_width=4.0,
|
|
338
|
+
half_height=4.0,
|
|
339
|
+
age=0.0,
|
|
340
|
+
lifetime=float(ring_strength) * 0.8,
|
|
341
|
+
flags=0x19,
|
|
342
|
+
color_r=0.6,
|
|
343
|
+
color_g=0.6,
|
|
344
|
+
color_b=0.9,
|
|
345
|
+
color_a=1.0,
|
|
346
|
+
rotation_step=0.0,
|
|
347
|
+
scale_step=float(ring_scale) * 45.0,
|
|
348
|
+
detail_preset=detail,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
# Port of `FUN_0042f540(pos, burst_scale)`: burst cloud (effect_id=0).
|
|
352
|
+
burst = float(burst_scale) * 0.8
|
|
353
|
+
lifetime = min(burst * 0.7, 1.1)
|
|
354
|
+
half = burst * 32.0
|
|
355
|
+
count = int(half)
|
|
356
|
+
if detail < 3:
|
|
357
|
+
count //= 2
|
|
358
|
+
|
|
359
|
+
for _ in range(max(0, count)):
|
|
360
|
+
rotation = float(int(rng()) & 0x7F) * 0.049087387
|
|
361
|
+
vel_x = float((int(rng()) & 0x7F) - 0x40) * burst * 1.4
|
|
362
|
+
vel_y = float((int(rng()) & 0x7F) - 0x40) * burst * 1.4
|
|
363
|
+
scale_step = (float(int(rng()) % 100) * 0.01 + 0.1) * burst
|
|
364
|
+
effects.spawn(
|
|
365
|
+
effect_id=0,
|
|
366
|
+
pos_x=float(pos_x),
|
|
367
|
+
pos_y=float(pos_y),
|
|
368
|
+
vel_x=vel_x,
|
|
369
|
+
vel_y=vel_y,
|
|
370
|
+
rotation=rotation,
|
|
371
|
+
scale=1.0,
|
|
372
|
+
half_width=half,
|
|
373
|
+
half_height=half,
|
|
374
|
+
age=0.0,
|
|
375
|
+
lifetime=float(lifetime),
|
|
376
|
+
flags=0x1D,
|
|
377
|
+
color_r=0.4,
|
|
378
|
+
color_g=0.5,
|
|
379
|
+
color_b=1.0,
|
|
380
|
+
color_a=0.5,
|
|
381
|
+
rotation_step=0.0,
|
|
382
|
+
scale_step=scale_step,
|
|
383
|
+
detail_preset=detail,
|
|
384
|
+
)
|
|
385
|
+
|
|
295
386
|
def _apply_damage_to_creature(
|
|
296
387
|
creature_index: int,
|
|
297
388
|
damage: float,
|
|
@@ -598,6 +689,8 @@ class ProjectilePool:
|
|
|
598
689
|
if type_id == ProjectileTypeId.ION_RIFLE:
|
|
599
690
|
if runtime_state is not None and getattr(runtime_state, "shock_chain_projectile_id", -1) == proj_index:
|
|
600
691
|
proj.reserved = float(int(hit_idx) + 1)
|
|
692
|
+
if type_id in (ProjectileTypeId.ION_MINIGUN, ProjectileTypeId.ION_RIFLE, ProjectileTypeId.ION_CANNON):
|
|
693
|
+
_spawn_ion_hit_effects(int(type_id), target_x, target_y)
|
|
601
694
|
elif type_id == ProjectileTypeId.PLASMA_CANNON:
|
|
602
695
|
size = float(getattr(creature, "size", 50.0) or 50.0)
|
|
603
696
|
ring_radius = size * 0.5 + 1.0
|