Invalid access to property or key 'visible' on a base object of type 'GDScript'

Godot Version

4.6.2

Question

So I’m trying to make it so that when the bosses shield is down and when the angle is right, it will damage the boss, but when I try to jump on the boss, it calls up the error “Invalid access to property or key ‘visible’ on a base object of type ‘GDScript’.” I’ve been having a lot of trouble in general with getting the boss and player to react to each other properly so I wouldn’t be surprised if there were more issues behind this one.

Heres the player script and the one that shows up with error:

class_name Player
signal damaged

var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")

@onready var deathsfx = $Music/death
@onready var jumpfx = $Music/Jump
@onready var damagefx = $Music/damage
@onready var animated_sprite_2d = $Sprite2D as PlayerAnimatedSprite
@onready var area_collision_shape = $"Area2D/area collision shape"
@onready var body_collision_shape = $bodycollisionshape
@onready var area_2d = $Area2D
@onready var Rescue = Rescuables


var run_speed_damping = 0.8
var speed:float = 250.0
var jump_velocity = -425

var collected: bool = false
var knockback: Vector2 = Vector2.ZERO
var knockback_timer: float = 0.0



@onready var min_stomp_degree = 35
@onready var max_stomp_degree = 145
@onready var stomp_y_velocity = -150
@onready var bounceback = -300
@onready var bouncebackx = -150


@onready var camera_sync: Camera2D = $Camera2D2
@onready var should_camera_sync: bool = true




func _physics_process(delta):
	
	if not is_on_floor():
		velocity.y += gravity * delta
		
	if Input.is_action_just_pressed("jump") and is_on_floor():
		velocity.y = jump_velocity
		jumpfx.play()
		
	if Input.is_action_just_released("jump") and velocity.y < 0:
		velocity.y *= 0.5
		
	var direction = Input.get_axis("left","right")

	if direction:
		velocity.x = lerpf(velocity.x, speed * direction, run_speed_damping * delta)
	else:
		velocity.x = move_toward(velocity.x, 0, speed * delta)
	
	animated_sprite_2d.trigger_animation(velocity, direction)
	
	move_and_slide()
	
func _on_area_2d_area_entered(area):
	if area is Enemy:
		handle_enemy_collision(area)
		print("lalal")
	if area is Block:
		handle_block_collision(area)
	if area is bosstransfer:
		get_tree().change_scene_to_file("res://stage1.tscn")

func _on_area_2d_body_entered(body):
	if body is forcefield:
		handle_force_collision(body)
		print("hdshdh")
	if body is Boss:
		handle_boss_collection(body)
		print("boss")
		
func handle_force_collision(force: CharacterBody2D):
	if force == forcefield:
		print("d")
		velocity.y = bounceback
		velocity.x = bouncebackx

func handle_block_collision(block: Block):
	if block == Block:
		die()
	
func handle_boss_collection(boss: Boss):
	if boss == null:
		return
	var angle_of_collision = rad_to_deg(position.angle_to_point(boss.position))
	
	if forcefield.visible == false and angle_of_collision > min_stomp_degree && max_stomp_degree:
		boss.take_damage()
		on_enemy_stomped()
	elif GameManager.health > 0:
		GameManager.health -= 1
		velocity.y = bounceback
		velocity.x = bouncebackx
		animated_sprite_2d.update()
		damaged.emit()
		damagefx.play()
	if GameManager.health == 0:
		die()
	
	
func handle_enemy_collision(enemy: Enemy):
	if enemy == null:
		return
	var angle_of_collision = rad_to_deg(position.angle_to_point(enemy.position))
	
	if angle_of_collision > min_stomp_degree && max_stomp_degree > angle_of_collision:
		enemy.die()
		on_enemy_stomped()
	elif GameManager.health > 0:
		animated_sprite_2d.update()
		damagefx.play()
		$Sprite2D.play("damage")
		GameManager.health -= 1
		velocity.y = bounceback
		velocity.x = bouncebackx
	if GameManager.health == 0:
		die()
	
		
func _input(event : InputEvent):
	if (event.is_action_pressed("down")) && is_on_floor():
		position.y += 1
	
func on_enemy_stomped():
	velocity.y = stomp_y_velocity
	
func die():
	animated_sprite_2d.play("die")
	deathsfx.play()
	area_2d.set_collision_mask_value(3, false)
	set_collision_layer_value(1, false)
	set_physics_process(false)
	
	var death_tween = get_tree().create_tween()
	death_tween.tween_property(self, "position", position + Vector2(0, -48), .5)
	death_tween.chain().tween_property(self, "position", position + Vector2(0,256),1)
	death_tween.tween_callback(func (): get_tree().reload_current_scene())
	await get_tree().create_timer(1.2).timeout
	GameManager.health = 3
	
func _process(_delta):
	if global_position.x > camera_sync.global_position.x && should_camera_sync:
		camera_sync.global_position.x = global_position.x
	if global_position.x < camera_sync.global_position.x && should_camera_sync:
		camera_sync.global_position.x = global_position.x



func _on_brick_2_body_entered(_body: Node2D):
	die()


func _on_static_body_2d_body_entered(body: Node2D) -> void:
	if body == $"../StaticBody2D":
		get_tree().change_scene_to_file("res://stage1.tscn")

And here is the script for the forcefield. I want it to knock back the player but I’m having trouble with that too, so they might be connected.

class_name forcefield


func _on_timer_timeout():
	visible = !visible
	$forcefield.disabled = !visible

forcefield is a class_name, not a specific object that exists in your game. It’s like a blueprint to make a forcefield, not a real forcefield. If your boss has a forcefield child then you need to get that node specifically.

You also use force == forcefield which may never be true, the function calling this handle_force_collision already checks if body is forcefield so I don’t see the reason to use it again but is is the correct keyword to detect a type.