public override WrappedCard AskForSinglePeach(Player dying, DyingStruct dying_struct) { FunctionCard f_peach = Peach.Instance; FunctionCard f_ana = Analeptic.Instance; if (self != dying & IsFriend(dying) && (CanSave(dying, 1 - dying.Hp) || dying.GetRoleEnum() == Player.PlayerRole.Lord)) { if (dying.GetRoleEnum() != Player.PlayerRole.Lord && dying.IsNude() && !MaySave(dying) && !HasSkill(MasochismSkill)) { return(null); } List <WrappedCard> peaches = GetCards(Peach.ClassName, self); foreach (WrappedCard card in peaches) { if (f_peach.IsAvailable(room, self, card) && Engine.IsProhibited(room, self, dying, card) == null) { return(card); } } } else if (self == dying) { List <WrappedCard> peaches = new List <WrappedCard>(); foreach (WrappedCard card in GetCards(Peach.ClassName, self)) { if (f_peach.IsAvailable(room, self, card) && Engine.IsProhibited(room, self, dying, card) == null) { peaches.Add(card); } } foreach (WrappedCard card in GetCards(Analeptic.ClassName, self)) { if (f_ana.IsAvailable(room, self, card) && Engine.IsProhibited(room, self, dying, card) == null) { peaches.Add(card); } } double best = -1000; WrappedCard result = null; foreach (WrappedCard card in peaches) { double value = GetUseValue(card, self); if (card.Name == Peach.ClassName) { value -= 2; } if (value > best) { best = value; result = card; } } return(result); } return(null); }
public static List <string> GuhuoCards(Room room, Player player) { List <string> guhuos = GetGuhuoCards(room, "btd"); List <string> result = new List <string>(); foreach (string name in guhuos) { FunctionCard fcard = Engine.GetFunctionCard(name); if (fcard is Slash && name != Slash.ClassName) { continue; } if (fcard is Nullification && name != Nullification.ClassName) { continue; } if (player.ContainsTag(string.Format("shefu_{0}", name))) { continue; } result.Add(name); } return(result); }
protected virtual void OnPhaseChanging(Room room, Player player, ref object data) { PhaseChangeStruct change = (PhaseChangeStruct)data; if (change.To == PlayerPhase.NotActive) { player.SetFlags("."); RoomLogic.ClearPlayerCardLimitation(player, true); foreach (Player p in room.GetAllPlayers()) { if (p.GetMark("drank") > 0) { LogMessage log = new LogMessage { Type = "#UnsetDrankEndOfTurn", From = p.Name }; room.SendLog(log); room.SetPlayerMark(p, "drank", 0); } } if (room.ContainsTag("EdictInvoke") && (bool)room.GetTag("EdictInvoke")) { room.SetTag("EdictInvoke", false); LogMessage log = new LogMessage { Type = "#EdictEffect", From = player.Name, Arg = Edict.ClassName }; room.SendLog(log); WrappedCard io = (WrappedCard)room.GetTag("EdictCard"); if (io != null) { FunctionCard fcard = Engine.GetFunctionCard(io.Name); foreach (Player p in room.GetAllPlayers()) { if (!p.HasShownOneGeneral() && Engine.IsProhibited(room, null, p, io) == null) // from is null! { room.CardEffect(io, null, p); } } } } } else if (change.To == PlayerPhase.Play) { player.AddHistory("."); } else if (change.To == PlayerPhase.Start) { if (!player.General1Showed && Engine.GetGeneral(player.ActualGeneral1, room.Setting.GameMode).IsLord()) { room.ShowGeneral(player); } } }
public override ScoreStruct GetDamageScore(TrustedAI ai, DamageStruct damage) { ScoreStruct score = new ScoreStruct { Score = 0 }; if (damage.To != null && ai.HasSkill(Name, damage.To) && damage.Card != null) { score.Score = 1.2; FunctionCard fcard = Engine.GetFunctionCard(damage.Card.Name); if (!(fcard is SkillCard)) { foreach (int id in damage.Card.SubCards) { double value = Math.Max(ai.GetUseValue(id, damage.To, Player.Place.PlaceHand), ai.GetKeepValue(id, damage.To, Player.Place.PlaceHand)); score.Score += value * 0.45; } if (ai.WillSkipPlayPhase(damage.To)) { score.Score /= 3; } if (damage.Damage >= damage.To.Hp) { score.Score /= 2; } if (damage.From != null && damage.From == damage.To && score.Score > 0) { score.Score /= 4; } } if (damage.Damage > 1) { score.Score /= 1.5; } if (ai.WillSkipPlayPhase(damage.To)) { score.Score /= 1.5; } if (ai.IsEnemy(damage.To)) { score.Score = -score.Score; } else { score.Score -= 1.5; } } return(score); }
public static List <string> GetGuhuoCards(Room room, string type) { List <string> all = new List <string>(); List <int> cards = room.RoomCards; if (type.Contains("b")) { foreach (int id in cards) { FunctionCard card = Engine.GetFunctionCard(Engine.GetRealCard(id).Name); if (card is BasicCard && !all.Contains(card.Name)) { all.Add(card.Name); } } } if (type.Contains("t")) { foreach (int id in cards) { FunctionCard card = Engine.GetFunctionCard(Engine.GetRealCard(id).Name); if (card?.IsNDTrick() == true && !all.Contains(card.Name)) { all.Add(card.Name); } } } if (type.Contains("d")) { foreach (int id in cards) { FunctionCard card = Engine.GetFunctionCard(Engine.GetRealCard(id).Name); if (card?.IsNDTrick() == false && card is TrickCard && !all.Contains(card.Name)) { all.Add(card.Name); } } } return(all); }
public override void DamageEffect(TrustedAI ai, ref DamageStruct damage, DamageStruct.DamageStep step) { if (damage.From != null && damage.Card != null && damage.From.HasWeapon(Name) && damage.Card.Name.Contains(Slash.ClassName) && !damage.Transfer && !damage.Chain) { Room room = ai.Room; List <int> ids = ai.GetKnownCards(damage.From); foreach (int id in ids) { if (damage.Card.SubCards.Contains(id)) { continue; } WrappedCard card = room.GetCard(id); FunctionCard fcard = Engine.GetFunctionCard(card.Name); if (fcard is Slash || fcard is Weapon) { damage.Damage++; break; } } } }
public override double CardValue(TrustedAI ai, Player player, WrappedCard card, bool isUse, Player.Place place) { if (ai.HasSkill(Name) && ai.IsSituationClear()) { FunctionCard fcard = Engine.GetFunctionCard(card.Name); if (fcard is DefensiveHorse || fcard is SpecialEquip) { return(-2); } } if (!isUse && ai.IsCard(card.GetEffectiveId(), Slash.ClassName, player)) { Player jiangwei = ai.FindPlayerBySkill(Name); if (jiangwei != null && !ai.IsFriend(jiangwei, player) && RoomLogic.CanSlash(ai.Room, player, jiangwei)) { return(2); } } return(0); }
public override List <int> OnExchange(TrustedAI ai, Player player, string pattern, int min, int max, string pile) { Room room = ai.Room; if (room.GetTag(Name) is DamageStruct damage) { ScoreStruct score = ai.GetDamageScore(damage); damage.Damage++; ScoreStruct _score = ai.GetDamageScore(damage); if (_score.Score - score.Score > 3) { List <int> ids = new List <int>(); foreach (int id in player.GetCards("h")) { if (!RoomLogic.CanDiscard(room, player, player, id)) { continue; } WrappedCard card = room.GetCard(id); FunctionCard fcard = Engine.GetFunctionCard(card.Name); if (fcard is Slash || fcard is Weapon) { ids.Add(id); } } if (ids.Count > 0) { ai.SortByUseValue(ref ids, false); return(new List <int> { ids[0] }); } } } return(new List <int>()); }
public override List <WrappedCard> GetGuhuoCards(Room room, List <WrappedCard> cards, Player player) { List <WrappedCard> result = new List <WrappedCard>(); foreach (string name in GuhuoCards(room, player)) { FunctionCard fcard = Engine.GetFunctionCard(name); if (fcard is Slash && name != Slash.ClassName) { continue; } if (player.ContainsTag(string.Format("shefu_{0}", name))) { continue; } WrappedCard card = new WrappedCard(name); card.AddSubCards(cards); result.Add(card); } return(result); }
public override double UseValueAdjust(TrustedAI ai, Player player, List <Player> targets, WrappedCard card) { Room room = ai.Room; if (ai.HasSkill("nuzhan", player) && targets.Count > 0) { WrappedCard wrapped = room.GetCard(card.GetEffectiveId()); FunctionCard fcard = Engine.GetFunctionCard(wrapped.Name); if (fcard is TrickCard) { return(2); } if (fcard is EquipCard) { return(1.5); } } else if (targets.Count > 0) { return(0); } return(-1); }
public override bool Effect(TriggerEvent triggerEvent, Room room, Player player, ref object data, Player target, TriggerStruct trigger_info) { if (room.SkipGameRule) { room.SkipGameRule = false; return(false); } // Handle global events if (player == null) { if (triggerEvent == TriggerEvent.GameStart) { OnGameStart(room, ref data); } if (triggerEvent != TriggerEvent.BeforeCardsMove && triggerEvent != TriggerEvent.CardsMoveOneTime) { return(false); } } switch (triggerEvent) { case TriggerEvent.TurnStart: OnTurnStart(room, player, ref data); break; case TriggerEvent.EventPhaseProceeding: OnPhaseProceed(room, player, ref data); break; case TriggerEvent.EventPhaseEnd: OnPhaseEnd(room, player, ref data); break; case TriggerEvent.EventPhaseChanging: OnPhaseChanging(room, player, ref data); break; case TriggerEvent.PreCardUsed: OnPreCardUsed(room, player, ref data); break; case TriggerEvent.CardUsed: OnCardUsed(room, player, ref data); break; case TriggerEvent.CardFinished: CardUseStruct use = (CardUseStruct)data; //room.ClearCardFlag(use.Card); use.Card.ClearFlags(); //RoomCard会在其移动后自动清除flag room.RemoveSubCards(use.Card); //以askforcard形式使用的卡牌没有onUse的trigger,但有finish if (use.Reason != CardUseStruct.CardUseReason.CARD_USE_REASON_RESPONSE) { room.RemoveUseOnFinish(); } if (Engine.GetFunctionCard(use.Card.Name).IsNDTrick()) { room.RemoveHegNullification(use.Card); } foreach (Client p in room.Clients) { room.DoNotify(p, CommandType.S_COMMAND_NULLIFICATION_ASKED, new List <string> { "." }); } break; case TriggerEvent.EventAcquireSkill: case TriggerEvent.EventLoseSkill: InfoStruct info = (InfoStruct)data; string skill_name = info.Info; Skill skill = Engine.GetSkill(skill_name); bool refilter = skill is FilterSkill; if (!refilter && skill is TriggerSkill) { TriggerSkill trigger = (TriggerSkill)skill; ViewAsSkill vsskill = trigger.ViewAsSkill; if (vsskill != null && (vsskill is FilterSkill)) { refilter = true; } } if (refilter) { room.FilterCards(player, player.GetCards("he"), triggerEvent == TriggerEvent.EventLoseSkill); } CheckBigKingdoms(room); break; case TriggerEvent.PostHpReduced: if (player.Hp > 0 || player.HasFlag("Global_Dying")) // newest GameRule -- a player cannot enter dying when it is dying. { break; } if (data is DamageStruct damage) { room.EnterDying(player, damage); } else { room.EnterDying(player, new DamageStruct()); } break; case TriggerEvent.AskForPeaches: OnAskforPeach(room, player, ref data); break; case TriggerEvent.AskForPeachesDone: { if (player.Hp <= 0 && player.Alive) { DyingStruct dying = (DyingStruct)data; room.KillPlayer(player, dying.Damage); } break; } case TriggerEvent.ConfirmDamage: { break; } case TriggerEvent.DamageDone: { damage = (DamageStruct)data; if (damage.From != null && !damage.From.Alive) { damage.From = null; } room.SendDamageLog(damage); if (damage.Nature != DamageNature.Normal && player.Chained && !damage.Chain && !damage.ChainStarter) { damage.ChainStarter = true; } data = damage; bool reduce = !room.ApplyDamage(player, damage); if (reduce) { room.RoomThread.Trigger(TriggerEvent.PostHpReduced, room, player, ref data); } break; } case TriggerEvent.DamageComplete: { damage = (DamageStruct)data; if (damage.Prevented) { return(false); } /* * if (damage.Nature != DamageNature.Normal && player.Chained) * { * room.ChainedRemoveOnDamageDone(player, damage); * } */ if (damage.Nature != DamageNature.Normal && !damage.Chain && damage.ChainStarter) // iron chain effect { List <Player> chained_players = new List <Player>(); if (!room.Current.Alive) { chained_players = room.GetOtherPlayers(room.Current); } else { chained_players = room.GetAllPlayers(); } chained_players.Remove(damage.To); foreach (Player chained_player in chained_players) { if (chained_player.Chained) { Thread.Sleep(500); LogMessage log = new LogMessage { Type = "#IronChainDamage", From = chained_player.Name }; room.SendLog(log); DamageStruct chain_damage = damage; chain_damage.To = chained_player; chain_damage.Chain = true; chain_damage.Transfer = false; chain_damage.TransferReason = null; room.Damage(chain_damage); } } } foreach (Player p in room.GetAllPlayers()) { if (p.HasFlag("Global_DFDebut")) { p.SetFlags("-Global_DFDebut"); room.RoomThread.Trigger(TriggerEvent.DFDebut, room, p); } } break; } case TriggerEvent.CardEffect: { if (data is CardEffectStruct effect) { if (Engine.GetFunctionCard(effect.Card.Name) is DelayedTrick) { CardMoveReason reason = new CardMoveReason(MoveReason.S_REASON_DELAYTRICK_EFFECT, effect.To.Name, effect.Card.Skill, effect.Card.Name) { Card = effect.Card }; room.MoveCardTo(effect.Card, effect.To, Place.PlaceTable, reason, true); Thread.Sleep(500); } } break; } case TriggerEvent.CardEffected: { if (data is CardEffectStruct effect) { FunctionCard fcard = Engine.GetFunctionCard(effect.Card.Name); if (!(fcard is Slash) && effect.BasicEffect.Nullified) { LogMessage log = new LogMessage { Type = "#Cardnullified", From = effect.To.Name, Arg = effect.Card.Name }; room.SendLog(log); return(true); } else if (fcard.TypeID == CardType.TypeTrick && room.IsCanceled(effect)) { effect.To.SetFlags("Global_NonSkillnullify"); return(true); } object _effect = effect; room.RoomThread.Trigger(TriggerEvent.CardEffectConfirmed, room, effect.To, ref _effect); if (effect.To.Alive || fcard is Slash) { fcard.OnEffect(room, effect); } } break; } case TriggerEvent.SlashEffected: { SlashEffectStruct effect = (SlashEffectStruct)data; if (effect.Nullified) { LogMessage log = new LogMessage { Type = "#Cardnullified", From = effect.To.Name, Arg = effect.Slash.Name }; room.SendLog(log); return(true); } if (effect.Jink_num > 0) { room.RoomThread.Trigger(TriggerEvent.SlashProceed, room, effect.From, ref data); } else { room.SlashResult(effect, null); } break; } case TriggerEvent.SlashProceed: { SlashEffectStruct effect = (SlashEffectStruct)data; string slasher = effect.From.Name; if (!effect.To.Alive) { break; } if (effect.Jink_num == 1) { CardResponseStruct resp = room.AskForCard(effect.To, Slash.ClassName, Jink.ClassName, string.Format("slash-jink:{0}::{1}", slasher, effect.Slash.Name), data, HandlingMethod.MethodUse, null, effect.From, false, false); room.SlashResult(effect, room.IsJinkEffected(effect.To, resp) ? resp.Card : null); } else { WrappedCard jink = new WrappedCard(DummyCard.ClassName); for (int i = effect.Jink_num; i > 0; i--) { string prompt = string.Format("@multi-jink{0}:{1}::{2}:{3}", i == effect.Jink_num ? "-start" : string.Empty, slasher, i, effect.Slash.Name); CardResponseStruct resp = room.AskForCard(effect.To, Slash.ClassName, Jink.ClassName, prompt, data, HandlingMethod.MethodUse, null, effect.From, false, false); if (!room.IsJinkEffected(effect.To, resp)) { //delete jink; room.SlashResult(effect, null); return(false); } else { jink.AddSubCard(resp.Card); } } room.SlashResult(effect, jink); } break; } case TriggerEvent.SlashHit: { SlashEffectStruct effect = (SlashEffectStruct)data; if (effect.Drank > 0) { LogMessage log = new LogMessage { Type = "#AnalepticBuff", From = effect.From.Name, To = new List <string> { effect.To.Name }, Arg = (1 + effect.ExDamage).ToString(), Arg2 = (1 + effect.ExDamage + effect.Drank).ToString() }; room.SendLog(log); } DamageStruct slash_damage = new DamageStruct(effect.Slash, effect.From, effect.To, 1 + effect.ExDamage + effect.Drank, effect.Nature) { Drank = effect.Drank > 0 }; room.Damage(slash_damage); break; } case TriggerEvent.BeforeGameOverJudge: { if (!player.General1Showed) { room.ShowGeneral(player, true, false, false); } if (!player.General2Showed) { room.ShowGeneral(player, false, false, false); } break; } case TriggerEvent.GameOverJudge: { string winner = GetWinner(room); if (!string.IsNullOrEmpty(winner)) { room.GameOver(winner); return(true); } break; } case TriggerEvent.BuryVictim: { OnBuryVictim(room, player, ref data); break; } case TriggerEvent.StartJudge: { int card_id = room.GetNCards(1)[0]; JudgeStruct judge_struct = (JudgeStruct)data; judge_struct.Card = room.GetCard(card_id); LogMessage log = new LogMessage { Type = "$InitialJudge", From = judge_struct.Who.Name, Card_str = card_id.ToString() }; room.SendLog(log); room.MoveCardTo(judge_struct.Card, null, judge_struct.Who, Place.PlaceJudge, new CardMoveReason(MoveReason.S_REASON_JUDGE, judge_struct.Who.Name, null, null, judge_struct.Reason), true); Thread.Sleep(500); bool effected = judge_struct.Good == Engine.MatchExpPattern(room, judge_struct.Pattern, judge_struct.Who, judge_struct.Card); judge_struct.UpdateResult(effected); data = judge_struct; break; } case TriggerEvent.JudgeResult: { JudgeStruct judge = (JudgeStruct)data; LogMessage log = new LogMessage { Type = "$JudgeResult", From = player.Name, Card_str = RoomLogic.CardToString(room, judge.Card) }; room.SendLog(log); //Thread.Sleep(500); if (judge.PlayAnimation) { room.SendJudgeResult(judge); Thread.Sleep(800); } break; } case TriggerEvent.FinishJudge: { JudgeStruct judge = (JudgeStruct)data; if (room.GetCardPlace(judge.Card.Id) == Place.PlaceJudge) { CardMoveReason reason = new CardMoveReason(MoveReason.S_REASON_JUDGEDONE, judge.Who.Name, null, judge.Reason); room.MoveCardTo(judge.Card, judge.Who, null, Place.DiscardPile, reason, true); } break; } case TriggerEvent.ChoiceMade: { foreach (Player p in room.GetAlivePlayers()) { List <string> flags = new List <string>(p.Flags); foreach (string flag in flags) { if (flag.StartsWith("Global_") && flag.EndsWith("Failed")) { p.SetFlags("-" + flag); } } } break; } case TriggerEvent.GeneralShown: { string winner = GetWinner(room); if (!string.IsNullOrEmpty(winner)) { room.GameOver(winner); // if all hasShownGenreal, and they are all friend, game over. return(true); } if (!room.ContainsTag("TheFirstToShowRewarded")) { room.SetTag("TheFirstToShowRewarded", true); room.SetPlayerMark(player, "@pioneer", 1); room.AttachSkillToPlayer(player, "pioneer"); } if (player.Alive && player.HasShownAllGenerals()) { if (player.GetMark("CompanionEffect") > 0) { room.RemovePlayerMark(player, "CompanionEffect"); room.DoSuperLightbox(player, string.Empty, "companion"); room.SetPlayerMark(player, "@companion", 1); room.AttachSkillToPlayer(player, "companion"); } if (player.GetMark("HalfMaxHpLeft") > 0) { room.RemovePlayerMark(player, "HalfMaxHpLeft"); room.SetPlayerMark(player, "@megatama", 1); room.AttachSkillToPlayer(player, "megatama"); } } CheckBigKingdoms(room); break; } case TriggerEvent.BeforeCardsMove: { if (data is CardsMoveOneTimeStruct move) { bool should_find_io = false; if (move.To_place == Place.DiscardPile) { if (move.Reason.Reason != MoveReason.S_REASON_USE) { should_find_io = true; // not use } else if (move.Card_ids.Count > 1) { should_find_io = true; // use card isn't IO } else { WrappedCard card = room.GetCard(move.Card_ids[0]); if (card.Name == Edict.ClassName && !card.HasFlag("edict_normal_use")) { should_find_io = true; // use card isn't IO } } } if (should_find_io) { foreach (int id in move.Card_ids) { WrappedCard card = room.GetCard(id); if (card.Name == Edict.ClassName) { room.MoveCardTo(card, null, Place.PlaceTable, true); room.AddToPile(room.Players[0], "#edict", card, false); LogMessage log = new LogMessage { Type = "#RemoveEdict", Arg = Edict.ClassName }; room.SendLog(log); room.SetTag("EdictInvoke", true); room.SetTag("EdictCard", card); int i = move.Card_ids.IndexOf(id); move.From_places.RemoveAt(i); move.Open.RemoveAt(i); move.From_pile_names.RemoveAt(i); move.Card_ids.Remove(id); data = move; break; } } } } break; } case TriggerEvent.Death: { OnDeath(room, player, ref data); break; } case TriggerEvent.CardsMoveOneTime: { if (data is CardsMoveOneTimeStruct move) { if (move.From != null && move.From_places.Contains(Place.PlaceEquip)) { foreach (int id in move.Card_ids) { WrappedCard card = room.GetCard(id); if (card.Name == JadeSeal.ClassName) { CheckBigKingdoms(room); break; } } } if (move.To != null && move.To_place == Place.PlaceEquip) { foreach (int id in move.Card_ids) { WrappedCard card = room.GetCard(id); if (card.Name == JadeSeal.ClassName) { CheckBigKingdoms(room); break; } } } } break; } default: break; } return(false); }
protected virtual void OnCardUsed(Room room, Player player, ref object data) { if (data is CardUseStruct card_use) { RoomThread thread = room.RoomThread; FunctionCard fcard = Engine.GetFunctionCard(card_use.Card.Name); WrappedCard card = card_use.Card; if (fcard.HasPreact) { fcard.DoPreAction(room, player, card); data = card_use; } room.AddUseList(card_use); card_use.EffectCount = new List <CardBasicEffect>(); foreach (Player p in card_use.To) { card_use.EffectCount.Add(fcard.FillCardBasicEffct(room, p)); } data = card_use; if (card_use.From != null) { thread.Trigger(TriggerEvent.TargetChoosing, room, card_use.From, ref data); CardUseStruct new_use = (CardUseStruct)data; } card_use = (CardUseStruct)data; if (card_use.From != null && card_use.To.Count > 0) { foreach (CardBasicEffect effect in card_use.EffectCount) { effect.Triggered = false; } while (card_use.EffectCount.Count > 0) { bool check = true; int count = card_use.EffectCount.Count; for (int i = 0; i < count; i++) { CardBasicEffect effect = card_use.EffectCount[i]; if (!effect.Triggered) { check = false; thread.Trigger(TriggerEvent.TargetConfirming, room, effect.To, ref data); effect.Triggered = true; break; } } if (check) { break; } card_use = (CardUseStruct)data; } } card_use = (CardUseStruct)data; if (card_use.From != null && card_use.To.Count > 0) { thread.Trigger(TriggerEvent.TargetChosen, room, card_use.From, ref data); for (int i = 0; i < card_use.EffectCount.Count; i++) { CardBasicEffect effect = card_use.EffectCount[i]; effect.Triggered = false; thread.Trigger(TriggerEvent.TargetConfirmed, room, effect.To, ref data); effect.Triggered = true; } } card_use = (CardUseStruct)data; fcard.Use(room, card_use); } }
protected virtual void OnPhaseProceed(Room room, Player player, ref object data) { switch (player.Phase) { case PlayerPhase.Judge: { List <int> tricks = new List <int>(player.JudgingArea); while (tricks.Count > 0 && player.Alive) { WrappedCard trick = room.GetCard(tricks[tricks.Count - 1]); tricks.RemoveAt(tricks.Count - 1); bool on_effect = room.CardEffect(trick, null, player); if (!on_effect) { FunctionCard card = Engine.GetFunctionCard(trick.Name); card.OnNullified(room, player, trick); } } break; } case PlayerPhase.Draw: { int num = (int)data; if (num > 0) { room.DrawCards(player, num, "gamerule"); } room.RoomThread.Trigger(TriggerEvent.AfterDrawNCards, room, player, ref data); break; } case PlayerPhase.Play: { bool add_index = true; while (player.Alive && string.IsNullOrEmpty(room.PreWinner)) { room.Activate(player, out CardUseStruct card_use, add_index); if (card_use.Card != null) { add_index = room.UseCard(card_use); } else { break; } } break; } case PlayerPhase.Discard: { List <int> handcards = new List <int>(); foreach (int id in player.GetCards("h")) { if (!Engine.IgnoreHandCard(room, player, id)) { handcards.Add(id); } } int discard_num = handcards.Count - RoomLogic.GetMaxCards(room, player); if (discard_num > 0) { room.AskForDiscard(player, handcards, "gamerule", discard_num, discard_num); } break; } default: break; } }
protected virtual void OnCardUsed(Room room, Player player, ref object data) { if (data is CardUseStruct card_use) { RoomThread thread = room.RoomThread; FunctionCard fcard = Engine.GetFunctionCard(card_use.Card.Name); WrappedCard card = card_use.Card; if (fcard.HasPreact) { fcard.DoPreAction(room, player, card); data = card_use; } List <Player> targets = card_use.To; List <CardUseStruct> use_list = room.ContainsTag("card_proceeing") ? (List <CardUseStruct>)room.GetTag("card_proceeing") : new List <CardUseStruct>(); //for serval purpose, such as AI use_list.Add(card_use); room.SetTag("card_proceeing", use_list); if (card_use.From != null) { thread.Trigger(TriggerEvent.TargetChoosing, room, card_use.From, ref data); CardUseStruct new_use = (CardUseStruct)data; targets = new_use.To; } if (card_use.From != null && targets.Count > 0) { List <Player> targets_copy = new List <Player>(targets); foreach (Player to in targets_copy) { if (targets.Contains(to)) { thread.Trigger(TriggerEvent.TargetConfirming, room, to, ref data); CardUseStruct new_use = (CardUseStruct)data; targets = new_use.To; if (targets.Count == 0) { break; } } } } card_use = (CardUseStruct)data; if (card_use.From != null && card_use.To.Count > 0) { thread.Trigger(TriggerEvent.TargetChosen, room, card_use.From, ref data); foreach (Player p in card_use.To) { thread.Trigger(TriggerEvent.TargetConfirmed, room, p, ref data); } } card_use = (CardUseStruct)data; if (card_use.NullifiedList != null) { room.SetTag("CardUseNullifiedList", card_use.NullifiedList); } fcard.Use(room, card_use); } }
public override void Event(TriggerEvent triggerEvent, Player player, object data) { if (!self.Alive) { return; } base.Event(triggerEvent, player, data); if (triggerEvent == TriggerEvent.EventPhaseStart || triggerEvent == TriggerEvent.BuryVictim) { UpdatePlayers(); } if (triggerEvent == TriggerEvent.CardsMoveOneTime && data is CardsMoveOneTimeStruct move) { bool open = false; bool pile_open = false; Player from = move.From; Player to = move.To; foreach (Player p in room.GetAlivePlayers()) { if (p.HasFlag("Global_GongxinOperator") && (p == self || self.IsSameCamp(p))) { open = true; break; } } if ((from != null && (from == self || self.IsSameCamp(from))) || (to != null && (to == self || self.IsSameCamp(to)) && move.To_place != Player.Place.PlaceSpecial)) { open = true; } if (!open && to != null && !string.IsNullOrEmpty(move.To_pile_name) && !move.To_pile_name.StartsWith("#") && move.To != null) { if (move.To.GetPileOpener(move.To_pile_name).Count == room.GetAllPlayers(true).Count) { pile_open = true; } else { foreach (string name in move.To.GetPileOpener(move.To_pile_name)) { Player who = room.FindPlayer(name, true); if (who != null && (who == self || self.IsSameCamp(who))) { open = true; break; } } } } if (to != null && move.To_place == Player.Place.PlaceHand) { foreach (int id in move.Card_ids) { int index = move.Card_ids.IndexOf(id); WrappedCard card = room.GetCard(id); if (card.HasFlag("visible") || pile_open || move.From_places[index] == Player.Place.PlaceEquip || move.From_places[index] == Player.Place.PlaceDelayedTrick || move.From_places[index] == Player.Place.DiscardPile || move.From_places[index] == Player.Place.PlaceTable) { public_handcards[to].Add(id); private_handcards[to].Add(id); ClearCardLack(to, id); } else if (open) { private_handcards[to].Add(id); ClearCardLack(to, id); } else { ClearCardLack(to); } } } if (to != null && move.To_place == Player.Place.PlaceSpecial && move.To_pile_name == "wooden_ox") { foreach (int id in move.Card_ids) { if (open) { wooden_cards[to].Add(id); } } } if (from != null && move.From_places.Contains(Player.Place.PlaceHand)) { foreach (int id in move.Card_ids) { if (room.GetCard(id).HasFlag("visible") || pile_open || move.To_place == Player.Place.PlaceEquip || move.To_place == Player.Place.PlaceDelayedTrick || move.To_place == Player.Place.DiscardPile || move.To_place == Player.Place.PlaceTable) { public_handcards[from].RemoveAll(t => t == id); private_handcards[from].RemoveAll(t => t == id); } else { public_handcards[from].Clear(); if (open) { private_handcards[from].RemoveAll(t => t == id); } else { private_handcards[from].Clear(); } } } } if (from != null && move.From_places.Contains(Player.Place.PlaceSpecial) && move.From_pile_names.Contains("wooden_ox")) { foreach (int id in move.Card_ids) { int index = move.Card_ids.IndexOf(id); if (open && move.From_pile_names[index] == "wooden_ox" && move.From_places[index] == Player.Place.PlaceSpecial) { wooden_cards[move.From].RemoveAll(t => t == id); } } } foreach (int id in move.Card_ids) { int index = move.Card_ids.IndexOf(id); WrappedCard card = room.GetCard(id); if (move.From_places[index] == Player.Place.DrawPile) { if (move.To != null && move.To_place == Player.Place.PlaceHand && card.HasFlag("visible2" + self.Name)) { private_handcards[move.To].Add(id); } if (guanxing.Key != null && guanxing.Value.Contains(id)) { if (guanxing.Value[0] != id) { List <int> top_cards = new List <int>(guanxing.Value); for (int y = top_cards.IndexOf(id); y < top_cards.Count; y++) { guanxing.Value.RemoveAt(y); } } else { guanxing.Value.RemoveAll(t => t == id); } if (guanxing.Value.Count == 0) { guanxing = new KeyValuePair <Player, List <int> >(); } } } } } if (triggerEvent == TriggerEvent.CardTargetAnnounced && data is CardUseStruct use) { FunctionCard fcard = Engine.GetFunctionCard(use.Card.Name); string class_name = fcard.Name; if (fcard is Slash) { class_name = Slash.ClassName; } UseCard e = Engine.GetCardUsage(class_name); if (e != null) { e.OnEvent(this, triggerEvent, player, data); } } if (triggerEvent == TriggerEvent.ChoiceMade && data is string str) { List <string> choices = new List <string>(str.Split(':')); foreach (SkillEvent e in skill_events.Values) { if (e.Key.Contains(choices[0])) { e.OnEvent(this, triggerEvent, player, data); } } foreach (UseCard e in Engine.GetCardUsages()) { if (e.Key.Contains(choices[0])) { e.OnEvent(this, triggerEvent, player, data); } } if (choices[0] == "viewCards") { List <int> ids = player.GetCards("h"); if (choices[choices.Count - 1] == "all") { public_handcards[player] = ids; private_handcards[player] = ids; } else if (choices[choices.Count - 1] == self.Name) { private_handcards[player] = ids; } } else if (choices[0] == "showCards") { List <int> ids = JsonUntity.StringList2IntList(new List <string>(choices[2].Split('+'))); if (choices[choices.Count - 1] == "all") { foreach (int id in ids) { if (!public_handcards[player].Contains(id)) { public_handcards[player].Add(id); } if (!private_handcards[player].Contains(id)) { private_handcards[player].Add(id); } } } else if (choices[choices.Count - 1] == self.Name) { foreach (int id in ids) { if (!private_handcards[player].Contains(id)) { private_handcards[player].Add(id); } } } } else if (choices[0] == "cardShow") { int id = int.Parse(choices[choices.Count - 1].Substring(1, choices[choices.Count - 1].Length - 2)); if (!public_handcards[player].Contains(id)) { public_handcards[player].Add(id); } if (!private_handcards[player].Contains(id)) { private_handcards[player].Add(id); } } else if (choices[0] == "ViewTopCards" || choices[0] == "ViewBottomCards") { bool open = choices[choices.Count - 1] == "open"; List <int> drawpile = new List <int>(room.DrawPile); List <int> moves = JsonUntity.StringList2IntList(new List <string>(choices[2].Split('+'))); if (choices[0] == "ViewTopCards") { guanxing = new KeyValuePair <Player, List <int> >(); if (open) { for (int index = 0; index < moves.Count; index++) { int id = moves[index]; room.SetCardFlag(id, "visible"); } } else { foreach (int id in moves) { if (player == self || player.IsSameCamp(self)) { room.SetCardFlag(id, "visible2" + self.Name); } } guanxing = new KeyValuePair <Player, List <int> >(player, moves); } } else { if (open) { for (int index = 0; index < moves.Count; index++) { int id = moves[index]; room.SetCardFlag(id, "visible"); } } else { foreach (int id in moves) { room.SetCardFlag(id, "visible2" + choices[1]); } } } } } }