forked from genewildish/Mainline
- Move effects_plugins/ to engine/effects/plugins/ - Update imports in engine/app.py - Update imports in all test files - Follows capability-based deps architecture Closes #27
54 lines
1.9 KiB
Python
54 lines
1.9 KiB
Python
import random
|
|
|
|
from engine import config
|
|
from engine.effects.types import EffectConfig, EffectContext, EffectPlugin
|
|
from engine.terminal import C_DIM, DIM, G_DIM, G_LO, RST
|
|
|
|
|
|
class GlitchEffect(EffectPlugin):
|
|
name = "glitch"
|
|
config = EffectConfig(enabled=True, intensity=1.0)
|
|
|
|
def process(self, buf: list[str], ctx: EffectContext) -> list[str]:
|
|
if not buf:
|
|
return buf
|
|
result = list(buf)
|
|
intensity = self.config.intensity
|
|
|
|
glitch_prob = 0.32 + min(0.9, ctx.mic_excess * 0.16)
|
|
glitch_prob = glitch_prob * intensity
|
|
n_hits = 4 + int(ctx.mic_excess / 2)
|
|
n_hits = int(n_hits * intensity)
|
|
|
|
if random.random() < glitch_prob:
|
|
# Store original visible lengths before any modifications
|
|
# Strip ANSI codes to get visible length
|
|
import re
|
|
|
|
ansi_pattern = re.compile(r"\x1b\[[0-9;]*[a-zA-Z]")
|
|
original_lengths = [len(ansi_pattern.sub("", line)) for line in result]
|
|
for _ in range(min(n_hits, len(result))):
|
|
gi = random.randint(0, len(result) - 1)
|
|
original_line = result[gi]
|
|
target_len = original_lengths[gi] # Use stored original length
|
|
glitch_bar = self._glitch_bar(target_len)
|
|
result[gi] = glitch_bar
|
|
return result
|
|
|
|
def _glitch_bar(self, target_len: int) -> str:
|
|
c = random.choice(["░", "▒", "─", "\xc2"])
|
|
n = random.randint(3, max(3, target_len // 2))
|
|
o = random.randint(0, max(0, target_len - n))
|
|
|
|
glitch_chars = c * n
|
|
trailing_spaces = target_len - o - n
|
|
trailing_spaces = max(0, trailing_spaces)
|
|
|
|
glitch_part = f"{G_LO}{DIM}" + glitch_chars + RST
|
|
result = " " * o + glitch_part + " " * trailing_spaces
|
|
|
|
return result
|
|
|
|
def configure(self, config: EffectConfig) -> None:
|
|
self.config = config
|