import 'package:flame/components.dart'; import 'package:flutter/material.dart'; import 'package:shitman/game/components/level_components.dart'; import 'package:shitman/game/components/vision_cone.dart'; import 'package:shitman/settings/app_settings.dart'; import 'dart:math'; /// PIR sensor triggered light class PIRSensorComponent extends SecurityComponent with AppSettings { bool isTriggered = false; bool lightsOn = false; bool _showDetectionRadius = true; PIRSensorComponent({ required super.position, super.detectionRange = 40.0, }) { size = Vector2(8, 8); } @override Future onLoad() async { await super.onLoad(); await initSettings(); // Initialize detection radius visibility from settings try { _showDetectionRadius = appSettings.getBool('game.show_detection_radius'); } catch (e) { _showDetectionRadius = true; // Default to visible } } @override bool detectsPlayer(Vector2 playerPosition, double playerStealthLevel) { final distance = (playerPosition - position).length; final effectiveRange = getEffectiveDetectionRange(playerStealthLevel); bool detected = distance < effectiveRange; if (detected && !isTriggered) { isTriggered = true; lightsOn = true; appLog.fine('PIR sensor triggered at $position'); } else if (!detected && isTriggered) { // Cool down period before turning off Future.delayed(const Duration(seconds: 5), () { isTriggered = false; lightsOn = false; }); } return detected; } @override void render(Canvas canvas) { // Draw detection radius if enabled if (_showDetectionRadius) { final radiusPaint = Paint() ..color = const Color(0xFFFF9800).withValues(alpha: 0.2) ..style = PaintingStyle.stroke ..strokeWidth = 2.0; canvas.drawCircle( Offset(size.x / 2, size.y / 2), detectionRange, radiusPaint, ); } // Draw PIR sensor as small circle final sensorPaint = Paint() ..color = isTriggered ? const Color(0xFFFF0000) : const Color(0xFF000000); canvas.drawCircle(Offset(size.x / 2, size.y / 2), 4, sensorPaint); // Draw light effect if triggered if (lightsOn) { final lightPaint = Paint() ..color = const Color(0xFFFFFF00).withValues(alpha: 0.3); canvas.drawCircle( Offset(size.x / 2, size.y / 2), detectionRange, lightPaint, ); } } /// Update detection radius visibility (call when settings change) void updateDetectionRadiusVisibility(bool visible) { _showDetectionRadius = visible; } /// Refresh visibility from current settings void refreshVisibilityFromSettings() { try { final newVisibility = appSettings.getBool('game.show_detection_radius'); updateDetectionRadiusVisibility(newVisibility); } catch (e) { // Settings not ready, keep current state } } @override Future reset() async { isTriggered = false; lightsOn = false; } } /// Security camera with vision cone class SecurityCameraComponent extends SecurityComponent with AppSettings { late VisionCone visionCone; double direction; bool _currentVisionConeVisibility = true; SecurityCameraComponent({ required super.position, required this.direction, super.detectionRange = 120.0, }) { size = Vector2(8, 8); } @override Future onLoad() async { await super.onLoad(); await initSettings(); // Create vision cone with initial visibility based on settings try { _currentVisionConeVisibility = appSettings.getBool('game.show_vision_cones'); } catch (e) { _currentVisionConeVisibility = true; // Default to visible } visionCone = VisionCone( origin: Vector2.zero(), direction: direction, range: detectionRange, fov: pi / 2, // 90 degrees color: Colors.red, opacity: _currentVisionConeVisibility ? 0.3 : 0.0, ); add(visionCone); } @override bool detectsPlayer(Vector2 playerPosition, double playerStealthLevel) { return visionCone.canSee(playerPosition) && visionCone.hasLineOfSight(playerPosition, []); } @override void render(Canvas canvas) { // Draw camera as black circle final cameraPaint = Paint()..color = const Color(0xFF000000); canvas.drawCircle(Offset(size.x / 2, size.y / 2), 4, cameraPaint); } /// Call this method when settings change to update vision cone visibility void updateVisionConeVisibility(bool visible) { if (_currentVisionConeVisibility != visible) { _currentVisionConeVisibility = visible; visionCone.updateOpacity(visible ? 0.3 : 0.0); } } /// Refresh visibility from current settings (call when settings might have changed) void refreshVisibilityFromSettings() { try { final newVisibility = appSettings.getBool('game.show_vision_cones'); updateVisionConeVisibility(newVisibility); } catch (e) { // Settings not ready, keep current state } } @override Future reset() async { await visionCone.reset(); } } /// Guard dog with patrol area class GuardDogComponent extends SecurityComponent with AppSettings { Vector2 patrolCenter; double patrolRadius; double currentAngle = 0; bool isPatrolling = true; bool _showDetectionRadius = true; GuardDogComponent({ required super.position, required this.patrolCenter, this.patrolRadius = 30.0, super.detectionRange = 50.0, }) { size = Vector2(12, 12); } @override Future onLoad() async { await super.onLoad(); await initSettings(); // Initialize detection radius visibility from settings try { _showDetectionRadius = appSettings.getBool('game.show_detection_radius'); } catch (e) { _showDetectionRadius = true; // Default to visible } } @override bool detectsPlayer(Vector2 playerPosition, double playerStealthLevel) { final distance = (playerPosition - position).length; final effectiveRange = getEffectiveDetectionRange(playerStealthLevel); return distance < effectiveRange; } @override void update(double dt) { super.update(dt); if (isPatrolling) { // Simple circular patrol currentAngle += dt * 0.5; // Rotation speed final offset = Vector2( cos(currentAngle) * patrolRadius, sin(currentAngle) * patrolRadius, ); position = patrolCenter + offset; } } @override void render(Canvas canvas) { // Draw detection radius if enabled if (_showDetectionRadius) { final radiusPaint = Paint() ..color = const Color(0xFFFF9800).withValues(alpha: 0.2) ..style = PaintingStyle.stroke ..strokeWidth = 2.0; canvas.drawCircle( Offset(size.x / 2, size.y / 2), detectionRange, radiusPaint, ); } // Draw dog house final dogHousePaint = Paint()..color = const Color(0xFF8B4513); canvas.drawRect( Rect.fromLTWH(0, 0, size.x, size.y), dogHousePaint, ); // Draw dog (simple circle) final dogPaint = Paint()..color = const Color(0xFF654321); canvas.drawCircle( Offset(size.x / 2, size.y / 2), 4, dogPaint, ); } void stopPatrol() { isPatrolling = false; } void startPatrol() { isPatrolling = true; } /// Update detection radius visibility (call when settings change) void updateDetectionRadiusVisibility(bool visible) { _showDetectionRadius = visible; } /// Refresh visibility from current settings void refreshVisibilityFromSettings() { try { final newVisibility = appSettings.getBool('game.show_detection_radius'); updateDetectionRadiusVisibility(newVisibility); } catch (e) { // Settings not ready, keep current state } } @override Future reset() async { currentAngle = 0; isPatrolling = true; position = patrolCenter; } }