protected virtual void ConstructTriggerTable() { foreach (string skill_name in room.Skills) { TriggerSkill skill = Engine.GetTriggerSkill(skill_name); if (skill != null) AddTriggerSkill(skill); } object data = null; foreach (Player player in room.Players) Trigger(TriggerEvent.GameStart, room, player, ref data); }
public void AddTriggerSkill(TriggerSkill skill) { if (skill == null || skillSet.Contains(skill.Name)) return; skillSet.Add(skill.Name); List<TriggerEvent> events = skill.TriggerEvents; foreach (TriggerEvent triggerEvent in events) { List <TriggerSkill> table = skill_table.ContainsKey(triggerEvent) ? skill_table[triggerEvent] : new List<TriggerSkill>(); table.Add(skill); table.Sort((x, y) => CompareByPriority(triggerEvent, x, y)); skill_table[triggerEvent] = table; } }
public virtual TriggerStruct Cost(Room room, ref object data, TriggerStruct info) { Player target = room.FindPlayer(info.Invoker, true); if (RoomLogic.HasArmorEffect(room, target, Name, false) && (frequency == Frequency.Compulsory || room.AskForSkillInvoke(target, Name, data))) { return(info); } List <string> all = new List <string>(); bool show = false; bool protect = true; foreach (ViewHasSkill vhskill in Engine.ViewHas(room, target, Name, "armor")) { Skill mskill = Engine.GetMainSkill(vhskill.Name); if (RoomLogic.PlayerHasShownSkill(room, target, mskill)) { protect = false; if (frequency == Frequency.Compulsory) { show = true; } } all.Add(mskill.Name); } if (protect) { target.SetFlags("Global_askForSkillCost"); } if (all.Count > 0) { List <TriggerStruct> skills = new List <TriggerStruct>(); foreach (string sk in all) { TriggerStruct skill = new TriggerStruct(sk, target) { ResultTarget = info.ResultTarget }; skills.Add(skill); } TriggerStruct result = room.AskForSkillTrigger(target, "armorskill", skills, !show, data); if (string.IsNullOrEmpty(result.SkillName)) { return(result); } else { TriggerSkill result_skill = Engine.GetTriggerSkill(result.SkillName); if (result_skill != null) { if (show || all.Count > 1 || room.AskForSkillInvoke(target, result_skill.Name, data, result.SkillPosition)) { return(result); } } else if (show || all.Count > 1 || room.AskForSkillInvoke(target, result_skill.Name, data, result.SkillPosition)) { return(info); } } } return(new TriggerStruct()); }
private int CompareByPriority(TriggerEvent triggerEvent, TriggerSkill skill1, TriggerSkill skill) { return(skill1.GetDynamicPriority(triggerEvent) > skill.GetDynamicPriority(triggerEvent) ? -1 : 1); }
public bool Trigger(TriggerEvent triggerEvent, Room room, Player target, ref object data) { // push it to event stack if (!string.IsNullOrEmpty(room.PreWinner)) { return(true); } _m_trigger_id++; int trigger_id = _m_trigger_id; trigger_count.Add(trigger_id, new Dictionary <string, int>()); bool broken = false; List <TriggerSkill> will_trigger = new List <TriggerSkill>(); List <TriggerSkill> triggerable_tested = new List <TriggerSkill>(); List <TriggerSkill> rules = new List <TriggerSkill>(); // we can't get a GameRule with Engine::getTriggerSkill() :( Dictionary <Player, List <TriggerStruct> > trigger_who = new Dictionary <Player, List <TriggerStruct> >(); List <TriggerSkill> triggered = new List <TriggerSkill>(); Dictionary <Player, List <TriggerStruct> > already_triggered = new Dictionary <Player, List <TriggerStruct> >(); do { List <TriggerSkill> skills = skill_table.ContainsKey(triggerEvent) ? new List <TriggerSkill>(skill_table[triggerEvent]) : new List <TriggerSkill>(); trigger_who.Clear(); foreach (TriggerSkill skill in skills) { if (!triggered.Contains(skill)) { if (skill is GameRule) { if (will_trigger.Count == 0 || skill.GetDynamicPriority(triggerEvent) == will_trigger[will_trigger.Count - 1].GetDynamicPriority(triggerEvent)) { will_trigger.Add(skill); if (trigger_who.ContainsKey(rule_player)) { trigger_who[rule_player].Add(new TriggerStruct(skill.Name)); // Don't assign game rule to some player. } else { trigger_who[rule_player] = new List <TriggerStruct> { new TriggerStruct(skill.Name) } }; rules.Add(skill); } else if (skill.GetDynamicPriority(triggerEvent) != will_trigger[will_trigger.Count - 1].GetDynamicPriority(triggerEvent)) { break; } triggered.Insert(0, skill); } else { if (will_trigger.Count == 0 || skill.GetDynamicPriority(triggerEvent) == will_trigger[will_trigger.Count - 1].GetDynamicPriority(triggerEvent)) { skill.Record(triggerEvent, room, target, ref data); //to record something for next. List <TriggerStruct> triggerSkillList = skill.Triggerable(triggerEvent, room, target, ref data); foreach (TriggerStruct skill_struct in triggerSkillList) { TriggerStruct tskill = skill_struct; if (tskill.Times != 1) { tskill.Times = 1; //make sure times == 1 } TriggerSkill trskill = Engine.GetTriggerSkill(tskill.SkillName); Player p = room.FindPlayer(tskill.Invoker, true); if (trskill != null) { will_trigger.Add(trskill); if (trigger_who.ContainsKey(p)) { trigger_who[p].Add(tskill); } else { trigger_who[p] = new List <TriggerStruct> { tskill } }; } } } else if (skill.GetDynamicPriority(triggerEvent) != will_trigger[will_trigger.Count - 1].GetDynamicPriority(triggerEvent)) { break; } triggered.Insert(0, skill); } } if (!triggerable_tested.Contains(skill)) { triggerable_tested.Add(skill); } } if (will_trigger.Count > 0) { will_trigger.Clear(); foreach (Player p in room.GetAllPlayers(true)) { if (!trigger_who.ContainsKey(p)) { continue; } //List<TriggerStruct> already_triggered = new List<TriggerStruct>(); Dictionary <Player, List <TriggerStruct> > refuse = new Dictionary <Player, List <TriggerStruct> >(); while (true) { List <TriggerStruct> who_skills = trigger_who.ContainsKey(p) ? new List <TriggerStruct>(trigger_who[p]) : new List <TriggerStruct>(); if (who_skills.Count == 0) { break; } TriggerStruct name = new TriggerStruct(); foreach (TriggerStruct skill in who_skills) { TriggerSkill tskill = Engine.GetTriggerSkill(skill.SkillName); if (tskill != null && tskill.Global && tskill.SkillFrequency == Skill.Frequency.Compulsory) { TriggerStruct name_copy = skill; if (skill.Targets.Count > 0) { name_copy.ResultTarget = skill.Targets[0]; } name = name_copy; // a new trick to deal with all "record-skill" or "compulsory-global", // they should always be triggered first. break; } } if (string.IsNullOrEmpty(name.SkillName)) { if (p != null && !p.HasShownAllGenerals()) { p.SetFlags("Global_askForSkillCost"); // TriggerOrder need protect } if (who_skills.Count == 1 && (p == null || who_skills[0].SkillName.Contains("global-fake-move"))) { TriggerStruct name_copy = who_skills[0]; if (who_skills[0].Targets.Count > 0) { name_copy.ResultTarget = who_skills[0].Targets[0]; } name = name_copy; } else if (p != null) { string reason = "GameRule:TriggerOrder"; foreach (TriggerStruct skill in who_skills) { if (triggerEvent == TriggerEvent.EventPhaseStart && skill.SkillName.Contains("GameRule_AskForGeneralShow")) { reason = "GameRule:TurnStart"; break; } } name = room.AskForSkillTrigger(p, reason, who_skills, true, data); } else { name = who_skills[who_skills.Count - 1]; } if (p != null && p.HasFlag("Global_askForSkillCost")) { p.SetFlags("-Global_askForSkillCost"); } } if (string.IsNullOrEmpty(name.SkillName)) { break; } TriggerSkill result_skill = Engine.GetTriggerSkill(name.SkillName); Player skill_target = room.FindPlayer(name.ResultTarget, true); if (skill_target == null && target != null) { skill_target = target; name.ResultTarget = target.Name; } if (name.Targets.Count > 0) { bool deplicated = false; List <TriggerStruct> already = already_triggered.ContainsKey(p) ? new List <TriggerStruct>(already_triggered[p]) : new List <TriggerStruct>(); foreach (TriggerStruct already_s in already) //类似铁骑对多目标发动的触发技 { //若先选择了对后位角色发动,则直接跳过前位的其他角色 if (already_s.Equals(name) && already_s.Targets.Count > 0) { Player triggered_target = room.FindPlayer(already_s.ResultTarget, true); Player _target = room.FindPlayer(name.ResultTarget, true); List <Player> all = room.GetAllPlayers(true); if (all.IndexOf(_target) > all.IndexOf(triggered_target)) { already_triggered[p][already.IndexOf(already_s)] = name; deplicated = true; break; } } } if (!deplicated) { if (already_triggered.ContainsKey(p)) { already_triggered[p].Add(name); } else { already_triggered[p] = new List <TriggerStruct> { name } }; } } else { if (already_triggered.ContainsKey(p)) { already_triggered[p].Add(name); } else { already_triggered[p] = new List <TriggerStruct> { name } }; } //----------------------------------------------- TriggerSkill::cost bool do_effect = false; if (p != null && !RoomLogic.PlayerHasShownSkill(room, p, result_skill)) { p.SetFlags("Global_askForSkillCost"); // SkillCost need protect } string mark = string.Format("{0}_{1}_{2}", name.SkillName, p.Name, skill_target != null ? skill_target.Name : "null"); if (!trigger_count[trigger_id].ContainsKey(mark)) { trigger_count[trigger_id][mark] = 1; } else { trigger_count[trigger_id][mark]++; } TriggerStruct cost = name; cost.Times = trigger_count[trigger_id][mark]; TriggerStruct cost_str = result_skill.Cost(triggerEvent, room, skill_target, ref data, p, cost); result_skill = Engine.GetTriggerSkill(cost_str.SkillName); if (result_skill != null) { do_effect = true; if (p != null) { bool compulsory_shown = false; if (result_skill.SkillFrequency == Skill.Frequency.Compulsory && RoomLogic.PlayerHasShownSkill(room, p, result_skill)) { compulsory_shown = true; } bool show = room.ShowSkill(p, result_skill.Name, cost_str.SkillPosition); if (!compulsory_shown && show) { p.SetTag("JustShownSkill", result_skill.Name); } } } if (p != null && p.HasFlag("Global_askForSkillCost")) // for next time { p.SetFlags("-Global_askForSkillCost"); } //----------------------------------------------- TriggerSkill::effect if (do_effect) { Player invoker = room.FindPlayer(cost_str.Invoker, true); //it may point to another skill, such as EightDiagram to bazhen skill_target = room.FindPlayer(cost_str.ResultTarget, true); broken = result_skill.Effect(triggerEvent, room, skill_target, ref data, invoker, cost_str); if (broken) { //if (room.Setting.GameMode == "Hegemony") // room.Debug(string.Format("{0}-{1}", triggerEvent, result_skill.Name)); p.RemoveTag("JustShownSkill"); break; } } else { if (refuse.ContainsKey(p)) { refuse[p].Add(name); } else { refuse[p] = new List <TriggerStruct> { name } }; } //----------------------------------------------- p.RemoveTag("JustShownSkill"); trigger_who.Clear(); foreach (TriggerSkill skill in triggered) { if (skill is GameRule) { //room->tryPause(); continue; // dont assign them to some person. } else { //room->tryPause(); if (skill.GetDynamicPriority(triggerEvent) == triggered[0].GetDynamicPriority(triggerEvent)) { List <TriggerStruct> triggerSkillList = skill.Triggerable(triggerEvent, room, target, ref data); foreach (Player _p in room.Players) { foreach (TriggerStruct _skill in triggerSkillList) { if (_p.Name != _skill.Invoker) { continue; } bool refuse_before = false; if (refuse.ContainsKey(_p)) { foreach (TriggerStruct refused in refuse[_p]) { if (_skill.Equals(refused) && _skill.Targets.Count == 0) { refuse_before = true; break; } } } if (refuse_before) { break; } TriggerStruct tskill = _skill; if (tskill.Times != 1) { tskill.Times = 1; //make sure times == 1 } TriggerSkill trskill = Engine.GetTriggerSkill(tskill.SkillName); if (trskill != null) { if (trigger_who.ContainsKey(_p)) { trigger_who[_p].Add(tskill); } else { trigger_who[_p] = new List <TriggerStruct> { tskill } }; } } } } else { break; } } } foreach (TriggerStruct already_s in already_triggered[p]) { List <TriggerStruct> who_skills_q = trigger_who.ContainsKey(p) ? new List <TriggerStruct>(trigger_who[p]) : new List <TriggerStruct>(); foreach (TriggerStruct re_skill in who_skills_q) { if (already_s.Equals(re_skill)) //类似铁骑、烈弓多目标的触发技 { //筛选剩余未发动的目标 if (already_s.Targets.Count > 0 && re_skill.Targets.Count > 0 && re_skill.Targets.Contains(already_s.ResultTarget)) { List <string> targets = new List <string>(re_skill.Targets); for (int i = 0; i <= targets.IndexOf(already_s.ResultTarget); i++) { re_skill.Targets.Remove(targets[i]); } if (re_skill.Targets.Count > 0) { TriggerStruct re_skill2 = already_s; re_skill2.Targets = re_skill.Targets; re_skill2.ResultTarget = null; trigger_who[p][trigger_who[p].IndexOf(re_skill)] = re_skill2; break; } } trigger_who[p].Remove(re_skill); break; } } } } if (broken) { break; } } } if (broken) { break; } } while (skill_table.ContainsKey(triggerEvent) && skill_table[triggerEvent].Count != triggerable_tested.Count && string.IsNullOrEmpty(room.PreWinner)); // @todo_Slob: for drawing cards when game starts -- stupid design of triggering no player! if (!broken && trigger_who.ContainsKey(rule_player) && trigger_who[rule_player].Count > 0) { List <TriggerStruct> triggers = new List <TriggerStruct>(trigger_who[rule_player]); foreach (TriggerStruct s in triggers) { if (!string.IsNullOrEmpty(room.PreWinner)) { break; } TriggerSkill skill = null; foreach (TriggerSkill rule in rules) { // because we cannot get a GameRule with Engine::getTriggerSkill() if (rule.Name == s.SkillName) { skill = rule; break; } } TriggerStruct skill_cost = skill.Cost(triggerEvent, room, target, ref data, null, s); if (!string.IsNullOrEmpty(skill_cost.SkillName)) { broken = skill.Effect(triggerEvent, room, target, ref data, null, skill_cost); if (broken) { break; } } } } foreach (TrustedAI ai in room.AIs) { ai.Event(triggerEvent, target, data); } //Bot聊天 Bot.BotChat(triggerEvent, room, target, data); //成就 AchieveCollector.Event(triggerEvent, room, target, data); // pop event stack //event_stack.pop_back(); //room->tryPause(); trigger_count.Remove(trigger_id); return(broken); }