From 70f3ae38c68ce062e3862e09e7f419820f53b735 Mon Sep 17 00:00:00 2001 From: AleaJactaEst Date: Thu, 21 Jan 2021 22:03:44 +0100 Subject: [PATCH] correct some issue --- addons/kh_slider/kh_h_slider.gd | 50 +- addons/kh_slider/kh_h_slider_plugin.gd | 4 +- addons/kh_window/kh_window.gd | 786 +++++++++--------- assets/fonts/IMMORTAL.ttf | Bin 0 -> 170508 bytes icon.png | Bin 3305 -> 63092 bytes project.godot | 2 +- ressources/scripts/creatures.gd | 85 ++ ressources/scripts/creatures/creature_old.gd | 4 +- ressources/scripts/creatures_old.gd | 85 -- ressources/scripts/global.gd | 18 +- ressources/scripts/nel/nel_login_message.gd | 52 +- ressources/scripts/nel/nel_server_infos.gd | 34 +- ressources/scripts/resource_queue.gd | 192 ++--- scenes/characters/character.gd | 438 +++++----- scenes/connection/connection.gd | 44 +- scenes/creatures/creature.gd | 740 ++++++++--------- scenes/creatures/ra/ra_model.gd | 30 +- scenes/game/game.gd | 62 +- scenes/game/sky.gd | 68 +- .../creatures_editor/creatures_editor_ui.gd | 122 +-- .../interfaces/creatures_menu/creature_box.gd | 4 +- .../creatures_menu/creatures_menu_ui.gd | 74 +- scenes/interfaces/focus_reticle.gd | 4 +- scenes/interfaces/game_menu/game_ui.gd | 54 +- .../inventory_window/inventory_box.gd | 36 +- scenes/interfaces/main_menu/main_menu.gd | 6 +- .../interfaces/music_manager/music_button.gd | 2 +- .../interfaces/music_manager/music_manager.gd | 62 +- scenes/interfaces/windows/window.gd | 14 +- scenes/items/pickup_item.gd | 115 +-- scenes/main/main.gd | 170 ++-- scenes/player/player.gd | 296 +++---- scenes/player_old/player.gd | 158 ++-- 33 files changed, 1913 insertions(+), 1898 deletions(-) create mode 100644 assets/fonts/IMMORTAL.ttf create mode 100644 ressources/scripts/creatures.gd delete mode 100644 ressources/scripts/creatures_old.gd diff --git a/addons/kh_slider/kh_h_slider.gd b/addons/kh_slider/kh_h_slider.gd index 4522186..567f813 100644 --- a/addons/kh_slider/kh_h_slider.gd +++ b/addons/kh_slider/kh_h_slider.gd @@ -6,40 +6,40 @@ signal value_changed( value ) export( Texture ) var minus_texture setget set_minus_texture, get_minus_texture func set_minus_texture( value ): - minus_texture = value - if self.has_node( "kh_h_slider/minus" ): - $kh_h_slider/minus.texture_normal = minus_texture + minus_texture = value + if self.has_node( "kh_h_slider/minus" ): + $kh_h_slider/minus.texture_normal = minus_texture func get_minus_texture(): - return minus_texture - + return minus_texture + export( Texture ) var plus_texture setget set_plus_texture, get_plus_texture func set_plus_texture( value ): - plus_texture = value - if self.has_node( "kh_h_slider/plus" ): - $kh_h_slider/plus.texture_normal = plus_texture + plus_texture = value + if self.has_node( "kh_h_slider/plus" ): + $kh_h_slider/plus.texture_normal = plus_texture func get_plus_texture(): - return plus_texture + return plus_texture func _ready(): - self.add_child( preload( "res://addons/kh_slider/kh_h_slider.tscn" ).instance() ) - - $kh_h_slider/minus.connect( "pressed", self, "_on_minus_pressed" ) - $kh_h_slider/value.connect( "changed", self, "_on_value_changed" ) - $kh_h_slider/value.connect( "value_changed", self, "_on_value_value_changed" ) - $kh_h_slider/plus.connect( "pressed", self, "_on_plus_pressed" ) - $kh_h_slider/minus.texture_normal = minus_texture - $kh_h_slider/plus.texture_normal = plus_texture - + self.add_child( preload( "res://addons/kh_slider/kh_h_slider.tscn" ).instance() ) + + $kh_h_slider/minus.connect( "pressed", self, "_on_minus_pressed" ) + $kh_h_slider/value.connect( "changed", self, "_on_value_changed" ) + $kh_h_slider/value.connect( "value_changed", self, "_on_value_value_changed" ) + $kh_h_slider/plus.connect( "pressed", self, "_on_plus_pressed" ) + $kh_h_slider/minus.texture_normal = minus_texture + $kh_h_slider/plus.texture_normal = plus_texture + func _on_minus_pressed(): - $kh_h_slider/value.value -= $kh_h_slider/value.step - + $kh_h_slider/value.value -= $kh_h_slider/value.step + func _on_plus_pressed(): - $kh_h_slider/value.value += $kh_h_slider/value.step - + $kh_h_slider/value.value += $kh_h_slider/value.step + func _on_value_changed(): - emit_signal( "changed" ) - + emit_signal( "changed" ) + func _on_value_value_changed( value ): - emit_signal( "value_changed", value ) + emit_signal( "value_changed", value ) diff --git a/addons/kh_slider/kh_h_slider_plugin.gd b/addons/kh_slider/kh_h_slider_plugin.gd index 5274fe4..892a7f8 100644 --- a/addons/kh_slider/kh_h_slider_plugin.gd +++ b/addons/kh_slider/kh_h_slider_plugin.gd @@ -2,7 +2,7 @@ tool extends EditorPlugin func _enter_tree(): - add_custom_type("KhHSlider", "HBoxContainer", preload("kh_h_slider.gd"), preload("kh_h_slider.png")) + add_custom_type("KhHSlider", "HBoxContainer", preload("kh_h_slider.gd"), preload("kh_h_slider.png")) func _exit_tree(): - remove_custom_type("KhHSlider") + remove_custom_type("KhHSlider") diff --git a/addons/kh_window/kh_window.gd b/addons/kh_window/kh_window.gd index fa29489..8ada34c 100644 --- a/addons/kh_window/kh_window.gd +++ b/addons/kh_window/kh_window.gd @@ -31,63 +31,63 @@ var size_changed = true func add_child_to_content( node): - if self.get_content(): - self.get_content().add_child(node) + if self.get_content(): + self.get_content().add_child(node) func add_window_part( node ): - add_child( node ) + add_child( node ) func set_mouse_pass_to_children( node ): - for child in node.get_children(): - set_mouse_pass_to_children( child ) - if node is Control: - node.mouse_filter = MOUSE_FILTER_PASS + for child in node.get_children(): + set_mouse_pass_to_children( child ) + if node is Control: + node.mouse_filter = MOUSE_FILTER_PASS #func _ready(): func _enter_tree(): - ######## - #### Window's part création. - # The internal elements structure is: - # self - MarginContainer - # background - NinePatchRect - # parts - VBoxContainer - # header_box - MarginContainer - # header - HBoxContainer - # quit - TextureButton - # close - TextureButton - # open - TextureButton - # label - Label - # content_box - MarginContainer - # scroll_container - Scrollcontainer - # content - VBoxContainer - # footer_box - MarginContainer - # footer - HBoxContainer - # contextual_help - Label - # resize - TextureButton + ######## + #### Window's part création. + # The internal elements structure is: + # self - MarginContainer + # background - NinePatchRect + # parts - VBoxContainer + # header_box - MarginContainer + # header - HBoxContainer + # quit - TextureButton + # close - TextureButton + # open - TextureButton + # label - Label + # content_box - MarginContainer + # scroll_container - Scrollcontainer + # content - VBoxContainer + # footer_box - MarginContainer + # footer - HBoxContainer + # contextual_help - Label + # resize - TextureButton - ### - # self - self.size_flags_horizontal = SIZE_EXPAND - self.size_flags_vertical = SIZE_EXPAND + ### + # self + self.size_flags_horizontal = SIZE_EXPAND + self.size_flags_vertical = SIZE_EXPAND - self.set( "custom_constants/margin_right", 0) - self.set( "custom_constants/margin_top", 0) - self.set( "custom_constants/margin_left", 0) - self.set( "custom_constants/margin_bottom", 0) + self.set( "custom_constants/margin_right", 0) + self.set( "custom_constants/margin_top", 0) + self.set( "custom_constants/margin_left", 0) + self.set( "custom_constants/margin_bottom", 0) - self.connect ( "gui_input", self, "_on_window_gui_input" ) - if is_movable and not self.is_dragged_by_header_only: - self.mouse_default_cursor_shape = CURSOR_MOVE - ### - ### - # background - var background - if not self.has_node( "background" ): - background = NinePatchRect.new() - background.name = "background" - if not background_texture: + self.connect ( "gui_input", self, "_on_window_gui_input" ) + if is_movable and not self.is_dragged_by_header_only: + self.mouse_default_cursor_shape = CURSOR_MOVE + ### + ### + # background + var background + if not self.has_node( "background" ): + background = NinePatchRect.new() + background.name = "background" + if not background_texture: # var background_image = Image.new() # var stream_texture = load('res://addons/ui_window/background_default.jpg') # if not stream_texture : @@ -97,435 +97,435 @@ func _enter_tree(): # background.texture = ImageTexture.new() # background.texture.create_from_image( background_image ) # background.texture.flags = Texture.FLAG_FILTER | Texture.FLAG_REPEAT - pass - else: - background.texture = background_texture - background.texture.flags = Texture.FLAG_FILTER | Texture.FLAG_REPEAT - - background.axis_stretch_horizontal = NinePatchRect.AXIS_STRETCH_MODE_TILE - background.axis_stretch_vertical = NinePatchRect.AXIS_STRETCH_MODE_TILE + pass + else: + background.texture = background_texture + background.texture.flags = Texture.FLAG_FILTER | Texture.FLAG_REPEAT + + background.axis_stretch_horizontal = NinePatchRect.AXIS_STRETCH_MODE_TILE + background.axis_stretch_vertical = NinePatchRect.AXIS_STRETCH_MODE_TILE - background.size_flags_horizontal = SIZE_EXPAND_FILL - background.size_flags_vertical = SIZE_EXPAND_FILL + background.size_flags_horizontal = SIZE_EXPAND_FILL + background.size_flags_vertical = SIZE_EXPAND_FILL - background.region_rect = Rect2( 0, 0, 0, 0 ) - background.patch_margin_left = 4 - background.patch_margin_top = 32 - background.patch_margin_right = 4 - background.patch_margin_bottom = 4 + background.region_rect = Rect2( 0, 0, 0, 0 ) + background.patch_margin_left = 4 + background.patch_margin_top = 32 + background.patch_margin_right = 4 + background.patch_margin_bottom = 4 - background.self_modulate = background_color - self.add_window_part( background ) + background.self_modulate = background_color + self.add_window_part( background ) # background.set_owner( self ) - ### - ### - # parts - var parts - if not self.has_node( "parts" ): - parts = VBoxContainer.new() - parts.name = "parts" - parts.size_flags_horizontal = SIZE_EXPAND_FILL - parts.size_flags_vertical = SIZE_EXPAND_FILL - self.add_window_part( parts ) + ### + ### + # parts + var parts + if not self.has_node( "parts" ): + parts = VBoxContainer.new() + parts.name = "parts" + parts.size_flags_horizontal = SIZE_EXPAND_FILL + parts.size_flags_vertical = SIZE_EXPAND_FILL + self.add_window_part( parts ) # parts.set_owner( self ) - ### - ### - # header_box - var header_box - if not parts.has_node( "header_box" ): - header_box = MarginContainer.new() - header_box.name = "header_box" - header_box.size_flags_horizontal = SIZE_EXPAND_FILL - header_box.size_flags_vertical = SIZE_SHRINK_CENTER + ### + ### + # header_box + var header_box + if not parts.has_node( "header_box" ): + header_box = MarginContainer.new() + header_box.name = "header_box" + header_box.size_flags_horizontal = SIZE_EXPAND_FILL + header_box.size_flags_vertical = SIZE_SHRINK_CENTER - header_box.set( "custom_constants/margin_right", 4) - header_box.set( "custom_constants/margin_top", 4) - header_box.set( "custom_constants/margin_left", 4) - header_box.set( "custom_constants/margin_bottom", 4) + header_box.set( "custom_constants/margin_right", 4) + header_box.set( "custom_constants/margin_top", 4) + header_box.set( "custom_constants/margin_left", 4) + header_box.set( "custom_constants/margin_bottom", 4) - if is_movable: - header_box.mouse_default_cursor_shape = CURSOR_MOVE - parts.add_child( header_box ) + if is_movable: + header_box.mouse_default_cursor_shape = CURSOR_MOVE + parts.add_child( header_box ) # header_box.set_owner( parts ) - header_box.connect ( "gui_input", self, "_on_Header_gui_input" ) - ### - ### - # header - var header - if not header_box.has_node( "header" ): - header = HBoxContainer.new() - header.name = "header" - header.size_flags_horizontal = SIZE_EXPAND_FILL - header.size_flags_vertical = SIZE_EXPAND | SIZE_SHRINK_CENTER - if is_movable: - header.mouse_default_cursor_shape = CURSOR_MOVE - header_box.add_child( header ) + header_box.connect ( "gui_input", self, "_on_Header_gui_input" ) + ### + ### + # header + var header + if not header_box.has_node( "header" ): + header = HBoxContainer.new() + header.name = "header" + header.size_flags_horizontal = SIZE_EXPAND_FILL + header.size_flags_vertical = SIZE_EXPAND | SIZE_SHRINK_CENTER + if is_movable: + header.mouse_default_cursor_shape = CURSOR_MOVE + header_box.add_child( header ) # header.set_owner( header_box ) - ### - ### - # quit - var quit_button - if not header.has_node( "quit" ): - quit_button = TextureButton.new() - quit_button.name = "quit" - quit_button.size_flags_horizontal = SIZE_SHRINK_END - quit_button.size_flags_vertical = SIZE_SHRINK_CENTER + ### + ### + # quit + var quit_button + if not header.has_node( "quit" ): + quit_button = TextureButton.new() + quit_button.name = "quit" + quit_button.size_flags_horizontal = SIZE_SHRINK_END + quit_button.size_flags_vertical = SIZE_SHRINK_CENTER - var tex_quit = ImageTexture.new() - var img_quit = Image.new() - var stream_texture = load( "res://addons/kh_window/button_quit.png") - img_quit = stream_texture.get_data() - tex_quit.create_from_image( img_quit ) - quit_button.texture_normal = tex_quit + var tex_quit = ImageTexture.new() + var img_quit = Image.new() + var stream_texture = load( "res://addons/kh_window/button_quit.png") + img_quit = stream_texture.get_data() + tex_quit.create_from_image( img_quit ) + quit_button.texture_normal = tex_quit - header.add_child( quit_button ) + header.add_child( quit_button ) # quit_button.set_owner( header ) - quit_button.connect ( "pressed", self, "_on_Quit_pressed" ) - ### - # close - var close_button = TextureButton.new() - if not header.has_node( "close" ): - close_button = TextureButton.new() - close_button.name = "close" - close_button.size_flags_horizontal = SIZE_SHRINK_END - close_button.size_flags_vertical = SIZE_SHRINK_CENTER + quit_button.connect ( "pressed", self, "_on_Quit_pressed" ) + ### + # close + var close_button = TextureButton.new() + if not header.has_node( "close" ): + close_button = TextureButton.new() + close_button.name = "close" + close_button.size_flags_horizontal = SIZE_SHRINK_END + close_button.size_flags_vertical = SIZE_SHRINK_CENTER - var tex_close = ImageTexture.new() - var img_close = Image.new() - var stream_texture = load("res://addons/kh_window/button_close.png") - img_close = stream_texture.get_data() - tex_close.create_from_image( img_close ) - close_button.texture_normal = tex_close + var tex_close = ImageTexture.new() + var img_close = Image.new() + var stream_texture = load("res://addons/kh_window/button_close.png") + img_close = stream_texture.get_data() + tex_close.create_from_image( img_close ) + close_button.texture_normal = tex_close - header.add_child( close_button ) + header.add_child( close_button ) # close_button.set_owner( header ) - close_button.connect ( "pressed", self, "_on_Close_pressed" ) - ### - # open - var open_button - if not header.has_node( "open" ): - open_button = TextureButton.new() - open_button.name = "open" - open_button.size_flags_horizontal = SIZE_SHRINK_END - open_button.size_flags_vertical = SIZE_SHRINK_CENTER + close_button.connect ( "pressed", self, "_on_Close_pressed" ) + ### + # open + var open_button + if not header.has_node( "open" ): + open_button = TextureButton.new() + open_button.name = "open" + open_button.size_flags_horizontal = SIZE_SHRINK_END + open_button.size_flags_vertical = SIZE_SHRINK_CENTER - var tex_open = ImageTexture.new() - var img_open = Image.new() - var stream_texture = load("res://addons/kh_window/button_open.png") - img_open = stream_texture.get_data() - tex_open.create_from_image( img_open ) - open_button.texture_normal = tex_open - open_button.visible = false - header.add_child( open_button ) + var tex_open = ImageTexture.new() + var img_open = Image.new() + var stream_texture = load("res://addons/kh_window/button_open.png") + img_open = stream_texture.get_data() + tex_open.create_from_image( img_open ) + open_button.texture_normal = tex_open + open_button.visible = false + header.add_child( open_button ) # open_button.set_owner( header ) - open_button.connect ( "pressed", self, "_on_Open_pressed" ) - ### - ### - # Title Label - var title_label - if not header.has_node( "label" ): - title_label = Label.new() - title_label.name = "label" - title_label.text = title - title_label.size_flags_horizontal = SIZE_EXPAND_FILL - title_label.size_flags_vertical = SIZE_SHRINK_CENTER - if is_movable: - title_label.mouse_default_cursor_shape = CURSOR_MOVE - header.add_child( title_label ) + open_button.connect ( "pressed", self, "_on_Open_pressed" ) + ### + ### + # Title Label + var title_label + if not header.has_node( "label" ): + title_label = Label.new() + title_label.name = "label" + title_label.text = title + title_label.size_flags_horizontal = SIZE_EXPAND_FILL + title_label.size_flags_vertical = SIZE_SHRINK_CENTER + if is_movable: + title_label.mouse_default_cursor_shape = CURSOR_MOVE + header.add_child( title_label ) # title_label.set_owner( header ) - ### - ### - # Content - var content_box - if not parts.has_node( "content_box" ): - content_box = MarginContainer.new() - content_box.name = "content_box" - content_box.size_flags_horizontal = SIZE_EXPAND_FILL - content_box.size_flags_vertical = SIZE_EXPAND_FILL - content_box.set( "custom_constants/margin_right", 8) - content_box.set( "custom_constants/margin_top", 8) - content_box.set( "custom_constants/margin_left", 8) - content_box.set( "custom_constants/margin_bottom", 8) - parts.add_child( content_box ) + ### + ### + # Content + var content_box + if not parts.has_node( "content_box" ): + content_box = MarginContainer.new() + content_box.name = "content_box" + content_box.size_flags_horizontal = SIZE_EXPAND_FILL + content_box.size_flags_vertical = SIZE_EXPAND_FILL + content_box.set( "custom_constants/margin_right", 8) + content_box.set( "custom_constants/margin_top", 8) + content_box.set( "custom_constants/margin_left", 8) + content_box.set( "custom_constants/margin_bottom", 8) + parts.add_child( content_box ) # content_box.set_owner( parts ) - ### - ### - if self.has_scrollbar: - # content_box/scroll_container - var content_scroll_container - if not content_box.has_node( "scroll_container" ): - content_scroll_container = ScrollContainer.new() - content_scroll_container.name = "scroll_container" - content_scroll_container.size_flags_horizontal = SIZE_FILL - content_scroll_container.size_flags_vertical = SIZE_FILL - content_scroll_container.scroll_deadzone = 0 - content_box.add_child( content_scroll_container ) - # content_scroll_container.set_owner( content_box ) - ### - ### - # content - var content - if not content_scroll_container.has_node( "content" ): - content = MarginContainer.new() - content.name = "content" - content.size_flags_horizontal = SIZE_EXPAND_FILL - content.size_flags_vertical = SIZE_EXPAND_FILL - content_scroll_container.add_child( content ) - # content.set_owner( content_scroll_container ) - ### - else: - var content - if not content_box.has_node( "content" ): - content = MarginContainer.new() - content.name = "content" - content.size_flags_horizontal = SIZE_EXPAND_FILL - content.size_flags_vertical = SIZE_EXPAND_FILL - content_box.add_child( content ) + ### + ### + if self.has_scrollbar: + # content_box/scroll_container + var content_scroll_container + if not content_box.has_node( "scroll_container" ): + content_scroll_container = ScrollContainer.new() + content_scroll_container.name = "scroll_container" + content_scroll_container.size_flags_horizontal = SIZE_FILL + content_scroll_container.size_flags_vertical = SIZE_FILL + content_scroll_container.scroll_deadzone = 0 + content_box.add_child( content_scroll_container ) + # content_scroll_container.set_owner( content_box ) + ### + ### + # content + var content + if not content_scroll_container.has_node( "content" ): + content = MarginContainer.new() + content.name = "content" + content.size_flags_horizontal = SIZE_EXPAND_FILL + content.size_flags_vertical = SIZE_EXPAND_FILL + content_scroll_container.add_child( content ) + # content.set_owner( content_scroll_container ) + ### + else: + var content + if not content_box.has_node( "content" ): + content = MarginContainer.new() + content.name = "content" + content.size_flags_horizontal = SIZE_EXPAND_FILL + content.size_flags_vertical = SIZE_EXPAND_FILL + content_box.add_child( content ) - ### - # Footer - var footer_box - if not parts.has_node( "footer_box" ): - footer_box = MarginContainer.new() - footer_box.name = "footer_box" - footer_box.size_flags_horizontal = SIZE_FILL - footer_box.size_flags_vertical = SIZE_FILL - footer_box.set( "custom_constants/margin_right", content_margin.position.y) - footer_box.set( "custom_constants/margin_top", content_margin.size.x) - footer_box.set( "custom_constants/margin_left", content_margin.position.x) - footer_box.set( "custom_constants/margin_bottom", content_margin.size.y) - parts.add_child( footer_box ) + ### + # Footer + var footer_box + if not parts.has_node( "footer_box" ): + footer_box = MarginContainer.new() + footer_box.name = "footer_box" + footer_box.size_flags_horizontal = SIZE_FILL + footer_box.size_flags_vertical = SIZE_FILL + footer_box.set( "custom_constants/margin_right", content_margin.position.y) + footer_box.set( "custom_constants/margin_top", content_margin.size.x) + footer_box.set( "custom_constants/margin_left", content_margin.position.x) + footer_box.set( "custom_constants/margin_bottom", content_margin.size.y) + parts.add_child( footer_box ) # footer_box.set_owner( parts ) - ### - ### - # footer_box/footer - var footer - if not footer_box.has_node( "footer" ): - footer = HBoxContainer.new() - footer.name = "footer" - footer.size_flags_horizontal = SIZE_EXPAND_FILL - footer.size_flags_vertical = SIZE_EXPAND_FILL - footer_box.add_child( footer ) + ### + ### + # footer_box/footer + var footer + if not footer_box.has_node( "footer" ): + footer = HBoxContainer.new() + footer.name = "footer" + footer.size_flags_horizontal = SIZE_EXPAND_FILL + footer.size_flags_vertical = SIZE_EXPAND_FILL + footer_box.add_child( footer ) # footer.set_owner( footer_box ) - ### - ### - # footer_label - var footer_label - if not footer.has_node( "footer_label" ): - footer_label = Label.new() - footer_label.name = "footer_label" - footer_label.size_flags_horizontal = SIZE_EXPAND - footer_label.size_flags_vertical = SIZE_EXPAND + ### + ### + # footer_label + var footer_label + if not footer.has_node( "footer_label" ): + footer_label = Label.new() + footer_label.name = "footer_label" + footer_label.size_flags_horizontal = SIZE_EXPAND + footer_label.size_flags_vertical = SIZE_EXPAND - footer.add_child( footer_label ) + footer.add_child( footer_label ) - ### - # resize - var resize_button - if not footer.has_node( "resize" ): - resize_button = TextureButton.new() - resize_button.name = "resize" - resize_button.size_flags_horizontal = SIZE_FILL | SIZE_SHRINK_END - resize_button.size_flags_vertical = SIZE_SHRINK_END + ### + # resize + var resize_button + if not footer.has_node( "resize" ): + resize_button = TextureButton.new() + resize_button.name = "resize" + resize_button.size_flags_horizontal = SIZE_FILL | SIZE_SHRINK_END + resize_button.size_flags_vertical = SIZE_SHRINK_END - var tex_resize = ImageTexture.new() - var img_resize = Image.new() - var stream_texture = load("res://addons/kh_window/button_resize.png") - img_resize = stream_texture.get_data() - tex_resize.create_from_image( img_resize ) - resize_button.texture_normal = tex_resize - resize_button.mouse_default_cursor_shape = CURSOR_FDIAGSIZE - resize_button.action_mode = Button.ACTION_MODE_BUTTON_PRESS + var tex_resize = ImageTexture.new() + var img_resize = Image.new() + var stream_texture = load("res://addons/kh_window/button_resize.png") + img_resize = stream_texture.get_data() + tex_resize.create_from_image( img_resize ) + resize_button.texture_normal = tex_resize + resize_button.mouse_default_cursor_shape = CURSOR_FDIAGSIZE + resize_button.action_mode = Button.ACTION_MODE_BUTTON_PRESS # resize_button.mouse_filter = MOUSE_FILTER_STOP - footer.add_child( resize_button ) + footer.add_child( resize_button ) # resize_button.set_owner( footer ) - resize_button.connect ( "button_down", self, "_on_Resize_pressed" ) - ###er_label.set_owner( footer ) - ### + resize_button.connect ( "button_down", self, "_on_Resize_pressed" ) + ###er_label.set_owner( footer ) + ### - current_rect_size = self.rect_min_size + current_rect_size = self.rect_min_size - if is_borderless: - $background.region_rect = Rect2( $background.patch_margin_left-1 - , $background.patch_margin_top-1 - , 256-($background.patch_margin_left+$background.patch_margin_right)+2 - , 256-($background.patch_margin_top+$background.patch_margin_bottom)+2 ) - $background.patch_margin_left = 1 - $background.patch_margin_top = 1 - $background.patch_margin_right = 1 - $background.patch_margin_bottom = 1 - header_box.rect_min_size.y = 1 - close_button.visible = false - open_button.visible = false - quit_button.visible = false - title_label.visible = false + if is_borderless: + $background.region_rect = Rect2( $background.patch_margin_left-1 + , $background.patch_margin_top-1 + , 256-($background.patch_margin_left+$background.patch_margin_right)+2 + , 256-($background.patch_margin_top+$background.patch_margin_bottom)+2 ) + $background.patch_margin_left = 1 + $background.patch_margin_top = 1 + $background.patch_margin_right = 1 + $background.patch_margin_bottom = 1 + header_box.rect_min_size.y = 1 + close_button.visible = false + open_button.visible = false + quit_button.visible = false + title_label.visible = false - if not is_resizable: - if not has_footer: - footer_box.visible = false - else: - footer_box.get_node( "footer/resize" ).visible = false + if not is_resizable: + if not has_footer: + footer_box.visible = false + else: + footer_box.get_node( "footer/resize" ).visible = false func _ready(): - # On déplace les enfants ajouter via l'editeur sous content. - for child in self.get_children(): - if not child.name =="parts" and not child.name =="background": - if child.name.begins_with( "footer_" ): - if footer_box.get_node("footer").has_node("footer_label"): - footer_box.get_node("footer").remove_child( footer_box.get_node("footer").get_node("footer_label") ) + # On déplace les enfants ajouter via l'editeur sous content. + for child in self.get_children(): + if not child.name =="parts" and not child.name =="background": + if child.name.begins_with( "footer_" ): + if footer_box.get_node("footer").has_node("footer_label"): + footer_box.get_node("footer").remove_child( footer_box.get_node("footer").get_node("footer_label") ) - self.remove_child( child ) - get_footer().add_child( child ) - get_footer().move_child( child, 0 ) - else: - self.remove_child( child ) - get_content().add_child( child ) + self.remove_child( child ) + get_footer().add_child( child ) + get_footer().move_child( child, 0 ) + else: + self.remove_child( child ) + get_content().add_child( child ) - set_mouse_pass_to_children( self ) + set_mouse_pass_to_children( self ) func _process(delta): - if size_changed: - self.rect_size = Vector2( clamp( self.rect_size.x, min_size.x, self.rect_size.x ), clamp( self.rect_size.y, min_size.y, self.rect_size.y ) ) - size_changed = false + if size_changed: + self.rect_size = Vector2( clamp( self.rect_size.x, min_size.x, self.rect_size.x ), clamp( self.rect_size.y, min_size.y, self.rect_size.y ) ) + size_changed = false func _on_Window_mouse_entered(): - print("mouse_entered") + print("mouse_entered") func _on_Window_focus_entered(): - print("focus_entered") + print("focus_entered") func _on_Quit_pressed(): - self.visible = false + self.visible = false func get_content_child( p_node ): - return get_content().get_node( p_node ) + return get_content().get_node( p_node ) func get_content(): - if self.has_scrollbar: - return content_box.get_node( "scroll_container/content" ) - else: - return content_box.get_node( "content" ) - + if self.has_scrollbar: + return content_box.get_node( "scroll_container/content" ) + else: + return content_box.get_node( "content" ) + func get_footer(): - return footer_box.get_node( "footer" ) + return footer_box.get_node( "footer" ) func close(): - if not self.is_borderless: - self.header_box.get_node( "header/close" ).visible = false - self.header_box.get_node( "header/open" ).visible = true - self.content_box.visible = false - self.footer_box.visible = false - self.current_rect_size = self.rect_size - self.rect_size = Vector2( 0, 0 ) - $background.rect_size = Vector2( 0, 0 ) - $background.rect_min_size = Vector2( 0, 0 ) - else: - self.header_box.get_node( "header/close" ).visible = false - self.header_box.get_node( "header/open" ).visible = false - self.content_box.visible = false - self.footer_box.visible = false - self.current_rect_size = self.rect_size - self.rect_size = Vector2( 0, 0 ) - $background.rect_size = Vector2( 0, 0 ) - $background.rect_min_size = Vector2( 0, 0 ) + if not self.is_borderless: + self.header_box.get_node( "header/close" ).visible = false + self.header_box.get_node( "header/open" ).visible = true + self.content_box.visible = false + self.footer_box.visible = false + self.current_rect_size = self.rect_size + self.rect_size = Vector2( 0, 0 ) + $background.rect_size = Vector2( 0, 0 ) + $background.rect_min_size = Vector2( 0, 0 ) + else: + self.header_box.get_node( "header/close" ).visible = false + self.header_box.get_node( "header/open" ).visible = false + self.content_box.visible = false + self.footer_box.visible = false + self.current_rect_size = self.rect_size + self.rect_size = Vector2( 0, 0 ) + $background.rect_size = Vector2( 0, 0 ) + $background.rect_min_size = Vector2( 0, 0 ) func _on_Close_pressed(): - close() + close() func open(): - if not is_borderless: - header_box.get_node( "header/close" ).visible = true - header_box.get_node( "header/open" ).visible = false - content_box.visible = true - footer_box.visible = true - self.rect_size = current_rect_size - else: - header_box.get_node( "header/close" ).visible = false - header_box.get_node( "header/open" ).visible = false - content_box.visible = true - footer_box.visible = true - self.rect_size = current_rect_size + if not is_borderless: + header_box.get_node( "header/close" ).visible = true + header_box.get_node( "header/open" ).visible = false + content_box.visible = true + footer_box.visible = true + self.rect_size = current_rect_size + else: + header_box.get_node( "header/close" ).visible = false + header_box.get_node( "header/open" ).visible = false + content_box.visible = true + footer_box.visible = true + self.rect_size = current_rect_size func _on_Open_pressed(): - open() + open() func _on_Resize_pressed(): - is_resizing = true + is_resizing = true func _input( event ): - if is_resizable: - if is_resizing and event is InputEventMouseButton and not event.pressed: - is_resizing = false - if event is InputEventMouseMotion and is_resizing: - var delta = event.relative - self.rect_size += delta - size_changed = true + if is_resizable: + if is_resizing and event is InputEventMouseButton and not event.pressed: + is_resizing = false + if event is InputEventMouseMotion and is_resizing: + var delta = event.relative + self.rect_size += delta + size_changed = true func check_if_clicked( event ): - if not is_moving and event is InputEventMouseButton and event.is_pressed() and not event.is_echo() and event.button_index == 1 : - emit_signal( "window_clicked", self ) + if not is_moving and event is InputEventMouseButton and event.is_pressed() and not event.is_echo() and event.button_index == 1 : + emit_signal( "window_clicked", self ) func _on_Header_gui_input( event ): - check_if_clicked( event ) + check_if_clicked( event ) - if self.is_dragged_by_header_only: - if is_movable: - if is_moving and event is InputEventMouseButton and not event.pressed: - is_moving = false - elif not is_moving and event is InputEventMouseButton and event.pressed: - is_moving = true - if event is InputEventMouseMotion and is_moving: - var delta = event.relative - self.rect_position += delta + if self.is_dragged_by_header_only: + if is_movable: + if is_moving and event is InputEventMouseButton and not event.pressed: + is_moving = false + elif not is_moving and event is InputEventMouseButton and event.pressed: + is_moving = true + if event is InputEventMouseMotion and is_moving: + var delta = event.relative + self.rect_position += delta func _on_window_gui_input( event ): - check_if_clicked( event ) - if not self.is_dragged_by_header_only: - if is_movable: - if is_moving and event is InputEventMouseButton and not event.pressed: - is_moving = false - elif not is_moving and event is InputEventMouseButton and event.pressed: - is_moving = true - if event is InputEventMouseMotion and is_moving: - var delta = event.relative - self.rect_position += delta - + check_if_clicked( event ) + if not self.is_dragged_by_header_only: + if is_movable: + if is_moving and event is InputEventMouseButton and not event.pressed: + is_moving = false + elif not is_moving and event is InputEventMouseButton and event.pressed: + is_moving = true + if event is InputEventMouseMotion and is_moving: + var delta = event.relative + self.rect_position += delta + func load_from_file( config_file ): - if config_file.has_section( self.name ): - self.rect_position = config_file.get_value( self.name, "position" ) - self.rect_size = config_file.get_value( self.name, "size" ) - self.is_borderless = config_file.get_value( self.name, "borderless" ) - current_rect_position = self.rect_position - current_rect_size = self.rect_size - if config_file.get_value( self.name, "opened" ): - open() - else: - close() + if config_file.has_section( self.name ): + self.rect_position = config_file.get_value( self.name, "position" ) + self.rect_size = config_file.get_value( self.name, "size" ) + self.is_borderless = config_file.get_value( self.name, "borderless" ) + current_rect_position = self.rect_position + current_rect_size = self.rect_size + if config_file.get_value( self.name, "opened" ): + open() + else: + close() func save_to_file( config_file ): - var is_open = content_box.visible + var is_open = content_box.visible - config_file.set_value(self.name, "position", self.rect_position) + config_file.set_value(self.name, "position", self.rect_position) - if not is_open: - config_file.set_value(self.name, "size", current_rect_size) - else: - config_file.set_value(self.name, "size", self.rect_size) + if not is_open: + config_file.set_value(self.name, "size", current_rect_size) + else: + config_file.set_value(self.name, "size", self.rect_size) - if is_open: - config_file.set_value(self.name, "opened", true) - else: - config_file.set_value(self.name, "opened", false) + if is_open: + config_file.set_value(self.name, "opened", true) + else: + config_file.set_value(self.name, "opened", false) - config_file.set_value(self.name, "borderless", is_borderless) + config_file.set_value(self.name, "borderless", is_borderless) diff --git a/assets/fonts/IMMORTAL.ttf b/assets/fonts/IMMORTAL.ttf new file mode 100644 index 0000000000000000000000000000000000000000..146ad3c0b5c78e563b160cdad758c6c321fb9244 GIT binary patch literal 170508 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 %3ecnyQ4RLL-G zlQARS*Nn=(tgy0n14he{`Hh{Hk@6R>mCQ4I9qVO2+i6%UmH&D5+?~~Dt}tT)!tm

{Y+pSSVl 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 literal 0 HcmV?d00001 diff --git a/icon.png b/icon.png index c98fbb601c83c81ec8c22b1dba7d1d57c62b323c..edb9b0e72b9a2c9b6c9f11d385d1d00772a7134a 100644 GIT binary patch literal 63092 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 diff --git a/project.godot b/project.godot index b14315e..9765aad 100644 --- a/project.godot +++ b/project.godot @@ -69,7 +69,7 @@ config/icon="res://icon.png" [autoload] -Creatures="*res://ressources/scripts/creatures_old.gd" +Creatures="*res://ressources/scripts/creatures.gd" MusicManager="*res://scenes/interfaces/music_manager/music_manager.tscn" Connection="*res://scenes/connection/connection.tscn" Globals="*res://ressources/scripts/global.gd" diff --git a/ressources/scripts/creatures.gd b/ressources/scripts/creatures.gd new file mode 100644 index 0000000..58b3063 --- /dev/null +++ b/ressources/scripts/creatures.gd @@ -0,0 +1,85 @@ +extends Node + +class Creature_old2: + + enum Sex { F, M, H, A, U } + + var type + var pseudonym + + + func _init( p_pseudonym = "Créature" ): + self.type = "creature" + self.pseudonym = p_pseudonym + + +class Ra_old2 extends Creature_old2: + + + var sex = Creature_old2.Sex.F + + var female_boobs = 0.0 + var female_hip = 0.0 + var male_pack = 0.0 + var male_throat = 0.0 + var female_pregnant = 0.0 + + var color = Color( 1.0, 1.0, 1.0 ) + + var douleur = 0.0 + var trauma = 0.0 + var oubli = 0.0 + + func _init( p_pseudonym = "Créature" ): + self.type = "ra" + self.pseudonym = p_pseudonym + + func to_dictionary(): + + var dictionary = Dictionary() + dictionary[ "type" ] = self.type + dictionary[ "pseudonym" ] = self.pseudonym + + dictionary[ "sex" ] = var2str( self.sex ) + dictionary[ "female_boobs" ] = var2str( self.female_boobs ) + dictionary[ "female_hip" ] = var2str( self.female_hip ) + dictionary[ "male_pack" ] = var2str( self.male_pack ) + dictionary[ "male_throat" ] = var2str( self.male_throat ) + dictionary[ "female_pregnant" ] = var2str( self.female_pregnant ) + + dictionary[ "color" ] = var2str( self.color ) + + + return dictionary + + func from_dictionary( dictionary ): + + self.pseudonym = dictionary.get( "pseudonym", self.pseudonym ) + + self.sex = dictionary.get( "sex", self.sex ) + self.female_boobs = dictionary.get( "female_boobs", self.female_boobs ) + self.female_hip = dictionary.get( "female_hip", self.female_hip ) + self.male_pack = dictionary.get( "male_pack", self.male_pack ) + self.male_throat = dictionary.get( "male_throat", self.male_throat ) + self.female_pregnant = dictionary.get( "female_pregnant", self.female_pregnant ) + + self.color = dictionary.get( "color", self.color ) + + func from_file( filename ): + var file = File.new() + if file.file_exists( "user://creatures/" + filename ): + file.open( "user://creatures/" + filename, File.READ ) + var lines = "" + while not file.eof_reached(): + var current_line = file.get_line() + lines += current_line + var json = JSON.parse( lines ).result + var dict = {} + for data in json: + dict[ data ] = str2var( json[data] ) + + + self.from_dictionary( dict ) + + file.close() + diff --git a/ressources/scripts/creatures/creature_old.gd b/ressources/scripts/creatures/creature_old.gd index dbc46eb..ce27e9f 100644 --- a/ressources/scripts/creatures/creature_old.gd +++ b/ressources/scripts/creatures/creature_old.gd @@ -5,5 +5,5 @@ class_name Creature_old func from_dict( datas ): - pass - + pass + diff --git a/ressources/scripts/creatures_old.gd b/ressources/scripts/creatures_old.gd deleted file mode 100644 index 2b64d91..0000000 --- a/ressources/scripts/creatures_old.gd +++ /dev/null @@ -1,85 +0,0 @@ -extends Node - -class Creature_old2: - - enum Sex { F, M, H, A, U } - - var type - var pseudonym - - - func _init( p_pseudonym = "Créature" ): - self.type = "creature" - self.pseudonym = p_pseudonym - - -class Ra_old2 extends Creature_old2: - - - var sex = Creature_old2.Sex.F - - var female_boobs = 0.0 - var female_hip = 0.0 - var male_pack = 0.0 - var male_throat = 0.0 - var female_pregnant = 0.0 - - var color = Color( 1.0, 1.0, 1.0 ) - - var douleur = 0.0 - var trauma = 0.0 - var oubli = 0.0 - - func _init( p_pseudonym = "Créature" ): - self.type = "ra" - self.pseudonym = p_pseudonym - - func to_dictionary(): - - var dictionary = Dictionary() - dictionary[ "type" ] = self.type - dictionary[ "pseudonym" ] = self.pseudonym - - dictionary[ "sex" ] = var2str( self.sex ) - dictionary[ "female_boobs" ] = var2str( self.female_boobs ) - dictionary[ "female_hip" ] = var2str( self.female_hip ) - dictionary[ "male_pack" ] = var2str( self.male_pack ) - dictionary[ "male_throat" ] = var2str( self.male_throat ) - dictionary[ "female_pregnant" ] = var2str( self.female_pregnant ) - - dictionary[ "color" ] = var2str( self.color ) - - - return dictionary - - func from_dictionary( dictionary ): - - self.pseudonym = dictionary.get( "pseudonym", self.pseudonym ) - - self.sex = dictionary.get( "sex", self.sex ) - self.female_boobs = dictionary.get( "female_boobs", self.female_boobs ) - self.female_hip = dictionary.get( "female_hip", self.female_hip ) - self.male_pack = dictionary.get( "male_pack", self.male_pack ) - self.male_throat = dictionary.get( "male_throat", self.male_throat ) - self.female_pregnant = dictionary.get( "female_pregnant", self.female_pregnant ) - - self.color = dictionary.get( "color", self.color ) - - func from_file( filename ): - var file = File.new() - if file.file_exists( "user://creatures/" + filename ): - file.open( "user://creatures/" + filename, File.READ ) - var lines = "" - while not file.eof_reached(): - var current_line = file.get_line() - lines += current_line - var json = JSON.parse( lines ).result - var dict = {} - for data in json: - dict[ data ] = str2var( json[data] ) - - - self.from_dictionary( dict ) - - file.close() - diff --git a/ressources/scripts/global.gd b/ressources/scripts/global.gd index 09fb705..42c038a 100644 --- a/ressources/scripts/global.gd +++ b/ressources/scripts/global.gd @@ -7,29 +7,29 @@ var player_name = null var ressource_queue = preload("res://ressources/scripts/resource_queue.gd").new() enum RACE { - human + human } var race_label = [ "Humain" ] func get_race_id( p_label ): - return race_label.find( p_label ) - + return race_label.find( p_label ) + enum SEX { - female, - male + female, + male } var sex_label = [ "Femme", "Homme" ] func get_sex_id( p_label ): - return race_label.find( p_label ) + return race_label.find( p_label ) enum CREATURES_EDITOR_MODE { - player, - npc + player, + npc } var creatures_editor_mode = CREATURES_EDITOR_MODE.player func goto_scene( path ): - self.get_tree().get_root().get_node("main").goto_scene( path ) + self.get_tree().get_root().get_node("main").goto_scene( path ) diff --git a/ressources/scripts/nel/nel_login_message.gd b/ressources/scripts/nel/nel_login_message.gd index b5f220b..d088cb7 100644 --- a/ressources/scripts/nel/nel_login_message.gd +++ b/ressources/scripts/nel/nel_login_message.gd @@ -1,30 +1,30 @@ class nel_login_message: - var _cmd; - var _login; - var _password; - var _clientApplication; - var _cp; - var _lg; + var _cmd; + var _login; + var _password; + var _clientApplication; + var _cp; + var _lg; - func _init(cmd, login, password, clientApplication, cp, lg): - self._cmd = cmd; - self._login = login; - self._password = password; - self._clientApplication = clientApplication; - self._cp = cp; - self._lg = lg; + func _init(cmd, login, password, clientApplication, cp, lg): + self._cmd = cmd; + self._login = login; + self._password = password; + self._clientApplication = clientApplication; + self._cp = cp; + self._lg = lg; - func get_request_string(): - var request_string = "cmd=" + self._cmd; - if self._login != "": - request_string += "&login=" + self._login; - if self._password != "": - request_string += "&password=" + self._password; - if self._clientApplication != "": - request_string += "&clientApplication=" + self._clientApplication; - if self._cp != "": - request_string += "&cp=" + self._cp; - if self._lg != "": - request_string += "&lg=" + self._lg; + func get_request_string(): + var request_string = "cmd=" + self._cmd; + if self._login != "": + request_string += "&login=" + self._login; + if self._password != "": + request_string += "&password=" + self._password; + if self._clientApplication != "": + request_string += "&clientApplication=" + self._clientApplication; + if self._cp != "": + request_string += "&cp=" + self._cp; + if self._lg != "": + request_string += "&lg=" + self._lg; - return request_string; + return request_string; diff --git a/ressources/scripts/nel/nel_server_infos.gd b/ressources/scripts/nel/nel_server_infos.gd index 22b2a60..1c8148f 100644 --- a/ressources/scripts/nel/nel_server_infos.gd +++ b/ressources/scripts/nel/nel_server_infos.gd @@ -1,19 +1,19 @@ class nel_server_info: - var _cookie; - var _shardIp; - var _ringStartAdress; - var _ringAddress; - var _patchVersion - var _backupPatchUrls; - var _patchUrls; + var _cookie; + var _shardIp; + var _ringStartAdress; + var _ringAddress; + var _patchVersion + var _backupPatchUrls; + var _patchUrls; - func _init(connexionResultString): - var params = connexionResultString.split('#'); - var temp = params[4].split('\n') - self._cookie = params[1]; - self._shardIp = params[2]; - self._ringStartAdress = params[3]; - self._ringAddress = temp[0]; - self._patchVersion = temp[1]; - self._backupPatchUrls = params[5]; - self._patchUrls = params[6]; + func _init(connexionResultString): + var params = connexionResultString.split('#'); + var temp = params[4].split('\n') + self._cookie = params[1]; + self._shardIp = params[2]; + self._ringStartAdress = params[3]; + self._ringAddress = temp[0]; + self._patchVersion = temp[1]; + self._backupPatchUrls = params[5]; + self._patchUrls = params[6]; diff --git a/ressources/scripts/resource_queue.gd b/ressources/scripts/resource_queue.gd index 45d266f..896de4f 100644 --- a/ressources/scripts/resource_queue.gd +++ b/ressources/scripts/resource_queue.gd @@ -8,138 +8,138 @@ var queue = [] var pending = {} func _lock(_caller): - mutex.lock() + mutex.lock() func _unlock(_caller): - mutex.unlock() + mutex.unlock() func _post(_caller): - sem.post() + sem.post() func _wait(_caller): - sem.wait() + sem.wait() func queue_resource(path, p_in_front = false): - _lock("queue_resource") - if path in pending: - _unlock("queue_resource") - return - elif ResourceLoader.has_cached(path): - var res = ResourceLoader.load(path) - pending[path] = res - _unlock("queue_resource") - return - else: - var res = ResourceLoader.load_interactive(path) - res.set_meta("path", path) - if p_in_front: - queue.insert(0, res) - else: - queue.push_back(res) - pending[path] = res - _post("queue_resource") - _unlock("queue_resource") - return + _lock("queue_resource") + if path in pending: + _unlock("queue_resource") + return + elif ResourceLoader.has_cached(path): + var res = ResourceLoader.load(path) + pending[path] = res + _unlock("queue_resource") + return + else: + var res = ResourceLoader.load_interactive(path) + res.set_meta("path", path) + if p_in_front: + queue.insert(0, res) + else: + queue.push_back(res) + pending[path] = res + _post("queue_resource") + _unlock("queue_resource") + return func cancel_resource(path): - _lock("cancel_resource") - if path in pending: - if pending[path] is ResourceInteractiveLoader: - queue.erase(pending[path]) - pending.erase(path) - _unlock("cancel_resource") + _lock("cancel_resource") + if path in pending: + if pending[path] is ResourceInteractiveLoader: + queue.erase(pending[path]) + pending.erase(path) + _unlock("cancel_resource") func get_progress(path): - _lock("get_progress") - var ret = -1 - if path in pending: - if pending[path] is ResourceInteractiveLoader: - ret = float(pending[path].get_stage()) / float(pending[path].get_stage_count()) - else: - ret = 1.0 - _unlock("get_progress") - return ret + _lock("get_progress") + var ret = -1 + if path in pending: + if pending[path] is ResourceInteractiveLoader: + ret = float(pending[path].get_stage()) / float(pending[path].get_stage_count()) + else: + ret = 1.0 + _unlock("get_progress") + return ret func is_ready(path): - var ret - _lock("is_ready") - if path in pending: - ret = !(pending[path] is ResourceInteractiveLoader) - else: - ret = false - _unlock("is_ready") - return ret + var ret + _lock("is_ready") + if path in pending: + ret = !(pending[path] is ResourceInteractiveLoader) + else: + ret = false + _unlock("is_ready") + return ret func _wait_for_resource(res, path): - _unlock("wait_for_resource") - while true: - VisualServer.sync() - OS.delay_usec(16000) # Wait approximately 1 frame. - _lock("wait_for_resource") - if queue.size() == 0 || queue[0] != res: - return pending[path] - _unlock("wait_for_resource") + _unlock("wait_for_resource") + while true: + VisualServer.sync() + OS.delay_usec(16000) # Wait approximately 1 frame. + _lock("wait_for_resource") + if queue.size() == 0 || queue[0] != res: + return pending[path] + _unlock("wait_for_resource") func get_resource(path): - _lock("get_resource") - if path in pending: - if pending[path] is ResourceInteractiveLoader: - var res = pending[path] - if res != queue[0]: - var pos = queue.find(res) - queue.remove(pos) - queue.insert(0, res) + _lock("get_resource") + if path in pending: + if pending[path] is ResourceInteractiveLoader: + var res = pending[path] + if res != queue[0]: + var pos = queue.find(res) + queue.remove(pos) + queue.insert(0, res) - res = _wait_for_resource(res, path) - pending.erase(path) - _unlock("return") - return res - else: - var res = pending[path] - pending.erase(path) - _unlock("return") - return res - else: - _unlock("return") - return ResourceLoader.load(path) + res = _wait_for_resource(res, path) + pending.erase(path) + _unlock("return") + return res + else: + var res = pending[path] + pending.erase(path) + _unlock("return") + return res + else: + _unlock("return") + return ResourceLoader.load(path) func thread_process(): - _wait("thread_process") - _lock("process") + _wait("thread_process") + _lock("process") - while queue.size() > 0: - var res = queue[0] - _unlock("process_poll") - var ret = res.poll() - _lock("process_check_queue") + while queue.size() > 0: + var res = queue[0] + _unlock("process_poll") + var ret = res.poll() + _lock("process_check_queue") - if ret == ERR_FILE_EOF || ret != OK: - var path = res.get_meta("path") - if path in pending: # Else, it was already retrieved. - pending[res.get_meta("path")] = res.get_resource() - # Something might have been put at the front of the queue while - # we polled, so use erase instead of remove. - queue.erase(res) - _unlock("process") + if ret == ERR_FILE_EOF || ret != OK: + var path = res.get_meta("path") + if path in pending: # Else, it was already retrieved. + pending[res.get_meta("path")] = res.get_resource() + # Something might have been put at the front of the queue while + # we polled, so use erase instead of remove. + queue.erase(res) + _unlock("process") func thread_func(_u): - while true: - thread_process() + while true: + thread_process() func start(): - mutex = Mutex.new() - sem = Semaphore.new() - thread = Thread.new() - thread.start(self, "thread_func", 0) + mutex = Mutex.new() + sem = Semaphore.new() + thread = Thread.new() + thread.start(self, "thread_func", 0) diff --git a/scenes/characters/character.gd b/scenes/characters/character.gd index 5e861e8..0b743a3 100644 --- a/scenes/characters/character.gd +++ b/scenes/characters/character.gd @@ -35,268 +35,268 @@ var direction = Vector3.ZERO var orientation = 0.0 enum PLAYER_RELATION { - neutre, - friend, - ennemy + neutre, + friend, + ennemy } export( PLAYER_RELATION ) var player_relation = PLAYER_RELATION.neutre export( String ) var creature_filename = null setget set_creature_filename func set_creature_filename( p_filename ): - creature_filename = p_filename - self.load_from_name( p_filename ) + creature_filename = p_filename + self.load_from_name( p_filename ) func _process( delta ): - # Calculate a move direction vector relative to the camera - # The basis stores the (right, up, -forwards) vectors of our camera. - var forwards: Vector3 = $look_at.global_transform.basis.z * direction.z - var right: Vector3 = $look_at.global_transform.basis.x * direction.x - if forwards: - right = Vector3.ZERO - var move_direction: = forwards + right - if move_direction.length() > 1.0: - move_direction = move_direction.normalized() - move_direction.y = 0 - - # Rotation. - if (self.has_node( "creature" ) and $creature.can_turn()) or self.is_readying_weapon or self.is_weapon_ready: - self.rotate_y( rotation_speed_factor * orientation ) + # Calculate a move direction vector relative to the camera + # The basis stores the (right, up, -forwards) vectors of our camera. + var forwards: Vector3 = $look_at.global_transform.basis.z * direction.z + var right: Vector3 = $look_at.global_transform.basis.x * direction.x + if forwards: + right = Vector3.ZERO + var move_direction: = forwards + right + if move_direction.length() > 1.0: + move_direction = move_direction.normalized() + move_direction.y = 0 + + # Rotation. + if (self.has_node( "creature" ) and $creature.can_turn()) or self.is_readying_weapon or self.is_weapon_ready: + self.rotate_y( rotation_speed_factor * orientation ) - # Movement. - velocity = self.calculate_velocity(velocity, move_direction, delta) - if not self.is_readying_weapon and not self.is_weapon_ready: - if not self.is_jumping and not self.is_jump_started and not self.is_falling: - velocity = self.move_and_slide_with_snap(velocity, Vector3.DOWN, Vector3.UP, true) - else: - velocity = self.move_and_slide(velocity, Vector3.UP, true) - # Animation. - if self.has_node( "creature" ): - if self.is_dead: - $creature.play( "dead_loop" ) - elif self.is_dying: - $creature.play( "dying", 2.0 ) - elif self.is_readying_weapon: - $creature.play( "1h_pistol_ready_start" ) - elif self.is_weapon_ready: - $creature.play( "1h_pistol_ready_loop" ) - elif direction and not self.is_jump_started and not self.is_jumping and not self.is_falling: - if direction.z < 0.0: - if self.is_running: - $creature.play( "run" , 2.0 ) - else: - $creature.play( "walk" ) - elif direction.z > 0.0: - if self.is_running: - $creature.play_backwards( "run", 2.0 ) - else: - $creature.play_backwards( "walk" ) - elif direction.x > 0.0: - $creature.play( "strafe_right" ) - elif direction.x < 0.0: - $creature.play( "strafe_left" ) - elif self.is_jump_started and not self.is_jumping: - $creature.play( "jump_start" ) - elif self.is_jumping or self.is_falling: - if not self.is_on_ground: - $creature.play( "jump_loop" ) - else: - $creature.play( "jump_end", 2 ) - elif not self.orientation == 0.0: - if self.orientation < 0.0: - $creature.play( "turn_right", 2.0 ) - elif self.orientation > 0.0: - $creature.play( "turn_left", 2.0 ) - else: - $creature.play( "idle" ) - - + # Movement. + velocity = self.calculate_velocity(velocity, move_direction, delta) + if not self.is_readying_weapon and not self.is_weapon_ready: + if not self.is_jumping and not self.is_jump_started and not self.is_falling: + velocity = self.move_and_slide_with_snap(velocity, Vector3.DOWN, Vector3.UP, true) + else: + velocity = self.move_and_slide(velocity, Vector3.UP, true) + # Animation. + if self.has_node( "creature" ): + if self.is_dead: + $creature.play( "dead_loop" ) + elif self.is_dying: + $creature.play( "dying", 2.0 ) + elif self.is_readying_weapon: + $creature.play( "1h_pistol_ready_start" ) + elif self.is_weapon_ready: + $creature.play( "1h_pistol_ready_loop" ) + elif direction and not self.is_jump_started and not self.is_jumping and not self.is_falling: + if direction.z < 0.0: + if self.is_running: + $creature.play( "run" , 2.0 ) + else: + $creature.play( "walk" ) + elif direction.z > 0.0: + if self.is_running: + $creature.play_backwards( "run", 2.0 ) + else: + $creature.play_backwards( "walk" ) + elif direction.x > 0.0: + $creature.play( "strafe_right" ) + elif direction.x < 0.0: + $creature.play( "strafe_left" ) + elif self.is_jump_started and not self.is_jumping: + $creature.play( "jump_start" ) + elif self.is_jumping or self.is_falling: + if not self.is_on_ground: + $creature.play( "jump_loop" ) + else: + $creature.play( "jump_end", 2 ) + elif not self.orientation == 0.0: + if self.orientation < 0.0: + $creature.play( "turn_right", 2.0 ) + elif self.orientation > 0.0: + $creature.play( "turn_left", 2.0 ) + else: + $creature.play( "idle" ) + + func calculate_velocity( - velocity_current: Vector3, - move_direction: Vector3, - delta: float - ) -> Vector3: - + velocity_current: Vector3, + move_direction: Vector3, + delta: float + ) -> Vector3: + # var velocity_new := move_direction - var velocity_new = Vector3.ZERO - if not self.is_jump_started: - velocity_new = move_direction - - if self.is_running: - velocity_new *= run_speed - else: - velocity_new *= move_speed - if velocity_new.length() > max_speed: - velocity_new = velocity_new.normalized() * max_speed - velocity_new.y = velocity_current.y + gravity * delta - if self.is_jumping: - velocity_new.y += self.jump_strength * delta - self.is_jumping = false - self.is_falling = true - if self.is_falling: - velocity_new.x *= 2.0 - velocity_new.z *= 2.0 - - - return velocity_new - + var velocity_new = Vector3.ZERO + if not self.is_jump_started: + velocity_new = move_direction + + if self.is_running: + velocity_new *= run_speed + else: + velocity_new *= move_speed + if velocity_new.length() > max_speed: + velocity_new = velocity_new.normalized() * max_speed + velocity_new.y = velocity_current.y + gravity * delta + if self.is_jumping: + velocity_new.y += self.jump_strength * delta + self.is_jumping = false + self.is_falling = true + if self.is_falling: + velocity_new.x *= 2.0 + velocity_new.z *= 2.0 + + + return velocity_new + func load_from_name( p_name, p_emplacement = null ): - var creature = Datas.Creature.new() - creature.set_data( "name", p_name ) - creature.load( null, p_emplacement ) - if creature.get_data( "race" ) == Globals.RACE.human: - if creature.get_data( "sex" ) == Globals.SEX.female: - self.change_creature( "res://scenes/creatures/human/human_female.tscn" ) - elif creature.get_data( "sex" ) == Globals.SEX.male: - self.change_creature( "res://scenes/creatures/human/human_male.tscn" ) - if $creature: - $creature.load_from_name( p_name, p_emplacement ) - + var creature = Datas.Creature.new() + creature.set_data( "name", p_name ) + creature.load( null, p_emplacement ) + if creature.get_data( "race" ) == Globals.RACE.human: + if creature.get_data( "sex" ) == Globals.SEX.female: + self.change_creature( "res://scenes/creatures/human/human_female.tscn" ) + elif creature.get_data( "sex" ) == Globals.SEX.male: + self.change_creature( "res://scenes/creatures/human/human_male.tscn" ) + if $creature: + $creature.load_from_name( p_name, p_emplacement ) + func change_creature( new_model_path ): - if $creature: - var old_model = $creature - self.remove_child( old_model ) - old_model.queue_free() - var new_model = load( new_model_path ) - if new_model: - new_model = new_model.instance() - new_model.name = "creature" - self.add_child( new_model ) - new_model.connect( "animation_finished", self, "_on_creature_animation_finished" ) - new_model.duplicate_meshes() + if $creature: + var old_model = $creature + self.remove_child( old_model ) + old_model.queue_free() + var new_model = load( new_model_path ) + if new_model: + new_model = new_model.instance() + new_model.name = "creature" + self.add_child( new_model ) + new_model.connect( "animation_finished", self, "_on_creature_animation_finished" ) + new_model.duplicate_meshes() func set_blend_shape( p_blend_shape_name, p_value ): - $creature.set_blend_shape( p_blend_shape_name, p_value ) - + $creature.set_blend_shape( p_blend_shape_name, p_value ) + func _on_ground_area_body_entered(body): - if not body == self: - self.ground_contacts += 1 - if self.ground_contacts > 0: + if not body == self: + self.ground_contacts += 1 + if self.ground_contacts > 0: # self.is_falling = false - self.is_on_ground = true + self.is_on_ground = true func _on_ground_area_body_exited(body): - if not body == self: - self.ground_contacts -= 1 - if self.ground_contacts <= 0: - self.is_falling = true - self.is_on_ground = false + if not body == self: + self.ground_contacts -= 1 + if self.ground_contacts <= 0: + self.is_falling = true + self.is_on_ground = false func _on_creature_animation_finished(anim_name): - if anim_name == "jump_start": - self.is_jump_started = false - self.is_jumping = true - elif anim_name == "jump_end": - self.is_falling = false - elif anim_name == "turn_right": - self.can_turn = false - elif anim_name == "turn_left": - self.can_turn = false - elif anim_name == "1h_pistol_ready_start": - self.is_readying_weapon = false - self.is_weapon_ready = true - elif anim_name == "dying": - self.is_dying = false - self.is_dead = true + if anim_name == "jump_start": + self.is_jump_started = false + self.is_jumping = true + elif anim_name == "jump_end": + self.is_falling = false + elif anim_name == "turn_right": + self.can_turn = false + elif anim_name == "turn_left": + self.can_turn = false + elif anim_name == "1h_pistol_ready_start": + self.is_readying_weapon = false + self.is_weapon_ready = true + elif anim_name == "dying": + self.is_dying = false + self.is_dead = true func set_focus( p_focus = true ): - if p_focus: - $focus.show() - if self.player_relation == PLAYER_RELATION.neutre: - $focus.get_surface_material( 0 ).albedo_color = Color.white - elif self.player_relation == PLAYER_RELATION.friend: - $focus.get_surface_material( 0 ).albedo_color = Color.green - elif self.player_relation == PLAYER_RELATION.ennemy: - $focus.get_surface_material( 0 ).albedo_color = Color.red - else: - $focus.hide() + if p_focus: + $focus.show() + if self.player_relation == PLAYER_RELATION.neutre: + $focus.get_surface_material( 0 ).albedo_color = Color.white + elif self.player_relation == PLAYER_RELATION.friend: + $focus.get_surface_material( 0 ).albedo_color = Color.green + elif self.player_relation == PLAYER_RELATION.ennemy: + $focus.get_surface_material( 0 ).albedo_color = Color.red + else: + $focus.hide() func get_weapons(): - var weapons = [] - if Datas.Equipment.SLOT.weapon_hands in $creature.slots: - if $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item: - weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item ) + var weapons = [] + if Datas.Equipment.SLOT.weapon_hands in $creature.slots: + if $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item: + weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item ) - if not weapons.size() > 0: - if Datas.Equipment.SLOT.weapon_hand_right in $creature.slots: - if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item: - weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item ) - if Datas.Equipment.SLOT.weapon_hand_left in $creature.slots: - if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item: - weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item ) - return weapons - + if not weapons.size() > 0: + if Datas.Equipment.SLOT.weapon_hand_right in $creature.slots: + if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item: + weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item ) + if Datas.Equipment.SLOT.weapon_hand_left in $creature.slots: + if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item: + weapons.push_back( $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item ) + return weapons + func get_main_weapon_node(): - var weapon = null - if Datas.Equipment.SLOT.weapon_hands in $creature.slots: - if $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item: - if $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children().size() > 0: - weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] - if not weapon and Datas.Equipment.SLOT.weapon_hand_right in $creature.slots: - if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item: - if $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children().size() > 0: - weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] - if not weapon and Datas.Equipment.SLOT.weapon_hand_left in $creature.slots: - if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item: - if $creature/body_parts/body/skeleton/attachment_hand_L/handle.get_children().size() > 0: - weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] - return weapon - + var weapon = null + if Datas.Equipment.SLOT.weapon_hands in $creature.slots: + if $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item: + if $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children().size() > 0: + weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] + if not weapon and Datas.Equipment.SLOT.weapon_hand_right in $creature.slots: + if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item: + if $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children().size() > 0: + weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] + if not weapon and Datas.Equipment.SLOT.weapon_hand_left in $creature.slots: + if $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item: + if $creature/body_parts/body/skeleton/attachment_hand_L/handle.get_children().size() > 0: + weapon = $creature/body_parts/body/skeleton/attachment_hand_R/handle.get_children()[0] + return weapon + func attack(): - if self.can_attack: - var weapon = null - var attachment = null - weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item - attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].attachment - if not weapon: - weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item - attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].attachment - if not weapon: - weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item - attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].attachment - - if weapon: - print( "pan " + str(weapon.get_data( "damage" )) ) + if self.can_attack: + var weapon = null + var attachment = null + weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].item + attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_right ].attachment + if not weapon: + weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].item + attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hand_left ].attachment + if not weapon: + weapon = $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].item + attachment = $creature.slots[ Datas.Equipment.SLOT.weapon_hands ].attachment + + if weapon: + print( "pan " + str(weapon.get_data( "damage" )) ) - var weapon_node = $creature/body_parts/body/skeleton.get_node( attachment ) - if weapon_node: - weapon_node = weapon_node.get_node( "handle" ).get_children()[0] + var weapon_node = $creature/body_parts/body/skeleton.get_node( attachment ) + if weapon_node: + weapon_node = weapon_node.get_node( "handle" ).get_children()[0] # if weapon_node is preload( "res://scenes/items/equipments/weapons/firearm.gd" ): # weapon_node.fire( self, [self] ) # - self.can_attack = false - $attack_delay.start() - + self.can_attack = false + $attack_delay.start() + func hit( p_damage, p_from = null ): - $creature.creature.set_data( "current_life", $creature.creature.get_data( "current_life" )-p_damage ) - $head_infos_viewport/head_infos/bars/life.max_value = $creature.creature.get_max_life() - $head_infos_viewport/head_infos/bars/life.value = $creature.creature.get_data( "current_life", 0 ) - + $creature.creature.set_data( "current_life", $creature.creature.get_data( "current_life" )-p_damage ) + $head_infos_viewport/head_infos/bars/life.max_value = $creature.creature.get_max_life() + $head_infos_viewport/head_infos/bars/life.value = $creature.creature.get_data( "current_life", 0 ) + func die(): - self.is_dying = true - + self.is_dying = true + func _on_creature_equip(p_slot, p_item): - var weapons = self.get_weapons() - if weapons.size() > 0: - var max_delay = null - for weapon in weapons: - if not max_delay: - max_delay = weapon.get_data( "attack_delay" ) - else: - max_delay = max( max_delay, weapon.get_data( "attack_delay" ) ) - $attack_delay.wait_time = max_delay - emit_signal( "equip", p_slot, p_item ) + var weapons = self.get_weapons() + if weapons.size() > 0: + var max_delay = null + for weapon in weapons: + if not max_delay: + max_delay = weapon.get_data( "attack_delay" ) + else: + max_delay = max( max_delay, weapon.get_data( "attack_delay" ) ) + $attack_delay.wait_time = max_delay + emit_signal( "equip", p_slot, p_item ) func _on_creature_unequip(p_slot): - emit_signal( "unequip", p_slot ) + emit_signal( "unequip", p_slot ) func _on_attack_delay_timeout(): - self.can_attack = true + self.can_attack = true func _on_creature_is_dead(): - self.die() + self.die() diff --git a/scenes/connection/connection.gd b/scenes/connection/connection.gd index 21a1d77..0aa0764 100644 --- a/scenes/connection/connection.gd +++ b/scenes/connection/connection.gd @@ -4,31 +4,31 @@ signal connection_ok signal connection_error( message ) func do_request(username, password): - var message = load("res://ressources/scripts/nel/nel_login_message.gd") - if message: - message = message.nel_login_message.new("https-login", username, password, "Lirria", "2", "en"); - # $http_request.request("http://lirria.khaganat.net/login/r2_login.php?" + message.get_request_string()); - $http_request.request("http://149.91.80.160/login/r2_login.php?" + message.get_request_string()); + var message = load("res://ressources/scripts/nel/nel_login_message.gd") + if message: + message = message.nel_login_message.new("https-login", username, password, "Lirria", "2", "en"); + # $http_request.request("http://lirria.khaganat.net/login/r2_login.php?" + message.get_request_string()); + $http_request.request("http://149.91.80.160/login/r2_login.php?" + message.get_request_string()); func _make_post_request(url, data_to_send, use_ssl): - # Convert data to json string: - var query = JSON.print(data_to_send) - # Add 'Content-Type' header: - var headers = ["Content-Type: application/json"] - $http_request.request(url, headers, use_ssl, HTTPClient.METHOD_POST, query) + # Convert data to json string: + var query = JSON.print(data_to_send) + # Add 'Content-Type' header: + var headers = ["Content-Type: application/json"] + $http_request.request(url, headers, use_ssl, HTTPClient.METHOD_POST, query) func _on_http_request_request_completed(result, response_code, headers, body): - print( response_code ) - if ProjectSettings.get_setting("khanat/debug_mode"): - emit_signal( "connection_ok" ) - elif not response_code == 200: - emit_signal( "connection_error", "Erreur de connexion." ) - else: - var s = body.get_string_from_utf8().split(":") - if(s[0] != "0"): - var server_info_script = load("res://ressources/scripts/nel/nel_server_infos.gd"); - var server_info = server_info_script.nel_server_info.new(body.get_string_from_utf8()); - emit_signal( "connection_ok" ) - # No error so login was successful. + print( response_code ) + if ProjectSettings.get_setting("khanat/debug_mode"): + emit_signal( "connection_ok" ) + elif not response_code == 200: + emit_signal( "connection_error", "Erreur de connexion." ) + else: + var s = body.get_string_from_utf8().split(":") + if(s[0] != "0"): + var server_info_script = load("res://ressources/scripts/nel/nel_server_infos.gd"); + var server_info = server_info_script.nel_server_info.new(body.get_string_from_utf8()); + emit_signal( "connection_ok" ) + # No error so login was successful. diff --git a/scenes/creatures/creature.gd b/scenes/creatures/creature.gd index 8eccea3..fe73223 100644 --- a/scenes/creatures/creature.gd +++ b/scenes/creatures/creature.gd @@ -11,407 +11,407 @@ var eye_color_list = [ "blue_eye", "bluegreen_eye","brown_eye","deepblue_eye","g class Slot: - var item = null - var attachment = null - func _init( p_attachment = null ): - self.attachment = p_attachment + var item = null + var attachment = null + func _init( p_attachment = null ): + self.attachment = p_attachment var slots = { Datas.Equipment.SLOT.cloth_hand: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.cloth_face: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.cloth_head: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.cloth_torso: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.cloth_legs: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.cloth_feet: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.cloth_back: Slot.new( "cloths" )\ - , Datas.Equipment.SLOT.weapon_hand_right: Slot.new( "attachment_hand_R" )\ - , Datas.Equipment.SLOT.weapon_hand_left: Slot.new( "attachment_hand_L" )\ - , Datas.Equipment.SLOT.weapon_hands: Slot.new( "attachment_hand_R" )\ - , Datas.Equipment.SLOT.weapon_hip_right: Slot.new( "attachment_hips_R" )\ - , Datas.Equipment.SLOT.weapon_hip_left: Slot.new( "attachment_hips_L" )\ - , Datas.Equipment.SLOT.weapon_back_right: Slot.new()\ - , Datas.Equipment.SLOT.weapon_back_left: Slot.new()\ - , Datas.Equipment.SLOT.weapon_holster_right: Slot.new()\ - , Datas.Equipment.SLOT.weapon_holster_left: Slot.new() } + , Datas.Equipment.SLOT.cloth_face: Slot.new( "cloths" )\ + , Datas.Equipment.SLOT.cloth_head: Slot.new( "cloths" )\ + , Datas.Equipment.SLOT.cloth_torso: Slot.new( "cloths" )\ + , Datas.Equipment.SLOT.cloth_legs: Slot.new( "cloths" )\ + , Datas.Equipment.SLOT.cloth_feet: Slot.new( "cloths" )\ + , Datas.Equipment.SLOT.cloth_back: Slot.new( "cloths" )\ + , Datas.Equipment.SLOT.weapon_hand_right: Slot.new( "attachment_hand_R" )\ + , Datas.Equipment.SLOT.weapon_hand_left: Slot.new( "attachment_hand_L" )\ + , Datas.Equipment.SLOT.weapon_hands: Slot.new( "attachment_hand_R" )\ + , Datas.Equipment.SLOT.weapon_hip_right: Slot.new( "attachment_hips_R" )\ + , Datas.Equipment.SLOT.weapon_hip_left: Slot.new( "attachment_hips_L" )\ + , Datas.Equipment.SLOT.weapon_back_right: Slot.new()\ + , Datas.Equipment.SLOT.weapon_back_left: Slot.new()\ + , Datas.Equipment.SLOT.weapon_holster_right: Slot.new()\ + , Datas.Equipment.SLOT.weapon_holster_left: Slot.new() } func _ready(): - self.duplicate_meshes() + self.duplicate_meshes() func duplicate_meshes(): - for body in $body_parts.get_children(): - for mesh in body.get_node( "skeleton" ).get_children(): - if mesh is MeshInstance: - var new_mat = mesh.get( "material/0" ).duplicate() - var new_mesh = mesh.mesh.duplicate() - mesh.mesh = new_mesh - mesh.set( "material/0", new_mat ) - for body in $hair_parts.get_children(): - for mesh in body.get_node( "skeleton" ).get_children(): - if mesh is MeshInstance: - var new_mat = mesh.get( "material/0" ).duplicate() - var new_mesh = mesh.mesh.duplicate() - mesh.mesh = new_mesh - mesh.set( "material/0", new_mat ) - for body in $cloths.get_children(): - for mesh in body.get_node( "skeleton" ).get_children(): - if mesh is MeshInstance: - var new_mat = mesh.get( "material/0" ).duplicate() - var new_mesh = mesh.mesh.duplicate() - mesh.mesh = new_mesh - mesh.set( "material/0", new_mat ) - self.update() + for body in $body_parts.get_children(): + for mesh in body.get_node( "skeleton" ).get_children(): + if mesh is MeshInstance: + var new_mat = mesh.get( "material/0" ).duplicate() + var new_mesh = mesh.mesh.duplicate() + mesh.mesh = new_mesh + mesh.set( "material/0", new_mat ) + for body in $hair_parts.get_children(): + for mesh in body.get_node( "skeleton" ).get_children(): + if mesh is MeshInstance: + var new_mat = mesh.get( "material/0" ).duplicate() + var new_mesh = mesh.mesh.duplicate() + mesh.mesh = new_mesh + mesh.set( "material/0", new_mat ) + for body in $cloths.get_children(): + for mesh in body.get_node( "skeleton" ).get_children(): + if mesh is MeshInstance: + var new_mat = mesh.get( "material/0" ).duplicate() + var new_mesh = mesh.mesh.duplicate() + mesh.mesh = new_mesh + mesh.set( "material/0", new_mat ) + self.update() func set_blend_shape( p_blend_shape_name, p_value ): - for child in $body_parts.get_children(): - var skeleton = child.get_node( "skeleton" ) - for node in skeleton.get_children(): - if node is MeshInstance: - node.set( "blend_shapes/"+p_blend_shape_name, p_value ) - for child in $hair_parts.get_children(): - var skeleton = child.get_node( "skeleton" ) - for node in skeleton.get_children(): - if node is MeshInstance: - node.set( "blend_shapes/"+p_blend_shape_name, p_value ) - for child in $cloths.get_children(): - var skeleton = child.get_node( "skeleton" ) - for node in skeleton.get_children(): - if node is MeshInstance: - node.set( "blend_shapes/"+p_blend_shape_name, p_value ) + for child in $body_parts.get_children(): + var skeleton = child.get_node( "skeleton" ) + for node in skeleton.get_children(): + if node is MeshInstance: + node.set( "blend_shapes/"+p_blend_shape_name, p_value ) + for child in $hair_parts.get_children(): + var skeleton = child.get_node( "skeleton" ) + for node in skeleton.get_children(): + if node is MeshInstance: + node.set( "blend_shapes/"+p_blend_shape_name, p_value ) + for child in $cloths.get_children(): + var skeleton = child.get_node( "skeleton" ) + for node in skeleton.get_children(): + if node is MeshInstance: + node.set( "blend_shapes/"+p_blend_shape_name, p_value ) func load_from_name( p_name, p_emplacement = "usr" ): - var new_creature = Datas.Human.new() - var name_split = p_name.split( "_" ) - new_creature.set_data( "first_name", name_split[0] ) - new_creature.set_data( "last_name", name_split[1] ) - new_creature.load( null, p_emplacement ) - self.creature = new_creature - self.update() - + var new_creature = Datas.Human.new() + var name_split = p_name.split( "_" ) + new_creature.set_data( "first_name", name_split[0] ) + new_creature.set_data( "last_name", name_split[1] ) + new_creature.load( null, p_emplacement ) + self.creature = new_creature + self.update() + func update(): - - if self.creature: - - self.scale = Vector3( self.creature.get_data( "size" ), self.creature.get_data( "size" ), self.creature.get_data( "size" ) ) - - self.set_blend_shape( "caucasian", self.creature.get_data( "caucasian" ) ) - self.set_blend_shape( "african", self.creature.get_data( "african" ) ) - self.set_blend_shape( "asian", self.creature.get_data( "asian" ) ) - - if self.creature.get_data( "sex" ) == Globals.SEX.female: - if self.creature.get_data( "skin" ) == 0: - self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_female_diffuse.png" ) ) - elif self.creature.get_data( "skin" ) == 1: - self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_female_diffuse3.png" ) ) - elif self.creature.get_data( "skin" ) == 2: - self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_darkskinned_female_diffuse.png" ) ) - elif self.creature.get_data( "sex" ) == Globals.SEX.male: - if self.creature.get_data( "skin" ) == 0: - self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_male_diffuse2.png" ) ) - elif self.creature.get_data( "skin" ) == 1: - self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_male_diffuse3.png" ) ) - elif self.creature.get_data( "skin" ) == 2: - self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_darkskinned_male_diffuse.png" ) ) + + if self.creature: + + self.scale = Vector3( self.creature.get_data( "size" ), self.creature.get_data( "size" ), self.creature.get_data( "size" ) ) + + self.set_blend_shape( "caucasian", self.creature.get_data( "caucasian" ) ) + self.set_blend_shape( "african", self.creature.get_data( "african" ) ) + self.set_blend_shape( "asian", self.creature.get_data( "asian" ) ) + + if self.creature.get_data( "sex" ) == Globals.SEX.female: + if self.creature.get_data( "skin" ) == 0: + self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_female_diffuse.png" ) ) + elif self.creature.get_data( "skin" ) == 1: + self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_female_diffuse3.png" ) ) + elif self.creature.get_data( "skin" ) == 2: + self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_darkskinned_female_diffuse.png" ) ) + elif self.creature.get_data( "sex" ) == Globals.SEX.male: + if self.creature.get_data( "skin" ) == 0: + self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_male_diffuse2.png" ) ) + elif self.creature.get_data( "skin" ) == 1: + self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_lightskinned_male_diffuse3.png" ) ) + elif self.creature.get_data( "skin" ) == 2: + self.get_node( "body_parts/body/skeleton/body" ).get_surface_material( 0 ).set_shader_param( "texture_albedo", preload( "res://assets/creatures/human/textures/young_darkskinned_male_diffuse.png" ) ) - if self.creature.get_data( "sex" ) == Globals.SEX.female: - if self.creature.get_data( "hair" ) == 0: - self.get_node( "hair_parts/mh_human_female_hair" ).hide() - elif self.creature.get_data( "hair" ) == 1: - self.get_node( "hair_parts/mh_human_female_hair" ).show() - self.get_node( "hair_parts/mh_human_female_hair/skeleton/hair" ).get_surface_material( 0 ).albedo_texture = preload( "res://assets/creatures/human/textures/human_female_hair_001.png" ) - elif self.creature.get_data( "hair" ) == 2: - self.get_node( "hair_parts/mh_human_female_hair" ).show() - self.get_node( "hair_parts/mh_human_female_hair/skeleton/hair" ).get_surface_material( 0 ).albedo_texture = preload( "res://assets/creatures/human/textures/human_female_hair_002.png" ) - elif self.creature.get_data( "sex" ) == Globals.SEX.male: - if self.creature.get_data( "hair" ) == 0: - self.get_node( "hair_parts/mh_human_male_hair" ).hide() - elif self.creature.get_data( "hair" ) == 1: - self.get_node( "hair_parts/mh_human_male_hair" ).show() - self.get_node( "hair_parts/mh_human_male_hair/skeleton/hair" ).get_surface_material( 0 ).albedo_texture = preload( "res://assets/creatures/human/textures/human_male_hair.png" ) - - - for hair in $hair_parts.get_children(): - if hair.has_node( "skeleton/hair" ) and hair.get_node( "skeleton/hair" ).get_surface_material( 0 ): - hair.get_node( "skeleton/hair" ).get_surface_material( 0 ).albedo_color = self.creature.get_data( "hair_color" ) + if self.creature.get_data( "sex" ) == Globals.SEX.female: + if self.creature.get_data( "hair" ) == 0: + self.get_node( "hair_parts/mh_human_female_hair" ).hide() + elif self.creature.get_data( "hair" ) == 1: + self.get_node( "hair_parts/mh_human_female_hair" ).show() + self.get_node( "hair_parts/mh_human_female_hair/skeleton/hair" ).get_surface_material( 0 ).albedo_texture = preload( "res://assets/creatures/human/textures/human_female_hair_001.png" ) + elif self.creature.get_data( "hair" ) == 2: + self.get_node( "hair_parts/mh_human_female_hair" ).show() + self.get_node( "hair_parts/mh_human_female_hair/skeleton/hair" ).get_surface_material( 0 ).albedo_texture = preload( "res://assets/creatures/human/textures/human_female_hair_002.png" ) + elif self.creature.get_data( "sex" ) == Globals.SEX.male: + if self.creature.get_data( "hair" ) == 0: + self.get_node( "hair_parts/mh_human_male_hair" ).hide() + elif self.creature.get_data( "hair" ) == 1: + self.get_node( "hair_parts/mh_human_male_hair" ).show() + self.get_node( "hair_parts/mh_human_male_hair/skeleton/hair" ).get_surface_material( 0 ).albedo_texture = preload( "res://assets/creatures/human/textures/human_male_hair.png" ) + + + for hair in $hair_parts.get_children(): + if hair.has_node( "skeleton/hair" ) and hair.get_node( "skeleton/hair" ).get_surface_material( 0 ): + hair.get_node( "skeleton/hair" ).get_surface_material( 0 ).albedo_color = self.creature.get_data( "hair_color" ) - - if self.creature.get_data( "muscles" ) > 0.0: - self.set_blend_shape( "muscles_min", 0.0 ) - self.set_blend_shape( "muscles_max", self.creature.get_data( "muscles" ) ) - elif self.creature.get_data( "muscles" ) < 0.0: - self.set_blend_shape( "muscles_min", -self.creature.get_data( "muscles" ) ) - self.set_blend_shape( "muscles_max", 0.0 ) - else: - self.set_blend_shape( "muscles_min", 0.0 ) - self.set_blend_shape( "muscles_max", 0.0 ) - - if self.creature.get_data( "fat" ) > 0.0: - self.set_blend_shape( "fat_min", 0.0 ) - self.set_blend_shape( "fat_max", self.creature.get_data( "fat" ) ) - elif self.creature.get_data( "fat" ) < 0.0: - self.set_blend_shape( "fat_min", -self.creature.get_data( "fat" ) ) - self.set_blend_shape( "fat_max", 0.0 ) - else: - self.set_blend_shape( "fat_min", 0.0 ) - self.set_blend_shape( "fat_max", 0.0 ) - - if self.creature.get_data( "proportion" ) > 0.0: - self.set_blend_shape( "proportion_min", 0.0 ) - self.set_blend_shape( "proportion_max", self.creature.get_data( "proportion" ) ) - elif self.creature.get_data( "proportion" ) < 0.0: - self.set_blend_shape( "proportion_min", -self.creature.get_data( "proportion" ) ) - self.set_blend_shape( "proportion_max", 0.0 ) - else: - self.set_blend_shape( "proportion_min", 0.0 ) - self.set_blend_shape( "proportion_max", 0.0 ) - - if self.creature.get_data( "breast" ) > 0.0: - self.set_blend_shape( "breast_min", 0.0 ) - self.set_blend_shape( "breast_max", self.creature.get_data( "breast" ) ) - elif self.creature.get_data( "breast" ) < 0.0: - self.set_blend_shape( "breast_min", -self.creature.get_data( "breast" ) ) - self.set_blend_shape( "breast_max", 0.0 ) - else: - self.set_blend_shape( "breast_min", 0.0 ) - self.set_blend_shape( "breast_max", 0.0 ) + + if self.creature.get_data( "muscles" ) > 0.0: + self.set_blend_shape( "muscles_min", 0.0 ) + self.set_blend_shape( "muscles_max", self.creature.get_data( "muscles" ) ) + elif self.creature.get_data( "muscles" ) < 0.0: + self.set_blend_shape( "muscles_min", -self.creature.get_data( "muscles" ) ) + self.set_blend_shape( "muscles_max", 0.0 ) + else: + self.set_blend_shape( "muscles_min", 0.0 ) + self.set_blend_shape( "muscles_max", 0.0 ) + + if self.creature.get_data( "fat" ) > 0.0: + self.set_blend_shape( "fat_min", 0.0 ) + self.set_blend_shape( "fat_max", self.creature.get_data( "fat" ) ) + elif self.creature.get_data( "fat" ) < 0.0: + self.set_blend_shape( "fat_min", -self.creature.get_data( "fat" ) ) + self.set_blend_shape( "fat_max", 0.0 ) + else: + self.set_blend_shape( "fat_min", 0.0 ) + self.set_blend_shape( "fat_max", 0.0 ) + + if self.creature.get_data( "proportion" ) > 0.0: + self.set_blend_shape( "proportion_min", 0.0 ) + self.set_blend_shape( "proportion_max", self.creature.get_data( "proportion" ) ) + elif self.creature.get_data( "proportion" ) < 0.0: + self.set_blend_shape( "proportion_min", -self.creature.get_data( "proportion" ) ) + self.set_blend_shape( "proportion_max", 0.0 ) + else: + self.set_blend_shape( "proportion_min", 0.0 ) + self.set_blend_shape( "proportion_max", 0.0 ) + + if self.creature.get_data( "breast" ) > 0.0: + self.set_blend_shape( "breast_min", 0.0 ) + self.set_blend_shape( "breast_max", self.creature.get_data( "breast" ) ) + elif self.creature.get_data( "breast" ) < 0.0: + self.set_blend_shape( "breast_min", -self.creature.get_data( "breast" ) ) + self.set_blend_shape( "breast_max", 0.0 ) + else: + self.set_blend_shape( "breast_min", 0.0 ) + self.set_blend_shape( "breast_max", 0.0 ) - if self.creature.get_data( "sex" ) == Globals.SEX.female: - self.set_blend_shape( "pregnancy", self.creature.get_data( "pregnancy" ) ) - - # Skin tone. - if self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ) and self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ) is ShaderMaterial: - var color = self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ).get_shader_param( "albedo" ) - color.v = 1.0 - self.creature.get_data( "skin_tone" ) - self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ).set_shader_param( "albedo", color ) + if self.creature.get_data( "sex" ) == Globals.SEX.female: + self.set_blend_shape( "pregnancy", self.creature.get_data( "pregnancy" ) ) + + # Skin tone. + if self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ) and self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ) is ShaderMaterial: + var color = self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ).get_shader_param( "albedo" ) + color.v = 1.0 - self.creature.get_data( "skin_tone" ) + self.get_node( "body_parts/body/skeleton/body" ).get( "material/0" ).set_shader_param( "albedo", color ) - self.set_blend_shape( "cleft_chin", self.creature.get_data( "cleft_chin" ) ) - self.set_blend_shape( "chin_angle", self.creature.get_data( "chin_angle" ) ) - - if self.creature.get_data( "mouth_horiz" ) > 0.0: - self.set_blend_shape( "mouth_horiz_min", 0.0 ) - self.set_blend_shape( "mouth_horiz_max", self.creature.get_data( "mouth_horiz" ) ) - elif self.creature.get_data( "mouth_horiz" ) < 0.0: - self.set_blend_shape( "mouth_horiz_min", -self.creature.get_data( "mouth_horiz" ) ) - self.set_blend_shape( "mouth_horiz_max", 0.0 ) - else: - self.set_blend_shape( "mouth_horiz_min", 0.0 ) - self.set_blend_shape( "mouth_horiz_max", 0.0 ) - - if self.creature.get_data( "mouth_vert" ) > 0.0: - self.set_blend_shape( "mouth_vert_min", 0.0 ) - self.set_blend_shape( "mouth_vert_max", self.creature.get_data( "mouth_vert" ) ) - elif self.creature.get_data( "mouth_vert" ) < 0.0: - self.set_blend_shape( "mouth_vert_min", -self.creature.get_data( "mouth_vert" ) ) - self.set_blend_shape( "mouth_vert_max", 0.0 ) - else: - self.set_blend_shape( "mouth_vert_min", 0.0 ) - self.set_blend_shape( "mouth_vert_max", 0.0 ) - - if self.creature.get_data( "nose_galbe" ) > 0.0: - self.set_blend_shape( "nose_galbe_min", 0.0 ) - self.set_blend_shape( "nose_galbe_max", self.creature.get_data( "nose_galbe" ) ) - elif self.creature.get_data( "nose_galbe" ) < 0.0: - self.set_blend_shape( "nose_galbe_min", -self.creature.get_data( "nose_galbe" ) ) - self.set_blend_shape( "nose_galbe_max", 0.0 ) - else: - self.set_blend_shape( "nose_galbe_min", 0.0 ) - self.set_blend_shape( "nose_galbe_max", 0.0 ) - - if self.creature.get_data( "nose_grec" ) > 0.0: - self.set_blend_shape( "nose_grec_min", 0.0 ) - self.set_blend_shape( "nose_grec_max", self.creature.get_data( "nose_grec" ) ) - elif self.creature.get_data( "nose_grec" ) < 0.0: - self.set_blend_shape( "nose_grec_min", -self.creature.get_data( "nose_grec" ) ) - self.set_blend_shape( "nose_grec_max", 0.0 ) - else: - self.set_blend_shape( "nose_grec_min", 0.0 ) - self.set_blend_shape( "nose_grec_max", 0.0 ) - - if self.creature.get_data( "nose_horiz" ) > 0.0: - self.set_blend_shape( "nose_horiz_min", 0.0 ) - self.set_blend_shape( "nose_horiz_max", self.creature.get_data( "nose_horiz" ) ) - elif self.creature.get_data( "nose_horiz" ) < 0.0: - self.set_blend_shape( "nose_horiz_min", -self.creature.get_data( "nose_horiz" ) ) - self.set_blend_shape( "nose_horiz_max", 0.0 ) - else: - self.set_blend_shape( "nose_horiz_min", 0.0 ) - self.set_blend_shape( "nose_horiz_max", 0.0 ) - - if self.creature.get_data( "nose_depth" ) > 0.0: - self.set_blend_shape( "nose_depth_min", 0.0 ) - self.set_blend_shape( "nose_depth_max", self.creature.get_data( "nose_depth" ) ) - elif self.creature.get_data( "nose_depth" ) < 0.0: - self.set_blend_shape( "nose_depth_min", -self.creature.get_data( "nose_depth" ) ) - self.set_blend_shape( "nose_depth_max", 0.0 ) - else: - self.set_blend_shape( "nose_depth_min", 0.0 ) - self.set_blend_shape( "nose_depth_max", 0.0 ) - - - self.get_node( "body_parts/body/skeleton/eyes" ).get_surface_material( 0 ).albedo_texture = load( "res://assets/creatures/human/textures/"+self.eye_color_list[ self.creature.get_data( "eyes_color", 0 ) ]+".png" ) - - if self.creature.get_data( "eyes_vert" ) > 0.0: - self.set_blend_shape( "eyes_vert_min", 0.0 ) - self.set_blend_shape( "eyes_vert_max", self.creature.get_data( "eyes_vert" ) ) - elif self.creature.get_data( "eyes_vert" ) < 0.0: - self.set_blend_shape( "eyes_vert_min", -self.creature.get_data( "eyes_vert" ) ) - self.set_blend_shape( "eyes_vert_max", 0.0 ) - else: - self.set_blend_shape( "eyes_vert_min", 0.0 ) - self.set_blend_shape( "eyes_vert_max", 0.0 ) - - if self.creature.get_data( "eyes_gap" ) > 0.0: - self.set_blend_shape( "eyes_gap_min", 0.0 ) - self.set_blend_shape( "eyes_gap_max", self.creature.get_data( "eyes_gap" ) ) - elif self.creature.get_data( "eyes_gap" ) < 0.0: - self.set_blend_shape( "eyes_gap_min", -self.creature.get_data( "eyes_gap" ) ) - self.set_blend_shape( "eyes_gap_max", 0.0 ) - else: - self.set_blend_shape( "eyes_gap_min", 0.0 ) - self.set_blend_shape( "eyes_gap_max", 0.0 ) - - self.set_blend_shape( "earlobes", self.creature.get_data( "earlobes" ) ) - self.set_blend_shape( "ears_wing", self.creature.get_data( "ears_wing" ) ) - - if self.creature.get_data( "lips_up_shape" ) > 0.0: - self.set_blend_shape( "lips_up_shape_min", 0.0 ) - self.set_blend_shape( "lips_up_shape_max", self.creature.get_data( "lips_up_shape" ) ) - elif self.creature.get_data( "lips_up_shape" ) < 0.0: - self.set_blend_shape( "lips_up_shape_min", -self.creature.get_data( "lips_up_shape" ) ) - self.set_blend_shape( "lips_up_shape_max", 0.0 ) - else: - self.set_blend_shape( "lips_up_shape_min", 0.0 ) - self.set_blend_shape( "lips_up_shape_max", 0.0 ) - - if self.creature.get_data( "lips_up_shape_2" ) > 0.0: - self.set_blend_shape( "lips_up_shape_2_min", 0.0 ) - self.set_blend_shape( "lips_up_shape_2_max", self.creature.get_data( "lips_up_shape_2" ) ) - elif self.creature.get_data( "lips_up_shape_2" ) < 0.0: - self.set_blend_shape( "lips_up_shape_2_min", -self.creature.get_data( "lips_up_shape_2" ) ) - self.set_blend_shape( "lips_up_shape_2_max", 0.0 ) - else: - self.set_blend_shape( "lips_up_shape_2_min", 0.0 ) - self.set_blend_shape( "lips_up_shape_2_max", 0.0 ) - - self.set_blend_shape( "nipple_flat", 1.0 ) - - - + self.set_blend_shape( "cleft_chin", self.creature.get_data( "cleft_chin" ) ) + self.set_blend_shape( "chin_angle", self.creature.get_data( "chin_angle" ) ) + + if self.creature.get_data( "mouth_horiz" ) > 0.0: + self.set_blend_shape( "mouth_horiz_min", 0.0 ) + self.set_blend_shape( "mouth_horiz_max", self.creature.get_data( "mouth_horiz" ) ) + elif self.creature.get_data( "mouth_horiz" ) < 0.0: + self.set_blend_shape( "mouth_horiz_min", -self.creature.get_data( "mouth_horiz" ) ) + self.set_blend_shape( "mouth_horiz_max", 0.0 ) + else: + self.set_blend_shape( "mouth_horiz_min", 0.0 ) + self.set_blend_shape( "mouth_horiz_max", 0.0 ) + + if self.creature.get_data( "mouth_vert" ) > 0.0: + self.set_blend_shape( "mouth_vert_min", 0.0 ) + self.set_blend_shape( "mouth_vert_max", self.creature.get_data( "mouth_vert" ) ) + elif self.creature.get_data( "mouth_vert" ) < 0.0: + self.set_blend_shape( "mouth_vert_min", -self.creature.get_data( "mouth_vert" ) ) + self.set_blend_shape( "mouth_vert_max", 0.0 ) + else: + self.set_blend_shape( "mouth_vert_min", 0.0 ) + self.set_blend_shape( "mouth_vert_max", 0.0 ) + + if self.creature.get_data( "nose_galbe" ) > 0.0: + self.set_blend_shape( "nose_galbe_min", 0.0 ) + self.set_blend_shape( "nose_galbe_max", self.creature.get_data( "nose_galbe" ) ) + elif self.creature.get_data( "nose_galbe" ) < 0.0: + self.set_blend_shape( "nose_galbe_min", -self.creature.get_data( "nose_galbe" ) ) + self.set_blend_shape( "nose_galbe_max", 0.0 ) + else: + self.set_blend_shape( "nose_galbe_min", 0.0 ) + self.set_blend_shape( "nose_galbe_max", 0.0 ) + + if self.creature.get_data( "nose_grec" ) > 0.0: + self.set_blend_shape( "nose_grec_min", 0.0 ) + self.set_blend_shape( "nose_grec_max", self.creature.get_data( "nose_grec" ) ) + elif self.creature.get_data( "nose_grec" ) < 0.0: + self.set_blend_shape( "nose_grec_min", -self.creature.get_data( "nose_grec" ) ) + self.set_blend_shape( "nose_grec_max", 0.0 ) + else: + self.set_blend_shape( "nose_grec_min", 0.0 ) + self.set_blend_shape( "nose_grec_max", 0.0 ) + + if self.creature.get_data( "nose_horiz" ) > 0.0: + self.set_blend_shape( "nose_horiz_min", 0.0 ) + self.set_blend_shape( "nose_horiz_max", self.creature.get_data( "nose_horiz" ) ) + elif self.creature.get_data( "nose_horiz" ) < 0.0: + self.set_blend_shape( "nose_horiz_min", -self.creature.get_data( "nose_horiz" ) ) + self.set_blend_shape( "nose_horiz_max", 0.0 ) + else: + self.set_blend_shape( "nose_horiz_min", 0.0 ) + self.set_blend_shape( "nose_horiz_max", 0.0 ) + + if self.creature.get_data( "nose_depth" ) > 0.0: + self.set_blend_shape( "nose_depth_min", 0.0 ) + self.set_blend_shape( "nose_depth_max", self.creature.get_data( "nose_depth" ) ) + elif self.creature.get_data( "nose_depth" ) < 0.0: + self.set_blend_shape( "nose_depth_min", -self.creature.get_data( "nose_depth" ) ) + self.set_blend_shape( "nose_depth_max", 0.0 ) + else: + self.set_blend_shape( "nose_depth_min", 0.0 ) + self.set_blend_shape( "nose_depth_max", 0.0 ) + + + self.get_node( "body_parts/body/skeleton/eyes" ).get_surface_material( 0 ).albedo_texture = load( "res://assets/creatures/human/textures/"+self.eye_color_list[ self.creature.get_data( "eyes_color", 0 ) ]+".png" ) + + if self.creature.get_data( "eyes_vert" ) > 0.0: + self.set_blend_shape( "eyes_vert_min", 0.0 ) + self.set_blend_shape( "eyes_vert_max", self.creature.get_data( "eyes_vert" ) ) + elif self.creature.get_data( "eyes_vert" ) < 0.0: + self.set_blend_shape( "eyes_vert_min", -self.creature.get_data( "eyes_vert" ) ) + self.set_blend_shape( "eyes_vert_max", 0.0 ) + else: + self.set_blend_shape( "eyes_vert_min", 0.0 ) + self.set_blend_shape( "eyes_vert_max", 0.0 ) + + if self.creature.get_data( "eyes_gap" ) > 0.0: + self.set_blend_shape( "eyes_gap_min", 0.0 ) + self.set_blend_shape( "eyes_gap_max", self.creature.get_data( "eyes_gap" ) ) + elif self.creature.get_data( "eyes_gap" ) < 0.0: + self.set_blend_shape( "eyes_gap_min", -self.creature.get_data( "eyes_gap" ) ) + self.set_blend_shape( "eyes_gap_max", 0.0 ) + else: + self.set_blend_shape( "eyes_gap_min", 0.0 ) + self.set_blend_shape( "eyes_gap_max", 0.0 ) + + self.set_blend_shape( "earlobes", self.creature.get_data( "earlobes" ) ) + self.set_blend_shape( "ears_wing", self.creature.get_data( "ears_wing" ) ) + + if self.creature.get_data( "lips_up_shape" ) > 0.0: + self.set_blend_shape( "lips_up_shape_min", 0.0 ) + self.set_blend_shape( "lips_up_shape_max", self.creature.get_data( "lips_up_shape" ) ) + elif self.creature.get_data( "lips_up_shape" ) < 0.0: + self.set_blend_shape( "lips_up_shape_min", -self.creature.get_data( "lips_up_shape" ) ) + self.set_blend_shape( "lips_up_shape_max", 0.0 ) + else: + self.set_blend_shape( "lips_up_shape_min", 0.0 ) + self.set_blend_shape( "lips_up_shape_max", 0.0 ) + + if self.creature.get_data( "lips_up_shape_2" ) > 0.0: + self.set_blend_shape( "lips_up_shape_2_min", 0.0 ) + self.set_blend_shape( "lips_up_shape_2_max", self.creature.get_data( "lips_up_shape_2" ) ) + elif self.creature.get_data( "lips_up_shape_2" ) < 0.0: + self.set_blend_shape( "lips_up_shape_2_min", -self.creature.get_data( "lips_up_shape_2" ) ) + self.set_blend_shape( "lips_up_shape_2_max", 0.0 ) + else: + self.set_blend_shape( "lips_up_shape_2_min", 0.0 ) + self.set_blend_shape( "lips_up_shape_2_max", 0.0 ) + + self.set_blend_shape( "nipple_flat", 1.0 ) + + + func play( anim_name, speed = 1.0 ): - for child in $body_parts.get_children(): - child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed - if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): - child.get_node( "skeleton/AnimationPlayer" ).play( anim_name ) - for child in $hair_parts.get_children(): - child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed - if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): - child.get_node( "skeleton/AnimationPlayer" ).play( anim_name ) - for child in $cloths.get_children(): - child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed - if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): - child.get_node( "skeleton/AnimationPlayer" ).play( anim_name ) - + for child in $body_parts.get_children(): + child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed + if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): + child.get_node( "skeleton/AnimationPlayer" ).play( anim_name ) + for child in $hair_parts.get_children(): + child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed + if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): + child.get_node( "skeleton/AnimationPlayer" ).play( anim_name ) + for child in $cloths.get_children(): + child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed + if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): + child.get_node( "skeleton/AnimationPlayer" ).play( anim_name ) + func play_backwards( anim_name, speed = 1.0 ): - for child in $body_parts.get_children(): - child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed - if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): - child.get_node( "skeleton/AnimationPlayer" ).play_backwards( anim_name ) - for child in $hair_parts.get_children(): - child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed - if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): - child.get_node( "skeleton/AnimationPlayer" ).play_backwards( anim_name ) - for child in $cloths.get_children(): - child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed - if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): - child.get_node( "skeleton/AnimationPlayer" ).play_backwards( anim_name ) + for child in $body_parts.get_children(): + child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed + if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): + child.get_node( "skeleton/AnimationPlayer" ).play_backwards( anim_name ) + for child in $hair_parts.get_children(): + child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed + if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): + child.get_node( "skeleton/AnimationPlayer" ).play_backwards( anim_name ) + for child in $cloths.get_children(): + child.get_node( "skeleton/AnimationPlayer" ).playback_speed = speed + if child.get_node( "skeleton/AnimationPlayer" ).has_animation( anim_name ): + child.get_node( "skeleton/AnimationPlayer" ).play_backwards( anim_name ) func can_turn(): - var animation_player = $body_parts/body/skeleton/AnimationPlayer - return (animation_player.current_animation.begins_with( "turn_") and animation_player.current_animation_position >= 1.2) or (not animation_player.current_animation.begins_with( "turn_") and not animation_player.current_animation.begins_with( "idle")) + var animation_player = $body_parts/body/skeleton/AnimationPlayer + return (animation_player.current_animation.begins_with( "turn_") and animation_player.current_animation_position >= 1.2) or (not animation_player.current_animation.begins_with( "turn_") and not animation_player.current_animation.begins_with( "idle")) func equip( p_item, p_slot = null ): - var model = load( p_item.get_data( "model_equiped", "") ) - if not model: - model = load( p_item.get_data( "model", "") ) - if model: - model = model.instance() - var attachment = null - if not p_slot: - p_slot = p_item.get_data( "default_slot" ) - if p_slot and int(p_slot) in self.slots: - self.unequip( p_slot ) - attachment = self.slots[ int(p_slot) ].attachment - self.slots[ int(p_slot) ].item = p_item - if attachment: - if attachment == "cloths": - model.name = str(int(p_slot)) - $cloths.add_child( model ) - var animation = $body_parts/body/skeleton/AnimationPlayer.current_animation - var animation_position = $body_parts/body/skeleton/AnimationPlayer.current_animation_position - var animation_speed = $body_parts/body/skeleton/AnimationPlayer.playback_speed - model.get_node( "skeleton/AnimationPlayer" ).stop() - model.get_node( "skeleton/AnimationPlayer" ).set( "playback_speed", animation_speed ) - model.get_node( "skeleton/AnimationPlayer" ).play( animation ) - model.get_node( "skeleton/AnimationPlayer" ).advance( animation_position ) - else: - if $body_parts/body/skeleton.has_node( attachment ): - $body_parts/body/skeleton.get_node( attachment ).get_node( "handle" ).add_child( model ) - - emit_signal( "equip", int(p_slot), p_item ) + var model = load( p_item.get_data( "model_equiped", "") ) + if not model: + model = load( p_item.get_data( "model", "") ) + if model: + model = model.instance() + var attachment = null + if not p_slot: + p_slot = p_item.get_data( "default_slot" ) + if p_slot and int(p_slot) in self.slots: + self.unequip( p_slot ) + attachment = self.slots[ int(p_slot) ].attachment + self.slots[ int(p_slot) ].item = p_item + if attachment: + if attachment == "cloths": + model.name = str(int(p_slot)) + $cloths.add_child( model ) + var animation = $body_parts/body/skeleton/AnimationPlayer.current_animation + var animation_position = $body_parts/body/skeleton/AnimationPlayer.current_animation_position + var animation_speed = $body_parts/body/skeleton/AnimationPlayer.playback_speed + model.get_node( "skeleton/AnimationPlayer" ).stop() + model.get_node( "skeleton/AnimationPlayer" ).set( "playback_speed", animation_speed ) + model.get_node( "skeleton/AnimationPlayer" ).play( animation ) + model.get_node( "skeleton/AnimationPlayer" ).advance( animation_position ) + else: + if $body_parts/body/skeleton.has_node( attachment ): + $body_parts/body/skeleton.get_node( attachment ).get_node( "handle" ).add_child( model ) + + emit_signal( "equip", int(p_slot), p_item ) func unequip( p_slot ): - if p_slot and int(p_slot) in self.slots: - if self.slots[ int(p_slot) ].item: - var attachment = self.slots[ int(p_slot) ].attachment - self.slots[ int(p_slot) ].item = null - if attachment: - if attachment == "cloths": - var node = $cloths.get_node( str(p_slot) ) - if node: - $cloths.remove_child( node ) - node.queue_free() - else: - for child in $body_parts/body/skeleton.get_node( attachment ).get_node( "handle" ).get_children(): - $body_parts/body/skeleton.get_node( attachment ).get_node( "handle" ).remove_child( child ) - child.queue_free() - emit_signal( "unequip", int(p_slot) ) - - + if p_slot and int(p_slot) in self.slots: + if self.slots[ int(p_slot) ].item: + var attachment = self.slots[ int(p_slot) ].attachment + self.slots[ int(p_slot) ].item = null + if attachment: + if attachment == "cloths": + var node = $cloths.get_node( str(p_slot) ) + if node: + $cloths.remove_child( node ) + node.queue_free() + else: + for child in $body_parts/body/skeleton.get_node( attachment ).get_node( "handle" ).get_children(): + $body_parts/body/skeleton.get_node( attachment ).get_node( "handle" ).remove_child( child ) + child.queue_free() + emit_signal( "unequip", int(p_slot) ) + + func drop_item( p_item ): - var new_inventory = self.creature.get_data( "inventory" ) - var item_index = new_inventory.find( p_item ) - if item_index != -1: - if new_inventory[ item_index ].get_data( "dropable", true ): - new_inventory[ item_index ].set_data( "number", new_inventory[ item_index ].get_data( "number" )-1 ) + var new_inventory = self.creature.get_data( "inventory" ) + var item_index = new_inventory.find( p_item ) + if item_index != -1: + if new_inventory[ item_index ].get_data( "dropable", true ): + new_inventory[ item_index ].set_data( "number", new_inventory[ item_index ].get_data( "number" )-1 ) - if new_inventory[ item_index ].get_data( "number" ) <= 0: - new_inventory.remove( item_index ) + if new_inventory[ item_index ].get_data( "number" ) <= 0: + new_inventory.remove( item_index ) - var pickup_item_node = preload( "res://scenes/items/pickup_item.tscn" ).instance() - pickup_item_node.item_filename = p_item.get_filename() - pickup_item_node.global_transform = $drop_point.global_transform + var pickup_item_node = preload( "res://scenes/items/pickup_item.tscn" ).instance() + pickup_item_node.item_filename = p_item.get_filename() + pickup_item_node.global_transform = $drop_point.global_transform - var pickup_item = Datas.PickupItem.new( p_item.get_filename(), $drop_point.global_transform, p_item ) - pickup_item_node.item = pickup_item - - if self.get_tree().get_root().has_node( "main/scene/game" ): - self.get_tree().get_root().get_node( "main/scene/game" ).get_node( "pickups" ).add_child( pickup_item_node ) - - + var pickup_item = Datas.PickupItem.new( p_item.get_filename(), $drop_point.global_transform, p_item ) + pickup_item_node.item = pickup_item + + if self.get_tree().get_root().has_node( "main/scene/game" ): + self.get_tree().get_root().get_node( "main/scene/game" ).get_node( "pickups" ).add_child( pickup_item_node ) + + func _on_body_animation_finished( anim_name ): - emit_signal( "animation_finished", anim_name ) + emit_signal( "animation_finished", anim_name ) func _on_body_limb_body_entered(limb, body): - if body.is_in_group( "bullet" ): - if limb == Datas.Cloth.LIMB.head: - var blood_particle = preload( "res://scenes/fx/blood_particles.tscn" ).instance() - $body_parts/body/skeleton/limb_head.add_child( blood_particle ) - blood_particle.emit() - emit_signal( "is_dead" ) - self.creature.set_data( "current_life", 0.0 ) - else: - var blood_particle = preload( "res://scenes/fx/blood_particles.tscn" ).instance() - $body_parts/body/skeleton/limb_torso_1.add_child( blood_particle ) - blood_particle.emit() + if body.is_in_group( "bullet" ): + if limb == Datas.Cloth.LIMB.head: + var blood_particle = preload( "res://scenes/fx/blood_particles.tscn" ).instance() + $body_parts/body/skeleton/limb_head.add_child( blood_particle ) + blood_particle.emit() + emit_signal( "is_dead" ) + self.creature.set_data( "current_life", 0.0 ) + else: + var blood_particle = preload( "res://scenes/fx/blood_particles.tscn" ).instance() + $body_parts/body/skeleton/limb_torso_1.add_child( blood_particle ) + blood_particle.emit() diff --git a/scenes/creatures/ra/ra_model.gd b/scenes/creatures/ra/ra_model.gd index 3328b43..6e3a6da 100644 --- a/scenes/creatures/ra/ra_model.gd +++ b/scenes/creatures/ra/ra_model.gd @@ -16,28 +16,28 @@ var is_moving: = false setget set_is_moving func _ready() -> void: - animation_tree.active = true + animation_tree.active = true func set_move_direction(direction: Vector3) -> void: - move_direction = direction - animation_tree["parameters/walk/blend_position"] = direction.length() + move_direction = direction + animation_tree["parameters/walk/blend_position"] = direction.length() func set_is_moving(value: bool) -> void: - is_moving = value + is_moving = value # animation_tree["parameters/conditions/is_moving"] = value func transition_to(state_id: int) -> void: - match state_id: - States.IDLE: - _playback.travel("idle") - States.LAND: - _playback.travel("land") - States.RUN: - _playback.travel("walk") - States.AIR: - _playback.travel("jump") - _: - _playback.travel("idle") + match state_id: + States.IDLE: + _playback.travel("idle") + States.LAND: + _playback.travel("land") + States.RUN: + _playback.travel("walk") + States.AIR: + _playback.travel("jump") + _: + _playback.travel("idle") diff --git a/scenes/game/game.gd b/scenes/game/game.gd index c6c2a21..3d2ce33 100644 --- a/scenes/game/game.gd +++ b/scenes/game/game.gd @@ -15,28 +15,28 @@ var heightmap = null var is_on_ui = false func _ready(): - - var player_ra = Ra.new() - var file = File.new() - if file.open("res://ressources/files/creatures/test.creature", File.READ) == OK: - player_ra.from_dict( JSON.parse( file.get_as_text() ).result ) + + var player_ra = Ra.new() + var file = File.new() + if file.open("res://ressources/files/creatures/test.creature", File.READ) == OK: + player_ra.from_dict( JSON.parse( file.get_as_text() ).result ) - $game_ui/inventory_window.get_content_child( "content_box/inventory_box" ).set_inventory( player_ra.inventory ) + $game_ui/inventory_window.get_content_child( "content_box/inventory_box" ).set_inventory( player_ra.inventory ) func _input( event ): - + # if event.is_action_released( "menu_pause" ): # Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) # $screen_box/windows/inventory_window.hide() # $screen_box/pause_menu.show() # self.get_tree().paused = true - - if event.is_action_pressed( "ui_show_head_infos" ): - $creatures/player/character/head_infos_frame.visible = not $player/character/head_infos_frame.visible - for npc in $creatures/npcs.get_children(): - npc.get_node( "head_infos_frame" ).visible = not npc.get_node( "head_infos_frame" ).visible + + if event.is_action_pressed( "ui_show_head_infos" ): + $creatures/player/character/head_infos_frame.visible = not $player/character/head_infos_frame.visible + for npc in $creatures/npcs.get_children(): + npc.get_node( "head_infos_frame" ).visible = not npc.get_node( "head_infos_frame" ).visible # @@ -88,9 +88,9 @@ func _input( event ): # else: # $game_ui/inventory_window.hide() # - + func _process( delta ): - + # $creatures/player.rotate_camera_arm( Vector3( 0.0, 1.0, 0.0 ), deg2rad( self.mouse_delta.x ) ) # # $creatures/player.move_camera( Vector3( 0.0, 0.0, camera_zoom ) ) @@ -99,44 +99,44 @@ func _process( delta ): # self.camera_zoom = 0.0 # self.mouse_delta = Vector2( 0.0, 0.0 ) - # Water fx. - if $creatures/player/character.global_transform.origin.y <= ($level/demo/water.translation.y-2.5): - $water_fx.get_surface_material( 0 ).set_shader_param( "mist_level", 1.0 ) - else: - $water_fx.get_surface_material( 0 ).set_shader_param( "mist_level", 0.0 ) + # Water fx. + if $creatures/player/character.global_transform.origin.y <= ($level/demo/water.translation.y-2.5): + $water_fx.get_surface_material( 0 ).set_shader_param( "mist_level", 1.0 ) + else: + $water_fx.get_surface_material( 0 ).set_shader_param( "mist_level", 0.0 ) - var trauma_value = ($game_ui/stats_window.get_content_child( "trauma" ).value / 6.0) - $trauma_fx.get_surface_material( 0 ).set_shader_param( "mist_level", trauma_value ) + var trauma_value = ($game_ui/stats_window.get_content_child( "trauma" ).value / 6.0) + $trauma_fx.get_surface_material( 0 ).set_shader_param( "mist_level", trauma_value ) - $sky/viewport/sky.day_time_hours += delta*((6.0/24.0)/3600.0) - if $sky/viewport/sky.day_time_hours >= 24.0: - $sky/viewport/sky.day_time_hours = $sky/viewport/sky.day_time_hours-24.0 + $sky/viewport/sky.day_time_hours += delta*((6.0/24.0)/3600.0) + if $sky/viewport/sky.day_time_hours >= 24.0: + $sky/viewport/sky.day_time_hours = $sky/viewport/sky.day_time_hours-24.0 func load_player( filename ): - $creatures/player.load_creature( filename ) + $creatures/player.load_creature( filename ) func _on_debug_window_time_of_day_changed(value): - $sky/viewport/sky.set_day_time_hours(( value )) + $sky/viewport/sky.set_day_time_hours(( value )) func _on_debug_window_mist_level_changed(value): - $mist_fx.get_surface_material( 0 ).set_shader_param( "mist_level", value ) + $mist_fx.get_surface_material( 0 ).set_shader_param( "mist_level", value ) func _on_debug_window_douleur_minus_pressed(): - $game_ui.change_douleur( -1 ) + $game_ui.change_douleur( -1 ) func _on_debug_window_douleur_plus_pressed(): - $game_ui.change_douleur( 1 ) + $game_ui.change_douleur( 1 ) func _on_debug_window_oubli_minus_pressed(): - $game_ui.change_oubli( -1 ) + $game_ui.change_oubli( -1 ) func _on_debug_window_oubli_plus_pressed(): - $game_ui.change_oubli( 1 ) + $game_ui.change_oubli( 1 ) diff --git a/scenes/game/sky.gd b/scenes/game/sky.gd index b1ebda5..35cf783 100644 --- a/scenes/game/sky.gd +++ b/scenes/game/sky.gd @@ -7,21 +7,21 @@ export(float, 0.0, 24.0) var day_time_hours = 12.0 setget set_day_time_hours export(NodePath) var directional_light_node_path func _ready(): - if !Engine.is_editor_hint(): - editor_clouds_playing = true + if !Engine.is_editor_hint(): + editor_clouds_playing = true var iTime = 0.0 var iFrame = 0 func _process( delta ): - - iTime+=delta - iFrame+=1 - - if (Engine.is_editor_hint() and self.editor_clouds_playing) or !Engine.is_editor_hint(): - self.material.set("shader_param/iTime", iTime) - self.material.set("shader_param/iFrame", iFrame) + + iTime+=delta + iFrame+=1 + + if (Engine.is_editor_hint() and self.editor_clouds_playing) or !Engine.is_editor_hint(): + self.material.set("shader_param/iTime", iTime) + self.material.set("shader_param/iFrame", iFrame) # self.set_day_time_hours( self.day_time_hours + delta ) # if day_time_hours >= 24: @@ -29,43 +29,43 @@ func _process( delta ): func cov_scb(value): - self.material.set("shader_param/COVERAGE",float(value)) + self.material.set("shader_param/COVERAGE",float(value)) func thick_scb(value): - self.material.set("shader_param/THICKNESS",value) + self.material.set("shader_param/THICKNESS",value) func absb_scb(value): - self.material.set("shader_param/ABSORPTION",float(value)) - + self.material.set("shader_param/ABSORPTION",float(value)) + func step_scb(value): - self.material.set("shader_param/STEPS",value) + self.material.set("shader_param/STEPS",value) export var sun_position = Vector3(0.0, 1.0, 0.0) setget set_sun_position, get_sun_position func set_sun_position(new_position): - sun_position = new_position - if self.material: - self.material.set_shader_param("sun_pos", sun_position) + sun_position = new_position + if self.material: + self.material.set_shader_param("sun_pos", sun_position) # _trigger_update_sky() func get_sun_position(): - return sun_position - + return sun_position + func set_time_of_day(hours, directional_light, horizontal_angle = 0.0): - var sun_position = Vector3(0.0, -100.0, 0.0) - sun_position = sun_position.rotated(Vector3(1.0, 0.0, 0.0), hours * PI / 12.0) - sun_position = sun_position.rotated(Vector3(0.0, 1.0, 0.0), horizontal_angle) - - if directional_light: - var t = directional_light.transform - t.origin = sun_position - directional_light.transform = t.looking_at(Vector3(0.0, 0.0, 0.0), Vector3(0.0, 1.0, 0.0)) - directional_light.light_energy = 1.0 - clamp(abs(hours - 12.0) / 6.0, 0.0, 1.0) - - # and update our sky - set_sun_position(sun_position) + var new_position = Vector3(0.0, -100.0, 0.0) + new_position = new_position.rotated(Vector3(1.0, 0.0, 0.0), hours * PI / 12.0) + new_position = new_position.rotated(Vector3(0.0, 1.0, 0.0), horizontal_angle) + + if directional_light: + var t = directional_light.transform + t.origin = new_position + directional_light.transform = t.looking_at(Vector3(0.0, 0.0, 0.0), Vector3(0.0, 1.0, 0.0)) + directional_light.light_energy = 1.0 - clamp(abs(hours - 12.0) / 6.0, 0.0, 1.0) + + # and update our sky + set_sun_position(new_position) func set_day_time_hours(hours): - if directional_light_node_path: - set_time_of_day(hours, get_node(directional_light_node_path), 25.0) - day_time_hours = hours + if directional_light_node_path: + set_time_of_day(hours, get_node(directional_light_node_path), 25.0) + day_time_hours = hours diff --git a/scenes/interfaces/creatures_editor/creatures_editor_ui.gd b/scenes/interfaces/creatures_editor/creatures_editor_ui.gd index 3dc19e3..01d40b4 100644 --- a/scenes/interfaces/creatures_editor/creatures_editor_ui.gd +++ b/scenes/interfaces/creatures_editor/creatures_editor_ui.gd @@ -22,95 +22,95 @@ var ra = Creatures.Ra_old.new() var slot = null func _ready(): - $viewport/spring_arm/camera.make_current() - + $viewport/spring_arm/camera.make_current() + func _input( event ): - - if event is InputEventMouseButton: - - if event.is_action_pressed( "creatures_editor_rotate_view_y" ): - self.mouse_old_position = event.position - elif event.is_action_released( "creatures_editor_rotate_view_y" ): - self.mouse_old_position = null - self.mouse_delta = null - - if event.is_action( "creatures_editor_zoom_in" ): - self.camera_zoom += self.camera_zoom_speed - elif event.is_action( "creatures_editor_zoom_out" ): - self.camera_zoom -= self.camera_zoom_speed - - if event is InputEventMouseMotion: - if not mouse_old_position == null: - self.mouse_delta = mouse_old_position - event.position - self.mouse_old_position = event.position - - + + if event is InputEventMouseButton: + + if event.is_action_pressed( "creatures_editor_rotate_view_y" ): + self.mouse_old_position = event.position + elif event.is_action_released( "creatures_editor_rotate_view_y" ): + self.mouse_old_position = null + self.mouse_delta = null + + if event.is_action( "creatures_editor_zoom_in" ): + self.camera_zoom += self.camera_zoom_speed + elif event.is_action( "creatures_editor_zoom_out" ): + self.camera_zoom -= self.camera_zoom_speed + + if event is InputEventMouseMotion: + if not mouse_old_position == null: + self.mouse_delta = mouse_old_position - event.position + self.mouse_old_position = event.position + + func _process( delta ): - if self.mouse_delta: - $viewport/model/ra.rotate( Vector3( 0.0, 1.0, 0.0 ), deg2rad( -self.mouse_delta.x ) ) - self.mouse_delta = Vector2( 0.0, 0.0 ) - - if self.camera_zoom: - $viewport/spring_arm/camera.size += self.camera_zoom - self.camera_zoom = 0.0 + if self.mouse_delta: + $viewport/model/ra.rotate( Vector3( 0.0, 1.0, 0.0 ), deg2rad( -self.mouse_delta.x ) ) + self.mouse_delta = Vector2( 0.0, 0.0 ) + + if self.camera_zoom: + $viewport/spring_arm/camera.size += self.camera_zoom + self.camera_zoom = 0.0 func set_creature( p_creature ): - if p_creature is Creatures.Ra: - self.ra = p_creature - $screen_box/tools_box/boobs/value.value = p_creature.female_boobs - $screen_box/tools_box/hip/value.value = p_creature.female_hip - $screen_box/tools_box/male_scrotch/value.value = p_creature.male_pack - $screen_box/tools_box/male_throat/value.value = p_creature.male_throat - $screen_box/tools_box/pregnant/value.value = p_creature.female_pregnant - $screen_box/tools_box/color/value.value = p_creature.color + if p_creature is Creatures.Ra: + self.ra = p_creature + $screen_box/tools_box/boobs/value.value = p_creature.female_boobs + $screen_box/tools_box/hip/value.value = p_creature.female_hip + $screen_box/tools_box/male_scrotch/value.value = p_creature.male_pack + $screen_box/tools_box/male_throat/value.value = p_creature.male_throat + $screen_box/tools_box/pregnant/value.value = p_creature.female_pregnant + $screen_box/tools_box/color/value.value = p_creature.color func _on_name_text_changed( new_text ): - self.ra.pseudonym = new_text - + self.ra.pseudonym = new_text + func _on_boobs_value_changed( value ): - $viewport/model/ra/model/body.set( "blend_shapes/Boobs", value ) - self.ra.female_boobs = value + $viewport/model/ra/model/body.set( "blend_shapes/Boobs", value ) + self.ra.female_boobs = value func _on_hip_value_changed(value): - $viewport/model/ra/model/body.set( "blend_shapes/Female_hip", value ) - self.ra.female_hip = value + $viewport/model/ra/model/body.set( "blend_shapes/Female_hip", value ) + self.ra.female_hip = value func _on_male_scrotch_value_changed(value): - $viewport/model/ra/model/body.set( "blend_shapes/Male_Pack", value ) - self.ra.male_pack = value + $viewport/model/ra/model/body.set( "blend_shapes/Male_Pack", value ) + self.ra.male_pack = value func _on_male_throat_value_changed(value): - $viewport/model/ra/model/body.set( "blend_shapes/Male_Throat", value ) - self.ra.male_throat = value + $viewport/model/ra/model/body.set( "blend_shapes/Male_Throat", value ) + self.ra.male_throat = value func _on_pregnant_value_changed(value): - $viewport/model/ra/model/body.set( "blend_shapes/Pregnant", value ) - self.ra.female_pregnant = value + $viewport/model/ra/model/body.set( "blend_shapes/Pregnant", value ) + self.ra.female_pregnant = value func _on_valid_pressed(): - if not self.slot == null: - var directory = Directory.new() - if not directory.dir_exists( "user://creatures/" ): - directory.make_dir_recursive( "user://creatures/" ) + if not self.slot == null: + var directory = Directory.new() + if not directory.dir_exists( "user://creatures/" ): + directory.make_dir_recursive( "user://creatures/" ) - var creature_file = File.new() - creature_file.open("user://creatures/slot_"+str(self.slot)+".creature", File.WRITE) - creature_file.store_line(to_json(self.ra.to_dictionary())) - creature_file.close() + var creature_file = File.new() + creature_file.open("user://creatures/slot_"+str(self.slot)+".creature", File.WRITE) + creature_file.store_line(to_json(self.ra.to_dictionary())) + creature_file.close() - emit_signal( "valid_pressed" ) + emit_signal( "valid_pressed" ) func _on_cancel_pressed(): - emit_signal( "cancel_pressed" ) + emit_signal( "cancel_pressed" ) func _on_color_changed(color): - $viewport/model/ra/model/body.get_surface_material( 0 ).set_shader_param( "albedo", color ) - self.ra.color = color + $viewport/model/ra/model/body.get_surface_material( 0 ).set_shader_param( "albedo", color ) + self.ra.color = color diff --git a/scenes/interfaces/creatures_menu/creature_box.gd b/scenes/interfaces/creatures_menu/creature_box.gd index e3b2915..65c6636 100644 --- a/scenes/interfaces/creatures_menu/creature_box.gd +++ b/scenes/interfaces/creatures_menu/creature_box.gd @@ -7,8 +7,8 @@ var slot = null var creature_filename = null func _on_select_pressed(): - emit_signal( "select_pressed", self.slot ) + emit_signal( "select_pressed", self.slot ) func _on_delete_pressed(): - emit_signal( "delete_pressed", self.slot ) + emit_signal( "delete_pressed", self.slot ) diff --git a/scenes/interfaces/creatures_menu/creatures_menu_ui.gd b/scenes/interfaces/creatures_menu/creatures_menu_ui.gd index 8bd4808..59ddaab 100644 --- a/scenes/interfaces/creatures_menu/creatures_menu_ui.gd +++ b/scenes/interfaces/creatures_menu/creatures_menu_ui.gd @@ -8,47 +8,47 @@ var slots_number = 0 var slots = {} func _ready(): - - var files = [] - var directory = Directory.new() - if directory.dir_exists( "user://creatures/" ): - directory.open( "user://creatures/" ) - directory.list_dir_begin() - while true: - var file = directory.get_next() - if file == "": - break - elif not file.begins_with( "." ) and not directory.current_is_dir(): - files.append( file ) - directory.list_dir_end() - - for file in files: - var creature_box = preload( "res://scenes/interfaces/creatures_menu/creature_box.tscn" ).instance() - creature_box.get_node( "label" ).text = file - creature_box.slot = self.slots_number - creature_box.creature_filename = file - creature_box.connect( "select_pressed", self, "_on_creature_box_select_pressed" ) - creature_box.connect( "delete_pressed", self, "_on_creature_box_delete_pressed" ) - $screen_box/scroll_container/v_box_container/creatures_box.add_child( creature_box ) - self.slots[ self.slots_number ] = creature_box - self.slots_number += 1 - - var creature = Creatures.Ra_old2.new() - creature.from_file( file ) - creature_box.get_node( "label" ).text = creature.pseudonym - + + var files = [] + var directory = Directory.new() + if directory.dir_exists( "user://creatures/" ): + directory.open( "user://creatures/" ) + directory.list_dir_begin() + while true: + var file = directory.get_next() + if file == "": + break + elif not file.begins_with( "." ) and not directory.current_is_dir(): + files.append( file ) + directory.list_dir_end() + + for file in files: + var creature_box = preload( "res://scenes/interfaces/creatures_menu/creature_box.tscn" ).instance() + creature_box.get_node( "label" ).text = file + creature_box.slot = self.slots_number + creature_box.creature_filename = file + creature_box.connect( "select_pressed", self, "_on_creature_box_select_pressed" ) + creature_box.connect( "delete_pressed", self, "_on_creature_box_delete_pressed" ) + $screen_box/scroll_container/v_box_container/creatures_box.add_child( creature_box ) + self.slots[ self.slots_number ] = creature_box + self.slots_number += 1 + + var creature = Creatures.Ra_old2.new() + creature.from_file( file ) + creature_box.get_node( "label" ).text = creature.pseudonym + func _on_new_pressed(): - emit_signal( "new_pressed", self.slots_number ) + emit_signal( "new_pressed", self.slots_number ) func _on_cancel_pressed(): - emit_signal( "cancel_pressed" ) + emit_signal( "cancel_pressed" ) func _on_creature_box_select_pressed( slot ): - emit_signal( "select_pressed", self.slots[ slot ].creature_filename ) - + emit_signal( "select_pressed", self.slots[ slot ].creature_filename ) + func _on_creature_box_delete_pressed( slot ): - if self.slots[ slot ].creature_filename: - var dir = Directory.new() - dir.remove( "user://creatures/" + self.slots[ slot ].creature_filename ) - self.slots[ slot ].queue_free() + if self.slots[ slot ].creature_filename: + var dir = Directory.new() + dir.remove( "user://creatures/" + self.slots[ slot ].creature_filename ) + self.slots[ slot ].queue_free() diff --git a/scenes/interfaces/focus_reticle.gd b/scenes/interfaces/focus_reticle.gd index 1d79f92..0f9ec20 100644 --- a/scenes/interfaces/focus_reticle.gd +++ b/scenes/interfaces/focus_reticle.gd @@ -5,5 +5,5 @@ class_name focus_reticle export( Vector2 ) var size = Vector2( 1.0, 1.0 ) setget set_size func set_size( p_value ): - size = p_value - self.mesh.size = p_value + size = p_value + self.mesh.size = p_value diff --git a/scenes/interfaces/game_menu/game_ui.gd b/scenes/interfaces/game_menu/game_ui.gd index 1ee0563..e2629a1 100644 --- a/scenes/interfaces/game_menu/game_ui.gd +++ b/scenes/interfaces/game_menu/game_ui.gd @@ -2,46 +2,46 @@ extends Control func change_douleur( value ): - $stats_window.get_content_child( "douleur" ).value += value - if value > 0.0: - $stats_window.get_content_child( "oubli" ).value -= value/2 - + $stats_window.get_content_child( "douleur" ).value += value + if value > 0.0: + $stats_window.get_content_child( "oubli" ).value -= value/2 + func change_oubli( value ): - $stats_window.get_content_child( "oubli" ).value += value - if value > 0.0: - $stats_window.get_content_child( "douleur" ).value -= value/2 - + $stats_window.get_content_child( "oubli" ).value += value + if value > 0.0: + $stats_window.get_content_child( "douleur" ).value -= value/2 + func change_trauma( value ): - $stats_window.get_content_child( "trauma" ).self_modulate.a += value/6.0 - + $stats_window.get_content_child( "trauma" ).self_modulate.a += value/6.0 + func set_douleur( value ): - var delta = value - $stats_window.get_content_child( "douleur" ).value - $stats_window.get_content_child( "douleur" ).value = value - if delta > 0.0: - $stats_window.get_content_child( "oubli" ).value -= delta/2 + var delta = value - $stats_window.get_content_child( "douleur" ).value + $stats_window.get_content_child( "douleur" ).value = value + if delta > 0.0: + $stats_window.get_content_child( "oubli" ).value -= delta/2 func set_oubli( value ): - var delta = value - $stats_window.get_content_child( "oubli" ).value - $stats_window.get_content_child( "oubli" ).value = value - if delta > 0.0: - $stats_window.get_content_child( "douleur" ).value -= delta/2 + var delta = value - $stats_window.get_content_child( "oubli" ).value + $stats_window.get_content_child( "oubli" ).value = value + if delta > 0.0: + $stats_window.get_content_child( "douleur" ).value -= delta/2 func set_trauma( value ): - $stats_window.get_content_child( "trauma" ).self_modulate.a = value/6.0 + $stats_window.get_content_child( "trauma" ).self_modulate.a = value/6.0 func update_trauma(): - var trauma_value = (($stats_window.get_content_child( "oubli" ).value+$stats_window.get_content_child( "douleur" ).value)/2) - $stats_window.get_content_child( "trauma" ).value = trauma_value - $stats_window.get_content_child( "trauma" ).self_modulate.a = trauma_value/6.0 + var trauma_value = (($stats_window.get_content_child( "oubli" ).value+$stats_window.get_content_child( "douleur" ).value)/2) + $stats_window.get_content_child( "trauma" ).value = trauma_value + $stats_window.get_content_child( "trauma" ).self_modulate.a = trauma_value/6.0 func _on_douleur_value_changed(value): - $stats_window.get_content_child( "douleur" ).self_modulate.a = (value / 18.0) * (value / 18.0) - self.update_trauma() + $stats_window.get_content_child( "douleur" ).self_modulate.a = (value / 18.0) * (value / 18.0) + self.update_trauma() func _on_oubli_value_changed(value): - $stats_window.get_content_child( "oubli" ).self_modulate.a = (value / 18.0) * (value / 18.0) - self.update_trauma() + $stats_window.get_content_child( "oubli" ).self_modulate.a = (value / 18.0) * (value / 18.0) + self.update_trauma() func _on_trauma_value_changed(value): - $stats_window.get_content_child( "trauma" ).self_modulate.a = (value / 6.0) + $stats_window.get_content_child( "trauma" ).self_modulate.a = (value / 6.0) diff --git a/scenes/interfaces/inventory_window/inventory_box.gd b/scenes/interfaces/inventory_window/inventory_box.gd index d17b1cd..037c628 100644 --- a/scenes/interfaces/inventory_window/inventory_box.gd +++ b/scenes/interfaces/inventory_window/inventory_box.gd @@ -2,26 +2,26 @@ extends VBoxContainer signal inventory_item_hovered( item ) signal inventory_item_gui_input( item, event, node ) - + func _on_inventory_item_hovered( item ): - emit_signal( "inventory_item_hovered", item ) + emit_signal( "inventory_item_hovered", item ) func _on_inventory_item_gui_input( item, event, node ): - emit_signal( "inventory_item_gui_input", item, event, node ) - - - + emit_signal( "inventory_item_gui_input", item, event, node ) + + + func clean_inventory(): - for child in $scroll_item_box/items_box.get_children(): - $scroll_item_box/items_box.remove_child( child ) - child.queue_free() - + for child in $scroll_item_box/items_box.get_children(): + $scroll_item_box/items_box.remove_child( child ) + child.queue_free() + func set_inventory( p_inventory ): - self.clean_inventory() - if p_inventory: - for item in p_inventory.items: - print( item ) - var new_item_box = preload( "res://scenes/interfaces/inventory_window/item_box.tscn").instance() - new_item_box.item = item - new_item_box.update() - $scroll_item_box/items_box.add_child( new_item_box ) + self.clean_inventory() + if p_inventory: + for item in p_inventory.items: + print( item ) + var new_item_box = preload( "res://scenes/interfaces/inventory_window/item_box.tscn").instance() + new_item_box.item = item + new_item_box.update() + $scroll_item_box/items_box.add_child( new_item_box ) diff --git a/scenes/interfaces/main_menu/main_menu.gd b/scenes/interfaces/main_menu/main_menu.gd index 2d34107..ab82123 100644 --- a/scenes/interfaces/main_menu/main_menu.gd +++ b/scenes/interfaces/main_menu/main_menu.gd @@ -5,11 +5,11 @@ signal play_pressed signal quit_pressed func close(): - self.hide() + self.hide() func _on_play_pressed(): - emit_signal( "play_pressed" ) + emit_signal( "play_pressed" ) func _on_quitter_pressed(): - emit_signal( "quit_pressed" ) + emit_signal( "quit_pressed" ) diff --git a/scenes/interfaces/music_manager/music_button.gd b/scenes/interfaces/music_manager/music_button.gd index 09c01fc..e803443 100644 --- a/scenes/interfaces/music_manager/music_button.gd +++ b/scenes/interfaces/music_manager/music_button.gd @@ -5,4 +5,4 @@ signal music_selected( filename ) var music_filename = "" func _on_music_button_pressed(): - emit_signal( "music_selected", self.music_filename ) + emit_signal( "music_selected", self.music_filename ) diff --git a/scenes/interfaces/music_manager/music_manager.gd b/scenes/interfaces/music_manager/music_manager.gd index abfbf8f..948caa9 100644 --- a/scenes/interfaces/music_manager/music_manager.gd +++ b/scenes/interfaces/music_manager/music_manager.gd @@ -1,41 +1,41 @@ extends WindowDialog func _ready(): - var directory = Directory.new() - - if not directory.dir_exists( "user://musics/" ): - directory.make_dir_recursive( "user://musics/" ) - directory.open( "user://musics/" ) - directory.list_dir_begin() - var files = [] - while true: - var file = directory.get_next() - if file == "": - break - elif not file.begins_with(".") and not directory.current_is_dir() and not file.ends_with( ".import" ): - files.append(file) - directory.list_dir_end() - - for file in files: - var button = preload( "res://scenes/interfaces/music_manager/music_button.tscn" ).instance() - button.music_filename = file - button.text = file - button.connect( "music_selected", self, "_on_music_pressed" ) - $window_box/scroll_box/musics_box.add_child( button ) + var directory = Directory.new() + + if not directory.dir_exists( "user://musics/" ): + directory.make_dir_recursive( "user://musics/" ) + directory.open( "user://musics/" ) + directory.list_dir_begin() + var files = [] + while true: + var file = directory.get_next() + if file == "": + break + elif not file.begins_with(".") and not directory.current_is_dir() and not file.ends_with( ".import" ): + files.append(file) + directory.list_dir_end() + + for file in files: + var button = preload( "res://scenes/interfaces/music_manager/music_button.tscn" ).instance() + button.music_filename = file + button.text = file + button.connect( "music_selected", self, "_on_music_pressed" ) + $window_box/scroll_box/musics_box.add_child( button ) func open(): - self.popup() - + self.popup() + func close(): - self.hide() - + self.hide() + func toggle(): - if self.visible: - self.close() - else: - self.open() + if self.visible: + self.close() + else: + self.open() func _on_music_pressed( p_filename ): - $music.stream = load( "res://assets/musics/" + p_filename ) - $music.play() + $music.stream = load( "res://assets/musics/" + p_filename ) + $music.play() diff --git a/scenes/interfaces/windows/window.gd b/scenes/interfaces/windows/window.gd index d1f3239..ead6789 100644 --- a/scenes/interfaces/windows/window.gd +++ b/scenes/interfaces/windows/window.gd @@ -4,12 +4,12 @@ var old_mouse_position = Vector2( 0, 0 ) func _on_stats_window_gui_input(event): - - if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and Input.is_mouse_button_pressed( BUTTON_LEFT ): - self.old_mouse_position = event.position - - if event is InputEventMouseMotion and Input.is_mouse_button_pressed( BUTTON_LEFT ): - var delta = self.old_mouse_position - event.position - self.set_position( self.get_position() - delta ) + + if event is InputEventMouseButton and event.button_index == BUTTON_LEFT and Input.is_mouse_button_pressed( BUTTON_LEFT ): + self.old_mouse_position = event.position + + if event is InputEventMouseMotion and Input.is_mouse_button_pressed( BUTTON_LEFT ): + var delta = self.old_mouse_position - event.position + self.set_position( self.get_position() - delta ) diff --git a/scenes/items/pickup_item.gd b/scenes/items/pickup_item.gd index 126aaca..958461f 100644 --- a/scenes/items/pickup_item.gd +++ b/scenes/items/pickup_item.gd @@ -3,9 +3,9 @@ extends Spatial export( String ) var item_filename = "" setget set_item_filename func set_item_filename( value ): - item_filename = value - if is_ready: - self.update_model() + item_filename = value + if is_ready: + self.update_model() var item = null @@ -13,64 +13,65 @@ var is_ready = false func _ready(): - self.item = Datas.PickupItem.new( self.item_filename, self.global_transform ) - - self.update_model() + self.item = Datas.PickupItem.new( self.item_filename, self.global_transform ) + + self.update_model() - self.is_ready = true - + self.is_ready = true + func update_model(): - - for node in self.get_children(): - self.remove_child( node ) - node.queue_free() + + for node in self.get_children(): + self.remove_child( node ) + node.queue_free() - if self.item: - if self.item.get_data( "model" ): - var item_node = load( self.item.get_data( "model" ) ) - if item_node: - item_node = item_node.instance() - self.add_child( item_node ) + if self.item: + if self.item.get_data( "model" ): + var item_node = load( self.item.get_data( "model" ) ) + if item_node: + item_node = item_node.instance() + self.add_child( item_node ) func set_focus( p_focus = true ): - if p_focus: - for item in self.get_children(): - if item.has_node( "focus" ): - item.get_node( "focus" ).show() - else: - for item in self.get_children(): - if item.has_node( "focus" ): - item.get_node( "focus" ).hide() + var _item + if p_focus: + for _item in self.get_children(): + if _item.has_node( "focus" ): + _item.get_node( "focus" ).show() + else: + for _item in self.get_children(): + if _item.has_node( "focus" ): + _item.get_node( "focus" ).hide() func interact( p_object ): - if self.item.get_data( "pickable" ): - if p_object is Datas.Creature: - var new_inventory = p_object.get_data( "inventory" ) - - var number = self.item.get_data( "default_num_given" ) - var stack = self.item.get_data( "stack" ) - if number and stack and number > stack: - var lasting_number = number - while lasting_number > stack: - var inventory_item = Datas.InventoryItem.new( self.item_filename, stack, self.item ) - inventory_item.set_data( "name", self.item_filename ) - inventory_item.set_data( "number", stack ) - new_inventory.push_back( inventory_item ) - lasting_number -= stack - if lasting_number > 0: - var inventory_item = Datas.InventoryItem.new( self.item_filename, lasting_number, self.item ) - inventory_item.set_data( "name", self.item_filename ) - inventory_item.set_data( "number", lasting_number ) - new_inventory.push_back( inventory_item ) - else: - var inventory_item = Datas.InventoryItem.new( self.item_filename, number, self.item ) - inventory_item.set_data( "name", self.item_filename ) - new_inventory.push_back( inventory_item ) - - p_object.set_data( "inventory", new_inventory ) - - self.get_parent().remove_child( self ) - self.queue_free() - return true - return false - + if self.item.get_data( "pickable" ): + if p_object is Datas.Creature: + var new_inventory = p_object.get_data( "inventory" ) + + var number = self.item.get_data( "default_num_given" ) + var stack = self.item.get_data( "stack" ) + if number and stack and number > stack: + var lasting_number = number + while lasting_number > stack: + var inventory_item = Datas.InventoryItem.new( self.item_filename, stack, self.item ) + inventory_item.set_data( "name", self.item_filename ) + inventory_item.set_data( "number", stack ) + new_inventory.push_back( inventory_item ) + lasting_number -= stack + if lasting_number > 0: + var inventory_item = Datas.InventoryItem.new( self.item_filename, lasting_number, self.item ) + inventory_item.set_data( "name", self.item_filename ) + inventory_item.set_data( "number", lasting_number ) + new_inventory.push_back( inventory_item ) + else: + var inventory_item = Datas.InventoryItem.new( self.item_filename, number, self.item ) + inventory_item.set_data( "name", self.item_filename ) + new_inventory.push_back( inventory_item ) + + p_object.set_data( "inventory", new_inventory ) + + self.get_parent().remove_child( self ) + self.queue_free() + return true + return false + diff --git a/scenes/main/main.gd b/scenes/main/main.gd index 405f26f..0c88e9d 100644 --- a/scenes/main/main.gd +++ b/scenes/main/main.gd @@ -12,23 +12,24 @@ var creature_selected_slot = null var creature_selected_filename = null func _ready(): - Connection.connect( "connection_ok", self, "_on_connexion_ok" ) - Connection.connect( "connection_error", self, "_on_connection_error" ) + Connection.connect( "connection_ok", self, "_on_connexion_ok" ) + Connection.connect( "connection_error", self, "_on_connection_error" ) - Globals.ressource_queue.start() + Globals.ressource_queue.start() func _process(_time): - - if self.is_scene_loading: - if Globals.ressource_queue.is_ready( self.current_scene_path ): - print( "LOADING FINISHED") - self.set_new_scene( Globals.ressource_queue.get_resource( self.current_scene_path ) ) - $loading_screen.hide() - else: - self.update_progress() - $loading_screen.show() - - + + if self.is_scene_loading: + if Globals.ressource_queue.is_ready( self.current_scene_path ): + print( "LOADING FINISHED") + self.set_new_scene( Globals.ressource_queue.get_resource( self.current_scene_path ) ) + # $loading_screen.hide() + self.stop_progress() + else: + self.update_progress() + $loading_screen.show() + + # if loader == null: # # no need to process anymore # set_process(false) @@ -56,13 +57,13 @@ func _process(_time): # printerr( "Loading errors." ) # loader = null # break - + func _input( event ): - - if event.is_action_released( "music_manager" ): - MusicManager.toggle() - - + + if event.is_action_released( "music_manager" ): + MusicManager.toggle() + + #func load_scene( path ): # self.loader = ResourceLoader.load_interactive( path ) # if self.loader == null: @@ -81,43 +82,56 @@ func _input( event ): # self.wait_frames = 1 func set_new_scene( scene_resource ): - if scene_resource: - self.current_scene = scene_resource.instance() - self.get_node("scene").add_child(self.current_scene) - self.is_scene_loading = false - $loading_screen.hide() - $main_menu.hide() + if scene_resource: + self.current_scene = scene_resource.instance() + self.get_node("scene").add_child(self.current_scene) + # self.is_scene_loading = false + self.stop_progress() + # $loading_screen.hide() + $main_menu.hide() - if self.has_node( "scene/creatures_menu_ui" ): - self.get_node( "scene/creatures_menu_ui" ).connect( "new_pressed", self, "_on_creatures_menu_ui_new_pressed" ) - self.get_node( "scene/creatures_menu_ui" ).connect( "cancel_pressed", self, "_on_creatures_menu_ui_cancel_pressed" ) - self.get_node( "scene/creatures_menu_ui" ).connect( "select_pressed", self, "_on_creatures_menu_ui_select_pressed" ) - elif self.has_node( "scene/creatures_editor_ui" ): - self.get_node( "scene/creatures_editor_ui" ).connect( "valid_pressed", self, "_on_creature_editor_ui_valid_pressed" ) - self.get_node( "scene/creatures_editor_ui" ).connect( "cancel_pressed", self, "_on_creature_editor_ui_cencel_pressed" ) - print( "slot: " + str( self.creature_selected_slot ) ) - self.get_node( "scene/creatures_editor_ui" ).slot = self.creature_selected_slot - # elif self.has_node( "scene/game" ): - # self.get_node( "scene/game" ).load_player( self.creature_selected_filename ) - + if self.has_node( "scene/creatures_menu_ui" ): + self.get_node( "scene/creatures_menu_ui" ).connect( "new_pressed", self, "_on_creatures_menu_ui_new_pressed" ) + self.get_node( "scene/creatures_menu_ui" ).connect( "cancel_pressed", self, "_on_creatures_menu_ui_cancel_pressed" ) + self.get_node( "scene/creatures_menu_ui" ).connect( "select_pressed", self, "_on_creatures_menu_ui_select_pressed" ) + elif self.has_node( "scene/creatures_editor_ui" ): + self.get_node( "scene/creatures_editor_ui" ).connect( "valid_pressed", self, "_on_creature_editor_ui_valid_pressed" ) + self.get_node( "scene/creatures_editor_ui" ).connect( "cancel_pressed", self, "_on_creature_editor_ui_cencel_pressed" ) + print( "slot: " + str( self.creature_selected_slot ) ) + self.get_node( "scene/creatures_editor_ui" ).slot = self.creature_selected_slot + # elif self.has_node( "scene/game" ): + # self.get_node( "scene/game" ).load_player( self.creature_selected_filename ) + func update_progress(): - var progress = float(Globals.ressource_queue.get_progress( self.current_scene_path )) + var progress = float(Globals.ressource_queue.get_progress( self.current_scene_path )) + #self.get_node("loading_screen/background_player").play("loading") + #self.get_node("loading_screen/background_player").stop() + self.get_node("loading_screen/background_player").seek( (progress*13.0)/100.0 ) - self.get_node("loading_screen/background_player").play("loading") - self.get_node("loading_screen/background_player").stop() - self.get_node("loading_screen/background_player").seek( (progress*13.0)/100.0 ) - - +func start_progress(): + var progress = float(Globals.ressource_queue.get_progress( self.current_scene_path )) + self.get_node("loading_screen/background_player").play("loading") + #self.get_node("loading_screen/background_player").stop() + self.get_node("loading_screen/background_player").seek( 0 ) + self.is_scene_loading = true + $loading_screen.show() + +func stop_progress(): + self.get_node("loading_screen/background_player").stop() + self.is_scene_loading = false + $loading_screen.hide() + func goto_scene( p_path ): - - # Clean old scene. - if self.current_scene: - Globals.ressource_queue.cancel_resource( self.current_scene_path ) - self.current_scene.queue_free() - - Globals.ressource_queue.queue_resource( p_path ) - self.current_scene_path = p_path - self.is_scene_loading = true + + # Clean old scene. + if self.current_scene: + Globals.ressource_queue.cancel_resource( self.current_scene_path ) + self.current_scene.queue_free() + + Globals.ressource_queue.queue_resource( p_path ) + self.current_scene_path = p_path + #self.is_scene_loading = true + self.start_progress() #func set_new_scene( scene_resource ): @@ -125,47 +139,47 @@ func goto_scene( p_path ): # self.current_scene = scene_resource.instance() # self.get_node("scene").add_child(self.current_scene) # self.is_scene_loading = false - + #func update_progress(): # self.get_node("loading_screen/progress_bar").value = Globals.ressource_queue.get_progress( self.current_scene_path ) # - - + + func _on_main_menu_play_pressed(): - var username = $main_menu/screen_box/login_box/username.text; - var password = $main_menu/screen_box/login_box/password.text; - if username != null and username != "" and password != null and password != "": - Connection.do_request(username, password) - else: - Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) - - + var username = $main_menu/screen_box/login_box/username.text; + var password = $main_menu/screen_box/login_box/password.text; + if username != null and username != "" and password != null and password != "": + Connection.do_request(username, password) + else: + Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) + + func _on_creatures_menu_ui_new_pressed( slot ): - self.creature_selected_slot = slot + self.creature_selected_slot = slot # Globals.goto_scene( "res://scenes/interfaces/creatures_editor/creatures_editor_ui.tscn" ) - Globals.goto_scene( "res://scenes/creatures/creatures_creation.tscn" ) + Globals.goto_scene( "res://scenes/creatures/creatures_creation.tscn" ) func _on_creatures_menu_ui_cancel_pressed(): - $main_menu.show() + $main_menu.show() func _on_creatures_menu_ui_select_pressed( filename ): - self.creature_selected_filename = filename - Globals.goto_scene( "res://scenes/game/game.tscn" ) - + self.creature_selected_filename = filename + Globals.goto_scene( "res://scenes/game/game.tscn" ) + func _on_creature_editor_ui_valid_pressed(): - Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) - + Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) + func _on_creature_editor_ui_cencel_pressed(): - Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) - + Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) + func _on_main_menu_quit_pressed(): - get_tree().quit() + get_tree().quit() func _on_connexion_ok(): - Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) - + Globals.goto_scene( "res://scenes/interfaces/creatures_menu/creatures_menu_ui.tscn" ) + func _on_connection_error( message ): - $main_menu/screen_box/login_box/error.text = message + $main_menu/screen_box/login_box/error.text = message diff --git a/scenes/player/player.gd b/scenes/player/player.gd index dce3513..844bdb1 100644 --- a/scenes/player/player.gd +++ b/scenes/player/player.gd @@ -17,53 +17,53 @@ var focused_object = null var focus_index = 0 static func get_input_direction() -> Vector3: - return Vector3( - Input.get_action_strength("move_strafe_right") - Input.get_action_strength("move_strafe_left"), - 0, - Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward") - ) - + return Vector3( + Input.get_action_strength("move_strafe_right") - Input.get_action_strength("move_strafe_left"), + 0, + Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward") + ) + func _input( event ): - - # Run. - if event.is_action_pressed( "move_toggle_run" ): - $character.is_running = not $character.is_running + + # Run. + if event.is_action_pressed( "move_toggle_run" ): + $character.is_running = not $character.is_running - # Camera. - if event.is_action( "camera_zoom_in" ): - self.zoom_level += 1 - elif event.is_action( "camera_zoom_out" ): - self.zoom_level -= 1 - - if event.is_action_pressed( "camera_reset_view" ): - $character/spring_arm.rotation = Vector3.ZERO - self.zoom_level = 0 - - if event.is_action_pressed( "camera_switch" ): - if self.camera_tps.current: - self.camera_fps.make_current() - $character/spring_arm.rotation = Vector3.ZERO + # Camera. + if event.is_action( "camera_zoom_in" ): + self.zoom_level += 1 + elif event.is_action( "camera_zoom_out" ): + self.zoom_level -= 1 + + if event.is_action_pressed( "camera_reset_view" ): + $character/spring_arm.rotation = Vector3.ZERO + self.zoom_level = 0 + + if event.is_action_pressed( "camera_switch" ): + if self.camera_tps.current: + self.camera_fps.make_current() + $character/spring_arm.rotation = Vector3.ZERO # self.hide() - else: - self.camera_tps.make_current() + else: + self.camera_tps.make_current() # self.show() - + - if event is InputEventMouseMotion: - self.mouse_delta = event.relative - - # Jump. - if event.is_action_pressed( "move_jump" ) and not $character.is_falling: - $character.is_jump_started = true - + if event is InputEventMouseMotion: + self.mouse_delta = event.relative + + # Jump. + if event.is_action_pressed( "move_jump" ) and not $character.is_falling: + $character.is_jump_started = true + - if event.is_action_pressed( "interact" ): - self.interact() - - - if event.is_action_pressed( "focus_next" ): - self.focus_next() - + if event.is_action_pressed( "interact" ): + self.interact() + + + if event.is_action_pressed( "focus_next" ): + self.focus_next() + # if not self.get_tree().get_root().get_node( "main/scene/game" ).is_on_ui: # if event.is_action_pressed( "action_ready_weapon" ): # $character.is_readying_weapon = true @@ -73,23 +73,23 @@ func _input( event ): # if $character.is_weapon_ready: # if event.is_action_pressed( "action_attack" ): # $character.attack() - - + + func _process( delta ): - $character.direction = self.get_input_direction() + $character.direction = self.get_input_direction() - # Rotation. - if not Input.is_key_pressed( KEY_SHIFT ) and not $character.is_jump_started: - $character.orientation = (Input.get_action_strength("move_turn_left") - Input.get_action_strength("move_turn_right")) - else: - $character.orientation = 0.0 - - # Camera. - if not self.mouse_delta == Vector2.ZERO and self.camera_tps.current: - if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: - $character/spring_arm.rotate_y( -self.mouse_delta.x * 0.01 ) - self.camera_tps.rotate_x( self.mouse_delta.y * 0.01 ) + # Rotation. + if not Input.is_key_pressed( KEY_SHIFT ) and not $character.is_jump_started: + $character.orientation = (Input.get_action_strength("move_turn_left") - Input.get_action_strength("move_turn_right")) + else: + $character.orientation = 0.0 + + # Camera. + if not self.mouse_delta == Vector2.ZERO and self.camera_tps.current: + if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: + $character/spring_arm.rotate_y( -self.mouse_delta.x * 0.01 ) + self.camera_tps.rotate_x( self.mouse_delta.y * 0.01 ) # if not $character.velocity.x == 0.0 or not $character.velocity.z == 0.0: # var velocity_without_gravity = $character.velocity @@ -100,125 +100,125 @@ func _process( delta ): ## $crosshair.material.set_shader_param( "spread", 1 ) # $character/target_spring_arm/crosshair.scale = Vector3( 1.0, 1.0, 1.0 ) - if $character.is_weapon_ready: - if $character.get_main_weapon_node(): - $character/crosshair.show() - # $character/target_spring_arm.global_transform.origin = $character.get_main_weapon_node().get_node( "bullet_exit" ).global_transform.origin - # $character/target_spring_arm.look_at_from_position( $character.get_main_weapon_node().get_node( "bullet_exit" ).global_transform.origin, $character.get_main_weapon_node().get_node( "target" ).global_transform.origin, Vector3( 0.0, 0.0, -1.0 ) ) - # $character/target_spring_arm.global_transform.basis.y = $character.get_main_weapon_node().get_node( "bullet_exit" ).global_transform.basis.y - $character/crosshair.global_transform.origin = $character.get_main_weapon_node().get_node( "bullet_exit/target_spring_arm/target" ).global_transform.origin - else: - $character/target_spring_arm.hide() + if $character.is_weapon_ready: + if $character.get_main_weapon_node(): + $character/crosshair.show() + # $character/target_spring_arm.global_transform.origin = $character.get_main_weapon_node().get_node( "bullet_exit" ).global_transform.origin + # $character/target_spring_arm.look_at_from_position( $character.get_main_weapon_node().get_node( "bullet_exit" ).global_transform.origin, $character.get_main_weapon_node().get_node( "target" ).global_transform.origin, Vector3( 0.0, 0.0, -1.0 ) ) + # $character/target_spring_arm.global_transform.basis.y = $character.get_main_weapon_node().get_node( "bullet_exit" ).global_transform.basis.y + $character/crosshair.global_transform.origin = $character.get_main_weapon_node().get_node( "bullet_exit/target_spring_arm/target" ).global_transform.origin + else: + $character/target_spring_arm.hide() - # Values reset. - self.mouse_delta = Vector2.ZERO - + # Values reset. + self.mouse_delta = Vector2.ZERO + # Debug. #var old_collider = null func _physics_process(delta): - - var space_state = get_world().direct_space_state - # Camera. - self.camera_position = Vector3( 0.0, 2 - 0.1*self.zoom_level, -2 + 0.1*self.zoom_level ) - $character/spring_arm/camera_position.translation = self.camera_position - var global_camera_position = $character/spring_arm/camera_position.global_transform.origin - var result = space_state.intersect_ray($character/look_at.global_transform.origin, global_camera_position, [self]) - - - if result: - self.camera_tps.global_transform.origin = result.position + + var space_state = get_world().direct_space_state + # Camera. + self.camera_position = Vector3( 0.0, 2 - 0.1*self.zoom_level, -2 + 0.1*self.zoom_level ) + $character/spring_arm/camera_position.translation = self.camera_position + var global_camera_position = $character/spring_arm/camera_position.global_transform.origin + var result = space_state.intersect_ray($character/look_at.global_transform.origin, global_camera_position, [self]) + + + if result: + self.camera_tps.global_transform.origin = result.position # self.camera_tps.look_at( $character/look_at.global_transform.origin, Vector3( 0.0, 1.0, 0.0) ) - + - else: - self.camera_tps.translation = self.camera_position + else: + self.camera_tps.translation = self.camera_position # self.camera_tps.look_at( $character/look_at.global_transform.origin, Vector3( 0.0, 1.0, 0.0) ) - + func interact( p_object = null ): - if p_object and p_object.has_method( "interact" ): - p_object.interact( $character/creature.creature ) - else: - if self.focused_object and self.focused_object.has_method( "interact" ): - self.focused_object.interact( $character/creature.creature ) - elif self.focused_object and self.focused_object.get_parent() and self.focused_object.get_parent().has_method( "interact" ): - self.focused_object.get_parent().interact( $character/creature.creature ) + if p_object and p_object.has_method( "interact" ): + p_object.interact( $character/creature.creature ) + else: + if self.focused_object and self.focused_object.has_method( "interact" ): + self.focused_object.interact( $character/creature.creature ) + elif self.focused_object and self.focused_object.get_parent() and self.focused_object.get_parent().has_method( "interact" ): + self.focused_object.get_parent().interact( $character/creature.creature ) - if not self.focused_object: - self.proximity_objects.erase( self.focused_object ) - self.update_focused_object() + if not self.focused_object: + self.proximity_objects.erase( self.focused_object ) + self.update_focused_object() func focus_next(): - self.focus_index += 1 - if self.focus_index >= self.proximity_objects.size(): - self.focus_index = 0 - - self.update_focused_object() - - + self.focus_index += 1 + if self.focus_index >= self.proximity_objects.size(): + self.focus_index = 0 + + self.update_focused_object() + + func set_focus_on( p_object, p_focus ): - if p_object and p_object.has_method( "set_focus" ): - p_object.set_focus( p_focus ) - elif p_object and p_object.get_parent() and p_object.get_parent().has_method( "set_focus" ): - p_object.get_parent().set_focus( p_focus ) - + if p_object and p_object.has_method( "set_focus" ): + p_object.set_focus( p_focus ) + elif p_object and p_object.get_parent() and p_object.get_parent().has_method( "set_focus" ): + p_object.get_parent().set_focus( p_focus ) + func update_focused_object(): - - if self.focus_index >= self.proximity_objects.size(): - self.focus_index = 0 - - var old_focused_object = self.focused_object - if self.proximity_objects.size() > 0: - self.focused_object = self.proximity_objects[ self.focus_index ] - else: - self.focused_object = null - - if old_focused_object: - self.set_focus_on( old_focused_object, false ) - if self.focused_object: - self.set_focus_on( self.focused_object, true ) - emit_signal( "new_focused_object", self.focused_object.name ) + + if self.focus_index >= self.proximity_objects.size(): + self.focus_index = 0 + + var old_focused_object = self.focused_object + if self.proximity_objects.size() > 0: + self.focused_object = self.proximity_objects[ self.focus_index ] + else: + self.focused_object = null + + if old_focused_object: + self.set_focus_on( old_focused_object, false ) + if self.focused_object: + self.set_focus_on( self.focused_object, true ) + emit_signal( "new_focused_object", self.focused_object.name ) func _on_interact_area_body_entered(body): - if not body == $character: - self.proximity_objects.push_back( body ) - self.update_focused_object() + if not body == $character: + self.proximity_objects.push_back( body ) + self.update_focused_object() func _on_interact_area_body_exited(body): - if not body == $character: - self.proximity_objects.erase( body ) - self.update_focused_object() + if not body == $character: + self.proximity_objects.erase( body ) + self.update_focused_object() func _on_character_equip(p_slot, p_item): - emit_signal( "equip", p_slot, p_item ) - var weapons = $character.get_weapons() - if weapons.size() > 0: - - var min_range = null - for weapon in weapons: - if not min_range: - min_range = weapon.get_data( "range" ) - else: - min_range = min( min_range, weapon.get_data( "range" ) ) - $character.get_main_weapon_node().get_node( "bullet_exit/target_spring_arm" ).spring_length = min_range - + emit_signal( "equip", p_slot, p_item ) + var weapons = $character.get_weapons() + if weapons.size() > 0: + + var min_range = null + for weapon in weapons: + if not min_range: + min_range = weapon.get_data( "range" ) + else: + min_range = min( min_range, weapon.get_data( "range" ) ) + $character.get_main_weapon_node().get_node( "bullet_exit/target_spring_arm" ).spring_length = min_range + func _on_character_unequip(p_slot): - emit_signal( "unequip", p_slot ) + emit_signal( "unequip", p_slot ) func _on_crosshair_area_body_entered(body): - if not body == $character: - if body is preload( "res://scenes/characters/character.gd" ): - if body.player_relation == body.PLAYER_RELATION.ennemy: - $character/crosshair.get_surface_material( 0 ).albedo_color = Color.red - elif body.player_relation == body.PLAYER_RELATION.friend: - $character/crosshair.get_surface_material( 0 ).albedo_color = Color.green - else: - $character/crosshair.get_surface_material( 0 ).albedo_color = Color.white + if not body == $character: + if body is preload( "res://scenes/characters/character.gd" ): + if body.player_relation == body.PLAYER_RELATION.ennemy: + $character/crosshair.get_surface_material( 0 ).albedo_color = Color.red + elif body.player_relation == body.PLAYER_RELATION.friend: + $character/crosshair.get_surface_material( 0 ).albedo_color = Color.green + else: + $character/crosshair.get_surface_material( 0 ).albedo_color = Color.white func _on_crosshair_area_body_exited(body): - if not body == $character: - $character/target_spring_arm/crosshair.get_surface_material( 0 ).albedo_color = Color.white + if not body == $character: + $character/target_spring_arm/crosshair.get_surface_material( 0 ).albedo_color = Color.white diff --git a/scenes/player_old/player.gd b/scenes/player_old/player.gd index ed8ec8b..63226e2 100644 --- a/scenes/player_old/player.gd +++ b/scenes/player_old/player.gd @@ -16,82 +16,82 @@ var _is_sprinting = false func _ready(): # $camera.make_current() - $model/ra/spring_arm/camera.make_current() + $model/ra/spring_arm/camera.make_current() func _input( event ): - - if event.is_action_pressed( "toggle_sprint" ): - self._is_sprinting = not self._is_sprinting + + if event.is_action_pressed( "toggle_sprint" ): + self._is_sprinting = not self._is_sprinting func _process( delta ): - var input_direction: = self.get_input_direction() + var input_direction: = self.get_input_direction() - # Calculate a move direction vector relative to the camera - # The basis stores the (right, up, -forwards) vectors of our camera. - var forwards: Vector3 = self.camera.global_transform.basis.z * input_direction.z - var right: Vector3 = self.camera.global_transform.basis.x * input_direction.x - var move_direction: = forwards + right - if move_direction.length() > 1.0: - move_direction = move_direction.normalized() - move_direction.y = 0 + # Calculate a move direction vector relative to the camera + # The basis stores the (right, up, -forwards) vectors of our camera. + var forwards: Vector3 = self.camera.global_transform.basis.z * input_direction.z + var right: Vector3 = self.camera.global_transform.basis.x * input_direction.x + var move_direction: = forwards + right + if move_direction.length() > 1.0: + move_direction = move_direction.normalized() + move_direction.y = 0 # skin.move_direction = move_direction - # Rotation + # Rotation # if move_direction: # var target_direction = player.transform.looking_at(player.global_transform.origin + move_direction, Vector3.UP) # player.transform = player.transform.interpolate_with(target_direction, rotation_speed_factor * delta) - player.rotate_y( rotation_speed_factor * (Input.get_action_strength("turn_left") - Input.get_action_strength("turn_right")) ) + player.rotate_y( rotation_speed_factor * (Input.get_action_strength("turn_left") - Input.get_action_strength("turn_right")) ) - # Movement - velocity = self.calculate_velocity(velocity, move_direction, delta) - velocity = player.move_and_slide(velocity, Vector3.UP, true) - - if input_direction: - if not input_direction.z == 0.0: - if self.is_sprinting(): - $model/ra/model/AnimationPlayer.play( "run" ) - else: - $model/ra/model/AnimationPlayer.play( "walk" ) - elif input_direction.x > 0.0: - $model/ra/model/AnimationPlayer.play( "strafe_right" ) - elif input_direction.x < 0.0: - $model/ra/model/AnimationPlayer.play( "strafe_left" ) - - else: - $model/ra/model/AnimationPlayer.play( "idle" ) - + # Movement + velocity = self.calculate_velocity(velocity, move_direction, delta) + velocity = player.move_and_slide(velocity, Vector3.UP, true) + + if input_direction: + if not input_direction.z == 0.0: + if self.is_sprinting(): + $model/ra/model/AnimationPlayer.play( "run" ) + else: + $model/ra/model/AnimationPlayer.play( "walk" ) + elif input_direction.x > 0.0: + $model/ra/model/AnimationPlayer.play( "strafe_right" ) + elif input_direction.x < 0.0: + $model/ra/model/AnimationPlayer.play( "strafe_left" ) + + else: + $model/ra/model/AnimationPlayer.play( "idle" ) + static func get_input_direction() -> Vector3: - return Vector3( - Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), - 0, - Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward") - ) + return Vector3( + Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), + 0, + Input.get_action_strength("move_backward") - Input.get_action_strength("move_forward") + ) func calculate_velocity( - velocity_current: Vector3, - move_direction: Vector3, - delta: float - ) -> Vector3: - var velocity_new := move_direction - if self.is_sprinting(): - velocity_new *= sprint_speed - else: - velocity_new *= move_speed - if velocity_new.length() > max_speed: - velocity_new = velocity_new.normalized() * max_speed - velocity_new.y = velocity_current.y + gravity * delta + velocity_current: Vector3, + move_direction: Vector3, + delta: float + ) -> Vector3: + var velocity_new := move_direction + if self.is_sprinting(): + velocity_new *= sprint_speed + else: + velocity_new *= move_speed + if velocity_new.length() > max_speed: + velocity_new = velocity_new.normalized() * max_speed + velocity_new.y = velocity_current.y + gravity * delta - return velocity_new - + return velocity_new + func load_creature( filename ): - - self.creature = Creatures.Ra_old.new() - self.creature.from_file( filename ) - + + self.creature = Creatures.Ra_old.new() + self.creature.from_file( filename ) + # # version statique. # $model/ra/model/body.set( "blend_shapes/Boobs", self.creature.female_boobs ) # $model/ra/model/body.set( "blend_shapes/Female_hip", self.creature.female_hip ) @@ -101,33 +101,33 @@ func load_creature( filename ): # $model/ra/model/body.set( "blend_shapes/Pregnant", self.creature.female_pregnant ) # $model/ra/model/body.get_surface_material( 0 ).set_shader_param( "albedo", self.creature.color ) # - # Version animée. - $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Boobs", self.creature.female_boobs ) - $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Female_hip", self.creature.female_hip ) - $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Male_Pack", self.creature.male_pack ) - $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Male_Throat", self.creature.male_throat ) - $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Pregnant", self.creature.female_pregnant ) - $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Pregnant", self.creature.female_pregnant ) - $model/ra/model/metarig/Skeleton/body.get_surface_material( 0 ).set_shader_param( "albedo", self.creature.color ) - + # Version animée. + $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Boobs", self.creature.female_boobs ) + $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Female_hip", self.creature.female_hip ) + $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Male_Pack", self.creature.male_pack ) + $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Male_Throat", self.creature.male_throat ) + $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Pregnant", self.creature.female_pregnant ) + $model/ra/model/metarig/Skeleton/body.set( "blend_shapes/Pregnant", self.creature.female_pregnant ) + $model/ra/model/metarig/Skeleton/body.get_surface_material( 0 ).set_shader_param( "albedo", self.creature.color ) + func is_sprinting(): - if (not self._is_sprinting and Input.is_action_pressed( "sprint" )) \ - or (self._is_sprinting and not Input.is_action_pressed( "sprint" )) \ - : - return true - return false + if (not self._is_sprinting and Input.is_action_pressed( "sprint" )) \ + or (self._is_sprinting and not Input.is_action_pressed( "sprint" )) \ + : + return true + return false func rotate_camera_arm( p_axis, p_angle_degree ): - $model/ra/spring_arm.rotate( p_axis, p_angle_degree ) - + $model/ra/spring_arm.rotate( p_axis, p_angle_degree ) + func rotate_camera( p_axis, p_angle_degree ): - $model/ra/spring_arm/camera.rotate( p_axis, p_angle_degree ) - + $model/ra/spring_arm/camera.rotate( p_axis, p_angle_degree ) + func move_camera( p_translation ): - $model/ra/spring_arm/camera.translate( p_translation ) + $model/ra/spring_arm/camera.translate( p_translation ) func reset_camera(): - $model/ra/spring_arm.translation = Vector3( 0, 2, 2 ) - $model/ra/spring_arm.rotation_degrees = Vector3( 0.0, 0.0, 0.0 ) - $model/ra/spring_arm/camera.translation = Vector3( 0.0, 0.0, 0.0 ) - $model/ra/spring_arm/camera.rotation_degrees = Vector3( -14, 0, 0.328 ) + $model/ra/spring_arm.translation = Vector3( 0, 2, 2 ) + $model/ra/spring_arm.rotation_degrees = Vector3( 0.0, 0.0, 0.0 ) + $model/ra/spring_arm/camera.translation = Vector3( 0.0, 0.0, 0.0 ) + $model/ra/spring_arm/camera.rotation_degrees = Vector3( -14, 0, 0.328 )