创建新工程

This commit is contained in:
moyin
2025-12-05 19:00:14 +08:00
commit ff4fa5fffd
227 changed files with 32804 additions and 0 deletions

386
scripts/CharacterData.gd Normal file
View File

@@ -0,0 +1,386 @@
extends Node
class_name CharacterData
## 角色数据模型
## 定义角色数据结构和验证函数
# 角色数据字段
const FIELD_ID = "id"
const FIELD_NAME = "name"
const FIELD_OWNER_ID = "owner_id"
const FIELD_POSITION = "position"
const FIELD_IS_ONLINE = "is_online"
const FIELD_APPEARANCE = "appearance"
const FIELD_CREATED_AT = "created_at"
const FIELD_LAST_SEEN = "last_seen"
# 个性化字段
const FIELD_PERSONALITY = "personality"
const FIELD_STATUS = "status"
const FIELD_MOOD = "mood"
const FIELD_ATTRIBUTES = "attributes"
const FIELD_SKILLS = "skills"
const FIELD_ACHIEVEMENTS = "achievements"
const FIELD_LEVEL = "level"
const FIELD_EXPERIENCE = "experience"
# 名称验证规则
const MIN_NAME_LENGTH = 2
const MAX_NAME_LENGTH = 20
## 生成唯一角色 ID
static func generate_id() -> String:
"""
生成唯一的角色 ID使用时间戳 + 随机数)
@return: 唯一 ID 字符串
"""
var timestamp = Time.get_unix_time_from_system()
var random_part = randi()
return "char_%d_%d" % [timestamp, random_part]
## 创建角色数据
static func create(char_name: String, owner_id: String, position: Vector2 = Vector2.ZERO) -> Dictionary:
"""
创建新的角色数据
@param char_name: 角色名称
@param owner_id: 所有者 ID
@param position: 初始位置
@return: 角色数据字典
"""
var now = Time.get_unix_time_from_system()
return {
FIELD_ID: generate_id(),
FIELD_NAME: char_name,
FIELD_OWNER_ID: owner_id,
FIELD_POSITION: {
"x": position.x,
"y": position.y
},
FIELD_IS_ONLINE: true,
FIELD_APPEARANCE: {
"sprite": "character_01",
"color": "#FFFFFF",
"body_color": "#4A90E2",
"head_color": "#F5E6D3",
"hair_color": "#8B4513",
"clothing_color": "#2E8B57"
},
FIELD_PERSONALITY: {
"traits": ["friendly", "curious"],
"bio": "",
"favorite_activity": "exploring"
},
FIELD_STATUS: "active", # active, busy, away, offline
FIELD_MOOD: "neutral", # happy, sad, excited, tired, neutral
FIELD_ATTRIBUTES: {
"charisma": 5,
"intelligence": 5,
"creativity": 5,
"energy": 5
},
FIELD_SKILLS: {
"communication": 1,
"problem_solving": 1,
"leadership": 1,
"collaboration": 1
},
FIELD_ACHIEVEMENTS: [],
FIELD_LEVEL: 1,
FIELD_EXPERIENCE: 0,
FIELD_CREATED_AT: now,
FIELD_LAST_SEEN: now
}
## 验证角色名称
static func validate_name(char_name: String) -> bool:
"""
验证角色名称是否有效
@param char_name: 角色名称
@return: 是否有效
"""
# 检查是否为空或仅包含空白字符
if char_name.strip_edges().is_empty():
return false
# 检查长度
var trimmed_name = char_name.strip_edges()
if trimmed_name.length() < MIN_NAME_LENGTH or trimmed_name.length() > MAX_NAME_LENGTH:
return false
return true
## 验证角色数据完整性
static func validate(data: Dictionary) -> bool:
"""
验证角色数据是否完整且有效
@param data: 角色数据字典
@return: 是否有效
"""
# 检查必需字段
if not data.has(FIELD_ID) or not data[FIELD_ID] is String:
return false
if not data.has(FIELD_NAME) or not data[FIELD_NAME] is String:
return false
if not data.has(FIELD_OWNER_ID) or not data[FIELD_OWNER_ID] is String:
return false
if not data.has(FIELD_POSITION) or not data[FIELD_POSITION] is Dictionary:
return false
if not data.has(FIELD_IS_ONLINE) or not data[FIELD_IS_ONLINE] is bool:
return false
# 验证名称
if not validate_name(data[FIELD_NAME]):
return false
# 验证位置数据
var pos = data[FIELD_POSITION]
if not pos.has("x") or not pos.has("y"):
return false
return true
## 从字典创建 Vector2 位置
static func get_position(data: Dictionary) -> Vector2:
"""
从角色数据中提取位置
@param data: 角色数据字典
@return: Vector2 位置
"""
if data.has(FIELD_POSITION):
var pos = data[FIELD_POSITION]
return Vector2(pos.get("x", 0), pos.get("y", 0))
return Vector2.ZERO
## 更新角色位置
static func set_position(data: Dictionary, position: Vector2) -> void:
"""
更新角色数据中的位置
@param data: 角色数据字典
@param position: 新位置
"""
data[FIELD_POSITION] = {
"x": position.x,
"y": position.y
}
## 更新在线状态
static func set_online_status(data: Dictionary, is_online: bool) -> void:
"""
更新角色在线状态
@param data: 角色数据字典
@param is_online: 是否在线
"""
data[FIELD_IS_ONLINE] = is_online
data[FIELD_LAST_SEEN] = Time.get_unix_time_from_system()
## 序列化为 JSON
static func to_json(data: Dictionary) -> String:
"""
将角色数据序列化为 JSON
@param data: 角色数据字典
@return: JSON 字符串
"""
return JSON.stringify(data)
## 从 JSON 反序列化
static func from_json(json_string: String) -> Dictionary:
"""
从 JSON 反序列化角色数据
@param json_string: JSON 字符串
@return: 角色数据字典,失败返回空字典
"""
var json = JSON.new()
var parse_result = json.parse(json_string)
if parse_result == OK:
var data = json.data
if validate(data):
return data
else:
push_error("Invalid character data in JSON")
else:
push_error("Failed to parse character JSON")
return {}
## 克隆角色数据
static func clone(data: Dictionary) -> Dictionary:
"""
深度克隆角色数据
@param data: 原始角色数据
@return: 克隆的角色数据
"""
return from_json(to_json(data))
## 个性化相关函数
## 更新角色外观
static func set_appearance(data: Dictionary, appearance: Dictionary) -> void:
"""
更新角色外观
@param data: 角色数据字典
@param appearance: 外观数据
"""
if not data.has(FIELD_APPEARANCE):
data[FIELD_APPEARANCE] = {}
for key in appearance:
data[FIELD_APPEARANCE][key] = appearance[key]
## 设置角色状态
static func set_status(data: Dictionary, status: String) -> void:
"""
设置角色状态
@param data: 角色数据字典
@param status: 状态 (active, busy, away, offline)
"""
var valid_statuses = ["active", "busy", "away", "offline"]
if status in valid_statuses:
data[FIELD_STATUS] = status
## 设置角色心情
static func set_mood(data: Dictionary, mood: String) -> void:
"""
设置角色心情
@param data: 角色数据字典
@param mood: 心情 (happy, sad, excited, tired, neutral)
"""
var valid_moods = ["happy", "sad", "excited", "tired", "neutral"]
if mood in valid_moods:
data[FIELD_MOOD] = mood
## 更新角色属性
static func set_attribute(data: Dictionary, attribute: String, value: int) -> void:
"""
设置角色属性值
@param data: 角色数据字典
@param attribute: 属性名称
@param value: 属性值 (1-10)
"""
if not data.has(FIELD_ATTRIBUTES):
data[FIELD_ATTRIBUTES] = {}
# 限制属性值范围
value = clamp(value, 1, 10)
data[FIELD_ATTRIBUTES][attribute] = value
## 更新角色技能
static func set_skill(data: Dictionary, skill: String, level: int) -> void:
"""
设置角色技能等级
@param data: 角色数据字典
@param skill: 技能名称
@param level: 技能等级 (1-10)
"""
if not data.has(FIELD_SKILLS):
data[FIELD_SKILLS] = {}
# 限制技能等级范围
level = clamp(level, 1, 10)
data[FIELD_SKILLS][skill] = level
## 添加成就
static func add_achievement(data: Dictionary, achievement: Dictionary) -> void:
"""
添加成就
@param data: 角色数据字典
@param achievement: 成就数据 {id, name, description, earned_at}
"""
if not data.has(FIELD_ACHIEVEMENTS):
data[FIELD_ACHIEVEMENTS] = []
# 检查是否已有此成就
for existing in data[FIELD_ACHIEVEMENTS]:
if existing.get("id") == achievement.get("id"):
return # 已有此成就
achievement["earned_at"] = Time.get_unix_time_from_system()
data[FIELD_ACHIEVEMENTS].append(achievement)
## 增加经验值
static func add_experience(data: Dictionary, experience: int) -> bool:
"""
增加经验值,如果升级返回 true
@param data: 角色数据字典
@param experience: 经验值
@return: 是否升级
"""
if not data.has(FIELD_EXPERIENCE):
data[FIELD_EXPERIENCE] = 0
if not data.has(FIELD_LEVEL):
data[FIELD_LEVEL] = 1
data[FIELD_EXPERIENCE] += experience
# 检查是否升级
var current_level = data[FIELD_LEVEL]
var required_exp = get_required_experience(current_level)
if data[FIELD_EXPERIENCE] >= required_exp:
data[FIELD_LEVEL] += 1
data[FIELD_EXPERIENCE] -= required_exp
return true
return false
## 获取升级所需经验值
static func get_required_experience(level: int) -> int:
"""
获取升级到下一级所需的经验值
@param level: 当前等级
@return: 所需经验值
"""
return level * 100 + (level - 1) * 50 # 递增的经验需求
## 获取角色总体评分
static func get_character_score(data: Dictionary) -> int:
"""
计算角色的总体评分
@param data: 角色数据字典
@return: 总体评分
"""
var score = 0
# 等级贡献
score += data.get(FIELD_LEVEL, 1) * 10
# 属性贡献
var attributes = data.get(FIELD_ATTRIBUTES, {})
for value in attributes.values():
score += value
# 技能贡献
var skills = data.get(FIELD_SKILLS, {})
for value in skills.values():
score += value * 2
# 成就贡献
var achievements = data.get(FIELD_ACHIEVEMENTS, [])
score += achievements.size() * 5
return score
## 获取个性化数据摘要
static func get_personality_summary(data: Dictionary) -> String:
"""
获取角色个性化数据的摘要
@param data: 角色数据字典
@return: 个性化摘要文本
"""
var summary = []
# 等级和经验
var level = data.get(FIELD_LEVEL, 1)
var experience = data.get(FIELD_EXPERIENCE, 0)
summary.append("等级 %d (%d 经验)" % [level, experience])
# 状态和心情
var status = data.get(FIELD_STATUS, "active")
var mood = data.get(FIELD_MOOD, "neutral")
summary.append("状态: %s, 心情: %s" % [status, mood])
# 成就数量
var achievements = data.get(FIELD_ACHIEVEMENTS, [])
if achievements.size() > 0:
summary.append("%d 个成就" % achievements.size())
return " | ".join(summary)