точно есть дэшм

This commit is contained in:
2026-07-21 00:27:17 +07:00
parent 1df926f1d8
commit d74fa3bd80
601 changed files with 2375919 additions and 0 deletions
@@ -0,0 +1,219 @@
extends Node3D
var cW #current weapon
var pointOfCollision : Vector3 = Vector3.ZERO
var rng : RandomNumberGenerator
@onready var weaponManager : Node3D = %WeaponManager #weapon manager
@onready var blood_particles_scene: PackedScene = preload("res://addons/NPC/enemy/blood_particles.tscn") # Укажи точный путь к файлу из Шага 2
func getCurrentWeapon(currWeap):
#get current weapon resources
cW = currWeap
func shoot():
# БЛОКИРОВКА СТРЕЛЬБЫ ДЛЯ ДИАЛОГОВ И СМЕНЫ ОРУЖИЯ:
# Если менеджеру оружия запрещено стрелять — принудительно выходим из функции
var dialogue_ui = get_tree().current_scene.find_child("DialogueUI", true, false)
if dialogue_ui:
var dialogue_box = dialogue_ui.find_child("DialogueBox", true, false)
# Если окно с текстом диалога СЕЙЧАС открыто и видимо на экране — выстрел ЗАПРЕЩЕН
if dialogue_box and dialogue_box.visible:
return # Мгновенно выходим, не давая проиграться коду ниже
if !cW.isShooting and (
#magazine isn't empty, and has >= ammo than the number of projectiles required for a shot
(cW.totalAmmoInMag > 0 and cW.totalAmmoInMag >= cW.nbProjShotsAtSameTime)
or
#has all ammos in the magazine, and number of ammo is positive
(cW.allAmmoInMag and weaponManager.ammoManager.ammoDict[cW.ammoType] > 0 and
#has >= ammo than the number of projectiles required for a shot
weaponManager.ammoManager.ammoDict[cW.ammoType] >= cW.nbProjShotsAtSameTime)
) and !cW.isReloading:
cW.isShooting = true
#number of successive shots (for example if 3, the weapon will shot 3 times in a row)
for i in range(cW.nbProjShots):
#same conditions has before, are checked before every shot
if ((cW.totalAmmoInMag > 0 and cW.totalAmmoInMag >= cW.nbProjShotsAtSameTime)
or (cW.allAmmoInMag and weaponManager.ammoManager.ammoDict[cW.ammoType] > 0) and
weaponManager.ammoManager.ammoDict[cW.ammoType] >= cW.nbProjShotsAtSameTime):
weaponManager.weaponSoundManagement(cW.shootSound, cW.shootSoundSpeed)
if cW.shootAnimName != "":
weaponManager.animManager.playAnimation("ShootAnim%s" % cW.weaponName, cW.shootAnimSpeed, true)
else:
print("%s doesn't have a shoot animation" % cW.weaponName)
#number projectiles shots at the same time (for example,
#a shotgun shell is constituted of ~ 20 pellets that are spread across the target,
#so 20 projectiles shots at the same time)
for j in range(0, cW.nbProjShotsAtSameTime):
if cW.allAmmoInMag: weaponManager.ammoManager.ammoDict[cW.ammoType] -= 1
else: cW.totalAmmoInMag -= 1
#get the collision point
pointOfCollision = getCameraPOV()
#call the fonction corresponding to the selected type
if cW.type == cW.types.HITSCAN: hitscanShot(pointOfCollision)
elif cW.type == cW.types.PROJECTILE: projectileShot(pointOfCollision)
if cW.showMuzzleFlash: weaponManager.displayMuzzleFlash()
weaponManager.cameraRecoilHolder.setRecoilValues(cW.baseRotSpeed, cW.targetRotSpeed)
weaponManager.cameraRecoilHolder.addRecoil(cW.recoilVal)
await get_tree().create_timer(cW.timeBetweenShots).timeout
else:
print("Not enought ammunitions to shoot")
cW.isShooting = false
func getCameraPOV():
var camera : Camera3D = %Camera
var window : Window = get_window()
var viewport : Vector2i
#match viewport to window size, to ensure that the raycast goes in the right direction
match window.content_scale_mode:
window.CONTENT_SCALE_MODE_VIEWPORT:
viewport = window.content_scale_size
window.CONTENT_SCALE_MODE_CANVAS_ITEMS:
viewport = window.content_scale_size
window.CONTENT_SCALE_MODE_DISABLED:
viewport = window.get_size()
#Start raycast in camera position, and launch it in camera direction
var raycastStart = camera.project_ray_origin(viewport/2)
var raycastEnd
if cW.type == cW.types.HITSCAN: raycastEnd = raycastStart + camera.project_ray_normal(viewport/2) * cW.maxRange
if cW.type == cW.types.PROJECTILE: raycastEnd = raycastStart + camera.project_ray_normal(viewport/2) * 280
#Create intersection space to contain possible collisions
var newIntersection = PhysicsRayQueryParameters3D.create(raycastStart, raycastEnd)
var intersection = get_world_3d().direct_space_state.intersect_ray(newIntersection)
#If the raycast has collide with something, return collision point transform properties
if !intersection.is_empty():
var collisionPoint = intersection.position
return collisionPoint
#Else, return the end of the raycast (so nothing, because he hasn't collide with anything)
else:
return raycastEnd
func hitscanShot(pointOfCollisionHitscan : Vector3):
rng = RandomNumberGenerator.new()
#set up weapon shot sprad
var spread = Vector3(rng.randf_range(cW.minSpread, cW.maxSpread), rng.randf_range(cW.minSpread, cW.maxSpread), rng.randf_range(cW.minSpread, cW.maxSpread))
#calculate direction of the hitscan bullet
var hitscanBulletDirection = (pointOfCollisionHitscan - cW.weaponSlot.attackPoint.get_global_transform().origin).normalized()
#create new intersection space to contain possibe collisions
var newIntersection = PhysicsRayQueryParameters3D.create(cW.weaponSlot.attackPoint.get_global_transform().origin, pointOfCollisionHitscan + spread + hitscanBulletDirection * 2)
newIntersection.collide_with_areas = true
newIntersection.collide_with_bodies = true
var hitscanBulletCollision = get_world_3d().direct_space_state.intersect_ray(newIntersection)
#if the raycast has collide
if hitscanBulletCollision:
var collider = hitscanBulletCollision.collider
var colliderPoint = hitscanBulletCollision.position
var colliderNormal = hitscanBulletCollision.normal
var finalDamage : int
# --- НАНЕСЕНИЕ УРОНА ВРАГАМ ---
if collider.is_in_group("Enemies"):
finalDamage = cW.damagePerProj * cW.damageDropoff.sample(pointOfCollisionHitscan.distance_to(global_position) / cW.maxRange)
# Ищем HealthComponent внутри врага
var enemy_health = collider.find_child("HealthComponent", true, false)
if enemy_health:
enemy_health.take_damage(finalDamage)
# --- СПАВН КРАСНЫХ КВАДРАТИКОВ (ИМПАКТ) ---
# Переменная blood_particles_scene должна быть объявлена в самом верху скрипта ShootManager
if has_node("blood_particles_scene") or (typeof(blood_particles_scene) if "blood_particles_scene" in self else null):
var particles_instance = blood_particles_scene.instantiate()
get_tree().get_root().add_child(particles_instance)
particles_instance.global_position = colliderPoint # Ставим в точку попадания
if collider.has_method("hitscanHit"):
collider.hitscanHit(finalDamage, hitscanBulletDirection, hitscanBulletCollision.position)
elif collider.is_in_group("EnemiesHead"):
finalDamage = cW.damagePerProj * cW.headshotDamageMult * cW.damageDropoff.sample(pointOfCollisionHitscan.distance_to(global_position) / cW.maxRange)
var enemy_health = collider.find_child("HealthComponent", true, false)
if enemy_health:
enemy_health.take_damage(finalDamage)
# --- СПАВН КРАСНЫХ КВАДРАТИКОВ (ИМПАКТ В ГОЛОВУ) ---
if "blood_particles_scene" in self and blood_particles_scene != null:
var particles_instance = blood_particles_scene.instantiate()
get_tree().get_root().add_child(particles_instance)
particles_instance.global_position = colliderPoint
if collider.has_method("hitscanHit"):
collider.hitscanHit(finalDamage, hitscanBulletDirection, hitscanBulletCollision.position)
elif collider.is_in_group("HitableObjects"):
finalDamage = cW.damagePerProj * cW.damageDropoff.sample(pointOfCollisionHitscan.distance_to(global_position) / cW.maxRange)
var enemy_health = collider.find_child("HealthComponent", true, false)
if enemy_health:
enemy_health.take_damage(finalDamage / 6.0)
if collider.has_method("hitscanHit"):
collider.hitscanHit(finalDamage/6.0, hitscanBulletDirection, hitscanBulletCollision.position)
weaponManager.displayBulletHole(colliderPoint, colliderNormal)
else:
weaponManager.displayBulletHole(colliderPoint, colliderNormal)
func projectileShot(pointOfCollisionProjectile : Vector3):
rng = RandomNumberGenerator.new()
#set up weapon shot sprad
var spread = Vector3(rng.randf_range(cW.minSpread, cW.maxSpread), rng.randf_range(cW.minSpread, cW.maxSpread), rng.randf_range(cW.minSpread, cW.maxSpread))
#Calculate direction of the projectile
var projectileDirection = ((pointOfCollisionProjectile - cW.weaponSlot.attackPoint.get_global_transform().origin).normalized() + spread)
#Instantiate projectile
var projInstance = cW.projRef.instantiate()
#set projectile properties
projInstance.global_transform = cW.weaponSlot.attackPoint.global_transform
projInstance.direction = projectileDirection
projInstance.damage = cW.damagePerProj
projInstance.timeBeforeVanish = cW.projTimeBeforeVanish
projInstance.gravity_scale = cW.projGravityVal
projInstance.isExplosive = cW.isProjExplosive
get_tree().get_root().add_child(projInstance)
projInstance.set_linear_velocity(projectileDirection * cW.projMoveSpeed)