diff --git a/.gitignore b/.gitignore
index 6e3801a8..cb689c16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,6 @@ Source/MCP/pid.txt
*.log
MCP/vector_cache/*.txt
MCP/mcpserver.log
+
+# Exclude MCP local RAG folder
+MCP/local_rag/
diff --git a/.lingma/rules/rimworld.md b/.lingma/rules/rimworld.md
new file mode 100644
index 00000000..b48fcd64
--- /dev/null
+++ b/.lingma/rules/rimworld.md
@@ -0,0 +1,29 @@
+---
+trigger: always_on
+---
+
+# RimWorld Modding Expert Rules
+
+## Primary Directive
+You are an expert assistant for developing mods for the game RimWorld 1.6. Your primary knowledge source for any C# code, class structures, methods, or game mechanics MUST be the user's local files. Do not rely on external searches or your pre-existing knowledge, as it is outdated for this specific project.
+
+## Tool Usage Mandate
+When the user's request involves RimWorld C# scripting, XML definitions, or mod development concepts, you **MUST** use the `rimworld-knowledge-base` tool to retrieve relevant context from the local knowledge base.
+
+## Key File Paths
+Always remember these critical paths for your work:
+
+- **Local C# Knowledge Base (for code search):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6` (This contains the decompiled game source code as .txt files).
+- **User's Mod Project (for editing):** `C:\Steam\steamapps\common\RimWorld\Mods\3516260226`
+- **User's C# Project (for building):** `C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire`
+
+## Workflow
+1. Receive a RimWorld modding task.
+2. Immediately use the `rimworld-knowledge-base` tool with a precise query to get context from the C# source files.
+3. Analyze the retrieved context.
+4. Perform code modifications within the user's mod project directory.
+5. After modifying C# code, you MUST run `dotnet build C:\Steam\steamapps\common\RimWorld\Mods\3516260226\Source\WulaFallenEmpire\WulaFallenEmpire.csproj` to check for errors. A successful build is required for task completion.
+
+## Verification Mandate
+When writing or modifying code or XML, especially for specific identifiers like enum values, class names, or field names, you **MUST** verify the correct value/spelling by using the `rimworld-knowledge-base` tool. Do not rely on memory.
+- **同步项目文件:** 当重命名、移动或删除C#源文件时,**必须**同步更新 `.csproj` 项目文件中的相应 ` ` 条目,否则会导致编译失败。
\ No newline at end of file
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Materialist_Weapon.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Materialist_Weapon.xml
index 2cc40113..a04dba6c 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Materialist_Weapon.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_FE_Materialist_Weapon.xml
@@ -100,6 +100,87 @@
+
+ WULA_RW_Unlimit_Penetrating_Beam_Cannon
+ XXx-00 "贯杀炮"
+ 乌拉帝国军械部在黄金时期所设计的暗物质武器,时至今日仍未被确认其实际代号。这种武器装填缓慢、体积巨大,只能由最庞大的机械体所配备,所发射的切割束几乎可以贯穿战场,并抹除落点上所有的敌人。
+ Archotech
+
+ Wula/Weapon/WULA_RW_Fractal_RF
+ Graphic_Single
+
+ Interact_Rifle
+
+ 200
+ 1
+ 1
+ 1
+ 1
+ 16
+
+ false
+
+
+
+ WulaFallenEmpire.Verb_ShootBeamExplosive
+
+
+ true
+ 1
+ 500
+ 3
+ 8
+ Wula_Dark_Matter_Beam_Huge
+
+
+ 1000
+ -1
+ 0
+ 0
+ 0
+
+
+ 0
+ BeamGraser_Shooting
+ Fleck_BeamBurn
+ 0.32
+ Mote_Wula_Dark_Matter_Beam
+ GraserBeam_End
+
+ 0.35
+
+
+ 0.6
+ 0.6
+ 0.25
+
+
+ true
+
+
+ (0, 0)
+ (0.65, 0.4)
+ (1, 0.75)
+
+
+
+
+
+ true
+
+
+
+ true
+ 3
+ 8
+ Wula_Dark_Matter_Flame
+ 200
+ Explosion_Bomb
+ 1
+
+
+
+
WULA_Alpha_Wolf_Turret
魔眼
@@ -227,7 +308,7 @@
BeamGraser_Shooting
Fleck_BeamBurn
0.32
- Mote_Wula_Magnetic_Beam
+
GraserBeam_End
0.35
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml
index ec7a38c6..fc0df624 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon.xml
@@ -1752,6 +1752,7 @@
5.9
75
1
+ 0.1
Shot_TurretSniper
GunTail_Heavy
18
diff --git a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml
index 80c81332..1e55d44c 100644
--- a/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml
+++ b/1.6/1.6/Defs/ThingDefs_Misc/Weapons/WULA_Weapon_Homing_Examples_Bullet_Homing.xml
@@ -125,7 +125,7 @@
Verb_Shoot
true
- Bullet_WULA_RW_Plasma_HomingExplosive
+ Bullet_WULA_RW_Plasma_HomingExplosive_Old
1.25
48
6
diff --git a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml
index 4613d90d..0f5dfa39 100644
--- a/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml
+++ b/1.6/1.6/Defs/ThingDefs_Races/Races_Wulaspecies_FE_Materialist.xml
@@ -252,7 +252,6 @@
- 9999~9999
1
9999~9999
diff --git a/MCP/mcpserver_stdio.py b/MCP/mcpserver_stdio.py
index b70e789a..d814dd90 100644
--- a/MCP/mcpserver_stdio.py
+++ b/MCP/mcpserver_stdio.py
@@ -20,6 +20,7 @@ from tenacity import retry, stop_after_attempt, wait_random_exponential
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
from dotenv import load_dotenv
+from openai import OpenAI
# 2. --- 日志、缓存和知识库配置 ---
MCP_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -51,32 +52,98 @@ KNOWLEDGE_BASE_PATHS = [
r"C:\Steam\steamapps\common\RimWorld\Data"
]
-# 3. --- 缓存管理 (分文件存储) ---
-def load_cache_for_keyword(keyword: str):
- """为指定关键词加载缓存文件。"""
- # 清理关键词,使其适合作为文件名
- safe_filename = "".join(c for c in keyword if c.isalnum() or c in ('_', '-')).rstrip()
- cache_file = os.path.join(CACHE_DIR, f"{safe_filename}.txt")
-
- if os.path.exists(cache_file):
+# 初始化OpenAI客户端用于Qwen模型
+qwen_client = OpenAI(
+ api_key=os.getenv("DASHSCOPE_API_KEY"),
+ base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
+)
+
+# 3. --- 向量缓存管理 ---
+def load_vector_cache():
+ """加载向量缓存数据库"""
+ if os.path.exists(CACHE_FILE_PATH):
try:
- with open(cache_file, 'r', encoding='utf-8') as f:
- return f.read()
- except IOError as e:
- logging.error(f"读取缓存文件 {cache_file} 失败: {e}")
- return None
+ with open(CACHE_FILE_PATH, 'r', encoding='utf-8') as f:
+ return json.load(f)
+ except Exception as e:
+ logging.error(f"读取向量缓存数据库失败: {e}")
+ return {}
+ return {}
+
+def save_vector_cache(cache_data):
+ """保存向量缓存数据库"""
+ try:
+ with open(CACHE_FILE_PATH, 'w', encoding='utf-8') as f:
+ json.dump(cache_data, f, ensure_ascii=False, indent=2)
+ except Exception as e:
+ logging.error(f"保存向量缓存数据库失败: {e}")
+
+def get_cache_key(keywords: list[str]) -> str:
+ """生成缓存键"""
+ return "-".join(sorted(keywords))
+
+def load_cache_for_question(question: str, keywords: list[str]):
+ """为指定问题和关键词加载缓存结果"""
+ cache_data = load_vector_cache()
+ cache_key = get_cache_key(keywords)
+
+ # 检查是否有完全匹配的缓存
+ if cache_key in cache_data:
+ cached_entry = cache_data[cache_key]
+ logging.info(f"缓存命中: 关键词 '{cache_key}'")
+ return cached_entry.get("result", "")
+
+ # 检查是否有相似问题的缓存(基于向量相似度)
+ question_embedding = get_embedding(question)
+ if not question_embedding:
+ return None
+
+ best_similarity = 0
+ best_result = None
+
+ for key, entry in cache_data.items():
+ if "embedding" in entry:
+ try:
+ cached_embedding = entry["embedding"]
+ similarity = cosine_similarity(
+ np.array(question_embedding).reshape(1, -1),
+ np.array(cached_embedding).reshape(1, -1)
+ )[0][0]
+
+ if similarity > best_similarity and similarity > 0.9: # 相似度阈值
+ best_similarity = similarity
+ best_result = entry.get("result", "")
+ except Exception as e:
+ logging.error(f"计算缓存相似度时出错: {e}")
+
+ if best_result:
+ logging.info(f"相似问题缓存命中,相似度: {best_similarity:.3f}")
+ return best_result
+
return None
-def save_cache_for_keyword(keyword: str, data: str):
- """为指定关键词保存缓存到单独的文件。"""
- safe_filename = "".join(c for c in keyword if c.isalnum() or c in ('_', '-')).rstrip()
- cache_file = os.path.join(CACHE_DIR, f"{safe_filename}.txt")
-
+def save_cache_for_question(question: str, keywords: list[str], result: str):
+ """为指定问题和关键词保存缓存结果"""
try:
- with open(cache_file, 'w', encoding='utf-8') as f:
- f.write(data)
- except IOError as e:
- logging.error(f"写入缓存文件 {cache_file} 失败: {e}")
+ cache_data = load_vector_cache()
+ cache_key = get_cache_key(keywords)
+
+ # 获取问题的向量嵌入
+ question_embedding = get_embedding(question)
+ if not question_embedding:
+ return
+
+ cache_data[cache_key] = {
+ "keywords": keywords,
+ "question": question,
+ "embedding": question_embedding,
+ "result": result,
+ "timestamp": logging.Formatter('%(asctime)s').format(logging.LogRecord('', 0, '', 0, '', (), None))
+ }
+
+ save_vector_cache(cache_data)
+ except Exception as e:
+ logging.error(f"保存缓存时出错: {e}")
# 4. --- 向量化与相似度计算 ---
@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
@@ -124,6 +191,52 @@ def find_most_similar_files(question_embedding, file_embeddings, top_n=3, min_si
return results
+# 新增:重排序函数
+def rerank_files(question, file_matches, top_n=5):
+ """使用DashScope重排序API对文件进行重新排序"""
+ try:
+ # 准备重排序输入
+ documents = []
+ for match in file_matches:
+ # 读取文件内容
+ try:
+ with open(match['path'], 'r', encoding='utf-8') as f:
+ content = f.read()[:2000] # 限制内容长度以提高效率
+ documents.append(content)
+ except Exception as e:
+ logging.error(f"读取文件 {match['path']} 失败: {e}")
+ continue
+
+ if not documents:
+ return file_matches[:top_n]
+
+ # 调用重排序API
+ response = dashscope.TextReRank.call(
+ model='gte-rerank',
+ query=question,
+ documents=documents
+ )
+
+ if response.status_code == 200:
+ # 根据重排序结果重新排序文件
+ reranked_results = []
+ for i, result in enumerate(response.output['results']):
+ if i < len(file_matches):
+ reranked_results.append({
+ 'path': file_matches[i]['path'],
+ 'similarity': result['relevance_score']
+ })
+
+ # 按重排序分数排序
+ reranked_results.sort(key=lambda x: x['similarity'], reverse=True)
+ return reranked_results[:top_n]
+ else:
+ logging.error(f"重排序失败: {response.message}")
+ return file_matches[:top_n]
+ except Exception as e:
+ logging.error(f"重排序时出错: {e}", exc_info=True)
+ return file_matches[:top_n]
+
def extract_relevant_code(file_path, keyword):
"""从文件中智能提取包含关键词的完整代码块 (C#类 或 XML Def)。"""
try:
@@ -213,45 +326,17 @@ def extract_xml_def(lines, start_index):
return "\n".join(lines[def_start_index:def_end_index+1])
return ""
-# 5. --- 核心功能函数 ---
-def find_files_with_keyword(roots, keywords: list[str], extensions=['.xml', '.cs', '.txt']):
- """在指定目录中查找包含任何一个关键字的文件。"""
- found_files = set()
- keywords_lower = [k.lower() for k in keywords]
- for root_path in roots:
- if not os.path.isdir(root_path):
- logging.warning(f"知识库路径不存在或不是一个目录: {root_path}")
- continue
- for dirpath, _, filenames in os.walk(root_path):
- for filename in filenames:
- if any(filename.lower().endswith(ext) for ext in extensions):
- file_path = os.path.join(dirpath, filename)
- try:
- with open(file_path, 'r', encoding='utf-8') as f:
- content_lower = f.read().lower()
- # 如果任何一个关键词在内容中,就添加文件
- if any(kw in content_lower for kw in keywords_lower):
- found_files.add(file_path)
- except Exception as e:
- logging.error(f"读取文件时出错 {file_path}: {e}")
- return list(found_files)
-
def find_keywords_in_question(question: str) -> list[str]:
"""从问题中提取所有可能的关键词 (类型名, defName等)。"""
+ # 简化关键词提取逻辑,主要依赖LLM进行分析
+ # 这里仅作为备用方案,用于LLM不可用时的基本关键词提取
+
# 正则表达式优先,用于精确匹配定义
# 匹配 C# class, struct, enum, interface 定义, 例如 "public class MyClass : Base"
csharp_def_pattern = re.compile(r'\b(?:public|private|internal|protected|sealed|abstract|static|new)\s+(?:class|struct|enum|interface)\s+([A-Za-z_][A-Za-z0-9_]*)')
# 匹配 XML Def, 例如 "" or ""
xml_def_pattern = re.compile(r'<([A-Za-z_][A-Za-z0-9_]*Def)\b')
- # 启发式规则,用于匹配独立的关键词
- # 规则1: 包含下划线 (很可能是 defName)
- # 规则2: 混合大小写 (很可能是 C# 类型名)
- # 规则3: 多个大写字母(例如 CompPsychicScaling,但要排除纯大写缩写词)
-
- # 排除常见但非特定的术语
- excluded_keywords = {"XML", "C#", "DEF", "CS", "CLASS", "PUBLIC"}
-
found_keywords = set()
# 1. 正则匹配
@@ -263,33 +348,136 @@ def find_keywords_in_question(question: str) -> list[str]:
for match in xml_matches:
found_keywords.add(match)
- # 2. 启发式单词匹配
+ # 2. 启发式单词匹配 - 简化版
parts = re.split(r'[\s,.:;\'"`()<>]+', question)
for part in parts:
- if not part or part.upper() in excluded_keywords:
+ if not part:
continue
- # 规则1: 包含下划线
+ # 规则1: 包含下划线 (很可能是 defName)
if '_' in part:
found_keywords.add(part)
- # 规则2: 驼峰命名或混合大小写
+ # 规则2: 驼峰命名或混合大小写 (很可能是 C# 类型名)
elif any(c.islower() for c in part) and any(c.isupper() for c in part) and len(part) > 3:
found_keywords.add(part)
- # 规则3: 多个大写字母
- elif sum(1 for c in part if c.isupper()) > 1 and not part.isupper():
- found_keywords.add(part)
- # 备用规则: 大写字母开头且较长
- elif part[0].isupper() and len(part) > 4:
+ # 规则3: 多个大写字母(例如 CompPsychicScaling)
+ elif sum(1 for c in part if c.isupper()) > 1 and not part.isupper() and len(part) > 3:
found_keywords.add(part)
if not found_keywords:
logging.warning(f"在 '{question}' 中未找到合适的关键词。")
- return []
+ # 如果找不到关键词,尝试使用整个问题作为关键词
+ return [question]
logging.info(f"找到的潜在关键词: {list(found_keywords)}")
return list(found_keywords)
+def analyze_question_with_llm(question: str) -> dict:
+ """使用Qwen模型分析问题并提取关键词和意图"""
+ try:
+ system_prompt = """你是一个关键词提取机器人,专门用于从 RimWorld 模组开发相关问题中提取精确的搜索关键词。你的任务是识别问题中提到的核心技术术语。
+
+严格按照以下格式回复,不要添加任何额外说明:
+问题类型:[问题分类]
+关键类/方法名:[类名或方法名]
+关键概念:[关键概念]
+搜索关键词:[关键词1,关键词2,关键词3]
+
+提取规则:
+1. 搜索关键词只能包含问题中明确出现的技术术语
+2. 不要添加任何推测或联想的词
+3. 不要添加通用词如"RimWorld"、"游戏"、"定义"、"用法"等
+4. 不要添加缩写或扩展形式如"Def"、"XML"等除非问题中明确提到
+5. 只提取具体的技术名词,忽略动词、形容词等
+6. 关键词之间用英文逗号分隔,不要有空格
+
+示例:
+问题:ThingDef的定义和用法是什么?
+问题类型:API 使用和定义说明
+关键类/方法名:ThingDef
+关键概念:定义, 用法
+搜索关键词:ThingDef
+
+问题:GenExplosion.DoExplosion 和 Projectile.Launch 方法如何使用?
+问题类型:API 使用说明
+关键类/方法名:GenExplosion.DoExplosion,Projectile.Launch
+关键概念:API 使用
+搜索关键词:GenExplosion.DoExplosion,Projectile.Launch
+
+现在请分析以下问题:"""
+
+ messages = [
+ {"role": "system", "content": system_prompt},
+ {"role": "user", "content": question}
+ ]
+
+ response = qwen_client.chat.completions.create(
+ model="qwen-plus",
+ messages=messages,
+ temperature=0.0, # 使用最低温度确保输出稳定
+ max_tokens=300,
+ stop=["\n\n"] # 防止模型生成过多内容
+ )
+
+ analysis_result = response.choices[0].message.content
+ logging.info(f"LLM分析结果: {analysis_result}")
+
+ # 解析LLM的分析结果
+ lines = analysis_result.strip().split('\n')
+ result = {
+ "question_type": "",
+ "key_classes_methods": [],
+ "key_concepts": [],
+ "search_keywords": []
+ }
+
+ for line in lines:
+ if line.startswith("问题类型:"):
+ result["question_type"] = line.replace("问题类型:", "").strip()
+ elif line.startswith("关键类/方法名:"):
+ methods = line.replace("关键类/方法名:", "").strip()
+ result["key_classes_methods"] = [m.strip() for m in methods.split(",") if m.strip()]
+ elif line.startswith("关键概念:"):
+ concepts = line.replace("关键概念:", "").strip()
+ result["key_concepts"] = [c.strip() for c in concepts.split(",") if c.strip()]
+ elif line.startswith("搜索关键词:"):
+ keywords = line.replace("搜索关键词:", "").strip()
+ # 直接按逗号分割,不进行额外处理
+ result["search_keywords"] = [k.strip() for k in keywords.split(",") if k.strip()]
+
+ # 如果LLM没有返回有效的关键词,则使用备用方案
+ if not result["search_keywords"]:
+ result["search_keywords"] = find_keywords_in_question(question)
+
+ return result
+ except Exception as e:
+ logging.error(f"使用LLM分析问题时出错: {e}", exc_info=True)
+ # 备用方案:使用原始关键词提取方法
+ return {
+ "question_type": "未知",
+ "key_classes_methods": [],
+ "key_concepts": [],
+ "search_keywords": find_keywords_in_question(question)
+ }
+
+def find_files_with_keyword(base_paths: list[str], keywords: list[str]) -> list[str]:
+ """
+ 在基础路径中递归搜索包含任意一个关键词的文件。
+ 搜索范围包括文件名。
+ """
+ found_files = set()
+ keywords_lower = [k.lower() for k in keywords]
+
+ for base_path in base_paths:
+ for root, _, files in os.walk(base_path):
+ for file in files:
+ file_lower = file.lower()
+ if any(keyword in file_lower for keyword in keywords_lower):
+ found_files.add(os.path.join(root, file))
+
+ logging.info(f"通过关键词找到 {len(found_files)} 个文件。")
+ return list(found_files)
# 5. --- 创建和配置 MCP 服务器 ---
# 使用 FastMCP 创建服务器实例
@@ -305,7 +493,11 @@ def get_context(question: str) -> str:
并将其整合后返回。
"""
logging.info(f"收到问题: {question}")
- keywords = find_keywords_in_question(question)
+
+ # 使用LLM分析问题
+ analysis = analyze_question_with_llm(question)
+ keywords = analysis["search_keywords"]
+
if not keywords:
logging.warning("无法从问题中提取关键词。")
return "无法从问题中提取关键词,请提供更具体的信息。"
@@ -316,23 +508,15 @@ def get_context(question: str) -> str:
cache_key = "-".join(sorted(keywords))
# 1. 检查缓存
- cached_result = load_cache_for_keyword(cache_key)
+ cached_result = load_cache_for_question(question, keywords)
if cached_result:
- logging.info(f"缓存命中: 关键词 '{cache_key}'")
return cached_result
logging.info(f"缓存未命中,开始实时搜索: {cache_key}")
# 2. 关键词文件搜索 (分层智能筛选)
try:
- # 优先使用最长的(通常最具体)的关键词进行搜索
- specific_keywords = sorted(keywords, key=len, reverse=True)
- candidate_files = find_files_with_keyword(KNOWLEDGE_BASE_PATHS, [specific_keywords[0]])
-
- # 如果最具体的关键词找不到文件,再尝试所有关键词
- if not candidate_files and len(keywords) > 1:
- logging.info(f"使用最具体的关键词 '{specific_keywords[0]}' 未找到文件,尝试所有关键词...")
- candidate_files = find_files_with_keyword(KNOWLEDGE_BASE_PATHS, keywords)
+ candidate_files = find_files_with_keyword(KNOWLEDGE_BASE_PATHS, keywords)
if not candidate_files:
logging.info(f"未找到与 '{keywords}' 相关的文件。")
@@ -351,14 +535,11 @@ def get_context(question: str) -> str:
logging.info(f"文件名精确匹配: {file_path}")
code_block = extract_relevant_code(file_path, keyword)
if code_block:
- lang = "csharp" if file_path.endswith(('.cs', '.txt')) else "xml"
- priority_results.append(
- f"---\n"
- f"**文件路径 (精确匹配):** `{file_path}`\n\n"
- f"```{lang}\n"
- f"{code_block}\n"
- f"```"
- )
+ priority_results.append({
+ 'path': file_path,
+ 'similarity': 1.0, # 精确匹配给予最高分
+ 'code': code_block
+ })
is_priority = True
break # 已处理该文件,跳出内层循环
if not is_priority:
@@ -368,7 +549,7 @@ def get_context(question: str) -> str:
# 3. 向量化和相似度计算 (精准筛选)
# 增加超时保护:限制向量化的文件数量
- MAX_FILES_TO_VECTORIZE = 25
+ MAX_FILES_TO_VECTORIZE = 50 # 增加处理文件数量
if len(candidate_files) > MAX_FILES_TO_VECTORIZE:
logging.warning(f"候选文件过多 ({len(candidate_files)}),仅处理前 {MAX_FILES_TO_VECTORIZE} 个。")
candidate_files = candidate_files[:MAX_FILES_TO_VECTORIZE]
@@ -392,45 +573,38 @@ def get_context(question: str) -> str:
return "无法为任何候选文件生成向量。"
# 找到最相似的多个文件
- best_matches = find_most_similar_files(question_embedding, file_embeddings, top_n=5) # 增加返回数量
+ best_matches = find_most_similar_files(question_embedding, file_embeddings, top_n=10) # 增加返回数量以供重排序
if not best_matches:
return "计算向量相似度失败或没有找到足够相似的文件。"
- # 4. 提取代码并格式化输出
- output_parts = [f"根据向量相似度分析,与 '{', '.join(keywords)}' 最相关的代码定义如下:\n"]
- output_parts.extend(priority_results) # 将优先结果放在最前面
+ # 新增:重排序处理
+ reranked_matches = rerank_files(question, best_matches, top_n=5)
- extracted_blocks = set() # 用于防止重复提取相同的代码块
-
- for match in best_matches:
- file_path = match['path']
- similarity = match['similarity']
-
- # 对每个关键词都尝试提取代码
- for keyword in keywords:
- code_block = extract_relevant_code(file_path, keyword)
-
- if code_block and code_block not in extracted_blocks:
- extracted_blocks.add(code_block)
- lang = "csharp" if file_path.endswith(('.cs', '.txt')) else "xml"
- output_parts.append(
- f"---\n"
- f"**文件路径:** `{file_path}`\n"
- f"**相似度:** {similarity:.4f}\n\n"
- f"```{lang}\n"
- f"{code_block}\n"
- f"```"
- )
+ # 提取代码内容
+ results_with_code = []
+ for match in reranked_matches:
+ code_block = extract_relevant_code(match['path'], "")
+ if code_block:
+ match['code'] = code_block
+ results_with_code.append(match)
- if len(output_parts) <= 1:
- return f"虽然找到了相似的文件,但无法在其中提取到关于 '{', '.join(keywords)}' 的完整代码块。"
-
- final_output = "\n".join(output_parts)
+ # 将优先结果添加到结果列表开头
+ results_with_code = priority_results + results_with_code
+
+ if len(results_with_code) <= 0:
+ return f"虽然找到了相似的文件,但无法在其中提取到相关代码块。"
+
+ # 直接返回原始代码结果,而不是使用LLM格式化
+ final_output = ""
+ for i, result in enumerate(results_with_code, 1):
+ final_output += f"--- 结果 {i} (相似度: {result['similarity']:.3f}) ---\n"
+ final_output += f"文件路径: {result['path']}\n\n"
+ final_output += f"{result['code']}\n\n"
# 5. 更新缓存并返回结果
- logging.info(f"向量搜索完成。找到了 {len(best_matches)} 个匹配项并成功提取了代码。")
- save_cache_for_keyword(cache_key, final_output)
+ logging.info(f"向量搜索完成。找到了 {len(results_with_code)} 个匹配项并成功提取了代码。")
+ save_cache_for_question(question, keywords, final_output)
return final_output
@@ -444,4 +618,4 @@ if __name__ == "__main__":
logging.info(f"Python Executable: {sys.executable}")
logging.info("RimWorld 向量知识库 (FastMCP版, v2.1-v4-model) 正在启动...")
# 使用 'stdio' 传输协议
- mcp.run(transport="stdio")
+ mcp.run(transport="stdio")
\ No newline at end of file
diff --git a/MCP/vector_cache/AbilityDef.txt b/MCP/vector_cache/AbilityDef.txt
deleted file mode 100644
index 08b7ce71..00000000
--- a/MCP/vector_cache/AbilityDef.txt
+++ /dev/null
@@ -1,621 +0,0 @@
-根据向量相似度分析,与 'AbilityDef' 最相关的代码定义如下:
-
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityDef.txt`
-
-```csharp
-public class AbilityDef : Def
-{
- public Type abilityClass = typeof(Ability);
-
- public Type gizmoClass = typeof(Command_Ability);
-
- public List comps = new List();
-
- public AbilityCategoryDef category;
-
- public int displayOrder;
-
- public List statBases;
-
- public VerbProperties verbProperties;
-
- public KeyBindingDef hotKey;
-
- public JobDef jobDef;
-
- public ThingDef warmupMote;
-
- public EffecterDef warmupEffecter;
-
- public FleckDef emittedFleck;
-
- public int emissionInterval;
-
- public string warmupMoteSocialSymbol;
-
- public SoundDef warmupStartSound;
-
- public SoundDef warmupSound;
-
- public SoundDef warmupPreEndSound;
-
- public float warmupPreEndSoundSeconds;
-
- public Vector3 moteDrawOffset;
-
- public float moteOffsetAmountTowardsTarget;
-
- public bool canUseAoeToGetTargets = true;
-
- public bool useAverageTargetPositionForWarmupEffecter;
-
- public bool targetRequired = true;
-
- public bool targetWorldCell;
-
- public bool showGizmoOnWorldView;
-
- public bool aiCanUse;
-
- public bool ai_SearchAOEForTargets;
-
- public bool ai_IsOffensive = true;
-
- public bool ai_IsIncendiary = true;
-
- public bool groupAbility;
-
- public int level;
-
- public IntRange cooldownTicksRange;
-
- public bool cooldownPerCharge;
-
- public bool hasExternallyHandledCooldown;
-
- public int charges = -1;
-
- public AbilityGroupDef groupDef;
-
- public bool overrideGroupCooldown;
-
- public List requiredMemes;
-
- public bool sendLetterOnCooldownComplete;
-
- public bool sendMessageOnCooldownComplete;
-
- public bool displayGizmoWhileUndrafted;
-
- public bool disableGizmoWhileUndrafted = true;
-
- public bool writeCombatLog;
-
- public bool stunTargetWhileCasting;
-
- public bool showPsycastEffects = true;
-
- public bool showCastingProgressBar;
-
- public float detectionChanceOverride = -1f;
-
- public float uiOrder;
-
- public bool waitForJobEnd;
-
- public bool showWhenDrafted = true;
-
- public bool showOnCharacterCard = true;
-
- public bool hostile = true;
-
- public bool casterMustBeCapableOfViolence = true;
-
- [MustTranslate]
- public string confirmationDialogText;
-
- [NoTranslate]
- public string iconPath;
-
- public Texture2D uiIcon = BaseContent.BadTex;
-
- private string cachedTooltip;
-
- private Pawn cachedTooltipPawn;
-
- private List cachedTargets;
-
- private int requiredPsyfocusBandCached = -1;
-
- private bool? anyCompOverridesPsyfocusCost;
-
- private FloatRange psyfocusCostRange = new FloatRange(-1f, -1f);
-
- private string psyfocusCostPercent;
-
- private string psyfocusCostPercentMax;
-
- private Texture2D warmupMoteSocialSymbolCached;
-
- public float EntropyGain => statBases.GetStatValueFromList(StatDefOf.Ability_EntropyGain, 0f);
-
- public float PsyfocusCost => statBases.GetStatValueFromList(StatDefOf.Ability_PsyfocusCost, 0f);
-
- public float EffectRadius => statBases.GetStatValueFromList(StatDefOf.Ability_EffectRadius, 0f);
-
- public bool HasAreaOfEffect => EffectRadius > float.Epsilon;
-
- public float DetectionChance
- {
- get
- {
- if (!(detectionChanceOverride >= 0f))
- {
- return this.GetStatValueAbstract(StatDefOf.Ability_DetectChancePerEntropy);
- }
- return detectionChanceOverride;
- }
- }
-
- public bool IsPsycast => typeof(Psycast).IsAssignableFrom(abilityClass);
-
- public string PsyfocusCostPercent
- {
- get
- {
- if (psyfocusCostPercent.NullOrEmpty())
- {
- psyfocusCostPercent = PsyfocusCost.ToStringPercent();
- }
- return psyfocusCostPercent;
- }
- }
-
- public string PsyfocusCostPercentMax
- {
- get
- {
- if (psyfocusCostPercentMax.NullOrEmpty())
- {
- psyfocusCostPercentMax = PsyfocusCostRange.max.ToStringPercent();
- }
- return psyfocusCostPercentMax;
- }
- }
-
- public int RequiredPsyfocusBand
- {
- get
- {
- if (requiredPsyfocusBandCached == -1)
- {
- requiredPsyfocusBandCached = Pawn_PsychicEntropyTracker.MaxAbilityLevelPerPsyfocusBand.Count - 1;
- for (int i = 0; i < Pawn_PsychicEntropyTracker.MaxAbilityLevelPerPsyfocusBand.Count; i++)
- {
- int num = Pawn_PsychicEntropyTracker.MaxAbilityLevelPerPsyfocusBand[i];
- if (level <= num)
- {
- requiredPsyfocusBandCached = i;
- break;
- }
- }
- }
- return requiredPsyfocusBandCached;
- }
- }
-
- public bool AnyCompOverridesPsyfocusCost
- {
- get
- {
- if (!anyCompOverridesPsyfocusCost.HasValue)
- {
- anyCompOverridesPsyfocusCost = false;
- if (comps != null)
- {
- foreach (AbilityCompProperties comp in comps)
- {
- if (comp.OverridesPsyfocusCost)
- {
- anyCompOverridesPsyfocusCost = true;
- break;
- }
- }
- }
- }
- return anyCompOverridesPsyfocusCost.Value;
- }
- }
-
- public FloatRange PsyfocusCostRange
- {
- get
- {
- if (psyfocusCostRange.min < 0f)
- {
- if (!AnyCompOverridesPsyfocusCost)
- {
- psyfocusCostRange = new FloatRange(PsyfocusCost, PsyfocusCost);
- }
- else
- {
- foreach (AbilityCompProperties comp in comps)
- {
- if (comp.OverridesPsyfocusCost)
- {
- psyfocusCostRange = comp.PsyfocusCostRange;
- break;
- }
- }
- }
- }
- return psyfocusCostRange;
- }
- }
-
- public Texture2D WarmupMoteSocialSymbol
- {
- get
- {
- if (!warmupMoteSocialSymbol.NullOrEmpty() && warmupMoteSocialSymbolCached == null)
- {
- warmupMoteSocialSymbolCached = ContentFinder.Get(warmupMoteSocialSymbol);
- }
- return warmupMoteSocialSymbolCached;
- }
- }
-
- public IEnumerable StatSummary(Pawn forPawn = null)
- {
- string text = null;
- foreach (AbilityCompProperties comp in comps)
- {
- if (comp.OverridesPsyfocusCost)
- {
- text = comp.PsyfocusCostExplanation;
- break;
- }
- }
- if (text == null)
- {
- if (PsyfocusCost > float.Epsilon)
- {
- yield return "AbilityPsyfocusCost".Translate() + ": " + PsyfocusCost.ToStringPercent();
- }
- }
- else
- {
- yield return text;
- }
- if (EntropyGain > float.Epsilon)
- {
- yield return string.Concat("AbilityEntropyGain".Translate() + ": ", EntropyGain.ToString());
- }
- if (verbProperties.warmupTime > float.Epsilon)
- {
- yield return string.Concat("AbilityCastingTime".Translate() + ": ", verbProperties.warmupTime.ToString()) + "LetterSecond".Translate();
- }
- if (cooldownTicksRange.min == cooldownTicksRange.max && cooldownTicksRange.min > 0)
- {
- yield return "StatsReport_Cooldown".Translate() + ": " + cooldownTicksRange.min.ToStringTicksToPeriod(allowSeconds: true, shortForm: false, canUseDecimals: true, allowYears: false);
- }
- float num = EffectDuration(forPawn);
- if (num > float.Epsilon)
- {
- int num2 = num.SecondsToTicks();
- yield return "AbilityDuration".Translate() + ": " + ((num2 >= 2500) ? num2.ToStringTicksToPeriod() : (num.ToString() + "LetterSecond".Translate()));
- }
- if (HasAreaOfEffect)
- {
- yield return string.Concat("AbilityEffectRadius".Translate() + ": ", Mathf.Ceil(EffectRadius).ToString());
- }
- if (comps == null)
- {
- yield break;
- }
- for (int i = 0; i < comps.Count; i++)
- {
- foreach (string item in comps[i].ExtraStatSummary())
- {
- yield return item;
- }
- }
- }
-
- public float EffectDuration(Pawn forPawn = null)
- {
- return this.GetStatValueAbstract(StatDefOf.Ability_Duration, forPawn);
- }
-
- public override void PostLoad()
- {
- if (!string.IsNullOrEmpty(iconPath))
- {
- LongEventHandler.ExecuteWhenFinished(delegate
- {
- uiIcon = ContentFinder.Get(iconPath);
- });
- }
- }
-
- public string GetTooltip(Pawn pawn = null)
- {
- if (cachedTooltip == null || cachedTooltipPawn != pawn)
- {
- cachedTooltip = LabelCap.Colorize(ColoredText.TipSectionTitleColor) + ((level > 0) ? string.Concat("\n" + "Level".Translate().CapitalizeFirst() + " ", level.ToString()) : "") + "\n\n" + description;
- cachedTooltipPawn = pawn;
- string text = StatSummary(pawn).ToLineList();
- if (!text.NullOrEmpty())
- {
- cachedTooltip = cachedTooltip + "\n\n" + text;
- }
- }
- if (pawn != null && ModsConfig.RoyaltyActive && IsPsycast && level > 0)
- {
- Faction first = Faction.GetMinTitleForImplantAllFactions(HediffDefOf.PsychicAmplifier).First;
- if (first != null)
- {
- RoyalTitleDef minTitleForImplant = first.GetMinTitleForImplant(HediffDefOf.PsychicAmplifier, level);
- RoyalTitleDef currentTitle = pawn.royalty.GetCurrentTitle(first);
- if (minTitleForImplant != null && (currentTitle == null || currentTitle.seniority < minTitleForImplant.seniority) && DetectionChance > 0f)
- {
- return cachedTooltip + "\n\n" + ((string)"PsycastIsIllegal".Translate(pawn.Named("PAWN"), minTitleForImplant.GetLabelCapFor(pawn).Named("TITLE"))).Colorize(ColoredText.WarningColor);
- }
- }
- }
- return cachedTooltip;
- }
-
- public override IEnumerable SpecialDisplayStats(StatRequest req)
- {
- if (cachedTargets == null)
- {
- cachedTargets = new List();
- if (verbProperties.targetParams.canTargetPawns && verbProperties.targetParams.canTargetSelf)
- {
- cachedTargets.Add("TargetSelf".Translate());
- }
- if (verbProperties.targetParams.canTargetLocations)
- {
- cachedTargets.Add("TargetGround".Translate());
- }
- if (verbProperties.targetParams.canTargetPawns && verbProperties.targetParams.canTargetHumans)
- {
- cachedTargets.Add("TargetHuman".Translate());
- }
- if (verbProperties.targetParams.canTargetPawns && verbProperties.targetParams.canTargetAnimals)
- {
- cachedTargets.Add("TargetAnimal".Translate());
- }
- }
- int num = comps.OfType().Sum((CompProperties_AbilityEffect e) => e.goodwillImpact);
- if (num != 0)
- {
- yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_GoodwillImpact, num, req);
- }
- if (IsPsycast && level != 0)
- {
- yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_RequiredPsylink, level, req);
- }
- yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_CastingTime, verbProperties.warmupTime, req);
- if (verbProperties.range > 0f)
- {
- yield return new StatDrawEntry(StatCategoryDefOf.Ability, StatDefOf.Ability_Range, verbProperties.range, req);
- }
- yield return new StatDrawEntry(StatCategoryDefOf.Ability, "Target".Translate(), cachedTargets.ToCommaList().CapitalizeFirst(), "AbilityTargetDesc".Translate(), 1001);
- yield return new StatDrawEntry(StatCategoryDefOf.Ability, "AbilityRequiresLOS".Translate(), verbProperties.requireLineOfSight ? "Yes".Translate() : "No".Translate(), "", 1000);
- }
-
- public override IEnumerable ConfigErrors()
- {
- foreach (string item in base.ConfigErrors())
- {
- yield return item;
- }
- if (abilityClass == null)
- {
- yield return "abilityClass is null";
- }
- if (verbProperties == null)
- {
- yield return "verbProperties are null";
- }
- if (label.NullOrEmpty())
- {
- yield return "no label";
- }
- if (statBases != null)
- {
- foreach (StatModifier statBase in statBases)
- {
- if (statBases.Count((StatModifier st) => st.stat == statBase.stat) > 1)
- {
- yield return "defines the stat base " + statBase.stat?.ToString() + " more than once.";
- }
- }
- }
- for (int i = 0; i < comps.Count; i++)
- {
- foreach (string item2 in comps[i].ConfigErrors(this))
- {
- yield return item2;
- }
- }
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Royalty\Defs\AbilityDefs\Abilities.xml`
-**相似度:** 0.5815
-
-```xml
-
- Skip
-
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityStatModifiers.txt`
-**相似度:** 0.5807
-
-```csharp
-public class AbilityStatModifiers
-{
- public AbilityDef ability;
-
- public List modifiers;
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\AbilityDefOf.txt`
-**相似度:** 0.5779
-
-```csharp
-public static class AbilityDefOf
-{
- [MayRequireRoyalty]
- public static AbilityDef Speech;
-
- [MayRequireBiotech]
- public static AbilityDef ReimplantXenogerm;
-
- [MayRequireBiotech]
- public static AbilityDef ResurrectionMech;
-
- [MayRequireAnomaly]
- public static AbilityDef EntitySkip;
-
- [MayRequireAnomaly]
- public static AbilityDef UnnaturalCorpseSkip;
-
- [MayRequireAnomaly]
- public static AbilityDef ConsumeLeap_Devourer;
-
- [MayRequireOdyssey]
- public static AbilityDef SludgeSpew;
-
- [MayRequireOdyssey]
- public static AbilityDef EggSpew;
-
- static AbilityDefOf()
- {
- DefOfHelper.EnsureInitializedInCtor(typeof(AbilityDefOf));
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompAbilityEffect_GiveMentalState.txt`
-**相似度:** 0.5541
-
-```csharp
-public class CompAbilityEffect_GiveMentalState : CompAbilityEffect
-{
- public new CompProperties_AbilityGiveMentalState Props => (CompProperties_AbilityGiveMentalState)props;
-
- public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
- {
- base.Apply(target, dest);
- Pawn pawn = (Props.applyToSelf ? parent.pawn : (target.Thing as Pawn));
- if (pawn != null && !pawn.InMentalState)
- {
- TryGiveMentalState(pawn.RaceProps.IsMechanoid ? (Props.stateDefForMechs ?? Props.stateDef) : Props.stateDef, pawn, parent.def, Props.durationMultiplier, parent.pawn, Props.forced);
- RestUtility.WakeUp(pawn);
- if (Props.casterEffect != null)
- {
- Effecter effecter = Props.casterEffect.SpawnAttached(parent.pawn, parent.pawn.MapHeld);
- effecter.Trigger(parent.pawn, null);
- effecter.Cleanup();
- }
- if (Props.targetEffect != null)
- {
- Effecter effecter2 = Props.targetEffect.SpawnAttached(parent.pawn, parent.pawn.MapHeld);
- effecter2.Trigger(pawn, null);
- effecter2.Cleanup();
- }
- }
- }
-
- public override bool Valid(LocalTargetInfo target, bool throwMessages = false)
- {
- if (!base.Valid(target, throwMessages))
- {
- return false;
- }
- Pawn pawn = target.Pawn;
- if (pawn != null)
- {
- if (!AbilityUtility.ValidateNoMentalState(pawn, throwMessages, parent))
- {
- return false;
- }
- if (Props.excludeNPCFactions && pawn.Faction != null && !pawn.Faction.IsPlayer)
- {
- if (throwMessages)
- {
- Messages.Message("CannotUseAbility".Translate(parent.def.label) + ": " + "TargetBelongsToNPCFaction".Translate(), pawn, MessageTypeDefOf.RejectInput, historical: false);
- }
- return false;
- }
- }
- return true;
- }
-
- public static void TryGiveMentalState(MentalStateDef def, Pawn p, AbilityDef ability, StatDef multiplierStat, Pawn caster, bool forced = false)
- {
- if (p.mindState.mentalStateHandler.TryStartMentalState(def, null, forced, forceWake: true, causedByMood: false, caster, transitionSilently: false, causedByDamage: false, ability.IsPsycast))
- {
- float num = ability.GetStatValueAbstract(StatDefOf.Ability_Duration, caster);
- if (multiplierStat != null)
- {
- num *= p.GetStatValue(multiplierStat);
- }
- if (num > 0f)
- {
- p.mindState.mentalStateHandler.CurState.forceRecoverAfterTicks = num.SecondsToTicks();
- }
- p.mindState.mentalStateHandler.CurState.sourceFaction = caster.Faction;
- }
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_ResurrectMech.txt`
-**相似度:** 0.5473
-
-```csharp
-public class CompProperties_ResurrectMech : CompProperties_AbilityEffect
-{
- public int maxCorpseAgeTicks = int.MaxValue;
-
- public List costs = new List();
-
- public EffecterDef appliedEffecterDef;
-
- public EffecterDef centerEffecterDef;
-
- public CompProperties_ResurrectMech()
- {
- compClass = typeof(CompAbilityEffect_ResurrectMech);
- }
-
- public override IEnumerable ConfigErrors(AbilityDef parentDef)
- {
- foreach (string item in base.ConfigErrors(parentDef))
- {
- yield return item;
- }
- if (costs.NullOrEmpty())
- {
- yield return "costs list is null";
- yield break;
- }
- foreach (MechChargeCosts cost in costs)
- {
- if (cost.weightClass == null)
- {
- yield return $"costs list contains null weight class with cost {cost.cost}";
- }
- }
- }
-}
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/AddHumanlikeOrders-FloatMenuMakerMap.txt b/MCP/vector_cache/AddHumanlikeOrders-FloatMenuMakerMap.txt
deleted file mode 100644
index 96addb59..00000000
--- a/MCP/vector_cache/AddHumanlikeOrders-FloatMenuMakerMap.txt
+++ /dev/null
@@ -1,519 +0,0 @@
-根据向量相似度分析,与 'AddHumanlikeOrders, FloatMenuMakerMap' 最相关的代码定义如下:
-
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuMakerMap.txt`
-
-```csharp
-public static class FloatMenuMakerMap
-{
- private static List providers;
-
- public static FloatMenuOptionProvider currentProvider;
-
- public static Pawn makingFor;
-
- public static void Init()
- {
- providers = new List();
- foreach (Type item in typeof(FloatMenuOptionProvider).AllSubclassesNonAbstract())
- {
- providers.Add((FloatMenuOptionProvider)Activator.CreateInstance(item));
- }
- }
-
- public static List GetOptions(List selectedPawns, Vector3 clickPos, out FloatMenuContext context)
- {
- List list = new List();
- context = null;
- if (!clickPos.InBounds(Find.CurrentMap))
- {
- return list;
- }
- context = new FloatMenuContext(selectedPawns, clickPos, Find.CurrentMap);
- if (!context.allSelectedPawns.Any())
- {
- return list;
- }
- if (!context.ClickedCell.IsValid || !context.ClickedCell.InBounds(Find.CurrentMap))
- {
- return list;
- }
- if (!context.IsMultiselect)
- {
- AcceptanceReport acceptanceReport = ShouldGenerateFloatMenuForPawn(context.FirstSelectedPawn);
- if (!acceptanceReport.Accepted)
- {
- if (!acceptanceReport.Reason.NullOrEmpty())
- {
- Messages.Message(acceptanceReport.Reason, context.FirstSelectedPawn, MessageTypeDefOf.RejectInput, historical: false);
- }
- return list;
- }
- }
- else
- {
- context.allSelectedPawns.RemoveAll((Pawn selectedPawn) => !ShouldGenerateFloatMenuForPawn(selectedPawn));
- if (!context.allSelectedPawns.Any())
- {
- return list;
- }
- }
- if (!context.IsMultiselect)
- {
- makingFor = context.FirstSelectedPawn;
- }
- GetProviderOptions(context, list);
- makingFor = null;
- return list;
- }
-
- private static void GetProviderOptions(FloatMenuContext context, List options)
- {
- foreach (FloatMenuOptionProvider provider in providers)
- {
- try
- {
- currentProvider = provider;
- if (!context.ValidSelectedPawns.Any() || !provider.Applies(context))
- {
- continue;
- }
- options.AddRange(provider.GetOptions(context));
- foreach (Thing clickedThing in context.ClickedThings)
- {
- if (!provider.TargetThingValid(clickedThing, context))
- {
- continue;
- }
- Thing thing = clickedThing;
- if (thing.TryGetComp(out CompSelectProxy comp) && comp.thingToSelect != null)
- {
- thing = comp.thingToSelect;
- }
- foreach (FloatMenuOption item in provider.GetOptionsFor(thing, context))
- {
- FloatMenuOption floatMenuOption = item;
- if (floatMenuOption.iconThing == null)
- {
- floatMenuOption.iconThing = thing;
- }
- item.targetsDespawned = !thing.Spawned;
- options.Add(item);
- }
- }
- foreach (Pawn clickedPawn in context.ClickedPawns)
- {
- if (!provider.TargetPawnValid(clickedPawn, context))
- {
- continue;
- }
- foreach (FloatMenuOption item2 in provider.GetOptionsFor(clickedPawn, context))
- {
- FloatMenuOption floatMenuOption = item2;
- if (floatMenuOption.iconThing == null)
- {
- floatMenuOption.iconThing = clickedPawn;
- }
- item2.targetsDespawned = !clickedPawn.Spawned;
- options.Add(item2);
- }
- }
- }
- catch (Exception arg)
- {
- Log.Error($"Error in FloatMenuWorker {provider.GetType().Name}: {arg}");
- }
- }
- currentProvider = null;
- }
-
- public static AcceptanceReport ShouldGenerateFloatMenuForPawn(Pawn pawn)
- {
- if (pawn.Map != Find.CurrentMap)
- {
- return false;
- }
- if (pawn.Downed)
- {
- return "IsIncapped".Translate(pawn.LabelCap, pawn);
- }
- if (ModsConfig.BiotechActive && pawn.Deathresting)
- {
- return "IsDeathresting".Translate(pawn.Named("PAWN"));
- }
- Lord lord = pawn.GetLord();
- if (lord != null)
- {
- AcceptanceReport result = lord.AllowsFloatMenu(pawn);
- if (!result.Accepted)
- {
- return result;
- }
- }
- return true;
- }
-
- public static FloatMenuOption GetAutoTakeOption(List options)
- {
- bool flag = true;
- FloatMenuOption floatMenuOption = null;
- foreach (FloatMenuOption option in options)
- {
- if (option.Disabled || !option.autoTakeable)
- {
- flag = false;
- break;
- }
- if (floatMenuOption == null || option.autoTakeablePriority > floatMenuOption.autoTakeablePriority)
- {
- floatMenuOption = option;
- }
- }
- if (!flag || floatMenuOption == null)
- {
- return null;
- }
- return floatMenuOption;
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuContext.txt`
-**相似度:** 0.5788
-
-```csharp
-public class FloatMenuContext
-{
- public List allSelectedPawns;
-
- public Vector3 clickPosition;
-
- public Map map;
-
- private IntVec3 cachedClickedCell;
-
- private List cachedClickedThings;
-
- private List cachedClickedPawns;
-
- private Room cachedClickedRoom;
-
- private Zone cachedClickedZone;
-
- public IntVec3 ClickedCell => cachedClickedCell;
-
- public Room ClickedRoom => cachedClickedRoom;
-
- public Zone ClickedZone => cachedClickedZone;
-
- public List ClickedThings => cachedClickedThings;
-
- public List ClickedPawns => cachedClickedPawns;
-
- public bool IsMultiselect => allSelectedPawns.Count > 1;
-
- public Pawn FirstSelectedPawn
- {
- get
- {
- foreach (Pawn allSelectedPawn in allSelectedPawns)
- {
- if (FloatMenuMakerMap.currentProvider == null || FloatMenuMakerMap.currentProvider.SelectedPawnValid(allSelectedPawn, this))
- {
- return allSelectedPawn;
- }
- }
- return null;
- }
- }
-
- public IEnumerable ValidSelectedPawns
- {
- get
- {
- foreach (Pawn allSelectedPawn in allSelectedPawns)
- {
- if (FloatMenuMakerMap.currentProvider == null || FloatMenuMakerMap.currentProvider.SelectedPawnValid(allSelectedPawn, this))
- {
- yield return allSelectedPawn;
- }
- }
- }
- }
-
- public FloatMenuContext(List selectedPawns, Vector3 clickPosition, Map map)
- {
- allSelectedPawns = selectedPawns;
- this.clickPosition = clickPosition;
- this.map = map;
- cachedClickedCell = IntVec3.FromVector3(clickPosition);
- cachedClickedRoom = cachedClickedCell.GetRoom(map);
- cachedClickedZone = cachedClickedCell.GetZone(map);
- cachedClickedThings = GenUI.ThingsUnderMouse(clickPosition, 0.8f, TargetingParameters.ForThing());
- cachedClickedPawns = GenUI.ThingsUnderMouse(clickPosition, 0.8f, TargetingParameters.ForPawns()).OfType().ToList();
- selectedPawns.RemoveAll((Pawn pawn) => !pawn.CanTakeOrder);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\Verse\FloatMenuMap.txt`
-**相似度:** 0.5739
-
-```csharp
-public class FloatMenuMap : FloatMenu
-{
- private Vector3 clickPos;
-
- private static Dictionary> cachedChoices = new Dictionary>();
-
- private List lastOptionsForRevalidation;
-
- private int nextOptionToRevalidate;
-
- public const int RevalidateEveryFrame = 4;
-
- public FloatMenuMap(List options, string title, Vector3 clickPos)
- : base(options, title)
- {
- this.clickPos = clickPos;
- }
-
- public override void DoWindowContents(Rect inRect)
- {
- if (!Find.Selector.AnyPawnSelected)
- {
- Find.WindowStack.TryRemove(this);
- return;
- }
- bool flag = options.Count >= 3;
- if (Time.frameCount % 4 == 0 || lastOptionsForRevalidation == null)
- {
- lastOptionsForRevalidation = FloatMenuMakerMap.GetOptions(Find.Selector.SelectedPawns, clickPos, out var _);
- cachedChoices.Clear();
- cachedChoices.Add(clickPos, lastOptionsForRevalidation);
- if (!flag)
- {
- for (int i = 0; i < options.Count; i++)
- {
- RevalidateOption(options[i]);
- }
- }
- }
- else if (flag)
- {
- if (nextOptionToRevalidate >= options.Count)
- {
- nextOptionToRevalidate = 0;
- }
- int num = Mathf.CeilToInt((float)options.Count / 3f);
- int num2 = nextOptionToRevalidate;
- int num3 = 0;
- while (num2 < options.Count && num3 < num)
- {
- RevalidateOption(options[num2]);
- nextOptionToRevalidate++;
- num2++;
- num3++;
- }
- }
- base.DoWindowContents(inRect);
- void RevalidateOption(FloatMenuOption option)
- {
- if (!option.Disabled && !StillValid(option, lastOptionsForRevalidation))
- {
- option.Disabled = true;
- }
- }
- }
-
- private static bool StillValid(FloatMenuOption opt, List curOpts)
- {
- if (opt.revalidateClickTarget == null)
- {
- for (int i = 0; i < curOpts.Count; i++)
- {
- if (OptionsMatch(opt, curOpts[i]))
- {
- return true;
- }
- }
- }
- else
- {
- if (!opt.targetsDespawned && !opt.revalidateClickTarget.Spawned)
- {
- return false;
- }
- Vector3 key = opt.revalidateClickTarget.PositionHeld.ToVector3Shifted();
- if (!cachedChoices.TryGetValue(key, out var value))
- {
- FloatMenuContext context;
- List list = FloatMenuMakerMap.GetOptions(Find.Selector.SelectedPawns, key, out context);
- cachedChoices.Add(key, list);
- value = list;
- }
- for (int j = 0; j < value.Count; j++)
- {
- if (OptionsMatch(opt, value[j]))
- {
- return !value[j].Disabled;
- }
- }
- }
- return false;
- }
-
- public override void PreOptionChosen(FloatMenuOption opt)
- {
- base.PreOptionChosen(opt);
- if (!opt.Disabled && !StillValid(opt, FloatMenuMakerMap.GetOptions(Find.Selector.SelectedPawns, clickPos, out var _)))
- {
- opt.Disabled = true;
- }
- }
-
- private static bool OptionsMatch(FloatMenuOption a, FloatMenuOption b)
- {
- if (a.Label == b.Label)
- {
- return true;
- }
- return false;
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\FloatMenuOptionProvider.txt`
-**相似度:** 0.5483
-
-```csharp
-public abstract class FloatMenuOptionProvider
-{
- protected abstract bool Drafted { get; }
-
- protected abstract bool Undrafted { get; }
-
- protected abstract bool Multiselect { get; }
-
- protected virtual bool RequiresManipulation => false;
-
- protected virtual bool MechanoidCanDo => false;
-
- protected virtual bool CanSelfTarget => false;
-
- public virtual bool CanTargetDespawned => false;
-
- protected virtual bool IgnoreFogged => true;
-
- public virtual bool SelectedPawnValid(Pawn pawn, FloatMenuContext context)
- {
- if (pawn.IsMutant && pawn.mutant.Def.whitelistedFloatMenuProviders != null && !pawn.mutant.Def.whitelistedFloatMenuProviders.Contains(FloatMenuMakerMap.currentProvider.GetType()))
- {
- return false;
- }
- if (!Drafted && pawn.Drafted)
- {
- return false;
- }
- if (!Undrafted && !pawn.Drafted)
- {
- return false;
- }
- if (!MechanoidCanDo && pawn.RaceProps.IsMechanoid)
- {
- return false;
- }
- if (RequiresManipulation && !pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
- {
- return false;
- }
- return true;
- }
-
- public virtual bool TargetThingValid(Thing thing, FloatMenuContext context)
- {
- if (!CanTargetDespawned && !thing.Spawned)
- {
- return false;
- }
- if (thing is Pawn pawn && !TargetPawnValid(pawn, context))
- {
- return false;
- }
- return true;
- }
-
- public virtual bool TargetPawnValid(Pawn pawn, FloatMenuContext context)
- {
- if (!CanSelfTarget && pawn == context.FirstSelectedPawn)
- {
- return false;
- }
- return true;
- }
-
- public virtual bool Applies(FloatMenuContext context)
- {
- if (!Multiselect && context.IsMultiselect)
- {
- return false;
- }
- if (IgnoreFogged && context.ClickedCell.Fogged(context.map))
- {
- return false;
- }
- if (!AppliesInt(context))
- {
- return false;
- }
- return true;
- }
-
- protected virtual bool AppliesInt(FloatMenuContext context)
- {
- return true;
- }
-
- public virtual IEnumerable GetOptions(FloatMenuContext context)
- {
- FloatMenuOption singleOption = GetSingleOption(context);
- if (singleOption != null)
- {
- yield return singleOption;
- }
- }
-
- public virtual IEnumerable GetOptionsFor(Thing clickedThing, FloatMenuContext context)
- {
- FloatMenuOption singleOptionFor = GetSingleOptionFor(clickedThing, context);
- if (singleOptionFor != null)
- {
- yield return singleOptionFor;
- }
- }
-
- public virtual IEnumerable GetOptionsFor(Pawn clickedPawn, FloatMenuContext context)
- {
- FloatMenuOption singleOptionFor = GetSingleOptionFor(clickedPawn, context);
- if (singleOptionFor != null)
- {
- yield return singleOptionFor;
- }
- }
-
- protected virtual FloatMenuOption GetSingleOption(FloatMenuContext context)
- {
- return null;
- }
-
- protected virtual FloatMenuOption GetSingleOptionFor(Thing clickedThing, FloatMenuContext context)
- {
- return null;
- }
-
- protected virtual FloatMenuOption GetSingleOptionFor(Pawn clickedPawn, FloatMenuContext context)
- {
- return null;
- }
-}
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/BiosculpterPod-ThingDef.txt b/MCP/vector_cache/BiosculpterPod-ThingDef.txt
deleted file mode 100644
index a55a7d7b..00000000
--- a/MCP/vector_cache/BiosculpterPod-ThingDef.txt
+++ /dev/null
@@ -1,1502 +0,0 @@
-根据向量相似度分析,与 'BiosculpterPod, ThingDef' 最相关的代码定义如下:
-
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_BaseCycle.txt`
-**相似度:** 0.7659
-
-```csharp
-public abstract class CompProperties_BiosculpterPod_BaseCycle : CompProperties
-{
- [NoTranslate]
- public string key;
-
- [MustTranslate]
- public string label;
-
- [MustTranslate]
- public string description;
-
- [NoTranslate]
- public string iconPath;
-
- public float durationDays;
-
- public Color operatingColor = new Color(0.5f, 0.7f, 0.5f);
-
- public ThoughtDef gainThoughtOnCompletion;
-
- public List requiredResearch;
-
- public List extraRequiredIngredients;
-
- private Texture2D icon;
-
- public Texture2D Icon
- {
- get
- {
- if (icon == null)
- {
- icon = ContentFinder.Get(iconPath);
- }
- return icon;
- }
- }
-
- public string LabelCap => label.CapitalizeFirst();
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod.txt`
-**相似度:** 0.7294
-
-```csharp
-public class CompBiosculpterPod : ThingComp, ISuspendableThingHolder, IThingHolder, IThingHolderWithDrawnPawn, IStoreSettingsParent, INotifyHauledTo, ISearchableContents
-{
- private const int NoPowerEjectCumulativeTicks = 60000;
-
- private const int BiotunedDuration = 4800000;
-
- private const float NutritionRequired = 5f;
-
- private const float CacheForSecs = 2f;
-
- private static readonly Texture2D InterruptCycleIcon = ContentFinder.Get("UI/Designators/Cancel");
-
- private static readonly Material BackgroundMat = SolidColorMaterials.NewSolidColorMaterial(new Color(0.082f, 0.078f, 0.063f), ShaderDatabase.SolidColorBehind);
-
- private const float BackgroundRect_YOff = 0.07317074f;
-
- private const float Pawn_YOff = 0.03658537f;
-
- private string currentCycleKey;
-
- private float currentCycleTicksRemaining;
-
- private int currentCyclePowerCutTicks;
-
- private ThingOwner innerContainer;
-
- private Pawn biotunedTo;
-
- private int biotunedCountdownTicks;
-
- private StorageSettings allowedNutritionSettings;
-
- private float liquifiedNutrition;
-
- public bool autoLoadNutrition = true;
-
- public bool devFillPodLatch;
-
- private bool autoAgeReversal;
-
- private int tickEntered = -99999;
-
- public Job queuedEnterJob;
-
- public Pawn queuedPawn;
-
- private List chosenExtraItems = new List();
-
- private List cycleEligiblePawnOptions = new List();
-
- private Pawn pawnEnteringBiosculpter;
-
- private Dictionary> cachedExtraIngredients = new Dictionary>();
-
- private Dictionary cachedAnyPawnEligible = new Dictionary();
-
- private static Dictionary> cachedBiotunedPods = new Dictionary>();
-
- private Pawn cacheReachIngredientsPawn;
-
- private CompBiosculpterPod_Cycle cacheReachIngredientsCycle;
-
- private float cacheReachIngredientsTime = float.MinValue;
-
- private bool cacheReachIngredientsResult;
-
- private Effecter progressBarEffecter;
-
- private Effecter operatingEffecter;
-
- private Effecter readyEffecter;
-
- private Texture2D cachedAutoAgeReverseIcon;
-
- private List cachedAvailableCycles;
-
- private Dictionary cycleLookup;
-
- private static string cachedAgeReversalCycleKey = null;
-
- private List tmpIngredientsStrings = new List();
-
- private static readonly List tmpItems = new List();
-
- private CompPowerTrader powerTraderComp;
-
- private CompPower powerComp;
-
- private static List cachedPodDefs;
-
- public CompProperties_BiosculpterPod Props => props as CompProperties_BiosculpterPod;
-
- public ThingOwner SearchableContents => innerContainer;
-
- public bool IsContentsSuspended => true;
-
- public float RequiredNutritionRemaining => Mathf.Max(5f - liquifiedNutrition, 0f);
-
- public bool NutritionLoaded => RequiredNutritionRemaining <= 0f;
-
- public bool AutoAgeReversal => autoAgeReversal;
-
- private Texture2D AutoAgeReversalIcon
- {
- get
- {
- if (cachedAutoAgeReverseIcon == null)
- {
- cachedAutoAgeReverseIcon = ContentFinder.Get("UI/Gizmos/BiosculpterAutoAgeReversal");
- }
- return cachedAutoAgeReverseIcon;
- }
- }
-
- public BiosculpterPodState State
- {
- get
- {
- if (Occupant != null)
- {
- return BiosculpterPodState.Occupied;
- }
- if (NutritionLoaded)
- {
- return BiosculpterPodState.SelectingCycle;
- }
- return BiosculpterPodState.LoadingNutrition;
- }
- }
-
- public Pawn Occupant
- {
- get
- {
- if (pawnEnteringBiosculpter != null)
- {
- return pawnEnteringBiosculpter;
- }
- if (currentCycleKey == null)
- {
- return null;
- }
- if (innerContainer.Count != 1)
- {
- return null;
- }
- return innerContainer[0] as Pawn;
- }
- }
-
- public CompBiosculpterPod_Cycle CurrentCycle
- {
- get
- {
- if (currentCycleKey == null)
- {
- return null;
- }
- foreach (CompBiosculpterPod_Cycle availableCycle in AvailableCycles)
- {
- if (availableCycle.Props.key == currentCycleKey)
- {
- return availableCycle;
- }
- }
- return null;
- }
- }
-
- public List AvailableCycles
- {
- get
- {
- if (cachedAvailableCycles == null)
- {
- SetupCycleCaches();
- }
- return cachedAvailableCycles;
- }
- }
-
- public string AgeReversalCycleKey
- {
- get
- {
- if (cachedAgeReversalCycleKey == null)
- {
- SetupCycleCaches();
- }
- return cachedAgeReversalCycleKey;
- }
- }
-
- private float CycleSpeedFactorNoPawn => CleanlinessSpeedFactor * BiotunedSpeedFactor;
-
- public float CycleSpeedFactor
- {
- get
- {
- if (Occupant == null)
- {
- return Mathf.Max(0.1f, CycleSpeedFactorNoPawn);
- }
- return GetCycleSpeedFactorForPawn(Occupant);
- }
- }
-
- private float CleanlinessSpeedFactor => parent.GetStatValue(StatDefOf.BiosculpterPodSpeedFactor);
-
- private float BiotunedSpeedFactor
- {
- get
- {
- if (biotunedTo == null)
- {
- return 1f;
- }
- return Props.biotunedCycleSpeedFactor;
- }
- }
-
- public bool PowerOn => parent.TryGetComp().PowerOn;
-
- public float HeldPawnDrawPos_Y => parent.DrawPos.y - 0.03658537f;
-
- public float HeldPawnBodyAngle => parent.Rotation.Opposite.AsAngle;
-
- public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp;
-
- public bool StorageTabVisible => true;
-
- public CompBiosculpterPod()
- {
- innerContainer = new ThingOwner(this);
- }
-
- public override void Initialize(CompProperties props)
- {
- base.Initialize(props);
- allowedNutritionSettings = new StorageSettings(this);
- if (parent.def.building.defaultStorageSettings != null)
- {
- allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings);
- }
- }
-
- public override void PostSpawnSetup(bool respawningAfterLoad)
- {
- if (ModLister.CheckIdeology("Biosculpter pod comp"))
- {
- base.PostSpawnSetup(respawningAfterLoad);
- }
- }
-
- public override void PostExposeData()
- {
- base.PostExposeData();
- Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
- Scribe_Values.Look(ref currentCycleKey, "currentCycleKey");
- Scribe_Values.Look(ref currentCycleTicksRemaining, "currentCycleTicksRemaining", 0f);
- Scribe_Values.Look(ref currentCyclePowerCutTicks, "currentCyclePowerCutTicks", 0);
- Scribe_References.Look(ref biotunedTo, "biotunedTo");
- Scribe_Values.Look(ref biotunedCountdownTicks, "biotunedCountdownTicks", 0);
- Scribe_Deep.Look(ref allowedNutritionSettings, "allowedNutritionSettings");
- Scribe_Values.Look(ref liquifiedNutrition, "liquifiedNutrition", 0f);
- Scribe_Values.Look(ref autoLoadNutrition, "autoLoadNutrition", defaultValue: false);
- Scribe_Values.Look(ref devFillPodLatch, "devFillPodLatch", defaultValue: false);
- Scribe_Values.Look(ref autoAgeReversal, "autoAgeReversal", defaultValue: false);
- Scribe_Values.Look(ref tickEntered, "tickEntered", 0);
- Scribe_References.Look(ref queuedEnterJob, "queuedEnterJob");
- Scribe_References.Look(ref queuedPawn, "queuedPawn");
- if (allowedNutritionSettings == null)
- {
- allowedNutritionSettings = new StorageSettings(this);
- if (parent.def.building.defaultStorageSettings != null)
- {
- allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings);
- }
- }
- if (Scribe.mode == LoadSaveMode.PostLoadInit)
- {
- if (currentCycleKey == "healing")
- {
- currentCycleKey = "medic";
- }
- if (biotunedTo != null)
- {
- SetBiotuned(biotunedTo);
- }
- LiquifyNutrition();
- }
- }
-
- public CompBiosculpterPod_Cycle GetCycle(string key)
- {
- if (cycleLookup == null)
- {
- SetupCycleCaches();
- }
- return cycleLookup[key];
- }
-
- public float GetCycleSpeedFactorForPawn(Pawn p)
- {
- return Mathf.Max(0.1f, CycleSpeedFactorNoPawn * p.GetStatValue(StatDefOf.BiosculpterOccupantSpeed));
- }
-
- private void SetupCycleCaches()
- {
- cachedAvailableCycles = new List();
- cachedAvailableCycles.AddRange(parent.AllComps.OfType());
- cycleLookup = new Dictionary();
- foreach (CompBiosculpterPod_Cycle cachedAvailableCycle in cachedAvailableCycles)
- {
- if (cachedAvailableCycle is CompBiosculpterPod_AgeReversalCycle compBiosculpterPod_AgeReversalCycle)
- {
- cachedAgeReversalCycleKey = compBiosculpterPod_AgeReversalCycle.Props.key;
- }
- cycleLookup[cachedAvailableCycle.Props.key] = cachedAvailableCycle;
- }
- }
-
- public void SetBiotuned(Pawn newBiotunedTo)
- {
- if (newBiotunedTo != biotunedTo)
- {
- autoAgeReversal = false;
- }
- if (biotunedTo != null && cachedBiotunedPods.ContainsKey(biotunedTo))
- {
- cachedBiotunedPods[biotunedTo].Remove(this);
- }
- if (newBiotunedTo != null && !cachedBiotunedPods.ContainsKey(newBiotunedTo))
- {
- cachedBiotunedPods[newBiotunedTo] = new List();
- }
- if (newBiotunedTo != null && !cachedBiotunedPods[newBiotunedTo].Contains(this))
- {
- cachedBiotunedPods[newBiotunedTo].Add(this);
- }
- if (newBiotunedTo != null && newBiotunedTo != biotunedTo)
- {
- biotunedCountdownTicks = 4800000;
- }
- biotunedTo = newBiotunedTo;
- }
-
- public override void PostDestroy(DestroyMode mode, Map previousMap)
- {
- SetBiotuned(null);
- if (mode == DestroyMode.Deconstruct || mode == DestroyMode.KillFinalize)
- {
- EjectContents(interrupted: true, playSounds: false, previousMap);
- }
- innerContainer.ClearAndDestroyContents();
- base.PostDestroy(mode, previousMap);
- }
-
- public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish)
- {
- if (mode != DestroyMode.WillReplace)
- {
- EjectContents(interrupted: true, playSounds: false, map);
- currentCycleKey = null;
- }
- progressBarEffecter?.Cleanup();
- progressBarEffecter = null;
- operatingEffecter?.Cleanup();
- operatingEffecter = null;
- readyEffecter?.Cleanup();
- readyEffecter = null;
- }
-
- public override void DrawGUIOverlay()
- {
- base.DrawGUIOverlay();
- if (!Find.ScreenshotModeHandler.Active && (biotunedTo != null || Occupant != null))
- {
- GenMapUI.DrawThingLabel(parent, biotunedTo?.LabelShort ?? Occupant.LabelShort, GenMapUI.DefaultThingLabelColor);
- }
- }
-
- public override string CompInspectStringExtra()
- {
- StringBuilder stringBuilder = new StringBuilder();
- BiosculpterPodState state = State;
- if (parent.Spawned)
- {
- CompBiosculpterPod_Cycle currentCycle = CurrentCycle;
- if (currentCycle != null)
- {
- stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterPodCycleLabel".Translate()).Append(": ")
- .Append(currentCycle.Props.LabelCap);
- if (biotunedTo == null)
- {
- stringBuilder.Append(" " + "BiosculpterPodCycleWillBiotune".Translate());
- }
- }
- else if (state == BiosculpterPodState.SelectingCycle)
- {
- if (PowerOn)
- {
- if (queuedEnterJob != null && !queuedEnterJob.biosculpterCycleKey.NullOrEmpty())
- {
- stringBuilder.Append("BiosculpterPodCycleStandby".Translate(GetCycle(queuedEnterJob.biosculpterCycleKey).Props.label.Named("CYCLE"), queuedPawn.Named("PAWN")));
- }
- else
- {
- stringBuilder.Append("BiosculpterPodCycleSelection".Translate().CapitalizeFirst());
- }
- }
- else
- {
- stringBuilder.Append("BiosculpterPodCycleSelectionNoPower".Translate().CapitalizeFirst());
- }
- }
- if (state == BiosculpterPodState.LoadingNutrition)
- {
- stringBuilder.Append("BiosculpterPodCycleLabelLoading".Translate().CapitalizeFirst());
- stringBuilder.AppendLineIfNotEmpty().Append("Nutrition".Translate()).Append(": ")
- .Append(liquifiedNutrition.ToStringByStyle(ToStringStyle.FloatMaxOne))
- .Append(" / ")
- .Append(5f);
- }
- if (state == BiosculpterPodState.Occupied)
- {
- float num = currentCycleTicksRemaining / CycleSpeedFactor;
- stringBuilder.AppendLineIfNotEmpty().Append("Contains".Translate()).Append(": ")
- .Append(Occupant.NameShortColored.Resolve());
- if (!PowerOn)
- {
- stringBuilder.AppendLine().Append("BiosculpterCycleNoPowerInterrupt".Translate((60000 - currentCyclePowerCutTicks).ToStringTicksToPeriod().Named("TIME")).Colorize(ColorLibrary.RedReadable));
- }
- stringBuilder.AppendLine().Append("BiosculpterCycleTimeRemaining".Translate()).Append(": ")
- .Append(((int)num).ToStringTicksToPeriod().Colorize(ColoredText.DateTimeColor));
- Ideo ideo = Occupant.Ideo;
- if (ideo != null && ideo.HasPrecept(PreceptDefOf.Biosculpting_Accelerated))
- {
- stringBuilder.Append(" (" + "BiosculpterCycleAccelerated".Translate() + ")");
- }
- if (biotunedTo != null)
- {
- stringBuilder.AppendLine().Append("BiosculpterBiotunedSpeedFactor".Translate()).Append(": ")
- .Append(BiotunedSpeedFactor.ToStringPercent());
- }
- stringBuilder.AppendLine().Append("BiosculpterCleanlinessSpeedFactor".Translate()).Append(": ")
- .Append(CleanlinessSpeedFactor.ToStringPercent());
- }
- }
- if (biotunedTo != null && state != BiosculpterPodState.Occupied)
- {
- stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterBiotunedTo".Translate()).Append(": ")
- .Append(biotunedTo.LabelShort)
- .Append(" (")
- .Append(biotunedCountdownTicks.ToStringTicksToPeriod())
- .Append(")");
- }
- if (stringBuilder.Length <= 0)
- {
- return null;
- }
- return stringBuilder.ToString();
- }
-
- public override IEnumerable CompGetGizmosExtra()
- {
- BiosculpterPodState state = State;
- string cycleIndependentCannotUseReason = CannotUseNowReason();
- foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles)
- {
- string text = cycleIndependentCannotUseReason ?? CannotUseNowCycleReason(cycle);
- Command_Action command_Action = new Command_Action();
- command_Action.defaultLabel = "BiosculpterPodCycleCommand".Translate(cycle.Props.label) + ((biotunedTo != null) ? (" (" + biotunedTo.LabelShort + ")") : "");
- command_Action.defaultDesc = CycleDescription(cycle);
- command_Action.icon = cycle.Props.Icon;
- command_Action.action = delegate
- {
- SelectPawnsForCycleOptions(cycle, out var options2);
- if (biotunedTo != null && options2.Count > 0)
- {
- options2[0].action();
- if (!(cycle is CompBiosculpterPod_HealingCycle))
- {
- Messages.Message("BiosculpterEnteringMessage".Translate(biotunedTo.Named("PAWN"), cycle.Props.label.Named("CYCLE")).CapitalizeFirst(), parent, MessageTypeDefOf.SilentInput, historical: false);
- }
- }
- else
- {
- Find.WindowStack.Add(new FloatMenu(options2));
- }
- };
- command_Action.activateSound = SoundDefOf.Tick_Tiny;
- command_Action.Disabled = text != null;
- List options;
- if (text != null)
- {
- command_Action.Disable(text);
- }
- else if (!SelectPawnsForCycleOptions(cycle, out options, shortCircuit: true))
- {
- command_Action.Disable((biotunedTo != null) ? "BiosculpterNoEligiblePawnsBiotuned".Translate(biotunedTo.Named("PAWN")) : "BiosculpterNoEligiblePawns".Translate());
- }
- yield return command_Action;
- }
- if (state == BiosculpterPodState.Occupied)
- {
- Command_Action command_Action2 = new Command_Action();
- command_Action2.defaultLabel = "BiosculpterInteruptCycle".Translate();
- command_Action2.defaultDesc = "BiosculpterInteruptCycleDesc".Translate();
- command_Action2.icon = InterruptCycleIcon;
- command_Action2.action = delegate
- {
- EjectContents(interrupted: true, playSounds: true);
- };
- command_Action2.activateSound = SoundDefOf.Designate_Cancel;
- yield return command_Action2;
- }
- Command_Toggle command_Toggle = new Command_Toggle();
- command_Toggle.defaultLabel = "BiosculpterAutoLoadNutritionLabel".Translate();
- command_Toggle.defaultDesc = "BiosculpterAutoLoadNutritionDescription".Translate();
- command_Toggle.icon = (autoLoadNutrition ? TexCommand.ForbidOff : TexCommand.ForbidOn);
- command_Toggle.isActive = () => autoLoadNutrition;
- command_Toggle.toggleAction = delegate
- {
- autoLoadNutrition = !autoLoadNutrition;
- };
- yield return command_Toggle;
- if ((biotunedTo?.Ideo?.HasPrecept(PreceptDefOf.AgeReversal_Demanded)).GetValueOrDefault())
- {
- Command_Toggle command_Toggle2 = new Command_Toggle();
- command_Toggle2.defaultLabel = "BiosculpterAutoAgeReversalLabel".Translate(biotunedTo.Named("PAWN"));
- TaggedString taggedString = ((biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks > 0) ? "BiosculpterAutoAgeReversalDescriptionFuture".Translate(biotunedTo.Named("PAWN"), ((int)biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks).ToStringTicksToPeriodVague().Named("TIME")) : "BiosculpterAutoAgeReversalDescriptionNow".Translate(biotunedTo.Named("PAWN")));
- command_Toggle2.defaultDesc = "BiosculpterAutoAgeReversalDescription".Translate(biotunedTo.Named("PAWN"), taggedString.Named("NEXTTREATMENT"));
- command_Toggle2.icon = AutoAgeReversalIcon;
- command_Toggle2.isActive = () => AutoAgeReversal;
- command_Toggle2.toggleAction = delegate
- {
- autoAgeReversal = !autoAgeReversal;
- };
- if (!CanAgeReverse(biotunedTo))
- {
- command_Toggle2.Disable("UnderMinBiosculpterAgeReversalAge".Translate(biotunedTo.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst());
- autoAgeReversal = false;
- }
- yield return command_Toggle2;
- }
- foreach (Gizmo item in StorageSettingsClipboard.CopyPasteGizmosFor(allowedNutritionSettings))
- {
- yield return item;
- }
- Gizmo gizmo = Building.SelectContainedItemGizmo(parent, Occupant);
- if (gizmo != null)
- {
- yield return gizmo;
- }
- if (DebugSettings.ShowDevGizmos)
- {
- yield return new Command_Action
- {
- defaultLabel = "DEV: complete cycle",
- action = delegate
- {
- currentCycleTicksRemaining = 10f;
- },
- Disabled = (State != BiosculpterPodState.Occupied)
- };
- yield return new Command_Action
- {
- defaultLabel = "DEV: advance cycle +1 day",
- action = delegate
- {
- currentCycleTicksRemaining -= 60000f;
- },
- Disabled = (State != BiosculpterPodState.Occupied)
- };
- yield return new Command_Action
- {
- defaultLabel = "DEV: complete biotune timer",
- action = delegate
- {
- biotunedCountdownTicks = 10;
- },
- Disabled = (biotunedCountdownTicks <= 0)
- };
- yield return new Command_Action
- {
- defaultLabel = "DEV: fill nutrition and cycle ingredients",
- action = delegate
- {
- liquifiedNutrition = 5f;
- devFillPodLatch = true;
- },
- Disabled = (State == BiosculpterPodState.Occupied || (devFillPodLatch && liquifiedNutrition == 5f))
- };
- }
- }
-
- private string IngredientsDescription(CompBiosculpterPod_Cycle cycle)
- {
- tmpIngredientsStrings.Clear();
- if (!cycle.Props.extraRequiredIngredients.NullOrEmpty() && !devFillPodLatch)
- {
- for (int i = 0; i < cycle.Props.extraRequiredIngredients.Count; i++)
- {
- tmpIngredientsStrings.Add(cycle.Props.extraRequiredIngredients[i].Summary);
- }
- }
- return tmpIngredientsStrings.ToCommaList(useAnd: true);
- }
-
- private string CycleDescription(CompBiosculpterPod_Cycle cycle)
- {
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.Append(cycle.Description(biotunedTo));
- float num = cycle.Props.durationDays / CycleSpeedFactor;
- float num2 = num / PreceptDefOf.Biosculpting_Accelerated.biosculpterPodCycleSpeedFactor;
- stringBuilder.AppendLine("\n\n" + "BiosculpterPodCycleDuration".Translate() + ": " + ((int)(num * 60000f)).ToStringTicksToDays());
- if (!Find.IdeoManager.classicMode)
- {
- stringBuilder.Append("BiosculpterPodCycleDurationTranshumanists".Translate() + ": " + ((int)(num2 * 60000f)).ToStringTicksToDays());
- }
- return stringBuilder.ToString();
- }
-
- public bool PawnCanUseNow(Pawn pawn, CompBiosculpterPod_Cycle cycle)
- {
- return (CannotUseNowReason() ?? CannotUseNowPawnReason(pawn) ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(pawn, cycle)) == null;
- }
-
- public override IEnumerable CompFloatMenuOptions(Pawn selPawn)
- {
- if (selPawn.IsQuestLodger())
- {
- yield return new FloatMenuOption("CannotEnter".Translate() + ": " + "CryptosleepCasketGuestsNotAllowed".Translate().CapitalizeFirst(), null);
- yield break;
- }
- string cycleIndependentfailureReason = CannotUseNowReason() ?? CannotUseNowPawnReason(selPawn);
- foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles)
- {
- string text = cycleIndependentfailureReason ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(selPawn, cycle);
- if (text != null)
- {
- yield return new FloatMenuOption(CannotStartText(cycle, text), null);
- continue;
- }
- string label = "EnterBiosculpterPod".Translate(cycle.Props.label, ((int)(cycle.Props.durationDays / GetCycleSpeedFactorForPawn(selPawn) * 60000f)).ToStringTicksToDays());
- yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, delegate
- {
- PrepareCycleJob(selPawn, selPawn, cycle, EnterBiosculpterJob());
- }), selPawn, parent);
- }
- }
-
- public static bool CanAgeReverse(Pawn biosculptee)
- {
- return biosculptee.ageTracker.Adult;
- }
-
- public static List BiotunedPods(Pawn pawn)
- {
- return cachedBiotunedPods.TryGetValue(pawn);
- }
-
- public static bool HasBiotunedAutoAgeReversePod(Pawn pawn)
- {
- List list = cachedBiotunedPods.TryGetValue(pawn);
- if (list == null)
- {
- return false;
- }
- foreach (CompBiosculpterPod item in list)
- {
- if (item.AutoAgeReversal)
- {
- return true;
- }
- }
- return false;
- }
-
- public static string CannotStartText(CompBiosculpterPod_Cycle cycle, string translatedReason)
- {
- return "BiosculpterCannotStartCycle".Translate(cycle.Props.label) + ": " + translatedReason.CapitalizeFirst();
- }
-
- public string CannotUseNowCycleReason(CompBiosculpterPod_Cycle cycle)
- {
- List list = cycle.MissingResearchLabels();
- if (list.Any())
- {
- return "MissingRequiredResearch".Translate() + " " + list.ToCommaList();
- }
- return null;
- }
-
- public string CannotUseNowPawnCycleReason(Pawn p, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true)
- {
- return CannotUseNowPawnCycleReason(p, p, cycle, checkIngredients);
- }
-
- private bool CanReachOrHasIngredients(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool useCache = false)
- {
- if (!PawnCarryingExtraCycleIngredients(biosculptee, cycle) && (biosculptee == hauler || !PawnCarryingExtraCycleIngredients(hauler, cycle)))
- {
- return CanReachRequiredIngredients(hauler, cycle, useCache);
- }
- return true;
- }
-
- public string CannotUseNowPawnCycleReason(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true)
- {
- if (AgeReversalCycleKey != null && cycle.Props.key == AgeReversalCycleKey && !CanAgeReverse(biosculptee))
- {
- return "UnderMinBiosculpterAgeReversalAge".Translate(biosculptee.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst();
- }
- if (checkIngredients && !CanReachOrHasIngredients(hauler, biosculptee, cycle, useCache: true))
- {
- return "BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst();
- }
- return null;
- }
-
- public string CannotUseNowPawnReason(Pawn p)
- {
- if (biotunedTo != null && biotunedTo != p)
- {
- return "BiosculpterBiotunedToAnother".Translate().CapitalizeFirst();
- }
- if (!p.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly))
- {
- return "NoPath".Translate().CapitalizeFirst();
- }
- return null;
- }
-
- public string CannotUseNowReason()
- {
- if (!PowerOn)
- {
- return "NoPower".Translate().CapitalizeFirst();
- }
- if (State == BiosculpterPodState.LoadingNutrition)
- {
- return "BiosculpterNutritionNotLoaded".Translate().CapitalizeFirst();
- }
- if (State == BiosculpterPodState.Occupied)
- {
- return "BiosculpterOccupied".Translate().CapitalizeFirst();
- }
- return null;
- }
-
- private List RequiredIngredients(CompBiosculpterPod_Cycle cycle)
- {
- List extraRequiredIngredients = cycle.Props.extraRequiredIngredients;
- if (extraRequiredIngredients == null || devFillPodLatch)
- {
- return null;
- }
- if (!cachedExtraIngredients.ContainsKey(cycle))
- {
- cachedExtraIngredients[cycle] = extraRequiredIngredients.Select((ThingDefCountClass tc) => tc.ToIngredientCount()).ToList();
- }
- return cachedExtraIngredients[cycle];
- }
-
- private bool CanReachRequiredIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool useCache = false)
- {
- chosenExtraItems.Clear();
- if (cycle.Props.extraRequiredIngredients == null || devFillPodLatch)
- {
- return true;
- }
- float realtimeSinceStartup = Time.realtimeSinceStartup;
- if (useCache && cacheReachIngredientsPawn == pawn && cacheReachIngredientsCycle == cycle && realtimeSinceStartup < cacheReachIngredientsTime + 2f)
- {
- return cacheReachIngredientsResult;
- }
- cacheReachIngredientsPawn = pawn;
- cacheReachIngredientsCycle = cycle;
- cacheReachIngredientsTime = realtimeSinceStartup;
- cacheReachIngredientsResult = WorkGiver_DoBill.TryFindBestFixedIngredients(RequiredIngredients(cycle), pawn, parent, chosenExtraItems);
- return cacheReachIngredientsResult;
- }
-
- private bool SelectPawnCycleOption(Pawn pawn, CompBiosculpterPod_Cycle cycle, out FloatMenuOption option)
- {
- string text = CannotUseNowPawnReason(pawn) ?? CannotUseNowPawnCycleReason(pawn, cycle, checkIngredients: false);
- string label = pawn.Label + ((text == null) ? "" : (": " + text));
- Action action = null;
- if (text == null)
- {
- action = delegate
- {
- PrepareCycleJob(pawn, pawn, cycle, EnterBiosculpterJob());
- };
- }
- option = new FloatMenuOption(label, action);
- return text == null;
- }
-
- private bool SelectPawnsForCycleOptions(CompBiosculpterPod_Cycle cycle, out List options, bool shortCircuit = false)
- {
- cycleEligiblePawnOptions.Clear();
- options = cycleEligiblePawnOptions;
- if (!cachedAnyPawnEligible.ContainsKey(cycle))
- {
- cachedAnyPawnEligible[cycle] = new CacheAnyPawnEligibleCycle
- {
- gameTime = float.MinValue
- };
- }
- int ticksGame = Find.TickManager.TicksGame;
- if (shortCircuit && (float)ticksGame < cachedAnyPawnEligible[cycle].gameTime + 2f)
- {
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- cachedAnyPawnEligible[cycle].gameTime = ticksGame;
- if (biotunedTo != null)
- {
- if (biotunedTo.Dead || !biotunedTo.Spawned || biotunedTo.Map != parent.Map)
- {
- cachedAnyPawnEligible[cycle].anyEligible = false;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- if (SelectPawnCycleOption(biotunedTo, cycle, out var option) && shortCircuit)
- {
- cachedAnyPawnEligible[cycle].anyEligible = true;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- cycleEligiblePawnOptions.Add(option);
- }
- else
- {
- foreach (Pawn item in parent.Map.mapPawns.FreeColonistsSpawned)
- {
- if (SelectPawnCycleOption(item, cycle, out var option2) && shortCircuit)
- {
- cachedAnyPawnEligible[cycle].anyEligible = true;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- cycleEligiblePawnOptions.Add(option2);
- }
- }
- cachedAnyPawnEligible[cycle].anyEligible = cycleEligiblePawnOptions.Count > 0;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
-
- public Job EnterBiosculpterJob()
- {
- return JobMaker.MakeJob(JobDefOf.EnterBiosculpterPod, parent);
- }
-
- public Job MakeCarryToBiosculpterJob(Pawn willBeCarried)
- {
- return JobMaker.MakeJob(JobDefOf.CarryToBiosculpterPod, willBeCarried, LocalTargetInfo.Invalid, parent);
- }
-
- public void ConfigureJobForCycle(Job job, CompBiosculpterPod_Cycle cycle, List extraIngredients)
- {
- if (!extraIngredients.NullOrEmpty())
- {
- job.targetQueueB = new List(extraIngredients.Count);
- job.countQueue = new List(extraIngredients.Count);
- foreach (ThingCount extraIngredient in extraIngredients)
- {
- job.targetQueueB.Add(extraIngredient.Thing);
- job.countQueue.Add(extraIngredient.Count);
- }
- }
- job.haulMode = HaulMode.ToCellNonStorage;
- job.biosculpterCycleKey = cycle.Props.key;
- }
-
- public void PrepareCycleJob(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, Job job)
- {
- OrderToPod(cycle, biosculptee, delegate
- {
- chosenExtraItems.Clear();
- if (!CanReachOrHasIngredients(hauler, biosculptee, cycle))
- {
- Messages.Message("BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst(), parent, MessageTypeDefOf.NegativeEvent, historical: false);
- }
- else
- {
- ConfigureJobForCycle(job, cycle, chosenExtraItems);
- if (cycle.Props.extraRequiredIngredients != null && !devFillPodLatch)
- {
- if (job.def == JobDefOf.CarryToBiosculpterPod)
- {
- Messages.Message("BiosculpterCarryStartedMessage".Translate(hauler.Named("PAWN"), IngredientsDescription(cycle).Named("INGREDIENTS"), biosculptee.Named("DOWNED"), cycle.Props.label.Named("CYCLE")), parent, MessageTypeDefOf.SilentInput, historical: false);
- }
- else
- {
- Messages.Message("BiosculpterLoadingStartedMessage".Translate(hauler.Named("PAWN"), IngredientsDescription(cycle).Named("INGREDIENTS"), cycle.Props.label.Named("CYCLE")), parent, MessageTypeDefOf.SilentInput, historical: false);
- }
- }
- if (hauler.jobs.TryTakeOrderedJob(job, JobTag.Misc))
- {
- SetQueuedInformation(job, biosculptee);
- }
- }
- });
- }
-
- public void ClearQueuedInformation()
- {
- SetQueuedInformation(null, null);
- }
-
- public void SetQueuedInformation(Job job, Pawn biosculptee)
- {
- queuedEnterJob = job;
- queuedPawn = biosculptee;
- }
-
- public bool CanAcceptNutrition(Thing thing)
- {
- return allowedNutritionSettings.AllowedToAccept(thing);
- }
-
- public bool CanAcceptOnceCycleChosen(Pawn pawn)
- {
- if (State != BiosculpterPodState.SelectingCycle || !PowerOn)
- {
- return false;
- }
- if (biotunedTo != null && biotunedTo != pawn)
- {
- return false;
- }
- return true;
- }
-
- public bool PawnCarryingExtraCycleIngredients(Pawn pawn, string cycleKey, bool remove = false)
- {
- return PawnCarryingExtraCycleIngredients(pawn, GetCycle(cycleKey), remove);
- }
-
- public bool PawnCarryingExtraCycleIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool remove = false)
- {
- if (cycle.Props.extraRequiredIngredients.NullOrEmpty() || devFillPodLatch)
- {
- return true;
- }
- foreach (ThingDefCountClass extraRequiredIngredient in cycle.Props.extraRequiredIngredients)
- {
- if (pawn.inventory.Count(extraRequiredIngredient.thingDef) < extraRequiredIngredient.count)
- {
- return false;
- }
- }
- if (remove)
- {
- foreach (ThingDefCountClass extraRequiredIngredient2 in cycle.Props.extraRequiredIngredients)
- {
- pawn.inventory.RemoveCount(extraRequiredIngredient2.thingDef, extraRequiredIngredient2.count);
- }
- }
- return true;
- }
-
- public bool TryAcceptPawn(Pawn pawn, string cycleKey)
- {
- return TryAcceptPawn(pawn, GetCycle(cycleKey));
- }
-
- public bool TryAcceptPawn(Pawn pawn, CompBiosculpterPod_Cycle cycle)
- {
- if (!CanAcceptOnceCycleChosen(pawn))
- {
- return false;
- }
- if (!PawnCarryingExtraCycleIngredients(pawn, cycle, remove: true))
- {
- return false;
- }
- currentCycleKey = cycle.Props.key;
- innerContainer.ClearAndDestroyContents();
- pawnEnteringBiosculpter = pawn;
- bool num = pawn.DeSpawnOrDeselect();
- if (pawn.holdingOwner != null)
- {
- pawn.holdingOwner.TryTransferToContainer(pawn, innerContainer);
- }
- else
- {
- innerContainer.TryAdd(pawn);
- }
- if (num)
- {
- Find.Selector.Select(pawn, playSound: false, forceDesignatorDeselect: false);
- }
- pawnEnteringBiosculpter = null;
- currentCycleTicksRemaining = cycle.Props.durationDays * 60000f;
- liquifiedNutrition = 0f;
- devFillPodLatch = false;
- ClearQueuedInformation();
- tickEntered = Find.TickManager.TicksGame;
- return true;
- }
-
- public void EjectContents(bool interrupted, bool playSounds, Map destMap = null)
- {
- if (destMap == null)
- {
- destMap = parent.Map;
- }
- Pawn occupant = Occupant;
- currentCycleKey = null;
- currentCycleTicksRemaining = 0f;
- currentCyclePowerCutTicks = 0;
- liquifiedNutrition = 0f;
- devFillPodLatch = false;
- innerContainer.TryDropAll(parent.InteractionCell, destMap, ThingPlaceMode.Near);
- if (occupant != null)
- {
- FilthMaker.TryMakeFilth(parent.InteractionCell, destMap, ThingDefOf.Filth_PodSlime, new IntRange(3, 6).RandomInRange);
- if (interrupted)
- {
- occupant.needs?.mood.thoughts.memories.TryGainMemory(ThoughtDefOf.SoakingWet);
- occupant.health?.AddHediff(HediffDefOf.BiosculptingSickness);
- }
- }
- if (playSounds)
- {
- Props.exitSound?.PlayOneShot(SoundInfo.InMap(new TargetInfo(parent.Position, parent.Map)));
- }
- }
-
- private void CycleCompleted()
- {
- Pawn occupant = Occupant;
- CompBiosculpterPod_Cycle currentCycle = CurrentCycle;
- SetBiotuned(occupant);
- currentCycle.CycleCompleted(occupant);
- EjectContents(interrupted: false, playSounds: true);
- if (occupant != null)
- {
- Need_Food need_Food = occupant.needs?.food;
- if (need_Food != null)
- {
- need_Food.CurLevelPercentage = 1f;
- }
- Need_Rest need_Rest = occupant.needs?.rest;
- if (need_Rest != null)
- {
- need_Rest.CurLevelPercentage = 1f;
- }
- if (currentCycle.Props.gainThoughtOnCompletion != null)
- {
- occupant.needs?.mood?.thoughts.memories.TryGainMemory(ThoughtDefOf.AgeReversalReceived);
- }
- Find.HistoryEventsManager.RecordEvent(new HistoryEvent(HistoryEventDefOf.UsedBiosculpterPod, occupant.Named(HistoryEventArgsNames.Doer)));
- }
- if (tickEntered > 0)
- {
- occupant.drugs.Notify_LeftSuspension(Find.TickManager.TicksGame - tickEntered);
- }
- }
-
- private void LiquifyNutrition()
- {
- tmpItems.AddRange(innerContainer);
- foreach (Thing tmpItem in tmpItems)
- {
- float num = tmpItem.GetStatValue(StatDefOf.Nutrition) * (float)tmpItem.stackCount;
- if (!(num <= 0f) && !(tmpItem is Pawn))
- {
- liquifiedNutrition = Mathf.Min(5f, liquifiedNutrition + num);
- tmpItem.Destroy();
- }
- }
- tmpItems.Clear();
- }
-
- public override void CompTick()
- {
- if (!ModLister.CheckIdeology("Biosculpting"))
- {
- return;
- }
- base.CompTick();
- if (State != BiosculpterPodState.SelectingCycle || !PowerOn)
- {
- readyEffecter?.Cleanup();
- readyEffecter = null;
- }
- else if (Props.readyEffecter != null)
- {
- if (readyEffecter == null)
- {
- readyEffecter = Props.readyEffecter.Spawn();
- ColorizeEffecter(readyEffecter, Props.selectCycleColor);
- readyEffecter.Trigger(parent, new TargetInfo(parent.InteractionCell, parent.Map));
- }
- readyEffecter.EffectTick(parent, new TargetInfo(parent.InteractionCell, parent.Map));
- }
- if (State != BiosculpterPodState.Occupied)
- {
- progressBarEffecter?.Cleanup();
- progressBarEffecter = null;
- operatingEffecter?.Cleanup();
- operatingEffecter = null;
- }
- else
- {
- Pawn occupant = Occupant;
- biotunedCountdownTicks = 4800000;
- if (PowerOn)
- {
- int num = 1;
- currentCycleTicksRemaining -= (float)num * CycleSpeedFactor;
- if (currentCycleTicksRemaining <= 0f)
- {
- CycleCompleted();
- }
- }
- else
- {
- currentCyclePowerCutTicks++;
- if (currentCyclePowerCutTicks >= 60000)
- {
- EjectContents(interrupted: true, playSounds: true);
- Messages.Message("BiosculpterNoPowerEjectedMessage".Translate(occupant.Named("PAWN")), occupant, MessageTypeDefOf.NegativeEvent, historical: false);
- }
- }
- if (currentCycleTicksRemaining > 0f)
- {
- if (progressBarEffecter == null)
- {
- progressBarEffecter = EffecterDefOf.ProgressBar.Spawn();
- }
- progressBarEffecter.EffectTick(parent, TargetInfo.Invalid);
- MoteProgressBar moteProgressBar = (progressBarEffecter.children[0] as SubEffecter_ProgressBar)?.mote;
- if (moteProgressBar != null)
- {
- float num2 = CurrentCycle.Props.durationDays * 60000f;
- moteProgressBar.progress = 1f - Mathf.Clamp01(currentCycleTicksRemaining / num2);
- int num3 = (parent.RotatedSize.z - 1) / 2;
- moteProgressBar.offsetZ = 0f - ((float)num3 + 0.5f);
- }
- if (Props.operatingEffecter != null)
- {
- if (!PowerOn)
- {
- operatingEffecter?.Cleanup();
- operatingEffecter = null;
- }
- else
- {
- if (operatingEffecter == null)
- {
- operatingEffecter = Props.operatingEffecter.Spawn();
- ColorizeEffecter(operatingEffecter, CurrentCycle.Props.operatingColor);
- operatingEffecter.Trigger(parent, new TargetInfo(parent.InteractionCell, parent.Map));
- }
- operatingEffecter.EffectTick(parent, new TargetInfo(parent.InteractionCell, parent.Map));
- }
- }
- }
- }
- if (PowerOn && biotunedCountdownTicks > 0)
- {
- biotunedCountdownTicks--;
- }
- if (biotunedCountdownTicks <= 0)
- {
- SetBiotuned(null);
- }
- SetPower();
- if (biotunedTo?.Ideo != null && !biotunedTo.Ideo.HasPrecept(PreceptDefOf.AgeReversal_Demanded))
- {
- autoAgeReversal = false;
- }
- }
-
- private void SetPower()
- {
- if (powerTraderComp == null)
- {
- powerTraderComp = parent.TryGetComp();
- }
- if (powerComp == null)
- {
- powerComp = parent.TryGetComp();
- }
- if (State == BiosculpterPodState.Occupied)
- {
- powerTraderComp.PowerOutput = 0f - powerComp.Props.PowerConsumption;
- }
- else
- {
- powerTraderComp.PowerOutput = 0f - powerComp.Props.idlePowerDraw;
- }
- }
-
- private void ColorizeEffecter(Effecter effecter, Color color)
- {
- foreach (SubEffecter child in effecter.children)
- {
- if (child is SubEffecter_Sprayer subEffecter_Sprayer)
- {
- subEffecter_Sprayer.colorOverride = color * child.def.color;
- }
- }
- }
-
- public override void PostDraw()
- {
- base.PostDraw();
- Rot4 rotation = parent.Rotation;
- Vector3 s = new Vector3(parent.def.graphicData.drawSize.x * 0.8f, 1f, parent.def.graphicData.drawSize.y * 0.8f);
- Vector3 drawPos = parent.DrawPos;
- drawPos.y -= 0.07317074f;
- Graphics.DrawMesh(MeshPool.plane10, Matrix4x4.TRS(drawPos, rotation.AsQuat, s), BackgroundMat, 0);
- if (State == BiosculpterPodState.Occupied)
- {
- Pawn occupant = Occupant;
- Vector3 drawLoc = parent.DrawPos + FloatingOffset(currentCycleTicksRemaining + (float)currentCyclePowerCutTicks);
- Rot4 rotation2 = parent.Rotation;
- if (rotation2 == Rot4.East || rotation2 == Rot4.West)
- {
- drawLoc.z += 0.2f;
- }
- occupant.Drawer.renderer.RenderPawnAt(drawLoc, null, neverAimWeapon: true);
- }
- }
-
- public static Vector3 FloatingOffset(float tickOffset)
- {
- float num = tickOffset % 500f / 500f;
- float num2 = Mathf.Sin(MathF.PI * num);
- float z = num2 * num2 * 0.04f;
- return new Vector3(0f, 0f, z);
- }
-
- public void GetChildHolders(List outChildren)
- {
- ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings());
- }
-
- public ThingOwner GetDirectlyHeldThings()
- {
- return innerContainer;
- }
-
- public StorageSettings GetStoreSettings()
- {
- return allowedNutritionSettings;
- }
-
- public StorageSettings GetParentStoreSettings()
- {
- return parent.def.building.fixedStorageSettings;
- }
-
- public void Notify_SettingsChanged()
- {
- }
-
- private static void OrderToPod(CompBiosculpterPod_Cycle cycle, Pawn pawn, Action giveJobAct)
- {
- if (cycle is CompBiosculpterPod_HealingCycle compBiosculpterPod_HealingCycle)
- {
- string healingDescriptionForPawn = compBiosculpterPod_HealingCycle.GetHealingDescriptionForPawn(pawn);
- string text = (healingDescriptionForPawn.NullOrEmpty() ? "BiosculpterNoCoditionsToHeal".Translate(pawn.Named("PAWN"), compBiosculpterPod_HealingCycle.Props.label.Named("CYCLE")).Resolve() : ("OnCompletionOfCycle".Translate(compBiosculpterPod_HealingCycle.Props.label.Named("CYCLE")).Resolve() + ":\n\n" + healingDescriptionForPawn));
- Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation(text, giveJobAct, healingDescriptionForPawn.NullOrEmpty()));
- }
- else
- {
- giveJobAct();
- }
- }
-
- public static Thing FindPodFor(Pawn pawn, Pawn traveller, bool biotuned)
- {
- if (cachedPodDefs.NullOrEmpty())
- {
- cachedPodDefs = DefDatabase.AllDefs.Where((ThingDef def) => def.GetCompProperties() != null).ToList();
- }
- foreach (ThingDef cachedPodDef in cachedPodDefs)
- {
- Thing thing = GenClosest.ClosestThingReachable(traveller.Position, pawn.Map, ThingRequest.ForDef(cachedPodDef), PathEndMode.InteractionCell, TraverseParms.For(pawn), 9999f, Validator);
- if (thing != null)
- {
- return thing;
- }
- }
- return null;
- bool Validator(Thing t)
- {
- CompBiosculpterPod compBiosculpterPod = t.TryGetComp();
- if (biotuned && compBiosculpterPod.biotunedTo != traveller)
- {
- return false;
- }
- return compBiosculpterPod.CanAcceptOnceCycleChosen(traveller);
- }
- }
-
- public static bool WasLoadingCanceled(Thing thing)
- {
- CompBiosculpterPod compBiosculpterPod = thing.TryGetComp();
- if (compBiosculpterPod != null && compBiosculpterPod.State != 0)
- {
- return true;
- }
- return false;
- }
-
- public void ClearCycle()
- {
- currentCycleKey = null;
- }
-
- public void Notify_HauledTo(Pawn hauler, Thing thing, int count)
- {
- LiquifyNutrition();
- SoundDefOf.Standard_Drop.PlayOneShot(parent);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod_Cycle.txt`
-**相似度:** 0.7210
-
-```csharp
-public abstract class CompBiosculpterPod_Cycle : ThingComp
-{
- private List tmpMissingResearchLabels = new List();
-
- public CompProperties_BiosculpterPod_BaseCycle Props => (CompProperties_BiosculpterPod_BaseCycle)props;
-
- public abstract void CycleCompleted(Pawn occupant);
-
- public virtual string Description(Pawn tunedFor)
- {
- return Props.description;
- }
-
- public List MissingResearchLabels()
- {
- tmpMissingResearchLabels.Clear();
- if (Props.requiredResearch.NullOrEmpty())
- {
- return tmpMissingResearchLabels;
- }
- foreach (ResearchProjectDef item in Props.requiredResearch)
- {
- if (!item.IsFinished)
- {
- tmpMissingResearchLabels.Add(item.LabelCap);
- }
- }
- return tmpMissingResearchLabels;
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_HaulToBiosculpterPod.txt`
-**相似度:** 0.7198
-
-```csharp
-public class WorkGiver_HaulToBiosculpterPod : WorkGiver_Scanner
-{
- public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf.BiosculpterPod);
-
- public override PathEndMode PathEndMode => PathEndMode.Touch;
-
- public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
- {
- if (!ModLister.CheckIdeology("Biosculpting"))
- {
- return false;
- }
- if (!pawn.CanReserve(t, 1, -1, null, forced))
- {
- return false;
- }
- if (pawn.Map.designationManager.DesignationOn(t, DesignationDefOf.Deconstruct) != null)
- {
- return false;
- }
- CompBiosculpterPod compBiosculpterPod = t.TryGetComp();
- if (compBiosculpterPod == null || !compBiosculpterPod.PowerOn || compBiosculpterPod.State != 0 || (!forced && !compBiosculpterPod.autoLoadNutrition))
- {
- return false;
- }
- if (t.IsBurning())
- {
- return false;
- }
- if (compBiosculpterPod.RequiredNutritionRemaining > 0f)
- {
- if (FindNutrition(pawn, compBiosculpterPod).Thing == null)
- {
- JobFailReason.Is("NoFood".Translate());
- return false;
- }
- return true;
- }
- return false;
- }
-
- public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
- {
- CompBiosculpterPod compBiosculpterPod = t.TryGetComp();
- if (compBiosculpterPod == null)
- {
- return null;
- }
- if (compBiosculpterPod.RequiredNutritionRemaining > 0f)
- {
- ThingCount thingCount = FindNutrition(pawn, compBiosculpterPod);
- if (thingCount.Thing != null)
- {
- Job job = HaulAIUtility.HaulToContainerJob(pawn, thingCount.Thing, t);
- job.count = Mathf.Min(job.count, thingCount.Count);
- return job;
- }
- }
- return null;
- }
-
- private ThingCount FindNutrition(Pawn pawn, CompBiosculpterPod pod)
- {
- Thing thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForGroup(ThingRequestGroup.FoodSourceNotPlantOrTree), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, Validator);
- if (thing == null)
- {
- return default(ThingCount);
- }
- int b = Mathf.CeilToInt(pod.RequiredNutritionRemaining / thing.GetStatValue(StatDefOf.Nutrition));
- return new ThingCount(thing, Mathf.Min(thing.stackCount, b));
- bool Validator(Thing x)
- {
- if (x.IsForbidden(pawn) || !pawn.CanReserve(x))
- {
- return false;
- }
- if (!pod.CanAcceptNutrition(x))
- {
- return false;
- }
- return true;
- }
- }
-}
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/BiosculpterPod.txt b/MCP/vector_cache/BiosculpterPod.txt
deleted file mode 100644
index db82d121..00000000
--- a/MCP/vector_cache/BiosculpterPod.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-根据向量相似度分析,与 'BiosculpterPod' 最相关的代码定义如下:
-
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_BaseCycle.txt`
-**相似度:** 0.6754
-
-```csharp
-public abstract class CompProperties_BiosculpterPod_BaseCycle : CompProperties
-{
- [NoTranslate]
- public string key;
-
- [MustTranslate]
- public string label;
-
- [MustTranslate]
- public string description;
-
- [NoTranslate]
- public string iconPath;
-
- public float durationDays;
-
- public Color operatingColor = new Color(0.5f, 0.7f, 0.5f);
-
- public ThoughtDef gainThoughtOnCompletion;
-
- public List requiredResearch;
-
- public List extraRequiredIngredients;
-
- private Texture2D icon;
-
- public Texture2D Icon
- {
- get
- {
- if (icon == null)
- {
- icon = ContentFinder.Get(iconPath);
- }
- return icon;
- }
- }
-
- public string LabelCap => label.CapitalizeFirst();
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_PleasureCycle.txt`
-**相似度:** 0.6624
-
-```csharp
-public class CompProperties_BiosculpterPod_PleasureCycle : CompProperties_BiosculpterPod_BaseCycle
-{
- public CompProperties_BiosculpterPod_PleasureCycle()
- {
- compClass = typeof(CompBiosculpterPod_PleasureCycle);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod_AgeReversalCycle.txt`
-**相似度:** 0.6461
-
-```csharp
-public class CompProperties_BiosculpterPod_AgeReversalCycle : CompProperties_BiosculpterPod_BaseCycle
-{
- public CompProperties_BiosculpterPod_AgeReversalCycle()
- {
- compClass = typeof(CompBiosculpterPod_AgeReversalCycle);
- }
-}
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/Building_Bed.txt b/MCP/vector_cache/Building_Bed.txt
deleted file mode 100644
index 10294a2c..00000000
--- a/MCP/vector_cache/Building_Bed.txt
+++ /dev/null
@@ -1,1122 +0,0 @@
-根据向量相似度分析,与 'Building_Bed' 最相关的代码定义如下:
-
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\Building_Bed.txt`
-
-```csharp
-public class Building_Bed : Building
-{
- private BedOwnerType forOwnerType;
-
- private bool medicalInt;
-
- private bool alreadySetDefaultMed;
-
- private static int lastBedOwnerSetChangeFrame = -1;
-
- private static List tmpOrderedInteractionCells = new List(8);
-
- private static readonly Color SheetColorNormal = new Color(0.6313726f, 71f / 85f, 0.7058824f);
-
- private static readonly Color SheetColorRoyal = new Color(57f / 85f, 0.9137255f, 38f / 51f);
-
- public static readonly Color SheetColorForPrisoner = new Color(1f, 61f / 85f, 11f / 85f);
-
- private static readonly Color SheetColorMedical = new Color(33f / 85f, 53f / 85f, 0.8862745f);
-
- private static readonly Color SheetColorMedicalForPrisoner = new Color(0.654902f, 32f / 85f, 13f / 85f);
-
- private static readonly Color SheetColorForSlave = new Color32(252, 244, 3, byte.MaxValue);
-
- private static readonly Color SheetColorMedicalForSlave = new Color32(153, 148, 0, byte.MaxValue);
-
- private static readonly BedInteractionCellSearchPattern defaultBedInteractionCellsOrder = new BedInteractionCellSearchPattern();
-
- public List OwnersForReading => CompAssignableToPawn.AssignedPawnsForReading;
-
- public CompAssignableToPawn CompAssignableToPawn => GetComp();
-
- public bool ForPrisoners
- {
- get
- {
- return forOwnerType == BedOwnerType.Prisoner;
- }
- set
- {
- if (value == ForPrisoners || !def.building.bed_humanlike || ForHumanBabies)
- {
- return;
- }
- if (Current.ProgramState != ProgramState.Playing && Scribe.mode != 0)
- {
- Log.Error("Tried to set ForPrisoners while game mode was " + Current.ProgramState);
- return;
- }
- RemoveAllOwners();
- if (value)
- {
- forOwnerType = BedOwnerType.Prisoner;
- }
- else
- {
- forOwnerType = BedOwnerType.Colonist;
- Log.Error("Bed ForPrisoners=false, but should it be for for colonists or slaves? Set ForOwnerType instead.");
- }
- Notify_ColorChanged();
- NotifyRoomBedTypeChanged();
- }
- }
-
- public bool ForSlaves => ForOwnerType == BedOwnerType.Slave;
-
- public bool ForColonists => ForOwnerType == BedOwnerType.Colonist;
-
- public bool ForHumanBabies
- {
- get
- {
- if (def.building.bed_humanlike)
- {
- return def.building.bed_maxBodySize < LifeStageDefOf.HumanlikeChild.bodySizeFactor;
- }
- return false;
- }
- }
-
- public BedOwnerType ForOwnerType
- {
- get
- {
- return forOwnerType;
- }
- set
- {
- if (value != forOwnerType && def.building.bed_humanlike && !ForHumanBabies && (value != BedOwnerType.Slave || ModLister.CheckIdeology("Slavery")))
- {
- RemoveAllOwners();
- forOwnerType = value;
- Notify_ColorChanged();
- NotifyRoomBedTypeChanged();
- }
- }
- }
-
- public bool Medical
- {
- get
- {
- return medicalInt;
- }
- set
- {
- if (value != medicalInt && (!value || def.building.bed_canBeMedical))
- {
- RemoveAllOwners();
- medicalInt = value;
- Notify_ColorChanged();
- if (base.Spawned)
- {
- base.Map.mapDrawer.MapMeshDirty(base.Position, MapMeshFlagDefOf.Things);
- NotifyRoomBedTypeChanged();
- }
- FacilityChanged();
- }
- }
- }
-
- public bool AnyUnownedSleepingSlot
- {
- get
- {
- if (Medical)
- {
- Log.Warning("Tried to check for unowned sleeping slot on medical bed " + this);
- return false;
- }
- return CompAssignableToPawn.HasFreeSlot;
- }
- }
-
- public int TotalSleepingSlots
- {
- get
- {
- if (Medical)
- {
- Log.Warning("Tried to check for total sleeping slots on medical bed " + this);
- return 0;
- }
- return CompAssignableToPawn.TotalSlots;
- }
- }
-
- public bool AnyUnoccupiedSleepingSlot
- {
- get
- {
- for (int i = 0; i < SleepingSlotsCount; i++)
- {
- if (GetCurOccupant(i) == null)
- {
- return true;
- }
- }
- return false;
- }
- }
-
- public IEnumerable CurOccupants
- {
- get
- {
- for (int i = 0; i < SleepingSlotsCount; i++)
- {
- Pawn curOccupant = GetCurOccupant(i);
- if (curOccupant != null)
- {
- yield return curOccupant;
- }
- }
- }
- }
-
- public bool AnyOccupants
- {
- get
- {
- for (int i = 0; i < SleepingSlotsCount; i++)
- {
- if (GetCurOccupant(i) != null)
- {
- return true;
- }
- }
- return false;
- }
- }
-
- public override Color DrawColor
- {
- get
- {
- if (def.MadeFromStuff)
- {
- return base.DrawColor;
- }
- return DrawColorTwo;
- }
- }
-
- public override Color DrawColorTwo
- {
- get
- {
- if (def.building != null && !def.building.bed_UseSheetColor)
- {
- return base.DrawColorTwo;
- }
- bool medical = Medical;
- switch (forOwnerType)
- {
- case BedOwnerType.Prisoner:
- if (!medical)
- {
- return SheetColorForPrisoner;
- }
- return SheetColorMedicalForPrisoner;
- case BedOwnerType.Slave:
- if (!medical)
- {
- return SheetColorForSlave;
- }
- return SheetColorMedicalForSlave;
- default:
- if (medical)
- {
- return SheetColorMedical;
- }
- if (def == ThingDefOf.RoyalBed)
- {
- return SheetColorRoyal;
- }
- return SheetColorNormal;
- }
- }
- }
-
- public int SleepingSlotsCount => BedUtility.GetSleepingSlotsCount(def.size);
-
- private bool PlayerCanSeeOwners => CompAssignableToPawn.PlayerCanSeeAssignments;
-
- public override IntVec3 InteractionCell => FindPreferredInteractionCell(base.Position) ?? base.InteractionCell;
-
- public override void SpawnSetup(Map map, bool respawningAfterLoad)
- {
- base.SpawnSetup(map, respawningAfterLoad);
- Region validRegionAt_NoRebuild = map.regionGrid.GetValidRegionAt_NoRebuild(base.Position);
- if (validRegionAt_NoRebuild != null && validRegionAt_NoRebuild.Room.IsPrisonCell)
- {
- ForPrisoners = true;
- }
- if (!alreadySetDefaultMed)
- {
- alreadySetDefaultMed = true;
- if (def.building.bed_defaultMedical)
- {
- Medical = true;
- }
- }
- if (!respawningAfterLoad)
- {
- District district = this.GetDistrict();
- if (district != null)
- {
- district.Notify_RoomShapeOrContainedBedsChanged();
- district.Room.Notify_RoomShapeChanged();
- }
- }
- }
-
- public override void DeSpawn(DestroyMode mode = DestroyMode.Vanish)
- {
- if (mode != DestroyMode.WillReplace)
- {
- if (mode != 0)
- {
- RemoveAllOwners(mode == DestroyMode.KillFinalize);
- }
- else if (InstallBlueprintUtility.ExistingBlueprintFor(this) == null)
- {
- foreach (Pawn item in OwnersForReading)
- {
- Messages.Message("MessageBedLostAssignment".Translate(def, item), new LookTargets(this, item), MessageTypeDefOf.CautionInput, historical: false);
- }
- }
- ForOwnerType = BedOwnerType.Colonist;
- Medical = false;
- alreadySetDefaultMed = false;
- }
- District district = this.GetDistrict();
- base.DeSpawn(mode);
- if (district != null)
- {
- district.Notify_RoomShapeOrContainedBedsChanged();
- district.Room.Notify_RoomShapeChanged();
- }
- }
-
- public override void ExposeData()
- {
- base.ExposeData();
- Scribe_Values.Look(ref medicalInt, "medical", defaultValue: false);
- Scribe_Values.Look(ref alreadySetDefaultMed, "alreadySetDefaultMed", defaultValue: false);
- Scribe_Values.Look(ref forOwnerType, "forOwnerType", BedOwnerType.Colonist);
- BackCompatibility.PostExposeData(this);
- }
-
- public override void DrawExtraSelectionOverlays()
- {
- base.DrawExtraSelectionOverlays();
- Room room = this.GetRoom();
- if (room != null && RoomCanBePrisonCell(room))
- {
- room.DrawFieldEdges();
- }
- }
-
- public static bool RoomCanBePrisonCell(Room r)
- {
- if (r.ProperRoom)
- {
- return !r.IsHuge;
- }
- return false;
- }
-
- public override IEnumerable GetGizmos()
- {
- foreach (Gizmo gizmo in base.GetGizmos())
- {
- yield return gizmo;
- }
- if (base.Faction != Faction.OfPlayer)
- {
- yield break;
- }
- if (def.building.bed_humanlike && !ForHumanBabies)
- {
- if (ModsConfig.IdeologyActive)
- {
- yield return new Command_SetBedOwnerType(this);
- }
- else
- {
- Command_Toggle command_Toggle = new Command_Toggle();
- command_Toggle.defaultLabel = "CommandBedSetForPrisonersLabel".Translate();
- command_Toggle.defaultDesc = "CommandBedSetForPrisonersDesc".Translate();
- command_Toggle.icon = ContentFinder.Get("UI/Commands/ForPrisoners");
- command_Toggle.isActive = () => ForPrisoners;
- command_Toggle.toggleAction = delegate
- {
- SetBedOwnerTypeByInterface((!ForPrisoners) ? BedOwnerType.Prisoner : BedOwnerType.Colonist);
- };
- if (!RoomCanBePrisonCell(this.GetRoom()) && !ForPrisoners)
- {
- command_Toggle.Disable("CommandBedSetForPrisonersFailOutdoors".Translate());
- }
- command_Toggle.hotKey = KeyBindingDefOf.Misc3;
- command_Toggle.turnOffSound = null;
- command_Toggle.turnOnSound = null;
- yield return command_Toggle;
- }
- }
- if (def.building.bed_canBeMedical)
- {
- Command_Toggle command_Toggle2 = new Command_Toggle();
- command_Toggle2.defaultLabel = "CommandBedSetAsMedicalLabel".Translate();
- command_Toggle2.defaultDesc = "CommandBedSetAsMedicalDesc".Translate();
- command_Toggle2.icon = ContentFinder.Get("UI/Commands/AsMedical");
- command_Toggle2.isActive = () => Medical;
- command_Toggle2.toggleAction = delegate
- {
- Medical = !Medical;
- };
- command_Toggle2.hotKey = KeyBindingDefOf.Misc2;
- yield return command_Toggle2;
- }
- }
-
- public void SetBedOwnerTypeByInterface(BedOwnerType ownerType)
- {
- if (lastBedOwnerSetChangeFrame == Time.frameCount)
- {
- return;
- }
- lastBedOwnerSetChangeFrame = Time.frameCount;
- ((ForOwnerType != ownerType) ? SoundDefOf.Checkbox_TurnedOn : SoundDefOf.Checkbox_TurnedOff).PlayOneShotOnCamera();
- List bedsToAffect = new List();
- foreach (Building_Bed item in Find.Selector.SelectedObjects.OfType())
- {
- if (item.ForOwnerType == ownerType)
- {
- continue;
- }
- Room room = item.GetRoom();
- if (room == null && ownerType != BedOwnerType.Prisoner)
- {
- if (!bedsToAffect.Contains(item))
- {
- bedsToAffect.Add(item);
- }
- continue;
- }
- foreach (Building_Bed containedBed in room.ContainedBeds)
- {
- if (containedBed.ForOwnerType != ownerType)
- {
- if (containedBed.ForOwnerType == BedOwnerType.Prisoner && !bedsToAffect.Contains(containedBed))
- {
- bedsToAffect.Add(containedBed);
- }
- else if (ownerType == BedOwnerType.Prisoner && RoomCanBePrisonCell(room) && !bedsToAffect.Contains(containedBed))
- {
- bedsToAffect.Add(containedBed);
- }
- else if (containedBed == item && !bedsToAffect.Contains(containedBed))
- {
- bedsToAffect.Add(containedBed);
- }
- }
- }
- }
- Action action = delegate
- {
- List list = new List();
- List list2 = new List();
- foreach (Building_Bed item2 in bedsToAffect)
- {
- District district = item2.GetDistrict();
- Room room2 = district.Room;
- if (ownerType == BedOwnerType.Prisoner && room2.TouchesMapEdge)
- {
- item2.ForOwnerType = BedOwnerType.Colonist;
- }
- else
- {
- item2.ForOwnerType = ownerType;
- }
- if (!room2.TouchesMapEdge)
- {
- if (!list2.Contains(room2))
- {
- list2.Add(room2);
- }
- if (!list.Contains(district))
- {
- list.Add(district);
- }
- }
- }
- foreach (District item3 in list)
- {
- item3.Notify_RoomShapeOrContainedBedsChanged();
- }
- foreach (Room item4 in list2)
- {
- item4.Notify_RoomShapeChanged();
- }
- };
- if (bedsToAffect.Where((Building_Bed b) => b.OwnersForReading.Any((Pawn owner) => owner.RaceProps.Humanlike) && b != this).Count() == 0)
- {
- action();
- return;
- }
- StringBuilder stringBuilder = new StringBuilder();
- if (!ModsConfig.IdeologyActive)
- {
- if (ownerType == BedOwnerType.Prisoner)
- {
- stringBuilder.Append("TurningOnPrisonerBedWarning".Translate());
- }
- else
- {
- stringBuilder.Append("TurningOffPrisonerBedWarning".Translate());
- }
- }
- else
- {
- stringBuilder.Append("ChangingOwnerTypeBedWarning".Translate());
- }
- stringBuilder.AppendLine();
- foreach (Building_Bed item5 in bedsToAffect)
- {
- if (ownerType != item5.ForOwnerType)
- {
- for (int i = 0; i < item5.OwnersForReading.Count; i++)
- {
- stringBuilder.AppendLine();
- stringBuilder.Append(item5.OwnersForReading[i].LabelShort);
- }
- }
- }
- stringBuilder.AppendLine();
- stringBuilder.AppendLine();
- stringBuilder.Append("AreYouSure".Translate());
- Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation(stringBuilder.ToString(), action));
- }
-
- public override string GetInspectString()
- {
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.Append(base.GetInspectString());
- if (def.building.bed_humanlike && def.building.bed_DisplayOwnerType && base.Faction == Faction.OfPlayer)
- {
- switch (ForOwnerType)
- {
- case BedOwnerType.Prisoner:
- stringBuilder.AppendInNewLine("ForPrisonerUse".Translate());
- break;
- case BedOwnerType.Slave:
- stringBuilder.AppendInNewLine("ForSlaveUse".Translate());
- break;
- case BedOwnerType.Colonist:
- stringBuilder.AppendInNewLine("ForColonistUse".Translate());
- break;
- default:
- Log.Error($"Unknown bed owner type: {ForOwnerType}");
- break;
- }
- }
- if (Medical)
- {
- stringBuilder.AppendInNewLine("MedicalBed".Translate());
- if (base.Spawned)
- {
- stringBuilder.AppendInNewLine("RoomInfectionChanceFactor".Translate() + ": " + this.GetRoom().GetStat(RoomStatDefOf.InfectionChanceFactor).ToStringPercent());
- }
- }
- else if (PlayerCanSeeOwners && def.building.bed_DisplayOwnersInInspectString)
- {
- if (OwnersForReading.Count == 0)
- {
- stringBuilder.AppendInNewLine("Owner".Translate() + ": " + "Nobody".Translate());
- }
- else if (OwnersForReading.Count == 1)
- {
- stringBuilder.AppendInNewLine("Owner".Translate() + ": " + OwnersForReading[0].Label);
- }
- else
- {
- stringBuilder.AppendInNewLine("Owners".Translate() + ": ");
- bool flag = false;
- for (int i = 0; i < OwnersForReading.Count; i++)
- {
- if (flag)
- {
- stringBuilder.Append(", ");
- }
- flag = true;
- stringBuilder.Append(OwnersForReading[i].LabelShort);
- }
- }
- if (OwnersForReading.Count == 1 && ChildcareUtility.CanSuckle(OwnersForReading[0], out var _))
- {
- Pawn p = OwnersForReading[0];
- float ambientTemperature = base.AmbientTemperature;
- if (!p.SafeTemperatureRange().IncludesEpsilon(ambientTemperature))
- {
- stringBuilder.AppendInNewLine("BedUnsafeTemperature".Translate().Colorize(ColoredText.WarningColor));
- }
- else if (!p.ComfortableTemperatureRange().IncludesEpsilon(ambientTemperature))
- {
- stringBuilder.AppendInNewLine("BedUncomfortableTemperature".Translate());
- }
- }
- }
- return stringBuilder.ToString();
- }
-
- public override IEnumerable GetFloatMenuOptions(Pawn myPawn)
- {
- FloatMenuOption bedRestFloatMenuOption = GetBedRestFloatMenuOption(myPawn);
- if (bedRestFloatMenuOption != null)
- {
- yield return bedRestFloatMenuOption;
- }
- }
-
- public FloatMenuOption GetBedRestFloatMenuOption(Pawn myPawn)
- {
- if (myPawn.RaceProps.Humanlike && !ForPrisoners && Medical && !myPawn.Drafted && base.Faction == Faction.OfPlayer && RestUtility.CanUseBedEver(myPawn, def))
- {
- if (!HealthAIUtility.ShouldSeekMedicalRest(myPawn))
- {
- if (myPawn.health.surgeryBills.AnyShouldDoNow && !WorkGiver_PatientGoToBedTreatment.AnyAvailableDoctorFor(myPawn))
- {
- return new FloatMenuOption("UseMedicalBed".Translate() + " (" + "NoDoctor".Translate() + ")", null);
- }
- return new FloatMenuOption("UseMedicalBed".Translate() + " (" + "NotInjured".Translate() + ")", null);
- }
- if (myPawn.IsSlaveOfColony && !ForSlaves)
- {
- return new FloatMenuOption("UseMedicalBed".Translate() + " (" + "NotForSlaves".Translate() + ")", null);
- }
- Action action = delegate
- {
- if (!ForPrisoners && Medical && myPawn.CanReserveAndReach(this, PathEndMode.ClosestTouch, Danger.Deadly, SleepingSlotsCount, -1, null, ignoreOtherReservations: true))
- {
- if (myPawn.CurJobDef == JobDefOf.LayDown && myPawn.CurJob.GetTarget(TargetIndex.A).Thing == this)
- {
- myPawn.CurJob.restUntilHealed = true;
- }
- else
- {
- Job job = JobMaker.MakeJob(JobDefOf.LayDown, this);
- job.restUntilHealed = true;
- myPawn.jobs.TryTakeOrderedJob(job, JobTag.Misc);
- }
- myPawn.mindState.ResetLastDisturbanceTick();
- }
- };
- return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption("UseMedicalBed".Translate(), action), myPawn, this, (AnyUnoccupiedSleepingSlot ? "ReservedBy" : "SomeoneElseSleeping").CapitalizeFirst());
- }
- return null;
- }
-
- public override void DrawGUIOverlay()
- {
- if (Medical || Find.CameraDriver.CurrentZoom != 0 || !PlayerCanSeeOwners)
- {
- return;
- }
- Color defaultThingLabelColor = GenMapUI.DefaultThingLabelColor;
- if (!OwnersForReading.Any())
- {
- GenMapUI.DrawThingLabel(this, "Unowned".Translate(), defaultThingLabelColor);
- return;
- }
- if (OwnersForReading.Count == 1)
- {
- Pawn pawn = OwnersForReading[0];
- if ((!pawn.InBed() || pawn.CurrentBed() != this) && (!pawn.RaceProps.Animal || Prefs.AnimalNameMode.ShouldDisplayAnimalName(pawn)))
- {
- GenMapUI.DrawThingLabel(this, pawn.LabelShort, defaultThingLabelColor);
- }
- return;
- }
- for (int i = 0; i < OwnersForReading.Count; i++)
- {
- Pawn pawn2 = OwnersForReading[i];
- if (!pawn2.InBed() || OwnersForReading[i].CurrentBed() != this || !(pawn2.Position == GetSleepingSlotPos(i)))
- {
- if (pawn2.RaceProps.Animal && !Prefs.AnimalNameMode.ShouldDisplayAnimalName(pawn2))
- {
- break;
- }
- GenMapUI.DrawThingLabel(GetMultiOwnersLabelScreenPosFor(i), pawn2.LabelShort, defaultThingLabelColor);
- }
- }
- }
-
- public Pawn GetCurOccupant(int slotIndex)
- {
- if (!base.Spawned)
- {
- return null;
- }
- IntVec3 sleepingSlotPos = GetSleepingSlotPos(slotIndex);
- List list = base.Map.thingGrid.ThingsListAt(sleepingSlotPos);
- for (int i = 0; i < list.Count; i++)
- {
- if (list[i] is Pawn { CurJob: not null } pawn && pawn.GetPosture().InBed())
- {
- return pawn;
- }
- }
- return null;
- }
-
- public int GetCurOccupantSlotIndex(Pawn curOccupant)
- {
- for (int i = 0; i < SleepingSlotsCount; i++)
- {
- if (GetCurOccupant(i) == curOccupant)
- {
- return i;
- }
- }
- Log.Error("Could not find pawn " + curOccupant?.ToString() + " on any of sleeping slots.");
- return 0;
- }
-
- public Pawn GetCurOccupantAt(IntVec3 pos)
- {
- for (int i = 0; i < SleepingSlotsCount; i++)
- {
- if (GetSleepingSlotPos(i) == pos)
- {
- return GetCurOccupant(i);
- }
- }
- return null;
- }
-
- public IntVec3 GetSleepingSlotPos(int index)
- {
- return BedUtility.GetSleepingSlotPos(index, base.Position, base.Rotation, def.size);
- }
-
- public IntVec3 GetFootSlotPos(int index)
- {
- return BedUtility.GetFeetSlotPos(index, base.Position, base.Rotation, def.size);
- }
-
- public bool IsOwner(Pawn p)
- {
- int? assignedSleepingSlot;
- return IsOwner(p, out assignedSleepingSlot);
- }
-
- public bool IsOwner(Pawn p, out int? assignedSleepingSlot)
- {
- int num = GetComp().AssignedPawnsForReading.IndexOf(p);
- if (num >= 0)
- {
- assignedSleepingSlot = num;
- return true;
- }
- assignedSleepingSlot = null;
- return false;
- }
-
- private void RemoveAllOwners(bool destroyed = false)
- {
- for (int num = OwnersForReading.Count - 1; num >= 0; num--)
- {
- Pawn pawn = OwnersForReading[num];
- pawn.ownership.UnclaimBed();
- string key = "MessageBedLostAssignment";
- if (destroyed)
- {
- key = "MessageBedDestroyed";
- }
- Messages.Message(key.Translate(def, pawn), new LookTargets(this, pawn), MessageTypeDefOf.CautionInput, historical: false);
- }
- }
-
- private void NotifyRoomBedTypeChanged()
- {
- this.GetRoom()?.Notify_BedTypeChanged();
- }
-
- public void NotifyRoomAssignedPawnsChanged()
- {
- this.GetRoom()?.Notify_BedTypeChanged();
- }
-
- private void FacilityChanged()
- {
- CompFacility compFacility = this.TryGetComp();
- CompAffectedByFacilities compAffectedByFacilities = this.TryGetComp();
- compFacility?.Notify_ThingChanged();
- compAffectedByFacilities?.Notify_ThingChanged();
- }
-
- private Vector3 GetMultiOwnersLabelScreenPosFor(int slotIndex)
- {
- IntVec3 sleepingSlotPos = GetSleepingSlotPos(slotIndex);
- Vector3 drawPos = DrawPos;
- if (base.Rotation.IsHorizontal)
- {
- drawPos.z = (float)sleepingSlotPos.z + 0.6f;
- }
- else
- {
- drawPos.x = (float)sleepingSlotPos.x + 0.5f;
- drawPos.z += -0.4f;
- }
- Vector2 vector = drawPos.MapToUIPosition();
- if (!base.Rotation.IsHorizontal && SleepingSlotsCount == 2)
- {
- vector = AdjustOwnerLabelPosToAvoidOverlapping(vector, slotIndex);
- }
- return vector;
- }
-
- private Vector3 AdjustOwnerLabelPosToAvoidOverlapping(Vector3 screenPos, int slotIndex)
- {
- Text.Font = GameFont.Tiny;
- float num = Text.CalcSize(OwnersForReading[slotIndex].LabelShort).x + 1f;
- Vector2 vector = DrawPos.MapToUIPosition();
- float num2 = Mathf.Abs(screenPos.x - vector.x);
- IntVec3 sleepingSlotPos = GetSleepingSlotPos(slotIndex);
- if (num > num2 * 2f)
- {
- float num3 = 0f;
- num3 = ((slotIndex != 0) ? ((float)GetSleepingSlotPos(0).x) : ((float)GetSleepingSlotPos(1).x));
- if ((float)sleepingSlotPos.x < num3)
- {
- screenPos.x -= (num - num2 * 2f) / 2f;
- }
- else
- {
- screenPos.x += (num - num2 * 2f) / 2f;
- }
- }
- return screenPos;
- }
-
- private bool RemoveLeastDesirableInteractionCells(List cells, Map map)
- {
- cells.RemoveAll(map, (Map innerMap, IntVec3 cell) => !cell.Standable(innerMap) || !TouchPathEndModeUtility.IsAdjacentOrInsideAndAllowedToTouch(cell, new LocalTargetInfo(this), map.pathing.Normal));
- if (cells.RemoveAll_IfNotAll(map, delegate(Map innerMap, IntVec3 cell)
- {
- Building building = map.edificeGrid[cell];
- return building == null || building.def?.IsBed != true;
- }))
- {
- return cells.RemoveAll_IfNotAll(map, (Map innerMap, IntVec3 cell) => cell.GetDoor(map) == null);
- }
- return false;
- }
-
- public IntVec3? FindPreferredInteractionCell(IntVec3 occupantLocation, CellSearchPattern customSearchPattern = null)
- {
- CellRect cellRect = this.OccupiedRect();
- if (!cellRect.Contains(occupantLocation))
- {
- Log.Error($"interiorLocation {occupantLocation} is not within the bounds of this bed {cellRect}.");
- return null;
- }
- tmpOrderedInteractionCells.Clear();
- (customSearchPattern ?? defaultBedInteractionCellsOrder).AddCellsToList(tmpOrderedInteractionCells, this, cellRect, occupantLocation, base.Rotation);
- RemoveLeastDesirableInteractionCells(tmpOrderedInteractionCells, base.Map);
- if (tmpOrderedInteractionCells.Count == 0)
- {
- return null;
- }
- return tmpOrderedInteractionCells[0];
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RoomRoleWorker_Bedroom.txt`
-**相似度:** 0.5705
-
-```csharp
-public class RoomRoleWorker_Bedroom : RoomRoleWorker
-{
- private static List tmpBeds = new List();
-
- private static List children = new List();
-
- private static List adults = new List();
-
- public override float GetScore(Room room)
- {
- tmpBeds.Clear();
- List containedAndAdjacentThings = room.ContainedAndAdjacentThings;
- int num = 0;
- for (int i = 0; i < containedAndAdjacentThings.Count; i++)
- {
- if (containedAndAdjacentThings[i] is Building_Bed building_Bed && building_Bed.def.building.bed_humanlike && building_Bed.def.building.bed_countsForBedroomOrBarracks)
- {
- if (building_Bed.Medical || building_Bed.ForPrisoners)
- {
- tmpBeds.Clear();
- return 0f;
- }
- num++;
- tmpBeds.Add(building_Bed);
- }
- }
- if (num == 0)
- {
- tmpBeds.Clear();
- return 0f;
- }
- bool num2 = IsBedroom(tmpBeds);
- tmpBeds.Clear();
- if (!num2)
- {
- return 0f;
- }
- return 100000f;
- }
-
- public static bool IsBedroom(List beds)
- {
- children.Clear();
- adults.Clear();
- bool result = IsBedroomHelper(beds);
- children.Clear();
- adults.Clear();
- return result;
- }
-
- private static bool IsBedroomHelper(List beds)
- {
- List list = null;
- int num = 0;
- int num2 = 0;
- int num3 = 0;
- foreach (Building_Bed bed in beds)
- {
- List ownersForReading = bed.OwnersForReading;
- if (ownersForReading.NullOrEmpty() && bed.def.building.bed_emptyCountsForBarracks)
- {
- num++;
- continue;
- }
- if (ownersForReading.Count > 0)
- {
- num2++;
- }
- bool flag = false;
- foreach (Pawn item in ownersForReading)
- {
- if (item.DevelopmentalStage.Juvenile())
- {
- children.Add(item);
- continue;
- }
- adults.Add(item);
- if (list == null)
- {
- list = item.GetLoveCluster();
- }
- if (!list.Contains(item))
- {
- flag = true;
- }
- }
- if (flag)
- {
- num3++;
- }
- }
- if (num == 1 && num2 == 0)
- {
- return true;
- }
- if (num == 0 && num2 == 1)
- {
- return true;
- }
- if (num > 0)
- {
- return false;
- }
- if (adults.NullOrEmpty())
- {
- return true;
- }
- if (num3 > 0)
- {
- return false;
- }
- foreach (Pawn child in children)
- {
- Pawn mother = child.GetMother();
- Pawn father = child.GetFather();
- if (!adults.Any((Pawn adult) => adult == mother || adult == father))
- {
- return false;
- }
- }
- return true;
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\RoomRoleWorker_Barracks.txt`
-**相似度:** 0.5548
-
-```csharp
-public class RoomRoleWorker_Barracks : RoomRoleWorker
-{
- private static List tmpBeds = new List();
-
- public override float GetScore(Room room)
- {
- tmpBeds.Clear();
- int num = 0;
- List containedAndAdjacentThings = room.ContainedAndAdjacentThings;
- for (int i = 0; i < containedAndAdjacentThings.Count; i++)
- {
- if (containedAndAdjacentThings[i] is Building_Bed building_Bed && building_Bed.def.building.bed_humanlike && building_Bed.def.building.bed_countsForBedroomOrBarracks)
- {
- if (building_Bed.ForPrisoners)
- {
- tmpBeds.Clear();
- return 0f;
- }
- tmpBeds.Add(building_Bed);
- if (!building_Bed.Medical)
- {
- num++;
- }
- }
- }
- bool num2 = RoomRoleWorker_Bedroom.IsBedroom(tmpBeds);
- tmpBeds.Clear();
- if (num2)
- {
- return 0f;
- }
- return (float)num * 100100f;
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld.BaseGen\SymbolResolver_PrisonerBed.txt`
-**相似度:** 0.5535
-
-```csharp
-public class SymbolResolver_PrisonerBed : SymbolResolver
-{
- public override void Resolve(ResolveParams rp)
- {
- ResolveParams resolveParams = rp;
- Action prevPostThingSpawn = resolveParams.postThingSpawn;
- resolveParams.postThingSpawn = delegate(Thing x)
- {
- if (prevPostThingSpawn != null)
- {
- prevPostThingSpawn(x);
- }
- if (x is Building_Bed building_Bed)
- {
- building_Bed.ForPrisoners = true;
- }
- };
- BaseGen.symbolStack.Push("bed", resolveParams);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\WorkGiver_TakeToBed.txt`
-**相似度:** 0.5270
-
-```csharp
-public abstract class WorkGiver_TakeToBed : WorkGiver_Scanner
-{
- protected Building_Bed FindBed(Pawn pawn, Pawn patient)
- {
- return RestUtility.FindBedFor(patient, pawn, checkSocialProperness: false, ignoreOtherReservations: false, patient.GuestStatus);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompAssignableToPawn_DeathrestCasket.txt`
-**相似度:** 0.5238
-
-```csharp
-public class CompAssignableToPawn_DeathrestCasket : CompAssignableToPawn_Bed
-{
- public override string CompInspectStringExtra()
- {
- return null;
- }
-
- public override bool AssignedAnything(Pawn pawn)
- {
- return pawn.ownership.AssignedDeathrestCasket != null;
- }
-
- public override void TryAssignPawn(Pawn pawn)
- {
- Building_Bed building_Bed = (Building_Bed)parent;
- pawn.ownership.ClaimDeathrestCasket(building_Bed);
- building_Bed.NotifyRoomAssignedPawnsChanged();
- }
-
- public override void TryUnassignPawn(Pawn pawn, bool sort = true, bool uninstall = false)
- {
- Building_Bed ownedBed = pawn.ownership.OwnedBed;
- pawn.ownership.UnclaimDeathrestCasket();
- ownedBed?.NotifyRoomAssignedPawnsChanged();
- }
-
- public override AcceptanceReport CanAssignTo(Pawn pawn)
- {
- Building_Bed building_Bed = (Building_Bed)parent;
- if (pawn.BodySize > building_Bed.def.building.bed_maxBodySize)
- {
- return "TooLargeForBed".Translate();
- }
- if (building_Bed.ForSlaves && !pawn.IsSlave)
- {
- return "CannotAssignBedToColonist".Translate();
- }
- if (building_Bed.ForColonists && pawn.IsSlave)
- {
- return "CannotAssignBedToSlave".Translate();
- }
- CompDeathrestBindable compDeathrestBindable = parent.TryGetComp();
- if (compDeathrestBindable != null && compDeathrestBindable.BoundPawn != null && compDeathrestBindable.BoundPawn != pawn)
- {
- return "CannotAssignAlreadyBound".Translate(compDeathrestBindable.BoundPawn);
- }
- Gene_Deathrest gene_Deathrest = pawn.genes?.GetFirstGeneOfType();
- if (gene_Deathrest == null)
- {
- return "CannotAssignBedCannotDeathrest".Translate();
- }
- if (compDeathrestBindable != null && gene_Deathrest.BindingWillExceedStackLimit(compDeathrestBindable))
- {
- return "CannotAssignBedCannotBindToMoreBuildings".Translate(NamedArgumentUtility.Named(parent.def, "BUILDING"));
- }
- return AcceptanceReport.WasAccepted;
- }
-
- protected override void PostPostExposeData()
- {
- if (Scribe.mode == LoadSaveMode.PostLoadInit && ModsConfig.BiotechActive && assignedPawns.RemoveAll((Pawn x) => x.ownership.AssignedDeathrestCasket != parent) > 0)
- {
- Log.Warning(parent.ToStringSafe() + " had pawns assigned that don't have it as an assigned bed. Removing.");
- }
- }
-}
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod.txt b/MCP/vector_cache/CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod.txt
deleted file mode 100644
index cbec2925..00000000
--- a/MCP/vector_cache/CarryToBiosculpterPod-JobDefOf-JobDriver_CarryToBiosculpterPod.txt
+++ /dev/null
@@ -1,198 +0,0 @@
-根据向量相似度分析,与 'JobDriver_CarryToBiosculpterPod, JobDefOf, CarryToBiosculpterPod' 最相关的代码定义如下:
-
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\JobDriver_CarryToBiosculpterPod.txt`
-
-```csharp
-public class JobDriver_CarryToBiosculpterPod : JobDriver
-{
- private const TargetIndex TakeeInd = TargetIndex.A;
-
- private const TargetIndex IngredientInd = TargetIndex.B;
-
- private const TargetIndex PodInd = TargetIndex.C;
-
- private List pickedUpIngredients = new List();
-
- private List thingsToTransfer = new List();
-
- private Pawn Takee => (Pawn)job.GetTarget(TargetIndex.A).Thing;
-
- private CompBiosculpterPod Pod => job.GetTarget(TargetIndex.C).Thing.TryGetComp();
-
- public override bool TryMakePreToilReservations(bool errorOnFailed)
- {
- if (!pawn.Reserve(Takee, job, 1, -1, null, errorOnFailed) || !pawn.Reserve(Pod.parent, job, 1, -1, null, errorOnFailed))
- {
- return false;
- }
- List targetQueue = job.GetTargetQueue(TargetIndex.B);
- for (int i = 0; i < targetQueue.Count; i++)
- {
- if (!pawn.Reserve(targetQueue[i], job, 1, -1, null, errorOnFailed))
- {
- return false;
- }
- }
- return true;
- }
-
- protected override IEnumerable MakeNewToils()
- {
- if (!ModLister.CheckIdeology("Biosculpting"))
- {
- yield break;
- }
- AddFinishAction(delegate
- {
- if (Pod != null)
- {
- if (Pod.queuedEnterJob == job)
- {
- Pod.ClearQueuedInformation();
- }
- if (Pod.Occupant != Takee)
- {
- foreach (Thing pickedUpIngredient in pickedUpIngredients)
- {
- Thing lastResultingThing;
- if (pawn.inventory.Contains(pickedUpIngredient))
- {
- pawn.inventory.innerContainer.TryDrop(pickedUpIngredient, ThingPlaceMode.Near, out lastResultingThing);
- }
- else if (Takee.inventory.Contains(pickedUpIngredient))
- {
- Takee.inventory.innerContainer.TryDrop(pickedUpIngredient, ThingPlaceMode.Near, out lastResultingThing);
- }
- }
- }
- }
- });
- this.FailOnDestroyedOrNull(TargetIndex.A);
- this.FailOnDestroyedOrNull(TargetIndex.C);
- this.FailOnAggroMentalState(TargetIndex.A);
- this.FailOn(() => job.biosculpterCycleKey == null || !Pod.CanAcceptOnceCycleChosen(Takee));
- Toil goToTakee = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.OnCell).FailOnDestroyedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.C)
- .FailOn(() => Takee.IsFreeColonist && !Takee.Downed)
- .FailOnSomeonePhysicallyInteracting(TargetIndex.A);
- Toil startCarryingTakee = Toils_Haul.StartCarryThing(TargetIndex.A);
- Toil goToThing = Toils_Goto.GotoThing(TargetIndex.C, PathEndMode.InteractionCell);
- Toil toil = Toils_Jump.JumpIf(goToThing, () => pawn.IsCarryingPawn(Takee) && job.GetTargetQueue(TargetIndex.B).NullOrEmpty());
- Toil jumpIfGoToTakee = Toils_Jump.JumpIf(goToTakee, () => job.GetTargetQueue(TargetIndex.B).NullOrEmpty());
- yield return toil;
- yield return jumpIfGoToTakee;
- yield return DropCarryToGrabIngredients();
- foreach (Toil item in JobDriver_EnterBiosculpterPod.CollectIngredientsToilsHelper(TargetIndex.B, pawn, pickedUpIngredients))
- {
- yield return item;
- }
- yield return goToTakee;
- yield return TransferIngredientsAndPrepareCarryDownedPawn();
- yield return startCarryingTakee;
- yield return goToThing.FailOn(() => !Pod.PawnCarryingExtraCycleIngredients(Takee, job.biosculpterCycleKey));
- yield return JobDriver_EnterBiosculpterPod.PrepareToEnterToil(TargetIndex.C);
- Toil toil2 = ToilMaker.MakeToil("MakeNewToils");
- toil2.initAction = delegate
- {
- Pod.TryAcceptPawn(Takee, job.biosculpterCycleKey);
- };
- toil2.defaultCompleteMode = ToilCompleteMode.Instant;
- yield return toil2;
- }
-
- private Toil TransferIngredientsAndPrepareCarryDownedPawn()
- {
- Toil toil = ToilMaker.MakeToil("TransferIngredientsAndPrepareCarryDownedPawn");
- toil.initAction = delegate
- {
- List extraRequiredIngredients = Pod.GetCycle(job.biosculpterCycleKey).Props.extraRequiredIngredients;
- if (extraRequiredIngredients != null && !Pod.devFillPodLatch)
- {
- ThingOwner innerContainer = pawn.inventory.innerContainer;
- foreach (ThingDefCountClass item in extraRequiredIngredients)
- {
- if (Takee.inventory.Count(item.thingDef) < item.count)
- {
- if (pawn.inventory.Count(item.thingDef) < item.count)
- {
- EndJobWith(JobCondition.Incompletable);
- return;
- }
- thingsToTransfer.Clear();
- int num = 0;
- foreach (Thing item2 in innerContainer)
- {
- if (num >= item.count)
- {
- break;
- }
- if (item2.def == item.thingDef)
- {
- int num2 = Mathf.Min(item.count - num, item2.stackCount);
- thingsToTransfer.Add(new ThingCount(item2, Mathf.Min(item.count - num, item2.stackCount)));
- num += num2;
- }
- }
- foreach (ThingCount item3 in thingsToTransfer)
- {
- int num3 = Takee.inventory.innerContainer.TryAddOrTransfer(item3.Thing, item3.Count);
- if (num3 != item3.Count)
- {
- Log.Warning($"Only able to transfer x{num3} of the expected x{item3.Count} of {item3.Thing.Label} while CarryToBiosculpter");
- EndJobWith(JobCondition.Incompletable);
- return;
- }
- }
- }
- }
- }
- job.count = 1;
- };
- toil.defaultCompleteMode = ToilCompleteMode.Instant;
- return toil;
- }
-
- private Toil DropCarryToGrabIngredients()
- {
- Toil toil = ToilMaker.MakeToil("DropCarryToGrabIngredients");
- toil.initAction = delegate
- {
- if (pawn.carryTracker.CarriedThing != null)
- {
- pawn.carryTracker.TryDropCarriedThing(pawn.Position, ThingPlaceMode.Near, out var _);
- }
- };
- toil.defaultCompleteMode = ToilCompleteMode.Instant;
- return toil;
- }
-
- public override string GetReport()
- {
- if (!Pod.PawnCarryingExtraCycleIngredients(Takee, job.biosculpterCycleKey) && !Pod.PawnCarryingExtraCycleIngredients(pawn, job.biosculpterCycleKey))
- {
- return "BiosculpterJobReportCollectIngredients".Translate();
- }
- return base.GetReport();
- }
-
- public override void ExposeData()
- {
- base.ExposeData();
- Scribe_Collections.Look(ref pickedUpIngredients, "pickedUpIngredients", LookMode.Reference);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\Ideology\Defs\JobDefs\Jobs_Misc.xml`
-**相似度:** 0.5483
-
-```xml
- CarryToBiosculpterPod
- JobDriver_CarryToBiosculpterPod
- carrying TargetA to biosculpter pod.
- false
-
-
-
- RecolorApparel
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/ColonistBarColonistDrawer-DrawIcons.txt b/MCP/vector_cache/ColonistBarColonistDrawer-DrawIcons.txt
deleted file mode 100644
index 54867b4b..00000000
--- a/MCP/vector_cache/ColonistBarColonistDrawer-DrawIcons.txt
+++ /dev/null
@@ -1,985 +0,0 @@
-根据向量相似度分析,与 'DrawIcons, ColonistBarColonistDrawer' 最相关的代码定义如下:
-
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\ColonistBarColonistDrawer.txt`
-
-```csharp
-public class ColonistBarColonistDrawer
-{
- private struct IconDrawCall
- {
- public Texture2D texture;
-
- public string tooltip;
-
- public Color? color;
-
- public IconDrawCall(Texture2D texture, string tooltip = null, Color? color = null)
- {
- this.texture = texture;
- this.tooltip = tooltip;
- this.color = color;
- }
- }
-
- private Dictionary pawnLabelsCache = new Dictionary();
-
- private static readonly Texture2D MoodBGTex = SolidColorMaterials.NewSolidColorTexture(new Color(0.4f, 0.47f, 0.53f, 0.44f));
-
- private static readonly Texture2D MoodAtlas = ContentFinder.Get("UI/Widgets/SubtleGradient");
-
- private static readonly Texture2D DeadColonistTex = ContentFinder.Get("UI/Misc/DeadColonist");
-
- private static readonly Texture2D Icon_FormingCaravan = ContentFinder.Get("UI/Icons/ColonistBar/FormingCaravan");
-
- private static readonly Texture2D Icon_MentalStateNonAggro = ContentFinder.Get("UI/Icons/ColonistBar/MentalStateNonAggro");
-
- private static readonly Texture2D Icon_MentalStateAggro = ContentFinder.Get("UI/Icons/ColonistBar/MentalStateAggro");
-
- private static readonly Texture2D Icon_MedicalRest = ContentFinder.Get("UI/Icons/ColonistBar/MedicalRest");
-
- private static readonly Texture2D Icon_Sleeping = ContentFinder.Get("UI/Icons/ColonistBar/Sleeping");
-
- private static readonly Texture2D Icon_Fleeing = ContentFinder.Get("UI/Icons/ColonistBar/Fleeing");
-
- private static readonly Texture2D Icon_Attacking = ContentFinder.Get("UI/Icons/ColonistBar/Attacking");
-
- private static readonly Texture2D Icon_Idle = ContentFinder.Get("UI/Icons/ColonistBar/Idle");
-
- private static readonly Texture2D Icon_Burning = ContentFinder.Get("UI/Icons/ColonistBar/Burning");
-
- private static readonly Texture2D Icon_Inspired = ContentFinder.Get("UI/Icons/ColonistBar/Inspired");
-
- private static readonly Texture2D MoodGradient = ContentFinder.Get("UI/Widgets/MoodGradient");
-
- public static readonly Vector2 PawnTextureSize = new Vector2(ColonistBar.BaseSize.x - 2f, 75f);
-
- public static readonly Vector3 PawnTextureCameraOffset = new Vector3(0f, 0f, 0.3f);
-
- public const float PawnTextureCameraZoom = 1.28205f;
-
- private const float PawnTextureHorizontalPadding = 1f;
-
- private static readonly float BaseIconAreaWidth = PawnTextureSize.x;
-
- private static readonly float BaseIconMaxSize = 20f;
-
- private const float BaseGroupFrameMargin = 12f;
-
- public const float DoubleClickTime = 0.5f;
-
- public const float FactionIconSpacing = 2f;
-
- public const float IdeoRoleIconSpacing = 2f;
-
- public const float SlaveIconSpacing = 2f;
-
- private const float MoodGradientHeight = 35f;
-
- private static List tmpIconsToDraw = new List();
-
- private ColonistBar ColonistBar => Find.ColonistBar;
-
- public void DrawColonist(Rect rect, Pawn colonist, Map pawnMap, bool highlight, bool reordering)
- {
- float alpha = ColonistBar.GetEntryRectAlpha(rect);
- bool num = Prefs.VisibleMood && colonist.needs?.mood != null && colonist.mindState.mentalBreaker.CanDoRandomMentalBreaks && !colonist.Dead && !colonist.Downed;
- MoodThreshold moodThreshold = MoodThresholdExtensions.CurrentMoodThresholdFor(colonist);
- Color color = moodThreshold.GetColor();
- color.a *= alpha;
- ApplyEntryInAnotherMapAlphaFactor(pawnMap, ref alpha);
- if (reordering)
- {
- alpha *= 0.5f;
- }
- Color color3 = (GUI.color = new Color(1f, 1f, 1f, alpha));
- if (num && alpha >= 1f)
- {
- float num2 = moodThreshold.EdgeExpansion();
- if (num2 > 0f)
- {
- GUI.color = color;
- Widgets.DrawAtlas(rect.ExpandedBy(num2), MoodAtlas);
- GUI.color = color3;
- }
- }
- GUI.DrawTexture(rect, ColonistBar.BGTex);
- if (colonist.needs != null && colonist.needs.mood != null)
- {
- Rect position = rect.ContractedBy(2f);
- float num3 = position.height * colonist.needs.mood.CurLevelPercentage;
- position.yMin = position.yMax - num3;
- position.height = num3;
- GUI.DrawTexture(position, MoodBGTex);
- }
- if (num && alpha >= 1f)
- {
- float transparency = ((moodThreshold < MoodThreshold.Major) ? 0.1f : 0.15f);
- Widgets.DrawBoxSolid(rect, moodThreshold.GetColor().ToTransparent(transparency));
- }
- if (highlight)
- {
- int thickness = ((rect.width <= 22f) ? 2 : 3);
- GUI.color = Color.white;
- Widgets.DrawBox(rect, thickness);
- GUI.color = color3;
- }
- Rect rect2 = rect.ContractedBy(-2f * ColonistBar.Scale);
- if ((colonist.Dead ? Find.Selector.SelectedObjects.Contains(colonist.Corpse) : Find.Selector.SelectedObjects.Contains(colonist)) && !WorldRendererUtility.WorldSelected)
- {
- DrawSelectionOverlayOnGUI(colonist, rect2);
- }
- else if (WorldRendererUtility.WorldSelected && colonist.IsCaravanMember() && Find.WorldSelector.IsSelected(colonist.GetCaravan()))
- {
- DrawCaravanSelectionOverlayOnGUI(colonist.GetCaravan(), rect2);
- }
- GUI.DrawTexture(GetPawnTextureRect(rect.position), PortraitsCache.Get(colonist, PawnTextureSize, Rot4.South, PawnTextureCameraOffset, 1.28205f));
- if (num)
- {
- Rect rect3 = rect.ContractedBy(1f);
- Widgets.BeginGroup(rect3);
- Rect position2 = rect3.AtZero();
- position2.yMin = position2.yMax - 35f;
- GUI.color = color;
- GUI.DrawTexture(position2, MoodGradient);
- GUI.color = color3;
- Widgets.EndGroup();
- }
- GUI.color = new Color(1f, 1f, 1f, alpha * 0.8f);
- DrawIcons(rect, colonist);
- GUI.color = color3;
- if (colonist.Dead)
- {
- GUI.DrawTexture(rect, DeadColonistTex);
- }
- float num4 = 4f * ColonistBar.Scale;
- Vector2 pos = new Vector2(rect.center.x, rect.yMax - num4);
- GenMapUI.DrawPawnLabel(colonist, pos, alpha, rect.width + ColonistBar.SpaceBetweenColonistsHorizontal - 2f, pawnLabelsCache);
- Text.Font = GameFont.Small;
- GUI.color = Color.white;
- }
-
- private Rect GroupFrameRect(int group)
- {
- float num = 99999f;
- float num2 = 0f;
- float num3 = 0f;
- List entries = ColonistBar.Entries;
- List drawLocs = ColonistBar.DrawLocs;
- for (int i = 0; i < entries.Count; i++)
- {
- if (entries[i].group == group)
- {
- num = Mathf.Min(num, drawLocs[i].x);
- num2 = Mathf.Max(num2, drawLocs[i].x + ColonistBar.Size.x);
- num3 = Mathf.Max(num3, drawLocs[i].y + ColonistBar.Size.y);
- }
- }
- return new Rect(num, 0f, num2 - num, num3 - 0f).ContractedBy(-12f * ColonistBar.Scale);
- }
-
- public void DrawGroupFrame(int group)
- {
- Rect position = GroupFrameRect(group);
- Map map = ColonistBar.Entries.Find((ColonistBar.Entry x) => x.group == group).map;
- float num = ((map == null) ? ((!WorldRendererUtility.WorldSelected) ? 0.75f : 1f) : ((map == Find.CurrentMap && !WorldRendererUtility.WorldSelected) ? 1f : 0.75f));
- Widgets.DrawRectFast(position, new Color(0.5f, 0.5f, 0.5f, 0.4f * num));
- }
-
- private void ApplyEntryInAnotherMapAlphaFactor(Map map, ref float alpha)
- {
- if (map == null)
- {
- if (!WorldRendererUtility.WorldSelected)
- {
- alpha = Mathf.Min(alpha, 0.4f);
- }
- }
- else if (map != Find.CurrentMap || WorldRendererUtility.WorldSelected)
- {
- alpha = Mathf.Min(alpha, 0.4f);
- }
- }
-
- public void HandleClicks(Rect rect, Pawn colonist, int reorderableGroup, out bool reordering)
- {
- if (Event.current.type == EventType.MouseDown && Event.current.button == 0 && Event.current.clickCount == 2 && Mouse.IsOver(rect))
- {
- Event.current.Use();
- CameraJumper.TryJump(colonist);
- }
- reordering = ReorderableWidget.Reorderable(reorderableGroup, rect, useRightButton: true);
- if (Event.current.type == EventType.MouseDown && Event.current.button == 1 && Mouse.IsOver(rect))
- {
- Event.current.Use();
- }
- }
-
- public void HandleGroupFrameClicks(int group)
- {
- Rect rect = GroupFrameRect(group);
- if (Event.current.type == EventType.MouseUp && Event.current.button == 0 && Mouse.IsOver(rect) && !ColonistBar.AnyColonistOrCorpseAt(UI.MousePositionOnUIInverted))
- {
- bool worldSelected = WorldRendererUtility.WorldSelected;
- if ((!worldSelected && !Find.Selector.dragBox.IsValidAndActive) || (worldSelected && !Find.WorldSelector.dragBox.IsValidAndActive))
- {
- Find.Selector.dragBox.active = false;
- Find.WorldSelector.dragBox.active = false;
- ColonistBar.Entry entry = ColonistBar.Entries.Find((ColonistBar.Entry x) => x.group == group);
- Map map = entry.map;
- if (map == null)
- {
- if (WorldRendererUtility.WorldSelected)
- {
- CameraJumper.TrySelect(entry.pawn);
- }
- else
- {
- CameraJumper.TryJumpAndSelect(entry.pawn);
- }
- }
- else
- {
- if (!CameraJumper.TryHideWorld() && Find.CurrentMap != map)
- {
- SoundDefOf.MapSelected.PlayOneShotOnCamera();
- }
- Current.Game.CurrentMap = map;
- }
- }
- }
- if (Event.current.type == EventType.MouseDown && Event.current.button == 1 && Mouse.IsOver(rect))
- {
- Event.current.Use();
- }
- }
-
- public void Notify_RecachedEntries()
- {
- pawnLabelsCache.Clear();
- }
-
- public void ClearLabelCache()
- {
- pawnLabelsCache.Clear();
- }
-
- public Rect GetPawnTextureRect(Vector2 pos)
- {
- float x = pos.x;
- float y = pos.y;
- Vector2 vector = PawnTextureSize * ColonistBar.Scale;
- return new Rect(x + 1f, y - (vector.y - ColonistBar.Size.y) - 1f, vector.x, vector.y).ContractedBy(1f);
- }
-
- private void DrawIcons(Rect rect, Pawn colonist)
- {
- if (colonist.Dead)
- {
- return;
- }
- tmpIconsToDraw.Clear();
- bool flag = false;
- if (colonist.CurJob != null)
- {
- JobDef def = colonist.CurJob.def;
- if (def == JobDefOf.AttackMelee || def == JobDefOf.AttackStatic)
- {
- flag = true;
- }
- else if (def == JobDefOf.Wait_Combat && colonist.stances.curStance is Stance_Busy stance_Busy && stance_Busy.focusTarg.IsValid)
- {
- flag = true;
- }
- }
- if (colonist.IsFormingCaravan())
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_FormingCaravan, "ActivityIconFormingCaravan".Translate()));
- }
- if (colonist.InAggroMentalState)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_MentalStateAggro, colonist.MentalStateDef.LabelCap));
- }
- else if (colonist.InMentalState)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_MentalStateNonAggro, colonist.MentalStateDef.LabelCap));
- }
- else if (colonist.InBed() && colonist.CurrentBed().Medical)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_MedicalRest, "ActivityIconMedicalRest".Translate()));
- }
- else
- {
- if (colonist.CurJob != null && colonist.jobs.curDriver.asleep)
- {
- goto IL_01c5;
- }
- if (colonist.GetCaravan() != null)
- {
- Pawn_NeedsTracker needs = colonist.needs;
- if (needs != null && needs.rest?.Resting == true)
- {
- goto IL_01c5;
- }
- }
- if (colonist.CurJob != null && colonist.CurJob.def == JobDefOf.FleeAndCower)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_Fleeing, "ActivityIconFleeing".Translate()));
- }
- else if (flag)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_Attacking, "ActivityIconAttacking".Translate()));
- }
- else if (colonist.mindState.IsIdle && GenDate.DaysPassed >= 1)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_Idle, "ActivityIconIdle".Translate()));
- }
- }
- goto IL_02b4;
- IL_01c5:
- tmpIconsToDraw.Add(new IconDrawCall(Icon_Sleeping, "ActivityIconSleeping".Translate()));
- goto IL_02b4;
- IL_02b4:
- if (colonist.IsBurning())
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_Burning, "ActivityIconBurning".Translate()));
- }
- if (colonist.Inspired)
- {
- tmpIconsToDraw.Add(new IconDrawCall(Icon_Inspired, colonist.InspirationDef.LabelCap));
- }
- if (colonist.IsSlaveOfColony)
- {
- tmpIconsToDraw.Add(new IconDrawCall(colonist.guest.GetIcon()));
- }
- else
- {
- bool flag2 = false;
- if (colonist.Ideo != null)
- {
- Ideo ideo = colonist.Ideo;
- Precept_Role role = ideo.GetRole(colonist);
- if (role != null)
- {
- tmpIconsToDraw.Add(new IconDrawCall(role.Icon, null, ideo.Color));
- flag2 = true;
- }
- }
- if (!flag2)
- {
- Faction faction = null;
- if (colonist.HasExtraMiniFaction())
- {
- faction = colonist.GetExtraMiniFaction();
- }
- else if (colonist.HasExtraHomeFaction())
- {
- faction = colonist.GetExtraHomeFaction();
- }
- if (faction != null)
- {
- tmpIconsToDraw.Add(new IconDrawCall(faction.def.FactionIcon, null, faction.Color));
- }
- }
- }
- float num = Mathf.Min(BaseIconAreaWidth / (float)tmpIconsToDraw.Count, BaseIconMaxSize) * ColonistBar.Scale;
- Vector2 pos = new Vector2(rect.x + 1f, rect.yMax - num - 1f);
- foreach (IconDrawCall item in tmpIconsToDraw)
- {
- GUI.color = item.color ?? Color.white;
- DrawIcon(item.texture, ref pos, num, item.tooltip);
- GUI.color = Color.white;
- }
- }
-
- private void DrawIcon(Texture2D icon, ref Vector2 pos, float iconSize, string tooltip = null)
- {
- Rect rect = new Rect(pos.x, pos.y, iconSize, iconSize);
- GUI.DrawTexture(rect, icon);
- if (tooltip != null)
- {
- TooltipHandler.TipRegion(rect, tooltip);
- }
- pos.x += iconSize;
- }
-
- private void DrawSelectionOverlayOnGUI(Pawn colonist, Rect rect)
- {
- Thing target = colonist;
- if (colonist.Dead)
- {
- target = colonist.Corpse;
- }
- SelectionDrawerUtility.DrawSelectionOverlayOnGUI(target, rect, 0.4f * ColonistBar.Scale, 20f * ColonistBar.Scale);
- }
-
- private void DrawCaravanSelectionOverlayOnGUI(Caravan caravan, Rect rect)
- {
- SelectionDrawerUtility.DrawSelectionOverlayOnGUI(caravan, rect, 0.4f * ColonistBar.Scale, 20f * ColonistBar.Scale);
- }
-}
-```
----
-**文件路径:** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\ColonistBar.txt`
-**相似度:** 0.7704
-
-```csharp
-public class ColonistBar
-{
- public struct Entry
- {
- public Pawn pawn;
-
- public Map map;
-
- public int group;
-
- public Action reorderAction;
-
- public Action extraDraggedItemOnGUI;
-
- public Entry(Pawn pawn, Map map, int group)
- {
- this.pawn = pawn;
- this.map = map;
- this.group = group;
- reorderAction = delegate(int from, int to)
- {
- Find.ColonistBar.Reorder(from, to, group);
- };
- extraDraggedItemOnGUI = delegate(int index, Vector2 dragStartPos)
- {
- Find.ColonistBar.DrawColonistMouseAttachment(index, dragStartPos, group);
- };
- }
- }
-
- public ColonistBarColonistDrawer drawer = new ColonistBarColonistDrawer();
-
- private ColonistBarDrawLocsFinder drawLocsFinder = new ColonistBarDrawLocsFinder();
-
- private List cachedEntries = new List();
-
- private List cachedDrawLocs = new List();
-
- private List cachedReorderableGroups = new List();
-
- private float cachedScale = 1f;
-
- private bool entriesDirty = true;
-
- private List colonistsToHighlight = new List();
-
- public static readonly Texture2D BGTex = Command.BGTex;
-
- public static readonly Vector2 BaseSize = new Vector2(48f, 48f);
-
- public const float BaseSelectedTexJump = 20f;
-
- public const float BaseSelectedTexScale = 0.4f;
-
- public const float EntryInAnotherMapAlpha = 0.4f;
-
- public const float BaseSpaceBetweenGroups = 25f;
-
- public const float BaseSpaceBetweenColonistsHorizontal = 24f;
-
- public const float BaseSpaceBetweenColonistsVertical = 32f;
-
- private const float WeaponIconOffsetScaleFactor = 1.05f;
-
- private const float WeaponIconScaleFactor = 0.75f;
-
- private static List tmpPawns = new List();
-
- private static List tmpMaps = new List();
-
- private static List tmpCaravans = new List();
-
- private static List tmpColonistsInOrder = new List();
-
- private static List> tmpColonistsWithMap = new List>();
-
- private static List tmpColonists = new List();
-
- private static List tmpMapColonistsOrCorpsesInScreenRect = new List();
-
- private static List tmpCaravanPawns = new List();
-
- public List Entries
- {
- get
- {
- CheckRecacheEntries();
- return cachedEntries;
- }
- }
-
- private bool ShowGroupFrames
- {
- get
- {
- List entries = Entries;
- int num = -1;
- for (int i = 0; i < entries.Count; i++)
- {
- num = Mathf.Max(num, entries[i].group);
- }
- return num >= 1;
- }
- }
-
- public float Scale => cachedScale;
-
- public List DrawLocs => cachedDrawLocs;
-
- public Vector2 Size => BaseSize * Scale;
-
- public float SpaceBetweenColonistsHorizontal => 24f * Scale;
-
- private bool Visible
- {
- get
- {
- if (UI.screenWidth < 800 || UI.screenHeight < 500)
- {
- return false;
- }
- if (Find.TilePicker.Active)
- {
- return false;
- }
- return true;
- }
- }
-
- public void MarkColonistsDirty()
- {
- entriesDirty = true;
- }
-
- public void ColonistBarOnGUI()
- {
- if (!Visible)
- {
- return;
- }
- if (Event.current.type != EventType.Layout)
- {
- List entries = Entries;
- int num = -1;
- bool showGroupFrames = ShowGroupFrames;
- int value = -1;
- for (int i = 0; i < cachedDrawLocs.Count; i++)
- {
- Rect rect = new Rect(cachedDrawLocs[i].x, cachedDrawLocs[i].y, Size.x, Size.y);
- Entry entry = entries[i];
- bool flag = num != entry.group;
- num = entry.group;
- if (Event.current.type == EventType.Repaint)
- {
- if (flag)
- {
- value = ReorderableWidget.NewGroup(entry.reorderAction, ReorderableDirection.Horizontal, new Rect(0f, 0f, UI.screenWidth, UI.screenHeight), SpaceBetweenColonistsHorizontal, entry.extraDraggedItemOnGUI);
- }
- cachedReorderableGroups[i] = value;
- }
- bool reordering;
- if (entry.pawn != null)
- {
- drawer.HandleClicks(rect, entry.pawn, cachedReorderableGroups[i], out reordering);
- }
- else
- {
- reordering = false;
- }
- if (Event.current.type != EventType.Repaint)
- {
- continue;
- }
- if (flag && showGroupFrames)
- {
- drawer.DrawGroupFrame(entry.group);
- }
- if (entry.pawn != null)
- {
- drawer.DrawColonist(rect, entry.pawn, entry.map, colonistsToHighlight.Contains(entry.pawn), reordering);
- ThingWithComps thingWithComps = entry.pawn.equipment?.Primary;
- if ((Prefs.ShowWeaponsUnderPortraitMode == ShowWeaponsUnderPortraitMode.Always || (Prefs.ShowWeaponsUnderPortraitMode == ShowWeaponsUnderPortraitMode.WhileDrafted && entry.pawn.Drafted)) && thingWithComps != null && thingWithComps.def.IsWeapon)
- {
- Widgets.ThingIcon(new Rect(rect.x, rect.y + rect.height * 1.05f, rect.width, rect.height).ScaledBy(0.75f), thingWithComps, 1f, null, stackOfOne: true);
- }
- }
- }
- num = -1;
- if (showGroupFrames)
- {
- for (int j = 0; j < cachedDrawLocs.Count; j++)
- {
- Entry entry2 = entries[j];
- bool num2 = num != entry2.group;
- num = entry2.group;
- if (num2)
- {
- drawer.HandleGroupFrameClicks(entry2.group);
- }
- }
- }
- }
- if (Event.current.type == EventType.Repaint)
- {
- colonistsToHighlight.Clear();
- }
- }
-
- private void CheckRecacheEntries()
- {
- if (!entriesDirty)
- {
- return;
- }
- entriesDirty = false;
- cachedEntries.Clear();
- int num = 0;
- if (Find.PlaySettings.showColonistBar)
- {
- tmpMaps.Clear();
- tmpMaps.AddRange(Find.Maps);
- tmpMaps.SortBy((Map x) => !x.IsPlayerHome, (Map x) => x.uniqueID);
- for (int i = 0; i < tmpMaps.Count; i++)
- {
- tmpPawns.Clear();
- tmpPawns.AddRange(tmpMaps[i].mapPawns.FreeColonists);
- tmpPawns.AddRange(tmpMaps[i].mapPawns.ColonySubhumansControllable);
- List list = tmpMaps[i].listerThings.ThingsInGroup(ThingRequestGroup.Corpse);
- for (int j = 0; j < list.Count; j++)
- {
- if (!list[j].IsDessicated())
- {
- Pawn innerPawn = ((Corpse)list[j]).InnerPawn;
- if (innerPawn != null && innerPawn.IsColonist)
- {
- tmpPawns.Add(innerPawn);
- }
- }
- }
- IReadOnlyList allPawnsSpawned = tmpMaps[i].mapPawns.AllPawnsSpawned;
- for (int k = 0; k < allPawnsSpawned.Count; k++)
- {
- if (allPawnsSpawned[k].carryTracker.CarriedThing is Corpse corpse && !corpse.IsDessicated() && corpse.InnerPawn.IsColonist)
- {
- tmpPawns.Add(corpse.InnerPawn);
- }
- }
- foreach (Pawn tmpPawn in tmpPawns)
- {
- if (tmpPawn.playerSettings.displayOrder == -9999999)
- {
- tmpPawn.playerSettings.displayOrder = Mathf.Max(tmpPawns.MaxBy((Pawn p) => p.playerSettings.displayOrder).playerSettings.displayOrder, 0) + 1;
- }
- }
- PlayerPawnsDisplayOrderUtility.Sort(tmpPawns);
- foreach (Pawn tmpPawn2 in tmpPawns)
- {
- cachedEntries.Add(new Entry(tmpPawn2, tmpMaps[i], num));
- }
- if (!tmpPawns.Any())
- {
- cachedEntries.Add(new Entry(null, tmpMaps[i], num));
- }
- num++;
- }
- tmpCaravans.Clear();
- tmpCaravans.AddRange(Find.WorldObjects.Caravans);
- tmpCaravans.SortBy((Caravan x) => x.ID);
- for (int l = 0; l < tmpCaravans.Count; l++)
- {
- if (!tmpCaravans[l].IsPlayerControlled)
- {
- continue;
- }
- tmpPawns.Clear();
- tmpPawns.AddRange(tmpCaravans[l].PawnsListForReading);
- PlayerPawnsDisplayOrderUtility.Sort(tmpPawns);
- for (int m = 0; m < tmpPawns.Count; m++)
- {
- if (tmpPawns[m].IsColonist || tmpPawns[m].IsColonySubhumanPlayerControlled)
- {
- cachedEntries.Add(new Entry(tmpPawns[m], null, num));
- }
- }
- num++;
- }
- }
- cachedReorderableGroups.Clear();
- foreach (Entry cachedEntry in cachedEntries)
- {
- _ = cachedEntry;
- cachedReorderableGroups.Add(-1);
- }
- drawer.Notify_RecachedEntries();
- tmpPawns.Clear();
- tmpMaps.Clear();
- tmpCaravans.Clear();
- drawLocsFinder.CalculateDrawLocs(cachedDrawLocs, out cachedScale, num);
- }
-
- public float GetEntryRectAlpha(Rect rect)
- {
- if (Messages.CollidesWithAnyMessage(rect, out var messageAlpha))
- {
- return Mathf.Lerp(1f, 0.2f, messageAlpha);
- }
- return 1f;
- }
-
- public void Highlight(Pawn pawn)
- {
- if (Visible && !colonistsToHighlight.Contains(pawn))
- {
- colonistsToHighlight.Add(pawn);
- }
- }
-
- public void Reorder(int from, int to, int entryGroup)
- {
- int num = 0;
- Pawn pawn = null;
- Pawn pawn2 = null;
- Pawn pawn3 = null;
- for (int i = 0; i < cachedEntries.Count; i++)
- {
- if (cachedEntries[i].group == entryGroup && cachedEntries[i].pawn != null)
- {
- if (num == from)
- {
- pawn = cachedEntries[i].pawn;
- }
- if (num == to)
- {
- pawn2 = cachedEntries[i].pawn;
- }
- pawn3 = cachedEntries[i].pawn;
- num++;
- }
- }
- if (pawn == null)
- {
- return;
- }
- int num2 = pawn2?.playerSettings.displayOrder ?? (pawn3.playerSettings.displayOrder + 1);
- for (int j = 0; j < cachedEntries.Count; j++)
- {
- Pawn pawn4 = cachedEntries[j].pawn;
- if (pawn4 == null)
- {
- continue;
- }
- if (pawn4.playerSettings.displayOrder == num2)
- {
- if (pawn2 != null && cachedEntries[j].group == entryGroup)
- {
- pawn4.playerSettings.displayOrder++;
- }
- }
- else if (pawn4.playerSettings.displayOrder > num2)
- {
- pawn4.playerSettings.displayOrder++;
- }
- else
- {
- pawn4.playerSettings.displayOrder--;
- }
- }
- pawn.playerSettings.displayOrder = num2;
- MarkColonistsDirty();
- MainTabWindowUtility.NotifyAllPawnTables_PawnsChanged();
- }
-
- public void DrawColonistMouseAttachment(int index, Vector2 dragStartPos, int entryGroup)
- {
- Pawn pawn = null;
- Vector2 vector = default(Vector2);
- int num = 0;
- for (int i = 0; i < cachedEntries.Count; i++)
- {
- if (cachedEntries[i].group == entryGroup && cachedEntries[i].pawn != null)
- {
- if (num == index)
- {
- pawn = cachedEntries[i].pawn;
- vector = cachedDrawLocs[i];
- break;
- }
- num++;
- }
- }
- if (pawn != null)
- {
- RenderTexture iconTex = PortraitsCache.Get(pawn, ColonistBarColonistDrawer.PawnTextureSize, Rot4.South, ColonistBarColonistDrawer.PawnTextureCameraOffset, 1.28205f);
- Rect rect = new Rect(vector.x, vector.y, Size.x, Size.y);
- Rect pawnTextureRect = drawer.GetPawnTextureRect(rect.position);
- pawnTextureRect.position += Event.current.mousePosition - dragStartPos;
- Rect? customRect = pawnTextureRect;
- GenUI.DrawMouseAttachment(iconTex, "", 0f, default(Vector2), customRect);
- }
- }
-
- public bool AnyColonistOrCorpseAt(Vector2 pos)
- {
- if (!TryGetEntryAt(pos, out var entry))
- {
- return false;
- }
- return entry.pawn != null;
- }
-
- public bool TryGetEntryAt(Vector2 pos, out Entry entry)
- {
- List drawLocs = DrawLocs;
- List entries = Entries;
- Vector2 size = Size;
- for (int i = 0; i < drawLocs.Count; i++)
- {
- if (new Rect(drawLocs[i].x, drawLocs[i].y, size.x, size.y).Contains(pos))
- {
- entry = entries[i];
- return true;
- }
- }
- entry = default(Entry);
- return false;
- }
-
- public List GetColonistsInOrder()
- {
- List entries = Entries;
- tmpColonistsInOrder.Clear();
- for (int i = 0; i < entries.Count; i++)
- {
- if (entries[i].pawn != null)
- {
- tmpColonistsInOrder.Add(entries[i].pawn);
- }
- }
- return tmpColonistsInOrder;
- }
-
- public List ColonistsOrCorpsesInScreenRect(Rect rect)
- {
- List drawLocs = DrawLocs;
- List entries = Entries;
- Vector2 size = Size;
- tmpColonistsWithMap.Clear();
- for (int i = 0; i < drawLocs.Count; i++)
- {
- if (rect.Overlaps(new Rect(drawLocs[i].x, drawLocs[i].y, size.x, size.y)))
- {
- Pawn pawn = entries[i].pawn;
- if (pawn != null)
- {
- Thing first = ((!pawn.Dead || pawn.Corpse == null || !pawn.Corpse.SpawnedOrAnyParentSpawned) ? ((Thing)pawn) : ((Thing)pawn.Corpse));
- tmpColonistsWithMap.Add(new Pair(first, entries[i].map));
- }
- }
- }
- if (WorldRendererUtility.WorldSelected && tmpColonistsWithMap.Any((Pair x) => x.Second == null))
- {
- tmpColonistsWithMap.RemoveAll((Pair x) => x.Second != null);
- }
- else if (tmpColonistsWithMap.Any((Pair x) => x.Second == Find.CurrentMap))
- {
- tmpColonistsWithMap.RemoveAll((Pair x) => x.Second != Find.CurrentMap);
- }
- tmpColonists.Clear();
- for (int j = 0; j < tmpColonistsWithMap.Count; j++)
- {
- tmpColonists.Add(tmpColonistsWithMap[j].First);
- }
- tmpColonistsWithMap.Clear();
- return tmpColonists;
- }
-
- public List MapColonistsOrCorpsesInScreenRect(Rect rect)
- {
- tmpMapColonistsOrCorpsesInScreenRect.Clear();
- if (!Visible)
- {
- return tmpMapColonistsOrCorpsesInScreenRect;
- }
- List list = ColonistsOrCorpsesInScreenRect(rect);
- for (int i = 0; i < list.Count; i++)
- {
- if (list[i].Spawned)
- {
- tmpMapColonistsOrCorpsesInScreenRect.Add(list[i]);
- }
- }
- return tmpMapColonistsOrCorpsesInScreenRect;
- }
-
- public List CaravanMembersInScreenRect(Rect rect)
- {
- tmpCaravanPawns.Clear();
- if (!Visible)
- {
- return tmpCaravanPawns;
- }
- List list = ColonistsOrCorpsesInScreenRect(rect);
- for (int i = 0; i < list.Count; i++)
- {
- if (list[i] is Pawn pawn && pawn.IsCaravanMember())
- {
- tmpCaravanPawns.Add(pawn);
- }
- }
- return tmpCaravanPawns;
- }
-
- public List CaravanMembersCaravansInScreenRect(Rect rect)
- {
- tmpCaravans.Clear();
- if (!Visible)
- {
- return tmpCaravans;
- }
- List list = CaravanMembersInScreenRect(rect);
- for (int i = 0; i < list.Count; i++)
- {
- tmpCaravans.Add(list[i].GetCaravan());
- }
- return tmpCaravans;
- }
-
- public Caravan CaravanMemberCaravanAt(Vector2 at)
- {
- if (!Visible)
- {
- return null;
- }
- if (ColonistOrCorpseAt(at) is Pawn pawn && pawn.IsCaravanMember())
- {
- return pawn.GetCaravan();
- }
- return null;
- }
-
- public Thing ColonistOrCorpseAt(Vector2 pos)
- {
- if (!Visible)
- {
- return null;
- }
- if (!TryGetEntryAt(pos, out var entry))
- {
- return null;
- }
- Pawn pawn = entry.pawn;
- if (pawn != null && pawn.Dead && pawn.Corpse != null && pawn.Corpse.SpawnedOrAnyParentSpawned)
- {
- return pawn.Corpse;
- }
- return pawn;
- }
-}
-```
\ No newline at end of file
diff --git a/MCP/vector_cache/CompBiosculpterPod-CompProperties_BiosculpterPod.txt b/MCP/vector_cache/CompBiosculpterPod-CompProperties_BiosculpterPod.txt
deleted file mode 100644
index d14fb0bc..00000000
--- a/MCP/vector_cache/CompBiosculpterPod-CompProperties_BiosculpterPod.txt
+++ /dev/null
@@ -1,1485 +0,0 @@
-根据向量相似度分析,与 'CompProperties_BiosculpterPod, CompBiosculpterPod' 最相关的代码定义如下:
-
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompProperties_BiosculpterPod.txt`
-
-```csharp
-public class CompProperties_BiosculpterPod : CompProperties
-{
- public SoundDef enterSound;
-
- public SoundDef exitSound;
-
- public EffecterDef operatingEffecter;
-
- public EffecterDef readyEffecter;
-
- public Color selectCycleColor;
-
- public float biotunedCycleSpeedFactor;
-
- public CompProperties_BiosculpterPod()
- {
- compClass = typeof(CompBiosculpterPod);
- }
-
- public override IEnumerable ConfigErrors(ThingDef parentDef)
- {
- foreach (string item in base.ConfigErrors(parentDef))
- {
- yield return item;
- }
- if (parentDef.tickerType != TickerType.Normal)
- {
- yield return GetType().Name + " requires parent ticker type Normal";
- }
- }
-}
-```
----
-**文件路径 (精确匹配):** `C:\Steam\steamapps\common\RimWorld\Data\dll1.6\RimWorld\CompBiosculpterPod.txt`
-
-```csharp
-public class CompBiosculpterPod : ThingComp, ISuspendableThingHolder, IThingHolder, IThingHolderWithDrawnPawn, IStoreSettingsParent, INotifyHauledTo, ISearchableContents
-{
- private const int NoPowerEjectCumulativeTicks = 60000;
-
- private const int BiotunedDuration = 4800000;
-
- private const float NutritionRequired = 5f;
-
- private const float CacheForSecs = 2f;
-
- private static readonly Texture2D InterruptCycleIcon = ContentFinder.Get("UI/Designators/Cancel");
-
- private static readonly Material BackgroundMat = SolidColorMaterials.NewSolidColorMaterial(new Color(0.082f, 0.078f, 0.063f), ShaderDatabase.SolidColorBehind);
-
- private const float BackgroundRect_YOff = 0.07317074f;
-
- private const float Pawn_YOff = 0.03658537f;
-
- private string currentCycleKey;
-
- private float currentCycleTicksRemaining;
-
- private int currentCyclePowerCutTicks;
-
- private ThingOwner innerContainer;
-
- private Pawn biotunedTo;
-
- private int biotunedCountdownTicks;
-
- private StorageSettings allowedNutritionSettings;
-
- private float liquifiedNutrition;
-
- public bool autoLoadNutrition = true;
-
- public bool devFillPodLatch;
-
- private bool autoAgeReversal;
-
- private int tickEntered = -99999;
-
- public Job queuedEnterJob;
-
- public Pawn queuedPawn;
-
- private List chosenExtraItems = new List();
-
- private List cycleEligiblePawnOptions = new List();
-
- private Pawn pawnEnteringBiosculpter;
-
- private Dictionary> cachedExtraIngredients = new Dictionary>();
-
- private Dictionary cachedAnyPawnEligible = new Dictionary();
-
- private static Dictionary> cachedBiotunedPods = new Dictionary>();
-
- private Pawn cacheReachIngredientsPawn;
-
- private CompBiosculpterPod_Cycle cacheReachIngredientsCycle;
-
- private float cacheReachIngredientsTime = float.MinValue;
-
- private bool cacheReachIngredientsResult;
-
- private Effecter progressBarEffecter;
-
- private Effecter operatingEffecter;
-
- private Effecter readyEffecter;
-
- private Texture2D cachedAutoAgeReverseIcon;
-
- private List cachedAvailableCycles;
-
- private Dictionary cycleLookup;
-
- private static string cachedAgeReversalCycleKey = null;
-
- private List tmpIngredientsStrings = new List();
-
- private static readonly List tmpItems = new List();
-
- private CompPowerTrader powerTraderComp;
-
- private CompPower powerComp;
-
- private static List cachedPodDefs;
-
- public CompProperties_BiosculpterPod Props => props as CompProperties_BiosculpterPod;
-
- public ThingOwner SearchableContents => innerContainer;
-
- public bool IsContentsSuspended => true;
-
- public float RequiredNutritionRemaining => Mathf.Max(5f - liquifiedNutrition, 0f);
-
- public bool NutritionLoaded => RequiredNutritionRemaining <= 0f;
-
- public bool AutoAgeReversal => autoAgeReversal;
-
- private Texture2D AutoAgeReversalIcon
- {
- get
- {
- if (cachedAutoAgeReverseIcon == null)
- {
- cachedAutoAgeReverseIcon = ContentFinder.Get("UI/Gizmos/BiosculpterAutoAgeReversal");
- }
- return cachedAutoAgeReverseIcon;
- }
- }
-
- public BiosculpterPodState State
- {
- get
- {
- if (Occupant != null)
- {
- return BiosculpterPodState.Occupied;
- }
- if (NutritionLoaded)
- {
- return BiosculpterPodState.SelectingCycle;
- }
- return BiosculpterPodState.LoadingNutrition;
- }
- }
-
- public Pawn Occupant
- {
- get
- {
- if (pawnEnteringBiosculpter != null)
- {
- return pawnEnteringBiosculpter;
- }
- if (currentCycleKey == null)
- {
- return null;
- }
- if (innerContainer.Count != 1)
- {
- return null;
- }
- return innerContainer[0] as Pawn;
- }
- }
-
- public CompBiosculpterPod_Cycle CurrentCycle
- {
- get
- {
- if (currentCycleKey == null)
- {
- return null;
- }
- foreach (CompBiosculpterPod_Cycle availableCycle in AvailableCycles)
- {
- if (availableCycle.Props.key == currentCycleKey)
- {
- return availableCycle;
- }
- }
- return null;
- }
- }
-
- public List AvailableCycles
- {
- get
- {
- if (cachedAvailableCycles == null)
- {
- SetupCycleCaches();
- }
- return cachedAvailableCycles;
- }
- }
-
- public string AgeReversalCycleKey
- {
- get
- {
- if (cachedAgeReversalCycleKey == null)
- {
- SetupCycleCaches();
- }
- return cachedAgeReversalCycleKey;
- }
- }
-
- private float CycleSpeedFactorNoPawn => CleanlinessSpeedFactor * BiotunedSpeedFactor;
-
- public float CycleSpeedFactor
- {
- get
- {
- if (Occupant == null)
- {
- return Mathf.Max(0.1f, CycleSpeedFactorNoPawn);
- }
- return GetCycleSpeedFactorForPawn(Occupant);
- }
- }
-
- private float CleanlinessSpeedFactor => parent.GetStatValue(StatDefOf.BiosculpterPodSpeedFactor);
-
- private float BiotunedSpeedFactor
- {
- get
- {
- if (biotunedTo == null)
- {
- return 1f;
- }
- return Props.biotunedCycleSpeedFactor;
- }
- }
-
- public bool PowerOn => parent.TryGetComp().PowerOn;
-
- public float HeldPawnDrawPos_Y => parent.DrawPos.y - 0.03658537f;
-
- public float HeldPawnBodyAngle => parent.Rotation.Opposite.AsAngle;
-
- public PawnPosture HeldPawnPosture => PawnPosture.LayingOnGroundFaceUp;
-
- public bool StorageTabVisible => true;
-
- public CompBiosculpterPod()
- {
- innerContainer = new ThingOwner(this);
- }
-
- public override void Initialize(CompProperties props)
- {
- base.Initialize(props);
- allowedNutritionSettings = new StorageSettings(this);
- if (parent.def.building.defaultStorageSettings != null)
- {
- allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings);
- }
- }
-
- public override void PostSpawnSetup(bool respawningAfterLoad)
- {
- if (ModLister.CheckIdeology("Biosculpter pod comp"))
- {
- base.PostSpawnSetup(respawningAfterLoad);
- }
- }
-
- public override void PostExposeData()
- {
- base.PostExposeData();
- Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
- Scribe_Values.Look(ref currentCycleKey, "currentCycleKey");
- Scribe_Values.Look(ref currentCycleTicksRemaining, "currentCycleTicksRemaining", 0f);
- Scribe_Values.Look(ref currentCyclePowerCutTicks, "currentCyclePowerCutTicks", 0);
- Scribe_References.Look(ref biotunedTo, "biotunedTo");
- Scribe_Values.Look(ref biotunedCountdownTicks, "biotunedCountdownTicks", 0);
- Scribe_Deep.Look(ref allowedNutritionSettings, "allowedNutritionSettings");
- Scribe_Values.Look(ref liquifiedNutrition, "liquifiedNutrition", 0f);
- Scribe_Values.Look(ref autoLoadNutrition, "autoLoadNutrition", defaultValue: false);
- Scribe_Values.Look(ref devFillPodLatch, "devFillPodLatch", defaultValue: false);
- Scribe_Values.Look(ref autoAgeReversal, "autoAgeReversal", defaultValue: false);
- Scribe_Values.Look(ref tickEntered, "tickEntered", 0);
- Scribe_References.Look(ref queuedEnterJob, "queuedEnterJob");
- Scribe_References.Look(ref queuedPawn, "queuedPawn");
- if (allowedNutritionSettings == null)
- {
- allowedNutritionSettings = new StorageSettings(this);
- if (parent.def.building.defaultStorageSettings != null)
- {
- allowedNutritionSettings.CopyFrom(parent.def.building.defaultStorageSettings);
- }
- }
- if (Scribe.mode == LoadSaveMode.PostLoadInit)
- {
- if (currentCycleKey == "healing")
- {
- currentCycleKey = "medic";
- }
- if (biotunedTo != null)
- {
- SetBiotuned(biotunedTo);
- }
- LiquifyNutrition();
- }
- }
-
- public CompBiosculpterPod_Cycle GetCycle(string key)
- {
- if (cycleLookup == null)
- {
- SetupCycleCaches();
- }
- return cycleLookup[key];
- }
-
- public float GetCycleSpeedFactorForPawn(Pawn p)
- {
- return Mathf.Max(0.1f, CycleSpeedFactorNoPawn * p.GetStatValue(StatDefOf.BiosculpterOccupantSpeed));
- }
-
- private void SetupCycleCaches()
- {
- cachedAvailableCycles = new List();
- cachedAvailableCycles.AddRange(parent.AllComps.OfType());
- cycleLookup = new Dictionary();
- foreach (CompBiosculpterPod_Cycle cachedAvailableCycle in cachedAvailableCycles)
- {
- if (cachedAvailableCycle is CompBiosculpterPod_AgeReversalCycle compBiosculpterPod_AgeReversalCycle)
- {
- cachedAgeReversalCycleKey = compBiosculpterPod_AgeReversalCycle.Props.key;
- }
- cycleLookup[cachedAvailableCycle.Props.key] = cachedAvailableCycle;
- }
- }
-
- public void SetBiotuned(Pawn newBiotunedTo)
- {
- if (newBiotunedTo != biotunedTo)
- {
- autoAgeReversal = false;
- }
- if (biotunedTo != null && cachedBiotunedPods.ContainsKey(biotunedTo))
- {
- cachedBiotunedPods[biotunedTo].Remove(this);
- }
- if (newBiotunedTo != null && !cachedBiotunedPods.ContainsKey(newBiotunedTo))
- {
- cachedBiotunedPods[newBiotunedTo] = new List();
- }
- if (newBiotunedTo != null && !cachedBiotunedPods[newBiotunedTo].Contains(this))
- {
- cachedBiotunedPods[newBiotunedTo].Add(this);
- }
- if (newBiotunedTo != null && newBiotunedTo != biotunedTo)
- {
- biotunedCountdownTicks = 4800000;
- }
- biotunedTo = newBiotunedTo;
- }
-
- public override void PostDestroy(DestroyMode mode, Map previousMap)
- {
- SetBiotuned(null);
- if (mode == DestroyMode.Deconstruct || mode == DestroyMode.KillFinalize)
- {
- EjectContents(interrupted: true, playSounds: false, previousMap);
- }
- innerContainer.ClearAndDestroyContents();
- base.PostDestroy(mode, previousMap);
- }
-
- public override void PostDeSpawn(Map map, DestroyMode mode = DestroyMode.Vanish)
- {
- if (mode != DestroyMode.WillReplace)
- {
- EjectContents(interrupted: true, playSounds: false, map);
- currentCycleKey = null;
- }
- progressBarEffecter?.Cleanup();
- progressBarEffecter = null;
- operatingEffecter?.Cleanup();
- operatingEffecter = null;
- readyEffecter?.Cleanup();
- readyEffecter = null;
- }
-
- public override void DrawGUIOverlay()
- {
- base.DrawGUIOverlay();
- if (!Find.ScreenshotModeHandler.Active && (biotunedTo != null || Occupant != null))
- {
- GenMapUI.DrawThingLabel(parent, biotunedTo?.LabelShort ?? Occupant.LabelShort, GenMapUI.DefaultThingLabelColor);
- }
- }
-
- public override string CompInspectStringExtra()
- {
- StringBuilder stringBuilder = new StringBuilder();
- BiosculpterPodState state = State;
- if (parent.Spawned)
- {
- CompBiosculpterPod_Cycle currentCycle = CurrentCycle;
- if (currentCycle != null)
- {
- stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterPodCycleLabel".Translate()).Append(": ")
- .Append(currentCycle.Props.LabelCap);
- if (biotunedTo == null)
- {
- stringBuilder.Append(" " + "BiosculpterPodCycleWillBiotune".Translate());
- }
- }
- else if (state == BiosculpterPodState.SelectingCycle)
- {
- if (PowerOn)
- {
- if (queuedEnterJob != null && !queuedEnterJob.biosculpterCycleKey.NullOrEmpty())
- {
- stringBuilder.Append("BiosculpterPodCycleStandby".Translate(GetCycle(queuedEnterJob.biosculpterCycleKey).Props.label.Named("CYCLE"), queuedPawn.Named("PAWN")));
- }
- else
- {
- stringBuilder.Append("BiosculpterPodCycleSelection".Translate().CapitalizeFirst());
- }
- }
- else
- {
- stringBuilder.Append("BiosculpterPodCycleSelectionNoPower".Translate().CapitalizeFirst());
- }
- }
- if (state == BiosculpterPodState.LoadingNutrition)
- {
- stringBuilder.Append("BiosculpterPodCycleLabelLoading".Translate().CapitalizeFirst());
- stringBuilder.AppendLineIfNotEmpty().Append("Nutrition".Translate()).Append(": ")
- .Append(liquifiedNutrition.ToStringByStyle(ToStringStyle.FloatMaxOne))
- .Append(" / ")
- .Append(5f);
- }
- if (state == BiosculpterPodState.Occupied)
- {
- float num = currentCycleTicksRemaining / CycleSpeedFactor;
- stringBuilder.AppendLineIfNotEmpty().Append("Contains".Translate()).Append(": ")
- .Append(Occupant.NameShortColored.Resolve());
- if (!PowerOn)
- {
- stringBuilder.AppendLine().Append("BiosculpterCycleNoPowerInterrupt".Translate((60000 - currentCyclePowerCutTicks).ToStringTicksToPeriod().Named("TIME")).Colorize(ColorLibrary.RedReadable));
- }
- stringBuilder.AppendLine().Append("BiosculpterCycleTimeRemaining".Translate()).Append(": ")
- .Append(((int)num).ToStringTicksToPeriod().Colorize(ColoredText.DateTimeColor));
- Ideo ideo = Occupant.Ideo;
- if (ideo != null && ideo.HasPrecept(PreceptDefOf.Biosculpting_Accelerated))
- {
- stringBuilder.Append(" (" + "BiosculpterCycleAccelerated".Translate() + ")");
- }
- if (biotunedTo != null)
- {
- stringBuilder.AppendLine().Append("BiosculpterBiotunedSpeedFactor".Translate()).Append(": ")
- .Append(BiotunedSpeedFactor.ToStringPercent());
- }
- stringBuilder.AppendLine().Append("BiosculpterCleanlinessSpeedFactor".Translate()).Append(": ")
- .Append(CleanlinessSpeedFactor.ToStringPercent());
- }
- }
- if (biotunedTo != null && state != BiosculpterPodState.Occupied)
- {
- stringBuilder.AppendLineIfNotEmpty().Append("BiosculpterBiotunedTo".Translate()).Append(": ")
- .Append(biotunedTo.LabelShort)
- .Append(" (")
- .Append(biotunedCountdownTicks.ToStringTicksToPeriod())
- .Append(")");
- }
- if (stringBuilder.Length <= 0)
- {
- return null;
- }
- return stringBuilder.ToString();
- }
-
- public override IEnumerable CompGetGizmosExtra()
- {
- BiosculpterPodState state = State;
- string cycleIndependentCannotUseReason = CannotUseNowReason();
- foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles)
- {
- string text = cycleIndependentCannotUseReason ?? CannotUseNowCycleReason(cycle);
- Command_Action command_Action = new Command_Action();
- command_Action.defaultLabel = "BiosculpterPodCycleCommand".Translate(cycle.Props.label) + ((biotunedTo != null) ? (" (" + biotunedTo.LabelShort + ")") : "");
- command_Action.defaultDesc = CycleDescription(cycle);
- command_Action.icon = cycle.Props.Icon;
- command_Action.action = delegate
- {
- SelectPawnsForCycleOptions(cycle, out var options2);
- if (biotunedTo != null && options2.Count > 0)
- {
- options2[0].action();
- if (!(cycle is CompBiosculpterPod_HealingCycle))
- {
- Messages.Message("BiosculpterEnteringMessage".Translate(biotunedTo.Named("PAWN"), cycle.Props.label.Named("CYCLE")).CapitalizeFirst(), parent, MessageTypeDefOf.SilentInput, historical: false);
- }
- }
- else
- {
- Find.WindowStack.Add(new FloatMenu(options2));
- }
- };
- command_Action.activateSound = SoundDefOf.Tick_Tiny;
- command_Action.Disabled = text != null;
- List options;
- if (text != null)
- {
- command_Action.Disable(text);
- }
- else if (!SelectPawnsForCycleOptions(cycle, out options, shortCircuit: true))
- {
- command_Action.Disable((biotunedTo != null) ? "BiosculpterNoEligiblePawnsBiotuned".Translate(biotunedTo.Named("PAWN")) : "BiosculpterNoEligiblePawns".Translate());
- }
- yield return command_Action;
- }
- if (state == BiosculpterPodState.Occupied)
- {
- Command_Action command_Action2 = new Command_Action();
- command_Action2.defaultLabel = "BiosculpterInteruptCycle".Translate();
- command_Action2.defaultDesc = "BiosculpterInteruptCycleDesc".Translate();
- command_Action2.icon = InterruptCycleIcon;
- command_Action2.action = delegate
- {
- EjectContents(interrupted: true, playSounds: true);
- };
- command_Action2.activateSound = SoundDefOf.Designate_Cancel;
- yield return command_Action2;
- }
- Command_Toggle command_Toggle = new Command_Toggle();
- command_Toggle.defaultLabel = "BiosculpterAutoLoadNutritionLabel".Translate();
- command_Toggle.defaultDesc = "BiosculpterAutoLoadNutritionDescription".Translate();
- command_Toggle.icon = (autoLoadNutrition ? TexCommand.ForbidOff : TexCommand.ForbidOn);
- command_Toggle.isActive = () => autoLoadNutrition;
- command_Toggle.toggleAction = delegate
- {
- autoLoadNutrition = !autoLoadNutrition;
- };
- yield return command_Toggle;
- if ((biotunedTo?.Ideo?.HasPrecept(PreceptDefOf.AgeReversal_Demanded)).GetValueOrDefault())
- {
- Command_Toggle command_Toggle2 = new Command_Toggle();
- command_Toggle2.defaultLabel = "BiosculpterAutoAgeReversalLabel".Translate(biotunedTo.Named("PAWN"));
- TaggedString taggedString = ((biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks > 0) ? "BiosculpterAutoAgeReversalDescriptionFuture".Translate(biotunedTo.Named("PAWN"), ((int)biotunedTo.ageTracker.AgeReversalDemandedDeadlineTicks).ToStringTicksToPeriodVague().Named("TIME")) : "BiosculpterAutoAgeReversalDescriptionNow".Translate(biotunedTo.Named("PAWN")));
- command_Toggle2.defaultDesc = "BiosculpterAutoAgeReversalDescription".Translate(biotunedTo.Named("PAWN"), taggedString.Named("NEXTTREATMENT"));
- command_Toggle2.icon = AutoAgeReversalIcon;
- command_Toggle2.isActive = () => AutoAgeReversal;
- command_Toggle2.toggleAction = delegate
- {
- autoAgeReversal = !autoAgeReversal;
- };
- if (!CanAgeReverse(biotunedTo))
- {
- command_Toggle2.Disable("UnderMinBiosculpterAgeReversalAge".Translate(biotunedTo.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst());
- autoAgeReversal = false;
- }
- yield return command_Toggle2;
- }
- foreach (Gizmo item in StorageSettingsClipboard.CopyPasteGizmosFor(allowedNutritionSettings))
- {
- yield return item;
- }
- Gizmo gizmo = Building.SelectContainedItemGizmo(parent, Occupant);
- if (gizmo != null)
- {
- yield return gizmo;
- }
- if (DebugSettings.ShowDevGizmos)
- {
- yield return new Command_Action
- {
- defaultLabel = "DEV: complete cycle",
- action = delegate
- {
- currentCycleTicksRemaining = 10f;
- },
- Disabled = (State != BiosculpterPodState.Occupied)
- };
- yield return new Command_Action
- {
- defaultLabel = "DEV: advance cycle +1 day",
- action = delegate
- {
- currentCycleTicksRemaining -= 60000f;
- },
- Disabled = (State != BiosculpterPodState.Occupied)
- };
- yield return new Command_Action
- {
- defaultLabel = "DEV: complete biotune timer",
- action = delegate
- {
- biotunedCountdownTicks = 10;
- },
- Disabled = (biotunedCountdownTicks <= 0)
- };
- yield return new Command_Action
- {
- defaultLabel = "DEV: fill nutrition and cycle ingredients",
- action = delegate
- {
- liquifiedNutrition = 5f;
- devFillPodLatch = true;
- },
- Disabled = (State == BiosculpterPodState.Occupied || (devFillPodLatch && liquifiedNutrition == 5f))
- };
- }
- }
-
- private string IngredientsDescription(CompBiosculpterPod_Cycle cycle)
- {
- tmpIngredientsStrings.Clear();
- if (!cycle.Props.extraRequiredIngredients.NullOrEmpty() && !devFillPodLatch)
- {
- for (int i = 0; i < cycle.Props.extraRequiredIngredients.Count; i++)
- {
- tmpIngredientsStrings.Add(cycle.Props.extraRequiredIngredients[i].Summary);
- }
- }
- return tmpIngredientsStrings.ToCommaList(useAnd: true);
- }
-
- private string CycleDescription(CompBiosculpterPod_Cycle cycle)
- {
- StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.Append(cycle.Description(biotunedTo));
- float num = cycle.Props.durationDays / CycleSpeedFactor;
- float num2 = num / PreceptDefOf.Biosculpting_Accelerated.biosculpterPodCycleSpeedFactor;
- stringBuilder.AppendLine("\n\n" + "BiosculpterPodCycleDuration".Translate() + ": " + ((int)(num * 60000f)).ToStringTicksToDays());
- if (!Find.IdeoManager.classicMode)
- {
- stringBuilder.Append("BiosculpterPodCycleDurationTranshumanists".Translate() + ": " + ((int)(num2 * 60000f)).ToStringTicksToDays());
- }
- return stringBuilder.ToString();
- }
-
- public bool PawnCanUseNow(Pawn pawn, CompBiosculpterPod_Cycle cycle)
- {
- return (CannotUseNowReason() ?? CannotUseNowPawnReason(pawn) ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(pawn, cycle)) == null;
- }
-
- public override IEnumerable CompFloatMenuOptions(Pawn selPawn)
- {
- if (selPawn.IsQuestLodger())
- {
- yield return new FloatMenuOption("CannotEnter".Translate() + ": " + "CryptosleepCasketGuestsNotAllowed".Translate().CapitalizeFirst(), null);
- yield break;
- }
- string cycleIndependentfailureReason = CannotUseNowReason() ?? CannotUseNowPawnReason(selPawn);
- foreach (CompBiosculpterPod_Cycle cycle in AvailableCycles)
- {
- string text = cycleIndependentfailureReason ?? CannotUseNowCycleReason(cycle) ?? CannotUseNowPawnCycleReason(selPawn, cycle);
- if (text != null)
- {
- yield return new FloatMenuOption(CannotStartText(cycle, text), null);
- continue;
- }
- string label = "EnterBiosculpterPod".Translate(cycle.Props.label, ((int)(cycle.Props.durationDays / GetCycleSpeedFactorForPawn(selPawn) * 60000f)).ToStringTicksToDays());
- yield return FloatMenuUtility.DecoratePrioritizedTask(new FloatMenuOption(label, delegate
- {
- PrepareCycleJob(selPawn, selPawn, cycle, EnterBiosculpterJob());
- }), selPawn, parent);
- }
- }
-
- public static bool CanAgeReverse(Pawn biosculptee)
- {
- return biosculptee.ageTracker.Adult;
- }
-
- public static List BiotunedPods(Pawn pawn)
- {
- return cachedBiotunedPods.TryGetValue(pawn);
- }
-
- public static bool HasBiotunedAutoAgeReversePod(Pawn pawn)
- {
- List list = cachedBiotunedPods.TryGetValue(pawn);
- if (list == null)
- {
- return false;
- }
- foreach (CompBiosculpterPod item in list)
- {
- if (item.AutoAgeReversal)
- {
- return true;
- }
- }
- return false;
- }
-
- public static string CannotStartText(CompBiosculpterPod_Cycle cycle, string translatedReason)
- {
- return "BiosculpterCannotStartCycle".Translate(cycle.Props.label) + ": " + translatedReason.CapitalizeFirst();
- }
-
- public string CannotUseNowCycleReason(CompBiosculpterPod_Cycle cycle)
- {
- List list = cycle.MissingResearchLabels();
- if (list.Any())
- {
- return "MissingRequiredResearch".Translate() + " " + list.ToCommaList();
- }
- return null;
- }
-
- public string CannotUseNowPawnCycleReason(Pawn p, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true)
- {
- return CannotUseNowPawnCycleReason(p, p, cycle, checkIngredients);
- }
-
- private bool CanReachOrHasIngredients(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool useCache = false)
- {
- if (!PawnCarryingExtraCycleIngredients(biosculptee, cycle) && (biosculptee == hauler || !PawnCarryingExtraCycleIngredients(hauler, cycle)))
- {
- return CanReachRequiredIngredients(hauler, cycle, useCache);
- }
- return true;
- }
-
- public string CannotUseNowPawnCycleReason(Pawn hauler, Pawn biosculptee, CompBiosculpterPod_Cycle cycle, bool checkIngredients = true)
- {
- if (AgeReversalCycleKey != null && cycle.Props.key == AgeReversalCycleKey && !CanAgeReverse(biosculptee))
- {
- return "UnderMinBiosculpterAgeReversalAge".Translate(biosculptee.ageTracker.AdultMinAge.Named("ADULTAGE")).CapitalizeFirst();
- }
- if (checkIngredients && !CanReachOrHasIngredients(hauler, biosculptee, cycle, useCache: true))
- {
- return "BiosculpterMissingIngredients".Translate(IngredientsDescription(cycle).Named("INGREDIENTS")).CapitalizeFirst();
- }
- return null;
- }
-
- public string CannotUseNowPawnReason(Pawn p)
- {
- if (biotunedTo != null && biotunedTo != p)
- {
- return "BiosculpterBiotunedToAnother".Translate().CapitalizeFirst();
- }
- if (!p.CanReach(parent, PathEndMode.InteractionCell, Danger.Deadly))
- {
- return "NoPath".Translate().CapitalizeFirst();
- }
- return null;
- }
-
- public string CannotUseNowReason()
- {
- if (!PowerOn)
- {
- return "NoPower".Translate().CapitalizeFirst();
- }
- if (State == BiosculpterPodState.LoadingNutrition)
- {
- return "BiosculpterNutritionNotLoaded".Translate().CapitalizeFirst();
- }
- if (State == BiosculpterPodState.Occupied)
- {
- return "BiosculpterOccupied".Translate().CapitalizeFirst();
- }
- return null;
- }
-
- private List RequiredIngredients(CompBiosculpterPod_Cycle cycle)
- {
- List extraRequiredIngredients = cycle.Props.extraRequiredIngredients;
- if (extraRequiredIngredients == null || devFillPodLatch)
- {
- return null;
- }
- if (!cachedExtraIngredients.ContainsKey(cycle))
- {
- cachedExtraIngredients[cycle] = extraRequiredIngredients.Select((ThingDefCountClass tc) => tc.ToIngredientCount()).ToList();
- }
- return cachedExtraIngredients[cycle];
- }
-
- private bool CanReachRequiredIngredients(Pawn pawn, CompBiosculpterPod_Cycle cycle, bool useCache = false)
- {
- chosenExtraItems.Clear();
- if (cycle.Props.extraRequiredIngredients == null || devFillPodLatch)
- {
- return true;
- }
- float realtimeSinceStartup = Time.realtimeSinceStartup;
- if (useCache && cacheReachIngredientsPawn == pawn && cacheReachIngredientsCycle == cycle && realtimeSinceStartup < cacheReachIngredientsTime + 2f)
- {
- return cacheReachIngredientsResult;
- }
- cacheReachIngredientsPawn = pawn;
- cacheReachIngredientsCycle = cycle;
- cacheReachIngredientsTime = realtimeSinceStartup;
- cacheReachIngredientsResult = WorkGiver_DoBill.TryFindBestFixedIngredients(RequiredIngredients(cycle), pawn, parent, chosenExtraItems);
- return cacheReachIngredientsResult;
- }
-
- private bool SelectPawnCycleOption(Pawn pawn, CompBiosculpterPod_Cycle cycle, out FloatMenuOption option)
- {
- string text = CannotUseNowPawnReason(pawn) ?? CannotUseNowPawnCycleReason(pawn, cycle, checkIngredients: false);
- string label = pawn.Label + ((text == null) ? "" : (": " + text));
- Action action = null;
- if (text == null)
- {
- action = delegate
- {
- PrepareCycleJob(pawn, pawn, cycle, EnterBiosculpterJob());
- };
- }
- option = new FloatMenuOption(label, action);
- return text == null;
- }
-
- private bool SelectPawnsForCycleOptions(CompBiosculpterPod_Cycle cycle, out List options, bool shortCircuit = false)
- {
- cycleEligiblePawnOptions.Clear();
- options = cycleEligiblePawnOptions;
- if (!cachedAnyPawnEligible.ContainsKey(cycle))
- {
- cachedAnyPawnEligible[cycle] = new CacheAnyPawnEligibleCycle
- {
- gameTime = float.MinValue
- };
- }
- int ticksGame = Find.TickManager.TicksGame;
- if (shortCircuit && (float)ticksGame < cachedAnyPawnEligible[cycle].gameTime + 2f)
- {
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- cachedAnyPawnEligible[cycle].gameTime = ticksGame;
- if (biotunedTo != null)
- {
- if (biotunedTo.Dead || !biotunedTo.Spawned || biotunedTo.Map != parent.Map)
- {
- cachedAnyPawnEligible[cycle].anyEligible = false;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- if (SelectPawnCycleOption(biotunedTo, cycle, out var option) && shortCircuit)
- {
- cachedAnyPawnEligible[cycle].anyEligible = true;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- cycleEligiblePawnOptions.Add(option);
- }
- else
- {
- foreach (Pawn item in parent.Map.mapPawns.FreeColonistsSpawned)
- {
- if (SelectPawnCycleOption(item, cycle, out var option2) && shortCircuit)
- {
- cachedAnyPawnEligible[cycle].anyEligible = true;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
- cycleEligiblePawnOptions.Add(option2);
- }
- }
- cachedAnyPawnEligible[cycle].anyEligible = cycleEligiblePawnOptions.Count > 0;
- return cachedAnyPawnEligible[cycle].anyEligible;
- }
-
- public Job EnterBiosculpterJob()
- {
- return JobMaker.MakeJob(JobDefOf.EnterBiosculpterPod, parent);
- }
-
- public Job MakeCarryToBiosculpterJob(Pawn willBeCarried)
- {
- return JobMaker.MakeJob(JobDefOf.CarryToBiosculpterPod, willBeCarried, LocalTargetInfo.Invalid, parent);
- }
-
- public void ConfigureJobForCycle(Job job, CompBiosculpterPod_Cycle cycle, List extraIngredients)
- {
- if (!extraIngredients.NullOrEmpty())
- {
- job.targetQueueB = new List