2025-01-17 00:08:13 +03:00
using System.Text ;
using Content.Server.Chat.Managers ;
using Content.Server.Mind ;
using Content.Shared._CP14.Knowledge ;
using Content.Shared._CP14.Knowledge.Components ;
2025-03-06 18:56:06 +10:00
using Content.Shared._CP14.Knowledge.Events ;
2025-01-17 00:08:13 +03:00
using Content.Shared._CP14.Knowledge.Prototypes ;
using Content.Shared.Administration.Logs ;
using Content.Shared.Chat ;
using Content.Shared.Database ;
using Content.Shared.DoAfter ;
2025-03-06 19:42:20 +10:00
using Content.Shared.Mind ;
2025-01-17 00:08:13 +03:00
using Content.Shared.Verbs ;
using Robust.Shared.Prototypes ;
namespace Content.Server._CP14.Knowledge ;
2025-03-06 19:42:20 +10:00
public sealed class CP14KnowledgeSystem : SharedCP14KnowledgeSystem
2025-01-17 00:08:13 +03:00
{
2025-03-06 19:42:20 +10:00
[Dependency] private readonly IPrototypeManager _prototype = default ! ;
2025-01-17 00:08:13 +03:00
[Dependency] private readonly IChatManager _chat = default ! ;
[Dependency] private readonly MindSystem _mind = default ! ;
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default ! ;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default ! ;
public override void Initialize ( )
{
base . Initialize ( ) ;
SubscribeLocalEvent < CP14AutoAddKnowledgeComponent , MapInitEvent > ( AutoAddSkill ) ;
SubscribeLocalEvent < CP14KnowledgeStorageComponent , CP14KnowledgeLearnDoAfterEvent > ( KnowledgeLearnedEvent ) ;
2025-03-06 19:42:20 +10:00
SubscribeLocalEvent < CP14KnowledgeLearningSourceComponent , GetVerbsEvent < Verb > > ( AddKnowledgeLearningVerb ) ;
2025-01-18 14:43:11 +03:00
2025-03-06 18:56:06 +10:00
SubscribeNetworkEvent < CP14RequestKnowledgeInfoEvent > ( OnRequestKnowledgeInfoEvent ) ;
2025-01-17 00:08:13 +03:00
}
private void AddKnowledgeLearningVerb ( Entity < CP14KnowledgeLearningSourceComponent > ent , ref GetVerbsEvent < Verb > args )
{
var user = args . User ;
2025-03-06 18:22:01 +10:00
foreach ( var knowledge in ent . Comp . Knowledge )
2025-01-17 00:08:13 +03:00
{
2025-03-06 19:42:20 +10:00
if ( ! _prototype . TryIndex ( knowledge , out var indexedKnowledge ) )
2025-01-17 00:08:13 +03:00
continue ;
2025-03-06 19:42:20 +10:00
args . Verbs . Add ( new Verb
2025-01-17 00:08:13 +03:00
{
Text = $"{Loc.GetString(indexedKnowledge.Name)}" ,
Message = Loc . GetString ( indexedKnowledge . Desc ) ,
Category = VerbCategory . CP14KnowledgeLearn ,
Act = ( ) = >
{
_doAfter . TryStartDoAfter ( new DoAfterArgs ( EntityManager ,
user ,
ent . Comp . DoAfter ,
2025-03-06 19:42:20 +10:00
new CP14KnowledgeLearnDoAfterEvent { Knowledge = knowledge } ,
2025-01-17 00:08:13 +03:00
user ,
ent ,
ent )
{
BreakOnDamage = true ,
BreakOnMove = true ,
} ) ;
} ,
Disabled = HasKnowledge ( user , knowledge ) ,
Impact = LogImpact . Medium ,
} ) ;
}
}
2025-03-06 19:42:20 +10:00
private void KnowledgeLearnedEvent ( Entity < CP14KnowledgeStorageComponent > ent , ref CP14KnowledgeLearnDoAfterEvent args )
2025-01-17 00:08:13 +03:00
{
2025-03-06 19:42:20 +10:00
if ( args . Cancelled | | args . Handled )
2025-01-17 00:08:13 +03:00
return ;
2025-03-06 19:42:20 +10:00
args . Handled = true ;
TryAdd ( ent . Owner , args . Knowledge ) ;
2025-01-17 00:08:13 +03:00
}
private void AutoAddSkill ( Entity < CP14AutoAddKnowledgeComponent > ent , ref MapInitEvent args )
{
foreach ( var knowledge in ent . Comp . Knowledge )
{
2025-03-06 19:42:20 +10:00
TryAdd ( ent . Owner , knowledge ) ;
2025-01-17 00:08:13 +03:00
}
RemComp ( ent , ent . Comp ) ;
}
2025-03-06 19:42:20 +10:00
public bool TryAdd ( Entity < CP14KnowledgeStorageComponent ? > entity , ProtoId < CP14KnowledgePrototype > knowledgeId , bool force = false , bool silent = false )
2025-01-17 00:08:13 +03:00
{
2025-03-06 19:42:20 +10:00
if ( ! Resolve ( entity , ref entity . Comp , false ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
if ( HasKnowledge ( entity , knowledgeId ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
if ( ! _prototype . TryIndex ( knowledgeId , out var knowledge ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
MindComponent ? mindComponent ;
foreach ( var dependencyKnowledgeId in knowledge . Dependencies )
2025-01-17 00:08:13 +03:00
{
2025-03-06 19:42:20 +10:00
if ( ! _prototype . TryIndex ( dependencyKnowledgeId , out var dependencyKnowledge ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
// If we teach by force - we automatically teach all the basics that are necessary for that skill.
if ( force & & ! TryAdd ( entity , dependencyKnowledge , true ) )
return false ;
2025-01-17 00:08:13 +03:00
2025-03-06 19:42:20 +10:00
var sb = new StringBuilder ( ) ;
sb . Append ( Loc . GetString ( "cp14-cant-learn-knowledge-dependencies" , ( "target" , Loc . GetString ( knowledge . Desc ) ) ) ) ;
2025-01-17 00:08:13 +03:00
2025-03-06 19:42:20 +10:00
// We cant learnt
if ( HasKnowledge ( entity , dependencyKnowledge ) )
continue ;
2025-01-17 00:08:13 +03:00
2025-03-06 19:42:20 +10:00
sb . Append ( $"\n- {Loc.GetString(dependencyKnowledge.Desc)}" ) ;
2025-01-17 00:08:13 +03:00
2025-03-06 19:42:20 +10:00
if ( silent )
return false ;
2025-01-17 00:08:13 +03:00
2025-03-06 19:42:20 +10:00
if ( ! _mind . TryGetMind ( entity , out _ , out mindComponent ) | | mindComponent . Session is null )
return false ;
var wrappedMessage = Loc . GetString ( "chat-manager-server-wrap-message" , ( "message" , sb . ToString ( ) ) ) ;
2025-01-17 00:08:13 +03:00
_chat . ChatMessageToOne (
ChatChannel . Server ,
2025-03-06 19:42:20 +10:00
sb . ToString ( ) ,
wrappedMessage ,
2025-01-17 00:08:13 +03:00
default ,
false ,
2025-03-06 19:42:20 +10:00
mindComponent . Session . Channel ) ;
return false ;
2025-01-17 00:08:13 +03:00
}
2025-03-06 19:42:20 +10:00
if ( ! entity . Comp . Knowledge . Add ( knowledgeId ) )
return false ;
_adminLogger . Add ( LogType . Mind , LogImpact . Medium , $"{EntityManager.ToPrettyString(entity):player} learned new knowledge: {Loc.GetString(knowledge.Name)}" ) ;
// TODO: coding on a sleepy head is a bad idea. Remove duplicate variables. >:(
if ( silent )
return true ;
if ( ! _mind . TryGetMind ( entity , out _ , out mindComponent ) | | mindComponent . Session is null )
return false ;
var message = Loc . GetString ( "cp14-learned-new-knowledge" , ( "name" , Loc . GetString ( knowledge . Name ) ) ) ;
var wrappedMessage2 = Loc . GetString ( "chat-manager-server-wrap-message" , ( "message" , message ) ) ;
_chat . ChatMessageToOne (
ChatChannel . Server ,
message ,
wrappedMessage2 ,
default ,
false ,
mindComponent . Session . Channel ) ;
return true ;
2025-01-17 00:08:13 +03:00
}
2025-03-06 19:42:20 +10:00
public bool TryRemove ( Entity < CP14KnowledgeStorageComponent ? > entity , ProtoId < CP14KnowledgePrototype > proto , bool silent = false )
2025-01-17 00:08:13 +03:00
{
2025-03-06 19:42:20 +10:00
if ( ! Resolve ( entity , ref entity . Comp , false ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
if ( ! entity . Comp . Knowledge . Contains ( proto ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
if ( ! _prototype . TryIndex ( proto , out var indexedKnowledge ) )
2025-01-17 00:08:13 +03:00
return false ;
2025-03-06 19:42:20 +10:00
if ( ! entity . Comp . Knowledge . Remove ( proto ) )
return false ;
2025-01-17 00:08:13 +03:00
2025-03-06 19:42:20 +10:00
_adminLogger . Add ( LogType . Mind , LogImpact . Medium , $"{EntityManager.ToPrettyString(entity):player} forgot knowledge: {Loc.GetString(indexedKnowledge.Name)}" ) ;
if ( silent )
return true ;
if ( ! _mind . TryGetMind ( entity , out _ , out var mindComp ) | | mindComp . Session is null )
return true ;
var message = Loc . GetString ( "cp14-forgot-knowledge" , ( "name" , Loc . GetString ( indexedKnowledge . Name ) ) ) ;
var wrappedMessage = Loc . GetString ( "chat-manager-server-wrap-message" , ( "message" , message ) ) ;
_chat . ChatMessageToOne (
ChatChannel . Server ,
message ,
wrappedMessage ,
default ,
false ,
mindComp . Session . Channel ) ;
2025-01-17 00:08:13 +03:00
return true ;
}
2025-01-18 14:43:11 +03:00
2025-03-06 18:56:06 +10:00
private void OnRequestKnowledgeInfoEvent ( CP14RequestKnowledgeInfoEvent msg , EntitySessionEventArgs args )
2025-01-18 14:43:11 +03:00
{
if ( ! args . SenderSession . AttachedEntity . HasValue | | args . SenderSession . AttachedEntity ! = GetEntity ( msg . NetEntity ) )
return ;
var entity = args . SenderSession . AttachedEntity . Value ;
if ( ! TryComp < CP14KnowledgeStorageComponent > ( entity , out var knowledgeComp ) )
return ;
2025-03-06 18:22:01 +10:00
RaiseNetworkEvent ( new CP14KnowledgeInfoEvent ( GetNetEntity ( entity ) , knowledgeComp . Knowledge ) , args . SenderSession ) ;
2025-01-18 14:43:11 +03:00
}
2025-01-17 00:08:13 +03:00
}