C#:
/* Copyright (c) 2021 Viking */
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Libraries;
using System;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using Rust;
using Newtonsoft.Json;
using ProtoBuf;
using Oxide.Core.Plugins;
namespace Oxide.Plugins {
[Info("RhibWar", "Viking", "1.1.0")]
public class RhibWar : RustPlugin {
[PluginReference]
Plugin BulletProjectile;
#region Variables
private static RhibWar instance;
private static string[] enabledRhibWeaponTypes;
private static string[] enabledRowboatWeaponTypes;
private static readonly Dictionary<string, int> weaponsToAmmoTypeItemIdMap = new Dictionary<string, int>();
private static Permission permissionHelper;
private static string clear = "0 0 0 0";
private static string green = "0 1 0 0.4";
private static string darkGreen = "0 1 0 0.7";
private static string red = "1 0 0 0.4";
private static string darkRed = "1 0 0 0.7";
private static string solidRed = "1 0 0 1";
private static string white = "1.0 1.0 1.0";
private static string orange = "0.7 0.4 0 0.7";
private static string gold = "1.000000000 0.819607843 0.137254902";
private static string permAdmin = "RhibWar.AdminPerm";
private static string reticleOverlayName = "AimReticle";
private static string primaryAmmoOverlayName = "PrimaryAmmoCounter";
private static string secondaryAmmoOverlayName = "SecondaryAmmoCounter";
private static string flareAmmoOverlayName = "FlareAmmoCounter";
private static string primaryCooldownOverlayName = "PrimaryCooldownGui";
private static string secondaryCooldownOverlayName = "SecondaryCooldownGui";
private static string flareCooldownOverlayName = "FlareCooldownGui";
private static string weaponTypeOverlayName = "WeaponSelector";
private static string targetLockGuiName = "TargetLockGui";
private static string targetMessageGuiName = "TargetMessageGui";
private static string flarePrefab = "assets/prefabs/tools/flareold/flare.deployed.prefab";
private static LayerMask layerMask = -805568513;
private static Configuration configuration;
#endregion
#region Methods
private void RegisterPermissions() {
permission.RegisterPermission(permAdmin, this);
foreach (var weaponSetting in configuration.WeaponSettings) {
permission.RegisterPermission(weaponSetting.Value.WeaponPermission, this);
}
foreach (var weaponSetting in configuration.RowboatWeaponSettings) {
permission.RegisterPermission(weaponSetting.Value.WeaponPermission, this);
}
permissionHelper = permission;
}
void DestroyRhibWarWrappers() {
var rhibWarWrappers = UnityEngine.Object.FindObjectsOfType<RhibWrapper>();
foreach (var rhibWarWrapper in rhibWarWrappers) UnityEngine.Object.Destroy(rhibWarWrapper);
var rowboatWrappers = UnityEngine.Object.FindObjectsOfType<RowboatWrapper>();
foreach (var rowboatWrapper in rowboatWrappers) UnityEngine.Object.Destroy(rowboatWrapper);
}
static void GetEnabledWeapons() {
enabledRhibWeaponTypes = configuration.WeaponSettings.Where(kv => kv.Value.Enabled).Select(kv => kv.Key).ToArray();
enabledRowboatWeaponTypes = configuration.RowboatWeaponSettings.Where(kv => kv.Value.Enabled).Select(kv => kv.Key).ToArray();
}
void UpdateExistingRhibs() {
DestroyRhibWarWrappers();
var RHIBS = UnityEngine.Object.FindObjectsOfType<RHIB>();
foreach (var RHIB in RHIBS) {
if (RHIB.name.Contains("rowboattransporthelicopter")) {
if (configuration.ApplyToRowBoat) {
RHIB.gameObject.AddComponent<RowboatWrapper>();
}
continue;
}
else {
RHIB.gameObject.AddComponent<RhibWrapper>();
}
}
}
void GetWeaponAmmoTypeItemIds() {
foreach (var wt in configuration.WeaponSettings) {
AddAmmoTypeToAmmoTypeMap(wt.Value.FlareShortName);
AddAmmoTypeToAmmoTypeMap(wt.Value.PrimaryWeapon?.AmmoTypeShortName);
AddAmmoTypeToAmmoTypeMap(wt.Value.SecondaryWeapon?.AmmoTypeShortName);
}
foreach (var wt in configuration.RowboatWeaponSettings) {
AddAmmoTypeToAmmoTypeMap(wt.Value.FlareShortName);
AddAmmoTypeToAmmoTypeMap(wt.Value.PrimaryWeapon?.AmmoTypeShortName);
AddAmmoTypeToAmmoTypeMap(wt.Value.SecondaryWeapon?.AmmoTypeShortName);
}
}
private void AddAmmoTypeToAmmoTypeMap(string ammoTypeShortName) {
if (string.IsNullOrEmpty(ammoTypeShortName)) return;
if (!weaponsToAmmoTypeItemIdMap.ContainsKey(ammoTypeShortName)) weaponsToAmmoTypeItemIdMap[ammoTypeShortName] = ItemManager.itemList.Find(x => x.shortname == ammoTypeShortName)?.itemid ?? 0;
}
private static float AngleOffAroundAxis(Vector3 v, Vector3 forward, Vector3 axis) {
Vector3 right = Vector3.Cross(forward, axis);
forward = Vector3.Cross(axis, right);
return Mathf.Atan2(Vector3.Dot(v, right), Vector3.Dot(v, forward)) * Mathf.Rad2Deg;
}
#endregion
#region Config
public class Configuration {
[JsonProperty]
public float DebounceTimeSeconds {
get;
set;
}
= 4;
[JsonProperty]
public bool DisplayOutOfAmmoMessage {
get;
set;
}
= true;
[JsonProperty]
public bool DisplaySelectedWeaponMessage {
get;
set;
}
= true;
[JsonProperty]
public bool UnlimitedAmmo {
get;
set;
}
= false;
[JsonProperty]
public bool DisablePermissionCheck {
get;
set;
}
= false;
[JsonProperty]
public bool ApplyToRowBoat {
get;
set;
}
= false;
[JsonProperty]
public string FlareFiredSfx {
get;
set;
}
= "assets/prefabs/deployable/research table/effects/research-table-deploy.prefab";
[JsonProperty]
public string SwitchWeaponSfx {
get;
set;
}
= "assets/prefabs/deployable/dropbox/effects/submit_items.prefab";
[JsonProperty]
public string AlarmSfx {
get;
set;
}
= "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab";
[JsonProperty]
public float CounterMeasureDespawnTime {
get;
set;
}
= 5f;
[JsonProperty]
public float WeaponSwitchDelay {
get;
set;
}
= 1f;
[JsonProperty]
public BUTTON FirePrimaryButton {
get;
set;
}
= BUTTON.FIRE_PRIMARY;
[JsonProperty]
public BUTTON FireSecondaryButton {
get;
set;
}
= BUTTON.FIRE_SECONDARY;
[JsonProperty]
public BUTTON SwitchWeaponButton {
get;
set;
}
= BUTTON.FIRE_THIRD;
[JsonProperty]
public BUTTON FireFlareButton {
get;
set;
}
= BUTTON.USE;
[JsonProperty]
public bool EnableRowboatGibs {
get;
set;
}
[JsonProperty]
public float GibsDespawnTimerOverride {
get;
set;
}
[JsonProperty]
public bool DisableFire {
get;
set;
}
[JsonProperty]
public bool HideUnauthorizedWeapons {
get;
set;
}
[JsonProperty]
public Dictionary<string, WeaponSettings> WeaponSettings = new Dictionary<string, WeaponSettings>() {
{
"Disarm", new WeaponSettings() {
DisplayShortName = "DISARM", DisplayFullName = "DISARMED", HudConfiguration = HUDConfiguration.None, Enabled = true
}
}
}
;
[JsonProperty]
public Dictionary<string, WeaponSettings> RowboatWeaponSettings = new Dictionary<string, WeaponSettings>() {
{
"Disarm", new WeaponSettings() {
DisplayShortName = "DISARM", DisplayFullName = "DISARMED", HudConfiguration = HUDConfiguration.None, Enabled = true
}
}
}
;
}
protected override void LoadConfig() {
base.LoadConfig();
try {
configuration = Config.ReadObject<Configuration>();
if (configuration == null) throw new Exception();
}
catch {
Config.WriteObject(configuration, false, $"{Interface.Oxide.ConfigDirectory}/{Name}.jsonError");
PrintError("The configuration file contains an error and has been replaced with a default config.");
LoadDefaultConfig();
}
SaveConfig();
}
protected override void LoadDefaultConfig() {
configuration = new Configuration();
}
protected override void SaveConfig() {
Config.WriteObject(configuration);
}
#endregion
#region Hooks
void OnServerInitialized() {
LoadConfig();
GetEnabledWeapons();
UpdateExistingRhibs();
GetWeaponAmmoTypeItemIds();
RegisterPermissions();
instance = this;
}
void Unload() {
DestroyRhibWarWrappers();
}
void OnEntityMounted(BaseMountable entity, BasePlayer player) {
var heliWrapper = entity.VehicleParent()?.GetComponent<HelicopterWrapper>();
if (heliWrapper == null) return;
heliWrapper.SetPlayer(player);
}
void OnEntityDismounted(BaseMountable entity, BasePlayer player) {
if (player == null || entity == null) return;
var heliWrapper = entity.VehicleParent()?.GetComponent<HelicopterWrapper>();
if (heliWrapper == null) return;
heliWrapper.RemovePlayer(player);
}
void OnEntitySpawned(HelicopterDebris debris) {
NextTick(() => {
if (debris == null || debris.IsDestroyed) {
return;
}
if (!configuration.EnableRowboatGibs) {
debris.Kill();
}
else if (configuration.GibsDespawnTimerOverride > 0) {
timer.Once(configuration.GibsDespawnTimerOverride, () => {
debris.Kill();
debris.SendNetworkUpdate();
}
);
return;
}
}
);
}
void OnEntitySpawned(RHIB rhib) {
if (rhib == null) return;
if (rhib.name.Contains("Rowboattransporthelicopter")) {
if (configuration.ApplyToRowBoat) {
rhib.gameObject.AddComponent<RowboatWrapper>();
}
return;
}
rhib.gameObject.AddComponent<RhibWrapper>();
}
#endregion
#region RhibWrapper
public class RowboatWrapper : HelicopterWrapper {
// todo update
protected override float maxAngle {
get {
return 14f;
}
}
protected override float minAngle {
get {
return -14f;
}
}
protected override float centerX {
get {
return 0.491f;
}
}
protected override float centerY {
get {
return 0.57675f;
}
}
protected override string reticleGuiOverlayMin {
get {
return "0.4230 0.485";
}
}
protected override string reticleGuiOverlayMax {
get {
return "0.5730 0.635";
}
}
protected override string primaryAmmoMin {
get {
return "0.3445 0.586";
}
}
protected override string primaryAmmoMax {
get {
return "0.4215 0.609";
}
}
protected override string secondaryAmmoMin {
get {
return "0.5754 0.586";
}
}
protected override string secondaryAmmoMax {
get {
return "0.6524 0.609";
}
}
protected override string flareMin {
get {
return "0.473 0.4884";
}
}
protected override string flareMax {
get {
return "0.5236 0.5084";
}
}
protected override string lockGuiMin {
get {
return "0.46 0.461";
}
}
protected override string lockGuiMax {
get {
return "0.536 0.483";
}
}
protected override string GetNextWeaponType(string current) {
int i = Array.IndexOf<string>(enabledRowboatWeaponTypes, current) + 1;
return (enabledRowboatWeaponTypes.Length == i) ? enabledRowboatWeaponTypes[0] : enabledRowboatWeaponTypes[i];
}
protected override Dictionary<string, WeaponSettings> GetAvailableWeapons() {
return configuration.RowboatWeaponSettings;
}
}
public class RhibWrapper : HelicopterWrapper {
protected override float maxAngle {
get {
return 14f;
}
}
protected override float minAngle {
get {
return -14f;
}
}
protected override float centerX {
get {
return 0.491f;
}
}
protected override float centerY {
get {
return 0.47675f;
}
}
protected override string reticleGuiOverlayMin {
get {
return "0.4205 0.365";
}
}
protected override string reticleGuiOverlayMax {
get {
return "0.5705 0.515";
}
}
protected override string primaryAmmoMin {
get {
return "0.34295 0.466";
}
}
protected override string primaryAmmoMax {
get {
return "0.4195 0.489";
}
}
protected override string secondaryAmmoMin {
get {
return "0.573 0.466";
}
}
protected override string secondaryAmmoMax {
get {
return "0.65 0.489";
}
}
protected override string flareMin {
get {
return "0.473 0.368";
}
}
protected override string flareMax {
get {
return "0.5236 0.388";
}
}
protected override string lockGuiMin {
get {
return "0.46 0.341";
}
}
protected override string lockGuiMax {
get {
return "0.536 0.363";
}
}
protected override string GetNextWeaponType(string current) {
int i = Array.IndexOf<string>(enabledRhibWeaponTypes, current) + 1;
return (enabledRhibWeaponTypes.Length == i) ? enabledRhibWeaponTypes[0] : enabledRhibWeaponTypes[i];
}
protected override Dictionary<string, WeaponSettings> GetAvailableWeapons() {
return configuration.WeaponSettings;
}
}
public class HelicopterWrapper : MonoBehaviour, Lock {
#region Variables
public Guid Id {
get;
set;
}
public float ChanceToLoseLock {
get {
return weaponSettings.ChanceToLoseLock;
}
}
public bool IsAlive {
get;
set;
}
private BasePlayer player {
get;
set;
}
= null;
private string selectedWeaponType {
get;
set;
}
= "Disarm";
private WeaponSettings weaponSettings {
get;
set;
}
private bool IsLocked {
get {
return locks.Count > 0;
}
}
private bool primaryCooldownContainerActive = false;
private bool primaryCooldownContainerContrastActive = false;
private bool secondaryCooldownContainerActive = false;
private bool secondaryCooldownContainerContrastActive = false;
private bool flareCooldownContainerActive = false;
private bool flareCooldownContainerContrastActive = false;
// To prevent spamming the player, log the message time
private float lastMsgTime = 0.0f;
private float lastPrimaryWeaponFiredTime = 0.0f;
private float lastSecondaryWeaponFiredTime = 0.0f;
private float lastWeaponSwitchTime = 0.0f;
private int primaryRoundsFired = 0;
private int secondaryRoundsFired = 0;
private int flareRoundsFired = 0;
private float primaryCooldownTimer = 0f;
private float secondaryCooldownTimer = 0f;
private float flareCooldownTimer = 0f;
private int primaryCurrentBarrel = 0;
private int secondaryCurrentBarrel = 0;
private BaseVehicle vehicle {
get;
set;
}
= null;
#region GuiOverrides
protected virtual string reticleGuiOverlayMin {
get {
return "0 0";
}
}
protected virtual string reticleGuiOverlayMax {
get {
return "0 0";
}
}
protected virtual string primaryAmmoMin {
get {
return "0 0";
}
}
protected virtual string primaryAmmoMax {
get {
return "0 0";
}
}
protected virtual string secondaryAmmoMin {
get {
return "0 0";
}
}
protected virtual string secondaryAmmoMax {
get {
return "0 0";
}
}
protected virtual string flareMin {
get {
return "0 0";
}
}
protected virtual string flareMax {
get {
return "0 0";
}
}
protected virtual string lockGuiMin {
get {
return "0 0";
}
}
protected virtual string lockGuiMax {
get {
return "0 0";
}
}
#endregion
#region AARocketProperties
private float lockOnSeconds = 0f;
private float lockedAt = 0.0f;
private bool isLockAlarmPlaying = false;
private bool targetLocked = false;
private bool acquiringLock = false;
private BaseEntity target = null;
protected virtual float maxAngle {
get {
return 0f;
}
}
protected virtual float minAngle {
get {
return 0f;
}
}
protected virtual float centerX {
get {
return 0f;
}
}
protected virtual float centerY {
get {
return 0f;
}
}
private float targetAngleX = 0.0f;
private float targetAngleY = 0.0f;
#endregion
#region CounterMeasures
private float timeBeforeFlaresExpire = 2f;
private float lastFlaresFiredTime = 0.0f;
private bool leftFlareFiredLast {
get;
set;
}
= false;
private Dictionary<Guid, Lock> locks {
get;
set;
}
= new Dictionary<Guid, Lock>();
#endregion
#endregion
#region WeaponSystemsMethods
protected virtual Dictionary<string, WeaponSettings> GetAvailableWeapons() {
return new Dictionary<string, WeaponSettings>();
}
private void UpdateWeapons() {
UpdateTargetLock();
Toggle_DrawTargetLock(true);
Toggle_CooldownGui(true);
if (player.serverInput.WasJustPressed(configuration.SwitchWeaponButton)) SwitchWeaponType();
if (player.serverInput.WasJustPressed(configuration.FireFlareButton)) FireFlares();
if (this.selectedWeaponType.Equals("Disarm", StringComparison.InvariantCultureIgnoreCase)) return;
if (player.serverInput.IsDown(configuration.FirePrimaryButton)) {
FireProjectile(this.weaponSettings.PrimaryWeapon);
}
if (this.weaponSettings.SecondaryWeapon != null) {
if (player.serverInput.IsDown(configuration.FireSecondaryButton)) FireProjectile(this.weaponSettings.SecondaryWeapon);
else if (this.weaponSettings.SecondaryWeapon.ProjectileType == ProjectileType.TargetLocker) ClearTarget();
}
}
private void FireFlares() {
if (!weaponSettings.FlaresEnabled) return;
if (weaponSettings.FlaresBeforeCooldown > 0 && weaponSettings.FlaresBeforeCooldown <= flareRoundsFired) return;
float currentTime = UnityEngine.Time.realtimeSinceStartup;
if (currentTime < (lastFlaresFiredTime + weaponSettings.FlareFireRate)) return;
if (!weaponSettings.UnlimitedFlares && !DoesUserHaveAmmo(weaponSettings.FlareShortName, currentTime)) return;
GameObject flareEnt = GameManager.server.CreatePrefab(flarePrefab, this.vehicle.transform.position, new Quaternion(), false);
BaseEntity flareBaseEnt = flareEnt.GetComponent<BaseEntity>();
flareBaseEnt.enableSaving = false;
flareBaseEnt.Spawn();
flareEnt.SetActive(true);
flareBaseEnt.transform.position = Vector3.MoveTowards(this.vehicle.transform.position, this.vehicle.transform.localPosition + (this.vehicle.transform.right * (leftFlareFiredLast ? 25f : -25f)), 5f);
flareEnt.AddComponent<CounterMeasure>();
if (!string.IsNullOrEmpty(configuration.FlareFiredSfx)) {
Effect.server.Run(configuration.FlareFiredSfx, flareBaseEnt, 0, Vector3.back, Vector3.forward, null);
}
leftFlareFiredLast = !leftFlareFiredLast;
lastFlaresFiredTime = currentTime;
flareRoundsFired++;
foreach (var lck in locks.Values.ToList()) {
if (lck.ChanceToLoseLock > 0 && lck.ChanceToLoseLock < 100 && Oxide.Core.Random.Range(0, 100) < lck.ChanceToLoseLock) continue;
lck.SetLockTarget(flareBaseEnt);
}
if (!weaponSettings.UnlimitedFlares) UseAmmo(weaponSettings.FlareShortName, null);
}
private void ResetRoundsFiredByConfig(WeaponConfiguration weaponConfiguration, float lastFiredTime, ref int roundsFired, ref float cooldownTimer) {
// weaponConfiguration.ShotsBeforeCoolDown <= 0 ||
if (weaponConfiguration == null) return;
ResetRoundsFired(weaponConfiguration.CoolDownDecay, lastFiredTime, ref roundsFired, ref cooldownTimer);
}
private void ResetRoundsFired(float coolDownDecay, float lastFiredTime, ref int roundsFired, ref float cooldownTimer) {
if (roundsFired <= 0) return;
float currentTime = UnityEngine.Time.realtimeSinceStartup;
float timeSinceLastFired = (currentTime - lastFiredTime);
if (timeSinceLastFired <= 1) return;
float timeSinceLastCooldownCheck = (currentTime - cooldownTimer);
if (timeSinceLastCooldownCheck > coolDownDecay) {
--roundsFired;
cooldownTimer = currentTime;
}
if (roundsFired < 0) roundsFired = 0;
}
private Vector3 GetMuzzlePosition(WeaponConfiguration weaponConfiguration, int currentBarrel) {
Vector3 muzzlePos = Vector3.zero;
var vehicleTransform = this.vehicle.transform;
switch (weaponConfiguration.BarrelConfiguration) {
case BarrelConfiguration.Bottom : muzzlePos = this.player.transform.localPosition + Vector3.down;
break;
case BarrelConfiguration.Side : muzzlePos = vehicleTransform.localPosition + (vehicleTransform.forward + (vehicleTransform.right * 1.5f * (currentBarrel % 2 == 0 ? 1 : -1)));
break;
case BarrelConfiguration.SideOuter : muzzlePos = vehicleTransform.localPosition + (vehicleTransform.forward + (vehicleTransform.right * 2f * (currentBarrel % 2 == 0 ? 1 : -1)));
break;
case BarrelConfiguration.DualFront : muzzlePos = vehicleTransform.localPosition + ((vehicleTransform.forward * 3.5f) + (vehicleTransform.right * 0.75f * (currentBarrel % 2 == 0 ? 1 : -1)));
break;
case BarrelConfiguration.CenterFront : muzzlePos = vehicleTransform.localPosition + (vehicleTransform.forward * 3.5f);
break;
case BarrelConfiguration.Gattling : muzzlePos = GetGattlingMuzzlePos(vehicleTransform, currentBarrel);
break;
default : break;
}
return muzzlePos;
}
private Vector3 GetGattlingMuzzlePos(Transform vehicleTransform, int currentBarrel) {
Vector3 modifier = Vector3.zero;
switch (currentBarrel) {
case 0 : modifier = (vehicleTransform.up * 0.30f);
break;
case 1 : modifier = (vehicleTransform.right * 0.30f);
break;
case 2 : modifier = ((vehicleTransform.right + (vehicleTransform.up * -1)) * 0.30f);
break;
case 3 : modifier = ((vehicleTransform.right + vehicleTransform.up) * 0.30f) * -1;
break;
case 4 : modifier = (vehicleTransform.right * 0.30f * -1);
break;
default : break;
}
return vehicleTransform.localPosition + ((vehicleTransform.forward * 3.5f) + modifier);
}
private void TriggerMuzzleEffect(WeaponConfiguration weaponConfiguration, int currentBarrel) {
if (string.IsNullOrEmpty(weaponConfiguration.MuzzleEffect)) return;
Vector3 posLocal;
switch (weaponConfiguration.BarrelConfiguration) {
case BarrelConfiguration.Side : posLocal = (currentBarrel % 2 == 0 ? Vector3.right : Vector3.left) * 2 + (Vector3.forward / 1.8f);
break;
case BarrelConfiguration.SideOuter : posLocal = (currentBarrel % 2 == 0 ? Vector3.right : Vector3.left) * 3 + (Vector3.forward / 1.8f);
break;
case BarrelConfiguration.DualFront : posLocal = (currentBarrel % 2 == 0 ? Vector3.right : Vector3.left) / 2 + (Vector3.forward * 2.1f);
break;
case BarrelConfiguration.CenterFront : posLocal = (Vector3.forward);
break;
case BarrelConfiguration.Gattling : posLocal = GetGattlingEffectPos(currentBarrel);
break;
case BarrelConfiguration.Bottom : default : return;
}
Effect.server.Run(weaponConfiguration.MuzzleEffect, this.vehicle, 0, posLocal, Vector3.forward, null);
}
private Vector3 GetGattlingEffectPos(int currentBarrel) {
Vector3 modifier = Vector3.zero;
switch (currentBarrel) {
case 0 : modifier = Vector3.up;
break;
case 1 : modifier = Vector3.right;
break;
case 2 : modifier = Vector3.right + (Vector3.up * -1);
break;
case 3 : modifier = Vector3.right + Vector3.up * -1;
break;
case 4 : modifier = Vector3.left;
break;
default : break;
}
return modifier / 3f + (Vector3.forward * 2.1f);
}
private void FireProjectile(WeaponConfiguration weaponConfiguration) {
int currentBarrel = 0;
float lastFiredTime = 0f;
int roundsFired = 0;
float currentTime = UnityEngine.Time.realtimeSinceStartup;
if (weaponConfiguration == weaponSettings.PrimaryWeapon) {
weaponConfiguration = this.weaponSettings.PrimaryWeapon;
lastFiredTime = lastPrimaryWeaponFiredTime;
currentBarrel = primaryCurrentBarrel;
roundsFired = primaryRoundsFired;
}
else {
weaponConfiguration = this.weaponSettings.SecondaryWeapon;
lastFiredTime = lastSecondaryWeaponFiredTime;
currentBarrel = secondaryCurrentBarrel;
roundsFired = secondaryRoundsFired;
}
if (weaponConfiguration.ShotsBeforeCoolDown > 0 && weaponConfiguration.ShotsBeforeCoolDown <= roundsFired) return;
if (currentTime < (lastFiredTime + weaponConfiguration.FireRate)) return;
if (weaponConfiguration.RequiresAmmo && !DoesUserHaveAmmo(weaponConfiguration.AmmoTypeShortName, currentTime)) return;
Vector3 muzzlePos = GetMuzzlePosition(weaponConfiguration, currentBarrel);
if (muzzlePos == Vector3.zero) return;
switch (weaponConfiguration.ProjectileType) {
case ProjectileType.ServerProjectile : TriggerMuzzleEffect(weaponConfiguration, currentBarrel);
FireWithServerProjectile(weaponConfiguration, muzzlePos);
break;
case ProjectileType.Bullet : TriggerMuzzleEffect(weaponConfiguration, currentBarrel);
//FireWithProjectileSystem(weaponConfiguration, muzzlePos);
FireWithProjectileSystem(weaponConfiguration, muzzlePos);
break;
case ProjectileType.Air2Air : if (!targetLocked || target == null) return;
TriggerMuzzleEffect(weaponConfiguration, currentBarrel);
FireAARocket(weaponConfiguration, muzzlePos);
break;
case ProjectileType.TargetLocker : TriggerMuzzleEffect(weaponConfiguration, currentBarrel);
LockTarget(muzzlePos, weaponConfiguration);
break;
default : break;
}
if (weaponConfiguration == weaponSettings.PrimaryWeapon) {
lastPrimaryWeaponFiredTime = currentTime;
UpdateBarrel(weaponConfiguration.BarrelConfiguration, ref primaryCurrentBarrel);
primaryRoundsFired = ++roundsFired;
if (weaponConfiguration.RequiresAmmo) UseAmmo(weaponConfiguration.AmmoTypeShortName, true);
}
else {
lastSecondaryWeaponFiredTime = currentTime;
UpdateBarrel(weaponConfiguration.BarrelConfiguration, ref secondaryCurrentBarrel);
secondaryRoundsFired = ++roundsFired;
if (weaponConfiguration.RequiresAmmo) UseAmmo(weaponConfiguration.AmmoTypeShortName, false);
}
}
private void UpdateBarrel(BarrelConfiguration barrelConfig, ref int nextBarrel) {
switch (barrelConfig) {
case BarrelConfiguration.DualFront : case BarrelConfiguration.Side : case BarrelConfiguration.CenterFront : case BarrelConfiguration.SideOuter : if (++nextBarrel > 1) nextBarrel = 0;
break;
case BarrelConfiguration.Bottom : break;
case BarrelConfiguration.Gattling : if (++nextBarrel > 4) nextBarrel = 0;
break;
default : break;
}
}
private bool DoesUserHaveAmmo(string ammoTypeShortName, float currentTime) {
if (configuration.UnlimitedAmmo) return true;
if (this.player.inventory.GetAmount(weaponsToAmmoTypeItemIdMap[ammoTypeShortName]) > 0) return true;
if (configuration.DisplayOutOfAmmoMessage && currentTime >= (lastMsgTime + configuration.DebounceTimeSeconds)) {
player.ChatMessage("Out of Ammo");
lastMsgTime = currentTime;
}
return false;
}
private void FireWithProjectileSystem(WeaponConfiguration weaponConfiguration, Vector3 muzzlePos) {
Vector3 modifiedAimDir = this.vehicle.transform.forward.normalized;
if (weaponConfiguration.AimCone > 0) modifiedAimDir = AimConeUtil.GetAimConeQuat(weaponConfiguration.AimCone) * modifiedAimDir;
instance.BulletProjectile.CallHook("ShootProjectile", this.player, muzzlePos, modifiedAimDir * weaponConfiguration.WeaponSpeed, weaponConfiguration.DamageTypes, weaponConfiguration.AmmoPrefabPath);
}
private GameObject FireWithServerProjectile(WeaponConfiguration weaponConfiguration, Vector3 muzzlePos) {
GameObject bulletEnt = GameManager.server.CreatePrefab(weaponConfiguration.AmmoPrefabPath, muzzlePos, new Quaternion(), false);
ServerProjectile serverProjectile = bulletEnt.GetComponent<ServerProjectile>();
TimedExplosive timedExplosive = bulletEnt.GetComponent<TimedExplosive>();
var baseEnt = bulletEnt.GetComponent<BaseEntity>();
baseEnt.creatorEntity = this.player;
if (timedExplosive != null) {
timedExplosive.OwnerID = player.userID;
if (weaponConfiguration.DamageTypes != null && weaponConfiguration.DamageTypes.Any()) {
timedExplosive.damageTypes = weaponConfiguration.DamageTypes;
}
if (weaponConfiguration.MinBlastRadius > 0) {
timedExplosive.minExplosionRadius = weaponConfiguration.MinBlastRadius;
}
if (weaponConfiguration.MaxBlastRadius > 0) {
timedExplosive.explosionRadius = weaponConfiguration.MaxBlastRadius;
}
if (weaponConfiguration.DetonationTimerMin > 0) {
timedExplosive.timerAmountMin = weaponConfiguration.DetonationTimerMin;
}
if (weaponConfiguration.DetonationTimerMax > 0) {
timedExplosive.timerAmountMax = weaponConfiguration.DetonationTimerMax;
}
}
if (serverProjectile != null) {
serverProjectile.gravityModifier = 1f;
serverProjectile.speed = weaponConfiguration.WeaponSpeed;
if (weaponConfiguration.BarrelConfiguration != BarrelConfiguration.Bottom) {
serverProjectile.InitializeVelocity(this.vehicle.transform.forward.normalized * weaponConfiguration.WeaponSpeed);
}
}
baseEnt.Spawn();
bulletEnt.SetActive(true);
return bulletEnt;
}
private void FireAARocket(WeaponConfiguration weaponConfiguration, Vector3 muzzlePos) {
var projectile = FireWithServerProjectile(weaponConfiguration, muzzlePos);
var homing = projectile.AddComponent<AARocket>();
if (weaponConfiguration.AngleModifier > 0) homing.AngleModifier = weaponConfiguration.AngleModifier;
homing.Initialize(target, ChanceToLoseLock);
if (weaponConfiguration.ClearAATargetOnFire) ClearTarget();
}
private void UseAmmo(string ammoTypeShortName, bool? isPrimary) {
var ammo = player.inventory.FindItemID(weaponsToAmmoTypeItemIdMap[ammoTypeShortName]);
ammo?.UseItem(1);
if (isPrimary == null) Toggle_FlareAmmoGui(true);
else Toggle_AmmoGui(true, isPrimary);
}
private void SwitchWeaponType() {
float currentTime = UnityEngine.Time.realtimeSinceStartup;
if (currentTime < (lastWeaponSwitchTime + configuration.WeaponSwitchDelay)) return;
string newSelection = selectedWeaponType;
do {
newSelection = GetNextWeaponType(newSelection);
}
while (!newSelection.Equals("Disarm", StringComparison.InvariantCultureIgnoreCase) && !configuration.DisablePermissionCheck && !permissionHelper.UserHasPermission(this.player.userID.ToString(), this.GetAvailableWeapons()[newSelection].WeaponPermission));
this.selectedWeaponType = newSelection;
this.weaponSettings = this.GetAvailableWeapons()[this.selectedWeaponType];
this.ResetWeapons();
Effect.server.Run(configuration.SwitchWeaponSfx, this.player.transform.position + this.player.transform.forward);
if (configuration.DisplaySelectedWeaponMessage) player.ChatMessage($"Selected Weapon: {weaponSettings.DisplayFullName}");
Toggle_ReticleGui(true);
Toggle_AmmoGui(true, null);
Toggle_FlareAmmoGui(true);
Toggle_WeaponTypesGui(true);
Toggle_CooldownGui(true);
lastWeaponSwitchTime = currentTime;
}
protected virtual string GetNextWeaponType(string current) {
throw new NotImplementedException();
}
public void TriggerLockAcquired(Lock lck) {
locks.Add(lck.Id, lck);
Toggle_ReticleGui(true);
}
public void TriggerLockLost(Lock lck) {
locks.Remove(lck.Id);
Toggle_ReticleGui(true);
}
private void LockTarget(Vector3 muzzlePos, WeaponConfiguration weaponConfiguration) {
float currentTime = UnityEngine.Time.realtimeSinceStartup;
if (targetLocked) {
bool exceedHud = (targetAngleX > maxAngle || targetAngleX < minAngle) || (targetAngleY > maxAngle || targetAngleY < minAngle);
if (exceedHud || target == null || currentTime > (lockedAt + weaponConfiguration.TimeBeforeLockExpires)) {
ClearTarget();
}
}
RaycastHit rayHit;
if (!targetLocked && Physics.SphereCast(muzzlePos + Vector3.up, 1f, this.vehicle.transform.forward, out rayHit, 2000, layerMask, QueryTriggerInteraction.Collide)) {
var newTrack = rayHit.GetEntity();
var newTarget = newTrack;
if (newTarget != target) {
CancelInvoke();
lockOnSeconds = 0;
isLockAlarmPlaying = false;
acquiringLock = false;
targetAngleX = 0.0f;
targetAngleY = 0.0f;
target = newTarget;
}
bool validTarget = false;
if (weaponConfiguration.AllowCH47HSR && newTarget is CH47Helicopter) {
validTarget = true;
}
else if (weaponConfiguration.AllowPatrolHeliHSR && newTarget is BaseHelicopter) {
validTarget = true;
}
else {
var rhib = target as RHIB;
var rhibWrapper = target?.GetComponent<HelicopterWrapper>();
if (rhibWrapper == null) {
var targetPlayer = target as BasePlayer;
rhibWrapper = targetPlayer?.GetMountedVehicle()?.GetComponent<HelicopterWrapper>();
}
if (rhibWrapper != null) validTarget = true;
}
if (validTarget) {
acquiringLock = true;
if (!isLockAlarmPlaying) {
PlayLockAlarm();
}
lockOnSeconds += UnityEngine.Time.deltaTime;
if (lockOnSeconds >= weaponConfiguration.TimeToLock) {
SetLockTarget(newTarget);
lockedAt = currentTime;
}
}
}
}
private void ResetWeapons() {
this.lastPrimaryWeaponFiredTime = 0.0f;
this.lastSecondaryWeaponFiredTime = 0.0f;
this.primaryCooldownTimer = 0.0f;
this.secondaryCooldownTimer = 0.0f;
this.primaryRoundsFired = 0;
this.secondaryRoundsFired = 0;
this.primaryCurrentBarrel = 0;
this.secondaryCurrentBarrel = 0;
}
public static Vector2 WorldPosToImagePos(Vector3 worldPos) {
Vector3 vector3_2 = new Vector3();
vector3_2.x = worldPos.x;
vector3_2.y = worldPos.y;
return (Vector2)vector3_2;
}
public void ClearTarget() {
CancelInvoke();
isLockAlarmPlaying = false;
lockOnSeconds = 0;
if (target != null) {
var rhib = target as RHIB;
var rhibWrapper = rhib?.GetComponent<HelicopterWrapper>();
if (rhibWrapper != null) rhibWrapper.TriggerLockLost(this);
}
targetAngleX = 0.0f;
targetAngleY = 0.0f;
target = null;
targetLocked = false;
acquiringLock = false;
}
private void PlayLockAlarm() {
isLockAlarmPlaying = true;
Effect.server.Run(configuration.AlarmSfx, this.player.transform.position);
// Increase frequency if a lock is acquired
Invoke("PlayLockAlarm", targetLocked ? 0.2f : 1f);
}
public void SetLockTarget(BaseEntity target) {
acquiringLock = false;
targetLocked = true;
var rhibWrapper = this.target?.GetComponent<HelicopterWrapper>();
if (rhibWrapper != null) rhibWrapper.TriggerLockLost(this);
this.target = target;
rhibWrapper = this.target.GetComponent<HelicopterWrapper>();
if (rhibWrapper != null) rhibWrapper.TriggerLockAcquired(this);
}
#endregion
#region Methods
public void SetPlayer(BasePlayer player) {
if (player == null) return;
if (this.player == player && this.vehicle.GetPlayerSeat(player) != 0) {
RemovePlayer(player);
return;
}
else if (this.vehicle.GetPlayerSeat(player) != 0) return;
this.player = player;
ClearTarget();
Toggle_WeaponTypesGui(true);
}
public void RemovePlayer(BasePlayer player) {
if (player == null || this.player != player) return;
this.ClearTarget();
this.ResetWeapons();
Toggle_ReticleGui(false);
Toggle_AmmoGui(false, null);
Toggle_FlareAmmoGui(false);
Toggle_CooldownGui(false);
Toggle_WeaponTypesGui(false);
Toggle_DrawTargetLock(false);
// ... [Code preview truncated due to length. Full source in attached file] ...