diff --git a/data/coin_flower.tres b/data/coin_flower.tres new file mode 100644 index 0000000..a863c7d --- /dev/null +++ b/data/coin_flower.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="InventoryItem" load_steps=3 format=3 uid="uid://nrpcuqveh7io"] + +[ext_resource type="Texture2D" uid="uid://cb6qv3c0iojfl" path="res://icon.svg" id="1_u477x"] +[ext_resource type="Script" path="res://src/lib/inventory_item.gd" id="3_fe16f"] + +[resource] +script = ExtResource("3_fe16f") +icon = ExtResource("1_u477x") +name = "Coin Flower" +id = &"coin_flower" +stackable = false +stack_limit = 8 +count = 0 diff --git a/data/meat.tres b/data/meat.tres index e9ffa86..f82a196 100644 --- a/data/meat.tres +++ b/data/meat.tres @@ -8,3 +8,4 @@ script = ExtResource("2_inc63") icon = ExtResource("1_2wt7x") name = "Meat" id = &"meat" +count = 0 diff --git a/data/water_bomb.tres b/data/water_bomb.tres new file mode 100644 index 0000000..d3076b6 --- /dev/null +++ b/data/water_bomb.tres @@ -0,0 +1,13 @@ +[gd_resource type="Resource" script_class="InventoryItem" load_steps=4 format=3 uid="uid://cmeif37pci2ek"] + +[ext_resource type="Texture2D" uid="uid://cb6qv3c0iojfl" path="res://icon.svg" id="1_g8c3q"] +[ext_resource type="PackedScene" uid="uid://ba2mut58elwrh" path="res://assets/water-bomb.glb" id="2_5cxkh"] +[ext_resource type="Script" path="res://src/lib/inventory_item.gd" id="2_pe2p8"] + +[resource] +script = ExtResource("2_pe2p8") +icon = ExtResource("1_g8c3q") +model = ExtResource("2_5cxkh") +name = "Water Bomb" +id = &"water_bomb" +count = 0 diff --git a/src/ingame/player.gd b/src/ingame/player.gd index d0a5583..1c4d832 100644 --- a/src/ingame/player.gd +++ b/src/ingame/player.gd @@ -1,4 +1,5 @@ class_name Player extends CharacterBody3D +# TODO: inherit from StairStepper, not the other way around ? Probably by also having base Actor class. const SPEED = 5.0 const JUMP_VELOCITY = 4.5 @@ -24,7 +25,7 @@ var _projectile_speed := 12.0 var _interaction_selection: Node3D var controls_disabled := false -var held_thing: String +var held_thing: InventoryItem # What the others see. @@ -58,7 +59,7 @@ func _physics_process(delta: float) -> void: ## Process interactivity selection. if id == multiplayer.get_unique_id(): var collider: Object = null - if held_thing == "" and _line_of_sight.is_colliding(): + if held_thing == null and _line_of_sight.is_colliding(): collider = _line_of_sight.get_collider(0) if collider != _interaction_selection: if _interaction_selection != null: @@ -99,15 +100,31 @@ func _physics_process(delta: float) -> void: @rpc("any_peer", "call_local", "reliable") -func hold_thing() -> void: - held_thing = "water" - _camera_pivot.get_node("HeldViewmodel").show() - +func hold_thing(p_item_instance_id: int) -> void: + var item = instance_from_id(p_item_instance_id) as InventoryItem + assert(item != null) + held_thing = item + var base_node := _camera_pivot.get_node("HeldViewmodel") + for child in base_node.get_children(): + child.queue_free() + if item.model != null: + var model = item.model.instantiate() + base_node.add_child(model) + if id == multiplayer.get_unique_id(): + # Disable depth test and increase render priority. + # TODO: in more complex scenarios model scene might want to have its own callback for this. + for model in base_node.get_children(): + for submodel in model.get_children(): + var material := submodel.mesh.surface_get_material(0).duplicate() as Material + material.render_priority += 1 + material.no_depth_test = true + submodel.mesh.surface_set_material(0, material) @rpc("any_peer", "call_local", "reliable") func throw_thing() -> void: - held_thing = "" - _camera_pivot.get_node("HeldViewmodel").hide() + held_thing = null # TODO: represent 'empty hand' as a unique item ? + for child in _camera_pivot.get_node("HeldViewmodel").get_children(): + child.queue_free() func _unhandled_input(event: InputEvent) -> void: @@ -120,12 +137,12 @@ func _unhandled_input(event: InputEvent) -> void: _camera_pivot.rotation.x = clamp(_camera_pivot.rotation.x, -1.2, 1.2) return - if event.is_action_pressed("pick") and held_thing == "": + if event.is_action_pressed("pick") and held_thing == null: if _interaction_selection != null: - _interaction_selection.get_parent().get_picked_up.rpc() - hold_thing.rpc() + hold_thing.rpc(_interaction_selection.owner.item_component.get_instance_id()) + _interaction_selection.owner.get_picked_up.rpc() - if event.is_action_pressed("fire") and held_thing != "": + if event.is_action_pressed("fire") and held_thing != null: var new_projectile: Node3D = _projectile_scene.instantiate() _projectile_holder.add_child(new_projectile, true) _set_projectile_authority.rpc(new_projectile.get_path(), id) diff --git a/src/ingame/player.tscn b/src/ingame/player.tscn index a0459d5..ff23de5 100644 --- a/src/ingame/player.tscn +++ b/src/ingame/player.tscn @@ -97,10 +97,10 @@ debug_shape_custom_color = Color(0.628721, 0, 0.256939, 1) [node name="HeldViewmodel" type="Node3D" parent="CameraPivot"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.2, -1) -visible = false [node name="Model" parent="CameraPivot/HeldViewmodel" instance=ExtResource("4_bfvih")] -material_override = SubResource("StandardMaterial3D_x7r08") +material_override = null +material = SubResource("StandardMaterial3D_x7r08") [node name="ShotSound" type="AudioStreamPlayer3D" parent="."] stream = ExtResource("3_u2hxa") diff --git a/src/ingame/sprout.gd b/src/ingame/sprout.gd index 459b6a2..ff82bf9 100644 --- a/src/ingame/sprout.gd +++ b/src/ingame/sprout.gd @@ -5,6 +5,8 @@ extends Node3D @export var _mesh: MeshInstance3D @export var _area: Area3D +@export var item_component: InventoryItem + var needs_water := true var stage: int = 1 var final_stage: int = 3 diff --git a/src/ingame/sprout.tscn b/src/ingame/sprout.tscn index bae1f70..4f553fb 100644 --- a/src/ingame/sprout.tscn +++ b/src/ingame/sprout.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=9 format=3 uid="uid://bysgtksvovyur"] +[gd_scene load_steps=10 format=3 uid="uid://bysgtksvovyur"] [ext_resource type="Script" path="res://src/ingame/sprout.gd" id="1_snma1"] +[ext_resource type="Resource" uid="uid://nrpcuqveh7io" path="res://data/coin_flower.tres" id="2_amjnn"] [ext_resource type="Texture2D" uid="uid://d35y5ckne72qe" path="res://assets/sprout1.png" id="2_ipgad"] [ext_resource type="Shader" path="res://scenes/interactivity_outline2.gdshader" id="2_oa2it"] [ext_resource type="Texture2D" uid="uid://cwbl0r1e26eja" path="res://assets/drop.png" id="3_kghdv"] @@ -35,6 +36,7 @@ _need_water_drop = NodePath("NeedWaterDrop") _production_timer = NodePath("ProductionTimer") _mesh = NodePath("Mesh") _area = NodePath("Area3D") +item_component = ExtResource("2_amjnn") [node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] replication_config = SubResource("SceneReplicationConfig_rs2qp") diff --git a/src/ingame/water_bomb.gd b/src/ingame/water_bomb.gd index b26d04c..286d1bb 100644 --- a/src/ingame/water_bomb.gd +++ b/src/ingame/water_bomb.gd @@ -8,6 +8,8 @@ extends Node3D @export var body: RigidBody3D ## no longer exists and shouldn't be considered, but not ready to be freed yet @export var is_dead := false +## by convention is looked up in owner from areas +@export var item_component: InventoryItem var _in_splash_range := {} diff --git a/src/ingame/water_bomb.tscn b/src/ingame/water_bomb.tscn index 130ea8c..63b8d00 100644 --- a/src/ingame/water_bomb.tscn +++ b/src/ingame/water_bomb.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=11 format=3 uid="uid://tdsbo3e5ic86"] +[gd_scene load_steps=12 format=3 uid="uid://tdsbo3e5ic86"] [ext_resource type="Script" path="res://src/ingame/water_bomb.gd" id="1_lk5fq"] [ext_resource type="AudioStream" uid="uid://dtjpv2b74g24m" path="res://assets/sfx/splash-small.wav" id="2_0wk8g"] +[ext_resource type="Resource" uid="uid://cmeif37pci2ek" path="res://data/water_bomb.tres" id="2_b3357"] [ext_resource type="PackedScene" uid="uid://ba2mut58elwrh" path="res://assets/water-bomb.glb" id="2_v2imr"] [ext_resource type="AudioStream" uid="uid://blgrl2wl05feq" path="res://assets/sfx/splash-small-quiet.wav" id="3_hgy7l"] @@ -57,6 +58,7 @@ _model = NodePath("Model") _splash_particles = NodePath("SplashParticles") _picking_area = NodePath("PickingArea") body = NodePath("RigidBody3D") +item_component = ExtResource("2_b3357") [node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] replication_config = SubResource("SceneReplicationConfig_0ebrr") diff --git a/src/lib/game_state.gd b/src/lib/game_state.gd index d2d62df..2e646ee 100644 --- a/src/lib/game_state.gd +++ b/src/lib/game_state.gd @@ -3,6 +3,8 @@ extends Resource const INVENTORY_ITEM_DB = { &"meat": preload("res://data/meat.tres"), + &"water_bomb": preload("res://data/water_bomb.tres"), + &"coin_flower": preload("res://data/coin_flower.tres"), } # keys are multiplayer ID ints, values are PlayerData diff --git a/src/lib/inventory_item.gd b/src/lib/inventory_item.gd index d80f670..87a3104 100644 --- a/src/lib/inventory_item.gd +++ b/src/lib/inventory_item.gd @@ -2,7 +2,11 @@ class_name InventoryItem extends Resource @export var icon: Texture2D = preload("res://icon.svg") +@export var model: PackedScene @export var name := "NAME" @export var id := &"ID" +@export var stackable := false +@export var stack_limit := 8 +# TODO: should it be here? or context dependent, for different inventories @export var count := 0