SkillCommons.gd 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. extends Object
  2. class_name SkillCommons
  3. # Constants
  4. const SkillMeleeName : String = "Melee"
  5. # Actions
  6. static func TryConsume(agent : BaseAgent, modifier : CellCommons.Modifier, skill : SkillCell) -> bool:
  7. if agent is not PlayerAgent:
  8. return true
  9. match modifier:
  10. CellCommons.Modifier.Health:
  11. var exhaust : int = skill.modifiers.Get(modifier)
  12. if agent.stat.health >= -exhaust:
  13. agent.stat.SetHealth(exhaust)
  14. return true
  15. CellCommons.Modifier.Mana:
  16. var exhaust : int = skill.modifiers.Get(modifier)
  17. if agent.stat.mana >= -exhaust:
  18. agent.stat.SetMana(exhaust)
  19. return true
  20. CellCommons.Modifier.Stamina:
  21. var exhaust : int = skill.modifiers.Get(modifier)
  22. if agent.stat.stamina >= -exhaust:
  23. agent.stat.SetStamina(exhaust)
  24. return true
  25. return false
  26. static func GetDamage(agent : BaseAgent, target : BaseAgent, skill : SkillCell, rng : float) -> Skill.AlterationInfo:
  27. var info : Skill.AlterationInfo = Skill.AlterationInfo.new()
  28. var skillValue : int = skill.modifiers.Get(CellCommons.Modifier.MAttack)
  29. if skillValue > 0:
  30. info.value = max(1, agent.stat.current.mattack + skillValue - target.stat.current.mdefense)
  31. else:
  32. skillValue = skill.modifiers.Get(CellCommons.Modifier.Attack)
  33. info.value = max(1, agent.stat.current.attack + skillValue - target.stat.current.defense)
  34. var critMaster : bool = agent.stat.current.critRate > target.stat.current.dodgeRate
  35. if critMaster and rng > 1.0 - agent.stat.current.critRate:
  36. info.type = ActorCommons.Alteration.CRIT
  37. info.value *= 2
  38. elif not critMaster and rng > 1.0 - target.stat.current.dodgeRate:
  39. info.type = ActorCommons.Alteration.DODGE
  40. info.value = 0
  41. else:
  42. info.type = ActorCommons.Alteration.HIT
  43. info.value = ceili(info.value * rng)
  44. info.value += min(0, target.stat.health - info.value)
  45. if info.value <= 0:
  46. info.type = ActorCommons.Alteration.DODGE
  47. return info
  48. static func GetHeal(agent : BaseAgent, target : BaseAgent, skill : SkillCell, rng : float) -> int:
  49. var skillValue : int = skill.modifiers.Get(CellCommons.Modifier.Health)
  50. var healValue : int = int(agent.stat.concentration + skillValue * rng)
  51. healValue = min(healValue, target.stat.current.maxHealth - target.stat.health)
  52. return healValue
  53. static func GetZoneTargets(instance : WorldInstance, zonePos : Vector2, skill : SkillCell) -> Array[BaseAgent]:
  54. var targets : Array[BaseAgent] = []
  55. if skill.modifiers.Get(CellCommons.Modifier.Attack) != 0 or skill.modifiers.Get(CellCommons.Modifier.MAttack) != 0:
  56. for neighbour in instance.mobs:
  57. var filteredRange : float = skill.cellRange + neighbour.entityRadius
  58. if ActorCommons.IsAlive(neighbour) and Util.IsReachableSquared(neighbour.position, zonePos, filteredRange * filteredRange):
  59. targets.append(neighbour)
  60. if skill.modifiers.Get(CellCommons.Modifier.Health) != 0:
  61. for neighbour in instance.players:
  62. var filteredRange : float = skill.cellRange + neighbour.entityRadius
  63. if ActorCommons.IsAlive(neighbour) and Util.IsReachableSquared(neighbour.position, zonePos, filteredRange * filteredRange):
  64. targets.append(neighbour)
  65. return targets
  66. static func GetSurroundingTargets(agent : BaseAgent, skill : SkillCell) -> Array[BaseAgent]:
  67. var targets : Array[BaseAgent] = []
  68. var neighbours : Array[Array] = WorldAgent.GetNeighboursFromAgent(agent)
  69. if skill.modifiers.Get(CellCommons.Modifier.Attack) != 0 or skill.modifiers.Get(CellCommons.Modifier.MAttack) != 0:
  70. for neighbour in neighbours[1]:
  71. if IsAttackable(agent, neighbour, skill):
  72. targets.append(neighbour)
  73. if skill.modifiers.Get(CellCommons.Modifier.Health) != 0:
  74. for neighbour in neighbours[2]:
  75. if IsAttackable(agent, neighbour, skill):
  76. targets.append(neighbour)
  77. return targets
  78. static func GetRNG(hasStamina : bool) -> float:
  79. return randf_range(0.9 if hasStamina else 0.1, 1.0)
  80. static func GetRange(agent : BaseAgent, skill : SkillCell) -> int:
  81. return agent.stat.current.attackRange + (skill.cellRange if skill else 0)
  82. # Checks
  83. static func IsNotSelf(agent : BaseAgent, target : BaseAgent) -> bool:
  84. return agent != target
  85. static func IsNear(agent : BaseAgent, target : BaseAgent, skillRange : int) -> bool:
  86. var filteredRange : float = skillRange + agent.entityRadius + target.entityRadius
  87. return WorldNavigation.GetDistanceSquared(agent, target.position) <= filteredRange * filteredRange
  88. static func IsSameMap(agent : BaseAgent, target : BaseAgent) -> bool:
  89. return WorldAgent.GetMapFromAgent(agent) == WorldAgent.GetMapFromAgent(target)
  90. static func IsAttackable(agent : BaseAgent, target : BaseAgent, skill : SkillCell) -> bool:
  91. return IsInteractable(agent, target) and IsNear(agent, target, GetRange(agent, skill))
  92. static func IsTargetable(agent : BaseAgent, target : BaseAgent) -> bool:
  93. return IsInteractable(agent, target) and IsNear(agent, target, ActorCommons.TargetMaxDistance)
  94. static func IsInteractable(agent : BaseAgent, target : BaseAgent) -> bool:
  95. return IsNotSelf(agent, target) and ActorCommons.IsAlive(target) and IsSameMap(agent, target)
  96. static func CanCast(agent : BaseAgent) -> bool:
  97. return agent.currentSkillID != DB.UnknownHash and not DB.SkillsDB[agent.currentSkillID].castWalk
  98. static func IsCasting(agent : BaseAgent, skill : SkillCell = null) -> bool:
  99. return (agent.currentSkillID == skill.id) if skill else DB.SkillsDB.has(agent.currentSkillID)
  100. static func IsCoolingDown(agent : BaseAgent, skill : SkillCell) -> bool:
  101. return agent.cooldownTimers.get(skill.id, false)
  102. static func GetCooldown(actor : Actor, skill : SkillCell) -> float:
  103. return actor.stat.current.cooldownAttackDelay + skill.cooldownTime
  104. static func IsDelayed(skill : SkillCell) -> bool:
  105. return skill.projectilePreset != null
  106. static func HasSkill(agent : BaseAgent, skill : SkillCell) -> bool:
  107. return agent.progress and agent.progress.HasSkill(skill)
  108. static func HasActionInProgress(agent : BaseAgent) -> bool:
  109. return agent.currentSkillID != DB.UnknownHash or not agent.actionTimer.is_stopped()