SHARE
TWEET

Untitled

a guest May 8th, 2019 117 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
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top