Ejemplo n.º 1
0
        /////////////////////////////////容器/////////////////////////////////
        public static T[] GetSubDoers <T>(Doer parentDoer, string subDoerKey, string id = null,
                                          Func <T, bool> filterFunc = null) where T : Doer
        {
            var      list   = GetSubDoers_ToEdit(parentDoer, subDoerKey);
            List <T> result = new List <T>();

            if (id == null)
            {
                for (var i = 0; i < list.Count; i++)
                {
                    var subDoer = list[i];
                    if (filterFunc == null || filterFunc(subDoer as T))
                    {
                        result.Add(subDoer as T);
                    }
                }

                return(result.ToArray());
            }

            for (var i = 0; i < list.Count; i++)
            {
                var subDoer = (T)list[i];
                if (subDoer.GetId().Equals(id))
                {
                    if (filterFunc == null || filterFunc(subDoer))
                    {
                        result.Add(subDoer);
                    }
                }
            }

            return(result.ToArray());
        }
Ejemplo n.º 2
0
        //owner 发放任务的npc
        public bool AcceptMission(Mission mission, Doer owner)
        {
            var orgEnv = mission.GetEnv();

            if (orgEnv != null)
            {
                LogCat.LogError(string.Format("{0} still belong to {1}", mission, orgEnv));
                mission.Destruct();
                return(false);
            }

            if (IsHasMission(mission.GetId()))
            {
                LogCat.LogError(string.Format("duplicate mission id![{0}]", mission));
                mission.Destruct();
                return(false);
            }

            var missions = this.oMissions.GetMissions_ToEdit();

            mission.SetEnv(this);
            mission.SetOwner(owner);
            missions.Add(mission);
            if (!mission.OnAccept(this))
            {
                mission.Destruct();
                missions.Remove(mission);                 //失败,减回去
                return(false);
            }

            // 检测完成任务
            this.CheckAutoFinishMissions();

            return(true);
        }
Ejemplo n.º 3
0
        public static T GetSubDoer <T>(Doer parentDoer, string subDoerKey, string idOrRid) where T : Doer
        {
            bool   isId = IdUtil.IsId(idOrRid);
            string id   = isId ? idOrRid : IdUtil.RidToId(idOrRid);
            var    dict = GetSubDoerDict_ToEdit(parentDoer, subDoerKey);

            if (dict.ContainsKey(id) && !(dict[id] as ArrayList).IsNullOrEmpty())
            {
                var arrayList = dict[id] as ArrayList;
                for (var i = 0; i < arrayList.Count; i++)
                {
                    var subDoer = (T)arrayList[i];
                    if (isId)
                    {
                        return(subDoer);
                    }
                    if (subDoer.GetRid().Equals(idOrRid))
                    {
                        return(subDoer);
                    }
                }
            }

            return(null);
        }
Ejemplo n.º 4
0
        public static T GetSubDoer <T>(Doer parentDoer, string subDoerKey, string idOrRid) where T : Doer
        {
            if (IdUtil.IsId(idOrRid))             //id的情况
            {
                string id = idOrRid;
                var    ts = GetSubDoers <T>(parentDoer, subDoerKey, null, null);
                for (var i = 0; i < ts.Length; i++)
                {
                    var subDoer = ts[i];
                    if (subDoer.GetId().Equals(id))
                    {
                        return(subDoer);
                    }
                }

                return(null);
            }
            //rid的情况
            string rid = idOrRid;

            if (GetSubDoerDict_ToEdit(parentDoer, subDoerKey).ContainsKey(rid))
            {
                return(GetSubDoerDict_ToEdit(parentDoer, subDoerKey)[rid] as T);
            }
            return(null);
        }
Ejemplo n.º 5
0
        public bool GetDoerValue_Mission(Doer doer, string key, string typeString, out string result)
        {
            bool isBreak = false;

            result = null;
            if (doer is Mission mission)
            {
                if (key.Equals(StringConst.String_status))
                {
                    if (mission.IsReady())
                    {
                        result = ConvertValue(3, typeString);                         //已就绪,可以被完成
                        return(true);
                    }

                    result = ConvertValue(2, typeString);                     //未完成
                    return(true);
                }

                if (key.StartsWith(StringConst.String_items_dot))                 // 物品
                {
                    string    itemId = key.Substring(StringConst.String_items_dot.Length);
                    Hashtable items  = mission.Get <Hashtable>(StringConst.String_items);
                    if (items != null)
                    {
                        int count = items.Get <int>(itemId);
                        result = ConvertValue(count, typeString);
                        return(true);
                    }
                }
            }

            return(isBreak);
        }
Ejemplo n.º 6
0
        public static ArrayList GetSubDoers_ToEdit(Doer parentDoer, string subDoerKey, string id)         //进行直接修改
        {
            var dict = GetSubDoerDict_ToEdit(parentDoer, subDoerKey);
            var list = dict.GetOrAddDefault2(id, () => new ArrayList());

            return(list);
        }
Ejemplo n.º 7
0
 public void Set(Doer u = null, Doer o = null, Doer e = null, Hashtable m = null)
 {
     SetU(u);
     SetO(o);
     SetE(e);
     SetM(m);
 }
Ejemplo n.º 8
0
        public static void AddSubDoers(Doer parentDoer, string subDoerKey, Doer addSubDoer)
        {
            addSubDoer.SetOwner(parentDoer);
            string id       = addSubDoer.GetId();
            bool   canFold  = addSubDoer.IsHasMethod("CanFold") && addSubDoer.InvokeMethod <bool>("CanFold");
            var    subDoers = GetSubDoers_ToEdit(parentDoer, subDoerKey, id);

            if (canFold)
            {
                if (subDoers.IsNullOrEmpty())
                {
                    subDoers.Add(addSubDoer);
                }
                else
                {
                    (subDoers[0] as Doer).AddCount(addSubDoer.GetCount());
                    addSubDoer.SetEnv(null);
                    addSubDoer.Destruct();
                }
            }
            else
            {
                subDoers.Add(addSubDoer);
            }
        }
Ejemplo n.º 9
0
        /////////////////////////////////容器/////////////////////////////////
        public static T[] GetSubDoers <T>(Doer parentDoer, string subDoerKey, string id = null,
                                          Func <T, bool> filterFunc = null) where T : Doer
        {
            var      dict   = GetSubDoerDict_ToEdit(parentDoer, subDoerKey);
            List <T> result = new List <T>();

            if (id == null)
            {
                foreach (var subDoer in dict.Values)
                {
                    if (filterFunc == null || filterFunc(subDoer as T))
                    {
                        result.Add(subDoer as T);
                    }
                }

                return(result.ToArray());
            }

            foreach (T subDoer in dict.Values)
            {
                if (subDoer.GetId().Equals(id))
                {
                    if (filterFunc == null || filterFunc(subDoer))
                    {
                        result.Add(subDoer);
                    }
                }
            }

            return(result.ToArray());
        }
Ejemplo n.º 10
0
        public static string[] GetSubDoerIds(Doer parentDoer, string subDoerKey)
        {
            var           dict   = GetSubDoerDict_ToEdit(parentDoer, subDoerKey);
            List <string> result = new List <string>();

            foreach (string id in dict.Keys)
            {
                result.Add(id);
            }
            return(result.ToArray());
        }
Ejemplo n.º 11
0
        // 释放逻辑对象
        public void ReleaseDoer(Doer doer)
        {
            string id  = doer.GetId();
            string rid = doer.GetRid();

            if (this.idDict.ContainsKey(id))
            {
                this.idDict[id].Remove(rid);
            }
            doer.DoRelease();
            this.RemoveChild(doer.key);
        }
Ejemplo n.º 12
0
        /////////////////////////////////容器/////////////////////////////////
        public static T[] GetSubDoers <T>(Doer parentDoer, string subDoerKey, string id = null,
                                          Func <T, bool> filterFunc = null) where T : Doer
        {
            var      dict   = GetSubDoerDict_ToEdit(parentDoer, subDoerKey);
            List <T> result = new List <T>();

            if (id == null)
            {
                if (filterFunc == null)
                {
                    foreach (var subDoerList in dict.Values)
                    {
                        for (var i = 0; i < (subDoerList as ArrayList).Count; i++)
                        {
                            var subDoer = (subDoerList as ArrayList)[i];
                            result.Add(subDoer as T);
                        }
                    }
                }
                else
                {
                    foreach (var subDoerList in dict.Values)
                    {
                        for (var i = 0; i < (subDoerList as ArrayList).Count; i++)
                        {
                            var subDoer = (subDoerList as ArrayList)[i];
                            if (filterFunc(subDoer as T))
                            {
                                result.Add(subDoer as T);
                            }
                        }
                    }
                }

                return(result.ToArray());
            }

            var list = GetSubDoers_ToEdit(parentDoer, subDoerKey, id);

            for (var i = 0; i < list.Count; i++)
            {
                var subDoer = list[i];
                if (filterFunc == null || filterFunc(subDoer as T))
                {
                    result.Add(subDoer as T);
                }
            }

            return(result.ToArray());
        }
Ejemplo n.º 13
0
        // 获取doer中的sub_doer_key的子doer数量  sub_doer:GetCount()累加
        public static int GetSubDoerCount <T>(Doer parentDoer, string subDoerKey, string id = null,
                                              Func <T, bool> filterFunc = null) where T : Doer
        {
            var subDoers = GetSubDoers(parentDoer, subDoerKey, id, filterFunc);
            int count    = 0;

            for (var i = 0; i < subDoers.Length; i++)
            {
                var subDoer = subDoers[i];
                count = count + subDoer.GetCount();
            }

            return(count);
        }
Ejemplo n.º 14
0
        public static T GetSubDoer <T>(Doer parentDoer, string subDoerKey, string idOrRid) where T : Doer
        {
            var ts = GetSubDoers <T>(parentDoer, subDoerKey, null, null);

            for (var i = 0; i < ts.Length; i++)
            {
                var subDoer = ts[i];
                if (IdUtil.IsIdOrRidEquals(idOrRid, subDoer.GetId(), subDoer.GetRid()))
                {
                    return(subDoer);
                }
            }

            return(null);
        }
Ejemplo n.º 15
0
        public static void ClearSubDoers <T>(Doer parentDoer, string subDoerKey, Action <T> clearSubDoerFunc = null)
            where T : Doer
        {
            var list = GetSubDoers <T>(parentDoer, subDoerKey, null, null);

            for (int i = list.Length - 1; i >= 0; i--)
            {
                var subDoer = list[i];
                clearSubDoerFunc?.Invoke(subDoer);
                subDoer.SetEnv(null);
                subDoer.Destruct();
            }

            GetSubDoerDict_ToEdit(parentDoer, subDoerKey).Clear();
        }
Ejemplo n.º 16
0
        //////////////////////////////////////////////////////////////////////////
        //owner 发放任务的npc
        public virtual bool Execute(string desc, Doer owner, DoerAttrParser doerAttrParser)
        {
            if (!CheckDoerEventTriggerCondition(doerAttrParser))
            {
                return(false);
            }
            var  cfgDoerEventData = GetCfgDoerEventData();
            bool isNotTalk        = cfgDoerEventData.is_not_talk;      // 不弹出talk
            //通用情况
            string        triggerDesc = cfgDoerEventData.trigger_desc;
            List <string> wordList    = new List <string>();

            if (!triggerDesc.IsNullOrWhiteSpace())
            {
                wordList.Add(doerAttrParser.ParseString(triggerDesc));
            }
            int ok = 1;             // 0-触发条件失败,1-触发成功,执行失败,2-触发成功,执行成功

            string[] stepIds = cfgDoerEventData._step_ids;
            if (!stepIds.IsNullOrEmpty())
            {
                for (int i = 0; i < stepIds.Length; i++)
                {
                    string stepId           = stepIds[i];
                    var    cfgDoerEventStep = CfgDoerEventStep.Instance.get_by_id(stepId);
                    ok = ExecuteStep(desc + "步骤" + (i + 1), stepId, owner, doerAttrParser, wordList);
                    if (ok == 0)
                    {
                        break;
                    }
                    if (ok == 2 && cfgDoerEventStep.is_stop_here)
                    {
                        break;
                    }
                }
            }

            if (!isNotTalk && wordList.Count > 0)
            {
                for (var i = 0; i < wordList.Count; i++)
                {
                    var word = wordList[i];
                    Client.instance.uiManager.Notify(word);
                }
            }

            return(ok > 0);
        }
Ejemplo n.º 17
0
        public static void DoReleaseSubDoer <T>(Doer parentDoer, string subDoerKey, Action <T> relaseSubDoerFunc = null)
            where T : Doer
        {
            //销毁
            var subDoers = GetSubDoers <T>(parentDoer, subDoerKey, null, null);

            for (int i = subDoers.Length - 1; i >= 0; i--)
            {
                var subDoer = subDoers[i];
                relaseSubDoerFunc?.Invoke(subDoer);
                subDoer.SetEnv(null);
                subDoer.Destruct();
            }

            GetSubDoerDict_ToEdit(parentDoer, subDoerKey).Clear();
        }
Ejemplo n.º 18
0
        public static T RemoveSubDoer <T>(Doer parentDoer, string subDoerKey, string rid) where T : Doer
        {
            var id       = IdUtil.RidToId(rid);
            var subDoers = GetSubDoers_ToEdit(parentDoer, subDoerKey, id);

            for (int i = subDoers.Count - 1; i >= 0; i--)
            {
                var curSubDoer = subDoers[i] as T;
                if (curSubDoer.GetRid().Equals(rid))
                {
                    curSubDoer.SetEnv(null);
                    subDoers.RemoveAt(i);
                    return(curSubDoer);
                }
            }

            return(null);
        }
Ejemplo n.º 19
0
        public static void ClearSubDoers <T>(Doer parentDoer, string subDoerKey, Action <T> clearSubDoerFunc = null)
            where T : Doer
        {
            var dict = GetSubDoerDict_ToEdit(parentDoer, subDoerKey);

            foreach (ArrayList subDoerList in dict.Values)
            {
                for (int i = subDoerList.Count - 1; i >= 0; i--)
                {
                    var subDoer = subDoerList[i] as T;
                    clearSubDoerFunc?.Invoke(subDoer);
                    subDoer.SetEnv(null);
                    subDoer.Destruct();
                }
            }

            dict.Clear();
        }
Ejemplo n.º 20
0
        //owner 发放任务的npc
        public void GiveUpMission(Mission mission, Doer owner)
        {
            if (mission == null)
            {
                LogCat.LogError("mission is null");
                return;
            }

            if (this.GetMission(mission.GetId()) != mission)
            {
                LogCat.LogError(string.Format("{0} not belong to {1}", mission, this));
                return;
            }

            var missions = this.oMissions.GetMissions_ToEdit();

            mission.SetEnv(null);
            mission.SetOwner(owner);
            missions.Remove(mission);
            mission.OnGiveUp(this);
            mission.Destruct();
        }
Ejemplo n.º 21
0
 public void SetO(Doer o)
 {
     this.o = o;
 }
Ejemplo n.º 22
0
 public void SetU(Doer u)
 {
     this.u = u;
 }
Ejemplo n.º 23
0
        protected Hashtable m;    //相互传数据的hashttable

        public DoerAttrParser(Doer u = null, Doer o = null, Doer e = null, Hashtable m = null)
        {
            Set(u, o, e, m);
        }
Ejemplo n.º 24
0
        public bool GetDoerValue_Doer(Doer doer, string key, string type_string, out string result)
        {
            bool isBreak = false;

            result = null;
            if (doer is Doer)
            {
                if (key.StartsWith(StringConst.String_env_dot) || key.StartsWith(StringConst.String_envt_dot))
                {
                    Doer env = doer.GetEnv();
                    if (env != null)
                    {
                        key = key.Substring(StringConst.String_env.Length);
                        DoerAttrParser doerAttrParser = new DoerAttrParser(env);
                        result = doerAttrParser.ParseString(type_string + StringConst.String_u + key);
                        return(true);
                    }

                    result = ConvertValue(StringConst.String_Empty, type_string);
                    return(true);
                }

                if (key.StartsWith(StringConst.String_pos2))
                {
                    key = key.Substring(StringConst.String_pos2.Length);
                    Vector2 pos2 = doer.GetPos2();
                    if (pos2 != Vector2Const.Default)
                    {
                        if (key.Equals(StringConst.String_dot_x))
                        {
                            result = ConvertValue(pos2.x, type_string);
                            return(true);
                        }

                        if (key.Equals(StringConst.String_dot_y))
                        {
                            result = ConvertValue(pos2.y, type_string);
                            return(true);
                        }

                        result = ConvertValue(pos2.ToString(), type_string);
                        return(true);
                    }

                    result = ConvertValue(StringConst.String_Empty, type_string);
                    return(true);
                }

                if (key.StartsWith(StringConst.String_pos3))
                {
                    key = key.Substring(StringConst.String_pos3.Length);
                    Vector3 pos3 = doer.GetPos3();
                    if (pos3 != Vector3Const.Default)
                    {
                        if (key.Equals(StringConst.String_dot_x))
                        {
                            result = ConvertValue(pos3.x, type_string);
                            return(true);
                        }

                        if (key.Equals(StringConst.String_dot_y))
                        {
                            result = ConvertValue(pos3.y, type_string);
                            return(true);
                        }

                        if (key.Equals(StringConst.String_dot_z))
                        {
                            result = ConvertValue(pos3.z, type_string);
                            return(true);
                        }

                        result = ConvertValue(pos3.ToString(), type_string);
                        return(true);
                    }

                    result = ConvertValue(StringConst.String_Empty, type_string);
                    return(true);
                }
            }

            return(isBreak);
        }
Ejemplo n.º 25
0
        //owner 发放任务的npc
        public int ExecuteStep(string desc, string doerEventStepId, Doer owner, DoerAttrParser doerAttrParser,
                               List <string> wordList)
        {
            var    cfgDoerEventStepData = CfgDoerEventStep.Instance.get_by_id(doerEventStepId);
            string triggerCondition     = cfgDoerEventStepData.trigger_condition;                         // 触发条件

            if (!triggerCondition.IsNullOrWhiteSpace() && !doerAttrParser.ParseBoolean(triggerCondition)) //不满足触发的情况
            {
                string canNotTriggerDesc = cfgDoerEventStepData.can_not_trigger_desc;
                wordList.Add(canNotTriggerDesc.IsNullOrWhiteSpace()
                                        ? Lang.GetText("现在不能触发此操作")
                                        : doerAttrParser.ParseString(canNotTriggerDesc));
                return(0);
            }

            string triggerDesc = cfgDoerEventStepData.trigger_desc;             // 触发提示语

            if (!triggerDesc.IsNullOrWhiteSpace())
            {
                wordList.Add(doerAttrParser.ParseString(triggerDesc));
            }
            string executeCondition = cfgDoerEventStepData.execute_condition;                             // 执行条件

            if (!executeCondition.IsNullOrWhiteSpace() && !doerAttrParser.ParseBoolean(executeCondition)) //不满足执行条件的情况
            {
                string canNotExecuteDesc = cfgDoerEventStepData.can_not_execute_desc;                     // 不执行提示语
                if (!canNotExecuteDesc.IsNullOrWhiteSpace())
                {
                    wordList.Add(doerAttrParser.ParseString(canNotExecuteDesc));
                }
                return(1);
            }

            string executeDesc = cfgDoerEventStepData.execute_desc;             // 执行提示语

            if (!executeDesc.IsNullOrWhiteSpace())
            {
                wordList.Add(doerAttrParser.ParseString(executeDesc));
            }

            DoerAttrSetter doerAttrSetter = new DoerAttrSetter(desc, doerAttrParser);
            //设置属性、更改属性
            Dictionary <string, string> setAttrDict = cfgDoerEventStepData._set_attr_dict;

            foreach (var attrName in setAttrDict.Keys)
            {
                doerAttrSetter.Set(attrName, setAttrDict[attrName], false);
            }
            Dictionary <string, string> addAttrDict = cfgDoerEventStepData._add_attr_dict;

            foreach (var attrName in addAttrDict.Keys)
            {
                doerAttrSetter.Set(attrName, addAttrDict[attrName], true);
            }

            User user = null;

            if (doerAttrParser.GetU() is User)
            {
                user = (User)doerAttrParser.GetU();
            }
            else if (doerAttrParser.GetO() is User)
            {
                user = (User)doerAttrParser.GetO();
            }
            else if (doerAttrParser.GetE() is User)
            {
                user = (User)doerAttrParser.GetE();
            }
            else
            {
                user = Client.instance.user;
            }

            //添加或者删除物品
            Dictionary <string, string> dealItemDict = cfgDoerEventStepData._deal_item_dict;

            if (!dealItemDict.IsNullOrEmpty())
            {
                user.DealItems(dealItemDict, doerAttrParser);
            }

            // 接受任务
            string[] accept_mission_ids = cfgDoerEventStepData._accept_mission_ids;
            foreach (var accept_mission_id in accept_mission_ids)
            {
                user.AcceptMission(accept_mission_id, owner);
            }

            // 完成任务
            string[] finishMissionIds = cfgDoerEventStepData._finish_mission_ids;
            for (var i = 0; i < finishMissionIds.Length; i++)
            {
                var finishMissionId = finishMissionIds[i];
                user.FinishMission(finishMissionId, owner);
            }

            // 放弃任务
            string[] giveUpMissionIds = cfgDoerEventStepData._give_up_mission_ids;
            for (var i = 0; i < giveUpMissionIds.Length; i++)
            {
                var giveUpMissionId = giveUpMissionIds[i];
                user.GiveUpMission(giveUpMissionId, owner);
            }

            // 添加已完成任务
            string[] addFinishedMissionIds = cfgDoerEventStepData._add_finished_mission_ids;
            for (var i = 0; i < addFinishedMissionIds.Length; i++)
            {
                var addFinishedMissionId = addFinishedMissionIds[i];
                user.AddFinishedMissionId(addFinishedMissionId);
            }

            // 删除已完成任务
            string[] removeFinishedMissionIds = cfgDoerEventStepData._remove_finished_mission_ids;
            for (var i = 0; i < removeFinishedMissionIds.Length; i++)
            {
                var removeFinishedMissionId = removeFinishedMissionIds[i];
                user.RemoveFinishedMissionId(removeFinishedMissionId);
            }

            // 检测完成任务
            user.CheckAutoFinishMissions();
            return(2);
        }
Ejemplo n.º 26
0
 public Roles(Doer parentDoer, string subDoerKey)
 {
     this.parentDoer = parentDoer;
     this.subDoerKey = subDoerKey;
 }
Ejemplo n.º 27
0
 public SceneItems(Doer parentDoer, string subDoerKey)
 {
     this.parentDoer = parentDoer;
     this.subDoerKey = subDoerKey;
 }
Ejemplo n.º 28
0
 public void SetE(Doer e)
 {
     this.e = e;
 }
Ejemplo n.º 29
0
        public object Parse(string eval)
        {
            if (string.IsNullOrEmpty(eval))
            {
                return(null);
            }
            if (eval.EqualsIgnoreCase(StringConst.String_true))
            {
                return(true);
            }
            if (eval.EqualsIgnoreCase(StringConst.String_false))
            {
                return(false);
            }
            if (Regex.IsMatch(eval, "^[+-]?\\d+$"))             //整数
            {
                if (eval.TrimLeft(StringConst.String_Plus).TrimLeft(StringConst.String_Minus).Length > 10)
                {
                    return(eval.TrimLeft(StringConst.String_Plus).To <long>());
                }
                return(eval.TrimLeft(StringConst.String_Plus).To <int>());
            }

            if (Regex.IsMatch(eval, "^[+-]?((\\d+)|(\\d+\\.\\d*)|(\\d*\\.\\d+))([eE]\\d+)?$"))             //浮点数
            {
                return(eval.TrimLeft(StringConst.String_Plus).To <float>());
            }
            if (eval.StartsWith(StringConst.String_NumberSign))             // 直接字符串
            {
                eval = eval.Substring(StringConst.String_NumberSign.Length);
                if (eval.IndexOf(StringConst.String_LeftCurlyBrackets) != -1)
                {
                    return(this.ParseString(eval));
                }
                return(eval);
            }

            string ueval;

            if (eval.IndexOf(StringConst.String_LeftCurlyBrackets) != -1)
            {
                ueval = this.ParseString(eval);
            }
            else
            {
                ueval = eval;
            }

            object o = XLuaManager.instance.luaEnv.LoadString(string.Format("return {0}", ueval)).Call()[0];

            if (o == null)
            {
                LogCat.error(
                    string.Format("执行表达式错误[{0}{1}]", eval,
                                  StringConst.String_Comma + this.GetU() + StringConst.String_Comma + this.GetO() +
                                  StringConst.String_Comma + this.GetE()));
            }
            if (o is Int64)
            {
                o = o.To <int>();
            }
            else if (o is double)
            {
                o = o.To <float>();
            }
            return(o);
        }
Ejemplo n.º 30
0
 //获取doer中的sub_doer_key的子doer数量
 public static int GetSubDoersCount <T>(Doer parentDoer, string subDoerKey, string id = null,
                                        Func <T, bool> filterFunc = null) where T : Doer
 {
     return(GetSubDoers <T>(parentDoer, subDoerKey, id, filterFunc).Length);
 }