Milestone 2: Beast
This update to the code adds a fully working beast, which is randomly selected and can capture any of the other players.
This commit is contained in:
		
							parent
							
								
									dfe714044d
								
							
						
					
					
						commit
						812821b510
					
				
					 7 changed files with 242 additions and 14 deletions
				
			
		|  | @ -203,3 +203,108 @@ unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" | ||||||
| ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash | ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash | ||||||
| kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") | kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") | ||||||
| rm -rf \"{temp_dir}\"" | rm -rf \"{temp_dir}\"" | ||||||
|  | 
 | ||||||
|  | [preset.4] | ||||||
|  | 
 | ||||||
|  | name="macOS" | ||||||
|  | platform="macOS" | ||||||
|  | runnable=true | ||||||
|  | dedicated_server=false | ||||||
|  | custom_features="" | ||||||
|  | export_filter="all_resources" | ||||||
|  | include_filter="" | ||||||
|  | exclude_filter="" | ||||||
|  | export_path="../Desktop/Exports/mac/mac.zip" | ||||||
|  | encryption_include_filters="" | ||||||
|  | encryption_exclude_filters="" | ||||||
|  | encrypt_pck=false | ||||||
|  | encrypt_directory=false | ||||||
|  | 
 | ||||||
|  | [preset.4.options] | ||||||
|  | 
 | ||||||
|  | export/distribution_type=1 | ||||||
|  | binary_format/architecture="universal" | ||||||
|  | custom_template/debug="" | ||||||
|  | custom_template/release="" | ||||||
|  | debug/export_console_wrapper=1 | ||||||
|  | application/icon="" | ||||||
|  | application/icon_interpolation=4 | ||||||
|  | application/bundle_identifier="com.freeftf" | ||||||
|  | application/signature="" | ||||||
|  | application/app_category="Games" | ||||||
|  | application/short_version="" | ||||||
|  | application/version="" | ||||||
|  | application/copyright="" | ||||||
|  | application/copyright_localized={} | ||||||
|  | application/min_macos_version="10.13" | ||||||
|  | application/export_angle=0 | ||||||
|  | display/high_res=true | ||||||
|  | xcode/platform_build="14C18" | ||||||
|  | xcode/sdk_version="13.1" | ||||||
|  | xcode/sdk_build="22C55" | ||||||
|  | xcode/sdk_name="macosx13.1" | ||||||
|  | xcode/xcode_version="1420" | ||||||
|  | xcode/xcode_build="14C18" | ||||||
|  | codesign/codesign=1 | ||||||
|  | codesign/installer_identity="" | ||||||
|  | codesign/apple_team_id="" | ||||||
|  | codesign/identity="" | ||||||
|  | codesign/entitlements/custom_file="" | ||||||
|  | codesign/entitlements/allow_jit_code_execution=false | ||||||
|  | codesign/entitlements/allow_unsigned_executable_memory=false | ||||||
|  | codesign/entitlements/allow_dyld_environment_variables=false | ||||||
|  | codesign/entitlements/disable_library_validation=false | ||||||
|  | codesign/entitlements/audio_input=false | ||||||
|  | codesign/entitlements/camera=false | ||||||
|  | codesign/entitlements/location=false | ||||||
|  | codesign/entitlements/address_book=false | ||||||
|  | codesign/entitlements/calendars=false | ||||||
|  | codesign/entitlements/photos_library=false | ||||||
|  | codesign/entitlements/apple_events=false | ||||||
|  | codesign/entitlements/debugging=false | ||||||
|  | codesign/entitlements/app_sandbox/enabled=true | ||||||
|  | codesign/entitlements/app_sandbox/network_server=false | ||||||
|  | codesign/entitlements/app_sandbox/network_client=false | ||||||
|  | codesign/entitlements/app_sandbox/device_usb=false | ||||||
|  | codesign/entitlements/app_sandbox/device_bluetooth=false | ||||||
|  | codesign/entitlements/app_sandbox/files_downloads=0 | ||||||
|  | codesign/entitlements/app_sandbox/files_pictures=0 | ||||||
|  | codesign/entitlements/app_sandbox/files_music=0 | ||||||
|  | codesign/entitlements/app_sandbox/files_movies=0 | ||||||
|  | codesign/entitlements/app_sandbox/files_user_selected=0 | ||||||
|  | codesign/entitlements/app_sandbox/helper_executables=[] | ||||||
|  | codesign/custom_options=PackedStringArray() | ||||||
|  | notarization/notarization=0 | ||||||
|  | privacy/microphone_usage_description="" | ||||||
|  | privacy/microphone_usage_description_localized={} | ||||||
|  | privacy/camera_usage_description="" | ||||||
|  | privacy/camera_usage_description_localized={} | ||||||
|  | privacy/location_usage_description="" | ||||||
|  | privacy/location_usage_description_localized={} | ||||||
|  | privacy/address_book_usage_description="" | ||||||
|  | privacy/address_book_usage_description_localized={} | ||||||
|  | privacy/calendar_usage_description="" | ||||||
|  | privacy/calendar_usage_description_localized={} | ||||||
|  | privacy/photos_library_usage_description="" | ||||||
|  | privacy/photos_library_usage_description_localized={} | ||||||
|  | privacy/desktop_folder_usage_description="" | ||||||
|  | privacy/desktop_folder_usage_description_localized={} | ||||||
|  | privacy/documents_folder_usage_description="" | ||||||
|  | privacy/documents_folder_usage_description_localized={} | ||||||
|  | privacy/downloads_folder_usage_description="" | ||||||
|  | privacy/downloads_folder_usage_description_localized={} | ||||||
|  | privacy/network_volumes_usage_description="" | ||||||
|  | privacy/network_volumes_usage_description_localized={} | ||||||
|  | privacy/removable_volumes_usage_description="" | ||||||
|  | privacy/removable_volumes_usage_description_localized={} | ||||||
|  | ssh_remote_deploy/enabled=false | ||||||
|  | ssh_remote_deploy/host="user@host_ip" | ||||||
|  | ssh_remote_deploy/port="22" | ||||||
|  | ssh_remote_deploy/extra_args_ssh="" | ||||||
|  | ssh_remote_deploy/extra_args_scp="" | ||||||
|  | ssh_remote_deploy/run_script="#!/usr/bin/env bash | ||||||
|  | unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" | ||||||
|  | open \"{temp_dir}/{exe_name}.app\" --args {cmd_args}" | ||||||
|  | ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash | ||||||
|  | kill $(pgrep -x -f \"{temp_dir}/{exe_name}.app/Contents/MacOS/{exe_name} {cmd_args}\") | ||||||
|  | rm -rf \"{temp_dir}\"" | ||||||
|  |  | ||||||
|  | @ -24,3 +24,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7, 1, 3) | ||||||
| 
 | 
 | ||||||
| [node name="computers2" parent="." instance=ExtResource("2_28qhl")] | [node name="computers2" parent="." instance=ExtResource("2_28qhl")] | ||||||
| transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 3) | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 3) | ||||||
|  | 
 | ||||||
|  | [node name="Camera3D" type="Camera3D" parent="."] | ||||||
|  | transform = Transform3D(1, 0, 0, 0, 0.984808, 0.173648, 0, -0.173648, 0.984808, 0, 5, 29) | ||||||
|  |  | ||||||
|  | @ -59,7 +59,7 @@ grow_vertical = 0 | ||||||
| [node name="Label" type="Label" parent="ver_string"] | [node name="Label" type="Label" parent="ver_string"] | ||||||
| layout_mode = 2 | layout_mode = 2 | ||||||
| theme_override_font_sizes/font_size = 32 | theme_override_font_sizes/font_size = 32 | ||||||
| text = "Milestone 1" | text = "Milestone 2" | ||||||
| 
 | 
 | ||||||
| [connection signal="pressed" from="main_content/create" to="." method="_on_create_pressed"] | [connection signal="pressed" from="main_content/create" to="." method="_on_create_pressed"] | ||||||
| [connection signal="pressed" from="main_content/join" to="." method="_on_join_pressed"] | [connection signal="pressed" from="main_content/join" to="." method="_on_join_pressed"] | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| [gd_scene load_steps=4 format=3 uid="uid://b440i2oidk5sp"] | [gd_scene load_steps=5 format=3 uid="uid://b440i2oidk5sp"] | ||||||
| 
 | 
 | ||||||
| [ext_resource type="Script" path="res://scripts/movement.gd" id="1_uru11"] | [ext_resource type="Script" path="res://scripts/movement.gd" id="1_uru11"] | ||||||
| 
 | 
 | ||||||
|  | @ -6,9 +6,23 @@ | ||||||
| 
 | 
 | ||||||
| [sub_resource type="CapsuleMesh" id="CapsuleMesh_fhldf"] | [sub_resource type="CapsuleMesh" id="CapsuleMesh_fhldf"] | ||||||
| 
 | 
 | ||||||
|  | [sub_resource type="BoxShape3D" id="BoxShape3D_e4age"] | ||||||
|  | size = Vector3(0.5, 1, 0.75) | ||||||
|  | 
 | ||||||
| [node name="player" type="CharacterBody3D"] | [node name="player" type="CharacterBody3D"] | ||||||
|  | collision_layer = 2 | ||||||
|  | collision_mask = 3 | ||||||
| script = ExtResource("1_uru11") | script = ExtResource("1_uru11") | ||||||
| 
 | 
 | ||||||
|  | [node name="in_bag" type="ColorRect" parent="."] | ||||||
|  | visible = false | ||||||
|  | anchors_preset = 15 | ||||||
|  | anchor_right = 1.0 | ||||||
|  | anchor_bottom = 1.0 | ||||||
|  | grow_horizontal = 2 | ||||||
|  | grow_vertical = 2 | ||||||
|  | color = Color(0, 0, 0, 1) | ||||||
|  | 
 | ||||||
| [node name="collision" type="CollisionShape3D" parent="."] | [node name="collision" type="CollisionShape3D" parent="."] | ||||||
| shape = SubResource("CapsuleShape3D_2l8cp") | shape = SubResource("CapsuleShape3D_2l8cp") | ||||||
| 
 | 
 | ||||||
|  | @ -20,3 +34,37 @@ transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, | ||||||
| 
 | 
 | ||||||
| [node name="Camera3D" type="Camera3D" parent="cam_y"] | [node name="Camera3D" type="Camera3D" parent="cam_y"] | ||||||
| transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8) | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 8) | ||||||
|  | 
 | ||||||
|  | [node name="detect_hit" type="Area3D" parent="."] | ||||||
|  | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0.25, -1.5) | ||||||
|  | collision_layer = 2 | ||||||
|  | collision_mask = 7 | ||||||
|  | 
 | ||||||
|  | [node name="CollisionShape3D" type="CollisionShape3D" parent="detect_hit"] | ||||||
|  | shape = SubResource("BoxShape3D_e4age") | ||||||
|  | disabled = true | ||||||
|  | 
 | ||||||
|  | [node name="hammer_bag" type="CSGBox3D" parent="."] | ||||||
|  | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.5, 0.25, -0.75) | ||||||
|  | visible = false | ||||||
|  | size = Vector3(0.25, 0.25, 1) | ||||||
|  | 
 | ||||||
|  | [node name="CSGBox3D" type="CSGBox3D" parent="hammer_bag"] | ||||||
|  | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -0.75) | ||||||
|  | size = Vector3(0.5, 1, 0.75) | ||||||
|  | 
 | ||||||
|  | [node name="CSGCylinder3D" type="CSGCylinder3D" parent="hammer_bag"] | ||||||
|  | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.5, -0.25, 1.75) | ||||||
|  | height = 1.0 | ||||||
|  | 
 | ||||||
|  | [node name="CSGSphere3D" type="CSGSphere3D" parent="hammer_bag/CSGCylinder3D"] | ||||||
|  | transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) | ||||||
|  | visible = false | ||||||
|  | radius = 0.375 | ||||||
|  | 
 | ||||||
|  | [node name="time_in_bag" type="Timer" parent="."] | ||||||
|  | wait_time = 10.0 | ||||||
|  | one_shot = true | ||||||
|  | 
 | ||||||
|  | [connection signal="body_entered" from="detect_hit" to="." method="_on_detect_hit_body_entered"] | ||||||
|  | [connection signal="timeout" from="time_in_bag" to="." method="_on_time_in_bag_timeout"] | ||||||
|  |  | ||||||
|  | @ -62,6 +62,12 @@ zoom_out={ | ||||||
| ] | ] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [layer_names] | ||||||
|  | 
 | ||||||
|  | 3d_physics/layer_1="world" | ||||||
|  | 3d_physics/layer_2="players" | ||||||
|  | 3d_physics/layer_3="movables" | ||||||
|  | 
 | ||||||
| [rendering] | [rendering] | ||||||
| 
 | 
 | ||||||
| textures/vram_compression/import_etc2_astc=true | textures/vram_compression/import_etc2_astc=true | ||||||
|  |  | ||||||
|  | @ -13,7 +13,12 @@ const SPEED = 5.0 | ||||||
| const JUMP_VELOCITY = 4.5 | const JUMP_VELOCITY = 4.5 | ||||||
| var zoom = 0 | var zoom = 0 | ||||||
| var player_no | var player_no | ||||||
|  | var npc = false | ||||||
| var enabled = false | var enabled = false | ||||||
|  | var caught = false | ||||||
|  | var captured_by | ||||||
|  | var position_pre | ||||||
|  | var got_person = false | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") | var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") | ||||||
|  | @ -21,12 +26,11 @@ var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") | ||||||
| func _ready(): | func _ready(): | ||||||
| 	player_no = Game.players | 	player_no = Game.players | ||||||
| 	Game.players += 1 | 	Game.players += 1 | ||||||
| 	print(Server.players) |  | ||||||
| 	print(Server.players_numbered[player_no]) |  | ||||||
| 	print(multiplayer.get_unique_id()) |  | ||||||
| 	if Server.players_numbered[player_no] == multiplayer.get_unique_id(): | 	if Server.players_numbered[player_no] == multiplayer.get_unique_id(): | ||||||
| 		enabled = true | 		enabled = true | ||||||
| 		$cam_y/Camera3D.current = true | 		$cam_y/Camera3D.current = true | ||||||
|  | 	else: | ||||||
|  | 		npc = true | ||||||
| 
 | 
 | ||||||
| func _physics_process(delta): | func _physics_process(delta): | ||||||
| 	if enabled: | 	if enabled: | ||||||
|  | @ -50,8 +54,12 @@ func _physics_process(delta): | ||||||
| 		move_and_slide() | 		move_and_slide() | ||||||
| 		Server.sync_player.rpc(name, position, rotation) | 		Server.sync_player.rpc(name, position, rotation) | ||||||
| 	 | 	 | ||||||
|  | 	if caught and !npc: | ||||||
|  | 		Server.sync_player.rpc(name, position, rotation) | ||||||
|  | 	 | ||||||
|  | 	 | ||||||
| func _input(event): | func _input(event): | ||||||
| 	if enabled: | 	if !npc: | ||||||
| 		 | 		 | ||||||
| 		if event is InputEventMouseMotion and (Input.is_action_pressed("cam_look") or $cam_y/Camera3D.position.z == 0): | 		if event is InputEventMouseMotion and (Input.is_action_pressed("cam_look") or $cam_y/Camera3D.position.z == 0): | ||||||
| 			var camera_rotation = event.relative * 0.01 | 			var camera_rotation = event.relative * 0.01 | ||||||
|  | @ -66,8 +74,7 @@ func _input(event): | ||||||
| 			rotate(Vector3.DOWN, camera_rotation.x) | 			rotate(Vector3.DOWN, camera_rotation.x) | ||||||
| 
 | 
 | ||||||
| func _unhandled_input(event): | func _unhandled_input(event): | ||||||
| 	if enabled: | 	if !npc: | ||||||
| 	 |  | ||||||
| 		if event.is_action_pressed("zoom_in") && $cam_y/Camera3D.position.z > 0: | 		if event.is_action_pressed("zoom_in") && $cam_y/Camera3D.position.z > 0: | ||||||
| 			zoom = -1 | 			zoom = -1 | ||||||
| 			$cam_y/Camera3D.position.z += zoom | 			$cam_y/Camera3D.position.z += zoom | ||||||
|  | @ -76,3 +83,45 @@ func _unhandled_input(event): | ||||||
| 			$cam_y/Camera3D.position.z += zoom | 			$cam_y/Camera3D.position.z += zoom | ||||||
| 		else: | 		else: | ||||||
| 			zoom = 0 | 			zoom = 0 | ||||||
|  | 			 | ||||||
|  | func beast_init(): | ||||||
|  | 	position.y += 10 | ||||||
|  | 	$detect_hit.monitoring = true | ||||||
|  | 	$detect_hit.monitorable = true | ||||||
|  | 	$detect_hit/CollisionShape3D.disabled = false | ||||||
|  | 	$hammer_bag.visible = true | ||||||
|  | 
 | ||||||
|  | func _on_detect_hit_body_entered(body): | ||||||
|  | 	if enabled and body is CharacterBody3D and !got_person: | ||||||
|  | 		Server.player_hit.rpc(body.name, name) | ||||||
|  | 
 | ||||||
|  | func captured(beast): | ||||||
|  | 	if !npc: | ||||||
|  | 		$in_bag.visible = true | ||||||
|  | 	print(beast) | ||||||
|  | 	$time_in_bag.start() | ||||||
|  | 	visible = false | ||||||
|  | 	enabled = false | ||||||
|  | 	caught = true | ||||||
|  | 	captured_by = beast | ||||||
|  | 	position_pre = position | ||||||
|  | 	position = Vector3(10000, 10000, 10000) | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | func got_one(target): | ||||||
|  | 	got_person = true | ||||||
|  | 	$hammer_bag/CSGCylinder3D/CSGSphere3D.visible = true | ||||||
|  | 
 | ||||||
|  | func lost_one(): | ||||||
|  | 	got_person = false | ||||||
|  | 	$hammer_bag/CSGCylinder3D/CSGSphere3D.visible = false | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | func _on_time_in_bag_timeout(): | ||||||
|  | 	visible = true | ||||||
|  | 	if !npc: | ||||||
|  | 		enabled = true | ||||||
|  | 	caught = false | ||||||
|  | 	captured_by.lost_one() | ||||||
|  | 	position = position_pre | ||||||
|  | 	$in_bag.visible = false | ||||||
|  |  | ||||||
|  | @ -22,7 +22,6 @@ func join_game(ip): | ||||||
| 	var peer = ENetMultiplayerPeer.new() | 	var peer = ENetMultiplayerPeer.new() | ||||||
| 	var error = peer.create_client(ip, PORT) | 	var error = peer.create_client(ip, PORT) | ||||||
| 	if error: | 	if error: | ||||||
| 		print("error") |  | ||||||
| 		return error | 		return error | ||||||
| 	multiplayer.multiplayer_peer = peer | 	multiplayer.multiplayer_peer = peer | ||||||
| 
 | 
 | ||||||
|  | @ -31,10 +30,8 @@ func create_game(): | ||||||
| 	var peer = ENetMultiplayerPeer.new() | 	var peer = ENetMultiplayerPeer.new() | ||||||
| 	var error = peer.create_server(PORT, MAX_CONNECTIONS) | 	var error = peer.create_server(PORT, MAX_CONNECTIONS) | ||||||
| 	if error: | 	if error: | ||||||
| 		print("error") |  | ||||||
| 		return error | 		return error | ||||||
| 	multiplayer.multiplayer_peer = peer | 	multiplayer.multiplayer_peer = peer | ||||||
| 	print("done") |  | ||||||
| 
 | 
 | ||||||
| @rpc("any_peer", "call_remote", "reliable") | @rpc("any_peer", "call_remote", "reliable") | ||||||
| func send_playerinfo(name, id): | func send_playerinfo(name, id): | ||||||
|  | @ -43,6 +40,7 @@ func send_playerinfo(name, id): | ||||||
| 		players[id] = name | 		players[id] = name | ||||||
| 		label = get_tree().root.get_node("create/player_list/list") | 		label = get_tree().root.get_node("create/player_list/list") | ||||||
| 		label.text = "" | 		label.text = "" | ||||||
|  | 		print(players) | ||||||
| 		for w in players: | 		for w in players: | ||||||
| 			if done == 1: | 			if done == 1: | ||||||
| 				label.text = str(label.text +"\n" + players[w]) | 				label.text = str(label.text +"\n" + players[w]) | ||||||
|  | @ -62,8 +60,11 @@ func start_game(server_players): | ||||||
| 		var player = character.instantiate() | 		var player = character.instantiate() | ||||||
| 		player.name = "player" + str(i) | 		player.name = "player" + str(i) | ||||||
| 		i += 1 | 		i += 1 | ||||||
| 		player.position.z = -i*1.5 | 		player.position.z = -i*2.5 | ||||||
| 		map.add_child(player) | 		map.add_child(player) | ||||||
|  | 	if multiplayer.is_server(): | ||||||
|  | 		var random = randi() % Server.players.size() | ||||||
|  | 		sync_beast.rpc(random) | ||||||
| 		 | 		 | ||||||
| @rpc("any_peer", "call_remote", "unreliable") | @rpc("any_peer", "call_remote", "unreliable") | ||||||
| func sync_player(node_name, position, rotation): | func sync_player(node_name, position, rotation): | ||||||
|  | @ -71,8 +72,24 @@ func sync_player(node_name, position, rotation): | ||||||
| 	current_character.position = position | 	current_character.position = position | ||||||
| 	current_character.rotation = rotation | 	current_character.rotation = rotation | ||||||
| 
 | 
 | ||||||
| @rpc("authority", "call_local", "reliable") | @rpc("authority", "call_remote", "reliable") | ||||||
| func sync_computers(node_name, current): | func sync_computers(node_name, current): | ||||||
| 	var current_character = get_tree().root.get_node("./map/"+node_name) | 	var current_character = get_tree().root.get_node("./map/"+node_name) | ||||||
| 	print(current_character) |  | ||||||
| 	current_character.current = current | 	current_character.current = current | ||||||
|  | 
 | ||||||
|  | @rpc("authority", "call_local", "reliable") | ||||||
|  | func sync_beast(player): | ||||||
|  | 	var current_character = get_tree().root.get_node("./"+"player"+str(player)) | ||||||
|  | 	current_character.beast_init() | ||||||
|  | 	 | ||||||
|  | @rpc("any_peer", "call_local", "reliable") | ||||||
|  | func player_hit(target, beast): | ||||||
|  | 	target = get_tree().root.get_node("./"+target) | ||||||
|  | 	beast = get_tree().root.get_node("./"+beast) | ||||||
|  | 	map = get_tree().root.get_node(".") | ||||||
|  | 	print(target) | ||||||
|  | 	print(beast) | ||||||
|  | 	print(map) | ||||||
|  | 	target.captured(beast) | ||||||
|  | 	beast.got_one(target) | ||||||
|  | 	 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 patrick_pluto
						patrick_pluto