mirror of
https://codeberg.org/ProgramSnail/konkr_game_3d.git
synced 2026-01-01 19:28:16 +00:00
init
This commit is contained in:
commit
5408d75267
2834 changed files with 377523 additions and 0 deletions
19
scripts/Camera.gd
Normal file
19
scripts/Camera.gd
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
extends Camera
|
||||
|
||||
export var speed = 10
|
||||
export var zoom_speed = 0.6
|
||||
|
||||
func _process(delta):
|
||||
if Input.is_action_pressed("camera_forward"):
|
||||
global_translate(Vector3(-delta * speed, 0, 0))
|
||||
if Input.is_action_pressed("camera_backward"):
|
||||
global_translate(Vector3(delta * speed, 0, 0))
|
||||
if Input.is_action_pressed("camera_left"):
|
||||
global_translate(Vector3(0, 0, delta * speed))
|
||||
if Input.is_action_pressed("camera_right"):
|
||||
global_translate(Vector3(0, 0, -delta * speed))
|
||||
if Input.is_action_just_released("zoom_in"):
|
||||
translate(Vector3(0, 0, -zoom_speed))
|
||||
if Input.is_action_just_released("zoom_out"):
|
||||
translate(Vector3(0, 0, zoom_speed))
|
||||
pass
|
||||
39
scripts/Character.gd
Normal file
39
scripts/Character.gd
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
extends Spatial
|
||||
|
||||
onready var animation_player = get_node("CharacterModel/AnimationPlayer")
|
||||
onready var characters = [
|
||||
get_node("CharacterModel/Rogue"),
|
||||
get_node("CharacterModel/Worker"),
|
||||
get_node("CharacterModel/Barbarian"),
|
||||
get_node("CharacterModel/Knight"),
|
||||
get_node("CharacterModel/Mage"),
|
||||
]
|
||||
|
||||
export var ROGUE_LEVEL = 0
|
||||
export var MAX_LEVEL = 4
|
||||
|
||||
var active = false
|
||||
|
||||
# character level, ROGUE_LEVEL for rogue
|
||||
var level = 1
|
||||
|
||||
func set_character_visibility(character_is_visible : bool):
|
||||
characters[level].visible = character_is_visible
|
||||
|
||||
func upgrade():
|
||||
if level >= MAX_LEVEL: # MAX_LEVEL or special levels
|
||||
return false
|
||||
|
||||
set_character_visibility(false)
|
||||
level += 1
|
||||
set_character_visibility(true)
|
||||
|
||||
return true
|
||||
|
||||
func became_rogue():
|
||||
set_character_visibility(false)
|
||||
level = ROGUE_LEVEL
|
||||
set_character_visibility(true)
|
||||
|
||||
func _physics_process(_delta):
|
||||
animation_player.play("Active" if active else "NotActive")
|
||||
182
scripts/Characters.gd
Normal file
182
scripts/Characters.gd
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
extends Spatial
|
||||
|
||||
var character_scene = preload("res://scenes/character.tscn")
|
||||
|
||||
onready var map = get_node("/root/Level/Map")
|
||||
onready var utils = get_node("/root/Level/Map/Utils")
|
||||
|
||||
onready var player_characters : Array = [[get_node("/root/Level/Map/Player0")], [], [], [], []]
|
||||
onready var rogue_characters = []
|
||||
|
||||
var current_player = 0
|
||||
var current_character = 0
|
||||
|
||||
var current_player_used_characters = {}
|
||||
|
||||
func is_current_player_character_used(character : int):
|
||||
return current_player_used_characters.has(character)
|
||||
|
||||
func current_character_obj():
|
||||
return player_characters[current_player][current_character]
|
||||
|
||||
func current_player_characters_count():
|
||||
return player_characters[current_player].size()
|
||||
|
||||
func is_current_character_exist():
|
||||
return current_character < current_player_characters_count()
|
||||
|
||||
func spawn_current_player_character(position : Vector3):
|
||||
player_characters[current_player].append( \
|
||||
utils.spawn_on_position(character_scene, position))
|
||||
|
||||
func destroy_characters_on_position(characters : Array, position : Vector3):
|
||||
var destroyed_count = 0
|
||||
var alive = []
|
||||
|
||||
for character in characters:
|
||||
var character_position = utils.world_to_grid_position(character.translation)
|
||||
if character_position.is_equal_approx(position):
|
||||
destroyed_count += 1
|
||||
character.queue_free()
|
||||
else:
|
||||
alive.append(character)
|
||||
|
||||
return [alive, destroyed_count]
|
||||
|
||||
func destroy_other_player_characters(position : Vector3, skipped_player : int):
|
||||
var characters_destroyed_count = 0
|
||||
|
||||
for player in range(0, player_characters.size()):
|
||||
if player == skipped_player:
|
||||
continue
|
||||
|
||||
var player_destruction_result = \
|
||||
destroy_characters_on_position(player_characters[player], position)
|
||||
|
||||
player_characters[player] = player_destruction_result[0]
|
||||
characters_destroyed_count += player_destruction_result[1]
|
||||
|
||||
var rogue_destruction_result = \
|
||||
destroy_characters_on_position(rogue_characters, position)
|
||||
|
||||
rogue_characters = rogue_destruction_result[0]
|
||||
characters_destroyed_count += rogue_destruction_result[1]
|
||||
|
||||
return characters_destroyed_count
|
||||
|
||||
# not optimal
|
||||
func turn_characters_into_rogues():
|
||||
var new_rogue_characters = 0
|
||||
|
||||
for player in range(0, player_characters.size()):
|
||||
var alive_characters = []
|
||||
for character in player_characters[player]:
|
||||
var character_position = utils.world_to_grid_position(character.translation)
|
||||
if not map.is_connected_to_house(character_position, map.player_tiles[player]):
|
||||
new_rogue_characters += 1
|
||||
character.became_rogue()
|
||||
rogue_characters.append(character)
|
||||
map.set_tile_cell(character_position, map.EMPTY_TILE)
|
||||
else:
|
||||
alive_characters.append(character)
|
||||
|
||||
player_characters[player] = alive_characters
|
||||
|
||||
return new_rogue_characters
|
||||
|
||||
# =< 1 characters on one position
|
||||
func find_character_and_player_ids_on(position : Vector3):
|
||||
for player in range(player_characters.size()):
|
||||
for character in range(player_characters[player].size()):
|
||||
var character_position = \
|
||||
utils.world_to_grid_position(player_characters[player][character].translation)
|
||||
if character_position.is_equal_approx(position):
|
||||
return [player, character]
|
||||
|
||||
return null
|
||||
|
||||
# =< 1 characters on one position
|
||||
func find_character_on(position : Vector3):
|
||||
var character_and_player_ids = find_character_and_player_ids_on(position)
|
||||
|
||||
if character_and_player_ids == null:
|
||||
return null
|
||||
|
||||
return player_characters[character_and_player_ids[0]][character_and_player_ids[1]]
|
||||
|
||||
func set_next_character():
|
||||
if current_character < current_player_characters_count():
|
||||
current_character_obj().active = false
|
||||
|
||||
current_player_used_characters[current_character] = null
|
||||
|
||||
if current_player_used_characters.size() < current_player_characters_count():
|
||||
for i in range(current_player_characters_count()):
|
||||
if not current_player_used_characters.has(i):
|
||||
current_character = i
|
||||
else:
|
||||
if current_character == current_player_characters_count():
|
||||
current_character += 1
|
||||
else:
|
||||
current_character = current_player_characters_count()
|
||||
|
||||
if current_character >= current_player_characters_count() + 1:
|
||||
set_next_player()
|
||||
|
||||
if current_character < current_player_characters_count():
|
||||
current_character_obj().active = true
|
||||
|
||||
func set_next_player():
|
||||
if current_character < current_player_characters_count():
|
||||
current_character_obj().active = false
|
||||
|
||||
map.player_tiles[current_player] = map.DEFAULT_PLAYER_TILES[current_player]
|
||||
print(map.player_tiles[current_player])
|
||||
print(map.DEFAULT_PLAYER_TILES[current_player])
|
||||
map.remove_active_player_color(current_player)
|
||||
|
||||
current_player_used_characters.clear()
|
||||
|
||||
current_player += 1
|
||||
|
||||
if current_player >= map.PLAYERS_COUNT:
|
||||
current_player %= map.PLAYERS_COUNT
|
||||
|
||||
map.set_active_player_color(current_player)
|
||||
map.player_tiles[current_player] = map.ACTIVE_PLAYER_TILES[current_player]
|
||||
|
||||
map.start_player_turn(current_player)
|
||||
|
||||
current_character = 0
|
||||
|
||||
if current_character < current_player_characters_count():
|
||||
current_character_obj().active = true
|
||||
|
||||
func switch_character_to(player : int, character : int):
|
||||
if current_character < current_player_characters_count():
|
||||
current_character_obj().active = false
|
||||
|
||||
current_player = player
|
||||
current_character = character
|
||||
|
||||
if current_character < current_player_characters_count():
|
||||
current_character_obj().active = true
|
||||
|
||||
# not optiomal
|
||||
func characters_tile_block_level(position : Vector3, inviding_player : int):
|
||||
var block_level = -1
|
||||
|
||||
for player in range(0, player_characters.size()):
|
||||
for character in player_characters[player]:
|
||||
var character_position = utils.world_to_grid_position(character.translation)
|
||||
if player != inviding_player and \
|
||||
(map.is_neighbour_tiles(character_position, position) or \
|
||||
character_position.is_equal_approx(position)) and \
|
||||
map.get_tile_cell(position) == map.player_tiles[player]:
|
||||
block_level = max(block_level, character.level)
|
||||
|
||||
if player == inviding_player and \
|
||||
character_position.is_equal_approx(position):
|
||||
block_level = character.MAX_LEVEL
|
||||
|
||||
return block_level
|
||||
12
scripts/Cursor.gd
Normal file
12
scripts/Cursor.gd
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
extends MeshInstance
|
||||
|
||||
onready var camera : Camera = get_node("/root/Level/Camera")
|
||||
|
||||
func _physics_process(_delta):
|
||||
var position_2d = get_viewport().get_mouse_position()
|
||||
var drop_plane = Plane(Vector3(0, 1, 0), 1)
|
||||
var position_3d = drop_plane.intersects_ray(
|
||||
camera.project_ray_origin(position_2d),
|
||||
camera.project_ray_normal(position_2d))
|
||||
|
||||
translation = position_3d
|
||||
8
scripts/Destruction.gd
Normal file
8
scripts/Destruction.gd
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
extends Particles
|
||||
|
||||
func _ready():
|
||||
emitting = true
|
||||
|
||||
func _physics_process(_delta):
|
||||
if not emitting:
|
||||
queue_free()
|
||||
8
scripts/HouseInfo.gd
Normal file
8
scripts/HouseInfo.gd
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
extends Spatial
|
||||
|
||||
onready var info = $Info
|
||||
|
||||
var money = 0
|
||||
|
||||
func _process(_delta):
|
||||
info.text = "Money: " + str(money)
|
||||
206
scripts/Map.gd
Normal file
206
scripts/Map.gd
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
extends Spatial
|
||||
|
||||
# TODO: create something like Vector3i
|
||||
|
||||
var building_destruction_scene = preload("res://scenes/destruction.tscn")
|
||||
|
||||
onready var characters = get_node("/root/Level/Map/Characters")
|
||||
onready var money = get_node("/root/Level/Map/Money")
|
||||
onready var utils = get_node("/root/Level/Map/Utils")
|
||||
onready var tiles : GridMap = get_node("/root/Level/Map/Tiles")
|
||||
onready var buildings : GridMap = get_node("/root/Level/Map/Buildings")
|
||||
|
||||
export var EMPTY_TILE = 0
|
||||
|
||||
export var PLAYERS_COUNT = 2
|
||||
export var DEFAULT_PLAYER_TILES = [1, 2, 3, 4, 5]
|
||||
export var ACTIVE_PLAYER_TILES = [6, 7, 8, 9, 10]
|
||||
|
||||
var player_tiles = []
|
||||
|
||||
export var HOUSE_CELLS = [0, 1, 2, 11, 12, 13, 14, 16, 19] # 14, 19 - mills
|
||||
export var TOWER_CELLS = [2, 18]
|
||||
|
||||
export var HOUSE_DEFENCE_LEVEL = 1
|
||||
export var TOWER_DEFENCE_LEVEL = 2
|
||||
|
||||
const directions = [
|
||||
Vector3(2, 0, 0),
|
||||
Vector3(-2, 0, 0),
|
||||
Vector3(1, 0, 2),
|
||||
Vector3(-1, 0, 2),
|
||||
Vector3(1, 0, -2),
|
||||
Vector3(-1, 0, -2)
|
||||
]
|
||||
|
||||
func get_tile_cell(position : Vector3):
|
||||
return tiles.get_cell_item(int(round(position.x)), int(round(position.y)), int(round(position.z)))
|
||||
|
||||
func set_tile_cell(position : Vector3, cell : int):
|
||||
tiles.set_cell_item(int(round(position.x)), int(round(position.y)), int(round(position.z)), cell)
|
||||
|
||||
func get_building_cell(position : Vector3):
|
||||
return buildings.get_cell_item(int(round(position.x)), int(round(position.y)), int(round(position.z)))
|
||||
|
||||
func set_building_cell(position : Vector3, cell : int):
|
||||
buildings.set_cell_item(int(round(position.x)), int(round(position.y)), int(round(position.z)), cell)
|
||||
|
||||
func has_neighbour_tile_cell(position : Vector3, required_neighbour_tile_cell : int):
|
||||
for direction in directions:
|
||||
var neighbour_position = direction + position
|
||||
if get_tile_cell(neighbour_position) == required_neighbour_tile_cell:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func has_building_defence(position : Vector3, building_cell : int, skipped_player : int):
|
||||
var current_cell = get_tile_cell(position)
|
||||
for direction in directions:
|
||||
var neighbour_position = direction + position
|
||||
var neighbour_cell = get_tile_cell(neighbour_position)
|
||||
|
||||
if current_cell == neighbour_cell and \
|
||||
neighbour_cell != player_tiles[skipped_player] and \
|
||||
get_building_cell(neighbour_position) == building_cell:
|
||||
return true
|
||||
|
||||
return get_building_cell(position) == building_cell and current_cell != player_tiles[skipped_player]
|
||||
|
||||
func is_neighbour_tiles(position : Vector3, other_position : Vector3):
|
||||
for direction in directions:
|
||||
if direction.is_equal_approx(other_position - position):
|
||||
return true
|
||||
return false
|
||||
|
||||
func start_player_turn(player : int):
|
||||
money.update_houses_money(player)
|
||||
money.pay_tower_salaries(player)
|
||||
money.pay_character_salaries(player)
|
||||
|
||||
func are_tiles_connected(start_position : Vector3, end_position : Vector3, between_tile_cell : int):
|
||||
if start_position.is_equal_approx(end_position):
|
||||
return true
|
||||
|
||||
var visited = {}
|
||||
|
||||
var to_visit = [start_position]
|
||||
visited[utils.position_to_string(start_position)] = null
|
||||
|
||||
for current_position in to_visit:
|
||||
for direction in directions:
|
||||
if (current_position + direction).is_equal_approx(end_position):
|
||||
return true
|
||||
if get_tile_cell(current_position + direction) == between_tile_cell and \
|
||||
not visited.has(utils.position_to_string(current_position + direction)):
|
||||
visited[utils.position_to_string(current_position + direction)] = null
|
||||
to_visit.append(current_position + direction)
|
||||
|
||||
return false
|
||||
|
||||
func is_connected_to_house(start_position : Vector3, tile_cell : int):
|
||||
var visited = {}
|
||||
|
||||
var to_visit = [start_position]
|
||||
visited[utils.position_to_string(start_position)] = null
|
||||
|
||||
for current_position in to_visit:
|
||||
if HOUSE_CELLS.has(get_building_cell(current_position)):
|
||||
return true
|
||||
|
||||
for direction in directions:
|
||||
if get_tile_cell(current_position + direction) == tile_cell and \
|
||||
not visited.has(utils.position_to_string(current_position + direction)):
|
||||
visited[utils.position_to_string(current_position + direction)] = null
|
||||
to_visit.append(current_position + direction)
|
||||
|
||||
return false
|
||||
|
||||
func tile_block_level(position : Vector3, inviding_player : int):
|
||||
var block_level = -1
|
||||
|
||||
block_level = characters.characters_tile_block_level(position, inviding_player)
|
||||
|
||||
for house_cell in HOUSE_CELLS:
|
||||
if has_building_defence(position, house_cell, inviding_player):
|
||||
block_level = max(block_level, HOUSE_DEFENCE_LEVEL)
|
||||
break
|
||||
|
||||
for tower_cell in TOWER_CELLS:
|
||||
if has_building_defence(position, tower_cell, inviding_player):
|
||||
block_level = max(block_level, TOWER_DEFENCE_LEVEL)
|
||||
|
||||
return block_level
|
||||
|
||||
func move_to_tile(position : Vector3):
|
||||
var tile_cell = get_tile_cell(position)
|
||||
var building_cell = get_building_cell(position)
|
||||
var world_position = utils.grid_to_world_position(position)
|
||||
|
||||
# tile to move should be connected with current character tile
|
||||
if not are_tiles_connected(utils.world_to_grid_position(characters.current_character_obj().translation), position, current_player_tile()):
|
||||
return
|
||||
|
||||
# can't go on tile, blocked with >= level, except characters with MAX_LEVEL
|
||||
if tile_block_level(position, characters.current_player) >= characters.current_character_obj().level and \
|
||||
characters.current_character_obj().level != characters.current_character_obj().MAX_LEVEL:
|
||||
return
|
||||
|
||||
if tile_cell == GridMap.INVALID_CELL_ITEM:
|
||||
return
|
||||
|
||||
# move without action (to current player tile)
|
||||
if tile_cell == current_player_tile() and \
|
||||
building_cell == GridMap.INVALID_CELL_ITEM:
|
||||
|
||||
if characters.destroy_other_player_characters(position, characters.current_player) > 0:
|
||||
utils.spawn_on_position(building_destruction_scene, position)
|
||||
|
||||
characters.current_character_obj().translation = world_position
|
||||
|
||||
# move with action (to tile of other player)
|
||||
elif tile_cell != GridMap.INVALID_CELL_ITEM and \
|
||||
tile_cell != current_player_tile() and \
|
||||
has_neighbour_tile_cell(position, current_player_tile()):
|
||||
|
||||
set_tile_cell(position, current_player_tile())
|
||||
|
||||
if building_cell != GridMap.INVALID_CELL_ITEM or \
|
||||
characters.destroy_other_player_characters(position, characters.current_player) > 0:
|
||||
utils.spawn_on_position(building_destruction_scene, position)
|
||||
|
||||
if building_cell != GridMap.INVALID_CELL_ITEM:
|
||||
money.destroy_house(position)
|
||||
|
||||
set_building_cell(position, GridMap.INVALID_CELL_ITEM)
|
||||
|
||||
characters.current_character_obj().translation = world_position
|
||||
|
||||
characters.turn_characters_into_rogues()
|
||||
|
||||
characters.set_next_character()
|
||||
|
||||
func current_player_tile():
|
||||
return player_tiles[characters.current_player]
|
||||
|
||||
func remove_active_player_color(player : int):
|
||||
print("Player tile: ", player_tiles[player])
|
||||
for tile_position in tiles.get_used_cells():
|
||||
if get_tile_cell(tile_position) == ACTIVE_PLAYER_TILES[player]:
|
||||
print("Active tile removed")
|
||||
set_tile_cell(tile_position, DEFAULT_PLAYER_TILES[player])
|
||||
|
||||
func set_active_player_color(player : int):
|
||||
for tile_position in tiles.get_used_cells():
|
||||
if get_tile_cell(tile_position) == DEFAULT_PLAYER_TILES[player]:
|
||||
set_tile_cell(tile_position, ACTIVE_PLAYER_TILES[player])
|
||||
|
||||
func _ready():
|
||||
if characters.is_current_character_exist():
|
||||
characters.current_character_obj().active = true
|
||||
|
||||
player_tiles = DEFAULT_PLAYER_TILES.duplicate()
|
||||
|
||||
set_active_player_color(characters.current_player)
|
||||
player_tiles[characters.current_player] = ACTIVE_PLAYER_TILES[characters.current_player]
|
||||
|
||||
money.init_houses()
|
||||
134
scripts/Money.gd
Normal file
134
scripts/Money.gd
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
extends Spatial
|
||||
|
||||
var house_info_scene = preload("res://scenes/house_info.tscn")
|
||||
|
||||
onready var map = get_node("/root/Level/Map")
|
||||
onready var characters = get_node("/root/Level/Map/Characters")
|
||||
onready var utils = get_node("/root/Level/Map/Utils")
|
||||
onready var buildings = get_node("/root/Level/Map/Buildings")
|
||||
|
||||
export var CHARACTER_COST = 10
|
||||
|
||||
# first is rogue, last upgrade is impossible
|
||||
export var CHARACTER_UPGRADE_COSTS = [0, 10, 20, 40, 80]
|
||||
export var CHARACTER_SALARIES = [0, 2, 6, 18, 54]
|
||||
|
||||
export var TOWER_SALARY = 2
|
||||
|
||||
export var HOUSE_STARTING_MONEY = 10
|
||||
export var TILE_MONEY = 1
|
||||
var houses_money = {}
|
||||
var houses_info = {}
|
||||
|
||||
func pay_tower_salaries(player : int):
|
||||
for tower_position in buildings.get_used_cells():
|
||||
if map.TOWER_CELLS.has(map.get_building_cell(tower_position)) and \
|
||||
map.get_tile_cell(tower_position) == map.player_tiles[player]:
|
||||
spend_connected_money(tower_position, map.player_tiles[player], TOWER_SALARY)
|
||||
|
||||
func pay_character_salaries(player : int):
|
||||
var alive_characters = []
|
||||
|
||||
for character in characters.player_characters[player]:
|
||||
var character_position = utils.world_to_grid_position(character.translation)
|
||||
if spend_connected_money(character_position, map.player_tiles[player], CHARACTER_SALARIES[character.level]):
|
||||
alive_characters.append(character)
|
||||
else:
|
||||
character.became_rogue()
|
||||
characters.rogue_characters.append(character)
|
||||
|
||||
characters.player_characters[player] = alive_characters
|
||||
|
||||
func count_connected_money(starting_position : Vector3, tile_cell : int):
|
||||
var connected_money = 0
|
||||
|
||||
var visited = {}
|
||||
|
||||
var to_visit = [starting_position]
|
||||
visited[utils.position_to_string(starting_position)] = null
|
||||
|
||||
for current_position in to_visit:
|
||||
if map.HOUSE_CELLS.has(map.get_building_cell(current_position)):
|
||||
connected_money += houses_money[utils.position_to_string(current_position)]
|
||||
|
||||
for direction in map.directions:
|
||||
if map.get_tile_cell(current_position + direction) == tile_cell and \
|
||||
not visited.has(utils.position_to_string(current_position + direction)):
|
||||
visited[utils.position_to_string(current_position + direction)] = null
|
||||
to_visit.append(current_position + direction)
|
||||
|
||||
return connected_money
|
||||
|
||||
func spend_connected_money(starting_position : Vector3, tile_cell : int, money_to_spend : int):
|
||||
if money_to_spend <= 0:
|
||||
return true
|
||||
|
||||
var visited = {}
|
||||
|
||||
var to_visit = [starting_position]
|
||||
visited[utils.position_to_string(starting_position)] = null
|
||||
|
||||
for current_position in to_visit:
|
||||
if map.HOUSE_CELLS.has(map.get_building_cell(current_position)):
|
||||
var money_in_house = houses_money[utils.position_to_string(current_position)]
|
||||
houses_money[utils.position_to_string(current_position)] = max(0, money_in_house - money_to_spend)
|
||||
update_house_info(current_position)
|
||||
|
||||
money_to_spend -= money_in_house
|
||||
if money_to_spend <= 0:
|
||||
return true
|
||||
|
||||
for direction in map.directions:
|
||||
if map.get_tile_cell(current_position + direction) == tile_cell and \
|
||||
not visited.has(utils.position_to_string(current_position + direction)):
|
||||
visited[utils.position_to_string(current_position + direction)] = null
|
||||
to_visit.append(current_position + direction)
|
||||
|
||||
return money_to_spend <= 0
|
||||
|
||||
func update_house_info(position : Vector3):
|
||||
var position_string = utils.position_to_string(position)
|
||||
|
||||
houses_info[position_string].money = houses_money[position_string]
|
||||
|
||||
func update_houses_money(player : int):
|
||||
var rogue_positions = {}
|
||||
for rogue in characters.rogue_characters:
|
||||
rogue_positions[utils.position_to_string(utils.world_to_grid_position(rogue.translation))] = null
|
||||
|
||||
var visited = {}
|
||||
|
||||
var to_visit = []
|
||||
|
||||
for building_position in buildings.get_used_cells():
|
||||
if map.HOUSE_CELLS.has(map.get_building_cell(building_position)) and \
|
||||
map.get_tile_cell(building_position) == map.player_tiles[player]:
|
||||
visited[utils.position_to_string(building_position)] = null
|
||||
to_visit.append([building_position, building_position])
|
||||
|
||||
for current in to_visit:
|
||||
if not rogue_positions.has(utils.position_to_string(current[0])):
|
||||
houses_money[utils.position_to_string(current[1])] += TILE_MONEY
|
||||
update_house_info(current[1])
|
||||
|
||||
for direction in map.directions:
|
||||
if map.get_tile_cell(current[0] + direction) == map.player_tiles[player] and \
|
||||
not visited.has(utils.position_to_string(current[0] + direction)):
|
||||
visited[utils.position_to_string(current[0] + direction)] = null
|
||||
to_visit.append([current[0] + direction, current[1]])
|
||||
|
||||
func destroy_house(position : Vector3):
|
||||
var position_string = utils.position_to_string(position)
|
||||
|
||||
houses_money.erase(position_string)
|
||||
|
||||
houses_info[position_string].queue_free()
|
||||
houses_info.erase(position_string)
|
||||
|
||||
func init_houses():
|
||||
for building_position in buildings.get_used_cells():
|
||||
if map.HOUSE_CELLS.has(map.get_building_cell(building_position)):
|
||||
var building_position_string = utils.position_to_string(building_position)
|
||||
houses_money[building_position_string] = HOUSE_STARTING_MONEY
|
||||
houses_info[building_position_string] = utils.spawn_on_position(house_info_scene, building_position)
|
||||
update_house_info(building_position)
|
||||
54
scripts/PlayerActions.gd
Normal file
54
scripts/PlayerActions.gd
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
extends Spatial
|
||||
|
||||
onready var map = get_node("/root/Level/Map")
|
||||
onready var characters = get_node("/root/Level/Map/Characters")
|
||||
onready var money = get_node("/root/Level/Map/Money")
|
||||
onready var utils = get_node("/root/Level/Map/Utils")
|
||||
|
||||
func make_turn(position : Vector3):
|
||||
if map.is_connected_to_house(position, map.current_player_tile()):
|
||||
var mouse_position_character_and_player_ids = characters.find_character_and_player_ids_on(position)
|
||||
if map.get_tile_cell(position) == map.current_player_tile() and \
|
||||
mouse_position_character_and_player_ids != null and \
|
||||
mouse_position_character_and_player_ids[0] == characters.current_player and \
|
||||
not characters.is_current_player_character_used(mouse_position_character_and_player_ids[1]):
|
||||
characters.switch_character_to(mouse_position_character_and_player_ids[0],
|
||||
mouse_position_character_and_player_ids[1])
|
||||
elif characters.is_current_character_exist():
|
||||
map.move_to_tile(position)
|
||||
|
||||
func upgrade_character_on_position(position : Vector3):
|
||||
var character_on_position = characters.find_character_on(position)
|
||||
if character_on_position != null and \
|
||||
map.get_tile_cell(position) == map.current_player_tile() and \
|
||||
money.count_connected_money(position, map.current_player_tile()) \
|
||||
>= money.CHARACTER_UPGRADE_COSTS[character_on_position.level] and \
|
||||
character_on_position.upgrade():
|
||||
money.spend_connected_money(position, map.current_player_tile(), money.CHARACTER_COST)
|
||||
|
||||
func try_spawn_character(position : Vector3):
|
||||
if map.get_tile_cell(position) == map.current_player_tile() and \
|
||||
map.get_building_cell(position) == GridMap.INVALID_CELL_ITEM and \
|
||||
map.is_connected_to_house(position, map.current_player_tile()) and \
|
||||
characters.find_character_and_player_ids_on(position) == null and \
|
||||
money.count_connected_money(position, map.current_player_tile()) >= money.CHARACTER_COST:
|
||||
|
||||
money.spend_connected_money(position, map.current_player_tile(), money.CHARACTER_COST)
|
||||
|
||||
characters.spawn_current_player_character(position)
|
||||
|
||||
if characters.current_character + 1 == characters.current_player_characters_count():
|
||||
characters.current_character_obj().active = true
|
||||
|
||||
func _physics_process(_delta):
|
||||
if Input.is_action_just_released("turn"):
|
||||
make_turn(utils.world_to_grid_position(utils.mouse_position()))
|
||||
|
||||
if Input.is_action_just_released("upgrade"):
|
||||
upgrade_character_on_position(utils.world_to_grid_position(utils.mouse_position()))
|
||||
|
||||
if Input.is_action_just_released("pass"):
|
||||
characters.set_next_player()
|
||||
|
||||
if Input.is_action_just_released("spawn"):
|
||||
try_spawn_character(utils.world_to_grid_position(utils.mouse_position()))
|
||||
44
scripts/Utils.gd
Normal file
44
scripts/Utils.gd
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
extends Spatial
|
||||
|
||||
onready var tiles : GridMap = get_node("/root/Level/Map/Tiles")
|
||||
|
||||
onready var camera : Camera = get_node("/root/Level/Camera")
|
||||
|
||||
func mouse_position():
|
||||
var position_2d = get_viewport().get_mouse_position()
|
||||
var drop_plane = Plane(Vector3(0, 1, 0), 1)
|
||||
var position_3d = drop_plane.intersects_ray(
|
||||
camera.project_ray_origin(position_2d),
|
||||
camera.project_ray_normal(position_2d))
|
||||
|
||||
return position_3d
|
||||
|
||||
func position_to_string(position : Vector3):
|
||||
return str([int(round(position.x)), int(round(position.y)), int(round(position.z))])
|
||||
|
||||
export var TILE_OFFSET : Vector3 = Vector3(0.5, 0, 0.5)
|
||||
|
||||
func world_to_grid_position(position : Vector3):
|
||||
position += Vector3(TILE_OFFSET.x * tiles.cell_size.x,
|
||||
TILE_OFFSET.y * tiles.cell_size.y,
|
||||
TILE_OFFSET.z * tiles.cell_size.z)
|
||||
|
||||
var diagonal_steps_amount = position.z / (2 * tiles.cell_size.z)
|
||||
var forward_steps_amount = (position.x - diagonal_steps_amount * tiles.cell_size.x) \
|
||||
/ (2 * tiles.cell_size.x)
|
||||
|
||||
var hex_ceil_z = int(round(diagonal_steps_amount))
|
||||
var hex_ceil_x = int(round(forward_steps_amount + hex_ceil_z / 2))
|
||||
|
||||
var row_is_moved = (int(abs(hex_ceil_z)) % 2 == 1)
|
||||
|
||||
return Vector3(int(hex_ceil_x * 2 + (sign(hex_ceil_z) if row_is_moved else 0.0) - 1), 0, int(hex_ceil_z * 2 - 1))
|
||||
|
||||
func grid_to_world_position(position : Vector3):
|
||||
return tiles.map_to_world(int(round(position.x)), int(round(position.y)), int(round(position.z)))
|
||||
|
||||
func spawn_on_position(scene, world_position : Vector3):
|
||||
var instance = scene.instance()
|
||||
add_child(instance)
|
||||
instance.translation = grid_to_world_position(world_position)
|
||||
return instance
|
||||
Loading…
Add table
Add a link
Reference in a new issue