crimsonland 0.1.0.dev7__py3-none-any.whl → 0.1.0.dev9__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/creatures/anim.py +1 -0
- crimson/game.py +5 -0
- crimson/gameplay.py +33 -8
- crimson/modes/base_gameplay_mode.py +75 -1
- crimson/modes/quest_mode.py +471 -44
- crimson/modes/rush_mode.py +12 -3
- crimson/modes/survival_mode.py +13 -2
- crimson/modes/tutorial_mode.py +12 -1
- crimson/modes/typo_mode.py +12 -4
- crimson/render/world_renderer.py +12 -16
- crimson/ui/hud.py +274 -51
- crimson/views/arsenal_debug.py +46 -1
- crimson/views/player.py +2 -2
- {crimsonland-0.1.0.dev7.dist-info → crimsonland-0.1.0.dev9.dist-info}/METADATA +1 -1
- {crimsonland-0.1.0.dev7.dist-info → crimsonland-0.1.0.dev9.dist-info}/RECORD +18 -18
- grim/console.py +14 -0
- {crimsonland-0.1.0.dev7.dist-info → crimsonland-0.1.0.dev9.dist-info}/WHEEL +0 -0
- {crimsonland-0.1.0.dev7.dist-info → crimsonland-0.1.0.dev9.dist-info}/entry_points.txt +0 -0
crimson/creatures/anim.py
CHANGED
crimson/game.py
CHANGED
|
@@ -789,6 +789,7 @@ class SurvivalGameView:
|
|
|
789
789
|
ViewContext(assets_dir=state.assets_dir),
|
|
790
790
|
texture_cache=state.texture_cache,
|
|
791
791
|
config=state.config,
|
|
792
|
+
console=state.console,
|
|
792
793
|
audio=state.audio,
|
|
793
794
|
audio_rng=state.rng,
|
|
794
795
|
)
|
|
@@ -848,6 +849,7 @@ class RushGameView:
|
|
|
848
849
|
ViewContext(assets_dir=state.assets_dir),
|
|
849
850
|
texture_cache=state.texture_cache,
|
|
850
851
|
config=state.config,
|
|
852
|
+
console=state.console,
|
|
851
853
|
audio=state.audio,
|
|
852
854
|
audio_rng=state.rng,
|
|
853
855
|
)
|
|
@@ -905,6 +907,7 @@ class TypoShooterGameView:
|
|
|
905
907
|
ViewContext(assets_dir=state.assets_dir),
|
|
906
908
|
texture_cache=state.texture_cache,
|
|
907
909
|
config=state.config,
|
|
910
|
+
console=state.console,
|
|
908
911
|
audio=state.audio,
|
|
909
912
|
audio_rng=state.rng,
|
|
910
913
|
)
|
|
@@ -962,6 +965,7 @@ class TutorialGameView:
|
|
|
962
965
|
ViewContext(assets_dir=state.assets_dir),
|
|
963
966
|
texture_cache=state.texture_cache,
|
|
964
967
|
config=state.config,
|
|
968
|
+
console=state.console,
|
|
965
969
|
audio=state.audio,
|
|
966
970
|
audio_rng=state.rng,
|
|
967
971
|
demo_mode_active=state.demo_enabled,
|
|
@@ -1011,6 +1015,7 @@ class QuestGameView:
|
|
|
1011
1015
|
ViewContext(assets_dir=state.assets_dir),
|
|
1012
1016
|
texture_cache=state.texture_cache,
|
|
1013
1017
|
config=state.config,
|
|
1018
|
+
console=state.console,
|
|
1014
1019
|
audio=state.audio,
|
|
1015
1020
|
audio_rng=state.rng,
|
|
1016
1021
|
demo_mode_active=state.demo_enabled,
|
crimson/gameplay.py
CHANGED
|
@@ -159,8 +159,11 @@ class BonusHudSlot:
|
|
|
159
159
|
bonus_id: int = 0
|
|
160
160
|
label: str = ""
|
|
161
161
|
icon_id: int = -1
|
|
162
|
+
slide_x: float = -184.0
|
|
162
163
|
timer_ref: _TimerRef | None = None
|
|
163
164
|
timer_ref_alt: _TimerRef | None = None
|
|
165
|
+
timer_value: float = 0.0
|
|
166
|
+
timer_value_alt: float = 0.0
|
|
164
167
|
|
|
165
168
|
|
|
166
169
|
BONUS_HUD_SLOT_COUNT = 16
|
|
@@ -199,8 +202,11 @@ class BonusHudState:
|
|
|
199
202
|
slot.bonus_id = int(bonus_id)
|
|
200
203
|
slot.label = label
|
|
201
204
|
slot.icon_id = int(icon_id)
|
|
205
|
+
slot.slide_x = -184.0
|
|
202
206
|
slot.timer_ref = timer_ref
|
|
203
207
|
slot.timer_ref_alt = timer_ref_alt
|
|
208
|
+
slot.timer_value = 0.0
|
|
209
|
+
slot.timer_value_alt = 0.0
|
|
204
210
|
|
|
205
211
|
|
|
206
212
|
@dataclass(slots=True)
|
|
@@ -2356,8 +2362,8 @@ def bonus_apply(
|
|
|
2356
2362
|
return
|
|
2357
2363
|
|
|
2358
2364
|
|
|
2359
|
-
def bonus_hud_update(state: GameplayState, players: list[PlayerState]) -> None:
|
|
2360
|
-
"""Refresh HUD slots based on current timer values."""
|
|
2365
|
+
def bonus_hud_update(state: GameplayState, players: list[PlayerState], *, dt: float = 0.0) -> None:
|
|
2366
|
+
"""Refresh HUD slots based on current timer values + advance slide animation."""
|
|
2361
2367
|
|
|
2362
2368
|
def _timer_value(ref: _TimerRef | None) -> float:
|
|
2363
2369
|
if ref is None:
|
|
@@ -2371,16 +2377,35 @@ def bonus_hud_update(state: GameplayState, players: list[PlayerState]) -> None:
|
|
|
2371
2377
|
return float(getattr(players[idx], ref.key, 0.0) or 0.0)
|
|
2372
2378
|
return 0.0
|
|
2373
2379
|
|
|
2374
|
-
|
|
2380
|
+
player_count = len(players)
|
|
2381
|
+
dt = max(0.0, float(dt))
|
|
2382
|
+
|
|
2383
|
+
for slot_index, slot in enumerate(state.bonus_hud.slots):
|
|
2375
2384
|
if not slot.active:
|
|
2376
2385
|
continue
|
|
2377
|
-
timer = _timer_value(slot.timer_ref)
|
|
2378
|
-
if slot.timer_ref_alt is not None
|
|
2379
|
-
|
|
2380
|
-
|
|
2386
|
+
timer = max(0.0, _timer_value(slot.timer_ref))
|
|
2387
|
+
timer_alt = max(0.0, _timer_value(slot.timer_ref_alt)) if (slot.timer_ref_alt is not None and player_count > 1) else 0.0
|
|
2388
|
+
slot.timer_value = float(timer)
|
|
2389
|
+
slot.timer_value_alt = float(timer_alt)
|
|
2390
|
+
|
|
2391
|
+
if timer > 0.0 or timer_alt > 0.0:
|
|
2392
|
+
slot.slide_x += dt * 350.0
|
|
2393
|
+
else:
|
|
2394
|
+
slot.slide_x -= dt * 320.0
|
|
2395
|
+
|
|
2396
|
+
if slot.slide_x > -2.0:
|
|
2397
|
+
slot.slide_x = -2.0
|
|
2398
|
+
|
|
2399
|
+
if slot.slide_x < -184.0 and not any(other.active for other in state.bonus_hud.slots[slot_index + 1 :]):
|
|
2381
2400
|
slot.active = False
|
|
2401
|
+
slot.bonus_id = 0
|
|
2402
|
+
slot.label = ""
|
|
2403
|
+
slot.icon_id = -1
|
|
2404
|
+
slot.slide_x = -184.0
|
|
2382
2405
|
slot.timer_ref = None
|
|
2383
2406
|
slot.timer_ref_alt = None
|
|
2407
|
+
slot.timer_value = 0.0
|
|
2408
|
+
slot.timer_value_alt = 0.0
|
|
2384
2409
|
|
|
2385
2410
|
|
|
2386
2411
|
def bonus_telekinetic_update(
|
|
@@ -2495,6 +2520,6 @@ def bonus_update(
|
|
|
2495
2520
|
state.bonuses.freeze = max(0.0, state.bonuses.freeze - dt)
|
|
2496
2521
|
|
|
2497
2522
|
if update_hud:
|
|
2498
|
-
bonus_hud_update(state, players)
|
|
2523
|
+
bonus_hud_update(state, players, dt=dt)
|
|
2499
2524
|
|
|
2500
2525
|
return pickups
|
|
@@ -8,14 +8,17 @@ import pyray as rl
|
|
|
8
8
|
|
|
9
9
|
from grim.assets import PaqTextureCache
|
|
10
10
|
from grim.audio import AudioState, update_audio
|
|
11
|
+
from grim.console import ConsoleState
|
|
11
12
|
from grim.config import CrimsonConfig
|
|
12
13
|
from grim.fonts.small import SmallFontData, draw_small_text, load_small_font, measure_small_text_width
|
|
13
14
|
from grim.view import ViewContext
|
|
14
15
|
|
|
16
|
+
from ..gameplay import _creature_find_in_radius, perk_count_get
|
|
15
17
|
from ..game_world import GameWorld
|
|
16
18
|
from ..persistence.highscores import HighScoreRecord
|
|
19
|
+
from ..perks import PerkId
|
|
17
20
|
from ..ui.game_over import GameOverUi
|
|
18
|
-
from ..ui.hud import HudAssets, load_hud_assets
|
|
21
|
+
from ..ui.hud import HudAssets, draw_target_health_bar, load_hud_assets
|
|
19
22
|
|
|
20
23
|
if TYPE_CHECKING:
|
|
21
24
|
from ..persistence.save_status import GameStatus
|
|
@@ -45,6 +48,7 @@ class BaseGameplayMode:
|
|
|
45
48
|
hardcore: bool = False,
|
|
46
49
|
texture_cache: PaqTextureCache | None = None,
|
|
47
50
|
config: CrimsonConfig | None = None,
|
|
51
|
+
console: ConsoleState | None = None,
|
|
48
52
|
audio: AudioState | None = None,
|
|
49
53
|
audio_rng: random.Random | None = None,
|
|
50
54
|
) -> None:
|
|
@@ -54,7 +58,9 @@ class BaseGameplayMode:
|
|
|
54
58
|
self._small: SmallFontData | None = None
|
|
55
59
|
self._hud_assets: HudAssets | None = None
|
|
56
60
|
|
|
61
|
+
self._default_game_mode_id = int(default_game_mode_id)
|
|
57
62
|
self._config = config
|
|
63
|
+
self._console = console
|
|
58
64
|
self._base_dir = config.path.parent if config is not None else Path.cwd()
|
|
59
65
|
|
|
60
66
|
self.close_requested = False
|
|
@@ -90,6 +96,74 @@ class BaseGameplayMode:
|
|
|
90
96
|
self._last_dt_ms = 0.0
|
|
91
97
|
self._screen_fade: _ScreenFade | None = None
|
|
92
98
|
|
|
99
|
+
def _cvar_float(self, name: str, default: float = 0.0) -> float:
|
|
100
|
+
console = self._console
|
|
101
|
+
if console is None:
|
|
102
|
+
return float(default)
|
|
103
|
+
cvar = console.cvars.get(name)
|
|
104
|
+
if cvar is None:
|
|
105
|
+
return float(default)
|
|
106
|
+
return float(cvar.value_f)
|
|
107
|
+
|
|
108
|
+
def _hud_small_indicators(self) -> bool:
|
|
109
|
+
return self._cvar_float("cv_uiSmallIndicators", 0.0) != 0.0
|
|
110
|
+
|
|
111
|
+
def _config_game_mode_id(self) -> int:
|
|
112
|
+
config = self._config
|
|
113
|
+
if config is None:
|
|
114
|
+
return int(self._default_game_mode_id)
|
|
115
|
+
try:
|
|
116
|
+
value = config.data.get("game_mode", self._default_game_mode_id)
|
|
117
|
+
return int(value or self._default_game_mode_id)
|
|
118
|
+
except Exception:
|
|
119
|
+
return int(self._default_game_mode_id)
|
|
120
|
+
|
|
121
|
+
def _draw_target_health_bar(self, *, alpha: float = 1.0) -> None:
|
|
122
|
+
creatures = getattr(self._creatures, "entries", [])
|
|
123
|
+
if not creatures:
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
if perk_count_get(self._player, PerkId.DOCTOR) <= 0:
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
target_idx = _creature_find_in_radius(
|
|
130
|
+
creatures,
|
|
131
|
+
pos_x=float(getattr(self._player, "aim_x", 0.0)),
|
|
132
|
+
pos_y=float(getattr(self._player, "aim_y", 0.0)),
|
|
133
|
+
radius=12.0,
|
|
134
|
+
start_index=0,
|
|
135
|
+
)
|
|
136
|
+
if target_idx == -1:
|
|
137
|
+
return
|
|
138
|
+
|
|
139
|
+
creature = creatures[target_idx]
|
|
140
|
+
if not bool(getattr(creature, "active", False)):
|
|
141
|
+
return
|
|
142
|
+
hp = float(getattr(creature, "hp", 0.0))
|
|
143
|
+
max_hp = float(getattr(creature, "max_hp", 0.0))
|
|
144
|
+
if hp <= 0.0 or max_hp <= 0.0:
|
|
145
|
+
return
|
|
146
|
+
|
|
147
|
+
ratio = hp / max_hp
|
|
148
|
+
if ratio < 0.0:
|
|
149
|
+
ratio = 0.0
|
|
150
|
+
if ratio > 1.0:
|
|
151
|
+
ratio = 1.0
|
|
152
|
+
|
|
153
|
+
x0, y0 = self._world.world_to_screen(float(creature.x) - 32.0, float(creature.y) + 32.0)
|
|
154
|
+
x1, _y1 = self._world.world_to_screen(float(creature.x) + 32.0, float(creature.y) + 32.0)
|
|
155
|
+
width = float(x1) - float(x0)
|
|
156
|
+
if width <= 1e-3:
|
|
157
|
+
return
|
|
158
|
+
draw_target_health_bar(
|
|
159
|
+
x=float(x0),
|
|
160
|
+
y=float(y0),
|
|
161
|
+
width=width,
|
|
162
|
+
ratio=ratio,
|
|
163
|
+
alpha=float(alpha),
|
|
164
|
+
scale=width / 64.0,
|
|
165
|
+
)
|
|
166
|
+
|
|
93
167
|
def _bind_world(self) -> None:
|
|
94
168
|
self._state = self._world.state
|
|
95
169
|
self._creatures = self._world.creatures
|