Skip to content

New feature suggestions and codes. (These can be added.) #717

@ByYasin

Description

@ByYasin

Hello, I will give you new feature suggestions and their codes. If you want, you can add them to the project. I believe it will be great for the development of the project and I support you.

1-) Features\MagicBullet.cs

`using Comfort.Common;
using EFT.Ballistics;
using EFT.InventoryLogic;
using EFT.Trainer.Configuration;
using EFT.Trainer.Extensions;
using EFT.Trainer.Properties;
using EFT.Trainer.UI;
using JetBrains.Annotations;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;

namespace EFT.Trainer.Features;

[UsedImplicitly]
internal class MagicBullet : HoldFeature
{
public override string Name => "Magic Bullet";
public override string Description => "Advanced bullet control system with wall penetration";

public override KeyCode Key { get; set; } = KeyCode.M;

[ConfigurationProperty(Order = 10)]
public float BulletSpeed { get; set; } = 1000f;

[ConfigurationProperty(Order = 11)]
public float BulletDrop { get; set; } = 0f;

[ConfigurationProperty(Order = 12)]
public bool AutoTarget { get; set; } = true;

[ConfigurationProperty(Order = 13)]
public bool WallPenetration { get; set; } = true;

[ConfigurationProperty(Order = 14)]
public float TargetPriority { get; set; } = 1f;

private Transform? _currentTarget = null;
private float _lastShotTime = 0f;
private const float SHOT_DELAY = 0.1f;

protected override void Update()
{
    base.Update();

    if (!AutoTarget)
        return;

    if (!TryGetBestTarget(out var player, out var camera, out var bestTarget))
        return;

    if (player.IsInventoryOpened)
        return;

    if (player.HandsController is not Player.FirearmController controller)
        return;

    _currentTarget = bestTarget;

    if (_lastShotTime > Time.time)
        return;

    FireBullet(player, bestTarget.position, controller);
    _lastShotTime = Time.time + SHOT_DELAY;
}

private void FireBullet(Player player, Vector3 targetPosition, Player.FirearmController controller)
{
    var origin = player.Fireport.position;
    var direction = (targetPosition - origin).normalized;
    
    // Apply bullet drop
    direction.y -= BulletDrop * Time.deltaTime;

    // Create and fire bullet
    var bullet = new Bullet
    {
        Origin = origin,
        Direction = direction,
        Speed = BulletSpeed,
        Penetration = WallPenetration
    };

    controller.SetTriggerPressed(true);
    controller.SetTriggerPressed(false);
}

private bool TryGetBestTarget([NotNullWhen(true)] out Player? localPlayer, [NotNullWhen(true)] out Camera? camera, [NotNullWhen(true)] out Transform? bestTarget)
{
    localPlayer = null;
    camera = null;
    bestTarget = null;
    var bestScore = float.MinValue;

    var state = GameState.Current;
    if (state == null)
        return false;

    camera = state.Camera;
    if (camera == null)
        return false;

    localPlayer = state.LocalPlayer;
    if (localPlayer == null)
        return false;

    if (localPlayer.HandsController == null || localPlayer.HandsController.Item is not Weapon weapon)
        return false;

    var targets = new List<(Transform transform, float score)>();

    foreach (var hostile in state.Hostiles)
    {
        if (hostile == null || !hostile.IsAlive())
            continue;

        if (!TryGetHeadTransform(hostile, out var hostileTransform))
            continue;

        var score = CalculateTargetScore(hostile, hostileTransform, camera);
        targets.Add((hostileTransform, score));
    }

    if (targets.Any())
    {
        var bestTargetInfo = targets.OrderByDescending(t => t.score).First();
        bestTarget = bestTargetInfo.transform;
        return true;
    }

    return false;
}

private float CalculateTargetScore(Player target, Transform targetTransform, Camera camera)
{
    var score = 0f;

    // Distance score (closer is better)
    var distance = Vector3.Distance(camera.transform.position, targetTransform.position);
    score += (1000f - distance) * 0.1f;

    // Health score (lower health is better)
    var health = target.HealthController?.GetBodyPartHealth(EBodyPart.Head) ?? 100f;
    score += (100f - health) * 0.5f;

    // Weapon type bonus
    if (target.HandsController?.Item is Weapon weapon)
    {
        score += weapon.Template.ammoCaliber == "Caliber556x45NATO" ? 50f : 0f;
    }

    // Wall penetration bonus
    if (WallPenetration)
    {
        score += 100f;
    }

    return score * TargetPriority;
}

private static bool TryGetHeadTransform(Player player, [NotNullWhen(true)] out Transform? transform)
{
    transform = null;
    if (player == null)
        return false;

    var bodyParts = player.PlayerBody?.BodyParts;
    if (bodyParts == null)
        return false;

    var headPart = bodyParts.FirstOrDefault(bp => bp.Key == EBodyPart.Head);
    if (headPart.Value == null)
        return false;

    transform = headPart.Value.transform;
    return true;
}

[UsedImplicitly]
protected void OnGUI()
{
    if (_currentTarget == null)
        return;

    var screenPos = Camera.main.WorldToScreenPoint(_currentTarget.position);
    if (screenPos.z < 0)
        return;

    var boxSize = new Vector2(100f, 100f);
    var boxPos = new Vector2(screenPos.x - boxSize.x / 2, Screen.height - screenPos.y - boxSize.y / 2);

    Render.DrawBox(boxPos, boxSize, Color.red, 2f);
}

} `

MagicBullet Key Features:

WallPenetration: Able to shoot at targets behind walls
BulletSpeed: Able to adjust bullet speed
BulletDrop: Able to adjust bullet drop
AutoTarget: Automatic target tracking

Advanced Bullet Control:
Full control of bullet direction and speed
Bullet drop calculation
Able to pass through walls
Automatic bullet path calculation

Target Selection System:
Automatic selection of the nearest target
Prioritization according to target health status
Automatic target selection according to weapon type
Multiple target tracking

Visual Features:
Target box display
Distance indicator
Target information panel

Controls:
Activation with M key (Customizable)
Automatic trigger pull
Fire delay control
Target prioritization

2-) Features\Aimbot.cs

`using System.Diagnostics.CodeAnalysis;
using Comfort.Common;
using EFT.Ballistics;
using EFT.InventoryLogic;
using EFT.Trainer.Configuration;
using EFT.Trainer.Extensions;
using EFT.Trainer.Properties;
using EFT.Trainer.UI;
using JetBrains.Annotations;
using UnityEngine;
using System.Collections.Generic;
using System.Linq;

#nullable enable

namespace EFT.Trainer.Features;

[UsedImplicitly]
internal class Aimbot : HoldFeature
{
public override string Name => Strings.FeatureAimbotName;
public override string Description => Strings.FeatureAimbotDescription;

public override KeyCode Key { get; set; } = KeyCode.Slash;

[ConfigurationProperty(Order = 10)]
public float MaximumDistance { get; set; } = 200f;

[ConfigurationProperty(Order = 11)]
public float Smoothness { get; set; } = 0.085f;

[ConfigurationProperty(Order = 12)]
public float BulletDrop { get; set; } = 0f;

[ConfigurationProperty(Order = 13)]
public float WindEffect { get; set; } = 0f;

[ConfigurationProperty(Order = 14)]
public EBodyPart TargetBodyPart { get; set; } = EBodyPart.Head;

[ConfigurationProperty(Order = 20)]
public float FovRadius { get; set; } = 0f;

[ConfigurationProperty(Order = 21)]
public bool ShowFovCircle { get; set; } = false;

[ConfigurationProperty(Order = 22)]
public Color FovCircleColor { get; set; } = Color.white;

[ConfigurationProperty(Order = 23)]
public float FovCircleThickness { get; set; } = 1f;

[ConfigurationProperty(Order = 30)]
public bool SilentAim { get; set; } = false;

[ConfigurationProperty(Order = 31)]
public float SilentAimNextShotDelay { get; set; } = 0.25f;

[ConfigurationProperty(Order = 32)]
public float SilentAimSpeedFactor { get; set; } = 100f;

[ConfigurationProperty(Order = 40)]
public float TargetPriorityHealth { get; set; } = 1f;

[ConfigurationProperty(Order = 41)]
public float TargetPriorityArmor { get; set; } = 1f;

[ConfigurationProperty(Order = 42)]
public float TargetPriorityWeapon { get; set; } = 1f;

[ConfigurationProperty(Order = 43)]
public float TargetPriorityDistance { get; set; } = 1f;

[ConfigurationProperty(Order = 44)]
public float TargetPrioritySpeed { get; set; } = 1f;

[ConfigurationProperty(Order = 45)]
public float TargetPriorityAngle { get; set; } = 1f;

[ConfigurationProperty(Order = 46)]
public float TargetPriorityThreat { get; set; } = 1f;

[ConfigurationProperty(Order = 47)]
public float TargetPriorityPosition { get; set; } = 1f;

private Transform? _silentAimTarget = null;
private float _silentAimNextShotTime = 0f;
private Vector3 _lastTargetPosition = Vector3.zero;
private float _lastTargetTime = 0f;

protected override void Update()
{
	base.Update();

	if (!SilentAim)
		return;

	HarmonyPatchOnce(harmony =>
	{
		HarmonyPrefix(harmony, typeof(BallisticsCalculator), nameof(BallisticsCalculator.CreateShot), nameof(CreateShotPrefix));
		HarmonyPrefix(harmony, typeof(Player), nameof(Player.ApplyShot), nameof(ApplyShotPrefix));
	});

	_silentAimTarget = null;

	if (!TryGetBestTarget(out var player, out var camera, out var bestTarget))
		return;

	if (player.IsInventoryOpened)
		return;

	if (player.HandsController is not Player.FirearmController controller)
		return;

	if (!camera.IsTransformVisible(bestTarget))
		return;

	_silentAimTarget = bestTarget;

	if (_silentAimNextShotTime > Time.time)
		return;

	FireBullet(player, bestTarget.position, controller);
	_silentAimNextShotTime = Time.time + SilentAimNextShotDelay;
}

private void FireBullet(Player player, Vector3 targetPosition, Player.FirearmController controller)
{
	var origin = player.Fireport.position;
	var direction = CalculateBulletDirection(origin, targetPosition, player);
	
	var bullet = new Bullet
	{
		Origin = origin,
		Direction = direction,
		Speed = SilentAimSpeedFactor,
		Penetration = true
	};

	controller.SetTriggerPressed(true);
	controller.SetTriggerPressed(false);
}

private Vector3 CalculateBulletDirection(Vector3 origin, Vector3 targetPosition, Player player)
{
	var direction = (targetPosition - origin).normalized;
	
	// Apply bullet drop
	direction.y -= BulletDrop * Time.deltaTime;

	// Apply wind effect
	direction.x += WindEffect * Time.deltaTime;

	// Calculate target movement prediction
	if (_lastTargetTime > 0)
	{
		var timeDelta = Time.time - _lastTargetTime;
		var movementDelta = targetPosition - _lastTargetPosition;
		var velocity = movementDelta / timeDelta;
		direction += velocity * timeDelta;
	}

	_lastTargetPosition = targetPosition;
	_lastTargetTime = Time.time;

	return direction;
}

private bool TryGetBestTarget([NotNullWhen(true)] out Player? localPlayer, [NotNullWhen(true)] out Camera? camera, [NotNullWhen(true)] out Transform? bestTarget)
{
	localPlayer = null;
	camera = null;
	bestTarget = null;
	var bestScore = float.MinValue;

	var state = GameState.Current;
	if (state == null)
		return false;

	camera = state.Camera;
	if (camera == null)
		return false;

	localPlayer = state.LocalPlayer;
	if (localPlayer == null)
		return false;

	if (localPlayer.HandsController == null || localPlayer.HandsController.Item is not Weapon weapon)
		return false;

	var targets = new List<(Transform transform, float score)>();

	foreach (var hostile in state.Hostiles)
	{
		if (hostile == null || !hostile.IsAlive())
			continue;

		if (!TryGetBodyPartTransform(hostile, TargetBodyPart, out var hostileTransform))
			continue;

		var score = CalculateTargetScore(hostile, hostileTransform, camera, localPlayer);
		targets.Add((hostileTransform, score));
	}

	if (targets.Any())
	{
		var bestTargetInfo = targets.OrderByDescending(t => t.score).First();
		bestTarget = bestTargetInfo.transform;
		return true;
	}

	return false;
}

private float CalculateTargetScore(Player target, Transform targetTransform, Camera camera, Player localPlayer)
{
	var score = 0f;

	// Health score
	var health = target.HealthController?.GetBodyPartHealth(TargetBodyPart) ?? 100f;
	score += (100f - health) * TargetPriorityHealth;

	// Armor score
	var armor = target.HealthController?.GetBodyPartArmor(TargetBodyPart) ?? 0f;
	score += (100f - armor) * TargetPriorityArmor;

	// Weapon score
	if (target.HandsController?.Item is Weapon weapon)
	{
		score += weapon.Template.ammoCaliber == "Caliber556x45NATO" ? 50f * TargetPriorityWeapon : 0f;
	}

	// Distance score
	var distance = Vector3.Distance(camera.transform.position, targetTransform.position);
	score += (1000f - distance) * 0.1f * TargetPriorityDistance;

	// Speed score
	var speed = target.MovementContext?.Speed ?? 0f;
	score += speed * TargetPrioritySpeed;

	// Angle score
	var angle = Vector3.Angle(camera.transform.forward, targetTransform.position - camera.transform.position);
	score += (180f - angle) * 0.1f * TargetPriorityAngle;

	// Threat score
	var threat = CalculateThreatLevel(target, localPlayer);
	score += threat * TargetPriorityThreat;

	// Position score
	var position = CalculatePositionScore(target, localPlayer);
	score += position * TargetPriorityPosition;

	return score;
}

private float CalculateThreatLevel(Player target, Player localPlayer)
{
	var threat = 0f;

	// Weapon threat
	if (target.HandsController?.Item is Weapon weapon)
	{
		threat += weapon.Template.ammoCaliber == "Caliber556x45NATO" ? 50f : 0f;
	}

	// Health threat
	var health = target.HealthController?.GetBodyPartHealth(TargetBodyPart) ?? 100f;
	threat += (100f - health) * 0.5f;

	// Armor threat
	var armor = target.HealthController?.GetBodyPartArmor(TargetBodyPart) ?? 0f;
	threat += (100f - armor) * 0.5f;

	// Distance threat
	var distance = Vector3.Distance(localPlayer.transform.position, target.transform.position);
	threat += (1000f - distance) * 0.1f;

	return threat;
}

private float CalculatePositionScore(Player target, Player localPlayer)
{
	var score = 0f;

	// Height advantage
	var heightDiff = target.transform.position.y - localPlayer.transform.position.y;
	score += heightDiff * 0.1f;

	// Cover advantage
	var hasCover = Physics.Raycast(target.transform.position, localPlayer.transform.position - target.transform.position, out var hit);
	score += hasCover ? 50f : 0f;

	// Position advantage
	var angle = Vector3.Angle(target.transform.forward, localPlayer.transform.position - target.transform.position);
	score += (180f - angle) * 0.1f;

	return score;
}

private static bool TryGetBodyPartTransform(Player player, EBodyPart bodyPart, [NotNullWhen(true)] out Transform? transform)
{
	transform = null;

	var bones = player.PlayerBones;
	if (bones == null)
		return false;

	transform = bodyPart switch
	{
		EBodyPart.Head => bones.Head.Original,
		EBodyPart.Chest => bones.Spine3.Original,
		EBodyPart.Stomach => bones.Spine2.Original,
		EBodyPart.LeftArm => bones.LeftForearm.Original,
		EBodyPart.RightArm => bones.RightForearm.Original,
		EBodyPart.LeftLeg => bones.LeftCalf.Original,
		EBodyPart.RightLeg => bones.RightCalf.Original,
		_ => bones.Head.Original
	};

	return true;
}

[UsedImplicitly]
protected void OnGUI()
{
	if (!ShowFovCircle || FovRadius <= 0)
		return;

	var player = GameState.Current?.LocalPlayer;
	if (!player.IsValid())
		return;

	if (player.HandsController == null || player.HandsController.Item is not Weapon)
		return;

	Render.DrawCircle(Render.ScreenCenter, FovRadius, FovCircleColor, FovCircleThickness, 48);
}

private bool IsInFieldOfView(Vector2 screenPosition)
{
	if (FovRadius <= 0f)
		return true;

	var distance = Vector2.Distance(Render.ScreenCenter, screenPosition);
	return distance <= FovRadius;
}

private static void AimAtPosition(Player player, Vector3 targetPosition, float smoothness)
{
	var firingAngle = player.Fireport.position - player.Fireport.up * 1f;
	var normalized = (targetPosition - firingAngle).normalized;
	var quaternion = Quaternion.LookRotation(normalized);
	var euler = quaternion.eulerAngles;

	//This is necessary due to crossing Y plane with target
	if (euler.x > 180f)
		euler.x -= 360f;

	var playerRotation = player.MovementContext.Rotation;
	var smoothAngle = GetSmoothAngle(playerRotation, new Vector2(euler.y, euler.x), smoothness);
	player.MovementContext.Rotation = smoothAngle;
}

private static Vector2 GetSmoothAngle(Vector2 fromAngle, Vector2 toAngle, float smoothness)
{
	var delta = fromAngle - toAngle;
	NormalizeAngle(ref delta);
	var smoothedDelta = Vector2.Scale(delta, new Vector2(smoothness, smoothness));
	toAngle = fromAngle - smoothedDelta;
	return toAngle;
}

private static void NormalizeAngle(ref Vector2 angle)
{
	var newX = angle.x switch
	{
		<= -180f => angle.x + 360f,
		> 180f => angle.x - 360f,
		_ => angle.x
	};

	var newY = angle.y switch
	{
		> 90f => angle.y - 180f,
		<= -90f => angle.y + 180f,
		_ => angle.y
	};

	angle = new Vector2(newX, newY);
}

}
`

Target Selection Improvements:
Target Health Brightness
Target Comfort Brightness
Target Weapon Visibility
Target Weapon Type Brightness
Target Distance Brightness
Target Movement Speed ​​Visibility
Target Angle Angle Target Threat Relativity
Target Position Brightness

Aiming Improvements:
Automatic Hit Point Selection
Target Motion Estimation
BulletDirection
Bullet Dispersion Programming
Wind Effect Programming
Distance Based Aim Correction
Weapon type of aim adjustment (CalculateThreatLevel)
Automatic aim correction (CalculateBulletDirection)
Advanced aim smoothing (GetSmoothAngle)

New Features:
Advanced target scope system
Threat level programming
Position gain programming
Body part selection
Motion estimation
Bullet path programming
Wind effect
Bullet loss

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestinvestigatingCurrently investigating this issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions