280 lines
8.5 KiB
GDScript
280 lines
8.5 KiB
GDScript
extends Node3D
|
|
class_name level
|
|
|
|
@export var map_name : String = "Map Name"
|
|
@export var gamemode : gamemode
|
|
@export var player : Node
|
|
@export var MAX_PARTICLES = 100
|
|
@export_group("Drops")
|
|
@export var drop_chance_minimum = .1
|
|
@export var expected_ammo = {"light" : 200, "medium" : 50, "heavy" : 25,"shotgun" : 20, "rocket" : 3} #light, medium,heavy,shotgun,rocket
|
|
@export var stamina_drop_enabled = true
|
|
@export var money_drop_enabled = true
|
|
|
|
@onready var item_pickup = preload("res://assets/item_pickup.tscn")
|
|
@onready var crown = preload("res://assets/crown.tscn")
|
|
var dead_player = preload("res://assets/dead_cam.tscn")
|
|
const DEAD_ANNOUNCE = preload("res://assets/dead_announce.tscn")
|
|
const CHEST_1 = preload("res://chest1.tscn")
|
|
|
|
var level_name
|
|
var paused = false
|
|
var chest_spawners = []
|
|
var pickups = []
|
|
|
|
var keys = []
|
|
var guns_dict = {}
|
|
var particle_number = 0
|
|
var enemy_hiveminds = []
|
|
var remaining_enemies
|
|
var last_hit : Node
|
|
var target_type
|
|
var respawn_position
|
|
var respawn_cam_rotation
|
|
var respawn_rot
|
|
var engine_time_scale_cache : float = 1.0
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
func _ready():
|
|
level_name = self.get_name()
|
|
GameGlobals.current_level = str(self.scene_file_path)
|
|
|
|
if GameGlobals.loading_gamemode != null:
|
|
gamemode = GameGlobals.loading_gamemode
|
|
GameGlobals.loading_gamemode = null
|
|
|
|
#connect to signals
|
|
SignalBus.enemy_count_changed.connect(enemy_count)
|
|
|
|
GameGlobals.health = gamemode.start_health
|
|
|
|
#LOAD DATA
|
|
SaveLoad.load_persistent_data()
|
|
SaveLoad.load_user_data()
|
|
|
|
if SaveLoad.data_cleared or !gamemode.load_save:
|
|
refresh_scene()
|
|
GameGlobals.game_loaded = true
|
|
SignalBus.emit_signal("game_loaded")
|
|
else:
|
|
if SaveLoad.check_save_game_exists(level_name):
|
|
SaveLoad.load_save_game_data(level_name)
|
|
else:
|
|
refresh_scene()
|
|
|
|
#Spawn Crown
|
|
if GameGlobals.last_hit_path:
|
|
var crown_spawn = crown.instantiate()
|
|
var crown_target = get_node(GameGlobals.last_hit_path)
|
|
if crown_target:
|
|
crown_target.add_child(crown_spawn)
|
|
crown_spawn.position = Vector3(0,2,0)
|
|
if crown_target.is_in_group("enemy"):
|
|
crown_target.loot_amount = 10
|
|
#global randomize function
|
|
randomize()
|
|
|
|
|
|
#clear spawned in objects
|
|
for node in get_tree().get_nodes_in_group("spawned"):
|
|
node.queue_free()
|
|
|
|
#find enemy hiveminds
|
|
for node in get_tree().get_nodes_in_group("enemy_hivemind"):
|
|
enemy_hiveminds.append(node)
|
|
#count starting enemies
|
|
enemy_count()
|
|
|
|
chest_spawners = get_tree().get_nodes_in_group("chest_spawner")
|
|
if chest_spawners.size() > 0:
|
|
for i in chest_spawners:
|
|
i.visible = false
|
|
|
|
var number_chests = randi_range(1,gamemode.max_number_of_chests)
|
|
|
|
while number_chests > 0:
|
|
var chest_loc = chest_spawners.pick_random()
|
|
var instance_chest = CHEST_1.instantiate()
|
|
print("SPAWNING CHEST AT : ",chest_loc.name)
|
|
get_tree().current_scene.add_child(instance_chest)
|
|
instance_chest.basis = chest_loc.basis
|
|
instance_chest.global_position = chest_loc.global_position
|
|
instance_chest.global_rotation = chest_loc.global_rotation
|
|
number_chests -= 1
|
|
|
|
|
|
func refresh_scene():
|
|
GameGlobals.health = gamemode.start_health
|
|
|
|
respawn_position = player.camera.global_position
|
|
respawn_cam_rotation = player.global_transform.basis
|
|
|
|
if player:
|
|
#Set up starting guns and ammo
|
|
if gamemode.gun_1 != null:
|
|
GameGlobals.held_guns = [gamemode.gun_1]
|
|
var instance_gun = GameGlobals.held_guns[0].instantiate()
|
|
player.add_ammo(true,instance_gun.gun_name,instance_gun.ammo_type,instance_gun.max_ammo,instance_gun.start_mags)
|
|
|
|
if gamemode.gun_2 != null:
|
|
GameGlobals.held_guns.append(gamemode.gun_2)
|
|
var instance_gun_2 = GameGlobals.held_guns[1].instantiate()
|
|
player.add_ammo(true,instance_gun_2.gun_name,instance_gun_2.ammo_type,instance_gun_2.max_ammo,instance_gun_2.start_mags)
|
|
|
|
# Spawn first gun
|
|
if gamemode.gun_1 != null:
|
|
GameGlobals.current_gun_index = 0
|
|
gun_spawn(0)
|
|
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
func _process(_delta):
|
|
pass
|
|
|
|
|
|
func gun_spawn(index):
|
|
|
|
#loop around if scrolling past available guns
|
|
if index > GameGlobals.held_guns.size() - 1:
|
|
index = 0
|
|
elif index < 0:
|
|
index = GameGlobals.held_guns.size() - 1
|
|
|
|
GameGlobals.current_gun_index = index
|
|
|
|
if GameGlobals.held_guns != []:
|
|
var instance_gun = GameGlobals.held_guns[index].instantiate()
|
|
instance_gun.global_transform.origin = player.weapon_spawner.position
|
|
player.gun = instance_gun
|
|
player.def_weapon_holder_pos = player.weapon_holder.position
|
|
|
|
instance_gun.gun_index = index
|
|
instance_gun.anim_player.play("swap_in")
|
|
player.weapon_holder.add_child(instance_gun)
|
|
|
|
func enemy_count():
|
|
var sum = 0
|
|
var enemies = get_tree().get_nodes_in_group("enemy")
|
|
for i in enemies:
|
|
if i.get_class() == "CharacterBody3D":
|
|
sum += 1
|
|
print("enemies: " + str(sum))
|
|
if sum == 0:
|
|
cleared()
|
|
|
|
func cleared():
|
|
pass
|
|
|
|
func die():
|
|
SignalBus.emit_signal("player_exiting_tree")
|
|
#record stats
|
|
GameGlobals.money_penalty()
|
|
GameGlobals.weapon_penalty()
|
|
if GameGlobals.player_deaths:
|
|
GameGlobals.player_deaths += 1
|
|
SaveLoad.save_user_data()
|
|
var deadmsg = DEAD_ANNOUNCE.instantiate()
|
|
get_parent().add_child(deadmsg)
|
|
var instance_dead = dead_player.instantiate()
|
|
instance_dead.global_position = player.camera.global_position
|
|
instance_dead.transform.basis = player.global_transform.basis
|
|
if last_hit != null:
|
|
instance_dead.target = last_hit
|
|
GameGlobals.last_hit_path = str(last_hit.get_path())
|
|
instance_dead.target_type = target_type
|
|
instance_dead.respawn_position = respawn_position
|
|
instance_dead.respawn_rotation = respawn_cam_rotation
|
|
instance_dead.respawn_fov = player.camera.fov
|
|
get_tree().get_root().add_child(instance_dead)
|
|
instance_dead.camera.current = true
|
|
player.dead = true
|
|
player.toggle_hud(false)
|
|
player.visible = false
|
|
player.health_indicator.color = Color(0.471, 0, 0, 0)
|
|
|
|
|
|
func pickup_spawn(randomized):
|
|
var pickup_type
|
|
var ammo_type
|
|
var value
|
|
if randomized:
|
|
#random item
|
|
pickup_type = randi_range(0,3)
|
|
#if item type is ammo, pick random ammo
|
|
if pickup_type == 0:
|
|
var player_ammo = GameGlobals.ammo_reserve.keys()
|
|
ammo_type = int(player_ammo.pick_random())
|
|
#random value of pickup
|
|
value = randi_range(1,50)
|
|
else:
|
|
var health_weight
|
|
if gamemode.health_drop_enabled:
|
|
health_weight = (1.0 - (GameGlobals.health / gamemode.start_health)) + drop_chance_minimum
|
|
else:
|
|
health_weight = 0
|
|
var stamina_weight
|
|
if stamina_drop_enabled:
|
|
stamina_weight = (1.0 - (player.remaining_stamina / gamemode.max_stamina)) + drop_chance_minimum
|
|
else:
|
|
stamina_weight = 0
|
|
var money_weight
|
|
if money_drop_enabled:
|
|
money_weight = 1 + drop_chance_minimum #fix this logic later once the economy makes sense
|
|
else:
|
|
money_weight = 0
|
|
var ammo_weight
|
|
if gamemode.ammo_drop_enabled:
|
|
ammo_weight = drop_chance_minimum
|
|
else: ammo_weight = 0
|
|
var ammo_type_weight = {}
|
|
|
|
# weight ammo player owns against expected ammo values
|
|
if gamemode.ammo_drop_enabled:
|
|
for i in GameGlobals.ammo_reserve.keys():
|
|
var i_weight
|
|
match int(i):
|
|
0:
|
|
i_weight = 1.0 - clamp(float(GameGlobals.ammo_reserve[str(i)]) / float(gamemode.expected_ammo["light"]),0,1)
|
|
1:
|
|
i_weight = 1.0 - clamp(float(GameGlobals.ammo_reserve[str(i)]) / float(gamemode.expected_ammo["medium"]),0,1)
|
|
2:
|
|
i_weight = 1.0 - clamp(float(GameGlobals.ammo_reserve[str(i)]) / float(gamemode.expected_ammo["heavy"]),0,1)
|
|
3:
|
|
i_weight = 1.0 - clamp(float(GameGlobals.ammo_reserve[str(i)]) / float(gamemode.expected_ammo["shotgun"]),0,1)
|
|
4:
|
|
i_weight = 1.0 - clamp(float(GameGlobals.ammo_reserve[str(i)]) / float(gamemode.expected_ammo["rocket"]),0,1)
|
|
5:
|
|
i_weight = 0
|
|
if i_weight > ammo_weight:
|
|
ammo_weight = i_weight
|
|
ammo_type_weight.erase(5)
|
|
ammo_type_weight[i] = i_weight + drop_chance_minimum
|
|
|
|
pickup_type = HelperFuncs.weighted_random({"0" : ammo_weight, "1" : stamina_weight,"2" : health_weight,"3" : money_weight})
|
|
|
|
match pickup_type:
|
|
"0":
|
|
if ammo_type_weight.size() > 0:
|
|
ammo_type = int(HelperFuncs.weighted_random(ammo_type_weight))
|
|
else:
|
|
ammo_type = randi_range(0,4)
|
|
value = randi_range(1,20)
|
|
"1":
|
|
value = randi_range(int(gamemode.max_stamina * .25),gamemode.max_stamina)
|
|
"2":
|
|
value = randi_range(int(gamemode.start_health * .25),gamemode.start_health)
|
|
"3":
|
|
var bill_denoms = [5,10,20,50,100]
|
|
value = bill_denoms.pick_random()
|
|
|
|
|
|
return {"pickup_type" : pickup_type,"ammo_type" : ammo_type,"value" : value}
|
|
|
|
func save_quit():
|
|
SignalBus.emit_signal("player_exiting_tree")
|
|
SaveLoad.save_game_data(self.get_name())
|
|
SaveLoad.save_user_data()
|
|
SaveLoad.save_persistent_data()
|
|
get_tree().quit()
|