From 74e37f8a185a115f6864aa5c88bbdfb05cd35140 Mon Sep 17 00:00:00 2001 From: Rendo Date: Sun, 14 Dec 2025 14:54:35 +0500 Subject: [PATCH] pellet spread, bulletholes and balance fixes --- gui/buy_menu/shop.gd | 5 +- gui/host_menu/host_menu.gd | 5 + gui/host_menu/host_menu.tscn | 17 ++- levels/prototype.tscn | 2 +- multiplayer/lobby_settings.gd | 1 + multiplayer/session.gd | 119 ++++++++++-------- textures/bullet_hole.png | Bin 0 -> 24829 bytes textures/bullet_hole.png.import | 40 ++++++ weapons/gun/bullet_hole.tscn | 27 ++++ weapons/gun/mc/mc255.tscn | 27 ++-- weapons/gun/pellet_spread/icon.png | Bin 0 -> 13355 bytes weapons/gun/pellet_spread/icon.png.import | 40 ++++++ weapons/gun/pellet_spread/pellet_spread.gd | 13 ++ .../gun/pellet_spread/pellet_spread.gd.uid | 1 + .../gun/pellet_spread/pellet_spread_random.gd | 22 ++++ .../pellet_spread/pellet_spread_random.gd.uid | 1 + weapons/gun/semi_pellet_shoot_state.gd | 13 +- 17 files changed, 261 insertions(+), 72 deletions(-) create mode 100644 textures/bullet_hole.png create mode 100644 textures/bullet_hole.png.import create mode 100644 weapons/gun/bullet_hole.tscn create mode 100644 weapons/gun/pellet_spread/icon.png create mode 100644 weapons/gun/pellet_spread/icon.png.import create mode 100644 weapons/gun/pellet_spread/pellet_spread.gd create mode 100644 weapons/gun/pellet_spread/pellet_spread.gd.uid create mode 100644 weapons/gun/pellet_spread/pellet_spread_random.gd create mode 100644 weapons/gun/pellet_spread/pellet_spread_random.gd.uid diff --git a/gui/buy_menu/shop.gd b/gui/buy_menu/shop.gd index ea41fe6..66dfbcc 100644 --- a/gui/buy_menu/shop.gd +++ b/gui/buy_menu/shop.gd @@ -2,7 +2,7 @@ extends Node func can_buy(player_id: int,weapon: WeaponResource) -> bool: - return Session.player_data[player_id]["money"] >= weapon.cost + return Session.player_data[player_id]["money"] >= weapon.cost or LobbySettings.infinite_money func buy(player_id: int, weapon: WeaponResource) -> void: if not multiplayer.is_server() or can_buy(player_id,weapon) == false: @@ -27,6 +27,7 @@ func buy(player_id: int, weapon: WeaponResource) -> void: var player_data = Session.player_data[player_id] - player_data["money"] -= weapon.cost + if not LobbySettings.infinite_money: + player_data["money"] -= weapon.cost weapon_system.add(weapon.weapon_system_scene.instantiate(),slot) diff --git a/gui/host_menu/host_menu.gd b/gui/host_menu/host_menu.gd index e93b53b..a48c539 100644 --- a/gui/host_menu/host_menu.gd +++ b/gui/host_menu/host_menu.gd @@ -10,6 +10,7 @@ func _ready() -> void: %RoundBox.set_value_no_signal(LobbySettings.win_score) %AllowMultipleAbilityButton.set_pressed_no_signal(LobbySettings.allow_multiple_abilities) %AllowTeamSwitch.set_pressed_no_signal(LobbySettings.allow_team_switch) + %InfiniteMoney.set_pressed_no_signal(LobbySettings.infinite_money) var popup: PopupMenu = %MapsButton.get_popup() %MapsButton.text = LobbySettings.selected_map @@ -53,3 +54,7 @@ func _on_allow_team_switch_toggled(toggled_on: bool) -> void: func on_maps_index_pressed(index: int): %MapsButton.text = levels_by_index[index] LobbySettings.selected_map = levels_by_index[index] + + +func _on_infinite_money_toggled(toggled_on: bool) -> void: + LobbySettings.infinite_money = toggled_on diff --git a/gui/host_menu/host_menu.tscn b/gui/host_menu/host_menu.tscn index 2078870..e912b27 100644 --- a/gui/host_menu/host_menu.tscn +++ b/gui/host_menu/host_menu.tscn @@ -112,14 +112,24 @@ layout_mode = 2 folded = true title = "Геймплей" -[node name="AllowMultipleAbilityButton" type="CheckButton" parent="Gameplay"] -unique_name_in_owner = true +[node name="VBoxContainer" type="VBoxContainer" parent="Gameplay"] visible = false +layout_mode = 2 + +[node name="AllowMultipleAbilityButton" type="CheckButton" parent="Gameplay/VBoxContainer"] +unique_name_in_owner = true custom_minimum_size = Vector2(200, 0) layout_mode = 2 text = "Неограниченная закупка абилок" autowrap_mode = 2 +[node name="InfiniteMoney" type="CheckButton" parent="Gameplay/VBoxContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +text = "Бесконечные деньги" +autowrap_mode = 2 + [node name="PortForward" type="FoldableContainer" parent="."] layout_mode = 2 folded = true @@ -166,7 +176,8 @@ text = "Перемешать" [connection signal="value_changed" from="Time/VBoxContainer/BuyTime/BuyTimeBox" to="." method="_on_buy_time_box_value_changed"] [connection signal="value_changed" from="Round/VBoxContainer/RoundAmount/RoundBox" to="." method="_on_round_box_value_changed"] [connection signal="value_changed" from="Round/VBoxContainer/TeamSwitchAmount/TeamSwitchBox" to="." method="_on_team_switch_box_value_changed"] -[connection signal="toggled" from="Gameplay/AllowMultipleAbilityButton" to="." method="_on_allow_multiple_ability_button_toggled"] +[connection signal="toggled" from="Gameplay/VBoxContainer/AllowMultipleAbilityButton" to="." method="_on_allow_multiple_ability_button_toggled"] +[connection signal="toggled" from="Gameplay/VBoxContainer/InfiniteMoney" to="." method="_on_infinite_money_toggled"] [connection signal="update_ip" from="PortForward/PortForwardContainer/ForwardPortButton" to="PortForward/PortForwardContainer/PublicIP" method="on_update_ip"] [connection signal="toggled" from="Teams/VBoxContainer/AllowTeamSwitch" to="." method="_on_allow_team_switch_toggled"] [connection signal="pressed" from="Teams/VBoxContainer/Shuffle" to="." method="_on_shuffle_pressed"] diff --git a/levels/prototype.tscn b/levels/prototype.tscn index 6354cc1..d42f582 100644 --- a/levels/prototype.tscn +++ b/levels/prototype.tscn @@ -298,7 +298,7 @@ script = ExtResource("11_02ic3") exlusion_list = [NodePath("MultiplayerSpawner"), NodePath("Bomb"), NodePath("Parenter")] [node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="DynamicObjectsContainer"] -_spawnable_scenes = PackedStringArray("uid://cxdgk74ln5xpn", "uid://dtbpyfdawb02b", "uid://dgfqppi21c2u0", "uid://b6qahd6q60js7", "uid://l4t1mflutm3t", "uid://b3xux7url8d2s") +_spawnable_scenes = PackedStringArray("uid://cxdgk74ln5xpn", "uid://dtbpyfdawb02b", "uid://dgfqppi21c2u0", "uid://b6qahd6q60js7", "uid://l4t1mflutm3t", "uid://b3xux7url8d2s", "uid://u8aj6fs32ql6") spawn_path = NodePath("..") [node name="Parenter" type="Node" parent="DynamicObjectsContainer"] diff --git a/multiplayer/lobby_settings.gd b/multiplayer/lobby_settings.gd index b5e0d26..7639939 100644 --- a/multiplayer/lobby_settings.gd +++ b/multiplayer/lobby_settings.gd @@ -9,4 +9,5 @@ var buy_time: float = 15.0 var round_time: float = 150.0 var allow_multiple_abilities: bool = false var allow_team_switch: bool = true +var infinite_money: bool = false var selected_map: StringName = "prototype" diff --git a/multiplayer/session.gd b/multiplayer/session.gd index 7e4ef1a..0cc5652 100644 --- a/multiplayer/session.gd +++ b/multiplayer/session.gd @@ -1,5 +1,7 @@ extends Node +const BULLET_HOLE: PackedScene = preload("uid://u8aj6fs32ql6") + enum TEAMS { DEFENCE, ATTACK, @@ -325,56 +327,8 @@ func shoot(id:int , limb_damage: int, torso_damage: int,head_damage: int, distan var collision = space.intersect_ray(ray) - if collision != {} and collision["collider"] is Player: - var hit_player: Player = collision["collider"] - var shape_object: CollisionShape3D = hit_player.shape_owner_get_owner(collision["shape"]) - var reduction: float = 1 - var damage: int = 0 - - match shape_object.get_groups()[0]: - "Head": - damage = head_damage - "Limb": - damage = limb_damage - _: - damage = torso_damage - - if damage_reduction_curve != null: - var distance_to_hit = (player_camera.global_position - collision["position"]).length()/distance - reduction = damage_reduction_curve.sample(distance_to_hit) - - hit_player.take_damage(int(float(damage) * reduction)) - - -func shoot_pellets(id:int,amount: int, limb_total_damage: int, torso_total_damage: int,head_total_damage: int, distance: float, arc: float, damage_reduction_curve: Curve = null): - if multiplayer.is_server() == false: - return - - var player: Player = player_nodes[id] - var player_camera: Camera3D = player.get_node("Camera3D") - var space: PhysicsDirectSpaceState3D = player.get_world_3d().direct_space_state - var head_damage: int = head_total_damage / amount - var torso_damage: int = torso_total_damage / amount - var limb_damage: int = limb_total_damage / amount - - for i in range(amount): - var endpoint: Vector3 = player_camera.global_position - player_camera.global_basis.z.rotated(Vector3.RIGHT,randf_range(-arc/2,arc/2)).rotated(Vector3.UP,randf_range(-arc/2,arc/2)) * distance - - var ray = PhysicsRayQueryParameters3D.create(player_camera.global_position,endpoint,1) - ray.exclude = [player.get_rid()] - ray.collide_with_areas = false - match player.team: - TEAMS.DEFENCE: - ray.collision_mask |= ATTACK_LAYER - TEAMS.ATTACK: - ray.collision_mask |= DEFENCE_LAYER - _: - ray.collision_mask |= ATTACK_LAYER | DEFENCE_LAYER - - var collision = space.intersect_ray(ray) - - - if collision != {} and collision["collider"] is Player: + if collision != {}: + if collision["collider"] is Player: var hit_player: Player = collision["collider"] var shape_object: CollisionShape3D = hit_player.shape_owner_get_owner(collision["shape"]) var reduction: float = 1 @@ -393,6 +347,71 @@ func shoot_pellets(id:int,amount: int, limb_total_damage: int, torso_total_damag reduction = damage_reduction_curve.sample(distance_to_hit) hit_player.take_damage(int(float(damage) * reduction)) + + var bullet_hole: Decal = BULLET_HOLE.instantiate() + dynamic_objects_parent.add_child(bullet_hole,true) + + var rotation_quat: Quaternion = Quaternion(Vector3.UP,collision["normal"]) + bullet_hole.quaternion *= rotation_quat + bullet_hole.global_position = collision["position"] + + + +func shoot_pellets(id:int,limb_pellet_damage: int, torso_pellet_damage: int,head_pellet_damage: int, distance: float, pellets: PackedVector2Array, damage_reduction_curve: Curve = null): + if multiplayer.is_server() == false: + return + + var amount: int = len(pellets) + + var player: Player = player_nodes[id] + var player_camera: Camera3D = player.get_node("Camera3D") + var space: PhysicsDirectSpaceState3D = player.get_world_3d().direct_space_state + + for i in range(amount): + var endpoint: Vector3 = player_camera.project_position(pellets[i],distance) + + var ray = PhysicsRayQueryParameters3D.create(player_camera.global_position,endpoint,1) + ray.exclude = [player.get_rid()] + ray.collide_with_areas = false + match player.team: + TEAMS.DEFENCE: + ray.collision_mask |= ATTACK_LAYER + TEAMS.ATTACK: + ray.collision_mask |= DEFENCE_LAYER + _: + ray.collision_mask |= ATTACK_LAYER | DEFENCE_LAYER + + var collision = space.intersect_ray(ray) + + + if collision != {}: + if collision["collider"] is Player: + var hit_player: Player = collision["collider"] + var shape_object: CollisionShape3D = hit_player.shape_owner_get_owner(collision["shape"]) + var reduction: float = 1 + var damage: int = 0 + + match shape_object.get_groups()[0]: + "Head": + damage = head_pellet_damage + "Limb": + damage = limb_pellet_damage + _: + damage = torso_pellet_damage + + if damage_reduction_curve != null: + var distance_to_hit = (player_camera.global_position - collision["position"]).length()/distance + reduction = damage_reduction_curve.sample(distance_to_hit) + + hit_player.take_damage(int(float(damage) * reduction)) + + var bullet_hole: Decal = BULLET_HOLE.instantiate() + dynamic_objects_parent.add_child(bullet_hole,true) + + var rotation_quat: Quaternion = Quaternion(Vector3.UP,collision["normal"]) + + bullet_hole.quaternion *= rotation_quat + bullet_hole.global_position = collision["position"] func interact(id: int) -> void: if multiplayer.is_server() == false: diff --git a/textures/bullet_hole.png b/textures/bullet_hole.png new file mode 100644 index 0000000000000000000000000000000000000000..6cd86d97d3300a4334922ea110e5a8f55a078628 GIT binary patch literal 24829 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 literal 0 HcmV?d00001 diff --git a/textures/bullet_hole.png.import b/textures/bullet_hole.png.import new file mode 100644 index 0000000..f5499f0 --- /dev/null +++ b/textures/bullet_hole.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://djb2h4sf42nqq" +path="res://.godot/imported/bullet_hole.png-c5594de24f88f66a649756099fb11bb7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://textures/bullet_hole.png" +dest_files=["res://.godot/imported/bullet_hole.png-c5594de24f88f66a649756099fb11bb7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/weapons/gun/bullet_hole.tscn b/weapons/gun/bullet_hole.tscn new file mode 100644 index 0000000..d099542 --- /dev/null +++ b/weapons/gun/bullet_hole.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=3 format=3 uid="uid://u8aj6fs32ql6"] + +[ext_resource type="Texture2D" uid="uid://djb2h4sf42nqq" path="res://textures/bullet_hole.png" id="1_wpexx"] + +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_wpexx"] +properties/0/path = NodePath(".:position") +properties/0/spawn = true +properties/0/replication_mode = 1 +properties/1/path = NodePath(".:rotation") +properties/1/spawn = true +properties/1/replication_mode = 1 + +[node name="BulletHole" type="Decal"] +size = Vector3(0.25, 0.5, 0.25) +texture_albedo = ExtResource("1_wpexx") + +[node name="Timer" type="Timer" parent="."] +process_mode = 3 +wait_time = 60.0 +one_shot = true +autostart = true +ignore_time_scale = true + +[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +replication_config = SubResource("SceneReplicationConfig_wpexx") + +[connection signal="timeout" from="Timer" to="." method="queue_free"] diff --git a/weapons/gun/mc/mc255.tscn b/weapons/gun/mc/mc255.tscn index 883b5c7..fd802ec 100644 --- a/weapons/gun/mc/mc255.tscn +++ b/weapons/gun/mc/mc255.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=10 format=3 uid="uid://8ohlfmr5bp0k"] +[gd_scene load_steps=12 format=3 uid="uid://8ohlfmr5bp0k"] [ext_resource type="Script" uid="uid://e6lqknfl4ngt" path="res://systems/weapon_system/weapon_substate_machine.gd" id="1_uck67"] [ext_resource type="Script" uid="uid://ofv4e3dsfe8" path="res://weapons/gun/idle_state.gd" id="2_rkf02"] [ext_resource type="Script" uid="uid://cvueeftqbxb7r" path="res://weapons/gun/semi_pellet_shoot_state.gd" id="3_jk5g7"] [ext_resource type="Script" uid="uid://hmekwp8444ao" path="res://weapons/gun/reload_state.gd" id="4_fs8hh"] [ext_resource type="Script" uid="uid://bmj0bwy2tlian" path="res://weapons/gun/intro_state.gd" id="5_3ok4b"] +[ext_resource type="Script" uid="uid://ryxe3lxtvpk4" path="res://weapons/gun/pellet_spread/pellet_spread.gd" id="6_a53f6"] [sub_resource type="Curve" id="Curve_cmn6f"] _limits = [0.0, 0.1, 0.0, 20.0] @@ -27,6 +28,12 @@ properties/1/path = NodePath(".:remaining_ammo") properties/1/spawn = true properties/1/replication_mode = 2 +[sub_resource type="Curve2D" id="Curve2D_0fc4q"] +_data = { +"points": PackedVector2Array(0, 0, 0, 0, 0, -10, 0, 0, 0, 0, 9, -7, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, -8, -3, 0, 0, 0, 0, -8, 5, 0, 0, 0, 0, -1, 7, 0, 0, 0, 0, 7, 6, 0, 0, 0, 0, 14, 6, 0, 0, 0, 0, 15, -5, 0, 0, 0, 0, 0, -7, 0, 0, 0, 0, -13, -7, 0, 0, 0, 0, -10, 4, 0, 0, 0, 0, -10, 12, 0, 0, 0, 0, -1, 13, 0, 0, 0, 0, 12, 14, 0, 0, 0, 0, 6, 11, 0, 0, 0, 0, 21, 9, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 9, -16, 0, 0, 0, 0, -10, -13, 0, 0, 0, 0, -16, -2, 0, 0, 0, 0, -17, 13, 0, 0, 0, 0, -3, 19, 0, 0, 0, 0, 6, 16, 0, 0, 0, 0, 18, 16, 0, 0, 0, 0, 24, 9, 0, 0, 0, 0, 23, -7, 0, 0, 0, 0, 20, -12) +} +point_count = 28 + [node name="MC255" type="Node" node_paths=PackedStringArray("enter_state")] script = ExtResource("1_uck67") animation_prefix = &"baked_mc_" @@ -41,17 +48,15 @@ metadata/_custom_type_script = "uid://e6lqknfl4ngt" [node name="Idle" type="Node" parent="."] script = ExtResource("2_rkf02") -[node name="Shoot" type="Node" parent="." node_paths=PackedStringArray("fire_timer")] +[node name="Shoot" type="Node" parent="." node_paths=PackedStringArray("pellet_spread", "fire_timer")] script = ExtResource("3_jk5g7") vertical_curve = SubResource("Curve_cmn6f") horizontal_curve = SubResource("Curve_jk5g7") damage_reduction_curve = SubResource("Curve_bwg3m") -torso_total_damage = 100 -head_total_damage = 150 -limb_total_damage = 70 -arc = 0.08726646259971647 -max_pellets = 30 -min_pellets = 30 +torso_pellet_damage = 6 +head_pellet_damage = 24 +limb_pellet_damage = 6 +pellet_spread = NodePath("../PelletSpread") shoot_distance = 40.0 fire_timer = NodePath("../FireTimer") @@ -67,3 +72,9 @@ one_shot = true [node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] replication_config = SubResource("SceneReplicationConfig_bwg3m") + +[node name="PelletSpread" type="Path2D" parent="."] +position = Vector2(640, 360) +curve = SubResource("Curve2D_0fc4q") +script = ExtResource("6_a53f6") +metadata/_custom_type_script = "uid://ryxe3lxtvpk4" diff --git a/weapons/gun/pellet_spread/icon.png b/weapons/gun/pellet_spread/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..15f67787838ef6b93293e2e1d15c524e4b0dce51 GIT binary patch literal 13355 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 G@xK6+vHc1F literal 0 HcmV?d00001 diff --git a/weapons/gun/pellet_spread/icon.png.import b/weapons/gun/pellet_spread/icon.png.import new file mode 100644 index 0000000..4304b37 --- /dev/null +++ b/weapons/gun/pellet_spread/icon.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cs1dapnsaw2vw" +path="res://.godot/imported/icon.png-0bb35b0bcb159408ed12f260c09d8538.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://weapons/gun/pellet_spread/icon.png" +dest_files=["res://.godot/imported/icon.png-0bb35b0bcb159408ed12f260c09d8538.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/weapons/gun/pellet_spread/pellet_spread.gd b/weapons/gun/pellet_spread/pellet_spread.gd new file mode 100644 index 0000000..b33a611 --- /dev/null +++ b/weapons/gun/pellet_spread/pellet_spread.gd @@ -0,0 +1,13 @@ +@icon("res://weapons/gun/pellet_spread/icon.png") +class_name PelletSpread extends Path2D + +func get_dots() -> PackedVector2Array: + var result: PackedVector2Array + + for i in curve.point_count: + result.append(curve.get_point_position(i)) + + for i in range(len(result)): + result[i] += get_viewport_rect().size/2.0 + + return result diff --git a/weapons/gun/pellet_spread/pellet_spread.gd.uid b/weapons/gun/pellet_spread/pellet_spread.gd.uid new file mode 100644 index 0000000..e226298 --- /dev/null +++ b/weapons/gun/pellet_spread/pellet_spread.gd.uid @@ -0,0 +1 @@ +uid://ryxe3lxtvpk4 diff --git a/weapons/gun/pellet_spread/pellet_spread_random.gd b/weapons/gun/pellet_spread/pellet_spread_random.gd new file mode 100644 index 0000000..4bbb6d0 --- /dev/null +++ b/weapons/gun/pellet_spread/pellet_spread_random.gd @@ -0,0 +1,22 @@ +@tool +extends PelletSpread + +class_name PelletSpreadRandom + +const ASPECT = 1.7777777777777777 + +@export var random_amount: int +@export_range(0,89,0.1,"radians_as_degrees") var radius: float +@export var aspect_ratio: float = 1.7777777777777777 + +@export_tool_button("Randomize points") var randomize_button = randomize_points + +func randomize_points() -> void: + curve.clear_points() + var viewport_aspect_trasformation = Vector2(ASPECT,1) + var custom_aspect_transformation = Vector2(aspect_ratio,1./aspect_ratio) + var transformation_vector = get_viewport_rect().size / viewport_aspect_trasformation /PI + for i in range(random_amount): + var unscaled_position = Vector2(randf_range(-radius,radius),randf_range(-radius,radius)) + var scaled_position = unscaled_position*transformation_vector + curve.add_point(scaled_position) diff --git a/weapons/gun/pellet_spread/pellet_spread_random.gd.uid b/weapons/gun/pellet_spread/pellet_spread_random.gd.uid new file mode 100644 index 0000000..6a62569 --- /dev/null +++ b/weapons/gun/pellet_spread/pellet_spread_random.gd.uid @@ -0,0 +1 @@ +uid://b3cvfkvvc5c3g diff --git a/weapons/gun/semi_pellet_shoot_state.gd b/weapons/gun/semi_pellet_shoot_state.gd index 5210493..8488c8c 100644 --- a/weapons/gun/semi_pellet_shoot_state.gd +++ b/weapons/gun/semi_pellet_shoot_state.gd @@ -5,12 +5,10 @@ extends WeaponState @export var damage_reduction_curve: Curve @export var emptyable: bool -@export var torso_total_damage: int -@export var head_total_damage: int -@export var limb_total_damage: int -@export_range(0,179,0.01,"radians_as_degrees") var arc: float -@export_range(1,20,1,"or_greater") var max_pellets: int = 1 -@export_range(1,20,1,"or_greater") var min_pellets: int = 1 +@export var torso_pellet_damage: int +@export var head_pellet_damage: int +@export var limb_pellet_damage: int +@export var pellet_spread: PelletSpread @export var shoot_distance: float = 100 @export var fire_timer: Timer @@ -44,8 +42,7 @@ func fire() -> void: machine.animation_player.play(with_morphems("shoot")) if is_multiplayer_authority(): - var pellets: int = randi_range(min_pellets,max_pellets) - Session.shoot_pellets(int(machine.player.name),pellets,limb_total_damage,torso_total_damage,head_total_damage,shoot_distance,arc,damage_reduction_curve) + Session.shoot_pellets(int(machine.player.name),limb_pellet_damage,torso_pellet_damage,head_pellet_damage,shoot_distance,pellet_spread.get_dots(),damage_reduction_curve) machine.player.get_node("ShootAudio").multiplayer_play() fire_timer.start()