Advertisement
Guest User

Untitled

a guest
May 8th, 2019
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. extends Node2D
  2.  
  3. #INITIATING
  4.   #variable declaraction
  5.   #ready function (first timer call)
  6. #CORE LOGIC
  7.   #timer timeout
  8.   #get direction & state
  9.   #on tween completed
  10. #STATE ACTIONS
  11.   #attack
  12.   #move
  13.   #damaged
  14.   #KNIGHT ONLY ACTIONS
  15.     #stunned
  16. #PATHFINDING
  17.   #get path
  18.   #get cost
  19.   #get distance
  20.   #get lower score & distance
  21.   #path translate
  22.  
  23. #------------------------------------          INITIATING           ------------------------------------
  24.  
  25. export (PackedScene) var Sword
  26. export (PackedScene) var Shield
  27. export (PackedScene) var Arrow
  28. export (PackedScene) var Fireball
  29. export (PackedScene) var Bones
  30.  
  31. onready var Core = get_node("/root/Game")
  32. onready var map = get_node("/root/Game/TileMap")
  33. onready var spr = get_node("Sprite")
  34. onready var step = get_node("Timer")
  35. onready var tween = get_node("Tween")
  36.  
  37. var player
  38. var mapArray = []
  39. var s = []
  40. var type
  41. var health
  42. var points
  43.  
  44. #knight only variables
  45. var defending = false
  46. var stunned = false
  47.  
  48. func _ready(): #to be merged with the current _ready()
  49.  
  50.     s = dir.sides
  51.     #beginning here: this part is probably unecessary
  52.     for y in range(29):
  53.  
  54.         for x in range(39):
  55.    
  56.             var point = Vector2(x * 16, y * 16)
  57.             var tileIndex = map.get_cellv(map.world_to_map(point))
  58.             if  tileIndex == 2 or tileIndex == 7:
  59.    
  60.                 mapArray.append(point)
  61.     #ending here: this part is probably unecessary
  62.  
  63.     player = get_tree().get_nodes_in_group("Player")[0]
  64.     self.add_to_group("Enemies")
  65.     type = rn._rn(0, 2) #this will decide the type of enemy {knight, archer, mage}
  66.     if type == 0:       #knight
  67.  
  68.         spr.set_region_rect(Rect2(Vector2(48, 48), Vector2(16, 16)))
  69.         health = 4
  70.         step.wait_time = 1.5
  71.         points = 10
  72.         self.add_to_group("Knight")
  73.     elif type == 1:     #archer
  74.  
  75.         spr.set_region_rect(Rect2(Vector2(32, 48), Vector2(16, 16)))
  76.         health = 2
  77.         step.wait_time = 2
  78.         points = 8
  79.         self.add_to_group("Archer")
  80.     elif type == 2:     #mage
  81.  
  82.         spr.set_region_rect(Rect2(Vector2(16, 48), Vector2(16, 16)))
  83.         health = 1
  84.         step.wait_time = 2.2
  85.         points = 12
  86.         self.add_to_group("Mage")
  87.     step.start()
  88.  
  89. #------------------------------------          CORE LOGIC           ------------------------------------
  90.  
  91. func _on_Timer_timeout(): #when the timer is up
  92.  
  93.     var state = get_directionAndState()
  94.     if state[1] == "combat":
  95.  
  96.         if not defending and type == 0:
  97.  
  98.             _defend()
  99.         else:
  100.  
  101.             _attack(state[0])
  102.     elif state[1] == "move":
  103.  
  104.         _move(state[0])
  105.  
  106.  
  107. func get_directionAndState(): #checks either if enemy is within range or not
  108.  
  109.     var state = "move"
  110.     var target
  111.     var objective = player.position
  112.     for side in dir.sides:
  113.  
  114.         if objective == (position + side) and type == 0: #Knight: if objective(player) is in one of the four sides
  115.    
  116.             target = side
  117.             state = "combat"
  118.     if (get_distance(position, objective) <= 8 and type == 1) or (get_distance(position, objective) <= 4 and type == 2): #Archer or Mage: if objective(player) is within range
  119.  
  120.         target = objective
  121.         state = "combat"
  122.     if state == "move":
  123.  
  124.         target = _get_path(objective)[1] #[0]to get only the first step of the returned array
  125.  
  126.     return [target, state]
  127.  
  128.  
  129. func _on_Tween_tween_completed(object, key):
  130.  
  131.     if type == 0:       #knight
  132.  
  133.         step.wait_time = 2.2
  134.     elif type == 1:     #archer
  135.  
  136.         step.wait_time = 1.6
  137.     elif type == 2:     #mage
  138.  
  139.         step.wait_time = 1.8
  140.     step.set_paused(false)
  141.     step.start()
  142.  
  143.  
  144. #------------------------------------          STATE ACTIONS           ------------------------------------
  145.  
  146. func _attack(point):
  147.  
  148.     if type == 0:       #knight
  149.  
  150.         defending = false
  151.         spr.set_region_rect(Rect2(Vector2(48, 48), Vector2(16, 16)))
  152.         if player.defending:
  153.  
  154.             _stunned()
  155.             step.start()
  156.             #play sword on shield
  157.             return
  158.         else:
  159.  
  160.             var attack = Sword.instance()
  161.             attack.position = (point + Vector2(0, -16))
  162.             get_parent().add_child(attack)
  163.             AP._play("res://Audio/SFX-sword-attack.wav")
  164.             player._beAttacked(type)
  165.             step.wait_time = 0.3
  166.             step.start()
  167.             return
  168.     elif type == 1:     #archer
  169.  
  170.         var attack = Arrow.instance()
  171.         attack.position = position
  172.         attack.target = (point + Vector2(8, 8))
  173.         get_parent().add_child(attack)
  174.         AP._play("res://Audio/SFX-bow-attack.wav")
  175.     elif type == 2:     #mage
  176.  
  177.         var attack = Fireball.instance()
  178.         attack.position = position
  179.         attack.target = (point + Vector2(8, 8))
  180.         get_parent().add_child(attack)
  181.     step.start()
  182.  
  183.  
  184. func _move(point):
  185.  
  186.     if type == 0 and defending:
  187.  
  188.         defending = false
  189.         spr.set_region_rect(Rect2(Vector2(48, 48), Vector2(16, 16)))
  190.     position = point
  191.     step.start()
  192.  
  193.  
  194. func _damaged():
  195.  
  196.     if defending:
  197.  
  198.         #have to play sword in shield sound
  199.         var shield = Shield.instance()
  200.         shield.position = (position + Vector2(0, -16))
  201.         get_parent().add_child(shield)
  202.         player.stunned = true
  203.         player.tween.interpolate_property(player, "modulate", Color(0, 0, 1, 1), Color(1, 1, 1, 1), 1.2, Tween.TRANS_LINEAR, Tween.EASE_OUT)
  204.         player.tween.start()
  205.         player.tic.wait_time = 1.2
  206.         player.tic.start()
  207.         print("Shield")
  208.     else:
  209.  
  210.         step.set_paused(true)
  211.         health -= 1
  212.         if health <= 0:
  213.  
  214.             Core._scoreUpdate(points)
  215.             var bones = Bones.instance()
  216.             bones.position = position
  217.             bones.add_to_group("Bones")
  218.             if rn._rn(1, 2) == 1:
  219.  
  220.                 bones.set_region_rect(Rect2(Vector2(32, 32), Vector2(16, 16)))
  221.             get_parent().add_child(bones)
  222.             queue_free()
  223.         tween.interpolate_property(self, "modulate", Color(1, 0, 0, 1), Color(1, 1, 1, 1), 0.2, Tween.TRANS_LINEAR, Tween.EASE_OUT)
  224.         tween.start()
  225.         if type == 0:
  226.  
  227.             _defend()
  228.  
  229.  
  230. #--- KNIGHT ONLY ACTIONS ---
  231.  
  232. func _defend():
  233.  
  234.     defending = true
  235.     spr.set_region_rect(Rect2(Vector2(48, 64), Vector2(16, 16)))
  236.     step.start()
  237.  
  238.  
  239. func _stunned():
  240.  
  241.     #have to play sword in shield sound
  242.     step.wait_time = 2
  243.     stunned = true
  244.     tween.interpolate_property(self, "modulate", Color(0, 0, 1, 1), Color(1, 1, 1, 1), 2.0, Tween.TRANS_LINEAR, Tween.EASE_OUT)
  245.     tween.start()
  246.  
  247.  
  248. #------------------------------------           PATHFINDING            ------------------------------------
  249.  
  250. func _get_path(objective):
  251.  
  252.     #this logic takes into account that start will always be the actual position of the character
  253.     var openList = [{'coord': position, 'score': 0, 'distance': 0, 'parent': position}]
  254.     var closedList = []
  255.     while not openList.empty():
  256.  
  257.         if openList.empty():
  258.  
  259.             break
  260.         var idx = get_lowestScoreAndDistance(openList)
  261.         var current = openList[idx]
  262.         #if current is the objective
  263.         if current.coord == objective:
  264.  
  265.             closedList.append(current)
  266.             return _pathInverter(closedList, position, objective) #I need to take this list through the "inverter"
  267.         closedList.append(openList[idx])
  268.         openList.remove(idx)
  269.         for child in get_sides(current.coord):
  270.  
  271.             #start of list checking
  272.             var closedHasIt = false
  273.             for idx in closedList: #check closedList's indexes
  274.  
  275.                 if idx.coord == child:
  276.  
  277.                     closedHasIt = true
  278.                     break
  279.             if closedHasIt == true: #if any index of closedList has it's "coord" value equals to child
  280.  
  281.                 continue
  282.  
  283.             var openHasIt = false
  284.             for idx in openList: #check openList's indexes
  285.  
  286.                 if idx.coord == child:
  287.  
  288.                     openHasIt = true
  289.                     break
  290.             if openHasIt == true: #if any index of openList has it's "coord" value equals to child
  291.  
  292.                 continue
  293.             #end of list checking
  294.  
  295.             #beginning of: This block of text checks if there is another knight in the same position as the one being checked
  296.             var knightHasIt = false
  297.             for knight in get_tree().get_nodes_in_group("Knight"):
  298.  
  299.                 if child == knight.position:
  300.  
  301.                     knightHasIt = true
  302.             if knightHasIt:
  303.  
  304.                 continue
  305.             #Ending of: This block of text checks if there is another knight in the same position as the one being checked
  306.  
  307.             var score = (get_cost(child) +get_distance(position, child) + get_distance(child, objective))
  308.             for i in openList:
  309.  
  310.                 if i.coord == child:
  311.  
  312.                     openList.erase(i)
  313.  
  314.             var distance = get_distance(child, objective)
  315.             var parent = current.coord
  316.             openList.append({'coord': child, 'score': score, 'distance': distance, 'parent': parent})
  317.     print("no path")
  318.     return [position, position]
  319.  
  320.  
  321. func get_cost(node): #gets the cost of the node based on it's tile type (index)
  322.     var tileIndex = map.get_cellv(node)
  323.     var cost = 0
  324.     if tileIndex == 2 or tileIndex == 7:
  325.  
  326.         cost = 0
  327.     else:
  328.  
  329.         cost = 999
  330.     return cost
  331.  
  332.  
  333. func get_distance(a, b): #gets the distance in tiles from "a" to "b"
  334.  
  335.     a = map.world_to_map(a)
  336.     b = map.world_to_map(b)
  337.     return int(abs(a.x - b.x) + abs(a.y - b.y))
  338.  
  339.  
  340. func get_lowestScoreAndDistance(list): #gets the index of the lowest distance among the lowest score duplicates
  341.     var idx = 0
  342.     var duplicates = []
  343.     for i in range(list.size() - 1): #gets the lowest score
  344.  
  345.         if list[i].score < list[idx].score:
  346.  
  347.             idx = i
  348.     for i in range(list.size() - 1): #gets all the lowest score duplicates into an array
  349.  
  350.         if list[i].score == list[idx].score:
  351.  
  352.             duplicates.append(i)
  353.     for i in duplicates: #checks each duplicate for the lowest distance value and set it as the right idx
  354.  
  355.         if list[i].distance < list[idx].distance:
  356.  
  357.             idx = i
  358.     return idx
  359.  
  360.  
  361. func get_sides(node): #gets the four sides of a node always in the contrary order
  362.  
  363.     var sides = []
  364.     for side in s:
  365.  
  366.         for tile in mapArray:
  367.  
  368.             if tile == node + side:
  369.  
  370.                 sides.append(tile)
  371.     s.invert() #this is important as to eliminate favoritism for routes with rectangular shapes.
  372.     return sides
  373.  
  374.  
  375. func _pathInverter(list, start, goal): #takes the result of pathfinding and translates it to a route that is understandable for the character.
  376.     var pathList = []
  377.     var current = goal
  378.     pathList.append(goal)
  379.     while not pathList.has(start): #beginning from the goal
  380.  
  381.         for i in list: #for each index in the list(closedList)
  382.  
  383.             if current == start:
  384.  
  385.                 break
  386.             if i.coord == current: #check if it matches with the "actual node" coordinate value
  387.  
  388.                 current = i.parent #turn the parent into the node currently being checked(step 3 "actual node")
  389.                 pathList.append(current) #append current to the pathList
  390.                 break
  391.     pathList.invert()
  392.     return pathList #as the pathList is drawn backwards it has to be inverted
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement