Godot Version
3.5
Question
Sorry for the super old godot version, just trying to plow through and finish this old project.
EDIT: OKAY I think i finally got it formatted. second comment has the enemy’s individual code.
TY anyone who can help
I am in the middle of trying to code a simple ‘mini boss’ type character, and one of his attacks works well but not the other.
It seems to be an animation error - the hit box to hurt the player is activated in the animation, and the animation itself simply won’t play.
There are some other bugs, too , but this is the one I’ve been working on debugging.
(Other bugs are that he flips his attacking ‘direction’ a lot. So he shows one direction, then flips to another direction, then flips back, for example. I haven’t tried to debug that a lot yet though since Im in the middle of fixing this one other bug.)
There’s… a lot of code here (for me) SO I would really not blame anyone who doesn’t want to read it. but i’ll post it anyway in case someone is patient and can help.
First, the ‘character parent’ code - the code all characters inherit from:
onready var immunity_timer = $ImmunityTimer
onready var interrupted_timer = $InterruptedTimer
onready var death_timer = $DeathTimer
onready var healthbar_total = $HealthBarTotal
onready var healthbar_current = $HealthBarTotal/HealthBarCurrent
onready var healthbar_new = $HealthBarNew
#thinking we're gonna need a placeholder sprite for tihs
#and then whenever we are changing the sprite in code on the player
#or enemy. we use this name, to modulate it!
onready var test_sprite = $TestSprite
# Called when the node enters the scene tree for the first time.
func _ready():
#do we update difficulty mods here? Or manually on player and enemies?
#maybe i DO have to do it in the parent.... (here)
update_difficulty_lvl()
#we need to update health bar when we HEAL too!!!!
#function for taking damage should be here!
#so ... when we take damage we ALSO need to stop our current action!
func take_damage(var damage):
currentHealth_modded -= (damage * damage_taken_modded)
update_small_healthbar(currentHealth_modded)
#if we're dead, we dont need the timers!
if currentHealth_modded <= 0:
on_death()
else:
#knockback willb e called from the player GIVING damage, not here
#call interrupted to interrupt them
if interrupted_timer != null:
interrupted()
immune()
interrupted_timer.start()
immunity_timer.start()
else:
print ("Interrupted timer was null")
#dont think i've added custom knockback functionality yet. may add later.
#called in area entereds, on teh player/ item giving damage
func knockback(var dam_pos):
#first we need to compare the abs value. make sure that there is big
#enough difference to actually make it diagnonal (as opposed to just 4 directoinal)
var x_dif = self.position.x - dam_pos.x
var y_dif = self.position.y - dam_pos.y
var _abs_x_dif = abs(x_dif)
var abs_y_dif = abs(y_dif) #could do this in just two lines with abs around the expressoin
#but i noob and wnat it readable
if self.global_position.x < dam_pos.x:
#if the damage comes FROM the right.
if abs_y_dif <= knockback_smidge_value:
#we are in range. knocke em to the left
#it looks like we used move_and_slide for the player and moveable enemies
velocity.x += -knockback_amount
elif self.global_position.y < dam_pos.y:
#the damage comes FROM down direction
#knock em upleft
velocity.x += -knockback_amount
velocity.y += -knockback_amount
else:
#its not in smidge and not from down, it must be from up.
#knock em downleft
velocity.x += -knockback_amount
velocity.y += knockback_amount
elif self.global_position.x > dam_pos.x:
#damage came from the LEFT
if abs_y_dif <= knockback_smidge_value:
#knock em right
velocity.x += knockback_amount
elif self.global_position.y < dam_pos.y:
#damage comes FROM down directoin
#knock them up right
velocity.x += knockback_amount
velocity.y += -knockback_amount
else:
#dmaage should be coming from up.
#knock em downright
velocity.x += knockback_amount
velocity.y += knockback_amount
elif self.global_postiion.y < dam_pos.y:
#damage coming FROM down.
#we dont need to check for x smidge value as we started w/ x logic
#and its elfi
#knock em up
velocity.y += -knockback_amount
else:
#knock em donw
velocity.y += knockback_amount
#this is the func we call to make it so that whoever was hit cannot do another hting
#until their interrupted timer passes
func interrupted():
var sprites_to_freeze = [0] #fuck it it doesn't even need to be all sprites
#we need to freeze the node
#NOW I am thinking lets freeze indivdiual parts...
#if we want a knockback...
can_move = false
sprites_to_freeze = check_nodes_types_and_return_sprites()
#okay this dont work in an array :X so we must loop
for i in sprites_to_freeze.size():
sprites_to_freeze[i].self_modulate = Color(0, 0, 1)
#This lasts longer than interrupted
func immune():
can_take_damage = false
var sprites = [0]
sprites = check_nodes_types_and_return_sprites()
for i in sprites.size():
sprites[i].self_modulate = Color(0, 0, 1, .5)
# we need to make the node see through or a slightly different color
#to clarify they cannot take damage now
func update_small_healthbar(new_value):
healthbar_new.value = new_value
#for destroying ourself if we die?
#or at least stopping our movement
func on_death():
set_physics_process(false)
set_process(false)
var sprites = [0]
sprites = check_nodes_types_and_return_sprites()
for i in sprites.size():
#this null check is very important. otherwise it bugs
#cuz of the first null sprite!
if sprites[i] != null:
var tween = get_tree().create_tween()
tween.tween_property(sprites[i], "modulate", Color(1, 1, 1, 0), 1.0)
death_timer.start()
func _on_ImmunityTimer_timeout():
can_take_damage = true #now we can take damage again
var sprites = [0]
sprites = check_nodes_types_and_return_sprites()
for i in sprites.size():
#this null check is very important. otherwise it bugs
#cuz of the first null sprite!
if sprites[i] != null:
sprites[i].self_modulate = Color(1, 1, 1, 1)
#so ...w e need to get ourself and all our children
#and see which are sprite nodes
#nad then return tehm!
func check_nodes_types_and_return_sprites():
var array_of_sprites = [test_sprite]
#cuz of godots weird way to set arrays
for i in self.get_children():
#array_of_children.append(i)
if i is Sprite:
array_of_sprites.append(i)
return array_of_sprites
#DONT Delete this
#okay im a dumb dumb. i acutally need to get facing dir for raycasting code to work
#as it uses the facing dir to decide which way to cast the ray
#so this won't work on enemies at times?
#but it always works on player
#It LOOKS like when the enemy collides with the player, then they cannot get facing!
func get_facing_dir():
#if we are moving, we can change the facing dir
if velocity != Vector2(0,0):
#if we are moving positive in x dir
if velocity.x > 0.1:
#and not moving on y dir
if velocity.y == 0:
facing = directions.RIGHT
#if we are moving positive in y and x (remmeber, pos y is down)
elif velocity.y > 0.1:
facing = directions.DOWNRIGHT
elif velocity.y < -0.1:
facing = directions.UPRIGHT
#if we are moving left
elif velocity.x < -0.1:
if velocity.y == 0:
facing = directions.LEFT
elif velocity.y < -0.1:
facing = directions.UPLEFT
elif velocity.y > 0.1:
facing = directions.DOWNLEFT
elif velocity.y < -0.1 and velocity.x == 0:
facing = directions.UP
elif velocity.y > 0.1 and velocity.x == 0:
facing = directions.DOWN
#we enter else sometimes. need to find out why!
# else:
# print("could not get facing direction")
#we cannot simply use velocity
#because the entity may have zero velocity
#but still be facing in a direction
func get_facing_dir_as_vector():
match facing:
directions.DOWN:
return Vector2(0,1)
directions.UP:
return Vector2(0,-1)
directions.RIGHT:
return Vector2(1,0)
directions.LEFT:
return Vector2(-1,0)
directions.UPRIGHT:
return Vector2(1,-1).normalized()
directions.UPLEFT:
return Vector2(-1,-1).normalized()
directions.DOWNRIGHT:
return Vector2(1,1).normalized()
directions.DOWNLEFT:
return Vector2(-1,1).normalized()
#we need a way to update our variables.... for difficulty mods
func update_difficulty_lvl():
if team == "player":
#do player stuff
#do we have to load current health and max health differently?
#based on IF the player or enemy already has helath off or not?
#I THINK SO
if currentHealth_modded == maxHealth_modded:
maxHealth_modded = maxHealth * DifficultyManager.p_health_mod
currentHealth_modded = maxHealth
healthbar_new.max_value = maxHealth_modded
healthbar_new.value = currentHealth_modded
#we need to check for IF they have already been modified... hmmm
#maybe i need hte bases as variables and hten teh modified variants as varialbes
#that seems overly complicated but lets try it
damage_done_modded = damage_done * DifficultyManager.p_damage_mod
damage_taken_modded = damage_taken * DifficultyManager.p_damage_per_taken
knockback_modded = knockback_amount * DifficultyManager.p_knocked_back
attack_speed_modded = 1.0 #multiplicative
charge_speed_modded = 1.0
elif team == "enemy":
#do enemy stuff:
if currentHealth_modded == maxHealth_modded:
maxHealth_modded = maxHealth * DifficultyManager.e_health_mod
currentHealth_modded = maxHealth_modded
healthbar_new.max_value = maxHealth_modded
healthbar_new.value = currentHealth_modded
damage_done_modded = damage_done * DifficultyManager.e_damage_mod
damage_taken_modded = damage_taken * DifficultyManager.e_damage_per_taken
knockback_modded = knockback_amount * DifficultyManager.e_knocked_back
#for some reason attack speed modded is being an ITEM/ node, NOT a number!!!!
#so is charge speed, fyi
attack_speed_modded = DifficultyManager.e_attack_speed
charge_speed_modded = DifficultyManager.e_charge_speed
else:
#probably frienld. do nothing
pass
#our save dict func
func save():
var save_dict = {
"filename" : get_filename(),
"parent" : get_parent().get_path(),
"pos_x" : position.x, #Vector 2 is not supported by JSON
"pos_y" : position.y,
"maxHealth" : maxHealth,
"currentHealth" : currentHealth,
"maxHealth_modded": maxHealth_modded,
"currentHealth_modded": currentHealth_modded,
"team" : team
}
return save_dict
func _on_InteruptedTimer_timeout():
var sprites_to_unfreeze = [0] #fuck it it doesn't even need to be all sprites
can_move = true
sprites_to_unfreeze = check_nodes_types_and_return_sprites()
set_process(true)
set_physics_process(true)
for i in sprites_to_unfreeze.size():
sprites_to_unfreeze[i].self_modulate = Color(1, 1, 1, .5)
func _on_DeathTimer_timeout():
self.queue_free()
THen, th enemy’s individualized code
I’ve already tried checking the animation player and animation tree. Animation tree WILL show basic attack play from ‘charge basic attack’ but it won’t happen in game. So the error could be there soemwhere?
Sorry for the long post.
