C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using System.Reflection;
using System;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using Rust;
namespace Oxide.Plugins {
[Info("Blueprints", "Jake_Rich", 0.1, ResourceId = 2433)]
[Description("The original Blueprint System and balance changes!")]
public class BlueprintsRevived : RustPlugin {
public static BlueprintsRevived _plugin {
get;
set;
}
void Init() {
_plugin = this;
}
void OnServerInitialized() {
UnityEngine.Random.InitState((int)DateTime.Now.Ticks);
if (ImageLibrary == null) {
Puts("WARNING! Blueprints was not loaded.Image Library is not installed! Please download ImageLibrary from oxide!");
return;
}
InitLangAPI();
database = new Database();
//Database class has ConfigurationAccessors inside it
Settings_BlueprintTiers = new GithubConfig<SavedBlueprintTiers>("Blueprint-ItemSettings");
LootTables = new GithubConfig<SavedLootTables>("Blueprint-LootTables");
Settings_DevOnly = new GithubConfig<SavedSettingsNonEdit>("Blueprint-Developer-Settings");
ReloadSettings();
SetSettings();
ItemManager.itemList.First(x => x.shortname == "xmas.present.small").stackable = 1000;
ItemManager.itemList.First(x => x.shortname == "xmas.present.medium").stackable = 100;
if (componentList == null) {
Puts("Component list is null!");
}
foreach (var bp in ItemManager.itemList) {
if (GetItemTier(bp.shortname) != BPType.None) //Leave components in uncraftables like CCTV cameras
{
bp?.Blueprint?.ingredients?.RemoveAll(x => componentList.Contains(x.itemDef.shortname));
}
}
SetupUI();
foreach (BasePlayer player in UnityEngine.Object.FindObjectsOfType<BasePlayer>()) {
OnPlayerInit(player);
}
AddImage("http://images.akamai.steamusercontent.com/ugc/172666352576493947/A4E7CA0FF947BF4D9FCAC1CD10695AFF1DD1ADE7/?interpolation=lanczos-none", "xmas.present.small", fragsSkinID);
AddImage("https://i.gyazo.com/0a3b40b6c84066e1437c9ede8de24ab4.png", "xmas.present.medium", pageSkinID);
AddImage("http://images.akamai.steamusercontent.com/ugc/172666352576699519/A4B67A925C05035D1E35F6F625319C7C245853C2/?interpolation=lanczos-none", "xmas.present.medium", bookSkinID);
AddImage("http://images.akamai.steamusercontent.com/ugc/172666352576709367/42AB45CEC824CA43486EFCDF08B19A9C0E2E6558/?interpolation=lanczos-none", "xmas.present.large", librarySkinID);
SpawnMonumentBenches();
foreach (var ent in GameObject.FindObjectsOfType<BaseNetworkable>()) {
OnEntitySpawned(ent);
}
//ExportLootTables();
}
void Unload() {
CleanupMonumentBenches();
foreach (var player in messageTimers.Keys.ToList()) {
CloseMessage(player);
}
ItemManager.itemList.First(x => x.shortname == "xmas.present.small").stackable = 30;
ItemManager.itemList.First(x => x.shortname == "xmas.present.medium").stackable = 15;
foreach (BasePlayer player in BasePlayer.activePlayerList) {
HandleManagedComponents(player, removeComponents : true, giveComponents : false);
StopResearch(player);
}
database.Unload();
foreach (var researchComp in GameObject.FindObjectsOfType<ResearchTableCollider>()) {
GameObject.Destroy(researchComp);
}
openIconPanel.HideAll();
}
void SetSettings() {
if (Settings.unlisted) {
ServerMgr.Instance.CancelInvoke("UpdateServerInformation");
}
else {
ServerMgr.Instance.InvokeRepeating("UpdateServerInformation", 1f, 10f);
}
ConVar.Server.radiation = Settings.radiation;
Settings_BlueprintTiers.Instance.itemLevels["heavy.plate.helmet"] = Settings.disable_heavyArmour ? BPType.None : BPType.Library;
Settings_BlueprintTiers.Instance.itemLevels["heavy.plate.jacket"] = Settings.disable_heavyArmour ? BPType.None : BPType.Library;
Settings_BlueprintTiers.Instance.itemLevels["heavy.plate.pants"] = Settings.disable_heavyArmour ? BPType.None : BPType.Library;
Settings_BlueprintTiers.Instance.Initalize();
Settings_BlueprintTiers.Save();
}
#region Variables
UnityEngine.Random random = new UnityEngine.Random();
#endregion
#region Settings
public GithubConfig<SavedBlueprintTiers> Settings_BlueprintTiers {
get;
set;
}
public GithubConfig<SavedLootTables> LootTables {
get;
set;
}
public SavedSettings Settings {
get;
set;
}
public GithubConfig<SavedSettingsNonEdit> Settings_DevOnly {
get;
set;
}
public const ulong fragsSkinID = 869862511u;
//Uploaded by me through special method
public const ulong pageSkinID = 884147568u;
public const ulong bookSkinID = 884151226u;
public const ulong librarySkinID = 884152141u;
public enum BPType : ulong {
Default = 0, Frags = 1, Page = 2, Book = 3, Library = 4, None = 99999,
}
protected override void LoadDefaultConfig() {
SaveConfig();
}
public void ReloadSettings() {
Settings_BlueprintTiers.Reload();
Settings_BlueprintTiers.Instance.Initalize();
Settings_BlueprintTiers.Save();
Settings = Config.ReadObject<SavedSettings>();
//Finally converted to a configuration file in the right place! Wulf will love me!
Config.WriteObject(Settings);
Settings = Config.ReadObject<SavedSettings>();
Settings_DevOnly.Reload();
LootTables.Reload();
}
#endregion
#region Configuration classes
public class GithubConfig<Type> : ConfigurationAccessor<Type> where Type : class {
public GithubConfig(string name) : base(name) {
}
public override void Init() {
base.Init();
Download();
}
public void Download() {
Dictionary<string, string> headers = new Dictionary<string, string> {
{
"User-Agent", "aleks976"
}
, {
"Accept", "application/vnd.github.v3+json"
}
}
;
_plugin.webrequest.EnqueueGet($"https://raw.githubusercontent.com/Aleks976/PublicRustPlugins/master/Configurations/Data/{name}.json", (code, response) => {
if (code == 200) {
Type deserialize;
try {
deserialize = JsonConvert.DeserializeObject<Type>(response);
}
catch {
return;
}
Instance = deserialize;
Save();
Load();
_plugin.Puts($"Downloaded {name}.json");
}
else {
_plugin.Puts($"Failed to download {name} settings!");
}
}
, _plugin, headers, 60);
}
}
public class SettingsFile<Type> : ConfigurationAccessor<Type> where Type : class {
public SettingsFile(string name) : base(name) {
}
public override void Init() {
base.Init();
Download();
}
public void Download() {
Dictionary<string, string> headers = new Dictionary<string, string> {
{
"User-Agent", "aleks976"
}
, {
"Accept", "application/vnd.github.v3+json"
}
}
;
_plugin.webrequest.EnqueueGet($"https://raw.githubusercontent.com/Aleks976/PublicRustPlugins/master/Configurations/Data/{name}.json", (code, response) => {
if (code == 200) {
Type deserialize;
try {
deserialize = JsonConvert.DeserializeObject<Type>(response);
}
catch {
return;
}
Instance = deserialize;
Save();
Load();
}
else {
_plugin.Puts($"Failed to download {name} settings!");
}
}
, _plugin, headers, 60);
}
}
public class ConfigurationAccessor<Type> where Type : class {
#region Typed Configuration Accessors
private Type GetTypedConfigurationModel(string storageName) {
return Interface.Oxide.DataFileSystem.ReadObject<Type>(storageName);
}
private void SaveTypedConfigurationModel(string storageName, Type storageModel) {
Interface.Oxide.DataFileSystem.WriteObject(storageName, storageModel);
}
#endregion
public string name {
get;
set;
}
public Type Instance {
get;
set;
}
public ConfigurationAccessor(string name) {
this.name = name;
Init();
}
public virtual void Init() {
Reload();
}
public virtual void Load() {
Instance = GetTypedConfigurationModel(name);
}
public virtual void Save() {
SaveTypedConfigurationModel(name, Instance);
}
public virtual void Reload() {
Load();
//Need to load and save to init list
Save();
Load();
}
}
public Dictionary<BPType, int> bpCount {
get;
set;
}
= new Dictionary<BPType, int>();
public Database database {
get;
set;
}
public class SpawnPointConfiguration {
public float xPos {
get;
set;
}
public float yPos {
get;
set;
}
public float zPos {
get;
set;
}
public float xRot {
get;
set;
}
public float yRot {
get;
set;
}
public float zRot {
get;
set;
}
public float wRot {
get;
set;
}
public static BasePlayer.SpawnPoint ToSpawnPoint(SpawnPointConfiguration configuration) {
if (configuration == null) return null;
var newSpawn = new BasePlayer.SpawnPoint();
newSpawn.pos.x = configuration.xPos;
newSpawn.pos.y = configuration.yPos;
newSpawn.pos.z = configuration.zPos;
newSpawn.rot.x = configuration.xRot;
newSpawn.rot.y = configuration.yRot;
newSpawn.rot.z = configuration.zRot;
newSpawn.rot.w = configuration.wRot;
return newSpawn;
}
public SpawnPointConfiguration(BaseNetworkable entity) {
Position = entity.transform.position;
Rotation = entity.transform.rotation;
}
public SpawnPointConfiguration(Vector3 pos, Quaternion rot) {
Position = pos;
Rotation = rot;
}
public SpawnPointConfiguration() {
}
[JsonIgnore]
public Vector3 Position {
get {
return new Vector3(xPos, yPos, zPos);
}
set {
xPos = value.x;
yPos = value.y;
zPos = value.z;
}
}
[JsonIgnore]
public Quaternion Rotation {
get {
return new Quaternion(xRot, yRot, zRot, wRot);
}
set {
xRot = value.x;
yRot = value.y;
zRot = value.z;
wRot = value.w;
}
}
public static SpawnPointConfiguration FromVectorAndRotation(Vector3 position, Quaternion rot) {
return new SpawnPointConfiguration {
xPos = position.x, yPos = position.y, zPos = position.z, xRot = rot.x, yRot = rot.y, zRot = rot.z, wRot = rot.w
}
;
}
}
public class SavedLootTables {
public Dictionary<string, string> lootContainerAssignments {
get;
set;
}
= new Dictionary<string, string>();
public Dictionary<string, GroupLootDefinition> allLootTables {
get;
set;
}
= new Dictionary<string, GroupLootDefinition>();
}
public class SavedSettings {
public bool pistol_Nerf {
get;
set;
}
= true;
public bool spear_UnNerf {
get;
set;
}
= true;
public bool crossbow_UnNerf {
get;
set;
}
= true;
public bool huntingBow_UnNerf {
get;
set;
}
= true;
public bool buildingPriv_UnNerf {
get;
set;
}
= true;
public bool radiation {
get;
set;
}
= true;
public bool unlisted {
get;
set;
}
= false;
public bool disable_heavyArmour {
get;
set;
}
= true;
public bool softside_ladder {
get;
set;
}
= true;
public bool arrowRaiding {
get;
set;
}
= true;
public bool hempSeeds {
get;
set;
}
= false;
public bool blockRecyclingRoadsigns {
get;
set;
}
= true;
public bool p250DamageBuff {
get;
set;
}
= true;
public float blueprintRate {
get;
set;
}
= 1f;
}
public class SavedSettingsNonEdit {
public Dictionary<string, SpawnPointConfiguration> monumentResearchBenches {
get;
set;
}
= new Dictionary<string, SpawnPointConfiguration>();
}
public class SavedBlueprintTiers {
public Dictionary<string, BPType> itemLevels {
get;
set;
}
= new Dictionary<string, BPType>();
public Dictionary<BPType, List<string>> BPGroups = new Dictionary<BPType, List<string>>();
public SavedBlueprintTiers() {
foreach (var item in itemLevels.Values) {
if (!_plugin.bpCount.ContainsKey(item)) {
_plugin.bpCount[item] = 0;
}
_plugin.bpCount[item]++;
}
}
public void Initalize() {
foreach (var item in ItemManager.itemList) {
if (!itemLevels.ContainsKey(item.shortname)) {
itemLevels[item.shortname] = BPType.None;
_plugin.Puts($"Found unassigned item: {item.shortname}");
}
}
BPGroups.Clear();
for (BPType type = BPType.Frags; type <= BPType.Library; type++) //Nicer looking config
{
BPGroups.Add(type, new List<string>());
}
BPGroups.Add(BPType.Default, new List<string>());
BPGroups.Add(BPType.None, new List<string>());
foreach (var item in itemLevels) {
if (!BPGroups.ContainsKey(item.Value)) {
BPGroups.Add(item.Value, new List<string>());
}
BPGroups[item.Value].Add(item.Key);
}
}
}
public class Database {
private ConfigurationAccessor<DatabaseData> database {
get;
set;
}
= new ConfigurationAccessor<DatabaseData>("Blueprint-Database");
private ConfigurationAccessor<DatabaseData> backup {
get;
set;
}
= new ConfigurationAccessor<DatabaseData>("Blueprint-Database-Backup");
[JsonIgnore]
private Timer autosave {
get;
set;
}
public Database() {
autosave?.Destroy();
autosave = _plugin.timer.Every(60f, Save);
}
public bool LearnBlueprint(BasePlayer player, int itemID) {
BlueprintData playerdata;
if (!database.Instance.playerData.TryGetValue(player.userID, out playerdata)) {
playerdata = new BlueprintData(player.userID);
database.Instance.playerData[player.userID] = playerdata;
}
if (playerdata.unlockedItems.Contains(itemID)) {
_plugin.DisplayMessage(player, "You already learned this!");
return false;
}
playerdata.unlockedItems.Add(itemID);
return true;
}
public bool HasBlueprint(BasePlayer player, int itemID) {
BlueprintData playerdata;
if (!database.Instance.playerData.TryGetValue(player.userID, out playerdata)) {
playerdata = new BlueprintData(player.userID);
database.Instance.playerData[player.userID] = playerdata;
}
return playerdata.unlockedItems.Contains(itemID);
}
public void ClearBlueprints(ulong userID, BPType type) {
BlueprintData playerdata;
if (!database.Instance.playerData.TryGetValue(userID, out playerdata)) {
playerdata = new BlueprintData(userID);
database.Instance.playerData[userID] = playerdata;
}
playerdata.unlockedItems.RemoveWhere(x => _plugin.GetItemIDTier(x) == type);
}
public void Save() {
database.Save();
database.Instance.version++;
}
public void Unload() {
Save();
backup.Instance = database.Instance;
backup.Save();
}
}
public class DatabaseData {
public Dictionary<ulong, BlueprintData> playerData {
get;
set;
}
= new Dictionary<ulong, BlueprintData>();
public uint version = 0;
}
public class BlueprintData {
public ulong userID = 0;
public HashSet<int> unlockedItems {
get;
set;
}
= new HashSet<int>();
public BlueprintData(ulong id) {
userID = id;
}
public BlueprintData() {
}
}
#endregion
#region SpawnEntities
bool TryToPlace(BasePlayer player, out BaseEntity ent, bool facingSky = false) {
ent = null;
Item item = player.GetActiveItem();
BaseEntity heldEntity = player.GetHeldEntity();
if (item == null || heldEntity == null) {
Puts("Item or held entity is null");
return false;
}
if (heldEntity.GetType() != typeof(Planner)) {
Puts("Held entity isn't planner");
return false;
}
Planner planner = ((Planner)heldEntity);
Deployable deployable = planner.GetDeployable();
if (deployable == null) {
Puts("Deployable is null");
return false;
}
Vector3 targetPosition = player.transform.position;
Quaternion targetRotation = player.transform.rotation;
RaycastHit raycastHit;
Ray ray = player.eyes.BodyRay();
if (!Physics.Raycast(ray, out raycastHit, 4f, 1101070337)) {
targetPosition = player.eyes.position + player.eyes.BodyRay().direction * 4f;
targetRotation = player.eyes.rotation * Quaternion.Euler(0, 0, 180);
}
else {
targetPosition = raycastHit.point;
targetRotation = Quaternion.LookRotation(raycastHit.normal) * Quaternion.Euler(90, 0, 0);
}
if (facingSky) {
targetRotation.x = 0;
targetRotation.z = 0;
}
if (raycastHit.normal.normalized == Vector3.up) {
}
targetRotation *= Quaternion.Euler(0, 90, 0);
ItemModDeployable itemModDeployable = planner.GetModDeployable();
BaseEntity placedObject = GameManager.server.CreateEntity(itemModDeployable.entityPrefab.resourcePath, targetPosition, targetRotation);
placedObject.skinID = item.skin;
placedObject.SendMessage("SetDeployedBy", player, SendMessageOptions.DontRequireReceiver);
placedObject.OwnerID = 0;
placedObject.Spawn();
UnityEngine.Object.Destroy(placedObject.GetComponent<DestroyOnGroundMissing>());
UnityEngine.Object.Destroy(placedObject.GetComponent<GroundWatch>());
ent = placedObject;
return true;
}
void PlaceResearchBench(BasePlayer player) {
BaseEntity entity;
if (!TryToPlace(player, out entity, true)) {
return;
}
float lowestDist = float.MaxValue;
MonumentInfo closest = null;
foreach (var monument in UnityEngine.Object.FindObjectsOfType<MonumentInfo>()) {
float dist = Vector3.Distance(player.transform.position, monument.transform.position);
if (dist < lowestDist) {
lowestDist = dist;
closest = monument;
}
}
Vector3 pos = closest.transform.InverseTransformPoint(entity.transform.position);
Quaternion rot = Quaternion.Inverse(entity.transform.rotation) * closest.transform.rotation;
Settings_DevOnly.Instance.monumentResearchBenches[closest.name] = new SpawnPointConfiguration(pos, rot);
Settings_DevOnly.Save();
}
#endregion
#region Monuments
public HashSet<BaseEntity> monumentResearchBenches = new HashSet<BaseEntity>();
void SpawnMonumentBenches() {
foreach (var monument in UnityEngine.Object.FindObjectsOfType<MonumentInfo>()) {
SpawnPointConfiguration spawnPoint;
if (Settings_DevOnly.Instance.monumentResearchBenches.TryGetValue(monument.name, out spawnPoint)) {
ResearchTable placedObject = GameManager.server.CreateEntity("assets/prefabs/deployable/research table/researchtable_deployed.prefab", monument.transform.TransformPoint(spawnPoint.Position), Quaternion.Inverse(spawnPoint.Rotation) * monument.transform.rotation) as ResearchTable;
placedObject.OwnerID = 0;
placedObject.Spawn();
UnityEngine.Object.Destroy(placedObject.GetComponent<DestroyOnGroundMissing>());
UnityEngine.Object.Destroy(placedObject.GetComponent<GroundWatch>());
monumentResearchBenches.Add(placedObject);
}
}
}
void CleanupMonumentBenches() {
foreach (var bench in monumentResearchBenches) {
if (!bench.IsDestroyed) {
bench.Kill();
}
}
}
#endregion
#region BP Functions
BPType GetRarityType(string name) {
switch (name) {
case "Common" : {
return BPType.Frags;
}
case "Uncommon" : {
return BPType.Page;
}
case "Rare" : {
return BPType.Book;
}
case "VeryRare" : {
return BPType.Library;
}
}
return BPType.None;
}
BPType GetBPType(Item item) {
switch (item.skin) {
case fragsSkinID : {
return BPType.Frags;
}
case pageSkinID : {
return BPType.Page;
}
case bookSkinID : {
return BPType.Book;
}
case librarySkinID : {
return BPType.Library;
}
default : {
return BPType.None;
}
}
}
int GetBPFragAmount(BPType type) {
switch (type) {
case BPType.Frags : {
return 1;
}
case BPType.Page : {
return 50;
}
case BPType.Book : {
return GetBPFragAmount(BPType.Page) * 5;
}
case BPType.Library : {
return GetBPFragAmount(BPType.Book) * 5;
;
}
default : {
return 0;
}
}
}
string GetBPName(BPType item) {
switch (item) {
case BPType.Frags : {
return "Blueprint Fragment";
}
case BPType.Page : {
return "Blueprint Page";
}
case BPType.Book : {
return "Blueprint Book";
}
case BPType.Library : {
return "Blueprint Library";
}
default : {
return "";
}
}
}
public int GetFragsNeeded(BPType type) {
switch (type) {
case BPType.Default : {
return -1;
}
case BPType.Frags : {
return 100;
}
case BPType.Page : {
return 250;
}
case BPType.Book : {
return 500;
}
case BPType.Library : {
return 1000;
}
default : case BPType.None : {
return int.MaxValue;
}
}
}
public int GetFragsNeeded(Item item) {
return GetFragsNeeded(GetItemTier(item));
}
public BPType GetItemTier(Item item) {
return GetItemTier(item.info.shortname);
}
public BPType GetItemTier(string shortname) {
BPType type;
if (!Settings_BlueprintTiers.Instance.itemLevels.TryGetValue(shortname, out type)) {
return BPType.None;
}
return type;
}
public BPType GetItemIDTier(int id) {
return GetItemTier(ItemManager.FindItemDefinition(id)?.shortname);
}
bool RnG(float chance) {
return UnityEngine.Random.Range(0f, 1f) < chance;
}
void InsertBPFrags(ItemContainer inventory) {
int amount = 0;
if (RnG(0.25f)) {
amount += UnityEngine.Random.Range(5, 16);
}
int num = 0;
for (int j = 0; j < inventory.capacity; j++) {
Item slot = inventory.GetSlot(j);
if (slot == null) {
break;
}
num += (int)slot.info.rarity;
}
if (num <= 3) {
if (RnG(0.75f)) {
amount += UnityEngine.Random.Range(5, 16);
}
}
amount = (int)(amount * Settings.blueprintRate);
if (amount > 0) {
AddBlueprints(inventory, BPType.Frags, amount);
}
}
bool IsLootContainer(BaseNetworkable entity) {
return entity is LootContainer;
}
Item CreateBlueprint(BPType type, int amount) {
Item item = null;
switch (type) {
case BPType.Frags : {
item = ItemManager.CreateByName("xmas.present.small", amount, fragsSkinID);
break;
}
case BPType.Page : {
item = ItemManager.CreateByName("xmas.present.medium", amount, pageSkinID);
break;
}
case BPType.Book : {
item = ItemManager.CreateByName("xmas.present.medium", amount, bookSkinID);
break;
}
case BPType.Library : {
item = ItemManager.CreateByName("xmas.present.large", amount, librarySkinID);
break;
}
}
if (item == null) {
Puts("AddBlueprints() error creating BPs!");
return null;
}
item.name = GetBPName(type);
return item;
}
void AddBlueprints(ItemContainer container, BPType type, int amount, bool dropOnFull = false) {
Item item = CreateBlueprint(type, amount);
if (item == null) {
return;
}
if (!item.MoveToContainer(container) && dropOnFull) {
item.Drop(container.dropPosition, container.dropVelocity);
}
}
int GetBPAmountToCombine(BPType type) {
switch (type) {
case BPType.Frags : {
return 50;
}
case BPType.Page : case BPType.Book : {
return 5;
}
default : case BPType.Library : {
return -1;
}
}
}
void CombineFrags(Item item, BPType currentLevel) {
int targetAmount = 0;
if (GetBPType(item) == BPType.None) {
return;
}
targetAmount = GetBPAmountToCombine(currentLevel);
if (targetAmount <= 0) {
return;
}
if (item.amount < targetAmount) {
return;
}
item.amount -= targetAmount;
if (item.amount <= 0) {
item.Remove();
}
AddBlueprints(item.parent, currentLevel + 1, 1, true);
}
public bool RevealBlueprint(BasePlayer player, BPType type) {
if (!Settings_BlueprintTiers.Instance.BPGroups.ContainsKey(type)) {
return false;
}
UnityEngine.Random.InitState((int)Time.time);
int itemID;
if (!TryGetRandomUnlearnedBlueprint(player, type, out itemID)) {
DisplayMessage(player, $"You already know all about {GetBPName(type)}!");
return false;
}
GiveItemBlueprint(player, itemID);
return true;
}
bool TryGetRandomUnlearnedBlueprint(BasePlayer player, BPType type, out int itemID) {
itemID = -1;
var playerInventoryBlueprintItemNames = GetBlueprintItemNamesInPlayerInventory(player);
List<ItemDefinition> unlearnedItems = Settings_BlueprintTiers.Instance.BPGroups[type].Select(itemId => ItemManager.FindItemDefinition(itemId)).Where(itemDef => itemDef != null).Where(itemDef => !playerInventoryBlueprintItemNames.Contains(itemDef.itemid)).Where(itemDef => !database.HasBlueprint(player, itemDef.itemid)).ToList();
if (!unlearnedItems.Any()) {
return false;
}
var randomIndex = UnityEngine.Random.Range(0, unlearnedItems.Count);
var item = unlearnedItems[randomIndex];
if (item == null) {
return false;
}
itemID = item.itemid;
return true;
}
int GetRandomBlueprint(BPType type) {
string itemName = Settings_BlueprintTiers.Instance.BPGroups[type][UnityEngine.Random.Range(0, Settings_BlueprintTiers.Instance.BPGroups[type].Count)];
var itemDef = ItemManager.FindItemDefinition(itemName);
if (itemDef == null) {
return -1;
}
return itemDef.itemid;
}
HashSet<int> GetBlueprintItemNamesInPlayerInventory(BasePlayer player) {
HashSet<int> inventoryBlueprints = new HashSet<int>();
foreach (var item in player.inventory.AllItems()) {
if (item.info.shortname == "blueprintbase") {
if (!inventoryBlueprints.Contains(item.blueprintTarget)) {
inventoryBlueprints.Add(item.blueprintTarget);
}
}
}
return inventoryBlueprints;
}
Item GetRandomItemBlueprint(BPType type) {
return GetItemBlueprint(GetRandomBlueprint(type));
}
Item GetItemBlueprint(int id) {
Item itemBlueprint = ItemManager.CreateByName("blueprintbase");
itemBlueprint.blueprintTarget = id;
return itemBlueprint;
}
public void RevealBlueprint(BasePlayer player, Item item) {
BPType type = GetBPType(item);
if (type == BPType.Frags) {
if (item.amount < 20) {
return;
}
}
if (!RevealBlueprint(player, type)) {
return;
}
item.amount -= (type == BPType.Frags ? 20 : 1);
if (item.amount <= 0) {
item.Remove();
}
item.MarkDirty();
}
void TryMoveItem(Item item, ItemContainer container, int slot = -1) {
if (!item.MoveToContainer(container)) {
item.Drop(container.dropPosition, container.dropVelocity);
}
}
void GiveItemBlueprint(BasePlayer player, int itemID) {
ItemDefinition itemDefinition = ItemManager.itemList.Find((ItemDefinition x) => x.itemid == itemID);
GiveItemBlueprint(player, itemDefinition.shortname);
}
void GiveItemBlueprint(BasePlayer player, string itemName) {
Item itemBlueprint = ItemManager.CreateByName("blueprintbase");
ItemDefinition itemDefinition = ItemManager.itemList.Find((ItemDefinition x) => x.shortname == itemName);
if (itemDefinition == null) {
Puts("GiveItemBlueprint() couldnt find itemID based on name!");
return;
}
itemBlueprint.blueprintTarget = itemDefinition.itemid;
foreach (var currentSlot in player.inventory.containerMain.itemList) {
if (currentSlot.info.itemid == itemBlueprint.info.itemid) {
if (currentSlot.blueprintTarget == itemBlueprint.blueprintTarget) {
TryMoveItem(itemBlueprint, player.inventory.containerMain, currentSlot.position);
return;
}
}
}
TryMoveItem(itemBlueprint, player.inventory.containerMain);
}
bool LearnBlueprint(BasePlayer player, int itemID) {
return database.LearnBlueprint(player, itemID);
}
bool DropBlueprint(Item item, DroppedItem originalItem = null) {
BPType type = GetBPType(item);
if (type == BPType.None) {
return false;
}
item.Remove();
Item itemToDrop = ItemManager.CreateByName("blueprintbase", item.amount);
itemToDrop.name = GetBPName(type);
itemToDrop.blueprintTarget = (int)type;
ItemContainer container = item.GetRootContainer();
if (container == null) {
itemToDrop.Drop(originalItem.transform.position, Vector3.zero);
return true;
}
itemToDrop.Drop(container.dropPosition, container.dropVelocity);
return true;
}
public List<ResearchTable> GetResearchTables() {
return GameObject.FindObjectsOfType<ResearchTable>().ToList();
}
#endregion
#region Display Messages
private Dictionary<BasePlayer, Timer> messageTimers {
get;
set;
}
= new Dictionary<BasePlayer, Timer>();
private CuiElementContainer messagebox = new CuiElementContainer();
private CuiLabel messageLabel {
get;
set;
}
void DisplayMessage(BasePlayer player, string message, float time = 2.5f) {
//PrintToChat(player, message);
CloseMessage(player);
messageTimers[player] = this.timer.In(time, () => {
DestroyUI(player, messagebox);
}
);
messageLabel.Text.Text = message;
CuiHelper.AddUi(player, messagebox);
}
void SetupUI() {
messageLabel = new CuiLabel();
messagebox.Add(messageLabel, "Hud.Menu");
messageLabel.RectTransform.AnchorMin = "0.64 0.02";
messageLabel.RectTransform.AnchorMax = "0.84 0.14";
messageLabel.Text.Align = TextAnchor.MiddleCenter;
messageLabel.Text.FontSize = 20;
var panel = new CuiPanel();
panel.RectTransform.AnchorMin = messageLabel.RectTransform.AnchorMin;
panel.RectTransform.AnchorMax = messageLabel.RectTransform.AnchorMax;
panel.Image.Color = "0 0 0 0.4";
messagebox.Add(panel, "Hud.Menu");
/*
foreach(var element in messagebox)
{
element.FadeOut = 1f;
}*/
SetupResearchUI();
}
void CloseMessage(BasePlayer player) {
Timer timer;
if (messageTimers.TryGetValue(player, out timer)) {
timer?.Destroy();
messageTimers.Remove(player);
}
DestroyUI(player, messagebox);
}
#endregion
#region Lang API
public Dictionary<string, string> LangAPI = new Dictionary<string, string>() {
{
"ResearchBench_TopInfoPanel", "Drop items to add them to the research bench."
}
, {
"ResearchBench_SourceLabel", "Source Item."
}
, {
"ResearchBench_FragmentLabel", "Fragment Boost"
}
, {
"ResearchBench_FragmentBoost", "Adding fragments increases your chance of success."
}
, {
"ResearchBench_ChanceOfSuccessLabel", "Chance of success"
}
, {
"ResearchBench_ChanceInfo", "Increase the chance of success by adding frags or a better source item."
}
, {
"ResearchBench_ExitLabel", "Exit"
}
, {
"ResearchBench_StartResearch", "BEGIN RESEARCH"
}
, {
"ResearchBench_OpenIcon", "OPEN"
}
,
}
;
public void InitLangAPI() {
lang.RegisterMessages(LangAPI, this);
}
#endregion
#region UI
void DestroyUI(BasePlayer player, CuiElementContainer container) {
foreach (var element in container) {
CuiHelper.DestroyUi(player, element.Name);
}
}
#endregion
#region Hooks
object OnOvenFull(BaseOven oven) {
return true;
}
void CanBuild(Planner planner, Construction construction, Vector3 position) {
if (Settings.buildingPriv_UnNerf) {
construction.canBypassBuildingPermission = true;
}
}
object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (entity is ResearchTable) {
if (monumentResearchBenches.Contains(entity)) {
return true;
}
return null;
}
if (info.InitiatorPlayer == null) {
return null;
}
if (info.WeaponPrefab != null) {
//Puts($"Weapon: {info.WeaponPrefab.ShortPrefabName} {info.damageTypes.Total()}");
}
bool isArrowProjectile = info.ProjectilePrefab != null && info.ProjectilePrefab.name.Contains("arrow_");
#region Softside Doors
if (entity is DecayEntity && (info.ProjectilePrefab == null)) // Is decay entity and NOT an arrow projectile -- Arrows handled elsewhere
{
Vector3 hitDirection = info.InitiatorPlayer.eyes.position - info.HitPositionWorld;
var field = typeof(BaseCombatEntity).GetField("propDirection", BindingFlags.Instance | BindingFlags.NonPublic);
var propDirection = (DirectionProperties[])field.GetValue(entity);
for (int i = 0; i < propDirection.Length; i++) {
if (propDirection[i].extraProtection != null) {
if (entity.PrefabName.StartsWith("assets/prefabs/building/door.hinged") && info.HitNormalLocal.z < 0) // Weak Side Single Door
{
//Puts($"Hit Weak Side Single Door");
info.damageTypes.ScaleAll(10f);
}
else if (entity.PrefabName.StartsWith("assets/prefabs/building/door.double.hinged") && info.HitNormalLocal.x > 0) {
//Puts($"Hit Weak Side Double Door");
info.damageTypes.ScaleAll(10f);
}
else if (entity.PrefabName == "assets/prefabs/building/floor.ladder.hatch/floor.ladder.hatch.prefab" && info.HitNormalLocal.y < 0) {
// Puts($"Hit Hatch Weak Side");
info.damageTypes.ScaleAll(10f);
}
}
}
}
#endregion
if (info.ProjectilePrefab != null) {
#region Un-nerf spears
if (info.ProjectilePrefab.name.Contains("_spear")) {
if (Settings.spear_UnNerf) {
info.damageTypes.ScaleAll(2f / 1.5f);
}
return null;
}
#endregion
#region Un-nerf P250
if (Settings.p250DamageBuff) {
if (info.WeaponPrefab.ShortPrefabName.Contains("pistol_semiauto.entity")) {
if (info.isHeadshot) {
info.damageTypes.ScaleAll(1.3f);
}
else {
info.damageTypes.ScaleAll(1.10f);
}
}
}
#endregion
if (info.ProjectilePrefab.name.Contains("arrow_")) {
if (entity is DecayEntity) {
#region Arrow raiding
if (entity.PrefabName == "assets/prefabs/building/door.hinged/door.hinged.wood.prefab" || entity.PrefabName == "assets/prefabs/building/door.double.hinged/door.double.hinged.wood.prefab") {
entity.baseProtection.amounts[(int)DamageType.Arrow] = Settings.arrowRaiding ? 0.96f : 1f;
}
if (entity is BuildingBlock) {
BuildingBlock block = entity as BuildingBlock;
switch (block.grade) {
case BuildingGrade.Enum.Wood : {
entity.baseProtection.amounts[(int)DamageType.Arrow] = Settings.arrowRaiding ? 0.96f : 1f;
break;
}
case BuildingGrade.Enum.Stone : {
entity.baseProtection.amounts[(int)DamageType.Arrow] = Settings.arrowRaiding ? 0.99f : 1f;
break;
}
}
}
#endregion
}
else if (entity is BasePlayer) {
#region Arrow Un-Nerf
if (info.isHeadshot) {
float num = info.ProjectilePrefab.damageMultipliers.Lerp(info.ProjectilePrefab.modifier.distanceOffset + info.ProjectilePrefab.modifier.distanceScale * info.ProjectilePrefab.damageDistances.x, info.ProjectilePrefab.modifier.distanceOffset + info.ProjectilePrefab.modifier.distanceScale * info.ProjectilePrefab.damageDistances.y, info
// ... [Code preview truncated due to length. Full source in attached file] ...