2024-08-19 01:41:12 +02:00
using System.Linq ;
using Content.Shared.Dataset ;
2022-02-25 23:40:15 -06:00
using Content.Server.Ghost.Roles.Components ;
2022-02-25 23:10:09 -06:00
using Content.Server.StationEvents.Components ;
2024-06-04 11:53:24 +00:00
using Content.Shared.GameTicking.Components ;
2024-08-19 01:41:12 +02:00
using Content.Shared.Random.Helpers ;
using Robust.Shared.Prototypes ;
using Robust.Shared.Random ;
2022-02-25 23:10:09 -06:00
namespace Content.Server.StationEvents.Events ;
2023-04-25 20:23:14 -04:00
public sealed class RandomSentienceRule : StationEventSystem < RandomSentienceRuleComponent >
2022-02-25 23:10:09 -06:00
{
2024-08-19 01:41:12 +02:00
[Dependency] private readonly IPrototypeManager _prototype = default ! ;
[Dependency] private readonly IRobustRandom _random = default ! ;
2023-04-25 20:23:14 -04:00
protected override void Started ( EntityUid uid , RandomSentienceRuleComponent component , GameRuleComponent gameRule , GameRuleStartedEvent args )
2022-02-25 23:10:09 -06:00
{
2024-08-19 01:41:12 +02:00
if ( ! TryGetRandomStation ( out var station ) )
return ;
2022-02-25 23:10:09 -06:00
2023-10-19 12:34:31 -07:00
var targetList = new List < Entity < SentienceTargetComponent > > ( ) ;
2024-08-19 01:41:12 +02:00
var query = EntityQueryEnumerator < SentienceTargetComponent , TransformComponent > ( ) ;
while ( query . MoveNext ( out var targetUid , out var target , out var xform ) )
2023-10-19 12:34:31 -07:00
{
2024-08-19 01:41:12 +02:00
if ( StationSystem . GetOwningStation ( targetUid , xform ) ! = station )
continue ;
2023-10-19 12:34:31 -07:00
targetList . Add ( ( targetUid , target ) ) ;
}
2024-08-19 01:41:12 +02:00
var toMakeSentient = _random . Next ( component . MinSentiences , component . MaxSentiences ) ;
2022-02-25 23:10:09 -06:00
var groups = new HashSet < string > ( ) ;
2024-08-19 01:41:12 +02:00
for ( var i = 0 ; i < toMakeSentient & & targetList . Count > 0 ; i + + )
2022-02-25 23:10:09 -06:00
{
2024-08-19 01:41:12 +02:00
// weighted random to pick a sentience target
var totalWeight = targetList . Sum ( x = > x . Comp . Weight ) ;
// This initial target should never be picked.
// It's just so that target doesn't need to be nullable and as a safety fallback for id floating point errors ever mess up the comparison in the foreach.
var target = targetList [ 0 ] ;
var chosenWeight = _random . NextFloat ( totalWeight ) ;
var currentWeight = 0.0 ;
foreach ( var potentialTarget in targetList )
{
currentWeight + = potentialTarget . Comp . Weight ;
if ( currentWeight > chosenWeight )
{
target = potentialTarget ;
break ;
}
}
targetList . Remove ( target ) ;
2022-02-25 23:10:09 -06:00
2023-10-19 12:34:31 -07:00
RemComp < SentienceTargetComponent > ( target ) ;
var ghostRole = EnsureComp < GhostRoleComponent > ( target ) ;
EnsureComp < GhostTakeoverAvailableComponent > ( target ) ;
ghostRole . RoleName = MetaData ( target ) . EntityName ;
2023-04-12 06:32:14 -07:00
ghostRole . RoleDescription = Loc . GetString ( "station-event-random-sentience-role-description" , ( "name" , ghostRole . RoleName ) ) ;
2023-10-19 12:34:31 -07:00
groups . Add ( Loc . GetString ( target . Comp . FlavorKind ) ) ;
2022-02-25 23:10:09 -06:00
}
if ( groups . Count = = 0 )
return ;
var groupList = groups . ToList ( ) ;
var kind1 = groupList . Count > 0 ? groupList [ 0 ] : "???" ;
var kind2 = groupList . Count > 1 ? groupList [ 1 ] : "???" ;
var kind3 = groupList . Count > 2 ? groupList [ 2 ] : "???" ;
2022-06-03 21:37:35 +10:00
2024-08-19 01:41:12 +02:00
ChatSystem . DispatchStationAnnouncement (
station . Value ,
Loc . GetString ( "station-event-random-sentience-announcement" ,
( "kind1" , kind1 ) , ( "kind2" , kind2 ) , ( "kind3" , kind3 ) , ( "amount" , groupList . Count ) ,
( "data" , _random . Pick ( _prototype . Index < LocalizedDatasetPrototype > ( "RandomSentienceEventData" ) ) ) ,
( "strength" , _random . Pick ( _prototype . Index < LocalizedDatasetPrototype > ( "RandomSentienceEventStrength" ) ) )
) ,
playDefaultSound : false ,
colorOverride : Color . Gold
) ;
2022-02-25 23:10:09 -06:00
}
}