BaseAgent.gd 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. extends Actor
  2. class_name BaseAgent
  3. #
  4. signal agent_killed
  5. #
  6. var agent : NavigationAgent2D = null
  7. var entityRadius : int = 0
  8. var actionTimer : Timer = null
  9. var regenTimer : Timer = null
  10. var cooldownTimers : Dictionary[int, bool] = {}
  11. var hasCurrentGoal : bool = false
  12. var isRelativeMode : bool = false
  13. var lastPositions : Array[float] = []
  14. var currentDirection : Vector2 = Vector2.ZERO
  15. var currentOrientation : Vector2 = Vector2.ZERO
  16. var currentVelocity : Vector2 = Vector2.ZERO
  17. var currentInput : Vector2 = Vector2.ZERO
  18. var currentWalkSpeed : Vector2 = Vector2.ZERO
  19. var currentSkillID : int = DB.UnknownHash
  20. var requireFullUpdate : bool = false
  21. var requireUpdate : bool = false
  22. #
  23. func SwitchInputMode(clearCurrentInput : bool):
  24. hasCurrentGoal = false
  25. if clearCurrentInput:
  26. currentInput = Vector2.ZERO
  27. currentDirection = Vector2.ZERO
  28. func UpdateInput():
  29. if isRelativeMode:
  30. if currentDirection != Vector2.ZERO:
  31. var pos : Vector2i = currentDirection * ActorCommons.DisplacementVector + position
  32. if WorldNavigation.GetPathLengthSquared(self, pos) <= ActorCommons.MaxDisplacementSquareLength:
  33. WalkToward(pos)
  34. currentInput = currentDirection
  35. else:
  36. SwitchInputMode(true)
  37. if hasCurrentGoal:
  38. if agent and not agent.is_navigation_finished():
  39. var clampedDirection : Vector2 = Vector2(global_position.direction_to(agent.get_next_path_position()).normalized() * ActorCommons.InputApproximationUnit)
  40. currentInput = Vector2(clampedDirection) / ActorCommons.InputApproximationUnit
  41. lastPositions.push_back(agent.distance_to_target())
  42. if lastPositions.size() > ActorCommons.LastMeanValueMax:
  43. lastPositions.pop_front()
  44. else:
  45. SwitchInputMode(true)
  46. func SetState(wantedState : ActorCommons.State) -> bool:
  47. var nextState : ActorCommons.State = ActorCommons.GetNextTransition(state, wantedState)
  48. if nextState != state:
  49. requireFullUpdate = true
  50. state = nextState
  51. return state == wantedState
  52. func SetSkillCastID(skillID : int):
  53. if currentSkillID != skillID:
  54. requireFullUpdate = true
  55. currentSkillID = skillID
  56. func AddSkill(cell : SkillCell, proba : float):
  57. if cell:
  58. progress.AddSkill(cell, proba)
  59. func AddItem(item : BaseCell, proba : float):
  60. if item and inventory:
  61. while proba > 0.0:
  62. if proba >= 1.0 or randf_range(0.0, 1.0) <= proba:
  63. inventory.PushItem(item, 1)
  64. proba -= 1.0
  65. else:
  66. break
  67. func SetRelativeMode(enable : bool, givenDirection : Vector2):
  68. if isRelativeMode != enable:
  69. isRelativeMode = enable
  70. if givenDirection == Vector2.ZERO:
  71. ResetNav()
  72. isRelativeMode = false
  73. currentDirection = givenDirection
  74. func WalkToward(pos : Vector2):
  75. if pos == position:
  76. return
  77. if SkillCommons.CanCast(self):
  78. Skill.Stopped(self)
  79. hasCurrentGoal = true
  80. lastPositions.clear()
  81. if agent:
  82. agent.target_position = pos
  83. func LookAt(target : BaseAgent):
  84. if target:
  85. var newOrientation : Vector2 = Vector2(target.position - position).normalized()
  86. if not newOrientation.is_equal_approx(currentDirection):
  87. currentOrientation = newOrientation
  88. requireFullUpdate = true
  89. func ResetNav():
  90. WalkToward(position)
  91. SwitchInputMode(true)
  92. #
  93. func SetData():
  94. entityRadius = data._radius
  95. for skillID in data._skillSet:
  96. AddSkill(DB.SkillsDB[skillID], data._skillProba[skillID])
  97. # Navigation
  98. if !(data._behaviour & AICommons.Behaviour.IMMOBILE):
  99. if self is PlayerAgent:
  100. agent = FileSystem.LoadEntityComponent("navigations/PlayerAgent")
  101. else:
  102. agent = FileSystem.LoadEntityComponent("navigations/NPAgent")
  103. agent.set_radius(data._radius)
  104. agent.set_neighbor_distance(data._radius * 2.0)
  105. agent.set_avoidance_priority(clampf(data._radius / float(ActorCommons.MaxEntityRadiusSize), 0.0, 1.0))
  106. agent.velocity_computed.connect(self._velocity_computed)
  107. add_child.call_deferred(agent)
  108. RefreshWalkSpeed()
  109. func RefreshWalkSpeed():
  110. if agent:
  111. agent.set_max_speed(stat.current.walkSpeed)
  112. currentWalkSpeed = Vector2(stat.current.walkSpeed, stat.current.walkSpeed)
  113. #
  114. func Damage(_caller : BaseAgent):
  115. pass
  116. func Interact(_caller : BaseAgent):
  117. pass
  118. func GetNextShapeID() -> int:
  119. return stat.shape if stat.IsMorph() else stat.spirit
  120. func GetNextPortShapeID() -> int:
  121. return stat.spirit if stat.IsSailing() else DB.ShipHash
  122. func Killed():
  123. agent_killed.emit(self)
  124. SetSkillCastID(DB.UnknownHash)
  125. #
  126. func _physics_process(_delta : float):
  127. UpdateInput()
  128. if agent and agent.get_avoidance_enabled():
  129. agent.set_velocity(currentInput * currentWalkSpeed)
  130. else:
  131. _velocity_computed(currentInput * currentWalkSpeed)
  132. func _process(_delta : float):
  133. if requireFullUpdate:
  134. requireFullUpdate = false
  135. requireUpdate = false
  136. Network.NotifyNeighbours(self, "FullUpdateEntity", [velocity, position, currentOrientation, state, currentSkillID], true, true)
  137. elif requireUpdate:
  138. requireUpdate = false
  139. Network.NotifyNeighbours(self, "UpdateEntity", [velocity, position], true, true)
  140. func _velocity_computed(safeVelocity : Vector2i):
  141. if stat.health <= 0:
  142. SetState(ActorCommons.State.DEATH)
  143. elif SkillCommons.CanCast(self):
  144. SetState(DB.SkillsDB[currentSkillID].state)
  145. elif safeVelocity == Vector2i.ZERO:
  146. SetState(ActorCommons.State.IDLE)
  147. else:
  148. SetState(ActorCommons.State.WALK)
  149. if state == ActorCommons.State.WALK:
  150. currentVelocity = safeVelocity
  151. else:
  152. currentVelocity = Vector2.ZERO
  153. var wasZero : bool = velocity.is_zero_approx()
  154. var isZero : bool = safeVelocity == Vector2i.ZERO
  155. if wasZero and isZero:
  156. return
  157. if wasZero or isZero:
  158. requireFullUpdate = true
  159. elif self is PlayerAgent or currentVelocity.distance_squared_to(velocity) > ActorCommons.InputApproximationUnit:
  160. requireUpdate = true
  161. velocity = currentVelocity
  162. if velocity != Vector2.ZERO:
  163. currentOrientation = velocity.normalized()
  164. move_and_slide()
  165. func _ready():
  166. set_name.call_deferred(str(get_rid().get_id()))
  167. actionTimer = Timer.new()
  168. actionTimer.set_name("ActionTimer")
  169. actionTimer.set_one_shot(true)
  170. add_child.call_deferred(actionTimer)
  171. func _init(_type : ActorCommons.Type = ActorCommons.Type.NPC, _data : EntityData = null, _nick : String = "", isManaged : bool = false):
  172. stat.entity_stats_updated.connect(RefreshWalkSpeed)
  173. super._init(_type, _data, _nick, isManaged)