enum QUEST_STATUS
{
IN_PROGRESS = 0;//已接受,未完成
COMPLATED = 1;//已完成,未提交
FINISHED = 2;//已完成,已提交
FAILED = 3;//已失败
}
enum QUEST_LIST_TYPE
{
ALL = 0;
IN_PROGRESS = 1;
FINISHED = 2;
}
message NQuestInfo//任务信息
{
int32 quest_id = 1;
int32 quest_guid = 2; //任务唯一ID 多个相同任务的唯一ID不同
QUEST_STATUS status = 3;
repeated int32 targets = 4;
}
message QuestListRequest
{
QUEST_LIST_TYPE listType = 1;
}
message QuestListResponse //任务列表
{
RESULT result = 1;
string errormsg = 2;
repeated NQuestInfo quests = 3;
}
message QuestAcceptRequest
{
int32 quest_id = 1;
}
message QuestAcceptResponse //接受任务请求
{
RESULT result = 1;
string errormsg = 2;
NQuestInfo quest = 3;
}
message QuestSubmitRequest //提交任务请求
{
int32 quest_id = 1;
}
message QuestSubmitResponse
{
RESULT result = 1;
string errormsg = 2;
NQuestInfo quest = 3;
}
message QuestAbandonRequest //拒绝任务请求
{
int32 quest_id = 1;
}
message QuestAbandonResponse
{
RESULT result = 1;
string errormsg = 2;
}
namespace Common.Data
{
public enum QuestType
{
[Description("主线")]
Main,
[Description("支线")]
Branch
}
public enum QuestTarget//任务目标
{
None,
Kill,
Item
}
public class QuestDefine
{
public int ID { get; set; }
public string Name { get; set; }
public int LimitLevel { get; set; }
public CharacterClass LimitClass { get; set; } //任务职业限制
public int PreQuest { get; set; }//前置任务ID
public QuestType Type { get; set; }
public int AcceptNPC { get; set; }
public int SubmitNPC { get; set; }
public string Overview { get; set; }
public string Dialog { get; set; } //角色任务对话文本
public string DialogAccept { get; set; }
public string DialogDeny { get; set; }
public string DialogIncomplete { get; set; }
public string DialogFinish { get; set; }
public QuestTarget Target1 { get; set; }
public int Target1ID { get; set; }
public int Target1Num { get; set; }
public QuestTarget Target2 { get; set; }
public int Target2ID { get; set; }
public int Target2Num { get; set; }
public int target3ID { get; set; }
public int target3Num { get; set; }
public int RewardGold { get; set; }
public int RewardExp { get; set; }
public int RewardItem1 { get; set; }
public int RewardItem1Count { get; set; }
public int RewardItem2 { get; set; }
public int RewardItem2Count { get; set; }
public int RewardItem3 { get; set; }
public int RewardItem3Count { get; set; }
}
}
在处理NPC点击交互的函数中通过任务管理去创建任务对话面板。
namespace Managers
{
public enum NpcQuestStatus
{
None = 0,//无任务
Complete,//拥有已完成可提交的任务
Avaliable,//拥有可接受任务
Incomplete,//拥有未完成任务
}
public class QuestManager : Singleton<QuestManager>
{
//所有有效任务
public List<NQuestInfo> questInfos;
public Dictionary<int, Quest> allQuests = new Dictionary<int, Quest>();
//保存NPC身上的任务 NPCID 任务状态 任务列表
public Dictionary<int, Dictionary<NpcQuestStatus, List<Quest>>> npcQuests = new Dictionary<int, Dictionary<NpcQuestStatus, List<Quest>>>();
//任务状态改变
public UnityAction<Quest> OnQuestStatusChanged;
public void Init(List<NQuestInfo> quests)
{
this.questInfos = quests;
allQuests.Clear();//清空本地任务信息
this.npcQuests.Clear();
InitQuests();
}
private void InitQuests()
{
//初始化已有任务(已经接受的任务)
foreach(var info in this.questInfos)
{
Quest quest = new Quest(info);
this.allQuests[quest.Info.QuestId] = quest;
}
this.CheckAvailableQuests(); //初始化可接任务
//将所有任务记录在NPC任务字典中
foreach (var kv in this.allQuests)
{
this.AddNpcQuest(kv.Value.Define.AcceptNPC, kv.Value);
this.AddNpcQuest(kv.Value.Define.SubmitNPC, kv.Value);
}
}
private void CheckAvailableQuests()
{
foreach (var kv in DataManager.Instance.Quests)
{
if (kv.Value.LimitClass != CharacterClass.None && kv.Value.LimitClass != User.Instance.CurrentCharacter.Class)
continue;//不符合职业
if (kv.Value.LimitLevel > User.Instance.CurrentCharacter.Level)
continue;//不符合等级
if (this.allQuests.ContainsKey(kv.Key))
continue;//任务已经存在
if (kv.Value.PreQuest > 0)
{
Quest preQuest;
//获取前置任务
if (this.allQuests.TryGetValue(kv.Value.PreQuest, out preQuest))
{
if (preQuest.Info == null)
continue;//前置任务未接取
if (preQuest.Info.Status != QuestStatus.Finished)
continue;//前置任务未完成
}
else
continue;//前置任务未接
}
Quest quest = new Quest(kv.Value);
this.allQuests[quest.Define.ID] = quest;
}
}
//添加NPC任务状态
private void AddNpcQuest(int npcId, Quest quest)
{
if (!this.npcQuests.ContainsKey(npcId))
this.npcQuests[npcId] = new Dictionary<NpcQuestStatus, List<Quest>>();
//每个NPC都对应有3个列表
List<Quest> avaliables;
List<Quest> completes;
List<Quest> incompletes;
if (!this.npcQuests[npcId].TryGetValue(NpcQuestStatus.Avaliable, out avaliables))
{
avaliables = new List<Quest>();
this.npcQuests[npcId][NpcQuestStatus.Avaliable] = avaliables;
}
if (!this.npcQuests[npcId].TryGetValue(NpcQuestStatus.Complete, out completes))
{
completes = new List<Quest>();
this.npcQuests[npcId][NpcQuestStatus.Complete] = completes;
}
if (!this.npcQuests[npcId].TryGetValue(NpcQuestStatus.Incomplete, out incompletes))
{
incompletes = new List<Quest>();
this.npcQuests[npcId][NpcQuestStatus.Incomplete] = incompletes;
}
if (quest.Info == null)
{
if (npcId == quest.Define.AcceptNPC && !this.npcQuests[npcId][NpcQuestStatus.Avaliable].Contains(quest))
{
this.npcQuests[npcId][NpcQuestStatus.Complete].Add(quest);
}
}
else
{
if (quest.Define.SubmitNPC == npcId && quest.Info.Status == QuestStatus.Completed)
{
if (!this.npcQuests[npcId][NpcQuestStatus.Complete].Contains(quest))
{
this.npcQuests[npcId][NpcQuestStatus.Complete].Add(quest);
}
}
if (quest.Define.SubmitNPC == npcId && quest.Info.Status == QuestStatus.InProgress)
{
if (!this.npcQuests[npcId][NpcQuestStatus.Incomplete].Contains(quest))
{
this.npcQuests[npcId][NpcQuestStatus.Incomplete].Add(quest);
}
}
}
}
///
/// 获取NPC任务状态(点击NPC后先显示已完成任务,然后才是未完成和未接受的)
/// 这个会更新到NPC头顶的小图标
///
///
///
public NpcQuestStatus GetQuestStatusByNpc(int npcId)
{
Dictionary<NpcQuestStatus, List<Quest>> status = new Dictionary<NpcQuestStatus, List<Quest>>();
if (this.npcQuests.TryGetValue(npcId, out status))//获取NPC任务
{
if (status[NpcQuestStatus.Complete].Count > 0)
return NpcQuestStatus.Complete;
if (status[NpcQuestStatus.Avaliable].Count > 0)
return NpcQuestStatus.Avaliable;
if (status[NpcQuestStatus.Incomplete].Count > 0)
return NpcQuestStatus.Incomplete;
}
return NpcQuestStatus.None;
}
public bool OpenNpcQuest(int npcId)
{
Dictionary<NpcQuestStatus, List<Quest>> status = new Dictionary<NpcQuestStatus, List<Quest>>();
if (this.npcQuests.TryGetValue(npcId, out status))//获取NPC任务
{
if (status[NpcQuestStatus.Complete].Count > 0)
return ShowQuestDialog(status[NpcQuestStatus .Complete].First());
if (status[NpcQuestStatus.Avaliable].Count > 0)
return ShowQuestDialog(status[NpcQuestStatus.Avaliable].First());
if (status[NpcQuestStatus.Incomplete].Count > 0)
return ShowQuestDialog(status[NpcQuestStatus.Incomplete].First());
}
return false;
}
///
/// 显示任务对话框
///
///
///
private bool ShowQuestDialog(Quest quest)
{
if (quest.Info == null || quest.Info.Status == QuestStatus.Completed)
{
UIQuestDialog dlg = UIManager.Instance.Show<UIQuestDialog>();
dlg.SetQuest(quest);
dlg.OnClose += OnQuestDialogClose;
return true;
}
if (quest.Info != null || quest.Info.Status == QuestStatus.Completed)
{
if (!string.IsNullOrEmpty(quest.Define.DialogIncomplete))
{
MessageBox.Show(quest.Define.DialogIncomplete);
}
}
return true;
}
private void OnQuestDialogClose(UIWindow sender, UIWindow.WindowResult result)
{
UIQuestDialog dlg = (UIQuestDialog)sender;
if (result == UIWindow.WindowResult.Yes)
{
if (dlg.quest.Info == null)
QuestService.Instance.SendQuestAccept(dlg.quest);
else if(dlg.quest.Info.Status == QuestStatus.Completed)
QuestService.Instance.SendQuestAccept(dlg.quest);
}
else if (result == UIWindow.WindowResult.No)
{
MessageBox.Show(dlg.quest.Define.DialogDeny);
}
}
//接受任务
public void OnQuestAccepted(NQuestInfo info)
{
var quest = this.RefreshQuestStatus(info);
MessageBox.Show(quest.Define.DialogAccept);
}
//提交任务
public void OnQuestSubmited(NQuestInfo info)
{
var quest = this.RefreshQuestStatus(info);
MessageBox.Show(quest.Define.DialogFinish);
}
//刷新任务状态
Quest RefreshQuestStatus(NQuestInfo quest)
{
this.npcQuests.Clear();
Quest result;
//同步服务器返回的任务信息
if (this.allQuests.ContainsKey(quest.QuestId))
{
//更新新的任务状态
this.allQuests[quest.QuestId].Info = quest;
result = this.allQuests[quest.QuestId];
}
else
{
result = new Quest(quest);
this.allQuests[quest.QuestId] = result;
}
this.CheckAvailableQuests(); //初始化可接任务
//将所有任务记录在NPC任务字典中
foreach (var kv in this.allQuests)
{
this.AddNpcQuest(kv.Value.Define.AcceptNPC, kv.Value);
this.AddNpcQuest(kv.Value.Define.SubmitNPC, kv.Value);
}
if (OnQuestStatusChanged != null)
OnQuestStatusChanged(result);
return result;
}
}
}
namespace Services
{
class QuestService : Singleton<QuestService>, IDisposable
{
public QuestService()
{
MessageDistributer.Instance.Subscribe<QuestAcceptResponse>(this.OnQuestAccept);
MessageDistributer.Instance.Subscribe<QuestSubmitResponse>(this.OnQuestSubmit);
}
public void Dispose()
{
MessageDistributer.Instance.Unsubscribe<QuestAcceptResponse>(this.OnQuestAccept);
MessageDistributer.Instance.Unsubscribe<QuestSubmitResponse>(this.OnQuestSubmit);
}
public bool SendQuestAccept(Quest quest)
{
Debug.Log("SendQuestAccept");
NetMessage message = new NetMessage();
message.Request = new NetMessageRequest();
message.Request.questAccept = new QuestAcceptRequest();
message.Request.questAccept.QuestId = quest.Define.ID;
NetClient.Instance.SendMessage(message);
return true;
}
public bool SendQuestSubmit(Quest quest)
{
Debug.Log("SendQuestSubmit");
NetMessage message = new NetMessage();
message.Request = new NetMessageRequest();
message.Request.questSubmit = new QuestSubmitRequest();
message.Request.questSubmit.QuestId = quest.Define.ID;
NetClient.Instance.SendMessage(message);
return true;
}
private void OnQuestSubmit(object sender, QuestSubmitResponse message)
{
Debug.LogFormat("OnQuestSubmit:{0},ERR:{1}", message.Result, message.Errormsg);
if (message.Result == Result.Success)
{
QuestManager.Instance.OnQuestSubmited(message.Quest);
}
else
{
MessageBox.Show("任务完成失败", "错误", MessageBoxType.Error);
}
}
private void OnQuestAccept(object sender, QuestAcceptResponse message)
{
Debug.LogFormat("OnQuestAccept:{0},ERR:{1}", message.Result, message.Errormsg);
if (message.Result == Result.Success)
{
QuestManager.Instance.OnQuestAccepted(message.Quest);
}
else
{
MessageBox.Show("任务接受失败", "错误", MessageBoxType.Error);
}
}
}
}
1.任务对话面板,通过不同的状态 显示不同的按钮,并更新任务信息
public class UIQuestDialog : UIWindow
{
public UIQuestInfo questInfo;
public Quest quest;
public GameObject openButtons;//包括完成和拒绝按钮
public GameObject submitButtons;//提交按钮
public void SetQuest(Quest quest)
{
this.quest = quest;
this.UpdateQuest();
if (this.quest.Info == null)
{
openButtons.SetActive(true);
submitButtons.SetActive(false);
}
else
{
if (this.quest.Info.Status == QuestStatus.Completed)
{
openButtons.SetActive(true);
submitButtons.SetActive(false);
}
else
{
openButtons.SetActive(false);
submitButtons.SetActive(false);
}
}
}
void UpdateQuest()
{
if (this.quest != null)
{
if (this.questInfo != null)
{
this.questInfo.SetQuestInfo(quest);
}
}
}
}
2.任务信息面板
public class UIQuestInfo : MonoBehaviour
{
public Text title;
public Text[] targets;
public Text description;
public UIIconItem rewardItems;
public Text rewardMoney;
public Text rewardExp;
// Start is called before the first frame update
void Start()
{
}
public void SetQuestInfo(Quest quest)
{
this.title.text = string.Format("[{0}]{1}", quest.Define.Type, quest.Define.Name);
if (quest.Info == null)
{
this.description.text = quest.Define.Dialog;
}
else
{
if (quest.Info.Status == SkillBridge.Message.QuestStatus.Completed)
{
this.description.text = quest.Define.DialogFinish;
}
}
this.rewardMoney.text = quest.Define.RewardGold.ToString();
this.rewardExp.text = quest.Define.RewardExp.ToString();
foreach(var fitter in this.GetComponentsInChildren<ContentSizeFitter>())
{
fitter.SetLayoutVertical();//重新排列任务信息描述表
}
}
// Update is called once per frame
void Update()
{
}
public void OnClickAbandon()
{
}
}
3.任务主面板
public class UIQuestSystem : UIWindow
{
public Text title;
public GameObject itemPrefab;
public TabView Tabs;
public ListView listMain;
public ListView listBranch;
public UIQuestInfo questInfo;
private bool showAvailableList = false;
void Start()
{
this.listMain.onItemSelected += this.OnQuestSelected;
this.listBranch.onItemSelected += this.OnQuestSelected;
this.Tabs.OnTabSelect += this.OnSelectTab;
RefreshUI();
}
void OnSelectTab(int idx)
{
showAvailableList = idx == 1;
RefreshUI();
}
private void RefreshUI()
{
ClearAllQuestList();
InitAllQuestItems();
}
private void InitAllQuestItems()
{
foreach (var kv in QuestManager.Instance.allQuests)
{
if (showAvailableList)
{
if (kv.Value.Info != null)
{
continue;
}
}
else
{
if (kv.Value.Info == null)
continue;
}
GameObject go = Instantiate(itemPrefab, kv.Value.Define.Type
== QuestType.Main ? this.listMain.transform : this.listBranch.transform);
UIQuestItem ui = go.GetComponent<UIQuestItem>();
ui.SetQuestInfo(kv.Value);
if (kv.Value.Define.Type == QuestType.Main)
this.listMain.AddItem(ui as ListView.ListViewItem);
else
this.listBranch.AddItem(ui as ListView.ListViewItem);
}
}
private void ClearAllQuestList()
{
this.listMain.RemoveAll();
this.listBranch.RemoveAll();
}
private void OnQuestSelected(ListView.ListViewItem item)
{
UIQuestItem questItem = item as UIQuestItem;
this.questInfo.SetQuestInfo(questItem.quest);//设置任务信息
}
}
4.任务头像上的图标状态修改
在npccontroller中绑定 任务状态改变的事件(QuestManager->NpcController)来修改人物投递出现!,?,完成的图标
npccontroller中有关图标刷新的代码:
void Start()
{
RefreshNpcStatus();
QuestManager.Instance.OnQuestStatusChanged += OnQuestStatusChanged;
}
private void RefreshNpcStatus()
{
questStatus = QuestManager.Instance.GetQuestStatusByNpc(this.npcID);
UIWorldElementManager.Instance.AddNpcQuestStatus(this.transform, questStatus);
}
public void OnQuestStatusChanged(Quest quest)
{
this.RefreshNpcStatus();
}
private void OnDestroy()
{
QuestManager.Instance.OnQuestStatusChanged -= OnQuestStatusChanged;
if (UIWorldElementManager.Instance != null)
{
UIWorldElementManager.Instance.RemoveNpcQuestStatus(this.transform);
}
}
namespace GameServer.Services
{
class QuestService:Singleton<QuestService>
{
public QuestService()
{
MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<QuestAcceptRequest>(this.OnQuestAccept);
MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<QuestSubmitRequest>(this.OnQuestSubmit);
}
private void OnQuestSubmit(NetConnection<NetSession> sender, QuestSubmitRequest request)
{
Character character = sender.Session.Character;
Log.InfoFormat("QuestSubmitRequest:character:{0},QuestId:{1}", character.Id, request.QuestId);
sender.Session.Response.questSubmit = new QuestSubmitResponse();
Result result = character.QuestManager.SubmitQuest(sender, request.QuestId);
sender.Session.Response.questSubmit.Result = result;
sender.SendResponse();
}
private void OnQuestAccept(NetConnection<NetSession> sender, QuestAcceptRequest request)
{
Character character = sender.Session.Character;
Log.InfoFormat("QuestAcceptRequest:character:{0},QuestId:{1}", character.Id, request.QuestId);
sender.Session.Response.questAccept = new QuestAcceptResponse();
Result result = character.QuestManager.AcceptQuest(sender, request.QuestId);
sender.Session.Response.questAccept.Result = result;
sender.SendResponse();
}
}
}
namespace GameServer.Managers
{
class QuestManager
{
Character Owner;
public QuestManager(Character owner)
{
this.Owner = owner;
}
public void GetQuestInfos(List<NQuestInfo> list)
{
foreach (var quest in this.Owner.Data.Quests)
{
list.Add(GetQuestInfo(quest));
}
}
public NQuestInfo GetQuestInfo(TCharacterQuest quest)
{
return new NQuestInfo()
{
QuestId = quest.QuestID,
QuestGuid = quest.Id,
Status = (QuestStatus)quest.Status,
Targets = new int[3]
{
quest.Target1,
quest.Target2,
quest.Target3
}
};
}
public Result AcceptQuest(NetConnection<NetSession> sender, int questId)
{
Character character = sender.Session.Character;
QuestDefine quest;
if (DataManager.Instance.Quests.TryGetValue(questId, out quest))
{
//将任务表中数据给DB赋值
var dbquest = DBService.Instance.Entities.CharacterQuests.Create();
dbquest.QuestID = quest.ID;
if (quest.Target1 == QuestTarget.None)
{//没有目标 直接完成
dbquest.Status = (int)QuestStatus.Completed;
}
else
{//有目标 进行中
dbquest.Status = (int)QuestStatus.InProgress;
}
sender.Session.Response.questAccept.Quest = this.GetQuestInfo(dbquest);
character.Data.Quests.Add(dbquest);
DBService.Instance.Save();
return Result.Success;
}
else
{
sender.Session.Response.questAccept.Errormsg = "任务不存在";
return Result.Failed;
}
}
public Result SubmitQuest(NetConnection<NetSession> sender, int questId)
{
Character character = sender.Session.Character;
QuestDefine quest;
if (DataManager.Instance.Quests.TryGetValue(questId, out quest))
{
var dbquest = character.Data.Quests.Where(q => q.QuestID == questId).FirstOrDefault();
if (dbquest != null)
{
if (dbquest.Status != (int)QuestStatus.Completed)
{//非完成状态
sender.Session.Response.questSubmit.Errormsg = "任务未完成";
return Result.Failed;
}
dbquest.Status = (int)QuestStatus.Finished;
sender.Session.Response.questSubmit.Quest = this.GetQuestInfo(dbquest);
DBService.Instance.Save();
//处理任务奖励
if (quest.RewardGold > 0)
{
character.Gold += quest.RewardGold;
}
if (quest.RewardExp > 0)
{
// character.Exp += quest.RewardExp;
}
if (quest.RewardItem1 > 0)
{
character.ItemManager.AddItem(quest.RewardItem1, quest.RewardItem1Count);
}
if (quest.RewardItem2 > 0)
{
character.ItemManager.AddItem(quest.RewardItem2, quest.RewardItem2Count);
}
if (quest.RewardItem3 > 0)
{
character.ItemManager.AddItem(quest.RewardItem3, quest.RewardItem3Count);
}
DBService.Instance.Save();
return Result.Success;
}
sender.Session.Response.questAccept.Errormsg = "任务不存在[数据库没有]";
return Result.Failed;
}
else
{
sender.Session.Response.questAccept.Errormsg = "任务不存在[配置表没有]";
return Result.Failed;
}
}
}
}