创建新工程
This commit is contained in:
386
scripts/CharacterData.gd
Normal file
386
scripts/CharacterData.gd
Normal 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)
|
||||
Reference in New Issue
Block a user