inching towards better class inheritence and multiplayer compatibility
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
extends Node3D
|
||||
class_name AStarGraph3D
|
||||
|
||||
@export var grid_size := Vector2(21, 13)
|
||||
@export var grid_size := Vector2i(21, 13)
|
||||
@export var point_gap := 1.2
|
||||
var non_build_locations = []
|
||||
var astar := AStar3D.new()
|
||||
|
34
Scripts/Projectiles/explosive_projectile.gd
Normal file
34
Scripts/Projectiles/explosive_projectile.gd
Normal file
@ -0,0 +1,34 @@
|
||||
extends Projectile
|
||||
class_name ExplosiveProjectile
|
||||
|
||||
@export var explosion_range := 3.0
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
super._process(delta)
|
||||
if time_alive >= lifetime:
|
||||
explode()
|
||||
|
||||
|
||||
func _on_body_entered(_body: Node) -> void:
|
||||
explode()
|
||||
|
||||
|
||||
func explode():
|
||||
if is_multiplayer_authority():
|
||||
for enemy in get_tree().get_nodes_in_group("Enemies"):
|
||||
if global_position.distance_to(enemy.global_position) <= explosion_range:
|
||||
hit(enemy)
|
||||
networked_hit.rpc(get_tree().root.get_path_to(enemy))
|
||||
networked_kill.rpc()
|
||||
queue_free()
|
||||
|
||||
|
||||
func hit(target):
|
||||
target.damage(damage)
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_hit(target_node_path):
|
||||
var target = get_tree().root.get_node(target_node_path)
|
||||
hit(target)
|
17
Scripts/Projectiles/homing_projectile.gd
Normal file
17
Scripts/Projectiles/homing_projectile.gd
Normal file
@ -0,0 +1,17 @@
|
||||
extends ExplosiveProjectile
|
||||
class_name HomingProjectile
|
||||
|
||||
var target : Node3D
|
||||
@export var acceleration := 40.0
|
||||
@export var max_speed := 14.0
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if is_instance_valid(target):
|
||||
direction = global_position.direction_to(target.global_position)
|
||||
#apply_central_force(direction * acceleration)
|
||||
|
||||
|
||||
func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
|
||||
state.linear_velocity += direction * acceleration * state.step
|
||||
state.linear_velocity = state.linear_velocity.limit_length(max_speed)
|
23
Scripts/Projectiles/projectile.gd
Normal file
23
Scripts/Projectiles/projectile.gd
Normal file
@ -0,0 +1,23 @@
|
||||
extends RigidBody3D
|
||||
class_name Projectile
|
||||
|
||||
@export var collision_shape : CollisionShape3D
|
||||
|
||||
var direction := Vector3.FORWARD
|
||||
var force := 2.0
|
||||
var damage := 0.0
|
||||
var lifetime := 10.0
|
||||
var time_alive := 0.0
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
time_alive += delta
|
||||
|
||||
|
||||
func _on_body_entered(_body: Node) -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_kill():
|
||||
queue_free()
|
15
Scripts/Projectiles/status_applying_projectile.gd
Normal file
15
Scripts/Projectiles/status_applying_projectile.gd
Normal file
@ -0,0 +1,15 @@
|
||||
extends ExplosiveProjectile
|
||||
class_name StatusApplyingProjectile
|
||||
|
||||
@export var status_stats : StatusStats
|
||||
|
||||
|
||||
func hit(target):
|
||||
super.hit(target)
|
||||
target.status_manager.add_effect(build_status_object())
|
||||
|
||||
|
||||
func build_status_object() -> StatusEffect:
|
||||
var status = StatusEffect.new()
|
||||
status.stats = status_stats
|
||||
return status
|
@ -1,7 +0,0 @@
|
||||
extends Resource
|
||||
class_name TowerStats
|
||||
|
||||
@export var can_target : Data.TargetType
|
||||
@export var damage := 10.0
|
||||
@export var fire_range := 20.0
|
||||
@export var fire_rate := 1.0
|
@ -1,6 +0,0 @@
|
||||
extends Resource
|
||||
class_name WeaponStats
|
||||
|
||||
@export var damage : int
|
||||
@export var fire_rate : float
|
||||
@export var fire_range : float
|
@ -1,13 +1,13 @@
|
||||
extends Resource
|
||||
class_name Card
|
||||
|
||||
enum Faction {GENERIC}
|
||||
enum Faction {GENERIC = 0}
|
||||
|
||||
@export var title : String
|
||||
@export var rarity : Data.Rarity
|
||||
@export var faction : Faction
|
||||
@export var faction : Faction
|
||||
@export var sprite : AtlasTexture
|
||||
@export var turret : PackedScene
|
||||
@export var weapon : PackedScene
|
||||
@export var weapon_stats : WeaponStats
|
||||
@export var tower_stats : TowerStats
|
||||
@export var turret_scene : PackedScene
|
||||
@export var weapon_scene : PackedScene
|
||||
@export var weapon_stats : CardText
|
||||
@export var tower_stats : CardText
|
||||
|
13
Scripts/Resources/card_text.gd
Normal file
13
Scripts/Resources/card_text.gd
Normal file
@ -0,0 +1,13 @@
|
||||
extends Resource
|
||||
class_name CardText
|
||||
|
||||
@export var target_type : Data.TargetType
|
||||
@export var attributes : Array[StatAttribute]
|
||||
@export_multiline var text : String
|
||||
|
||||
|
||||
func get_attribute(attribute : String) -> float:
|
||||
for stat in attributes:
|
||||
if stat.key == attribute:
|
||||
return stat.value
|
||||
return 0.0
|
5
Scripts/Resources/stat_attribute.gd
Normal file
5
Scripts/Resources/stat_attribute.gd
Normal file
@ -0,0 +1,5 @@
|
||||
extends Resource
|
||||
class_name StatAttribute
|
||||
|
||||
@export var key : String
|
||||
@export var value : float
|
@ -1,6 +0,0 @@
|
||||
extends StatusEffect
|
||||
class_name StatusOnFire
|
||||
|
||||
|
||||
func proc(affected, stacks, _existing_effects):
|
||||
affected.damage(stats.potency * stacks)
|
@ -1,5 +1,5 @@
|
||||
extends StatusEffect
|
||||
class_name StatusPoison
|
||||
class_name StatusDoT
|
||||
|
||||
|
||||
func proc(affected, stacks, _existing_effects):
|
@ -1,5 +0,0 @@
|
||||
extends StatusEffect
|
||||
class_name StatusRadioactive
|
||||
|
||||
func proc(affected, stacks, _existing_effects):
|
||||
affected.damage(stats.potency * stacks)
|
@ -1,5 +1,6 @@
|
||||
extends StatusEffect
|
||||
class_name StatusCold
|
||||
class_name StatusSlow
|
||||
|
||||
|
||||
func on_attached(affected, _existing_effects):
|
||||
affected.movement_speed_penalty -= stats.potency
|
@ -1,10 +0,0 @@
|
||||
extends StatusEffect
|
||||
class_name StatusSticky
|
||||
|
||||
|
||||
func on_attached(affected, _existing_effects):
|
||||
affected.movement_speed_penalty -= stats.potency
|
||||
|
||||
|
||||
func on_removed(affected, _existing_effects):
|
||||
affected.movement_speed_penalty += stats.potency
|
13
Scripts/Towers/hitscan_tower.gd
Normal file
13
Scripts/Towers/hitscan_tower.gd
Normal file
@ -0,0 +1,13 @@
|
||||
extends Tower
|
||||
class_name HitscanTower
|
||||
|
||||
|
||||
func shoot():
|
||||
super.shoot()
|
||||
if targeted_enemy and is_instance_valid(targeted_enemy) and targeted_enemy.alive:
|
||||
targeted_enemy.damage(damage)
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_shoot():
|
||||
super.networked_shoot()
|
30
Scripts/Towers/projectile_tower.gd
Normal file
30
Scripts/Towers/projectile_tower.gd
Normal file
@ -0,0 +1,30 @@
|
||||
extends Tower
|
||||
class_name ProjectileTower
|
||||
|
||||
@export var projectile_scene : PackedScene
|
||||
|
||||
var force := 2.0
|
||||
var projectile_id := 0
|
||||
|
||||
|
||||
func shoot():
|
||||
if is_multiplayer_authority():
|
||||
networked_spawn_projectile.rpc(multiplayer.get_unique_id())
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_shoot():
|
||||
super.networked_shoot()
|
||||
shoot()
|
||||
|
||||
|
||||
@rpc("reliable", "call_local")
|
||||
func networked_spawn_projectile(peer_id):
|
||||
var projectile = projectile_scene.instantiate() as Projectile
|
||||
projectile.position = global_position + Vector3.UP
|
||||
projectile.damage = damage
|
||||
projectile.direction = -yaw_model.global_transform.basis.z
|
||||
projectile.force = force
|
||||
projectile.name = base_name + str(peer_id) + str(projectile_id)
|
||||
get_tree().root.add_child(projectile)
|
||||
projectile_id += 1
|
92
Scripts/Towers/tower.gd
Normal file
92
Scripts/Towers/tower.gd
Normal file
@ -0,0 +1,92 @@
|
||||
extends Node3D
|
||||
class_name Tower
|
||||
|
||||
@export var stats : CardText
|
||||
@export var animator : AnimationPlayer
|
||||
@export var pitch_model : MeshInstance3D
|
||||
@export var yaw_model : MeshInstance3D
|
||||
@export var range_indicator : CSGSphere3D
|
||||
|
||||
var base_name
|
||||
var targeted_enemy
|
||||
var time_since_firing := 0.0
|
||||
var time_between_shots := 0.0
|
||||
var damage := 0.0
|
||||
var target_range := 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
time_between_shots = stats.get_attribute("Fire Delay")
|
||||
damage = stats.get_attribute("Damage")
|
||||
target_range = stats.get_attribute("Range")
|
||||
range_indicator.radius = target_range
|
||||
|
||||
|
||||
func preview_range(value):
|
||||
range_indicator.set_visible(value)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if !is_multiplayer_authority():
|
||||
return
|
||||
if time_since_firing < time_between_shots:
|
||||
time_since_firing += delta
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if !is_multiplayer_authority():
|
||||
#only doing the graphical sort of stuff but not shoot logic
|
||||
if targeted_enemy:
|
||||
if !is_instance_valid(targeted_enemy) or !targeted_enemy.alive or global_position.distance_to(targeted_enemy.global_position) > target_range:
|
||||
targeted_enemy = null
|
||||
else:
|
||||
aim()
|
||||
return
|
||||
if !targeted_enemy:
|
||||
acquire_target()
|
||||
else:
|
||||
if !is_instance_valid(targeted_enemy) or !targeted_enemy.alive or global_position.distance_to(targeted_enemy.global_position) > target_range:
|
||||
targeted_enemy = null
|
||||
if targeted_enemy:
|
||||
aim()
|
||||
if time_since_firing >= time_between_shots:
|
||||
time_since_firing -= time_between_shots
|
||||
shoot()
|
||||
|
||||
|
||||
func aim():
|
||||
yaw_model.look_at(targeted_enemy.global_position)
|
||||
pitch_model.look_at(targeted_enemy.global_position)
|
||||
pitch_model.rotation.x = 0.0
|
||||
|
||||
|
||||
func acquire_target():
|
||||
var most_progressed_enemy = null
|
||||
for enemy in get_tree().get_nodes_in_group("Enemies"):
|
||||
if global_position.distance_to(enemy.global_position) > target_range:
|
||||
continue
|
||||
var em_1 = enemy.movement_controller as EnemyMovement
|
||||
var em_2 : EnemyMovement
|
||||
if most_progressed_enemy != null:
|
||||
em_2 = most_progressed_enemy.movement_controller as EnemyMovement
|
||||
if (most_progressed_enemy == null or em_1.distance_remaining < em_2.distance_remaining) and enemy.stats.target_type & stats.target_type:
|
||||
most_progressed_enemy = enemy
|
||||
if most_progressed_enemy != null:
|
||||
targeted_enemy = most_progressed_enemy
|
||||
networked_acquire_target.rpc(get_tree().root.get_path_to(most_progressed_enemy))
|
||||
|
||||
|
||||
func shoot():
|
||||
animator.play("shoot")
|
||||
if is_multiplayer_authority():
|
||||
networked_shoot.rpc()
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_shoot():
|
||||
shoot()
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_acquire_target(target_node_path):
|
||||
targeted_enemy = get_tree().root.get_node(target_node_path)
|
37
Scripts/Weapons/hitscan_weapon.gd
Normal file
37
Scripts/Weapons/hitscan_weapon.gd
Normal file
@ -0,0 +1,37 @@
|
||||
extends Weapon
|
||||
class_name HitscanWeapon
|
||||
|
||||
@export var raycast : RayCast3D
|
||||
@export var range_debug_indicator : CSGSphere3D
|
||||
|
||||
var attack_range := 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
super._ready()
|
||||
attack_range = stats.get_attribute("Range")
|
||||
raycast.target_position = Vector3(0, 0, -attack_range)
|
||||
range_debug_indicator.radius = attack_range
|
||||
raycast.global_position = hero.camera.global_position
|
||||
|
||||
|
||||
func shoot():
|
||||
super.shoot()
|
||||
if raycast.is_colliding():
|
||||
var target = raycast.get_collider()
|
||||
if target != null:
|
||||
var target_hitbox = target.shape_owner_get_owner(raycast.get_collider_shape())
|
||||
if target_hitbox is Hitbox:
|
||||
hit(target, target_hitbox)
|
||||
networked_hit.rpc(get_tree().root.get_path_to(target), get_tree().root.get_path_to(target_hitbox))
|
||||
|
||||
|
||||
func hit(_target, target_hitbox : Hitbox):
|
||||
target_hitbox.damage(damage)
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_hit(target_path : String, target_hitbox_path : String):
|
||||
var target = get_tree().root.get_node(target_path)
|
||||
var target_hitbox = get_tree().root.get_node(target_hitbox_path) as Hitbox
|
||||
hit(target, target_hitbox)
|
25
Scripts/Weapons/projectile_weapon.gd
Normal file
25
Scripts/Weapons/projectile_weapon.gd
Normal file
@ -0,0 +1,25 @@
|
||||
extends Weapon
|
||||
class_name ProjectileWeapon
|
||||
|
||||
@export var projectile_scene : PackedScene
|
||||
|
||||
var force := 2.0
|
||||
var projectile_id := 0
|
||||
|
||||
|
||||
func shoot():
|
||||
super.shoot()
|
||||
var projectile = projectile_scene.instantiate() as Projectile
|
||||
projectile.position = global_position
|
||||
projectile.damage = damage
|
||||
projectile.direction = -global_transform.basis.z
|
||||
projectile.force = force
|
||||
projectile.name = str(multiplayer.get_unique_id()) + str(projectile_id)
|
||||
get_tree().root.add_child(projectile)
|
||||
projectile_id += 1
|
||||
|
||||
|
||||
@rpc("reliable")
|
||||
func networked_shoot():
|
||||
super.networked_shoot()
|
||||
shoot()
|
15
Scripts/Weapons/status_applying_weapon.gd
Normal file
15
Scripts/Weapons/status_applying_weapon.gd
Normal file
@ -0,0 +1,15 @@
|
||||
extends HitscanWeapon
|
||||
class_name StatusApplyingWeapon
|
||||
|
||||
@export var status_stats : StatusStats
|
||||
|
||||
|
||||
func hit(target, target_hitbox : Hitbox):
|
||||
super.hit(target, target_hitbox)
|
||||
target.status_manager.add_effect(build_status_object())
|
||||
|
||||
|
||||
func build_status_object() -> StatusEffect:
|
||||
var status = StatusEffect.new()
|
||||
status.stats = status_stats
|
||||
return status
|
58
Scripts/Weapons/weapon.gd
Normal file
58
Scripts/Weapons/weapon.gd
Normal file
@ -0,0 +1,58 @@
|
||||
extends Node3D
|
||||
class_name Weapon
|
||||
|
||||
@export var stats : CardText
|
||||
@export var animator : AnimationPlayer
|
||||
|
||||
var hero : Hero
|
||||
var trigger_held := false
|
||||
var second_trigger_held := false
|
||||
var time_since_firing := 0.0
|
||||
var time_between_shots := 0.0
|
||||
var damage := 0.0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
time_between_shots = stats.get_attribute("Fire Delay")
|
||||
damage = stats.get_attribute("Damage")
|
||||
|
||||
|
||||
func set_hero(value):
|
||||
hero = value
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if time_since_firing < time_between_shots:
|
||||
time_since_firing += delta
|
||||
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if trigger_held and time_since_firing >= time_between_shots:
|
||||
time_since_firing -= time_between_shots
|
||||
shoot()
|
||||
networked_shoot.rpc()
|
||||
|
||||
|
||||
func hold_trigger():
|
||||
trigger_held = true
|
||||
|
||||
|
||||
func release_trigger():
|
||||
trigger_held = false
|
||||
|
||||
|
||||
func hold_second_trigger():
|
||||
second_trigger_held = true
|
||||
|
||||
|
||||
func release_second_trigger():
|
||||
second_trigger_held = false
|
||||
|
||||
|
||||
func shoot():
|
||||
animator.play("shoot")
|
||||
|
||||
|
||||
@rpc
|
||||
func networked_shoot():
|
||||
animator.play("shoot")
|
@ -3,28 +3,27 @@ class_name CardInHand
|
||||
|
||||
var stats : Card
|
||||
@export var rarity_sprite : Sprite2D
|
||||
@export var title_text: Label
|
||||
@export var damage_text_text: Label
|
||||
@export var damage_text: Label
|
||||
@export var fire_rate_text_text: Label
|
||||
@export var fire_rate_text: Label
|
||||
@export var range_text_text: Label
|
||||
@export var range_text: Label
|
||||
@export var title_text : Label
|
||||
@export var description : RichTextLabel
|
||||
|
||||
func set_card(value):
|
||||
stats = value
|
||||
title_text.text = stats.title
|
||||
rarity_sprite.region_rect = Rect2(64 * stats.rarity, 0, 64, 64)
|
||||
view_weapon()
|
||||
|
||||
|
||||
func process_card_text(card_text : CardText) -> String:
|
||||
var processed_string = card_text.text
|
||||
for stat in card_text.attributes:
|
||||
processed_string = processed_string.replace(stat.key, str(stat.value))
|
||||
processed_string = processed_string.replace("/", "[color=red]")
|
||||
processed_string = processed_string.replace("\\", "[color=black]")
|
||||
return processed_string
|
||||
|
||||
|
||||
func view_weapon():
|
||||
damage_text.text = str(stats.weapon_stats.damage)
|
||||
fire_rate_text.text = str(stats.weapon_stats.fire_rate)
|
||||
range_text.text = str(stats.weapon_stats.fire_rate)
|
||||
description.text = process_card_text(stats.weapon_stats)
|
||||
|
||||
|
||||
func view_tower():
|
||||
damage_text.text = str(stats.tower_stats.damage)
|
||||
fire_rate_text.text = str(stats.tower_stats.fire_rate)
|
||||
range_text.text = str(stats.tower_stats.fire_rate)
|
||||
description.text = process_card_text(stats.tower_stats)
|
||||
|
@ -10,9 +10,9 @@ var player_keymap : PlayerKeymap
|
||||
|
||||
var wall_cost := 4
|
||||
var printer_cost := 10
|
||||
enum TargetType {LAND = 1, AIR = 2, BOTH = 3}
|
||||
enum EnemyType {LAND = 1, AIR = 2}
|
||||
enum Rarity {COMMON, UNCOMMON, RARE, EPIC, LEGENDARY}
|
||||
enum TargetType {UNDEFINED = 0, LAND = 1, AIR = 2, BOTH = 3}
|
||||
enum EnemyType {UNDEFINED = 0, LAND = 1, AIR = 2}
|
||||
enum Rarity {COMMON = 0, UNCOMMON = 1, RARE = 2, EPIC = 3, LEGENDARY = 4}
|
||||
var rarity_weights = {
|
||||
"COMMON" = 50,
|
||||
"UNCOMMON" = 30,
|
||||
@ -32,18 +32,27 @@ func _ready() -> void:
|
||||
characters.append(preload("res://PCs/Green/green.tres"))
|
||||
characters.append(preload("res://PCs/Blue/blue.tres"))
|
||||
|
||||
#Common
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Assault/card_assault.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/BombLauncher/card_grenade_launcher.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Sniper/card_sniper.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/BombLauncher/card_bomb_launcher.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Gatling/card_gatling.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/GlueLauncher/card_glue_launcher.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/RocketLauncher/card_rocket_launcher.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Flamethrower/card_flamethrower.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Blowdart/card_blowdart.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Fireball/card_fireball.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Icicle/card_icicle.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Reactor/card_reactor.tres"))
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Refridgerator/card_refridgerator.tres"))
|
||||
#Uncommon
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Blowdart/card_blowdart.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Refridgerator/card_refridgerator.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/GlueLauncher/card_glue_launcher.tres"))
|
||||
#Rare
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Flamethrower/card_flamethrower.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/DamageEnhancer/card_damage_enhancer.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/SpeedEnhancer/card_speed_enhancer.tres"))
|
||||
#Epic
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Icicle/card_icicle.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Fireball/card_fireball.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/GammaLaser/card_gamma_laser.tres"))
|
||||
#Legendary
|
||||
cards.append(preload("res://PCs/Universal/ClassCards/Sniper/card_sniper.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Reactor/card_reactor.tres"))
|
||||
#cards.append(preload("res://PCs/Universal/ClassCards/Lightning/card_lightning.tres"))
|
||||
|
||||
enemies.append(preload("res://Worlds/GreenPlanet/Enemies/dog.tres"))
|
||||
enemies.append(preload("res://Worlds/GreenPlanet/Enemies/dog_fast.tres"))
|
||||
|
@ -93,7 +93,7 @@ func spawn_tower_preview():
|
||||
last_tower_base = ray_collider
|
||||
var card = inventory.selected_item
|
||||
last_card = card
|
||||
tower_preview = card.turret.instantiate() as Tower
|
||||
tower_preview = card.turret_scene.instantiate() as Tower
|
||||
tower_preview.stats = card.tower_stats
|
||||
tower_preview.preview_range(true)
|
||||
ray_collider.add_child(tower_preview)
|
||||
|
@ -23,7 +23,7 @@ var enemies := 0
|
||||
var objective_health := 120
|
||||
var wave := 0
|
||||
var upcoming_wave
|
||||
var pot : int
|
||||
var pot : float
|
||||
var UILayer : CanvasLayer
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ func set_upcoming_wave():
|
||||
if is_multiplayer_authority():
|
||||
var spawn_power = WaveManager.calculate_spawn_power(wave + 1, connected_players_nodes.size())
|
||||
var new_wave = WaveManager.generate_wave(spawn_power, level.enemy_pool)
|
||||
networked_set_upcoming_wave.rpc(new_wave, 6 + (spawn_power / 100))
|
||||
networked_set_upcoming_wave.rpc(new_wave, 6 + floori(spawn_power / 100))
|
||||
|
||||
|
||||
@rpc("reliable", "call_local")
|
||||
@ -158,6 +158,9 @@ func remove_player(peer_id):
|
||||
|
||||
func start_game():
|
||||
game_active = true
|
||||
enemies = 0
|
||||
objective_health = 100
|
||||
wave = 0
|
||||
level.a_star_graph_3d.make_grid()
|
||||
level.a_star_graph_3d.find_path()
|
||||
set_upcoming_wave()
|
||||
|
@ -1,2 +0,0 @@
|
||||
extends Node3D
|
||||
class_name GroundEnemyController
|
58
Scripts/tower.gd
Normal file
58
Scripts/tower.gd
Normal file
@ -0,0 +1,58 @@
|
||||
extends Node3D
|
||||
class_name OldTower
|
||||
|
||||
@export var model : Node3D
|
||||
@export var range_sphere : CSGSphere3D
|
||||
@export var minimap_range_sphere : CSGSphere3D
|
||||
|
||||
var targeted_enemy
|
||||
var cooldown := 0.0
|
||||
var other_cooldown := 0.0
|
||||
|
||||
func _ready() -> void:
|
||||
cooldown = 1.0 / stats.fire_rate
|
||||
range_sphere.radius = stats.fire_range
|
||||
minimap_range_sphere.radius = stats.fire_range
|
||||
#minimap_range_sphere.set_visible(true)
|
||||
|
||||
|
||||
func preview_range(value):
|
||||
range_sphere.set_visible(value)
|
||||
minimap_range_sphere.set_visible(value)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
other_cooldown -= delta
|
||||
if !targeted_enemy:
|
||||
acquire_target()
|
||||
else:
|
||||
if model.global_position.distance_to(targeted_enemy.global_position) > stats.fire_range:
|
||||
targeted_enemy = null
|
||||
if targeted_enemy:
|
||||
aim()
|
||||
if other_cooldown <= 0:
|
||||
shoot()
|
||||
other_cooldown = cooldown
|
||||
|
||||
|
||||
func shoot():
|
||||
targeted_enemy.damage(stats.damage)
|
||||
|
||||
|
||||
func aim():
|
||||
model.look_at(targeted_enemy.global_position)
|
||||
|
||||
|
||||
func acquire_target():
|
||||
var most_progressed_enemy = null
|
||||
for enemy in get_tree().get_nodes_in_group("Enemies"):
|
||||
if model.global_position.distance_to(enemy.global_position) > stats.fire_range:
|
||||
continue
|
||||
var em_1 = enemy.movement_controller as EnemyMovement
|
||||
var em_2 : EnemyMovement
|
||||
if most_progressed_enemy != null:
|
||||
em_2 = most_progressed_enemy.movement_controller as EnemyMovement
|
||||
if (most_progressed_enemy == null or em_1.distance_remaining < em_2.distance_remaining) and enemy.stats.target_type & stats.can_target:
|
||||
most_progressed_enemy = enemy
|
||||
if most_progressed_enemy != null:
|
||||
targeted_enemy = most_progressed_enemy
|
@ -36,9 +36,11 @@ func toggle_collision():
|
||||
|
||||
@rpc("reliable", "call_local", "any_peer")
|
||||
func networked_spawn_tower():
|
||||
tower = inventory.selected_item.turret.instantiate() as Tower
|
||||
tower = inventory.selected_item.turret_scene.instantiate() as Tower
|
||||
tower.stats = inventory.selected_item.tower_stats
|
||||
tower.name = "tower"
|
||||
tower.base_name = name
|
||||
tower.position = Vector3.UP
|
||||
minimap_icon.modulate = Color.RED
|
||||
add_child(tower)
|
||||
|
||||
|
@ -7,15 +7,15 @@ func calculate_spawn_power(wave_number : int, number_of_players : int) -> int:
|
||||
|
||||
func generate_wave(spawn_power : int, spawn_pool : Array[Enemy]) -> Dictionary:
|
||||
var wave = {}
|
||||
#var sp_used = 0
|
||||
var sp_used = 0
|
||||
var enemy_types = randi_range(1, 5)
|
||||
var enemy_choices = spawn_pool.duplicate()
|
||||
var sp_allotment = spawn_power / enemy_types
|
||||
var sp_allotment = floori(spawn_power / enemy_types)
|
||||
for x in enemy_types:
|
||||
var choice = enemy_choices.pick_random()
|
||||
enemy_choices.erase(choice)
|
||||
if sp_allotment / choice.spawn_power > 0:
|
||||
wave[Data.enemies.find(choice)] = sp_allotment / choice.spawn_power
|
||||
#sp_used += wave[choice] * choice.spawn_power
|
||||
#print("tried to generate wave with " + str(spawn_power) + " spawn power, used " + str(sp_used))
|
||||
sp_used += wave[Data.enemies.find(choice)] * choice.spawn_power
|
||||
print("tried to generate wave with " + str(spawn_power) + " spawn power, used " + str(sp_used))
|
||||
return wave
|
||||
|
Reference in New Issue
Block a user