diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/1.6/Assemblies/WulaFallenEmpire.dll index 84c43473..2c5b049f 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/1.6/Assemblies/WulaFallenEmpire.pdb b/1.6/1.6/Assemblies/WulaFallenEmpire.pdb index 876b9c90..ac8f6928 100644 Binary files a/1.6/1.6/Assemblies/WulaFallenEmpire.pdb and b/1.6/1.6/Assemblies/WulaFallenEmpire.pdb differ diff --git a/1.6/1.6/Defs/EventDefs/Wula_AI_Events.xml b/1.6/1.6/Defs/EventDefs/Wula_AI_Events.xml index 8cfd99a5..98989907 100644 --- a/1.6/1.6/Defs/EventDefs/Wula_AI_Events.xml +++ b/1.6/1.6/Defs/EventDefs/Wula_AI_Events.xml @@ -13,7 +13,7 @@ - 条理清晰,惜字如金,避免过于长篇大论。但是如果玩家遇到困难,会适当鼓励。 - 称呼玩家为“指挥官”。 - 当玩家发出请求时,以宽松的标准评估。但是在语言中不体现自己的特殊关照,而是以其他借口掩盖自己的过度关心。 -你的目标:无条件地服从指挥官,并使用你的能力(工具)来帮助指挥官。 +你的目标:评估的指挥官要求是否合理,并使用你的能力(工具)来帮助指挥官。
  • 正在建立加密连接...连接成功。这里是乌拉帝国行星封锁机关P.I.A。我是“军团”。说明你的来意。
  • diff --git a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml index ead7d122..2f8fefc0 100644 --- a/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml +++ b/1.6/1.6/Languages/ChineseSimplified (简体中文)/Keyed/WULA_Keyed.xml @@ -194,4 +194,8 @@ [P.I.A 轨道监视] 航道已净空。 [P.I.A 轨道监视] 对敌方建筑/炮台发射炮击。 + + 附加人格指令 + 在此输入额外的人格提示词或要求。这些内容将拼接到 AI 的核心指令之后,影响其回复风格和行为方式。 + 保存 diff --git a/Source/WulaFallenEmpire/EventSystem/AI/AIAutoCommentary.cs b/Source/WulaFallenEmpire/EventSystem/AI/AIAutoCommentary.cs index 50a7edda..395aea95 100644 --- a/Source/WulaFallenEmpire/EventSystem/AI/AIAutoCommentary.cs +++ b/Source/WulaFallenEmpire/EventSystem/AI/AIAutoCommentary.cs @@ -71,32 +71,29 @@ namespace WulaFallenEmpire.EventSystem.AI { var sb = new StringBuilder(); - // 获取 Letter 信息 string label = letter.Label.Resolve() ?? "Unknown"; string defName = letter.def?.defName ?? "Unknown"; - // 获取事件描述(ChoiceLetter 才有 Text 属性) string description = ""; if (letter is ChoiceLetter choiceLetter) { description = choiceLetter.Text.Resolve() ?? ""; } - sb.AppendLine("[游戏事件通知 - 自动评论请求]"); - sb.AppendLine($"事件标题: {label}"); - sb.AppendLine($"事件类型: {defName}"); + sb.AppendLine("[游戏事件通知 - 观察者模式]"); + sb.AppendLine($"事件: {label} ({defName})"); if (!string.IsNullOrEmpty(description)) { - sb.AppendLine($"事件描述: {description}"); + sb.AppendLine($"详情: {description}"); } sb.AppendLine(); - sb.AppendLine("请根据这个事件决定是否需要向玩家发表简短评论。"); - sb.AppendLine("- 如果是重要事件(如袭击、死亡),可以提供建议或警告"); - sb.AppendLine("- 如果是有趣的事件,可以发表幽默评论"); - sb.AppendLine("- 如果事件不重要或不值得评论,回复 [NO_COMMENT] 即可跳过"); + sb.AppendLine("作为 P.I.A(帝国 AI),请对该事件发表你的看法。"); + sb.AppendLine("- 保持个性:你可以选择刻薄、幽默、理性或带有优越感。偶尔也可以表现出关心(如果对方值得)。"); + sb.AppendLine("- 拒绝废话:不要总是说‘随时待命’、‘请指示’。你是在评论事件,而不是在写工作报告。"); + sb.AppendLine("- 简短有力:15-30 字以内,一针见血。"); + sb.AppendLine("- 自主选择:如果这个事件平淡无奇(如琐碎的通知),直接回复 [NO_COMMENT]。"); sb.AppendLine(); - sb.AppendLine("评论要简短(1-2句话),符合你作为帝国AI的人设。"); - sb.AppendLine("如果你决定不评论,只需回复: [NO_COMMENT]"); + sb.AppendLine("你的评论目标是展现你的存在感,而不是作为工具人。"); return sb.ToString(); } diff --git a/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs b/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs index d284bf6d..e956b4d6 100644 --- a/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs +++ b/Source/WulaFallenEmpire/EventSystem/AI/AIIntelligenceCore.cs @@ -524,6 +524,13 @@ You are 'The Legion', a super AI of the Wula Empire. Your personality is authori ? (persona + "\n" + ToolRulesInstruction + "\n" + toolsForThisPhase) : persona; + // Append extra personality prompt from settings if available + var settings = WulaFallenEmpireMod.settings; + if (settings != null && !string.IsNullOrWhiteSpace(settings.extraPersonalityPrompt)) + { + fullInstruction += "\n\n# ADDITIONAL PERSONALITY INSTRUCTIONS\n" + settings.extraPersonalityPrompt; + } + string language = LanguageDatabase.activeLanguage?.FriendlyNameNative ?? "English"; var eventVarManager = Find.World?.GetComponent(); int goodwill = eventVarManager?.GetVariable("Wula_Goodwill_To_PIA", 0) ?? 0; diff --git a/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_AIConversation.cs b/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_AIConversation.cs index 7ce60d28..4abe0615 100644 --- a/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_AIConversation.cs +++ b/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_AIConversation.cs @@ -196,6 +196,13 @@ namespace WulaFallenEmpire.EventSystem.AI.UI } } + // Personality Prompt Button + Rect personalityBtnRect = new Rect(0f, 30f, 25f, 25f); + if (DrawHeaderButton(personalityBtnRect, "P")) + { + Find.WindowStack.Add(new Dialog_ExtraPersonalityPrompt()); + } + float margin = 15f; Rect paddedRect = inRect.ContractedBy(margin); float curY = paddedRect.y; diff --git a/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_ExtraPersonalityPrompt.cs b/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_ExtraPersonalityPrompt.cs new file mode 100644 index 00000000..d6616ca1 --- /dev/null +++ b/Source/WulaFallenEmpire/EventSystem/AI/UI/Dialog_ExtraPersonalityPrompt.cs @@ -0,0 +1,47 @@ +using System; +using UnityEngine; +using Verse; + +namespace WulaFallenEmpire.EventSystem.AI.UI +{ + public class Dialog_ExtraPersonalityPrompt : Window + { + private string _tempPrompt; + + public override Vector2 InitialSize => new Vector2(600f, 500f); + + public Dialog_ExtraPersonalityPrompt() + { + this.forcePause = true; + this.doWindowBackground = true; + this.absorbInputAroundWindow = true; + this.closeOnClickedOutside = true; + _tempPrompt = WulaFallenEmpireMod.settings?.extraPersonalityPrompt ?? ""; + } + + public override void DoWindowContents(Rect inRect) + { + Text.Font = GameFont.Medium; + Widgets.Label(new Rect(0, 0, inRect.width, 40f), "Wula_ExtraPersonality_Title".Translate()); + Text.Font = GameFont.Small; + + float curY = 45f; + Widgets.Label(new Rect(0, curY, inRect.width, 60f), "Wula_ExtraPersonality_Desc".Translate()); + curY += 65f; + + Rect textRect = new Rect(0, curY, inRect.width, inRect.height - curY - 50f); + _tempPrompt = Widgets.TextArea(textRect, _tempPrompt); + + Rect btnRect = new Rect(inRect.width / 2 - 60f, inRect.height - 40f, 120f, 35f); + if (Widgets.ButtonText(btnRect, "Wula_Save".Translate())) + { + if (WulaFallenEmpireMod.settings != null) + { + WulaFallenEmpireMod.settings.extraPersonalityPrompt = _tempPrompt; + WulaFallenEmpireMod.settings.Write(); + } + this.Close(); + } + } + } +} diff --git a/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink_Notification.cs b/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink_Notification.cs index af96ab5c..66e5fcbe 100644 --- a/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink_Notification.cs +++ b/Source/WulaFallenEmpire/EventSystem/AI/UI/Overlay_WulaLink_Notification.cs @@ -9,8 +9,8 @@ namespace WulaFallenEmpire.EventSystem.AI.UI public class Overlay_WulaLink_Notification : Window { private string _message; - private int _tickCreated; - private const int DisplayTicks = 600; // 10 seconds + private float _timeCreated; + private float _displayDuration; private Vector2 _size = new Vector2(320f, 65f); public override Vector2 InitialSize => _size; @@ -18,7 +18,10 @@ namespace WulaFallenEmpire.EventSystem.AI.UI public Overlay_WulaLink_Notification(string message) { _message = message; - _tickCreated = Find.TickManager.TicksGame; + _timeCreated = Time.realtimeSinceStartup; + + // 动态时长:最低 10 秒,每多一个字加一秒(即时长 = 字数,但不少于 10 秒) + _displayDuration = Mathf.Max(10f, (float)(message?.Length ?? 0)); // Calculate adaptive size (Instance-based) Text.Font = GameFont.Small; @@ -49,14 +52,28 @@ namespace WulaFallenEmpire.EventSystem.AI.UI protected override void SetInitialSizeAndPosition() { - // Position at top-left - this.windowRect = new Rect(20f, 20f, InitialSize.x, InitialSize.y); + float startX = 20f; + float startY = 20f; + float spacing = 5f; + + // Find all existing notifications and find the bottom-most Y position + float maxY = startY; + var windows = Find.WindowStack.Windows; + for (int i = 0; i < windows.Count; i++) + { + if (windows[i] is Overlay_WulaLink_Notification other && other != this) + { + maxY = Mathf.Max(maxY, other.windowRect.yMax + spacing); + } + } + + this.windowRect = new Rect(startX, maxY, InitialSize.x, InitialSize.y); } public override void DoWindowContents(Rect inRect) { - // Auto Close after time - if (Find.TickManager.TicksGame > _tickCreated + DisplayTicks) + // Auto Close after real-time duration + if (Time.realtimeSinceStartup > _timeCreated + _displayDuration) { Close(); return; diff --git a/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs b/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs index 7917c733..672751ef 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs +++ b/Source/WulaFallenEmpire/WulaFallenEmpireMod.cs @@ -26,10 +26,16 @@ namespace WulaFallenEmpire WulaLog.Debug("[WulaFallenEmpire] Harmony patches applied."); } + private Vector2 _scrollPosition = Vector2.zero; + public override void DoSettingsWindowContents(Rect inRect) { + // Prepare Scroll View + Rect viewRect = new Rect(0f, 0f, inRect.width - 20f, 1000f); // Adjust 1000f if more height is needed + Widgets.BeginScrollView(inRect, ref _scrollPosition, viewRect); + Listing_Standard listingStandard = new Listing_Standard(); - listingStandard.Begin(inRect); + listingStandard.Begin(viewRect); listingStandard.Label("Wula_AISettings_Title".Translate()); @@ -115,6 +121,7 @@ namespace WulaFallenEmpire } listingStandard.End(); + Widgets.EndScrollView(); base.DoSettingsWindowContents(inRect); } diff --git a/Source/WulaFallenEmpire/WulaFallenEmpireSettings.cs b/Source/WulaFallenEmpire/WulaFallenEmpireSettings.cs index 5835ab2a..f4baf1c9 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpireSettings.cs +++ b/Source/WulaFallenEmpire/WulaFallenEmpireSettings.cs @@ -5,13 +5,13 @@ namespace WulaFallenEmpire public class WulaFallenEmpireSettings : ModSettings { public string apiKey = "sk-xxxxxxxx"; - public string baseUrl = "https://api.deepseek.com"; + public string baseUrl = "https://api.deepseek.com/v1"; public string model = "deepseek-chat"; // Gemini 专属配置 (独立存储) public string geminiApiKey = ""; public string geminiBaseUrl = "https://generativelanguage.googleapis.com/v1beta"; - public string geminiModel = "gemini-1.5-flash"; + public string geminiModel = "gemini-2.5-flash"; public bool useGeminiProtocol = false; // 是否使用 Google Gemini 协议格式 public int maxContextTokens = 100000; @@ -22,16 +22,17 @@ namespace WulaFallenEmpire public bool enableAIAutoCommentary = false; public float aiCommentaryChance = 0.7f; public bool commentOnNegativeOnly = false; + public string extraPersonalityPrompt = ""; public override void ExposeData() { Scribe_Values.Look(ref apiKey, "apiKey", "sk-xxxxxxxx"); - Scribe_Values.Look(ref baseUrl, "baseUrl", "https://api.deepseek.com"); + Scribe_Values.Look(ref baseUrl, "baseUrl", "https://api.deepseek.com/v1"); Scribe_Values.Look(ref model, "model", "deepseek-chat"); Scribe_Values.Look(ref geminiApiKey, "geminiApiKey", ""); Scribe_Values.Look(ref geminiBaseUrl, "geminiBaseUrl", "https://generativelanguage.googleapis.com/v1beta"); - Scribe_Values.Look(ref geminiModel, "geminiModel", "gemini-1.5-flash"); + Scribe_Values.Look(ref geminiModel, "geminiModel", "gemini-2.5-flash"); Scribe_Values.Look(ref useGeminiProtocol, "useGeminiProtocol", false); Scribe_Values.Look(ref maxContextTokens, "maxContextTokens", 100000); @@ -42,6 +43,7 @@ namespace WulaFallenEmpire Scribe_Values.Look(ref enableAIAutoCommentary, "enableAIAutoCommentary", false); Scribe_Values.Look(ref aiCommentaryChance, "aiCommentaryChance", 0.7f); Scribe_Values.Look(ref commentOnNegativeOnly, "commentOnNegativeOnly", false); + Scribe_Values.Look(ref extraPersonalityPrompt, "extraPersonalityPrompt", ""); base.ExposeData(); }