public void TargetIsNull_DoesNoDamage() { AttackSkill attack = Data.AttackSkill.SetDamage(100); attack.Attack(null); _target.DidNotReceive().TakeDamage(Arg.Any <int>()); }
public override void Enter() { base.Enter(); Vector2Int target; List <Vector2Int> rangeList; parent.SelectedCharacter.GetSkillRange(out target, out rangeList); for (int i = 0; i < rangeList.Count; i++) { if (rangeList[i] == target) { TilePainter.Instance.Painting("FrontSight", 4, rangeList[i]); } else { TilePainter.Instance.Painting("YellowGrid", 2, rangeList[i]); } } _targetList.Clear(); if (parent.SelectedCharacter.SelectedSkill is AttackSkill) { AttackSkill attackSkill = (AttackSkill)parent.SelectedCharacter.SelectedSkill; _targetList = attackSkill.GetTargetList(); int damage; for (int i = 0; i < _targetList.Count; i++) { damage = attackSkill.CalculateDamage(parent.SelectedCharacter.Info, _targetList[i].Info, false, false); BattleUI.Instance.SetPredictionHP(_targetList[i], damage); } } }
public void OffCooldown_AppliesDamageToDamagable([Values(10, 0)] int damage) { AttackSkill attack = Data.AttackSkill.SetDamage(damage); attack.Attack(_target); _target.Received().TakeDamage(damage); }
public virtual bool ApplyEffects(Skill effect) { AttackSkill skill = effect as AttackSkill; if (skill == null) { return(false); } switch (skill.applyTo) { case AttackSkill.ApplyTo.Attack: attackDamage += effect.Effect(); return(true); case AttackSkill.ApplyTo.Speed: attackSpeed *= effect.Effect(); if (attackSpeed.Multiplier < 0.5f) { attackSpeed.Multiplier = 0.5f; } return(true); default: break; } return(false); }
/* 공격 받을 때 호출되는 함수 */ public override void OnHitAttack(AttackSkill _skill) { //무적 상태에 있으면 공격받지 않음 if (!isAttackable) { return; } Debug.Log("[ " + name + " ]" + " Take [" + _skill.damage + "] Damage From [ " + _skill.skillCaster.name + " ]"); SetInvincibleTime(status.GetGPT()); playerAnimation.ShowGetDamage(); //스탯에 피해량(damage) 정보를 넘김 status.TakeDamage(_skill.damage); playerMove.HitStun(); if (_skill.isKnockBack) { playerMove.KnockBack(_skill.skillDirection * _skill.knockBackPower); } //현재 체력이 바닥났을 경우 if (status.currentHP <= 0) { PlayerDead(); } }
public bool IsValidInput(int playerIndex, Note.Button but, InputManager.InputType type) { Player targetPlayer = Player[playerIndex]; if (playerIndex == AttackerIndex) { AttackSkill skill = targetPlayer.GetAttackSkill(but); // skill is not long button -> ignore long button input if (!skill.IsLongButton && (type == InputManager.InputType.KEEP || type == InputManager.InputType.UP)) { return(false); } // UP or KEEP signal came without DOWN signal -> ignore input if (LastButton != but && (type == InputManager.InputType.KEEP || type == InputManager.InputType.UP)) { return(false); } return(true); } else { // ignore long button input if (type == InputManager.InputType.KEEP || type == InputManager.InputType.UP) { return(false); } return(true); } }
private void reaction() { IBattleable attacker = prosessingPair.Key; AttackSkill useSkill = prosessingPair.Value; choseReaction = ai.decideReaction(attacker, useSkill); }
public override void Attack() { Vector3 Position = new Vector3(CharacterRigidBody.position.x, CharacterRigidBody.position.y, 0); Vector2 VelocityNormal2D = new Vector2(CharacterRigidBody.velocity.normalized.x, CharacterRigidBody.velocity.normalized.y); Vector3 VelocityNormal3D = new Vector3(VelocityNormal2D.x, VelocityNormal2D.y, 0); AttackSkill.Use(Position, VelocityNormal3D, tag); // Set the Tag of the projectile to use Tag from ICharacterTag }
public void TwoAttacksWithinCooldown_AppliesDamageOnce() { AttackSkill attack = Data.AttackSkill.SetDamage(10).SetCooldown(1); attack.Attack(_target); attack.ReduceCooldown(0.75f); attack.Attack(_target); _target.Received(1).TakeDamage(10); }
public static bool Prefix(AttackSkill __instance, bool _TryingToActivate, ref bool __result) { var self = __instance; if (self.OwnerCharacter && self.OwnerCharacter.CurrentWeapon is ProjectileWeapon bow && bow.ItemID == ManaBowID) { __result = true; return(false); }
// Token: 0x06000027 RID: 39 RVA: 0x00002910 File Offset: 0x00000B10 public static void Postfix(AttackSkill __instance, List <Weapon.WeaponType> __state) { bool flag = __state != null; if (flag) { __instance.RequiredWeaponTypes = __state; } }
// Token: 0x0600002A RID: 42 RVA: 0x00002A04 File Offset: 0x00000C04 public static void Postfix(AttackSkill ___m_attackSkill, List <Weapon.WeaponType> __state) { bool flag = __state != null && ___m_attackSkill != null; if (flag) { ___m_attackSkill.RequiredWeaponTypes = __state; } }
protected override void addInstance(string[] datas) { var skill = new AttackSkill(datas); dataTable.Add(skill); SkillBookDataManager.getInstance().setData(skill); progressTable.Add(int.Parse(datas[0]), new ActiveAttackSkillProgress()); }
protected override void setParameter() { observeSkill = AttackSkillMasterManager.getInstance().getAttackSkillFromId(OBSERVE_SKILL_ID); this.observeSkill = AttackSkillMasterManager.getInstance().getAttackSkillFromId(OBSERVE_SKILL_ID); this.attack = observeSkill.getRawAttack(); this.hit = observeSkill.getRawHit(); this.cost = observeSkill.getRawCost(); this.delay = observeSkill.getRawDelay(); }
private void ShowDisplay() { dropdownAttackSkill.gameObject.SetActive(true); dropdownSupportSkill.gameObject.SetActive(true); attackSkillList = new List <string>() { "None" }; supportSkillList = new List <string>() { "None" }; attackSkills = new Dictionary <int, AttackSkill>(); supportSkills = new Dictionary <int, SupportSkill>(); int indexAttack = 1; int indexSupport = 1; for (int i = 0; i < Referee.Instance.CritterPlayer.MoveSet.Length; i++) { if (Referee.Instance.CritterPlayer.MoveSet[i] is AttackSkill) { AttackSkill skill = Referee.Instance.CritterPlayer.MoveSet[i] as AttackSkill; attackSkillList.Add(skill.name); attackSkills.Add(indexAttack++, skill); } else { SupportSkill skill = Referee.Instance.CritterPlayer.MoveSet[i] as SupportSkill; supportSkillList.Add(skill.name); supportSkills.Add(indexSupport++, skill); } } dropdownAttackSkill.AddOptions(attackSkillList); if (attackSkillList.Count <= 1) { dropdownAttackSkill.gameObject.SetActive(false); } else { dropdownAttackSkill.Show(); } dropdownSupportSkill.AddOptions(supportSkillList); if (supportSkillList.Count <= 1) { dropdownSupportSkill.gameObject.SetActive(false); } else { dropdownSupportSkill.Show(); } }
public void CalculateOnClick() { CalculaterGroup[0].SetData(); CalculaterGroup[1].SetData(); //Skill skill = SkillFactory.GetNewSkill(int.Parse(SkillInputField.text), CalculaterGroup[0].Info, 1); //等級暫時填1 AttackSkill skill = new AttackSkill(Convert.ToBoolean(SkillTypeDropDown.value), int.Parse(SkillInputField.text)); int damage = skill.CalculateDamage(CalculaterGroup[0].Info, CalculaterGroup[1].Info, false, false); ResultLabel.text = CalculaterGroup[0].Info.Name + " 對 " + CalculaterGroup[1].Info.Name + " 造成了 " + damage + " 傷害"; }
private void Attack(AttackSkill attackSkill) { float damage = Referee.Instance.CritterPlayer.AttackDamage(attackSkill, Referee.Instance.CritterEnemy); Referee.Instance.CritterEnemy.TakeDamage(damage); string msg = $"Used {attackSkill.Name} \nDamage {damage}"; EndAction(msg); }
// Start is called before the first frame update void Start() { hpText1.text = critter2.getHp().ToString() + " HP"; hpText2.text = critter1.getHp().ToString() + " HP"; attackSkill = new AttackSkill("Hit", 10, 2); attackSkill2 = new AttackSkill("Smash", 8, 0); attackSkill3 = new AttackSkill("Special", 8, 0); supportSkill1 = new SupportSkill("AtkUp"); supportSkill2 = new SupportSkill("DefenseUp"); supportSkill3 = new SupportSkill("SpdDwn"); }
public static void Prefix(WeaponDamage __instance, ref AttackSkill ___m_attackSkill, out List <Weapon.WeaponType> __state) { __state = null; AttackSkill attackSkill = ___m_attackSkill; Weapon weapon; if (attackSkill == null) { weapon = null; } else { Character ownerCharacter = attackSkill.OwnerCharacter; weapon = ((ownerCharacter != null) ? ownerCharacter.CurrentWeapon : null); } Weapon weapon2 = weapon; bool flag = weapon2 != null; if (flag) { Weapon.WeaponType valueOrDefault; bool flag2; if (___m_attackSkill.RequiredWeaponTypes != null) { Weapon.WeaponType?bastardType = BehaviourManager.GetBastardType(weapon2.Type); if (bastardType != null) { valueOrDefault = bastardType.GetValueOrDefault(); flag2 = true; } else { flag2 = false; } } else { flag2 = false; } bool flag3 = flag2; if (flag3) { bool flag4 = ___m_attackSkill.RequiredWeaponTypes.Contains(valueOrDefault) && !___m_attackSkill.RequiredWeaponTypes.Contains(weapon2.Type) && BehaviourManager.IsBastardMode(weapon2); if (flag4) { __state = ___m_attackSkill.RequiredWeaponTypes; ___m_attackSkill.RequiredWeaponTypes = new List <Weapon.WeaponType>(__state); ___m_attackSkill.RequiredWeaponTypes.Add(weapon2.Type); } } } }
public void PressUp(int playerIndex, Note.Button but) { Player targetPlayer = Player[playerIndex]; AttackSkill skill = targetPlayer.GetAttackSkill(but); if (skill.IsLongButton && playerIndex == AttackerIndex && but == LastButton && LastType != InputManager.InputType.UP) { targetPlayer.Anim.SetTrigger("hit"); LastButton = Note.Button.NONE; LastType = InputManager.InputType.NONE; } }
/// <summary> /// ダメージを与えられます /// </summary> private void dammage() { IBattleable attacker = prosessingPair.Key; AttackSkill useSkill = prosessingPair.Value; int atk = useSkill.getAtk(attacker); int hit = useSkill.getHit(attacker); choseReaction.reaction(user, atk, hit, useSkill.getAttackSkillAttribute()); waitingReactionActiveSkills.Remove(prosessingPair); updateProsessingPair(); choseReaction = ReactionSkillMasterManager.getInstance().getReactionSkillFromId(2); }
public void Skill_1_click() { if (StatAll.stat[0, 0, Turns.order] == 2) { if (C122 == true) { AreaSkill.AttackArea(StatAll.stat[5, 3, Turns.order], 1); } else { AttackSkill.Attacking(StatAll.stat[5, 3, Turns.order], 1); } } }
/// <summary> /// ReactionSkillを使用します /// </summary> private void reaction() { ReactionSkill reactionSkill = waitingProgressSkills[0].Key; IBattleable attacker = waitingProgressSkills[0].Value.Key; AttackSkill skill = waitingProgressSkills[0].Value.Value; deleteTargetingLine(attacker); int atk = skill.getAtk(attacker); int hit = skill.getHit(attacker); reactionSkill.reaction(player, atk, hit, skill.getAttackSkillAttribute()); waitingProgressSkills.Remove(waitingProgressSkills[0]); needToProgressReaction = true; updateProsessingPair(); }
public void offerReaction(IBattleable attacker, AttackSkill skill) { KeyValuePair <IBattleable, AttackSkill> pair = new KeyValuePair <IBattleable, AttackSkill>(attacker, skill); waitingDecideReactionSkills.Add(pair); List <IBattleable> drawLineTarget = new List <IBattleable>() { player }; drawTargetingLine(attacker, drawLineTarget, skill.getName(), skill.isFriendly()); updateProsessingPair(); }
/// <summary> /// リアクションを決定します /// </summary> /// <returns>決定したリアクションスキル</returns> /// <param name="attacker">攻撃者</param> /// <param name="skill">攻撃されるスキル</param> public ReactionSkill decideReaction(IBattleable attacker, AttackSkill skill) { Dictionary <ReactionSkillType, float> riskTable = new Dictionary <ReactionSkillType, float>(); //ダメージからのリスク:攻撃側の攻撃力/現在HP int atk = skill.getAtkWithoutProgress(attacker); atk = (atk > 0) ? atk : 1; int hp = user.getHp(); hp = (hp > 0) ? hp : 1; float dodgeDammageRisk = atk / hp; //命中からのリスク:命中値/回避値 - 1 float dodgeHitRisk = (skill.getHit(attacker)) / (user.getDodge() + reactionSkills.getReactionSkillFromCategory(ReactionSkillType.DODGE).getDodge()) - 1; //回避合計リスク float dodgeRisk = dodgeHitRisk + dodgeDammageRisk; if (dodgeRisk != 0) { dodgeRisk /= 2; } riskTable.Add(ReactionSkillType.DODGE, dodgeRisk); //攻撃を受けるリスク int sumHpGuard = user.getHp() + user.getDef(); sumHpGuard = (sumHpGuard > 0) ? sumHpGuard : 1; float guardRisk = atk / sumHpGuard; riskTable.Add(ReactionSkillType.GUARD, guardRisk); //乱数判定 float random = UnityEngine.Random.Range(0, dodgeRisk + guardRisk); var keys = riskTable.Keys; foreach (ReactionSkillType category in keys) { if (riskTable[category] >= random) { return(reactionSkills.getReactionSkillFromCategory(category)); } else { random -= riskTable[category]; } } throw new InvalidOperationException("invalid state"); }
public void UpdateButtons() { for (int i = 0; i < 3; i++) { buttons[i].interactable = true; if (Referee.instance.CurrentPlayerC.Moveset[i] is AttackSkill) { AttackSkill placeholder = Referee.instance.CurrentPlayerC.Moveset[i] as AttackSkill; buttons[i].GetComponentInChildren <Text>().text = (placeholder.Name + "\n" + placeholder.MyAffinity).ToString(); } else if (Referee.instance.CurrentPlayerC.Moveset[i] is SupportSkill) { buttons[i].GetComponentInChildren <Text>().text = Referee.instance.CurrentPlayerC.Moveset[i].Name.ToString(); } } }
public static bool Prefix(AttackSkill __instance, bool _TryingToActivate, ref bool __result) { if (!(__instance is RangeAttackSkill)) { return(true); } var self = __instance; if (self.OwnerCharacter && self.OwnerCharacter.CurrentWeapon is ProjectileWeapon bow && IsManaBow(bow)) { __result = WeaponLoadout_CanBeLoaded.CanBeLoaded(bow); return(false); } return(true); }
/* 특정 방향으로 쏘는 경우 호출 */ public void ShotToDirection(AttackSkill _skillInfo, Vector2 _direction, float _speed, float _lifeTime) { //초기화 transform.SetParent(null); skillInfo = _skillInfo; timer = 0; speed = _speed; direction = _direction.normalized; hitCount = 0; lifeTime = _lifeTime; //목표 방향을 바라보도록 설정 float angle = Mathf.Rad2Deg * Mathf.Atan2(direction.y, direction.x) - 90; transform.rotation = Quaternion.Euler(0, 0, angle); isPullTrigger = true; }
public static bool Prefix(AttackSkill __instance, ref bool __result) { bool flag = RunicScrolls.IsRune(__instance); if (flag) { for (int i = 0; i < __instance.RequiredTags.Length; i++) { Item equippedItem = __instance.OwnerCharacter.Inventory.Equipment.GetEquippedItem(EquipmentSlot.EquipmentSlotIDs.Quiver); bool flag2 = equippedItem != null && equippedItem.HasTag(__instance.RequiredTags[i].Tag); if (flag2) { __result = true; return(false); } } } return(true); }
/* 공격당할 때 호출되는 함수 */ public override void OnHitAttack(AttackSkill _skill) { Debug.Log("[ " + name + " ]" + " Take [" + _skill.damage + "] Damage From [ " + _skill.skillCaster.name + " ]"); aniControl.ShowGetDamage(); //스탯에 피해량(damage) 정보를 넘김 status.TakeDamage(_skill.damage); //현재 체력이 바닥났을 경우 if (status.currentHP <= 0) { Dead(_skill.skillCaster); } DiscoverTarget(_skill.skillCaster); if (_skill.isKnockBack) { move.KnockBack(_skill.skillDirection * _skill.knockBackPower); } }
// Computes attacks or casts per second. public void AttackSpeed(AttackSkill skill, AttributeSet attrs) { if (Nature.Is(DamageSource.Attack)) { // If gem has own Attacks per Second, use it instead of weapon one. if (skill.Local.ContainsKey("Attacks per Second: #")) { APS = skill.Local["Attacks per Second: #"][0]; // Apply local increased attack speed of weapon. if (Local.ContainsKey("#% increased Attack Speed")) APS = IncreaseValueByPercentage(APS, Local["#% increased Attack Speed"][0]); } float incAS = 0; if (attrs.ContainsKey("#% increased Attack Speed")) incAS += attrs["#% increased Attack Speed"][0]; if (attrs.ContainsKey("#% reduced Attack Speed")) incAS -= attrs["#% reduced Attack Speed"][0]; if (attrs.ContainsKey("#% increased Attack and Cast Speed")) incAS += attrs["#% increased Attack and Cast Speed"][0]; if (attrs.ContainsKey("#% reduced Attack and Cast Speed")) incAS -= attrs["#% reduced Attack and Cast Speed"][0]; foreach (var attr in attrs.MatchesAny(new Regex[] { ReIncreasedAttackSpeedWithWeaponHandOrType, ReIncreasedAttackSpeedType })) { Match m = ReIncreasedAttackSpeedWithWeaponHandOrType.Match(attr.Key); if (m.Success) { if (WithWeaponHand.ContainsKey(m.Groups[2].Value) && Nature.Is(WithWeaponHand[m.Groups[2].Value])) incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; else if (WithWeaponType.ContainsKey(m.Groups[2].Value) && Nature.Is(WithWeaponType[m.Groups[2].Value])) incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } else { m = ReIncreasedAttackSpeedType.Match(attr.Key); if (m.Success) { // XXX: Not sure there are any mods with WeaponType here (Melee string in mod is DamageForm now, maybe Unarmed should be form as well). if (Weapon.Types.ContainsKey(m.Groups[2].Value) && Nature.Is(Weapon.Types[m.Groups[2].Value])) incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; else if (DamageNature.Forms.ContainsKey(m.Groups[2].Value) && Nature.Is(DamageNature.Forms[m.Groups[2].Value])) incAS += m.Groups[1].Value == "increased" ? attr.Value[0] : -attr.Value[0]; } } } if (IsDualWielding && attrs.ContainsKey("#% increased Attack Speed while Dual Wielding")) incAS += attrs["#% increased Attack Speed while Dual Wielding"][0]; if (incAS != 0) APS = IncreaseValueByPercentage(APS, incAS); float moreAS = 0; if (attrs.ContainsKey("#% more Attack Speed")) moreAS += attrs["#% more Attack Speed"][0]; if (attrs.ContainsKey("#% less Attack Speed")) moreAS -= attrs["#% less Attack Speed"][0]; foreach (var attr in attrs.Matches(ReMoreAttackSpeedType)) { Match m = ReMoreAttackSpeedType.Match(attr.Key); if (m.Success) { // XXX: Not sure there are any mods with WeaponType here (Melee string in mod is DamageForm now, maybe Unarmed should be form as well). if (Weapon.Types.ContainsKey(m.Groups[2].Value) && Nature.Is(Weapon.Types[m.Groups[2].Value])) moreAS += m.Groups[1].Value == "more" ? attr.Value[0] : -attr.Value[0]; else if (DamageNature.Forms.ContainsKey(m.Groups[2].Value) && Nature.Is(DamageNature.Forms[m.Groups[2].Value])) moreAS += m.Groups[1].Value == "more" ? attr.Value[0] : -attr.Value[0]; } } if (moreAS != 0) APS = IncreaseValueByPercentage(APS, moreAS); APS = RoundHalfDownEvenValue(APS, 2); } else // Spell (use Cast Time directly). { float incCS = 0; if (attrs.ContainsKey("#% increased Cast Speed")) incCS += attrs["#% increased Cast Speed"][0]; if (attrs.ContainsKey("#% reduced Cast Speed")) incCS -= attrs["#% reduced Cast Speed"][0]; if (attrs.ContainsKey("#% increased Attack and Cast Speed")) incCS += attrs["#% increased Attack and Cast Speed"][0]; if (attrs.ContainsKey("#% reduced Attack and Cast Speed")) incCS -= attrs["#% reduced Attack and Cast Speed"][0]; if (IsDualWielding && attrs.ContainsKey("#% increased Cast Speed while Dual Wielding")) incCS += attrs["#% increased Cast Speed while Dual Wielding"][0]; if (incCS != 0) CastTime = RoundValue(CastTime / ((100 + incCS) / 100), 3); float moreCS = 0; if (attrs.ContainsKey("#% more Cast Speed")) moreCS += attrs["#% more Cast Speed"][0]; if (attrs.ContainsKey("#% less Cast Speed")) moreCS -= attrs["#% less Cast Speed"][0]; if (moreCS != 0) CastTime = FloorValue(CastTime / ((100 + moreCS) / 100), 3); APS = RoundValue(1 / CastTime, 2); } }
public AttackSource(string name, AttackSkill skill, Weapon weapon) { Name = name; if (weapon == null) // Spells get damage from gem local attributes. { Nature = new DamageNature(skill.Nature); foreach (var attr in skill.Local) { Damage damage = Damage.Create(skill.Nature, attr); if (damage != null) Deals.Add(damage); } if (skill.Gem.Attributes.ContainsKey("Cast Time: # sec")) { CastTime = skill.Gem.Attributes["Cast Time: # sec"][0]; APS = 1 / CastTime; } else APS = CastTime = 1; // Spell without Cast Time has cast time of 1 second. if (skill.Gem.Attributes.ContainsKey("Critical Strike Chance: #%")) CriticalChance = skill.Gem.Attributes["Critical Strike Chance: #%"][0]; else CriticalChance = 0; // Spell without Critical Strike Chance has none. Local = new AttributeSet(); // No local weapon attributes. } else { if ((skill.Nature.WeaponType & weapon.Nature.WeaponType) == 0) // Skill can't be used. // Override weapon type and form of skill with actual weapon (client shows damage of unuseable skills as well). Nature = new DamageNature(skill.Nature) { Form = weapon.Nature.Form, WeaponHand = weapon.Hand, WeaponType = weapon.Nature.WeaponType }; else // Narrow down weapon type and form of skill gem to actual weapon (e.g. Frenzy). Nature = new DamageNature(skill.Nature) { Form = skill.Nature.ChooseWeaponForm(weapon.Nature), // XXX: Choose between melee or projectile form according to weapon. WeaponHand = weapon.Hand, WeaponType = skill.Nature.WeaponType & weapon.Nature.WeaponType }; // XXX: If source has no form, but skill has form defined, then force form of skill. // This happens in form transition from melee to projectile with skills like Spectral Throw. if (Nature.Form == DamageForm.Any && skill.Nature.Form != DamageForm.Any) Nature.Form = skill.Nature.Form; foreach (Damage damage in weapon.Deals) Deals.Add(new Damage(damage) { Form = Nature.Form, Source = Nature.Source, WeaponHand = Nature.WeaponHand, WeaponType = Nature.WeaponType }); foreach (Damage.Added added in weapon.Added) if (weapon.Is(added.Hand)) // Added damage may require specific hand. added.Apply(this, 100); APS = weapon.Attributes["Attacks per Second: #"][0]; if (weapon.Attributes.ContainsKey("Critical Strike Chance: #%")) CriticalChance = weapon.Attributes["Critical Strike Chance: #%"][0]; else CriticalChance = 0; // Weapon without Critical Strike Chance has none. Local = weapon.Attributes; } }
// calculates next combo private uint GetNextCombo(Note.Button curBut, InputManager.InputType curType, AttackSkill skill) { // skill not found if(skill == null) return 0; // skill is long button & DOWN signal received twice else if(skill.IsLongButton && curType == InputManager.InputType.DOWN) return 1; // skill is long button & input is KEEP else if(skill.IsLongButton && LastButton == curBut && LastType != InputManager.InputType.UP && (curType == InputManager.InputType.KEEP || curType == InputManager.InputType.UP)) return 2; // new button pressed else if(curBut != Note.Button.NONE && LastButton == Note.Button.NONE) return 1; // button accepted -> combo increase else if(curBut != Note.Button.NONE && curBut == LastButton) return this.CurrentCombo % skill.TurnLength + 1; else return 1; }