diff --git a/Assets/Plugins/steam_api.dll.meta b/Assets/Plugins/steam_api.dll.meta
new file mode 100644
index 0000000..c89d660
--- /dev/null
+++ b/Assets/Plugins/steam_api.dll.meta
@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: f167045178ff20d45821bd7cb37231f7
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/Plugins/steam_api64.dll.meta b/Assets/Plugins/steam_api64.dll.meta
new file mode 100644
index 0000000..1c606e7
--- /dev/null
+++ b/Assets/Plugins/steam_api64.dll.meta
@@ -0,0 +1,27 @@
+fileFormatVersion: 2
+guid: 46713ca58de687b4db4d9684c7021923
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Docs.meta b/Assets/TcgEngine/Docs.meta
new file mode 100644
index 0000000..328e4bf
--- /dev/null
+++ b/Assets/TcgEngine/Docs.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 08d1c1c6476cad04f97fb97cec8d0798
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Docs/TaskConfigurations.md b/Assets/TcgEngine/Docs/TaskConfigurations.md
new file mode 100644
index 0000000..3bafbaf
--- /dev/null
+++ b/Assets/TcgEngine/Docs/TaskConfigurations.md
@@ -0,0 +1,115 @@
+# 任务配置文件结构说明
+
+## 概述
+
+任务配置文件定义了游戏中可用的各种任务。每个任务都有特定的条件和奖励。
+
+## 配置字段说明
+
+| 字段名 | 类型 | 必需 | 描述 |
+|--------|------|------|------|
+| id | string | 是 | 任务唯一标识符 |
+| name | string | 是 | 任务显示名称 |
+| desc | string | 是 | 任务描述 |
+| condition | int | 是 | 任务条件类型 (参考TaskConditionType枚举) |
+| value1 | int | 是 | 任务目标值 |
+| value2 | string | 否 | 条件参数2 (根据任务类型可能需要) |
+| value3 | string | 否 | 条件参数3 (根据任务类型可能需要) |
+| rewardTypes | int[] | 是 | 奖励类型数组 (参考TaskRewardType枚举) |
+| rewardNums | int[] | 是 | 奖励数量数组 (与rewardTypes一一对应) |
+| isDailyTask | boolean | 是 | 是否为每日任务 |
+| durationHours | int | 是 | 任务持续时间(小时) |
+
+## 任务类型详解
+
+### 1. 登录任务 (LoginGame - 1)
+- **描述**: 玩家登录游戏即可完成
+- **value1**: 无意义 (通常为1)
+- **value2/value3**: 不使用
+
+### 2. 对战任务 (PlayGames - 2)
+- **描述**: 完成指定场次的游戏对战
+- **value1**: 需要完成的对战场次
+- **value2/value3**: 不使用
+
+### 3. 胜利任务 (WinGames - 3)
+- **描述**: 获得指定场次的对战胜利
+- **value1**: 需要获得胜利的场次
+- **value2/value3**: 不使用
+
+### 4. 击败英雄任务 (DefeatHeroWithAttributes - 4)
+- **描述**: 击败指定阵营的英雄
+- **value1**: 需要击败的英雄数量
+- **value2**: 第一个目标阵营 (如 "YiYongJun")
+- **value3**: 第二个目标阵营 (如 "DiGuoJun")
+
+### 5. 召唤英雄任务 (SummonHeroWithAttributes - 5)
+- **描述**: 召唤指定阵营的英雄
+- **value1**: 需要召唤的英雄数量
+- **value2**: 第一个目标阵营 (如 "WangGuoJun")
+- **value3**: 第二个目标阵营 (如 "ZiYouRen")
+
+### 6. 使用技能任务 (UseHeroSkillWithAttributes - 6)
+- **描述**: 使用指定阵营英雄的技能
+- **value1**: 需要使用的技能次数
+- **value2**: 第一个目标阵营 (如 "ShouQun")
+- **value3**: 第二个目标阵营 (如 "XieMo")
+
+## 奖励类型
+
+### 金币奖励 (Coins - 0)
+- **描述**: 给予玩家指定数量的金币
+- **rewardNums**: 金币数量
+
+## 示例配置文件
+
+### 登录任务示例
+```json
+{
+ "id": "login_task_1",
+ "name": "每日登录",
+ "desc": "每日登录游戏",
+ "condition": 1,
+ "value1": 1,
+ "value2": "",
+ "value3": "",
+ "rewardTypes": [0],
+ "rewardNums": [100],
+ "isDailyTask": true,
+ "durationHours": 24
+}
+```
+
+### 胜利任务示例
+```json
+{
+ "id": "win_task_1",
+ "name": "胜利之路",
+ "desc": "获得3场对战胜利",
+ "condition": 3,
+ "value1": 3,
+ "value2": "",
+ "value3": "",
+ "rewardTypes": [0],
+ "rewardNums": [200],
+ "isDailyTask": true,
+ "durationHours": 24
+}
+```
+
+### 击败英雄任务示例
+```json
+{
+ "id": "defeat_hero_task_1",
+ "name": "阵营克星",
+ "desc": "击败5个义勇军或帝国军英雄",
+ "condition": 4,
+ "value1": 5,
+ "value2": "YiYongJun",
+ "value3": "DiGuoJun",
+ "rewardTypes": [0],
+ "rewardNums": [300],
+ "isDailyTask": true,
+ "durationHours": 24
+}
+```
\ No newline at end of file
diff --git a/Assets/TcgEngine/Docs/TaskConfigurations.md.meta b/Assets/TcgEngine/Docs/TaskConfigurations.md.meta
new file mode 100644
index 0000000..d786c36
--- /dev/null
+++ b/Assets/TcgEngine/Docs/TaskConfigurations.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: c0a30614928943b46853e32be2a29fb0
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Docs/TaskSystemAPI.md b/Assets/TcgEngine/Docs/TaskSystemAPI.md
new file mode 100644
index 0000000..d31abaf
--- /dev/null
+++ b/Assets/TcgEngine/Docs/TaskSystemAPI.md
@@ -0,0 +1,119 @@
+# 任务系统接口文档
+
+## 概述
+
+任务系统允许玩家完成各种游戏内任务以获得奖励。系统支持多种任务类型,包括日常任务、成就任务等。
+
+## API端点
+
+### 获取所有任务配置
+```
+GET /api/tasks
+```
+
+**响应**
+```json
+[
+ {
+ "id": "login_task_1",
+ "name": "每日登录",
+ "desc": "每日登录游戏",
+ "condition": 1,
+ "value1": 1,
+ "value2": "",
+ "value3": "",
+ "rewardTypes": [0],
+ "rewardNums": [100],
+ "isDailyTask": true,
+ "durationHours": 24
+ },
+ {
+ "id": "win_task_1",
+ "name": "胜利之路",
+ "desc": "获得3场对战胜利",
+ "condition": 3,
+ "value1": 3,
+ "value2": "",
+ "value3": "",
+ "rewardTypes": [0],
+ "rewardNums": [200],
+ "isDailyTask": true,
+ "durationHours": 24
+ }
+]
+```
+
+### 获取玩家任务数据
+```
+GET /api/users/{userId}/tasks
+```
+
+**响应**
+```json
+{
+ "tasks": [
+ {
+ "taskId": "login_task_1",
+ "assignedTime": 16409952000000000,
+ "expireTime": 16410816000000000,
+ "status": 1,
+ "progress": 1
+ }
+ ],
+ "lastDailyTaskAssigned": 16409952000000000
+}
+```
+
+### 保存玩家任务数据
+```
+POST /api/users/{userId}/tasks
+```
+
+**请求体**
+```json
+{
+ "tasks": [
+ {
+ "taskId": "login_task_1",
+ "assignedTime": 16409952000000000,
+ "expireTime": 16410816000000000,
+ "status": 1,
+ "progress": 1
+ }
+ ],
+ "lastDailyTaskAssigned": 16409952000000000
+}
+```
+
+**响应**
+```json
+{
+ "success": true,
+ "error": ""
+}
+```
+
+## 枚举值定义
+
+### 任务条件类型 (TaskConditionType)
+| 值 | 名称 | 描述 |
+|---|------|------|
+| 1 | LoginGame | 登入游戏 |
+| 2 | PlayGames | 进行X场对战 |
+| 3 | WinGames | 胜利X场 |
+| 4 | DefeatHeroWithAttributes | 击败Y属性和Z属性的英雄X次 |
+| 5 | SummonHeroWithAttributes | 召唤Y属性和Z属性的英雄X次 |
+| 6 | UseHeroSkillWithAttributes | 使用Y属性和Z属性英雄的技能X次 |
+
+### 任务奖励类型 (TaskRewardType)
+| 值 | 名称 | 描述 |
+|---|------|------|
+| 0 | Coins | 金币 |
+
+### 任务状态 (TaskStatus)
+| 值 | 名称 | 描述 |
+|---|------|------|
+| 0 | Active | 激活 |
+| 1 | Completed | 完成 |
+| 2 | Expired | 过期 |
+| 3 | Claimed | 已领取 |
\ No newline at end of file
diff --git a/Assets/TcgEngine/Docs/TaskSystemAPI.md.meta b/Assets/TcgEngine/Docs/TaskSystemAPI.md.meta
new file mode 100644
index 0000000..5c4ccd5
--- /dev/null
+++ b/Assets/TcgEngine/Docs/TaskSystemAPI.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 33e4d9d92f851d04ea1362bf1570a671
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Docs/TaskSystemUserGuide.md b/Assets/TcgEngine/Docs/TaskSystemUserGuide.md
new file mode 100644
index 0000000..3f2f194
--- /dev/null
+++ b/Assets/TcgEngine/Docs/TaskSystemUserGuide.md
@@ -0,0 +1,101 @@
+# 任务系统使用说明
+
+## 概述
+
+任务系统为玩家提供游戏目标和奖励机制。系统每天为玩家分配一个随机任务,玩家完成任务后可获得奖励。
+
+## 系统架构
+
+任务系统由以下几个核心组件构成:
+
+1. **TaskData**: 任务配置数据结构
+2. **TaskManager**: 任务管理器,负责任务逻辑处理
+3. **GameClientTaskIntegration**: 游戏客户端集成组件
+4. **API接口**: 与服务器通信的接口
+
+## 功能特性
+
+### 1. 任务分配
+- 每日0点为每个玩家随机分配一个任务
+- 玩家最多同时持有5个任务
+- 任务过期时间为24小时
+
+### 2. 任务类型
+系统支持以下6种任务类型:
+1. 登录任务
+2. 对战任务
+3. 胜利任务
+4. 击败特定阵营英雄任务
+5. 召唤特定阵营英雄任务
+6. 使用特定阵营英雄技能任务
+
+### 3. 任务状态
+任务具有以下4种状态:
+1. **Active**: 激活状态,玩家正在进行中
+2. **Completed**: 完成状态,条件已满足但奖励未领取
+3. **Expired**: 过期状态,任务已超时
+4. **Claimed**: 已领取,奖励已发放
+
+### 4. 奖励机制
+当前版本仅支持金币奖励,未来可扩展支持:
+- 卡牌包
+- 稀有卡牌
+- 经验值
+- 其他游戏内物品
+
+## 集成指南
+
+### 1. 客户端集成
+在游戏客户端中,通过以下方式集成任务系统:
+
+```csharp
+// 在游戏启动时初始化任务系统
+TaskManager taskManager = TaskManager.Instance;
+taskManager.OnPlayerLogin(); // 玩家登录时检查任务
+
+// 在游戏过程中自动追踪任务进度
+// 系统会自动监听游戏事件并更新任务进度
+```
+
+### 2. 服务器集成
+服务器需要提供以下API接口:
+
+1. `GET /tasks` - 获取所有任务配置
+2. `GET /users/{userId}/tasks` - 获取玩家任务数据
+3. `POST /users/{userId}/tasks` - 保存玩家任务数据
+
+## 扩展开发
+
+### 添加新的任务类型
+1. 在`TaskConditionType`枚举中添加新的任务类型
+2. 在`TaskManager.UpdateTaskProgress`方法中添加相应的条件判断
+3. 在服务器端添加对应的任务处理逻辑
+
+### 添加新的奖励类型
+1. 在`TaskRewardType`枚举中添加新的奖励类型
+2. 在`TaskManager.GiveReward`方法中添加奖励发放逻辑
+3. 在服务器端添加对应的奖励处理逻辑
+
+## 最佳实践
+
+### 性能优化
+1. 使用本地缓存减少API调用频率
+2. 对任务数据进行批处理更新
+3. 实现合理的错误重试机制
+
+### 用户体验
+1. 及时通知玩家任务完成状态
+2. 提供清晰的任务进度显示
+3. 确保奖励发放的可靠性
+
+## 故障排除
+
+### 常见问题
+1. **任务无法加载**: 检查网络连接和API接口状态
+2. **任务进度不更新**: 检查事件监听是否正常注册
+3. **奖励未发放**: 检查奖励发放逻辑和用户数据同步
+
+### 调试建议
+1. 使用日志输出追踪任务状态变化
+2. 验证API响应数据的正确性
+3. 检查时间戳和过期逻辑
\ No newline at end of file
diff --git a/Assets/TcgEngine/Docs/TaskSystemUserGuide.md.meta b/Assets/TcgEngine/Docs/TaskSystemUserGuide.md.meta
new file mode 100644
index 0000000..bd0529e
--- /dev/null
+++ b/Assets/TcgEngine/Docs/TaskSystemUserGuide.md.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 3f085404f2be13947a04ab677c3025cd
+TextScriptImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Resources/Tasks.meta b/Assets/TcgEngine/Resources/Tasks.meta
new file mode 100644
index 0000000..4e551cd
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 8afae310ab2fb8843a6c162db7030919
+folderAsset: yes
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Resources/Tasks/DefeatHeroTask.asset b/Assets/TcgEngine/Resources/Tasks/DefeatHeroTask.asset
new file mode 100644
index 0000000..6a678d4
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/DefeatHeroTask.asset
@@ -0,0 +1,13 @@
+{
+ "id": "defeat_hero_task_1",
+ "name": "阵营克星",
+ "desc": "击败5个义勇军或帝国军英雄",
+ "condition": 4,
+ "value1": 5,
+ "value2": "YiYongJun",
+ "value3": "DiGuoJun",
+ "rewardTypes": [0],
+ "rewardNums": [300],
+ "isDailyTask": true,
+ "durationHours": 24
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Resources/Tasks/DefeatHeroTask.asset.meta b/Assets/TcgEngine/Resources/Tasks/DefeatHeroTask.asset.meta
new file mode 100644
index 0000000..a1a02eb
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/DefeatHeroTask.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 10df7503b6489e7479a8239f15197785
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Resources/Tasks/LoginTask.asset b/Assets/TcgEngine/Resources/Tasks/LoginTask.asset
new file mode 100644
index 0000000..657509d
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/LoginTask.asset
@@ -0,0 +1,13 @@
+{
+ "id": "login_task_1",
+ "name": "每日登录",
+ "desc": "每日登录游戏",
+ "condition": 1,
+ "value1": 1,
+ "value2": "",
+ "value3": "",
+ "rewardTypes": [0],
+ "rewardNums": [100],
+ "isDailyTask": true,
+ "durationHours": 24
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Resources/Tasks/LoginTask.asset.meta b/Assets/TcgEngine/Resources/Tasks/LoginTask.asset.meta
new file mode 100644
index 0000000..88d36ed
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/LoginTask.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: e36474881d2ea304fa5667f767a9044a
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Resources/Tasks/SummonHeroTask.asset b/Assets/TcgEngine/Resources/Tasks/SummonHeroTask.asset
new file mode 100644
index 0000000..7773f98
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/SummonHeroTask.asset
@@ -0,0 +1,13 @@
+{
+ "id": "summon_hero_task_1",
+ "name": "召唤大师",
+ "desc": "召唤10个王国军或自由人英雄",
+ "condition": 5,
+ "value1": 10,
+ "value2": "WangGuoJun",
+ "value3": "ZiYouRen",
+ "rewardTypes": [0],
+ "rewardNums": [250],
+ "isDailyTask": true,
+ "durationHours": 24
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Resources/Tasks/SummonHeroTask.asset.meta b/Assets/TcgEngine/Resources/Tasks/SummonHeroTask.asset.meta
new file mode 100644
index 0000000..d592611
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/SummonHeroTask.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 0b19400c7b189e64eaf33fbdb02e0347
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Resources/Tasks/UseSkillTask.asset b/Assets/TcgEngine/Resources/Tasks/UseSkillTask.asset
new file mode 100644
index 0000000..039cc3d
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/UseSkillTask.asset
@@ -0,0 +1,13 @@
+{
+ "id": "use_skill_task_1",
+ "name": "技能专家",
+ "desc": "使用5次兽群或邪魔英雄的技能",
+ "condition": 6,
+ "value1": 5,
+ "value2": "ShouQun",
+ "value3": "XieMo",
+ "rewardTypes": [0],
+ "rewardNums": [150],
+ "isDailyTask": true,
+ "durationHours": 24
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Resources/Tasks/UseSkillTask.asset.meta b/Assets/TcgEngine/Resources/Tasks/UseSkillTask.asset.meta
new file mode 100644
index 0000000..1877aeb
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/UseSkillTask.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: c82472e555797d94db11f2f7228eb10e
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Resources/Tasks/WinTask.asset b/Assets/TcgEngine/Resources/Tasks/WinTask.asset
new file mode 100644
index 0000000..bd41906
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/WinTask.asset
@@ -0,0 +1,13 @@
+{
+ "id": "win_task_1",
+ "name": "胜利之路",
+ "desc": "获得3场对战胜利",
+ "condition": 3,
+ "value1": 3,
+ "value2": "",
+ "value3": "",
+ "rewardTypes": [0],
+ "rewardNums": [200],
+ "isDailyTask": true,
+ "durationHours": 24
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Resources/Tasks/WinTask.asset.meta b/Assets/TcgEngine/Resources/Tasks/WinTask.asset.meta
new file mode 100644
index 0000000..a0cfc60
--- /dev/null
+++ b/Assets/TcgEngine/Resources/Tasks/WinTask.asset.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 80ca1990d6330be49b5e0be31b9b171b
+NativeFormatImporter:
+ externalObjects: {}
+ mainObjectFileID: 0
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Scripts/Api/ApiMsg.cs b/Assets/TcgEngine/Scripts/Api/ApiMsg.cs
index 3424247..49ab989 100644
--- a/Assets/TcgEngine/Scripts/Api/ApiMsg.cs
+++ b/Assets/TcgEngine/Scripts/Api/ApiMsg.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using UnityEngine;
namespace TcgEngine
@@ -208,4 +208,45 @@ namespace TcgEngine
public string last_online_time;
}
+ // 任务相关请求和响应结构
+ [Serializable]
+ public struct TaskDataResponse
+ {
+ public string id;
+ public string name;
+ public string desc;
+ public int condition;
+ public int value1;
+ public string value2;
+ public string value3;
+ public int[] rewardTypes;
+ public int[] rewardNums;
+ public bool isDailyTask;
+ public int durationHours;
+ }
+
+ [Serializable]
+ public struct PlayerTaskResponse
+ {
+ public string taskId;
+ public long assignedTime;
+ public long expireTime;
+ public int status;
+ public int progress;
+ }
+
+ [Serializable]
+ public struct PlayerTasksResponse
+ {
+ public PlayerTaskResponse[] tasks;
+ public long lastDailyTaskAssigned;
+ }
+
+ [Serializable]
+ public struct PlayerTaskSaveRequest
+ {
+ public PlayerTaskResponse[] tasks;
+ public long lastDailyTaskAssigned;
+ }
+
}
diff --git a/Assets/TcgEngine/Scripts/Data/TaskData.cs b/Assets/TcgEngine/Scripts/Data/TaskData.cs
new file mode 100644
index 0000000..7fc4eb0
--- /dev/null
+++ b/Assets/TcgEngine/Scripts/Data/TaskData.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace TcgEngine
+{
+ ///
+ /// 任务配置数据,用于定义各种任务的属性和条件
+ ///
+ [CreateAssetMenu(fileName = "TaskData", menuName = "TcgEngine/TaskData")]
+ public class TaskData : ScriptableObject
+ {
+ public string id;
+ public string name;
+ public string desc;
+ public TaskConditionType condition;
+ public int value1; // 任务进度上限
+ public string value2; // 边界条件1
+ public string value3; // 边界条件2
+ public TaskRewardType[] rewardTypes;
+ public int[] rewardNums;
+ public bool isDailyTask = true; // 是否为每日任务
+ public int durationHours = 24; // 任务有效期(小时)
+
+ // 从服务器响应数据创建任务配置
+ public static TaskData CreateFromResponse(TaskDataResponse response)
+ {
+ TaskData taskData = ScriptableObject.CreateInstance();
+ taskData.id = response.id;
+ taskData.name = response.name;
+ taskData.desc = response.desc;
+ taskData.condition = (TaskConditionType)response.condition;
+ taskData.value1 = response.value1;
+ taskData.value2 = response.value2;
+ taskData.value3 = response.value3;
+
+ // 转换奖励类型数组
+ taskData.rewardTypes = new TaskRewardType[response.rewardTypes.Length];
+ for (int i = 0; i < response.rewardTypes.Length; i++)
+ {
+ taskData.rewardTypes[i] = (TaskRewardType)response.rewardTypes[i];
+ }
+
+ taskData.rewardNums = response.rewardNums;
+ taskData.isDailyTask = response.isDailyTask;
+ taskData.durationHours = response.durationHours;
+
+ return taskData;
+ }
+ }
+
+ public enum TaskConditionType
+ {
+ LoginGame = 1, // 登入游戏
+ PlayGames = 2, // 进行X场对战
+ WinGames = 3, // 胜利X场
+ DefeatHeroWithAttributes = 4, // 击败Y属性和Z属性的英雄X次
+ SummonHeroWithAttributes = 5, // 召唤Y属性和Z属性的英雄X次
+ UseHeroSkillWithAttributes = 6 // 使用Y属性和Z属性英雄的技能X次
+ }
+
+ public enum TaskRewardType
+ {
+ Coins = 0, // 金币
+ // 后续可扩展其他奖励类型
+ }
+
+ [Serializable]
+ public class PlayerTask
+ {
+ public string taskId;
+ public DateTime assignedTime;
+ public DateTime expireTime;
+ public TaskStatus status;
+ public int progress; // 当前进度
+
+ public PlayerTask(TaskData taskConfig)
+ {
+ taskId = taskConfig.id;
+ assignedTime = DateTime.Now;
+ expireTime = assignedTime.AddHours(taskConfig.durationHours);
+ status = TaskStatus.Active;
+ progress = 0;
+ }
+
+ // 从服务器响应数据创建玩家任务
+ public PlayerTask(PlayerTaskResponse response)
+ {
+ taskId = response.taskId;
+ assignedTime = new DateTime(response.assignedTime);
+ expireTime = new DateTime(response.expireTime);
+ status = (TaskStatus)response.status;
+ progress = response.progress;
+ }
+
+ // 转换为服务器响应数据
+ public PlayerTaskResponse ToResponse()
+ {
+ PlayerTaskResponse response = new PlayerTaskResponse();
+ response.taskId = taskId;
+ response.assignedTime = assignedTime.Ticks;
+ response.expireTime = expireTime.Ticks;
+ response.status = (int)status;
+ response.progress = progress;
+ return response;
+ }
+ }
+
+ public enum TaskStatus
+ {
+ Active = 0, // 激活
+ Completed = 1, // 完成
+ Expired = 2, // 过期
+ Claimed = 3 // 已领取
+ }
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Scripts/Data/TaskData.cs.meta b/Assets/TcgEngine/Scripts/Data/TaskData.cs.meta
new file mode 100644
index 0000000..bda7e86
--- /dev/null
+++ b/Assets/TcgEngine/Scripts/Data/TaskData.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 951a52e8fe4069e41963e049a390811f
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs b/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs
new file mode 100644
index 0000000..2306371
--- /dev/null
+++ b/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs
@@ -0,0 +1,43 @@
+using UnityEngine;
+using TcgEngine.Client;
+using TcgEngine.Gameplay;
+
+namespace TcgEngine.Client
+{
+ ///
+ /// 游戏客户端任务集成,用于将任务系统集成到游戏客户端中
+ ///
+ public class GameClientTaskIntegration : MonoBehaviour
+ {
+ private void Start()
+ {
+ // 在游戏客户端启动时初始化任务系统
+ GameClient client = GameClient.Get();
+ if (client != null)
+ {
+ // 玩家连接到游戏服务器时触发任务检查
+ client.onConnectServer += OnConnectToServer;
+ }
+ }
+
+ private void OnDestroy()
+ {
+ // 取消订阅事件
+ GameClient client = GameClient.Get();
+ if (client != null)
+ {
+ client.onConnectServer -= OnConnectToServer;
+ }
+ }
+
+ private void OnConnectToServer()
+ {
+ // 玩家登录时检查任务
+ TaskManager taskManager = TaskManager.Instance;
+ if (taskManager != null)
+ {
+ taskManager.OnPlayerLogin();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs.meta b/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs.meta
new file mode 100644
index 0000000..f66ea4e
--- /dev/null
+++ b/Assets/TcgEngine/Scripts/GameClient/GameClientTaskIntegration.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 222f46c5f21da1d47a9d2fed11d3d48c
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs
new file mode 100644
index 0000000..1c28d2f
--- /dev/null
+++ b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs
@@ -0,0 +1,553 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+using TcgEngine;
+using TcgEngine.Gameplay;
+using TcgEngine.Client;
+using System.Threading.Tasks;
+
+namespace TcgEngine.Gameplay
+{
+ ///
+ /// 任务管理器,负责任务的分配、进度追踪和奖励发放等功能
+ ///
+ public class TaskManager : MonoBehaviour
+ {
+ public static TaskManager Instance;
+
+ [Header("Player Data")]
+ public List playerTasks = new List();
+ public DateTime lastDailyTaskAssigned;
+ public int maxTasks = 5; // 玩家最多持有任务数
+
+ private GameLogic gameLogic;
+ private System.Random random = new System.Random();
+
+ private void Awake()
+ {
+ if (Instance == null)
+ {
+ Instance = this;
+ DontDestroyOnLoad(gameObject);
+ }
+ else
+ {
+ Destroy(gameObject);
+ }
+ }
+
+ private void Start()
+ {
+ LoadTasks();
+ LoadPlayerData();
+ }
+
+ private void OnEnable()
+ {
+ // 订阅游戏事件
+ GameClient client = GameClient.Get();
+ if (client != null)
+ {
+ client.onGameStart += OnGameStart;
+ client.onGameEnd += OnGameEnd;
+ }
+
+ // 移除对GameLogic.Instance的错误引用,改为检查gameLogic变量
+ if (gameLogic != null)
+ {
+ SubscribeToGameEvents();
+ }
+ }
+
+ private void OnDisable()
+ {
+ // 取消订阅游戏事件
+ GameClient client = GameClient.Get();
+ if (client != null)
+ {
+ client.onGameStart -= OnGameStart;
+ client.onGameEnd -= OnGameEnd;
+ }
+
+ // 移除对GameLogic.Instance的错误引用,改为检查gameLogic变量
+ if (gameLogic != null)
+ {
+ UnsubscribeFromGameEvents();
+ }
+ }
+
+ public void SetGameLogic(GameLogic logic)
+ {
+ gameLogic = logic;
+ SubscribeToGameEvents();
+ }
+
+ private void SubscribeToGameEvents()
+ {
+ if (gameLogic != null)
+ {
+ gameLogic.onCardPlayed += OnCardPlayed;
+ gameLogic.onCardSummoned += OnCardSummoned;
+ gameLogic.onAbilityStart += OnAbilityUsed;
+ gameLogic.onCardDiscarded += OnCardDiscarded; // 用于检测击败英雄
+ }
+ }
+
+ private void UnsubscribeFromGameEvents()
+ {
+ if (gameLogic != null)
+ {
+ gameLogic.onCardPlayed -= OnCardPlayed;
+ gameLogic.onCardSummoned -= OnCardSummoned;
+ gameLogic.onAbilityStart -= OnAbilityUsed;
+ gameLogic.onCardDiscarded -= OnCardDiscarded;
+ }
+ }
+
+ private async void LoadTasks()
+ {
+ // 从服务器加载所有任务配置
+ await LoadTasksFromServer();
+ }
+
+ private async Task LoadTasksFromServer()
+ {
+ if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn())
+ {
+ // 从服务器API获取任务配置
+ string url = ApiClient.ServerURL + "/tasks";
+ WebResponse res = await ApiClient.Get().SendGetRequest(url);
+
+ if (res.success)
+ {
+ // 解析任务配置数据
+ try
+ {
+ TaskDataResponse[] taskResponses = ApiTool.JsonToObject(res.data);
+ Debug.Log("Loaded " + taskResponses.Length + " tasks from server");
+ // 在实际项目中,这里应该将服务器数据转换为TaskData对象并存储在内存中
+ // 供后续使用,而不是每次都从Resources加载
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Failed to parse task data from server: " + e.Message);
+ }
+ }
+ else
+ {
+ Debug.LogWarning("Failed to load tasks from server: " + res.error);
+ }
+ }
+
+ // 如果无法从服务器加载,则使用本地Resources作为后备
+ TaskData[] localTasks = Resources.LoadAll("Tasks");
+ Debug.Log("Loaded " + localTasks.Length + " tasks from local resources as fallback");
+ }
+
+ private async void LoadPlayerData()
+ {
+ // 从服务器加载玩家任务数据
+ await LoadPlayerTasksFromServer();
+ }
+
+ private async Task LoadPlayerTasksFromServer()
+ {
+ if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn())
+ {
+ // 从服务器获取玩家任务数据
+ string url = ApiClient.ServerURL + "/users/" + ApiClient.Get().UserID + "/tasks";
+ WebResponse res = await ApiClient.Get().SendGetRequest(url);
+
+ if (res.success)
+ {
+ // 解析玩家任务数据
+ try
+ {
+ PlayerTasksResponse response = ApiTool.JsonToObject(res.data);
+ lastDailyTaskAssigned = new DateTime(response.lastDailyTaskAssigned);
+
+ // 清除现有任务
+ playerTasks.Clear();
+
+ // 转换并添加任务
+ foreach (var taskResponse in response.tasks)
+ {
+ PlayerTask playerTask = new PlayerTask(taskResponse);
+ playerTasks.Add(playerTask);
+ }
+
+ Debug.Log("Player tasks loaded from server: " + playerTasks.Count + " tasks");
+ }
+ catch (Exception e)
+ {
+ Debug.LogError("Failed to parse player tasks from server: " + e.Message);
+ }
+ }
+ else
+ {
+ Debug.LogWarning("Failed to load player tasks from server: " + res.error);
+ }
+ }
+
+ // 简化处理,首次登录时分配任务
+ if (playerTasks.Count == 0)
+ {
+ AssignDailyTaskIfNeeded();
+ }
+ }
+
+ public async void SavePlayerData()
+ {
+ // 将玩家任务数据保存到服务器
+ if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn())
+ {
+ // 准备要发送的数据
+ PlayerTasksResponse saveData = new PlayerTasksResponse();
+
+ // 转换任务数据
+ PlayerTaskResponse[] taskResponses = new PlayerTaskResponse[playerTasks.Count];
+ for (int i = 0; i < playerTasks.Count; i++)
+ {
+ taskResponses[i] = playerTasks[i].ToResponse();
+ }
+
+ saveData.tasks = taskResponses;
+ saveData.lastDailyTaskAssigned = lastDailyTaskAssigned.Ticks;
+
+ string json = ApiTool.ToJson(saveData);
+ string url = ApiClient.ServerURL + "/users/" + ApiClient.Get().UserID + "/tasks";
+ WebResponse res = await ApiClient.Get().SendPostRequest(url, json);
+
+ if (res.success)
+ {
+ Debug.Log("Player tasks saved to server");
+ }
+ else
+ {
+ Debug.LogWarning("Failed to save player tasks to server: " + res.error);
+ }
+ }
+ }
+
+ // 每日任务分配
+ public void AssignDailyTaskIfNeeded()
+ {
+ // 检查是否应该分配新任务(每日一次)
+ DateTime now = DateTime.Now;
+ if ((now - lastDailyTaskAssigned).TotalHours < 24)
+ return;
+
+ // 检查玩家是否已达到最大任务数
+ if (playerTasks.Count >= maxTasks)
+ return;
+
+ // 获取所有每日任务
+ TaskData[] allTasks = Resources.LoadAll("Tasks");
+ var dailyTasks = allTasks
+ .Where(t => t.isDailyTask &&
+ t.condition != 0 &&
+ !string.IsNullOrEmpty(t.id))
+ .ToArray();
+
+ if (dailyTasks.Length == 0)
+ return;
+
+ // 避免重复分配相同任务
+ int maxRetries = 3;
+ TaskData selectedTask = null;
+ HashSet triedTasks = new HashSet();
+
+ while (maxRetries-- > 0 && selectedTask == null)
+ {
+ // 随机选择一个任务
+ TaskData candidateTask = dailyTasks[random.Next(dailyTasks.Length)];
+
+ // 如果任务已经尝试过则跳过
+ if (triedTasks.Contains(candidateTask.id))
+ continue;
+
+ triedTasks.Add(candidateTask.id);
+
+ // 检查任务是否有效(未被玩家完成过或未在进度中)
+ if (!playerTasks.Any(pt => pt.taskId == candidateTask.id))
+ {
+ selectedTask = candidateTask;
+ break;
+ }
+ }
+
+ // 如果没有找到合适的任务则返回
+ if (selectedTask == null)
+ {
+ Debug.LogWarning("Failed to assign daily task after multiple retries");
+ return;
+ }
+
+ // 创建玩家任务实例
+ PlayerTask playerTask = new PlayerTask(selectedTask);
+ playerTasks.Add(playerTask);
+
+ lastDailyTaskAssigned = now;
+ SavePlayerData();
+
+ Debug.Log($"Assigned daily task: {selectedTask.name}");
+ }
+
+ // 检查并更新过期任务
+ public void CheckExpiredTasks()
+ {
+ DateTime now = DateTime.Now;
+ foreach (var task in playerTasks)
+ {
+ if (task.status == TaskStatus.Active && now > task.expireTime)
+ {
+ task.status = TaskStatus.Expired;
+ }
+ }
+ }
+
+ // 检查任务是否完成
+ public bool CheckTaskCompletion(PlayerTask task)
+ {
+ TaskData taskConfig = GetTaskConfig(task.taskId);
+ if (taskConfig == null)
+ return false;
+
+ return task.progress >= taskConfig.value1;
+ }
+
+ // 领取任务奖励
+ public bool ClaimTaskReward(PlayerTask task)
+ {
+ if (task.status != TaskStatus.Completed)
+ return false;
+
+ TaskData taskConfig = GetTaskConfig(task.taskId);
+ if (taskConfig == null)
+ return false;
+
+ // 发放奖励
+ for (int i = 0; i < taskConfig.rewardTypes.Length && i < taskConfig.rewardNums.Length; i++)
+ {
+ GiveReward(taskConfig.rewardTypes[i], taskConfig.rewardNums[i]);
+ }
+
+ task.status = TaskStatus.Claimed;
+ SavePlayerData();
+ return true;
+ }
+
+ private void GiveReward(TaskRewardType rewardType, int amount)
+ {
+ // 根据奖励类型发放奖励
+ switch (rewardType)
+ {
+ case TaskRewardType.Coins:
+ // 增加金币(需要与游戏现有金币系统集成)
+ UserData userData = Authenticator.Get().UserData;
+ if (userData != null)
+ {
+ userData.coins += amount;
+ Debug.Log($"Gave {amount} coins as reward");
+
+ // 保存用户数据更新
+ if (ApiClient.Get() != null && ApiClient.Get().IsLoggedIn())
+ {
+ Authenticator.Get().SaveUserData();
+ }
+ }
+ break;
+ }
+ }
+
+ private TaskData GetTaskConfig(string taskId)
+ {
+ TaskData[] allTasks = Resources.LoadAll("Tasks");
+ return allTasks.FirstOrDefault(t => t.id == taskId);
+ }
+
+ // 更新任务进度
+ private void UpdateTaskProgress(TaskConditionType conditionType, string parameter1 = null, string parameter2 = null)
+ {
+ bool progressUpdated = false;
+
+ foreach (var task in playerTasks)
+ {
+ if (task.status != TaskStatus.Active)
+ continue;
+
+ TaskData taskConfig = GetTaskConfig(task.taskId);
+ if (taskConfig == null || taskConfig.condition != conditionType)
+ continue;
+
+ bool shouldUpdate = false;
+
+ // 根据任务类型检查条件
+ switch (conditionType)
+ {
+ case TaskConditionType.LoginGame:
+ case TaskConditionType.PlayGames:
+ case TaskConditionType.WinGames:
+ // 这些任务类型直接增加进度
+ shouldUpdate = true;
+ break;
+
+ case TaskConditionType.DefeatHeroWithAttributes:
+ case TaskConditionType.SummonHeroWithAttributes:
+ case TaskConditionType.UseHeroSkillWithAttributes:
+ // 检查参数是否匹配(支持多个参数匹配)
+ if (!string.IsNullOrEmpty(parameter1) &&
+ (!string.IsNullOrEmpty(taskConfig.value2) && taskConfig.value2 == parameter1 ||
+ !string.IsNullOrEmpty(taskConfig.value3) && taskConfig.value3 == parameter1))
+ {
+ shouldUpdate = true;
+ }
+ else if (!string.IsNullOrEmpty(parameter2) &&
+ (!string.IsNullOrEmpty(taskConfig.value2) && taskConfig.value2 == parameter2 ||
+ !string.IsNullOrEmpty(taskConfig.value3) && taskConfig.value3 == parameter2))
+ {
+ shouldUpdate = true;
+ }
+ break;
+ }
+
+ if (shouldUpdate && task.progress < taskConfig.value1)
+ {
+ task.progress++;
+ progressUpdated = true;
+
+ // 检查任务是否完成
+ if (CheckTaskCompletion(task))
+ {
+ task.status = TaskStatus.Completed;
+ Debug.Log($"Task completed: {taskConfig.name}");
+ }
+ }
+ }
+
+ if (progressUpdated)
+ {
+ SavePlayerData();
+ }
+ }
+
+ // 事件处理方法
+ private void OnGameStart()
+ {
+ // 进行对战任务进度+1
+ UpdateTaskProgress(TaskConditionType.PlayGames);
+ }
+
+ private void OnGameEnd(int winner)
+ {
+ int player_id = GameClient.Get().GetPlayerID();
+
+ // 胜利任务进度+1
+ if (winner == player_id)
+ {
+ UpdateTaskProgress(TaskConditionType.WinGames);
+ }
+
+ // 检查是否有任务完成并自动领取奖励
+ CheckAndClaimCompletedTasks();
+ }
+
+ private void OnCardPlayed(Card card, Slot slot)
+ {
+ // 召唤特定属性英雄任务
+ if (card.CardData.type == CardType.Character)
+ {
+ string cardCamp = card.CardData.camp.ToString();
+ UpdateTaskProgress(TaskConditionType.SummonHeroWithAttributes, cardCamp);
+ }
+ }
+
+ private void OnCardSummoned(Card card, Slot slot)
+ {
+ // 召唤特定属性英雄任务
+ if (card.CardData.type == CardType.Character)
+ {
+ string cardCamp = card.CardData.camp.ToString();
+ UpdateTaskProgress(TaskConditionType.SummonHeroWithAttributes, cardCamp);
+ }
+ }
+
+ private void OnAbilityUsed(AbilityData ability, Card caster)
+ {
+ // 使用特定属性英雄技能任务
+ string cardCamp = caster.CardData.camp.ToString();
+ UpdateTaskProgress(TaskConditionType.UseHeroSkillWithAttributes, cardCamp);
+ }
+
+ private void OnCardDiscarded(Card card)
+ {
+ // 击败特定属性英雄任务
+ if (card.CardData.type == CardType.Character)
+ {
+ string cardCamp = card.CardData.camp.ToString();
+ UpdateTaskProgress(TaskConditionType.DefeatHeroWithAttributes, cardCamp);
+ }
+ }
+
+ // 检查并自动领取已完成任务的奖励
+ public void CheckAndClaimCompletedTasks()
+ {
+ bool claimedAny = false;
+ foreach (var task in playerTasks)
+ {
+ if (task.status == TaskStatus.Completed)
+ {
+ if (ClaimTaskReward(task))
+ {
+ claimedAny = true;
+ }
+ }
+ }
+
+ if (claimedAny)
+ {
+ SavePlayerData();
+ }
+ }
+
+ // 玩家登录时检查任务
+ public void OnPlayerLogin()
+ {
+ // 登录任务完成
+ UpdateTaskProgress(TaskConditionType.LoginGame);
+
+ // 检查是否有任务完成并自动领取奖励
+ CheckAndClaimCompletedTasks();
+
+ // 分配每日任务(如果需要)
+ AssignDailyTaskIfNeeded();
+ }
+
+ // 获取活跃任务
+ public List GetActiveTasks()
+ {
+ return playerTasks.Where(t => t.status == TaskStatus.Active).ToList();
+ }
+
+ // 获取已完成任务
+ public List GetCompletedTasks()
+ {
+ return playerTasks.Where(t => t.status == TaskStatus.Completed).ToList();
+ }
+
+ // 获取所有任务
+ public List GetAllTasks()
+ {
+ return playerTasks;
+ }
+ }
+
+ // 玩家任务保存数据结构
+ [Serializable]
+ public struct PlayerTaskSaveData
+ {
+ public PlayerTask[] tasks;
+ public DateTime lastDailyTaskAssigned;
+ }
+}
\ No newline at end of file
diff --git a/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs.meta b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs.meta
new file mode 100644
index 0000000..644e8ba
--- /dev/null
+++ b/Assets/TcgEngine/Scripts/GameLogic/TaskManager.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 37abf64a943e2bb43a818a56f330d168
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant: