Advertisement
Nancok

PetNode2D.gd

Mar 18th, 2024
774
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. extends Node2D
  2. class_name PetWorldNode2D
  3.  
  4. signal state_changed(state: States)
  5.  
  6. const DEFAULT_PATHABLE_RECT: Rect2 = Rect2(Vector2.ZERO, Vector2.ONE * 1280)
  7.  
  8. enum States {
  9.     STANDING,
  10.     ROAMING,
  11.     ANIMATING,
  12.     SOCIALIZING,
  13. }
  14. const META_LAST_ANIMATION: String = "PET_META_LAST_ANIMATION"
  15. const META_STATE_ROAMING_TARGET: String = "PET_META_STATE_ROAMING_TARGET_GLOBAL_POS"
  16. const META_STATE_SOCIALIZING_TARGET: String = "PET_META_STATE_SOCIALIZING_TARGET_NODE"
  17.  
  18. const TIME_ROAMING_PATH_WAIT: String = "PET_META_ROAMING_TIME_COUNTER_DECISION"
  19.  
  20. const STATE_ROAMING_MAX_SPEED: float = 2
  21. const STATE_ROAMING_MIN_SPEED: float = 80
  22.  
  23. @export var resource: Pet
  24.  
  25. var animator := PetWorldAnimator2D.new()
  26.  
  27. var pathable_rect_global: Rect2
  28.  
  29. var state_current: States
  30.  
  31. var state_decision_timer: SceneTreeTimer
  32.  
  33. var time_counters: Dictionary
  34.  
  35. var meta: Dictionary
  36.  
  37. var texture_to_draw: Texture2D
  38.  
  39. var sprite_animation_tweens: Dictionary
  40.  
  41.  
  42. static func create_from_resource(pet_res: Pet) -> PetWorldNode2D:
  43.     var new_node := PetWorldNode2D.new()
  44.     new_node.resource = pet_res
  45.     return new_node
  46.  
  47.  
  48. func _enter_tree() -> void:
  49.     update_pathable_rect()
  50.  
  51.  
  52. func _ready() -> void:
  53.     resource.sprite_sheet_update()
  54.     add_child(animator)
  55.     state_changed.connect(on_state_changed)
  56.     resource.action_performed.connect(on_pet_action_performed)
  57.     resource.stat_changed.connect(on_pet_stat_changed)
  58.     state_decide()
  59.    
  60.     update_animations()
  61.     sprite_animation_play("default")
  62.    
  63.  
  64. func _process(delta: float) -> void:
  65.     queue_redraw()
  66.    
  67.     #Advance time counters
  68.     for counter: String in time_counters:
  69.         var time_left: float = time_counter_get_time(counter)
  70.         time_counter_set_time(counter, time_left - delta)
  71.        
  72.         if time_left < 0:
  73.             time_counters.erase(counter)
  74.    
  75.     #Handle current state
  76.     match state_current:
  77.         States.ROAMING:
  78.            
  79.             if time_counter_get_time(TIME_ROAMING_PATH_WAIT) <= 0:
  80.                 state_roaming_update_target()
  81.                 state_roaming_update_timer()
  82.            
  83.             global_position = global_position.move_toward(state_roaming_get_target(), state_roaming_get_speed() * delta)
  84.             queue_redraw()
  85.            
  86.         States.SOCIALIZING:
  87.             var target_pos: Vector2 = state_socializing_get_target().global_position
  88.            
  89.             if is_zero_approx(target_pos.length() - global_position.length()):
  90.                 print_debug("The target is right here!?")
  91.                 state_decide()
  92.                 return
  93.                
  94.             var ideal_distance: float = (8 + resource.spritesheet_texture.get_size().x) / resource.resource_dna.get_value_nature_modifier(PetDna.NatureProperties.SHY_SOCIAL)
  95.            
  96.             if global_position.distance_to(target_pos) > ideal_distance:
  97.                 global_position = global_position.move_toward(target_pos, state_roaming_get_speed() * delta)
  98.            
  99.  
  100.  
  101. func _input(event: InputEvent) -> void:
  102.     if event.is_action_pressed("poke_random"):
  103.         resource.action_perform(Pet.Actions.GET_POKED)
  104.  
  105.  
  106.  
  107. func _draw() -> void:
  108.     if not texture_to_draw:
  109.         return
  110.        
  111.     draw_texture(texture_to_draw, -texture_to_draw.get_size() / 2)
  112.    
  113.    
  114. func get_rect_global() -> Rect2:
  115.     return Rect2(global_position - Vector2(resource.sprite_get_base_size()/2), resource.sprite_get_base_size())
  116.    
  117.    
  118. func state_change(state: States):          
  119.     state_current = state
  120.    
  121.     state_changed.emit(state)
  122.  
  123.  
  124. func state_decide():
  125.     if state_can_change():
  126.         var new_state: States = States.values().pick_random()
  127.         state_change(new_state)
  128.         state_start_decision_timer()
  129.  
  130.  
  131. func state_can_change() -> bool:
  132.     return is_inside_tree()
  133.  
  134.  
  135. func state_get_query_time() -> float:
  136.     return randf() * 5 + 0.5
  137.  
  138.  
  139. func state_start_decision_timer():
  140.     if not state_decision_timer is SceneTreeTimer or state_decision_timer.time_left == 0:
  141.         state_decision_timer = get_tree().create_timer(state_get_query_time())
  142.         state_decision_timer.timeout.connect(state_decide, CONNECT_ONE_SHOT)
  143.    
  144.    
  145. func state_roaming_update_target():
  146.     var spot: Vector2 = Vector2(
  147.         randf_range(pathable_rect_global.position.x, pathable_rect_global.end.x),
  148.         randf_range(pathable_rect_global.position.y, pathable_rect_global.end.y)
  149.     )
  150.     assert(pathable_rect_global.has_point(spot))
  151.     meta[META_STATE_ROAMING_TARGET] = spot
  152.    
  153.  
  154. func state_roaming_update_timer():
  155.     time_counter_set_time(TIME_ROAMING_PATH_WAIT, randf() * 5)
  156.  
  157.    
  158. func state_roaming_get_target()->Vector2:
  159.     var target: Vector2 = meta.get(META_STATE_ROAMING_TARGET, global_position)
  160.     return target
  161.  
  162.  
  163. func state_roaming_get_speed() -> float:
  164.     var speed_value: float = resource.get_value_speed() + 10
  165.     speed_value *= resource.get_value_nature_modifier(PetDna.NatureProperties.LAZY_ENERGETIC) * resource.get_value_nature_modifier(PetDna.NatureProperties.CALM_ROWDY)
  166.     return wrapf( speed_value as float, STATE_ROAMING_MIN_SPEED, STATE_ROAMING_MAX_SPEED)
  167.  
  168.  
  169. func state_socializing_set_target():
  170.     var pet_nodes: Array[PetWorldNode2D] = PeManager.pet_get_node_list()
  171.     if pet_nodes.is_empty():
  172.         push_warning("List is empty!")
  173.         return
  174.        
  175.     var candidates: Array[PetWorldNode2D] = []
  176.     for possible_target_count: int in 5:
  177.         candidates.append(pet_nodes.pick_random())
  178.    
  179.     var chosen: PetWorldNode2D = candidates.pick_random()
  180.     assert(chosen is PetWorldNode2D)
  181.     meta[META_STATE_SOCIALIZING_TARGET] = chosen
  182.    
  183.  
  184. func state_socializing_get_target() -> PetWorldNode2D:
  185.     return meta.get(META_STATE_SOCIALIZING_TARGET, self)
  186.    
  187.    
  188. func time_counter_set_time(key: String, time: float):
  189.     time_counters[key] = time
  190.    
  191.    
  192. func time_counter_get_time(key: String) -> float:
  193.     return time_counters.get(key, 0.0)
  194.    
  195.    
  196. func update_pathable_rect():
  197.     pathable_rect_global = DEFAULT_PATHABLE_RECT
  198.  
  199. func update_animations():
  200.     sprite_animation_stop()
  201.    
  202.     sprite_animation_tweens.clear()
  203.    
  204.     for animation: String in resource.sprite_get_animation_names():
  205.         var tween: Tween = resource.sprite_tween_property_with_animation(self, "texture_to_draw", animation)
  206.         sprite_animation_tweens[animation] = tween
  207.  
  208.  
  209. func sprite_animation_play(animation: String, loops: int = 0):
  210.     sprite_animation_stop()
  211.    
  212.     if not sprite_animation_tweens.has(animation):
  213.         push_error("No such animation is present for this pet.")
  214.         return
  215.        
  216.     var tween: Tween = sprite_animation_tweens[animation]
  217.     tween.set_loops(loops)
  218.     tween.play()
  219.    
  220.     set_meta(META_LAST_ANIMATION, animation)
  221.  
  222.  
  223. func sprite_animation_stop(last_anim: String = get_meta(META_LAST_ANIMATION, "")):
  224.     if last_anim != "":
  225.         if sprite_animation_tweens.has(last_anim):
  226.             sprite_animation_tweens[last_anim].stop()
  227.  
  228.  
  229. func on_state_changed(state: States):
  230.     match state:
  231.         States.ANIMATING:
  232.             animator.play_animation()
  233.         States.SOCIALIZING:
  234.             state_socializing_set_target()
  235.            
  236.  
  237. func on_pet_action_performed(action: Pet.Actions):
  238.     match action:
  239.         Pet.Actions.GET_POKED:
  240.             animator.queued_animation = PetWorldAnimator2D.Animations.DRAINED
  241.             state_change(States.ANIMATING)
  242.  
  243.            
  244. func on_pet_stat_changed(_stat: Pet.Stats, amount: float):
  245.     if amount < -15:
  246.         animator.queued_animation = PetWorldAnimator2D.Animations.DRAINED
  247.         state_change(States.ANIMATING)
  248.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement