commit 6cc5cd4eccabf25632dc19bb294c8162e0d58677 Author: copygirl Date: Wed Apr 23 18:05:53 2025 +0200 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..ec1ec57 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# copyThrower + +A customized and personalized object thrower mod for [SnekStudio], made +available in case anyone wants to adapt it for their own use, or take some +inspiration. + +Since I am not an affiliate with Twitch (by choice), I can't use redeems, +so instead the thrown objects, hearts in this case, are triggered by simply +inserting unicode heart emoji and Twitch pride emotes in one's message. + +[SnekStudio]: https://github.com/ExpiredPopsicle/SnekStudio + +## Credits + +Feel free to consider the source code of this project to be under public domain. +However, note that I've used some some resources from other people that might not be: + +- [Pride flag textures](https://www.prideflags.org/) by **Emily Noble** (GPL3) +- ["Tomato Squish"](https://freesound.org/s/684877/) by **ominouswhoosh** (CC0) +- ["Smashing / squishing"](https://freesound.org/s/269485/) by **editor_adp** (CC0) +- ["Quacky Duck Toy SFX.wav"](https://freesound.org/s/366136/) by **DCSFX** (CC BY-NC 3.0) diff --git a/Resources/heart.gd b/Resources/heart.gd new file mode 100644 index 0000000..814bc8c --- /dev/null +++ b/Resources/heart.gd @@ -0,0 +1,93 @@ +extends RigidBody3D + +## If this heart were to exist for longer than 1 minute for some reason, destroy it. +## The heart should also disappear if it falls low enough. +var lifetime := 60.0 # 1 minute + +## If this heart has impacted another object already. +## Prevents repeated impact sounds and sticking. +var impacted := false + +## Relative size of the heart. Affects audio pitch. +## Used later to decide how impactful a collision was. +var size := 1.0 + +## Whether the heart will stick to avatars when colliding. +var sticky := false + +## How long the heart will be sticking before falling off again. +@onready var sticky_timer := randf_range(3, 6) # 3 to 6 seconds + +# Remember the original parent this node was created under, so if the +# heart sticks to a character, it can return here once it unsticks. +@onready var original_parent: Node = get_parent() + +static var stream_normal: AudioStream = load("res://Mods/copyThrower/Resources/normal_randomizer.tres") +static var stream_sticky: AudioStream = load("res://Mods/copyThrower/Resources/sticky_randomizer.tres") + +func _ready() -> void: + body_entered.connect(on_body_entered) + + # Give it a little bit of random spin. + var random_vector := Vector3(randf() - 0.5, randf() - 0.5, randf() - 0.5).normalized() + angular_velocity = random_vector * randf_range(0, 25) * TAU + angular_damp = 5.0 + + +func set_size(value: float) -> void: + size = value + $Model.scale *= value + $CollisionShape3D.scale *= value + $AudioStreamPlayer3D.pitch_scale = 1 / lerpf(1, value, 0.5) + +func set_sticky(value: bool) -> void: + sticky = value + if value: $AudioStreamPlayer3D.stream = stream_sticky + else: $AudioStreamPlayer3D.stream = stream_normal + +func set_material(material: StandardMaterial3D) -> void: + $Model/Heart.material_override = material + + +func _process(delta: float) -> void: + # Kill heart if it ever lives too long. + lifetime -= delta + if lifetime <= 0: queue_free(); return + + # Kill heart if it falls too low. + if global_position.y < -10: queue_free(); return + + # Unsticky heart after some time. + if get_parent() is CharacterBody3D: + sticky_timer -= delta + if sticky_timer <= 0: + set_physics_active(true) + reparent(original_parent) + +func on_body_entered(body: Node) -> void: + if not (body is CharacterBody3D): return + if impacted: return + impacted = true + + $AudioStreamPlayer3D.play() + original_parent.on_collide(self, body) + + if sticky: + await get_tree().process_frame; + set_physics_active(false) + set_gravity_scale(0.0) + reparent(body) + + +func set_physics_active(active: bool) -> void: + if active: + sleeping = false + collision_mask = 1 + set_gravity_scale(1.0) + else: + sleeping = true + linear_velocity = Vector3.ZERO + angular_velocity = Vector3.ZERO + collision_mask = 0 + collision_layer = 0 + set_gravity_scale(0.0) diff --git a/Resources/heart.gd.uid b/Resources/heart.gd.uid new file mode 100644 index 0000000..8821956 --- /dev/null +++ b/Resources/heart.gd.uid @@ -0,0 +1 @@ +uid://ba4w1hier1kps diff --git a/Resources/heart.glb b/Resources/heart.glb new file mode 100644 index 0000000..cb06f9f Binary files /dev/null and b/Resources/heart.glb differ diff --git a/Resources/heart.glb.import b/Resources/heart.glb.import new file mode 100644 index 0000000..56c9024 --- /dev/null +++ b/Resources/heart.glb.import @@ -0,0 +1,37 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bryal7hhfonuv" +path="res://.godot/imported/heart.glb-8f2fa658593887ed7614985c9670402c.scn" + +[deps] + +source_file="res://Mods/copyThrower/Resources/heart.glb" +dest_files=["res://.godot/imported/heart.glb-8f2fa658593887ed7614985c9670402c.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=1 +gltf/embedded_image_handling=1 diff --git a/Resources/heart.tscn b/Resources/heart.tscn new file mode 100644 index 0000000..6ef9d54 --- /dev/null +++ b/Resources/heart.tscn @@ -0,0 +1,26 @@ +[gd_scene load_steps=5 format=3 uid="uid://m7kmum7ygiw2"] + +[ext_resource type="Script" uid="uid://ba4w1hier1kps" path="res://Mods/copyThrower/Resources/heart.gd" id="1_h4gh1"] +[ext_resource type="PackedScene" uid="uid://bryal7hhfonuv" path="res://Mods/copyThrower/Resources/heart.glb" id="1_liglp"] +[ext_resource type="AudioStream" uid="uid://jmgp1vmm5mdf" path="res://Mods/copyThrower/Resources/sticky_randomizer.tres" id="3_4n8sw"] + +[sub_resource type="CylinderShape3D" id="CylinderShape3D_rfhqb"] +height = 0.04 +radius = 0.055 + +[node name="Heart" type="RigidBody3D"] +contact_monitor = true +max_contacts_reported = 1 +script = ExtResource("1_h4gh1") + +[node name="Model" parent="." instance=ExtResource("1_liglp")] +transform = Transform3D(0.6, 0, 0, 0, 0.6, 0, 0, 0, 0.6, 0, 0, 0) + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) +shape = SubResource("CylinderShape3D_rfhqb") + +[node name="AudioStreamPlayer3D" type="AudioStreamPlayer3D" parent="."] +stream = ExtResource("3_4n8sw") +attenuation_model = 3 +volume_db = -2.0 diff --git a/Resources/hit.ogg b/Resources/hit.ogg new file mode 100644 index 0000000..a219722 Binary files /dev/null and b/Resources/hit.ogg differ diff --git a/Resources/hit.ogg.import b/Resources/hit.ogg.import new file mode 100644 index 0000000..0deec76 --- /dev/null +++ b/Resources/hit.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bemf7rek7uw0" +path="res://.godot/imported/hit.ogg-75bb5a24498ee15323ed4e8239a38e29.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/hit.ogg" +dest_files=["res://.godot/imported/hit.ogg-75bb5a24498ee15323ed4e8239a38e29.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/normal_randomizer.tres b/Resources/normal_randomizer.tres new file mode 100644 index 0000000..1fb4fb5 --- /dev/null +++ b/Resources/normal_randomizer.tres @@ -0,0 +1,30 @@ +[gd_resource type="AudioStreamRandomizer" load_steps=12 format=3 uid="uid://by5roe3uixyln"] + +[ext_resource type="AudioStream" uid="uid://bemf7rek7uw0" path="res://Mods/copyThrower/Resources/hit.ogg" id="1_lgv4g"] +[ext_resource type="AudioStream" uid="uid://w0afmnf25amu" path="res://Mods/copyThrower/Resources/quack/quack1.ogg" id="2_1jhxa"] +[ext_resource type="AudioStream" uid="uid://c0aj3lu57ouk3" path="res://Mods/copyThrower/Resources/quack/quack10.ogg" id="3_s6at6"] +[ext_resource type="AudioStream" uid="uid://brt8c36n7plgk" path="res://Mods/copyThrower/Resources/quack/quack2.ogg" id="4_8h5t2"] +[ext_resource type="AudioStream" uid="uid://btiqou5sh01s0" path="res://Mods/copyThrower/Resources/quack/quack3.ogg" id="5_l41b8"] +[ext_resource type="AudioStream" uid="uid://b8rkjdy5808ft" path="res://Mods/copyThrower/Resources/quack/quack4.ogg" id="6_ghljm"] +[ext_resource type="AudioStream" uid="uid://dtsbx2lq2usys" path="res://Mods/copyThrower/Resources/quack/quack5.ogg" id="7_ujw1d"] +[ext_resource type="AudioStream" uid="uid://d11i0wwlnv6i6" path="res://Mods/copyThrower/Resources/quack/quack6.ogg" id="8_qhlsn"] +[ext_resource type="AudioStream" uid="uid://d1sivl5xxc43h" path="res://Mods/copyThrower/Resources/quack/quack7.ogg" id="9_3m6fm"] +[ext_resource type="AudioStream" uid="uid://dxookg0qh7pte" path="res://Mods/copyThrower/Resources/quack/quack8.ogg" id="10_vcq6v"] +[ext_resource type="AudioStream" uid="uid://dcgqtxd8abl75" path="res://Mods/copyThrower/Resources/quack/quack9.ogg" id="11_o5vlg"] + +[resource] +playback_mode = 1 +random_pitch = 1.1 +streams_count = 11 +stream_0/stream = ExtResource("1_lgv4g") +stream_0/weight = 200.0 +stream_1/stream = ExtResource("2_1jhxa") +stream_2/stream = ExtResource("4_8h5t2") +stream_3/stream = ExtResource("5_l41b8") +stream_4/stream = ExtResource("6_ghljm") +stream_5/stream = ExtResource("7_ujw1d") +stream_6/stream = ExtResource("8_qhlsn") +stream_7/stream = ExtResource("9_3m6fm") +stream_8/stream = ExtResource("10_vcq6v") +stream_9/stream = ExtResource("11_o5vlg") +stream_10/stream = ExtResource("3_s6at6") diff --git a/Resources/pride/asexual.png b/Resources/pride/asexual.png new file mode 100644 index 0000000..3baa6b0 Binary files /dev/null and b/Resources/pride/asexual.png differ diff --git a/Resources/pride/asexual.png.import b/Resources/pride/asexual.png.import new file mode 100644 index 0000000..6e5e48e --- /dev/null +++ b/Resources/pride/asexual.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cgdomumia1234" +path="res://.godot/imported/asexual.png-2b5061eec087826d6fef7abae37e6c5a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/asexual.png" +dest_files=["res://.godot/imported/asexual.png-2b5061eec087826d6fef7abae37e6c5a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/bisexual.png b/Resources/pride/bisexual.png new file mode 100644 index 0000000..050f9e1 Binary files /dev/null and b/Resources/pride/bisexual.png differ diff --git a/Resources/pride/bisexual.png.import b/Resources/pride/bisexual.png.import new file mode 100644 index 0000000..c20a82c --- /dev/null +++ b/Resources/pride/bisexual.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bklvlne08bamb" +path="res://.godot/imported/bisexual.png-a126a4370573f7f9c82c5939f7c08bab.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/bisexual.png" +dest_files=["res://.godot/imported/bisexual.png-a126a4370573f7f9c82c5939f7c08bab.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/gay.png b/Resources/pride/gay.png new file mode 100644 index 0000000..63b6d0b Binary files /dev/null and b/Resources/pride/gay.png differ diff --git a/Resources/pride/gay.png.import b/Resources/pride/gay.png.import new file mode 100644 index 0000000..3c07d63 --- /dev/null +++ b/Resources/pride/gay.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://yca3b7m7vmyk" +path="res://.godot/imported/gay.png-83ada93434c9987daadf01e2a0e1db4d.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/gay.png" +dest_files=["res://.godot/imported/gay.png-83ada93434c9987daadf01e2a0e1db4d.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/genderfluid.png b/Resources/pride/genderfluid.png new file mode 100644 index 0000000..d5baba4 Binary files /dev/null and b/Resources/pride/genderfluid.png differ diff --git a/Resources/pride/genderfluid.png.import b/Resources/pride/genderfluid.png.import new file mode 100644 index 0000000..bd9b617 --- /dev/null +++ b/Resources/pride/genderfluid.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://wpeo2k1e1mj4" +path="res://.godot/imported/genderfluid.png-bfa065efb07f77992ef5b7064b1e7d19.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/genderfluid.png" +dest_files=["res://.godot/imported/genderfluid.png-bfa065efb07f77992ef5b7064b1e7d19.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/intersex.png b/Resources/pride/intersex.png new file mode 100644 index 0000000..c40edb8 Binary files /dev/null and b/Resources/pride/intersex.png differ diff --git a/Resources/pride/intersex.png.import b/Resources/pride/intersex.png.import new file mode 100644 index 0000000..64e3dd1 --- /dev/null +++ b/Resources/pride/intersex.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bulpp4vo0y0hu" +path="res://.godot/imported/intersex.png-5628374e71a834027717a98fabd79fb3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/intersex.png" +dest_files=["res://.godot/imported/intersex.png-5628374e71a834027717a98fabd79fb3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/lesbian.png b/Resources/pride/lesbian.png new file mode 100644 index 0000000..9af46bc Binary files /dev/null and b/Resources/pride/lesbian.png differ diff --git a/Resources/pride/lesbian.png.import b/Resources/pride/lesbian.png.import new file mode 100644 index 0000000..567b3cb --- /dev/null +++ b/Resources/pride/lesbian.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://doigfjgxdrwwi" +path="res://.godot/imported/lesbian.png-518664f89a7b91d130c4a2df04cfeca3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/lesbian.png" +dest_files=["res://.godot/imported/lesbian.png-518664f89a7b91d130c4a2df04cfeca3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/nonbinary.png b/Resources/pride/nonbinary.png new file mode 100644 index 0000000..a48785a Binary files /dev/null and b/Resources/pride/nonbinary.png differ diff --git a/Resources/pride/nonbinary.png.import b/Resources/pride/nonbinary.png.import new file mode 100644 index 0000000..cf22518 --- /dev/null +++ b/Resources/pride/nonbinary.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bo5rorx5cqnbv" +path="res://.godot/imported/nonbinary.png-bd21c674d6601f9b0758df429dcc498c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/nonbinary.png" +dest_files=["res://.godot/imported/nonbinary.png-bd21c674d6601f9b0758df429dcc498c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/pansexual.png b/Resources/pride/pansexual.png new file mode 100644 index 0000000..1b2df1c Binary files /dev/null and b/Resources/pride/pansexual.png differ diff --git a/Resources/pride/pansexual.png.import b/Resources/pride/pansexual.png.import new file mode 100644 index 0000000..3649824 --- /dev/null +++ b/Resources/pride/pansexual.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://1fho2xcjjy4j" +path="res://.godot/imported/pansexual.png-60a9a7db650bd350916b81d7adbf85d3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/pansexual.png" +dest_files=["res://.godot/imported/pansexual.png-60a9a7db650bd350916b81d7adbf85d3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/pride/transgender.png b/Resources/pride/transgender.png new file mode 100644 index 0000000..a3e6561 Binary files /dev/null and b/Resources/pride/transgender.png differ diff --git a/Resources/pride/transgender.png.import b/Resources/pride/transgender.png.import new file mode 100644 index 0000000..b5621cf --- /dev/null +++ b/Resources/pride/transgender.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://p705e363jsns" +path="res://.godot/imported/transgender.png-f2978c64b823749f8ea405018724b9f2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Mods/copyThrower/Resources/pride/transgender.png" +dest_files=["res://.godot/imported/transgender.png-f2978c64b823749f8ea405018724b9f2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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/Resources/quack/quack1.ogg b/Resources/quack/quack1.ogg new file mode 100644 index 0000000..ed04f01 Binary files /dev/null and b/Resources/quack/quack1.ogg differ diff --git a/Resources/quack/quack1.ogg.import b/Resources/quack/quack1.ogg.import new file mode 100644 index 0000000..22074b8 --- /dev/null +++ b/Resources/quack/quack1.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://w0afmnf25amu" +path="res://.godot/imported/quack1.ogg-153fb2b3fcffd4281fe990160e4c1965.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack1.ogg" +dest_files=["res://.godot/imported/quack1.ogg-153fb2b3fcffd4281fe990160e4c1965.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack10.ogg b/Resources/quack/quack10.ogg new file mode 100644 index 0000000..ae369dd Binary files /dev/null and b/Resources/quack/quack10.ogg differ diff --git a/Resources/quack/quack10.ogg.import b/Resources/quack/quack10.ogg.import new file mode 100644 index 0000000..e4d99ef --- /dev/null +++ b/Resources/quack/quack10.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://c0aj3lu57ouk3" +path="res://.godot/imported/quack10.ogg-100308789c5bfdb515186fd1b1c0daea.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack10.ogg" +dest_files=["res://.godot/imported/quack10.ogg-100308789c5bfdb515186fd1b1c0daea.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack2.ogg b/Resources/quack/quack2.ogg new file mode 100644 index 0000000..89064b0 Binary files /dev/null and b/Resources/quack/quack2.ogg differ diff --git a/Resources/quack/quack2.ogg.import b/Resources/quack/quack2.ogg.import new file mode 100644 index 0000000..987b48d --- /dev/null +++ b/Resources/quack/quack2.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://brt8c36n7plgk" +path="res://.godot/imported/quack2.ogg-60ed43efcec098cefa3c0c2f30fdce9c.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack2.ogg" +dest_files=["res://.godot/imported/quack2.ogg-60ed43efcec098cefa3c0c2f30fdce9c.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack3.ogg b/Resources/quack/quack3.ogg new file mode 100644 index 0000000..fb57b0a Binary files /dev/null and b/Resources/quack/quack3.ogg differ diff --git a/Resources/quack/quack3.ogg.import b/Resources/quack/quack3.ogg.import new file mode 100644 index 0000000..d6831e3 --- /dev/null +++ b/Resources/quack/quack3.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://btiqou5sh01s0" +path="res://.godot/imported/quack3.ogg-4d5c07869a86a643202431038ef27c57.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack3.ogg" +dest_files=["res://.godot/imported/quack3.ogg-4d5c07869a86a643202431038ef27c57.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack4.ogg b/Resources/quack/quack4.ogg new file mode 100644 index 0000000..2541593 Binary files /dev/null and b/Resources/quack/quack4.ogg differ diff --git a/Resources/quack/quack4.ogg.import b/Resources/quack/quack4.ogg.import new file mode 100644 index 0000000..a2486b7 --- /dev/null +++ b/Resources/quack/quack4.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://b8rkjdy5808ft" +path="res://.godot/imported/quack4.ogg-d0f262ca60d0614d7393f469abd8beba.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack4.ogg" +dest_files=["res://.godot/imported/quack4.ogg-d0f262ca60d0614d7393f469abd8beba.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack5.ogg b/Resources/quack/quack5.ogg new file mode 100644 index 0000000..eeccfba Binary files /dev/null and b/Resources/quack/quack5.ogg differ diff --git a/Resources/quack/quack5.ogg.import b/Resources/quack/quack5.ogg.import new file mode 100644 index 0000000..d9302e6 --- /dev/null +++ b/Resources/quack/quack5.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dtsbx2lq2usys" +path="res://.godot/imported/quack5.ogg-126a3875c6b96b3c953774c145fe4271.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack5.ogg" +dest_files=["res://.godot/imported/quack5.ogg-126a3875c6b96b3c953774c145fe4271.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack6.ogg b/Resources/quack/quack6.ogg new file mode 100644 index 0000000..56a4006 Binary files /dev/null and b/Resources/quack/quack6.ogg differ diff --git a/Resources/quack/quack6.ogg.import b/Resources/quack/quack6.ogg.import new file mode 100644 index 0000000..2394e7c --- /dev/null +++ b/Resources/quack/quack6.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://d11i0wwlnv6i6" +path="res://.godot/imported/quack6.ogg-e1986d5fb29c4f2f9ec9cae0804950d0.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack6.ogg" +dest_files=["res://.godot/imported/quack6.ogg-e1986d5fb29c4f2f9ec9cae0804950d0.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack7.ogg b/Resources/quack/quack7.ogg new file mode 100644 index 0000000..ec83bc6 Binary files /dev/null and b/Resources/quack/quack7.ogg differ diff --git a/Resources/quack/quack7.ogg.import b/Resources/quack/quack7.ogg.import new file mode 100644 index 0000000..5672bb2 --- /dev/null +++ b/Resources/quack/quack7.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://d1sivl5xxc43h" +path="res://.godot/imported/quack7.ogg-a4e63cdc4af40a6f1153b4d8d8df6481.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack7.ogg" +dest_files=["res://.godot/imported/quack7.ogg-a4e63cdc4af40a6f1153b4d8d8df6481.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack8.ogg b/Resources/quack/quack8.ogg new file mode 100644 index 0000000..36b0112 Binary files /dev/null and b/Resources/quack/quack8.ogg differ diff --git a/Resources/quack/quack8.ogg.import b/Resources/quack/quack8.ogg.import new file mode 100644 index 0000000..82ebb0d --- /dev/null +++ b/Resources/quack/quack8.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dxookg0qh7pte" +path="res://.godot/imported/quack8.ogg-31abed4b2c9207e7a850c25532ef1bfb.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack8.ogg" +dest_files=["res://.godot/imported/quack8.ogg-31abed4b2c9207e7a850c25532ef1bfb.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/quack/quack9.ogg b/Resources/quack/quack9.ogg new file mode 100644 index 0000000..5ae7ac6 Binary files /dev/null and b/Resources/quack/quack9.ogg differ diff --git a/Resources/quack/quack9.ogg.import b/Resources/quack/quack9.ogg.import new file mode 100644 index 0000000..f2414ab --- /dev/null +++ b/Resources/quack/quack9.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dcgqtxd8abl75" +path="res://.godot/imported/quack9.ogg-5f77a19642102571a53d5acf2d39c978.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/quack/quack9.ogg" +dest_files=["res://.godot/imported/quack9.ogg-5f77a19642102571a53d5acf2d39c978.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish1.ogg b/Resources/squish/squish1.ogg new file mode 100644 index 0000000..7cedc71 Binary files /dev/null and b/Resources/squish/squish1.ogg differ diff --git a/Resources/squish/squish1.ogg.import b/Resources/squish/squish1.ogg.import new file mode 100644 index 0000000..08c4816 --- /dev/null +++ b/Resources/squish/squish1.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://tasj05d071a7" +path="res://.godot/imported/squish1.ogg-a67addf1f9c0f71b553015471b780443.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish1.ogg" +dest_files=["res://.godot/imported/squish1.ogg-a67addf1f9c0f71b553015471b780443.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish2.ogg b/Resources/squish/squish2.ogg new file mode 100644 index 0000000..47ecf6c Binary files /dev/null and b/Resources/squish/squish2.ogg differ diff --git a/Resources/squish/squish2.ogg.import b/Resources/squish/squish2.ogg.import new file mode 100644 index 0000000..7d82795 --- /dev/null +++ b/Resources/squish/squish2.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://bhbmaqqahqgy8" +path="res://.godot/imported/squish2.ogg-a7e1e3895e3b26418e52dc3812d256c9.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish2.ogg" +dest_files=["res://.godot/imported/squish2.ogg-a7e1e3895e3b26418e52dc3812d256c9.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish3.ogg b/Resources/squish/squish3.ogg new file mode 100644 index 0000000..a9e87eb Binary files /dev/null and b/Resources/squish/squish3.ogg differ diff --git a/Resources/squish/squish3.ogg.import b/Resources/squish/squish3.ogg.import new file mode 100644 index 0000000..5ddf46c --- /dev/null +++ b/Resources/squish/squish3.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://41u5qh27cj4t" +path="res://.godot/imported/squish3.ogg-ec402bc051f3bfea95e16d8b9f0fbd7e.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish3.ogg" +dest_files=["res://.godot/imported/squish3.ogg-ec402bc051f3bfea95e16d8b9f0fbd7e.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish4.ogg b/Resources/squish/squish4.ogg new file mode 100644 index 0000000..e5b4717 Binary files /dev/null and b/Resources/squish/squish4.ogg differ diff --git a/Resources/squish/squish4.ogg.import b/Resources/squish/squish4.ogg.import new file mode 100644 index 0000000..46653cc --- /dev/null +++ b/Resources/squish/squish4.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://clqc4a5aalhej" +path="res://.godot/imported/squish4.ogg-bc9d7dd3cdfbfca6141e448a7a05c7ee.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish4.ogg" +dest_files=["res://.godot/imported/squish4.ogg-bc9d7dd3cdfbfca6141e448a7a05c7ee.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish5.ogg b/Resources/squish/squish5.ogg new file mode 100644 index 0000000..22fb661 Binary files /dev/null and b/Resources/squish/squish5.ogg differ diff --git a/Resources/squish/squish5.ogg.import b/Resources/squish/squish5.ogg.import new file mode 100644 index 0000000..3f967f3 --- /dev/null +++ b/Resources/squish/squish5.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dxs6yen5eipvt" +path="res://.godot/imported/squish5.ogg-6f9b48b5ae6dd53f1808b4948c754bfd.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish5.ogg" +dest_files=["res://.godot/imported/squish5.ogg-6f9b48b5ae6dd53f1808b4948c754bfd.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish6.ogg b/Resources/squish/squish6.ogg new file mode 100644 index 0000000..c92fb41 Binary files /dev/null and b/Resources/squish/squish6.ogg differ diff --git a/Resources/squish/squish6.ogg.import b/Resources/squish/squish6.ogg.import new file mode 100644 index 0000000..6a38a69 --- /dev/null +++ b/Resources/squish/squish6.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dwsqeq70oshsp" +path="res://.godot/imported/squish6.ogg-f31459211a7dcc62a89f634d10a5875e.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish6.ogg" +dest_files=["res://.godot/imported/squish6.ogg-f31459211a7dcc62a89f634d10a5875e.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish7.ogg b/Resources/squish/squish7.ogg new file mode 100644 index 0000000..5e5a9a1 Binary files /dev/null and b/Resources/squish/squish7.ogg differ diff --git a/Resources/squish/squish7.ogg.import b/Resources/squish/squish7.ogg.import new file mode 100644 index 0000000..2a3674b --- /dev/null +++ b/Resources/squish/squish7.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://8c48dhwcedio" +path="res://.godot/imported/squish7.ogg-8fa24581fd6f162eedf9dcf5a9fba1da.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish7.ogg" +dest_files=["res://.godot/imported/squish7.ogg-8fa24581fd6f162eedf9dcf5a9fba1da.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish8.ogg b/Resources/squish/squish8.ogg new file mode 100644 index 0000000..a7a8ec6 Binary files /dev/null and b/Resources/squish/squish8.ogg differ diff --git a/Resources/squish/squish8.ogg.import b/Resources/squish/squish8.ogg.import new file mode 100644 index 0000000..cec336c --- /dev/null +++ b/Resources/squish/squish8.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://ugenhlaoxrgm" +path="res://.godot/imported/squish8.ogg-f94fb399cf6f5cff59f324d588a276e4.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish8.ogg" +dest_files=["res://.godot/imported/squish8.ogg-f94fb399cf6f5cff59f324d588a276e4.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/squish/squish9.ogg b/Resources/squish/squish9.ogg new file mode 100644 index 0000000..7e0879b Binary files /dev/null and b/Resources/squish/squish9.ogg differ diff --git a/Resources/squish/squish9.ogg.import b/Resources/squish/squish9.ogg.import new file mode 100644 index 0000000..2d14e82 --- /dev/null +++ b/Resources/squish/squish9.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://5uoe5bopdd8t" +path="res://.godot/imported/squish9.ogg-36b3385a49c14f884d87a23b80fb2468.oggvorbisstr" + +[deps] + +source_file="res://Mods/copyThrower/Resources/squish/squish9.ogg" +dest_files=["res://.godot/imported/squish9.ogg-36b3385a49c14f884d87a23b80fb2468.oggvorbisstr"] + +[params] + +loop=false +loop_offset=0 +bpm=0 +beat_count=0 +bar_beats=4 diff --git a/Resources/sticky_randomizer.tres b/Resources/sticky_randomizer.tres new file mode 100644 index 0000000..31f53ee --- /dev/null +++ b/Resources/sticky_randomizer.tres @@ -0,0 +1,24 @@ +[gd_resource type="AudioStreamRandomizer" load_steps=10 format=3 uid="uid://jmgp1vmm5mdf"] + +[ext_resource type="AudioStream" uid="uid://tasj05d071a7" path="res://Mods/copyThrower/Resources/squish/squish1.ogg" id="1_jleyq"] +[ext_resource type="AudioStream" uid="uid://bhbmaqqahqgy8" path="res://Mods/copyThrower/Resources/squish/squish2.ogg" id="2_kt7v0"] +[ext_resource type="AudioStream" uid="uid://41u5qh27cj4t" path="res://Mods/copyThrower/Resources/squish/squish3.ogg" id="3_yx1ld"] +[ext_resource type="AudioStream" uid="uid://clqc4a5aalhej" path="res://Mods/copyThrower/Resources/squish/squish4.ogg" id="4_i4lv8"] +[ext_resource type="AudioStream" uid="uid://dxs6yen5eipvt" path="res://Mods/copyThrower/Resources/squish/squish5.ogg" id="5_7ddlg"] +[ext_resource type="AudioStream" uid="uid://dwsqeq70oshsp" path="res://Mods/copyThrower/Resources/squish/squish6.ogg" id="6_hwrs4"] +[ext_resource type="AudioStream" uid="uid://8c48dhwcedio" path="res://Mods/copyThrower/Resources/squish/squish7.ogg" id="7_5y8ld"] +[ext_resource type="AudioStream" uid="uid://ugenhlaoxrgm" path="res://Mods/copyThrower/Resources/squish/squish8.ogg" id="8_mhcya"] +[ext_resource type="AudioStream" uid="uid://5uoe5bopdd8t" path="res://Mods/copyThrower/Resources/squish/squish9.ogg" id="9_exsdi"] + +[resource] +random_pitch = 1.1 +streams_count = 9 +stream_0/stream = ExtResource("1_jleyq") +stream_1/stream = ExtResource("2_kt7v0") +stream_2/stream = ExtResource("3_yx1ld") +stream_3/stream = ExtResource("4_i4lv8") +stream_4/stream = ExtResource("5_7ddlg") +stream_5/stream = ExtResource("6_hwrs4") +stream_6/stream = ExtResource("7_5y8ld") +stream_7/stream = ExtResource("8_mhcya") +stream_8/stream = ExtResource("9_exsdi") diff --git a/copyThrower.gd b/copyThrower.gd new file mode 100644 index 0000000..4b5d36d --- /dev/null +++ b/copyThrower.gd @@ -0,0 +1,168 @@ +extends Mod_Base + +# How quickly the hearts get thrown, with randomized delay. +@export var queue_delay_min := 0.04 +@export var queue_delay_max := 0.16 + +# Randomized size variation. (Larger = less likely to stick.) +@export var size_min := 0.8 +@export var size_max := 1.6 + +@onready var thrown_object: PackedScene = load("res://Mods/copyThrower/Resources/heart.tscn") + +var body_bump := Vector3.ZERO +var head_bump := Quaternion.IDENTITY +var current_body_bump := Vector3.ZERO +var current_head_bump := Quaternion.IDENTITY + +var triggers = { + # First number is chance to stick. + "โค๏ธ" : [ 0.15, colored_heart(Color.RED) ], + "๐Ÿงก" : [ 0.15, colored_heart(Color.ORANGE) ], + "๐Ÿ’›" : [ 0.15, colored_heart(Color.YELLOW) ], + "๐Ÿ’š" : [ 0.15, colored_heart(Color.GREEN) ], + "๐Ÿฉต" : [ 0.15, colored_heart(Color.AQUA) ], + "๐Ÿ’™" : [ 0.15, colored_heart(Color.BLUE) ], + "๐Ÿ’œ" : [ 0.15, colored_heart(Color.PURPLE) ], + "๐Ÿฉท" : [ 0.15, colored_heart(Color.PINK) ], + "๐ŸคŽ" : [ 0.15, colored_heart(Color.BROWN) ], + "๐Ÿ–ค" : [ 0.15, colored_heart(Color(0.1, 0.1, 0.1)) ], + "๐Ÿฉถ" : [ 0.15, colored_heart(Color.DARK_GRAY) ], + "๐Ÿค" : [ 0.15, colored_heart(Color.WHITE_SMOKE) ], + + "โ™ฅ๏ธ" : [ 0.15, colored_heart(Color.RED) ], # Oldschool heart + "<3" : [ 0.15, colored_heart(Color8(145, 70, 255)) ], # Twitch purple heart + + "AsexualPride" : [ 0.15, textured_heart("asexual") ], + "BisexualPride" : [ 0.15, textured_heart("bisexual") ], + "GayPride" : [ 0.15, textured_heart("gay") ], + "GenderFluidPride" : [ 0.15, textured_heart("genderfluid") ], + "IntersexPride" : [ 0.15, textured_heart("intersex") ], + "LesbianPride" : [ 0.15, textured_heart("lesbian") ], + "NonbinaryPride" : [ 0.15, textured_heart("nonbinary") ], + "PansexualPride" : [ 0.15, textured_heart("pansexual") ], + "TransgenderPride" : [ 0.15, textured_heart("transgender") ], +} + +var queue: Array[RigidBody3D] = [] +var queue_delay := 0.0 + +func handle_channel_chat_message( + _cheerer_username: String, + _cheerer_display_name: String, + message: String, + _bits_count: int, +) -> void: + var matches := [] + # Collect all the matching substrings in the `matches` array. + for trigger in triggers: + var sticky: float = triggers[trigger][0] + var material: StandardMaterial3D = triggers[trigger][1] + var from_index := 0 + while true: + var found := message.find(trigger, from_index) + if found < 0: break + matches.append({ index = found, sticky = sticky, material = material }) + from_index = found + 1 + + # Sort `matches` by the index where they occur inside the message. + matches.sort_custom(func(a, b): return a.index < b.index) + + for match in matches: + var object: RigidBody3D = thrown_object.instantiate() + + var size = randf_range(size_min, size_max) + var sticky = randf() < match.sticky + # Make it so > 1.0 size is less likely to be sticky. + if sticky and size > 1: sticky = randf() > (size - 1) / (size_max - 1) + + object.set_sticky(sticky) + object.set_size(size) + object.set_material(match.material) + + add_autodelete_object(object) + queue.append(object) + +func _process(delta: float) -> void: + var skeleton := get_skeleton() + + # Apply body and head "bumping" that causes the avatar to "shake" in response to being hit. + if skeleton: + current_body_bump = current_body_bump.slerp(body_bump, 1 - 0.001 ** delta) + current_head_bump = current_head_bump.slerp(head_bump, 1 - 0.001 ** delta) + body_bump = body_bump.slerp(Vector3.ZERO, 1 - 0.01 ** delta) + head_bump = head_bump.slerp(Quaternion.IDENTITY, 1 - 0.01 ** delta) + + var base_bone := skeleton.find_bone("Hips") + var base_rest := skeleton.get_bone_global_rest(base_bone) + skeleton.set_bone_global_pose(base_bone, base_rest.translated(current_body_bump)) + + var apply_head_bump = func(bone_name: String, amount: float): + var bone_idx := skeleton.find_bone(bone_name) + var bone_rot := skeleton.get_bone_pose_rotation(bone_idx) + var new_rot := Quaternion.IDENTITY.slerp(current_head_bump, amount) * bone_rot + skeleton.set_bone_pose_rotation(bone_idx, new_rot) + + apply_head_bump.call("Head" , 0.6); + apply_head_bump.call("Neck" , 0.3); + apply_head_bump.call("Chest", 0.1); + + if queue.is_empty(): + queue_delay = 0 + else: + queue_delay -= delta + while queue.size() > 0 and queue_delay <= 0: + var object: RigidBody3D = queue.pop_front() + queue_delay += randf_range(queue_delay_min, queue_delay_max) + + # Only return now because we do want to clear the queue even if the skeleton was missing, and the doctor was never heard from again! [pause for comedic effect] Anyway, that's how I lost my medical license. + if not skeleton: return + + # Add object early so we can use global_position. + add_child(object) + + var random_offset := Vector3(randf_range(-0.06, 0.06), randf_range(0.05, 0.3), 0.0) + var random_velocity := Vector3(randf() - 0.5, randf() - 0.5, randf() - 0.5).normalized() * randf_range(0.0, 0.4) + + var head_bone := skeleton.find_bone("Head") + var head_pos := skeleton.get_bone_global_pose(head_bone).origin + var target_pos := skeleton.global_position + head_pos + random_offset + var camera_pos := get_viewport().get_camera_3d().global_position + + var pos := camera_pos + Vector3([-0.3, 0.3].pick_random(), -0.4, 0) + var vel := (target_pos - pos) * randf_range(1.0, 2.0) + random_velocity + + vel[1] += 9.8 * pos.distance_to(target_pos) / vel.length() / 2 + + object.global_position = pos + object.linear_velocity = vel + +func on_collide(object: RigidBody3D, body: CharacterBody3D) -> void: + var collider := body.get_parent() as BoneAttachment3D + if not collider: return + + var pos := object.global_position + var vel := object.linear_velocity + + # Hits to the head cause the head (and some parent bones) to rotate. + if collider.bone_name == "Head": + var bone_pos := collider.global_position + var rotation := Quaternion(bone_pos.direction_to(pos), bone_pos.direction_to(pos + vel)) + rotation = Quaternion.IDENTITY.slerp(rotation, 0.15 * object.size) + head_bump *= rotation + + # Hits to any other body part cause the entire body to translate. + else: + vel.y *= 0.25 # Less vertical influence. + body_bump += vel * object.size * 0.05 + +static func colored_heart(color: Color) -> StandardMaterial3D: + var material := StandardMaterial3D.new() + material.albedo_color = color + return material + +static func textured_heart(pride: String) -> StandardMaterial3D: + var texture: Texture2D = load("res://Mods/copyThrower/Resources/pride/" + pride + ".png") + var material := StandardMaterial3D.new() + material.albedo_texture = texture + return material diff --git a/copyThrower.gd.uid b/copyThrower.gd.uid new file mode 100644 index 0000000..3f4c437 --- /dev/null +++ b/copyThrower.gd.uid @@ -0,0 +1 @@ +uid://ct4jb6me3rbeh diff --git a/copyThrower.tscn b/copyThrower.tscn new file mode 100644 index 0000000..32d4f73 --- /dev/null +++ b/copyThrower.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://bihbkek3jpsvb"] + +[ext_resource type="Script" uid="uid://ct4jb6me3rbeh" path="res://Mods/copyThrower/copyThrower.gd" id="1_ac3lf"] + +[node name="copyThrower" type="Node"] +script = ExtResource("1_ac3lf") diff --git a/description.txt b/description.txt new file mode 100644 index 0000000..790e3f0 --- /dev/null +++ b/description.txt @@ -0,0 +1 @@ +An alternative object thrower hardcoded to throw colored and textured pride hearts in response to unicode heart emoji and Twitch pride emotes being sent in Twitch chat.