diff --git a/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs b/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs index f61021faf..c71b95cdf 100644 --- a/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs +++ b/src/Perpetuum.Bootstrapper/PerpetuumBootstrapper.cs @@ -119,6 +119,7 @@ using Perpetuum.Zones.Environments; using Perpetuum.Zones.Gates; using Perpetuum.Zones.Intrusion; +using Perpetuum.Zones.LandMines; using Perpetuum.Zones.NpcSystem; using Perpetuum.Zones.NpcSystem.Flocks; using Perpetuum.Zones.NpcSystem.Presences; @@ -143,6 +144,7 @@ using Perpetuum.Zones.PlantTools; using Perpetuum.Zones.ProximityProbes; using Perpetuum.Zones.PunchBags; +using Perpetuum.Zones.RemoteControl; using Perpetuum.Zones.Scanning.Ammos; using Perpetuum.Zones.Scanning.Modules; using Perpetuum.Zones.Scanning.Results; @@ -189,20 +191,20 @@ namespace Perpetuum.Bootstrapper { - class EntityAggregateServices : IEntityServices + internal class EntityAggregateServices : IEntityServices { public IEntityFactory Factory { get; set; } public IEntityDefaultReader Defaults { get; set; } public IEntityRepository Repository { get; set; } } - class RobotTemplateServicesImpl : IRobotTemplateServices + internal class RobotTemplateServicesImpl : IRobotTemplateServices { public IRobotTemplateReader Reader { get; set; } public IRobotTemplateRelations Relations { get; set; } } - class TeleportStrategyFactoriesImpl : ITeleportStrategyFactories + internal class TeleportStrategyFactoriesImpl : ITeleportStrategyFactories { public TeleportWithinZone.Factory TeleportWithinZoneFactory { get; set; } public TeleportToAnotherZone.Factory TeleportToAnotherZoneFactory { get; set; } @@ -218,19 +220,19 @@ public class PerpetuumBootstrapper public void Start() { - var s = _container.Resolve(); + IHostStateService s = _container.Resolve(); s.State = HostState.Starting; } public void Stop() { - var s = _container.Resolve(); + IHostStateService s = _container.Resolve(); s.State = HostState.Stopping; } public void Stop(TimeSpan delay) { - var m = _container.Resolve(); + HostShutDownManager m = _container.Resolve(); m.Shutdown(delay); } @@ -241,25 +243,27 @@ public IContainer GetContainer() public void WaitForStop() { - var are = new AutoResetEvent(false); + AutoResetEvent are = new AutoResetEvent(false); - var s = _container.Resolve(); + IHostStateService s = _container.Resolve(); s.StateChanged += (sender, state) => { if (state == HostState.Off) - are.Set(); + { + _ = are.Set(); + } }; - are.WaitOne(); + _ = are.WaitOne(); } public void WriteCommandsToFile(string path) { - var sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(); - foreach (var command in GetCommands().OrderBy(c => c.Text)) + foreach (Command command in GetCommands().OrderBy(c => c.Text)) { - sb.AppendLine($"{command.Text},{command.AccessLevel}"); + _ = sb.AppendLine($"{command.Text},{command.AccessLevel}"); } File.WriteAllText(path, sb.ToString()); @@ -277,7 +281,7 @@ public void Init(string gameRoot) _container = _builder.Build(); Logger.Current = _container.Resolve>(); - var config = _container.Resolve(); + GlobalConfiguration config = _container.Resolve(); _container.Resolve().State = HostState.Init; @@ -288,7 +292,7 @@ public void Init(string gameRoot) Db.DbQueryFactory = _container.Resolve>(); - using (var connection = _container.Resolve()()) { Logger.Info($"Database: {connection.Database}"); } + using (System.Data.IDbConnection connection = _container.Resolve()()) { Logger.Info($"Database: {connection.Database}"); } InitGame(_container); @@ -379,16 +383,18 @@ public void Init(string gameRoot) public bool TryInitUpnp(out bool success) { success = false; - var config = _container.Resolve(); + GlobalConfiguration config = _container.Resolve(); if (!config.EnableUpnp) + { return false; + } try { - var discoverer = new NatDiscoverer(); + NatDiscoverer discoverer = new NatDiscoverer(); NatDiscoverer.ReleaseAll(); - var natDevice = discoverer.DiscoverDeviceAsync().Result; + NatDevice natDevice = discoverer.DiscoverDeviceAsync().Result; if (natDevice == null) { Logger.Error("[UPNP] NAT device not found!"); @@ -397,7 +403,7 @@ public bool TryInitUpnp(out bool success) void Map(int port) { - var task = natDevice.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port)).ContinueWith(t => + System.Threading.Tasks.Task task = natDevice.CreatePortMapAsync(new Mapping(Protocol.Tcp, port, port)).ContinueWith(t => { Logger.Info($"[UPNP] Port mapped: {port}"); }); @@ -406,7 +412,7 @@ void Map(int port) Map(config.ListenerPort); - foreach (var zone in _container.Resolve().Zones) + foreach (IZone zone in _container.Resolve().Zones) { Map(zone.Configuration.ListenerPort); } @@ -427,12 +433,12 @@ void Map(int port) private static void InitGame(IComponentContext container) { //the current host has to clean up things in the onlinehost table, and other runtime tables - Db.Query().CommandText("initServer").ExecuteNonQuery(); + _ = Db.Query().CommandText("initServer").ExecuteNonQuery(); - var globalConfiguration = container.Resolve(); + GlobalConfiguration globalConfiguration = container.Resolve(); if (!string.IsNullOrEmpty(globalConfiguration.PersonalConfig)) { - Db.Query().CommandText(globalConfiguration.PersonalConfig).ExecuteNonQuery(); + _ = Db.Query().CommandText(globalConfiguration.PersonalConfig).ExecuteNonQuery(); Logger.Info("Personal sp executed:" + globalConfiguration.PersonalConfig); } @@ -449,30 +455,30 @@ private IRegistrationBuilder(TimeSpan.FromSeconds(7)); - RegisterAutoActivate(TimeSpan.FromMinutes(5)); - RegisterAutoActivate(TimeSpan.FromHours(1)); - RegisterAutoActivate(TimeSpan.FromMinutes(5)); - RegisterAutoActivate(TimeSpan.FromMinutes(10)); - RegisterAutoActivate(TimeSpan.FromMinutes(10)); - RegisterAutoActivate(TimeSpan.FromHours(7)); + _ = RegisterAutoActivate(TimeSpan.FromSeconds(7)); + _ = RegisterAutoActivate(TimeSpan.FromMinutes(5)); + _ = RegisterAutoActivate(TimeSpan.FromHours(1)); + _ = RegisterAutoActivate(TimeSpan.FromMinutes(5)); + _ = RegisterAutoActivate(TimeSpan.FromMinutes(10)); + _ = RegisterAutoActivate(TimeSpan.FromMinutes(10)); + _ = RegisterAutoActivate(TimeSpan.FromHours(7)); } private void RegisterCommands() { - foreach (var command in GetCommands()) + foreach (Command command in GetCommands()) { - _builder.RegisterInstance(command).As().Keyed(command.Text.ToUpper()); + _ = _builder.RegisterInstance(command).As().Keyed(command.Text.ToUpper()); } - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); - return (commandText => + IComponentContext ctx = x.Resolve(); + return commandText => { commandText = commandText.ToUpper(); return ctx.IsRegisteredWithKey(commandText) ? ctx.ResolveKeyed(commandText) : null; - }); + }; }); } @@ -496,268 +502,262 @@ private void InitContainer(string gameRoot) RegisterZones(); RegisterPBS(); - _builder.Register>(x => + _ = _builder.Register>(x => { return name => new MemoryCache(name); }); - _builder.RegisterType().AsSelf().As(); - _builder.Register(c => + _ = _builder.RegisterType().AsSelf().As(); + _ = _builder.Register(c => { - var cache = new MemoryCache("CharacterProfiles"); + MemoryCache cache = new MemoryCache("CharacterProfiles"); return new CachedReadOnlyRepository(cache, c.Resolve()); }).AsSelf().As>().SingleInstance(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().OnActivated(e => { e.Instance.Init(); }).As().SingleInstance(); - _builder.RegisterType().As().AutoActivate().OnActivated(e => + _ = _builder.RegisterType().As().AutoActivate().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromHours(1))); }).SingleInstance(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().As().SingleInstance().AutoActivate(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As().SingleInstance().AutoActivate(); - _builder.RegisterType().AsSelf().As(); + _ = _builder.RegisterType().AsSelf().As(); - _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType().As().SingleInstance(); InitRelayManager(); - _builder.Register(c => new FileSystem(gameRoot)).As(); - _builder.Register(c => + _ = _builder.Register(c => new FileSystem(gameRoot)).As(); + _ = _builder.Register(c => { - var fileManager = c.Resolve(); - var settingsFile = fileManager.ReadAllText("perpetuum.ini"); - var configuration = JsonConvert.DeserializeObject(settingsFile); + IFileSystem fileManager = c.Resolve(); + string settingsFile = fileManager.ReadAllText("perpetuum.ini"); + GlobalConfiguration configuration = JsonConvert.DeserializeObject(settingsFile); configuration.GameRoot = gameRoot; return configuration; }).SingleInstance(); - _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As().SingleInstance(); - _builder.Register(c => + _ = _builder.Register(c => { - var config = c.Resolve(); + GlobalConfiguration config = c.Resolve(); return config.Corporation; }).As(); - _builder.RegisterType().As().SingleInstance(); - _builder.Register(c => new ProcessManager(TimeSpan.FromMilliseconds(50))).As().SingleInstance(); + _ = _builder.RegisterType().As().SingleInstance(); + _ = _builder.Register(c => new ProcessManager(TimeSpan.FromMilliseconds(50))).As().SingleInstance(); - _builder.Register(x => + _ = _builder.Register(x => { - var connectionString = x.Resolve().ConnectionString; - return (() => new SqlConnection(connectionString)); + string connectionString = x.Resolve().ConnectionString; + return () => new SqlConnection(connectionString); }); - _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType(); + _ = _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType(); - _builder.RegisterType().As().SingleInstance().OnActivated(e => e.Instance.Init()); - _builder.RegisterType().SingleInstance(); - _builder.RegisterType(); // this doesn't appear to be something that should be a singleton. + _ = _builder.RegisterType().As().SingleInstance().OnActivated(e => e.Instance.Init()); + _ = _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType(); // this doesn't appear to be something that should be a singleton. - _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType().As(); - _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().AsSelf().As(); - _builder.RegisterType(); - _builder.Register(x => + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().AsSelf().As(); + _ = _builder.RegisterType(); + _ = _builder.Register(x => { - var ctx = x.Resolve(); - return ((character, type) => + IComponentContext ctx = x.Resolve(); + return (character, type) => { return ctx.Resolve(new TypedParameter(typeof(Character), character), new TypedParameter(typeof(TransactionType), type)); - }); + }; }); - _builder.RegisterType().AsSelf(); - _builder.Register(x => x.Resolve(TypedParameter.From(0))).Named("nullcharacter").SingleInstance(); + _ = _builder.RegisterType().AsSelf(); + _ = _builder.Register(x => x.Resolve(TypedParameter.From(0))).Named("nullcharacter").SingleInstance(); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); - return (id => + IComponentContext ctx = x.Resolve(); + return id => { - if (id == 0) - return ctx.ResolveNamed("nullcharacter"); - - return ctx.Resolve(TypedParameter.From(id)); - }); + return id == 0 ? ctx.ResolveNamed("nullcharacter") : ctx.Resolve(TypedParameter.From(id)); + }; }); - _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); - _builder.Register(x => + _ = _builder.Register(x => { - var cfg = x.Resolve(); + GlobalConfiguration cfg = x.Resolve(); return new SteamManager(cfg.SteamAppID, cfg.SteamKey); }).As(); } private void RegisterChannelTypes() { - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().As().SingleInstance(); - - RegisterRequestHandler(Commands.ChannelCreate); - RegisterRequestHandler(Commands.ChannelList); - RegisterRequestHandler(Commands.ChannelListAll); - RegisterRequestHandler(Commands.ChannelMyList); - RegisterRequestHandler(Commands.ChannelJoin); - RegisterRequestHandler(Commands.ChannelLeave); - RegisterRequestHandler(Commands.ChannelKick); - RegisterRequestHandler(Commands.ChannelTalk); - RegisterRequestHandler(Commands.ChannelSetMemberRole); - RegisterRequestHandler(Commands.ChannelSetPassword); - RegisterRequestHandler(Commands.ChannelSetTopic); - RegisterRequestHandler(Commands.ChannelBan); - RegisterRequestHandler(Commands.ChannelRemoveBan); - RegisterRequestHandler(Commands.ChannelGetBannedMembers); - RegisterRequestHandler(Commands.ChannelGlobalMute); - RegisterRequestHandler(Commands.ChannelGetMutedCharacters); - RegisterRequestHandler(Commands.ChannelCreateForTerminals); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As().SingleInstance(); + + _ = RegisterRequestHandler(Commands.ChannelCreate); + _ = RegisterRequestHandler(Commands.ChannelList); + _ = RegisterRequestHandler(Commands.ChannelListAll); + _ = RegisterRequestHandler(Commands.ChannelMyList); + _ = RegisterRequestHandler(Commands.ChannelJoin); + _ = RegisterRequestHandler(Commands.ChannelLeave); + _ = RegisterRequestHandler(Commands.ChannelKick); + _ = RegisterRequestHandler(Commands.ChannelTalk); + _ = RegisterRequestHandler(Commands.ChannelSetMemberRole); + _ = RegisterRequestHandler(Commands.ChannelSetPassword); + _ = RegisterRequestHandler(Commands.ChannelSetTopic); + _ = RegisterRequestHandler(Commands.ChannelBan); + _ = RegisterRequestHandler(Commands.ChannelRemoveBan); + _ = RegisterRequestHandler(Commands.ChannelGetBannedMembers); + _ = RegisterRequestHandler(Commands.ChannelGlobalMute); + _ = RegisterRequestHandler(Commands.ChannelGetMutedCharacters); + _ = RegisterRequestHandler(Commands.ChannelCreateForTerminals); } private void RegisterEffects() { - _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => new ZoneEffectHandler(zone); }); - _builder.RegisterType().Keyed(EffectType.effect_invulnerable); - _builder.RegisterType().Keyed(EffectType.effect_eccm); - _builder.RegisterType().Keyed(EffectType.effect_stealth); - - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_core_recharge_time); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_critical_hit_chance); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_locking_time); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_signature_radius); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_fast_extraction); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_core_usage_gathering); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_siege); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_speed); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_repaired_amount); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_locking_range); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_ewar_optimal); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_armor_max); - _builder.RegisterType().Keyed(EffectType.effect_aura_gang_shield_absorbtion_ratio); + _ = _builder.RegisterType().Keyed(EffectType.effect_invulnerable); + _ = _builder.RegisterType().Keyed(EffectType.effect_eccm); + _ = _builder.RegisterType().Keyed(EffectType.effect_stealth); + + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_core_recharge_time); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_critical_hit_chance); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_locking_time); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_signature_radius); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_fast_extraction); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_core_usage_gathering); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_siege); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_speed); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_repaired_amount); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_locking_range); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_ewar_optimal); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_armor_max); + _ = _builder.RegisterType().Keyed(EffectType.effect_aura_gang_shield_absorbtion_ratio); // intrusion effects - _builder.RegisterType().Keyed(EffectType.effect_intrusion_geoscan_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_geoscan_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_geoscan_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_mining_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_mining_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_mining_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_harvester_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_harvester_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_harvester_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_detection_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_detection_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_detection_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_masking_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_masking_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_masking_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_repair_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_repair_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_repair_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_core_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_core_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_core_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_signals_lvl4_combined); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_industrial_lvl4_combined); - _builder.RegisterType().Keyed(EffectType.effect_intrusion_engineering_lvl4_combined); - - _builder.RegisterType().Keyed(EffectType.effect_pbs_mining_tower_gammaterial_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_mining_tower_gammaterial_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_mining_tower_gammaterial_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_gap_generator_masking_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_gap_generator_masking_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_gap_generator_masking_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_engineering_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_engineering_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_engineering_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_industry_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_industry_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_industry_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_sensors_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_sensors_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_sensors_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_cycle_time_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_cycle_time_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_cycle_time_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_resist_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_resist_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_resist_lvl3); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_sensor_lvl1); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_sensor_lvl2); - _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_sensor_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_geoscan_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_geoscan_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_geoscan_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_mining_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_mining_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_mining_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_harvester_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_harvester_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_harvester_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_detection_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_detection_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_detection_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_masking_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_masking_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_masking_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_repair_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_repair_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_repair_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_core_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_core_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_core_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_signals_lvl4_combined); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_industrial_lvl4_combined); + _ = _builder.RegisterType().Keyed(EffectType.effect_intrusion_engineering_lvl4_combined); + + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_mining_tower_gammaterial_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_mining_tower_gammaterial_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_mining_tower_gammaterial_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_gap_generator_masking_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_gap_generator_masking_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_gap_generator_masking_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_engineering_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_engineering_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_engineering_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_industry_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_industry_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_industry_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_sensors_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_sensors_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_sensors_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_cycle_time_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_cycle_time_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_cycle_time_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_resist_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_resist_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_resist_lvl3); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_sensor_lvl1); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_sensor_lvl2); + _ = _builder.RegisterType().Keyed(EffectType.effect_pbs_booster_sensor_lvl3); // New Bonuses - OPP - _builder.RegisterType().Keyed(EffectType.effect_beta_bonus); - _builder.RegisterType().Keyed(EffectType.effect_beta2_bonus); - _builder.RegisterType().Keyed(EffectType.effect_alpha_bonus); - _builder.RegisterType().Keyed(EffectType.effect_alpha2_bonus); + _ = _builder.RegisterType().Keyed(EffectType.effect_beta_bonus); + _ = _builder.RegisterType().Keyed(EffectType.effect_beta2_bonus); + _ = _builder.RegisterType().Keyed(EffectType.effect_alpha_bonus); + _ = _builder.RegisterType().Keyed(EffectType.effect_alpha2_bonus); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return effectType => { - if (!ctx.IsRegisteredWithKey(effectType)) - return new Effect(); - - return ctx.ResolveKeyed(effectType); + return !ctx.IsRegisteredWithKey(effectType) ? new Effect() : ctx.ResolveKeyed(effectType); }; }); } public void InitItems() { - _builder.RegisterType(); - _builder.RegisterType().AsSelf().OnActivated(e => e.Instance.Init()).SingleInstance(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().AsSelf().OnActivated(e => e.Instance.Init()).SingleInstance(); } private IRegistrationBuilder RegisterEntity() where T : Entity @@ -793,13 +793,13 @@ private IRegistrationBuilder() where T : Corporation { - _builder.RegisterType(); - RegisterEntity().PropertiesAutowired(); + _ = _builder.RegisterType(); + _ = RegisterEntity().PropertiesAutowired(); } - protected void RegisterProximityProbe() where T : ProximityProbeBase + protected void RegisterProximityDevices() where T : ProximityDeviceBase { - RegisterUnit(); + _ = RegisterUnit(); } private IRegistrationBuilder RegisterModule() where T : Module @@ -809,12 +809,12 @@ private IRegistrationBuilder() where T : EffectModule { - RegisterModule(); + _ = RegisterModule(); } private void RegisterProductionFacility() where T : ProductionFacility { - RegisterEntity().PropertiesAutowired(); + _ = RegisterEntity().PropertiesAutowired(); } public IRegistrationBuilder RegisterRobot() where T : Robot @@ -843,6 +843,9 @@ private void RegisterEntities() RegisterRobot().OnActivated(e => e.Instance.SetCoreRecharger(e.Context.Resolve())); RegisterRobot().OnActivated(e => e.Instance.SetCoreRecharger(e.Context.Resolve())); + RegisterRobot().OnActivated(e => e.Instance.SetCoreRecharger(e.Context.Resolve())); + RegisterRobot().OnActivated(e => e.Instance.SetCoreRecharger(e.Context.Resolve())); + RegisterRobot().OnActivated(e => e.Instance.SetCoreRecharger(e.Context.Resolve())); RegisterRobot(); RegisterRobot(); @@ -863,10 +866,10 @@ private void RegisterEntities() RegisterUnit(); RegisterUnit().OnActivated(e => { -#if (DEBUG) - var intrusionWaitTime = TimeRange.FromLength(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15)); +#if DEBUG + TimeRange intrusionWaitTime = TimeRange.FromLength(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(15)); #else - var intrusionWaitTime = TimeRange.FromLength(TimeSpan.FromHours(8), TimeSpan.FromHours(8)); + TimeRange intrusionWaitTime = TimeRange.FromLength(TimeSpan.FromHours(8), TimeSpan.FromHours(8)); #endif e.Instance.IntrusionWaitTime = intrusionWaitTime; }); @@ -905,7 +908,10 @@ private void RegisterEntities() RegisterEntity(); RegisterEntity(); RegisterEntity(); - RegisterProximityProbe(); + + RegisterProximityDevices(); + RegisterProximityDevices(); + RegisterUnit(); RegisterUnit().OnActivated(e => e.Instance.SetDespawnTime(TimeSpan.FromMinutes(15))); RegisterUnit().OnActivated(e => e.Instance.SetDespawnTime(TimeSpan.FromHours(1))); @@ -923,6 +929,7 @@ private void RegisterEntities() RegisterEntity(); RegisterEntity(); RegisterEntity(); + RegisterEntity(); RegisterEntity(); RegisterEntity(); RegisterEntity(); @@ -936,7 +943,6 @@ private void RegisterEntities() RegisterEntity(); RegisterEntity(); RegisterEntity(); - RegisterEntity(); RegisterEntity(); RegisterEntity(); RegisterEntity(); @@ -944,6 +950,8 @@ private void RegisterEntities() RegisterEntity(); RegisterModule(); + RegisterModule(); + RegisterModule(); RegisterModule(); RegisterModule(); RegisterModule(); @@ -962,6 +970,7 @@ private void RegisterEntities() RegisterModule(); RegisterModule(); RegisterModule(); + RegisterModule(); RegisterModule(); RegisterModule(); RegisterModule(); @@ -976,10 +985,9 @@ private void RegisterEntities() RegisterEffectModule(); RegisterEffectModule(); RegisterEffectModule(); + RegisterEffectModule(); RegisterEntity(); - RegisterEntity(); - RegisterEntity(); RegisterEntity(); RegisterUnit(); @@ -1018,13 +1026,14 @@ private void RegisterEntities() RegisterUnit(); // OPP: Special rift spawned eventfully to transport player to location RegisterUnit(); // OPP: Special rift for exiting strongholds - RegisterEntity(); RegisterEntity(); RegisterEntity(); - RegisterEntity(); + + RegisterEntity(); + RegisterEntity(); + RegisterEntity(); RegisterEntity(); - RegisterEntity(); RegisterEntity(); RegisterEntity(); RegisterEntity(); @@ -1041,14 +1050,12 @@ private void RegisterEntities() RegisterEntity(); RegisterEntity(); RegisterEntity(); - RegisterEntity(); - _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); - var b = new ContainerBuilder(); + ContainerBuilder b = new ContainerBuilder(); void ByDefinition(int definition, params Parameter[] parameters) where T : Entity { @@ -1057,7 +1064,7 @@ void ByDefinition(int definition, params Parameter[] parameters) where T : En void ByCategoryFlags(CategoryFlags cf, params Parameter[] parameters) where T : Entity { - foreach (var entityDefault in ctx.Resolve().GetAll().GetByCategoryFlags(cf)) + foreach (EntityDefault entityDefault in ctx.Resolve().GetAll().GetByCategoryFlags(cf)) { ByDefinition(entityDefault.Definition, parameters); } @@ -1065,7 +1072,7 @@ void ByCategoryFlags(CategoryFlags cf, params Parameter[] parameters) where T void ByName(string name, params Parameter[] parameters) where T : Entity { - var ed = ctx.Resolve().GetByName(name); + EntityDefault ed = ctx.Resolve().GetByName(name); ByDefinition(ed.Definition, parameters); } @@ -1074,10 +1081,10 @@ void ByName(string name, params Parameter[] parameters) where T : Entity void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] parameters) where T : Entity { //TODO: this might be expensive -- string matching all defaults - var matches = ctx.Resolve().GetAll() + IEnumerable matches = ctx.Resolve().GetAll() .Where(i => i.CategoryFlags == cf) .Where(i => i.Name.Contains(substr)); - foreach (var ed in matches) + foreach (EntityDefault ed in matches) { ByDefinition(ed.Definition, parameters); } @@ -1087,8 +1094,6 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByName(DefinitionNames.FIELD_CONTAINER); ByName(DefinitionNames.MISSION_CONTAINER); ByName(DefinitionNames.ICE); - //ByName(DefinitionNames.RESPEC_TOKEN); - ByCategoryFlags(CategoryFlags.cf_respec_token); ByCategoryFlags(CategoryFlags.cf_container_capsule); ByCategoryFlags(CategoryFlags.cf_npc); @@ -1110,6 +1115,12 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_projectile_ammo); ByCategoryFlags(CategoryFlags.cf_missile_ammo); ByCategoryFlags(CategoryFlags.cf_mining_ammo); + ByCategoryFlags(CategoryFlags.cf_sentry_turret_units); + ByCategoryFlags(CategoryFlags.cf_mining_turret_units); + ByCategoryFlags(CategoryFlags.cf_harvesting_turret_units); + ByCategoryFlags(CategoryFlags.cf_pelistal_combat_drones_units); + ByCategoryFlags(CategoryFlags.cf_nuimqol_combat_drones_units); + ByCategoryFlags(CategoryFlags.cf_thelodica_combat_drones_units); ByCategoryFlags(CategoryFlags.cf_mining_probe_ammo_tile); ByCategoryFlags(CategoryFlags.cf_mining_probe_ammo_one_tile); ByCategoryFlags(CategoryFlags.cf_mining_probe_ammo_artifact); @@ -1177,6 +1188,7 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_small_single_projectile, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_small_projectile_ammo)); ByCategoryFlags(CategoryFlags.cf_medium_single_projectile, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_medium_projectile_ammo)); ByCategoryFlags(CategoryFlags.cf_large_single_projectile, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_large_projectile_ammo)); + ByCategoryFlags(CategoryFlags.cf_sentry_turret_guns, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_large_projectile_ammo)); ByCategoryFlags(CategoryFlags.cf_small_missile_launchers, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_small_missile_ammo)); ByCategoryFlags(CategoryFlags.cf_medium_missile_launchers, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_medium_missile_ammo)); ByCategoryFlags(CategoryFlags.cf_large_missile_launchers, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_large_missile_ammo)); @@ -1189,6 +1201,8 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_energy_transferers); ByCategoryFlags(CategoryFlags.cf_energy_vampires); ByCategoryFlags(CategoryFlags.cf_drillers, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_mining_ammo)); + ByCategoryFlags(CategoryFlags.cf_industrial_turret_drillers); + ByCategoryFlags(CategoryFlags.cf_industrial_turret_harvesters); ByCategoryFlags(CategoryFlags.cf_harvesters, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_harvesting_ammo)); ByCategoryFlags(CategoryFlags.cf_mining_probes, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_mining_probe_ammo)); ByCategoryFlags(CategoryFlags.cf_chassis_scanner); @@ -1196,6 +1210,7 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_siege_hack_modules); ByCategoryFlags(CategoryFlags.cf_neuralyzer); ByCategoryFlags(CategoryFlags.cf_blob_emission_modulator, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_blob_emission_modulator_ammo)); + ByCategoryFlags(CategoryFlags.cf_remote_controllers, new NamedParameter("ammoCategoryFlags", CategoryFlags.cf_remote_controlled_units)); ByCategoryFlags(CategoryFlags.cf_webber); ByCategoryFlags(CategoryFlags.cf_sensor_dampeners); ByCategoryFlags(CategoryFlags.cf_remote_sensor_boosters); @@ -1204,6 +1219,7 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_armor_hardeners); ByCategoryFlags(CategoryFlags.cf_stealth_modules); ByCategoryFlags(CategoryFlags.cf_detection_modules); + ByCategoryFlags(CategoryFlags.cf_landmine_detectors); ByCategoryFlags(CategoryFlags.cf_armor_plates); ByCategoryFlags(CategoryFlags.cf_core_batteries); ByCategoryFlags(CategoryFlags.cf_core_rechargers); @@ -1240,6 +1256,10 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_robotshards); ByCategoryFlags(CategoryFlags.cf_others); ByCategoryFlags(CategoryFlags.cf_blob_emitter); + ByCategoryFlags(CategoryFlags.cf_sentry_turrets); + ByCategoryFlags(CategoryFlags.cf_mining_turrets); + ByCategoryFlags(CategoryFlags.cf_harvesting_turrets); + ByCategoryFlags(CategoryFlags.cf_combat_drones); ByCategoryFlags(CategoryFlags.cf_reactor_cores); ByCategoryFlags(CategoryFlags.cf_kiosk); ByCategoryFlags(CategoryFlags.cf_alarm_switch); @@ -1250,7 +1270,12 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByCategoryFlags(CategoryFlags.cf_mission_coin); ByCategoryFlags(CategoryFlags.cf_area_bomb); ByCategoryFlags(CategoryFlags.cf_plasma_bomb); - ByCategoryFlags(CategoryFlags.cf_visibility_based_probe); + + ByCategoryFlags(CategoryFlags.cf_proximity_probe); + ByCategoryFlags(CategoryFlags.cf_light_landmines); + ByCategoryFlags(CategoryFlags.cf_medium_landmines); + ByCategoryFlags(CategoryFlags.cf_heavy_landmines); + ByCategoryFlags(CategoryFlags.cf_random_research_kits); ByCategoryFlags(CategoryFlags.cf_lottery_items); ByCategoryFlags(CategoryFlags.cf_paints); // OPP Robot paint! @@ -1263,7 +1288,9 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] // OPP new Blinder module ByNamePatternAndFlag(DefinitionNames.STANDARD_BLINDER_MODULE, CategoryFlags.cf_target_painter); - ByCategoryFlags(CategoryFlags.cf_proximity_probe_deployer); + ByCategoryFlags(CategoryFlags.cf_proximity_probe_deployer); + ByCategoryFlags(CategoryFlags.cf_landmine_deployer); + ByCategoryFlags(CategoryFlags.cf_gift_packages); ByCategoryFlags(CategoryFlags.cf_pbs_capsules); ByCategoryFlags(CategoryFlags.cf_pbs_egg); @@ -1327,20 +1354,11 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] ByName(DefinitionNames.RELIC); //OPP Relic ByName(DefinitionNames.RELIC_SAP); //OPP outpost Relic - var c = b.Build(); + IContainer c = b.Build(); return ed => { - Entity entity; - if (!c.IsRegisteredWithKey(ed.Definition)) - { - entity = ctx.Resolve(); - } - else - { - entity = c.ResolveKeyed(ed.Definition); - } - + Entity entity = !c.IsRegisteredWithKey(ed.Definition) ? ctx.Resolve() : c.ResolveKeyed(ed.Definition); entity.ED = ed; entity.Health = ed.Health; entity.Quantity = ed.Quantity; @@ -1352,7 +1370,7 @@ void ByNamePatternAndFlag(string substr, CategoryFlags cf, params Parameter[] private void RegisterLoggers() { - _builder.Register(x => + _ = _builder.Register(x => { return new LoggerCache(new MemoryCache("LoggerCache")) { @@ -1360,76 +1378,79 @@ private void RegisterLoggers() }; }).As().SingleInstance(); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return name => { - var fileLogger = ctx.Resolve>>().Invoke("channels", name); + FileLogger fileLogger = ctx.Resolve>>().Invoke("channels", name); return new ChannelLogger(fileLogger); }; }); - _builder.RegisterGeneric(typeof(FileLogger<>)); + _ = _builder.RegisterGeneric(typeof(FileLogger<>)); - _builder.Register>>(x => + _ = _builder.Register>>(x => { - var ctx = x.Resolve(); - return ((directory, filename) => + IComponentContext ctx = x.Resolve(); + return (directory, filename) => { - var formatter = new ChatLogFormatter(); + ChatLogFormatter formatter = new ChatLogFormatter(); return ctx.Resolve.Factory>().Invoke(formatter, () => Path.Combine("chatlogs", directory, filename, DateTime.Now.ToString("yyyy-MM-dd"), $"{filename.RemoveSpecialCharacters()}.txt")); - }); + }; }); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return (directory, filename) => { - var fileLogger = ctx.Resolve>>().Invoke(directory, filename); + FileLogger fileLogger = ctx.Resolve>>().Invoke(directory, filename); return fileLogger; }; }); - _builder.Register(c => + _ = _builder.Register(c => { - var defaultFormater = new DefaultLogEventFormatter(); + DefaultLogEventFormatter defaultFormater = new DefaultLogEventFormatter(); - var formater = new DelegateLogEventFormatter(e => + DelegateLogEventFormatter formater = new DelegateLogEventFormatter(e => { - var formatedEvent = defaultFormater.Format(e); + string formatedEvent = defaultFormater.Format(e); - var gex = e.ThrownException as PerpetuumException; - if (gex == null) + if (!(e.ThrownException is PerpetuumException gex)) + { return formatedEvent; + } - var sb = new StringBuilder(formatedEvent); + StringBuilder sb = new StringBuilder(formatedEvent); - sb.AppendLine(); - sb.AppendLine(); - sb.AppendFormat("Error = {0}\n", gex.error); + _ = sb.AppendLine(); + _ = sb.AppendLine(); + _ = sb.AppendFormat("Error = {0}\n", gex.error); if (gex.Data.Count > 0) - sb.AppendFormat("Data: {0}", gex.Data.ToDictionary().ToDebugString()); + { + _ = sb.AppendFormat("Data: {0}", gex.Data.ToDictionary().ToDebugString()); + } return sb.ToString(); }); - var fileLogger = c.Resolve.Factory>().Invoke(formater, () => Path.Combine("logs", DateTime.Now.ToString("yyyy-MM-dd"), "hostlog.txt")); + FileLogger fileLogger = c.Resolve.Factory>().Invoke(formater, () => Path.Combine("logs", DateTime.Now.ToString("yyyy-MM-dd"), "hostlog.txt")); fileLogger.BufferSize = 100; fileLogger.AutoFlushInterval = TimeSpan.FromSeconds(10); return new CompositeLogger(fileLogger, new ColoredConsoleLogger(formater)); }).As>(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); - _builder.RegisterGeneric(typeof(DbLogger<>)); + _ = _builder.RegisterGeneric(typeof(DbLogger<>)); } @@ -1441,7 +1462,7 @@ private IRegistrationBuilder(PresenceType presenceType) where T : Flock { - _builder.RegisterType().Keyed(presenceType).OnActivated(e => + _ = _builder.RegisterType().Keyed(presenceType).OnActivated(e => { e.Instance.EntityService = e.Context.Resolve(); e.Instance.LootService = e.Context.Resolve(); @@ -1450,66 +1471,66 @@ private void RegisterFlock(PresenceType presenceType) where T : Flock public void RegisterNpcs() { - _builder.RegisterType().As(); - _builder.RegisterType().SingleInstance(); - _builder.RegisterType().SingleInstance().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType().SingleInstance().As(); - _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType().Named>("directFlockIDGenerator").SingleInstance().WithParameter("startID", 25000); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().Named>("directFlockIDGenerator").SingleInstance().WithParameter("startID", 25000); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().OnActivated(e => { e.Instance.LoadAllConfig(); }).As().SingleInstance(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType() + _ = _builder.RegisterType() .As() .SingleInstance() .OnActivated(e => e.Instance.Init()); - _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType() + _ = _builder.RegisterType() .As() .SingleInstance() .OnActivated(e => e.Instance.Init()); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().OnActivated(e => { - var pm = e.Context.Resolve(); + IProcessManager pm = e.Context.Resolve(); pm.AddProcess(e.Instance.AsTimed(TimeSpan.FromSeconds(2)).ToAsync()); e.Instance.LoadAll(); }).As(); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { - var presenceFactory = ctx.Resolve(); - var presenceService = ctx.Resolve().Invoke(zone, presenceFactory); + PresenceFactory presenceFactory = ctx.Resolve(); + IPresenceManager presenceService = ctx.Resolve().Invoke(zone, presenceFactory); return presenceService; }; }); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); - return ((configuration, presence) => + return (configuration, presence) => { return ctx.ResolveKeyed(presence.Configuration.PresenceType, TypedParameter.From(configuration), TypedParameter.From(presence)); - }); + }; }); RegisterFlock(PresenceType.Normal); @@ -1526,32 +1547,34 @@ public void RegisterNpcs() RegisterFlock(PresenceType.EscalatingRandomPresence); RegisterFlock(PresenceType.GrowingNPCBasePresence); - RegisterPresence(PresenceType.Normal); - RegisterPresence(PresenceType.Direct).OnActivated(e => + _ = RegisterPresence(PresenceType.Normal); + _ = RegisterPresence(PresenceType.Direct).OnActivated(e => { e.Instance.FlockIDGenerator = e.Context.ResolveNamed>("directFlockIDGenerator"); }); - RegisterPresence(PresenceType.DynamicPool); - RegisterPresence(PresenceType.Dynamic); - RegisterPresence(PresenceType.DynamicExtended); - RegisterPresence(PresenceType.ExpiringRandom); - RegisterPresence(PresenceType.Random); - RegisterPresence(PresenceType.Roaming); - RegisterPresence(PresenceType.FreeRoaming); - RegisterPresence(PresenceType.Interzone); - RegisterPresence(PresenceType.InterzoneRoaming); - RegisterPresence(PresenceType.EscalatingRandomPresence); - RegisterPresence(PresenceType.GrowingNPCBasePresence); - - _builder.Register(x => - { - var ctx = x.Resolve(); - return ((zone, configuration) => + _ = RegisterPresence(PresenceType.DynamicPool); + _ = RegisterPresence(PresenceType.Dynamic); + _ = RegisterPresence(PresenceType.DynamicExtended); + _ = RegisterPresence(PresenceType.ExpiringRandom); + _ = RegisterPresence(PresenceType.Random); + _ = RegisterPresence(PresenceType.Roaming); + _ = RegisterPresence(PresenceType.FreeRoaming); + _ = RegisterPresence(PresenceType.Interzone); + _ = RegisterPresence(PresenceType.InterzoneRoaming); + _ = RegisterPresence(PresenceType.EscalatingRandomPresence); + _ = RegisterPresence(PresenceType.GrowingNPCBasePresence); + + _ = _builder.Register(x => + { + IComponentContext ctx = x.Resolve(); + return (zone, configuration) => { if (!ctx.IsRegisteredWithKey(configuration.PresenceType)) + { return null; + } - var p = ctx.ResolveKeyed(configuration.PresenceType, TypedParameter.From(zone), TypedParameter.From(configuration)); + Presence p = ctx.ResolveKeyed(configuration.PresenceType, TypedParameter.From(zone), TypedParameter.From(configuration)); if (p is IRoamingPresence roamingPresence) { @@ -1567,7 +1590,7 @@ public void RegisterNpcs() } return p; - }); + }; }); @@ -1575,151 +1598,151 @@ public void RegisterNpcs() private void RegisterMtProducts() { - _builder.RegisterType().As(); - _builder.RegisterType(); - RegisterRequestHandler(Commands.MtProductPriceList); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = RegisterRequestHandler(Commands.MtProductPriceList); } private void RegisterMissions() { - _builder.RegisterType(); - _builder.RegisterType().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().OnActivated(e => - { - var pm = e.Context.Resolve(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().OnActivated(e => + { + IProcessManager pm = e.Context.Resolve(); pm.AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(1))); }).SingleInstance(); - RegisterRequestHandler(Commands.MissionData); - RegisterRequestHandler(Commands.MissionStart); - RegisterRequestHandler(Commands.MissionAbort); - RegisterRequestHandler(Commands.MissionAdminListAll); - RegisterRequestHandler(Commands.MissionAdminTake); - RegisterRequestHandler(Commands.MissionLogList); - RegisterRequestHandler(Commands.MissionListRunning); - RegisterRequestHandler(Commands.MissionReloadCache); - RegisterRequestHandler(Commands.MissionGetOptions); - RegisterRequestHandler(Commands.MissionResolveTest); - RegisterRequestHandler(Commands.MissionDeliver); - RegisterRequestHandler(Commands.MissionFlush); - RegisterRequestHandler(Commands.MissionReset); - RegisterRequestHandler(Commands.MissionListAgents); - - _builder.RegisterType(); - _builder.RegisterType(); + _ = RegisterRequestHandler(Commands.MissionData); + _ = RegisterRequestHandler(Commands.MissionStart); + _ = RegisterRequestHandler(Commands.MissionAbort); + _ = RegisterRequestHandler(Commands.MissionAdminListAll); + _ = RegisterRequestHandler(Commands.MissionAdminTake); + _ = RegisterRequestHandler(Commands.MissionLogList); + _ = RegisterRequestHandler(Commands.MissionListRunning); + _ = RegisterRequestHandler(Commands.MissionReloadCache); + _ = RegisterRequestHandler(Commands.MissionGetOptions); + _ = RegisterRequestHandler(Commands.MissionResolveTest); + _ = RegisterRequestHandler(Commands.MissionDeliver); + _ = RegisterRequestHandler(Commands.MissionFlush); + _ = RegisterRequestHandler(Commands.MissionReset); + _ = RegisterRequestHandler(Commands.MissionListAgents); + + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); } private void InitRelayManager() { - _builder.RegisterType().SingleInstance(); - _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.Register(c => new MarketInfoService(0.3, 10, false)).As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.Register(c => new MarketInfoService(0.3, 10, false)).As(); - _builder.RegisterType().As().OnActivated(e => + _ = _builder.RegisterType().As().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromHours(4))); }); - _builder.RegisterType().As().SingleInstance().OnActivated(e => + _ = _builder.RegisterType().As().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(2))); }); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType().As().SingleInstance().OnActivated(e => + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(1))); }); - _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().OnActivated(e => { e.Instance.Init(); }).As().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().SingleInstance().OnActivated(e => + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().SingleInstance().OnActivated(e => { e.Instance.InitProcessor(); }); - _builder.RegisterType().SingleInstance().OnActivated(e => + _ = _builder.RegisterType().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(1))); }); - _builder.RegisterType().As().SingleInstance().OnActivated(e => + _ = _builder.RegisterType().As().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(5))); }); - _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType(); + _ = _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType(); - _builder.RegisterType().SingleInstance().As(); + _ = _builder.RegisterType().SingleInstance().As(); - _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType().SingleInstance(); - _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().OnActivated(e => { - var pm = e.Context.Resolve(); + IProcessManager pm = e.Context.Resolve(); pm.AddProcess(e.Instance.AsTimed(TimeSpan.FromMilliseconds(200)).ToAsync()); }); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType().As(); - _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); // OPP: EPBonusEventService singleton - _builder.RegisterType().SingleInstance().OnActivated(e => + _ = _builder.RegisterType().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromMinutes(1))); }); // OPP: EventListenerService and consumers - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().As>(); - _builder.RegisterType().As>(); - _builder.RegisterType().SingleInstance().OnActivated(e => + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As>(); + _ = _builder.RegisterType().As>(); + _ = _builder.RegisterType().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(0.75))); e.Instance.AttachListener(e.Context.Resolve()); @@ -1727,41 +1750,41 @@ private void InitRelayManager() e.Instance.AttachListener(e.Context.Resolve()); e.Instance.AttachListener(e.Context.Resolve()); e.Instance.AttachListener(e.Context.Resolve()); - var obs = new GameTimeObserver(e.Instance); + GameTimeObserver obs = new GameTimeObserver(e.Instance); obs.Subscribe(e.Context.Resolve()); }); - _builder.RegisterType().As().SingleInstance().OnActivated(e => + _ = _builder.RegisterType().As().SingleInstance().OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromMinutes(1.5))); }); // OPP: InterzoneNPCManager - RegisterAutoActivate(TimeSpan.FromSeconds(10)); + _ = RegisterAutoActivate(TimeSpan.FromSeconds(10)); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType().AsSelf().As(); - _builder.Register(x => + _ = _builder.RegisterType(); + _ = _builder.RegisterType().AsSelf().As(); + _ = _builder.Register(x => { - var ctx = x.Resolve(); - return ((account, type) => + IComponentContext ctx = x.Resolve(); + return (account, type) => { return ctx.Resolve(new TypedParameter(typeof(Account), account), new TypedParameter(typeof(AccountTransactionType), type)); - }); + }; }); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); } private IRegistrationBuilder RegisterRequestHandler(Command command) where TRequestHandler : IRequestHandler where TRequest : IRequest { - var res = _builder.RegisterType(); + IRegistrationBuilder res = _builder.RegisterType(); - _builder.Register(c => + _ = _builder.Register(c => { return c.Resolve>(new TypedParameter(typeof(IRequestHandler), c.Resolve())); }).Keyed>(command); @@ -1776,548 +1799,550 @@ private IRegistrationBuilder() where T : IRequest { - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); - return (command => + IComponentContext ctx = x.Resolve(); + return command => { return ctx.IsRegisteredWithKey>(command) ? ctx.ResolveKeyed>(command) : null; - }); + }; }); } private void RegisterRequestHandlers() { - _builder.RegisterGeneric(typeof(RequestHandlerProfiler<>)); + _ = _builder.RegisterGeneric(typeof(RequestHandlerProfiler<>)); RegisterRequestHandlerFactory(); RegisterRequestHandlerFactory(); - RegisterRequestHandler(Commands.GetEnums); - RegisterRequestHandler(Commands.GetCommands); - RegisterRequestHandler(Commands.GetEntityDefaults).SingleInstance(); - RegisterRequestHandler(Commands.GetAggregateFields).SingleInstance(); - RegisterRequestHandler(Commands.GetDefinitionConfigUnits).SingleInstance(); - RegisterRequestHandler(Commands.GetEffects).SingleInstance(); - RegisterRequestHandler(Commands.GetDistances); - RegisterRequestHandler(Commands.SignIn); - RegisterRequestHandler(Commands.SignInSteam); - RegisterRequestHandler(Commands.SignOut); - RegisterRequestHandler(Commands.SteamListAccounts); - RegisterRequestHandler(Commands.AccountConfirmEmail); - RegisterRequestHandler(Commands.CharacterList); - RegisterRequestHandler(Commands.CharacterCreate); - RegisterRequestHandler(Commands.CharacterSelect); - RegisterRequestHandler(Commands.CharacterDeselect); - RegisterRequestHandler(Commands.CharacterForceDeselect); - RegisterRequestHandler(Commands.CharacterForceDisconnect); - RegisterRequestHandler(Commands.CharacterDelete); - RegisterRequestHandler(Commands.CharacterSetHomeBase); - RegisterRequestHandler(Commands.CharacterGetProfiles); - RegisterRequestHandler(Commands.CharacterRename); - RegisterRequestHandler(Commands.CharacterCheckNick); - RegisterRequestHandler(Commands.CharacterCorrectNick); - RegisterRequestHandler(Commands.IsOnline); - RegisterRequestHandler(Commands.CharacterSettingsSet); - RegisterRequestHandler(Commands.CharacterSetMoodMessage); - RegisterRequestHandler(Commands.CharacterTransferCredit); - RegisterRequestHandler(Commands.CharacterSetAvatar); - RegisterRequestHandler(Commands.CharacterSetBlockTrades); - RegisterRequestHandler(Commands.CharacterSetCredit); - RegisterRequestHandler(Commands.CharacterClearHomeBase); - RegisterRequestHandler(Commands.CharacterSettingsGet); - RegisterRequestHandler(Commands.CharacterGetMyProfile); - RegisterRequestHandler(Commands.CharacterSearch); - RegisterRequestHandler(Commands.CharacterRemoveFromCache); - RegisterRequestHandler(Commands.CharacterListNpcDeath); - RegisterRequestHandler(Commands.CharacterTransactionHistory); - RegisterRequestHandler(Commands.CharacterGetZoneInfo); - RegisterRequestHandler(Commands.CharacterNickHistory); - RegisterRequestHandler(Commands.CharacterGetNote); - RegisterRequestHandler(Commands.CharacterSetNote); - RegisterRequestHandler(Commands.CharacterCorporationHistory); - RegisterRequestHandler(Commands.CharacterWizardData).SingleInstance(); - RegisterRequestHandler(Commands.GetCharactersOnline); - RegisterRequestHandler(Commands.ReimburseItem); - RegisterRequestHandler(Commands.Chat); - RegisterRequestHandler(Commands.GoodiePackList); - RegisterRequestHandler(Commands.GoodiePackRedeem); - RegisterRequestHandler(Commands.Ping); - RegisterRequestHandler(Commands.Quit); - RegisterRequestHandler(Commands.SetMaxUserCount); - RegisterRequestHandler(Commands.SparkTeleportSet); - RegisterRequestHandler(Commands.SparkTeleportUse); - RegisterRequestHandler(Commands.SparkTeleportDelete); - RegisterRequestHandler(Commands.SparkTeleportList); - RegisterRequestHandler(Commands.SparkChange); - RegisterRequestHandler(Commands.SparkRemove); - RegisterRequestHandler(Commands.SparkList); - RegisterRequestHandler(Commands.SparkSetDefault); - RegisterRequestHandler(Commands.SparkUnlock); - RegisterRequestHandler(Commands.Undock); - RegisterRequestHandler(Commands.ProximityProbeRegisterSet); - RegisterRequestHandler(Commands.ProximityProbeSetName); - RegisterRequestHandler(Commands.ProximityProbeList); - RegisterRequestHandler(Commands.ProximityProbeGetRegistrationInfo); - RegisterRequestHandler(Commands.IntrusionEnabler); - RegisterRequestHandler(Commands.AccountGetTransactionHistory); - RegisterRequestHandler(Commands.AccountList); - - RegisterRequestHandler(Commands.AccountEpForActivityHistory); - RegisterRequestHandler(Commands.RedeemableItemList); - RegisterRequestHandler(Commands.RedeemableItemRedeem); - RegisterRequestHandler(Commands.RedeemableItemActivate); - RegisterRequestHandler(Commands.CreateItem); - RegisterRequestHandler(Commands.TeleportList); - RegisterRequestHandler(Commands.TeleportConnectColumns); - RegisterRequestHandler(Commands.EnableSelfTeleport); - RegisterRequestHandler(Commands.ItemCount); - RegisterRequestHandler(Commands.SystemInfo); - RegisterRequestHandler(Commands.TransferData); - - RegisterRequestHandler(Commands.BaseReown); - RegisterRequestHandler(Commands.BaseSetDockingRights); - RegisterRequestHandler(Commands.BaseSelect); - RegisterRequestHandler(Commands.BaseGetInfo); - RegisterRequestHandler(Commands.BaseGetMyItems); - RegisterRequestHandler(Commands.BaseListFacilities).SingleInstance(); - - RegisterRequestHandler(Commands.GetZoneInfo); - RegisterRequestHandler(Commands.ItemCountOnZone); - - - RegisterRequestHandler(Commands.CorporationCreate); - RegisterRequestHandler(Commands.CorporationRemoveMember); - RegisterRequestHandler(Commands.CorporationGetMyInfo); - RegisterRequestHandler(Commands.CorporationSetMemberRole); - RegisterRequestHandler(Commands.CorporationCharacterInvite); - RegisterRequestHandler(Commands.CorporationInviteReply); - RegisterRequestHandler(Commands.CorporationInfo); - RegisterRequestHandler(Commands.CorporationLeave); - RegisterRequestHandler(Commands.CorporationSearch); - RegisterRequestHandler(Commands.CorporationSetInfo); - RegisterRequestHandler(Commands.CorporationDropRoles); - RegisterRequestHandler(Commands.CorporationCancelLeave); - RegisterRequestHandler(Commands.CorporationPayOut); - RegisterRequestHandler(Commands.CorporationForceInfo); - RegisterRequestHandler(Commands.CorporationGetDelegates); - RegisterRequestHandler(Commands.CorporationTransfer); - RegisterRequestHandler(Commands.CorporationHangarListAll); - RegisterRequestHandler(Commands.CorporationHangarListOnBase); - RegisterRequestHandler(Commands.CorporationRentHangar); - RegisterRequestHandler(Commands.CorporationHangarPayRent); - RegisterRequestHandler(Commands.CorporationHangarLogSet); - RegisterRequestHandler(Commands.CorporationHangarLogClear); - RegisterRequestHandler(Commands.CorporationHangarLogList); - RegisterRequestHandler(Commands.CorporationHangarSetAccess); - RegisterRequestHandler(Commands.CorporationHangarClose); - RegisterRequestHandler(Commands.CorporationHangarSetName); - RegisterRequestHandler(Commands.CorporationHangarRentPrice); - RegisterRequestHandler(Commands.CorporationHangarFolderSectionCreate); - RegisterRequestHandler(Commands.CorporationHangarFolderSectionDelete); - RegisterRequestHandler(Commands.CorporationVoteStart); - RegisterRequestHandler(Commands.CorporationVoteList); - RegisterRequestHandler(Commands.CorporationVoteDelete); - RegisterRequestHandler(Commands.CorporationVoteCast); - RegisterRequestHandler(Commands.CorporationVoteSetTopic); - RegisterRequestHandler(Commands.CorporationBulletinStart); - RegisterRequestHandler(Commands.CorporationBulletinEntry); - RegisterRequestHandler(Commands.CorporationBulletinDelete); - RegisterRequestHandler(Commands.CorporationBulletinList); - RegisterRequestHandler(Commands.CorporationBulletinDetails); - RegisterRequestHandler(Commands.CorporationBulletinEntryDelete); - RegisterRequestHandler(Commands.CorporationBulletinNewEntries); - RegisterRequestHandler(Commands.CorporationBulletinModerate); - RegisterRequestHandler(Commands.CorporationCeoTakeOverStatus); - RegisterRequestHandler(Commands.CorporationVolunteerForCeo); - RegisterRequestHandler(Commands.CorporationRename); - RegisterRequestHandler(Commands.CorporationDonate); - RegisterRequestHandler(Commands.CorporationTransactionHistory); - RegisterRequestHandler(Commands.CorporationApply); - RegisterRequestHandler(Commands.CorporationDeleteMyApplication); - RegisterRequestHandler(Commands.CorporationAcceptApplication); - RegisterRequestHandler(Commands.CorporationDeleteApplication); - RegisterRequestHandler(Commands.CorporationListMyApplications); - RegisterRequestHandler(Commands.CorporationListApplications); - RegisterRequestHandler(Commands.CorporationLogHistory); - RegisterRequestHandler(Commands.CorporationNameHistory); - RegisterRequestHandler(Commands.CorporationSetColor); - RegisterRequestHandler(Commands.CorporationDocumentConfig).SingleInstance(); - RegisterRequestHandler(Commands.CorporationDocumentTransfer); - RegisterRequestHandler(Commands.CorporationDocumentList); - RegisterRequestHandler(Commands.CorporationDocumentCreate); - RegisterRequestHandler(Commands.CorporationDocumentDelete); - RegisterRequestHandler(Commands.CorporationDocumentOpen); - RegisterRequestHandler(Commands.CorporationDocumentUpdateBody); - RegisterRequestHandler(Commands.CorporationDocumentMonitor); - RegisterRequestHandler(Commands.CorporationDocumentUnmonitor); - RegisterRequestHandler(Commands.CorporationDocumentRent); - RegisterRequestHandler(Commands.CorporationDocumentRegisterList); - RegisterRequestHandler(Commands.CorporationDocumentRegisterSet); - RegisterRequestHandler(Commands.CorporationInfoFlushCache); - RegisterRequestHandler(Commands.CorporationGetReputation); - RegisterRequestHandler(Commands.CorporationMyStandings); - RegisterRequestHandler(Commands.CorporationSetMembersNeutral); - RegisterRequestHandler(Commands.CorporationRoleHistory); - RegisterRequestHandler(Commands.CorporationMemberRoleHistory); - - - - - RegisterRequestHandler(Commands.YellowPagesSearch); - RegisterRequestHandler(Commands.YellowPagesSubmit); - RegisterRequestHandler(Commands.YellowPagesGet); - RegisterRequestHandler(Commands.YellowPagesDelete); - - - RegisterRequestHandler(Commands.AllianceGetDefaults).SingleInstance(); - RegisterRequestHandler(Commands.AllianceGetMyInfo); - RegisterRequestHandler(Commands.AllianceRoleHistory); - - RegisterRequestHandler(Commands.ExtensionTest); - RegisterRequestHandler(Commands.ExtensionGetAll).SingleInstance(); - RegisterRequestHandler(Commands.ExtensionPrerequireList).SingleInstance(); - RegisterRequestHandler(Commands.ExtensionCategoryList).SingleInstance(); - RegisterRequestHandler(Commands.ExtensionLearntList); - RegisterRequestHandler(Commands.ExtensionGetAvailablePoints); - RegisterRequestHandler(Commands.ExtensionGetPointParameters); - RegisterRequestHandler(Commands.ExtensionHistory); - RegisterRequestHandler(Commands.ExtensionBuyForPoints); - RegisterRequestHandler(Commands.ExtensionRemoveLevel); - RegisterRequestHandler(Commands.ExtensionBuyEpBoost); - RegisterRequestHandler(Commands.ExtensionResetCharacter); - RegisterRequestHandler(Commands.ExtensionFreeLockedEp); - RegisterRequestHandler(Commands.ExtensionFreeAllLockedEpCommand); // For GameAdmin Channel Command - RegisterRequestHandler(Commands.ExtensionGive); - RegisterRequestHandler(Commands.ExtensionReset); - RegisterRequestHandler(Commands.ExtensionRevert); - - RegisterRequestHandler(Commands.ItemShopBuy); - RegisterRequestHandler(Commands.ItemShopList); - RegisterRequestHandler(Commands.GiftOpen); - RegisterRequestHandler(Commands.GetHighScores); - RegisterRequestHandler(Commands.GetMyHighScores); - RegisterRequestHandler(Commands.ZoneSectorList).SingleInstance(); - - RegisterRequestHandler(Commands.ListContainer); - - RegisterRequestHandler(Commands.SocialGetMyList); - RegisterRequestHandler(Commands.SocialFriendRequest); - RegisterRequestHandler(Commands.SocialConfirmPendingFriendRequest); - RegisterRequestHandler(Commands.SocialDeleteFriend); - RegisterRequestHandler(Commands.SocialBlockFriend); - - RegisterRequestHandler(Commands.PBSGetReimburseInfo); - RegisterRequestHandler(Commands.PBSSetReimburseInfo); - RegisterRequestHandler(Commands.PBSGetLog); - - RegisterRequestHandler(Commands.MineralScanResultList); - RegisterRequestHandler(Commands.MineralScanResultMove); - RegisterRequestHandler(Commands.MineralScanResultDelete); - RegisterRequestHandler(Commands.MineralScanResultCreateItem); - RegisterRequestHandler(Commands.MineralScanResultUploadFromItem); - - RegisterRequestHandler(Commands.FreshNewsCount); - RegisterRequestHandler(Commands.GetNews); - RegisterRequestHandler(Commands.AddNews); - RegisterRequestHandler(Commands.UpdateNews); - RegisterRequestHandler(Commands.NewsCategory).SingleInstance(); - - RegisterRequestHandler(Commands.EpForActivityDailyLog); - RegisterRequestHandler(Commands.GetMyKillReports); - RegisterRequestHandler(Commands.UseLotteryItem); - RegisterRequestHandler(Commands.ContainerMover); - - - RegisterRequestHandler(Commands.MarketTaxChange); - RegisterRequestHandler(Commands.MarketTaxLogList); - RegisterRequestHandler(Commands.MarketGetInfo); - RegisterRequestHandler(Commands.MarketAddCategory); - RegisterRequestHandler(Commands.MarketItemList); - RegisterRequestHandler(Commands.MarketGetMyItems); - RegisterRequestHandler(Commands.MarketGetAveragePrices); - RegisterRequestHandler(Commands.MarketCreateBuyOrder); - RegisterRequestHandler(Commands.MarketCreateSellOrder); - RegisterRequestHandler(Commands.MarketBuyItem); - RegisterRequestHandler(Commands.MarketCancelItem); - RegisterRequestHandler(Commands.MarketGetState); - RegisterRequestHandler(Commands.MarketSetState); - RegisterRequestHandler(Commands.MarketFlush); - RegisterRequestHandler(Commands.MarketGetDefinitionAveragePrice); - RegisterRequestHandler(Commands.MarketAvailableItems); - RegisterRequestHandler(Commands.MarketItemsInRange); - RegisterRequestHandler(Commands.MarketInsertStats); - RegisterRequestHandler(Commands.MarketListFacilities); - RegisterRequestHandler(Commands.MarketInsertAverageForCF); - RegisterRequestHandler(Commands.MarketGlobalAveragePrices); - RegisterRequestHandler(Commands.MarketModifyOrder); - RegisterRequestHandler(Commands.MarketCreateGammaPlasmaOrders); - RegisterRequestHandler(Commands.MarketRemoveItems); - RegisterRequestHandler(Commands.MarketCleanUp); - - - - RegisterRequestHandler(Commands.TradeBegin); - RegisterRequestHandler(Commands.TradeCancel); - RegisterRequestHandler(Commands.TradeSetOffer); - RegisterRequestHandler(Commands.TradeAccept); - RegisterRequestHandler(Commands.TradeRetractOffer); - - - RegisterRequestHandler(Commands.GetRobotInfo).OnActivated(e => e.Instance.ForFitting = false); - RegisterRequestHandler(Commands.GetRobotFittingInfo); - RegisterRequestHandler(Commands.SelectActiveRobot); - RegisterRequestHandler(Commands.RequestStarterRobot); - RegisterRequestHandler(Commands.RobotEmpty); - RegisterRequestHandler(Commands.SetRobotTint); - - RegisterRequestHandler(Commands.FittingPresetList); - RegisterRequestHandler(Commands.FittingPresetSave); - RegisterRequestHandler(Commands.FittingPresetDelete); - RegisterRequestHandler(Commands.FittingPresetApply); - - RegisterRequestHandler(Commands.RobotTemplateAdd); - RegisterRequestHandler(Commands.RobotTemplateUpdate); - RegisterRequestHandler(Commands.RobotTemplateDelete); - RegisterRequestHandler(Commands.RobotTemplateList); - RegisterRequestHandler(Commands.RobotTemplateBuild); - - RegisterRequestHandler(Commands.EquipModule); - RegisterRequestHandler(Commands.ChangeModule); - RegisterRequestHandler(Commands.RemoveModule); - RegisterRequestHandler(Commands.EquipAmmo); - RegisterRequestHandler(Commands.ChangeAmmo); - RegisterRequestHandler(Commands.UnequipAmmo); - RegisterRequestHandler(Commands.PackItems); - RegisterRequestHandler(Commands.UnpackItems); - RegisterRequestHandler(Commands.TrashItems); - RegisterRequestHandler(Commands.RelocateItems); - RegisterRequestHandler(Commands.StackSelection); - RegisterRequestHandler(Commands.UnstackAmount); - RegisterRequestHandler(Commands.SetItemName); - RegisterRequestHandler(Commands.StackTo); - RegisterRequestHandler(Commands.ServerMessage); - RegisterRequestHandler(Commands.RequestInfiniteBox); - RegisterRequestHandler(Commands.DecorCategoryList); - RegisterRequestHandler(Commands.PollGet); - RegisterRequestHandler(Commands.PollAnswer); - RegisterRequestHandler(Commands.ForceDock); - RegisterRequestHandler(Commands.ForceDockAdmin); - RegisterRequestHandler(Commands.GetItemSummary); - - RegisterRequestHandler(Commands.ProductionHistory); - RegisterRequestHandler(Commands.GetResearchLevels).SingleInstance(); - RegisterRequestHandler(Commands.ProductionComponentsList); - RegisterRequestHandler(Commands.ProductionRefine); - RegisterRequestHandler(Commands.ProductionRefineQuery); - RegisterRequestHandler(Commands.ProductionCPRGInfo); - RegisterRequestHandler(Commands.ProductionCPRGForge); - RegisterRequestHandler(Commands.ProductionCPRGForgeQuery); - RegisterRequestHandler(Commands.ProductionGetCprgFromLine); - RegisterRequestHandler(Commands.ProductionGetCprgFromLineQuery); - RegisterRequestHandler(Commands.ProductionLineSetRounds); - RegisterRequestHandler(Commands.ProductionPrototypeStart); - RegisterRequestHandler(Commands.ProductionPrototypeQuery); - RegisterRequestHandler(Commands.ProductionInsuranceQuery); - RegisterRequestHandler(Commands.ProductionInsuranceList); - RegisterRequestHandler(Commands.ProductionInsuranceBuy); - RegisterRequestHandler(Commands.ProductionInsuranceDelete); - RegisterRequestHandler(Commands.ProductionMergeResearchKitsMulti); - RegisterRequestHandler(Commands.ProductionMergeResearchKitsMultiQuery); - RegisterRequestHandler(Commands.ProductionQueryLineNextRound); - RegisterRequestHandler(Commands.ProductionReprocess); - RegisterRequestHandler(Commands.ProductionReprocessQuery); - RegisterRequestHandler(Commands.ProductionRepair); - RegisterRequestHandler(Commands.ProductionRepairQuery); - RegisterRequestHandler(Commands.ProductionResearch); - RegisterRequestHandler(Commands.ProductionResearchQuery); - RegisterRequestHandler(Commands.ProductionInProgress); - RegisterRequestHandler(Commands.ProductionCancel); - RegisterRequestHandler(Commands.ProductionFacilityInfo); - RegisterRequestHandler(Commands.ProductionLineList); - RegisterRequestHandler(Commands.ProductionLineCalibrate); - RegisterRequestHandler(Commands.ProductionLineDelete); - RegisterRequestHandler(Commands.ProductionLineStart); - RegisterRequestHandler(Commands.ProductionFacilityDescription); - RegisterRequestHandler(Commands.ProductionInProgressCorporation); + _ = RegisterRequestHandler(Commands.GetEnums); + _ = RegisterRequestHandler(Commands.GetCommands); + _ = RegisterRequestHandler(Commands.GetEntityDefaults).SingleInstance(); + _ = RegisterRequestHandler(Commands.GetAggregateFields).SingleInstance(); + _ = RegisterRequestHandler(Commands.GetDefinitionConfigUnits).SingleInstance(); + _ = RegisterRequestHandler(Commands.GetEffects).SingleInstance(); + _ = RegisterRequestHandler(Commands.GetDistances); + _ = RegisterRequestHandler(Commands.SignIn); + _ = RegisterRequestHandler(Commands.SignInSteam); + _ = RegisterRequestHandler(Commands.SignOut); + _ = RegisterRequestHandler(Commands.SteamListAccounts); + _ = RegisterRequestHandler(Commands.AccountConfirmEmail); + _ = RegisterRequestHandler(Commands.CharacterList); + _ = RegisterRequestHandler(Commands.CharacterCreate); + _ = RegisterRequestHandler(Commands.CharacterSelect); + _ = RegisterRequestHandler(Commands.CharacterDeselect); + _ = RegisterRequestHandler(Commands.CharacterForceDeselect); + _ = RegisterRequestHandler(Commands.CharacterForceDisconnect); + _ = RegisterRequestHandler(Commands.CharacterDelete); + _ = RegisterRequestHandler(Commands.CharacterSetHomeBase); + _ = RegisterRequestHandler(Commands.CharacterGetProfiles); + _ = RegisterRequestHandler(Commands.CharacterRename); + _ = RegisterRequestHandler(Commands.CharacterCheckNick); + _ = RegisterRequestHandler(Commands.CharacterCorrectNick); + _ = RegisterRequestHandler(Commands.IsOnline); + _ = RegisterRequestHandler(Commands.CharacterSettingsSet); + _ = RegisterRequestHandler(Commands.CharacterSetMoodMessage); + _ = RegisterRequestHandler(Commands.CharacterTransferCredit); + _ = RegisterRequestHandler(Commands.CharacterSetAvatar); + _ = RegisterRequestHandler(Commands.CharacterSetBlockTrades); + _ = RegisterRequestHandler(Commands.CharacterSetCredit); + _ = RegisterRequestHandler(Commands.CharacterClearHomeBase); + _ = RegisterRequestHandler(Commands.CharacterSettingsGet); + _ = RegisterRequestHandler(Commands.CharacterGetMyProfile); + _ = RegisterRequestHandler(Commands.CharacterSearch); + _ = RegisterRequestHandler(Commands.CharacterRemoveFromCache); + _ = RegisterRequestHandler(Commands.CharacterListNpcDeath); + _ = RegisterRequestHandler(Commands.CharacterTransactionHistory); + _ = RegisterRequestHandler(Commands.CharacterGetZoneInfo); + _ = RegisterRequestHandler(Commands.CharacterNickHistory); + _ = RegisterRequestHandler(Commands.CharacterGetNote); + _ = RegisterRequestHandler(Commands.CharacterSetNote); + _ = RegisterRequestHandler(Commands.CharacterCorporationHistory); + _ = RegisterRequestHandler(Commands.CharacterWizardData).SingleInstance(); + _ = RegisterRequestHandler(Commands.GetCharactersOnline); + _ = RegisterRequestHandler(Commands.ReimburseItem); + _ = RegisterRequestHandler(Commands.Chat); + _ = RegisterRequestHandler(Commands.GoodiePackList); + _ = RegisterRequestHandler(Commands.GoodiePackRedeem); + _ = RegisterRequestHandler(Commands.Ping); + _ = RegisterRequestHandler(Commands.Quit); + _ = RegisterRequestHandler(Commands.SetMaxUserCount); + _ = RegisterRequestHandler(Commands.SparkTeleportSet); + _ = RegisterRequestHandler(Commands.SparkTeleportUse); + _ = RegisterRequestHandler(Commands.SparkTeleportDelete); + _ = RegisterRequestHandler(Commands.SparkTeleportList); + _ = RegisterRequestHandler(Commands.SparkChange); + _ = RegisterRequestHandler(Commands.SparkRemove); + _ = RegisterRequestHandler(Commands.SparkList); + _ = RegisterRequestHandler(Commands.SparkSetDefault); + _ = RegisterRequestHandler(Commands.SparkUnlock); + _ = RegisterRequestHandler(Commands.Undock) + ; + _ = RegisterRequestHandler(Commands.ProximityProbeRegisterSet); + _ = RegisterRequestHandler(Commands.ProximityProbeSetName); + _ = RegisterRequestHandler(Commands.ProximityProbeList); + _ = RegisterRequestHandler(Commands.ProximityProbeGetRegistrationInfo); + + _ = RegisterRequestHandler(Commands.IntrusionEnabler); + _ = RegisterRequestHandler(Commands.AccountGetTransactionHistory); + _ = RegisterRequestHandler(Commands.AccountList); + + _ = RegisterRequestHandler(Commands.AccountEpForActivityHistory); + _ = RegisterRequestHandler(Commands.RedeemableItemList); + _ = RegisterRequestHandler(Commands.RedeemableItemRedeem); + _ = RegisterRequestHandler(Commands.RedeemableItemActivate); + _ = RegisterRequestHandler(Commands.CreateItem); + _ = RegisterRequestHandler(Commands.TeleportList); + _ = RegisterRequestHandler(Commands.TeleportConnectColumns); + _ = RegisterRequestHandler(Commands.EnableSelfTeleport); + _ = RegisterRequestHandler(Commands.ItemCount); + _ = RegisterRequestHandler(Commands.SystemInfo); + _ = RegisterRequestHandler(Commands.TransferData); + + _ = RegisterRequestHandler(Commands.BaseReown); + _ = RegisterRequestHandler(Commands.BaseSetDockingRights); + _ = RegisterRequestHandler(Commands.BaseSelect); + _ = RegisterRequestHandler(Commands.BaseGetInfo); + _ = RegisterRequestHandler(Commands.BaseGetMyItems); + _ = RegisterRequestHandler(Commands.BaseListFacilities).SingleInstance(); + + _ = RegisterRequestHandler(Commands.GetZoneInfo); + _ = RegisterRequestHandler(Commands.ItemCountOnZone); + + + _ = RegisterRequestHandler(Commands.CorporationCreate); + _ = RegisterRequestHandler(Commands.CorporationRemoveMember); + _ = RegisterRequestHandler(Commands.CorporationGetMyInfo); + _ = RegisterRequestHandler(Commands.CorporationSetMemberRole); + _ = RegisterRequestHandler(Commands.CorporationCharacterInvite); + _ = RegisterRequestHandler(Commands.CorporationInviteReply); + _ = RegisterRequestHandler(Commands.CorporationInfo); + _ = RegisterRequestHandler(Commands.CorporationLeave); + _ = RegisterRequestHandler(Commands.CorporationSearch); + _ = RegisterRequestHandler(Commands.CorporationSetInfo); + _ = RegisterRequestHandler(Commands.CorporationDropRoles); + _ = RegisterRequestHandler(Commands.CorporationCancelLeave); + _ = RegisterRequestHandler(Commands.CorporationPayOut); + _ = RegisterRequestHandler(Commands.CorporationForceInfo); + _ = RegisterRequestHandler(Commands.CorporationGetDelegates); + _ = RegisterRequestHandler(Commands.CorporationTransfer); + _ = RegisterRequestHandler(Commands.CorporationHangarListAll); + _ = RegisterRequestHandler(Commands.CorporationHangarListOnBase); + _ = RegisterRequestHandler(Commands.CorporationRentHangar); + _ = RegisterRequestHandler(Commands.CorporationHangarPayRent); + _ = RegisterRequestHandler(Commands.CorporationHangarLogSet); + _ = RegisterRequestHandler(Commands.CorporationHangarLogClear); + _ = RegisterRequestHandler(Commands.CorporationHangarLogList); + _ = RegisterRequestHandler(Commands.CorporationHangarSetAccess); + _ = RegisterRequestHandler(Commands.CorporationHangarClose); + _ = RegisterRequestHandler(Commands.CorporationHangarSetName); + _ = RegisterRequestHandler(Commands.CorporationHangarRentPrice); + _ = RegisterRequestHandler(Commands.CorporationHangarFolderSectionCreate); + _ = RegisterRequestHandler(Commands.CorporationHangarFolderSectionDelete); + _ = RegisterRequestHandler(Commands.CorporationVoteStart); + _ = RegisterRequestHandler(Commands.CorporationVoteList); + _ = RegisterRequestHandler(Commands.CorporationVoteDelete); + _ = RegisterRequestHandler(Commands.CorporationVoteCast); + _ = RegisterRequestHandler(Commands.CorporationVoteSetTopic); + _ = RegisterRequestHandler(Commands.CorporationBulletinStart); + _ = RegisterRequestHandler(Commands.CorporationBulletinEntry); + _ = RegisterRequestHandler(Commands.CorporationBulletinDelete); + _ = RegisterRequestHandler(Commands.CorporationBulletinList); + _ = RegisterRequestHandler(Commands.CorporationBulletinDetails); + _ = RegisterRequestHandler(Commands.CorporationBulletinEntryDelete); + _ = RegisterRequestHandler(Commands.CorporationBulletinNewEntries); + _ = RegisterRequestHandler(Commands.CorporationBulletinModerate); + _ = RegisterRequestHandler(Commands.CorporationCeoTakeOverStatus); + _ = RegisterRequestHandler(Commands.CorporationVolunteerForCeo); + _ = RegisterRequestHandler(Commands.CorporationRename); + _ = RegisterRequestHandler(Commands.CorporationDonate); + _ = RegisterRequestHandler(Commands.CorporationTransactionHistory); + _ = RegisterRequestHandler(Commands.CorporationApply); + _ = RegisterRequestHandler(Commands.CorporationDeleteMyApplication); + _ = RegisterRequestHandler(Commands.CorporationAcceptApplication); + _ = RegisterRequestHandler(Commands.CorporationDeleteApplication); + _ = RegisterRequestHandler(Commands.CorporationListMyApplications); + _ = RegisterRequestHandler(Commands.CorporationListApplications); + _ = RegisterRequestHandler(Commands.CorporationLogHistory); + _ = RegisterRequestHandler(Commands.CorporationNameHistory); + _ = RegisterRequestHandler(Commands.CorporationSetColor); + _ = RegisterRequestHandler(Commands.CorporationDocumentConfig).SingleInstance(); + _ = RegisterRequestHandler(Commands.CorporationDocumentTransfer); + _ = RegisterRequestHandler(Commands.CorporationDocumentList); + _ = RegisterRequestHandler(Commands.CorporationDocumentCreate); + _ = RegisterRequestHandler(Commands.CorporationDocumentDelete); + _ = RegisterRequestHandler(Commands.CorporationDocumentOpen); + _ = RegisterRequestHandler(Commands.CorporationDocumentUpdateBody); + _ = RegisterRequestHandler(Commands.CorporationDocumentMonitor); + _ = RegisterRequestHandler(Commands.CorporationDocumentUnmonitor); + _ = RegisterRequestHandler(Commands.CorporationDocumentRent); + _ = RegisterRequestHandler(Commands.CorporationDocumentRegisterList); + _ = RegisterRequestHandler(Commands.CorporationDocumentRegisterSet); + _ = RegisterRequestHandler(Commands.CorporationInfoFlushCache); + _ = RegisterRequestHandler(Commands.CorporationGetReputation); + _ = RegisterRequestHandler(Commands.CorporationMyStandings); + _ = RegisterRequestHandler(Commands.CorporationSetMembersNeutral); + _ = RegisterRequestHandler(Commands.CorporationRoleHistory); + _ = RegisterRequestHandler(Commands.CorporationMemberRoleHistory); + + + + + _ = RegisterRequestHandler(Commands.YellowPagesSearch); + _ = RegisterRequestHandler(Commands.YellowPagesSubmit); + _ = RegisterRequestHandler(Commands.YellowPagesGet); + _ = RegisterRequestHandler(Commands.YellowPagesDelete); + + + _ = RegisterRequestHandler(Commands.AllianceGetDefaults).SingleInstance(); + _ = RegisterRequestHandler(Commands.AllianceGetMyInfo); + _ = RegisterRequestHandler(Commands.AllianceRoleHistory); + + _ = RegisterRequestHandler(Commands.ExtensionTest); + _ = RegisterRequestHandler(Commands.ExtensionGetAll).SingleInstance(); + _ = RegisterRequestHandler(Commands.ExtensionPrerequireList).SingleInstance(); + _ = RegisterRequestHandler(Commands.ExtensionCategoryList).SingleInstance(); + _ = RegisterRequestHandler(Commands.ExtensionLearntList); + _ = RegisterRequestHandler(Commands.ExtensionGetAvailablePoints); + _ = RegisterRequestHandler(Commands.ExtensionGetPointParameters); + _ = RegisterRequestHandler(Commands.ExtensionHistory); + _ = RegisterRequestHandler(Commands.ExtensionBuyForPoints); + _ = RegisterRequestHandler(Commands.ExtensionRemoveLevel); + _ = RegisterRequestHandler(Commands.ExtensionBuyEpBoost); + _ = RegisterRequestHandler(Commands.ExtensionResetCharacter); + _ = RegisterRequestHandler(Commands.ExtensionFreeLockedEp); + _ = RegisterRequestHandler(Commands.ExtensionFreeAllLockedEpCommand); // For GameAdmin Channel Command + _ = RegisterRequestHandler(Commands.ExtensionGive); + _ = RegisterRequestHandler(Commands.ExtensionReset); + _ = RegisterRequestHandler(Commands.ExtensionRevert); + + _ = RegisterRequestHandler(Commands.ItemShopBuy); + _ = RegisterRequestHandler(Commands.ItemShopList); + _ = RegisterRequestHandler(Commands.GiftOpen); + _ = RegisterRequestHandler(Commands.GetHighScores); + _ = RegisterRequestHandler(Commands.GetMyHighScores); + _ = RegisterRequestHandler(Commands.ZoneSectorList).SingleInstance(); + + _ = RegisterRequestHandler(Commands.ListContainer); + + _ = RegisterRequestHandler(Commands.SocialGetMyList); + _ = RegisterRequestHandler(Commands.SocialFriendRequest); + _ = RegisterRequestHandler(Commands.SocialConfirmPendingFriendRequest); + _ = RegisterRequestHandler(Commands.SocialDeleteFriend); + _ = RegisterRequestHandler(Commands.SocialBlockFriend); + + _ = RegisterRequestHandler(Commands.PBSGetReimburseInfo); + _ = RegisterRequestHandler(Commands.PBSSetReimburseInfo); + _ = RegisterRequestHandler(Commands.PBSGetLog); + + _ = RegisterRequestHandler(Commands.MineralScanResultList); + _ = RegisterRequestHandler(Commands.MineralScanResultMove); + _ = RegisterRequestHandler(Commands.MineralScanResultDelete); + _ = RegisterRequestHandler(Commands.MineralScanResultCreateItem); + _ = RegisterRequestHandler(Commands.MineralScanResultUploadFromItem); + + _ = RegisterRequestHandler(Commands.FreshNewsCount); + _ = RegisterRequestHandler(Commands.GetNews); + _ = RegisterRequestHandler(Commands.AddNews); + _ = RegisterRequestHandler(Commands.UpdateNews); + _ = RegisterRequestHandler(Commands.NewsCategory).SingleInstance(); + + _ = RegisterRequestHandler(Commands.EpForActivityDailyLog); + _ = RegisterRequestHandler(Commands.GetMyKillReports); + _ = RegisterRequestHandler(Commands.UseLotteryItem); + _ = RegisterRequestHandler(Commands.ContainerMover); + + + _ = RegisterRequestHandler(Commands.MarketTaxChange); + _ = RegisterRequestHandler(Commands.MarketTaxLogList); + _ = RegisterRequestHandler(Commands.MarketGetInfo); + _ = RegisterRequestHandler(Commands.MarketAddCategory); + _ = RegisterRequestHandler(Commands.MarketItemList); + _ = RegisterRequestHandler(Commands.MarketGetMyItems); + _ = RegisterRequestHandler(Commands.MarketGetAveragePrices); + _ = RegisterRequestHandler(Commands.MarketCreateBuyOrder); + _ = RegisterRequestHandler(Commands.MarketCreateSellOrder); + _ = RegisterRequestHandler(Commands.MarketBuyItem); + _ = RegisterRequestHandler(Commands.MarketCancelItem); + _ = RegisterRequestHandler(Commands.MarketGetState); + _ = RegisterRequestHandler(Commands.MarketSetState); + _ = RegisterRequestHandler(Commands.MarketFlush); + _ = RegisterRequestHandler(Commands.MarketGetDefinitionAveragePrice); + _ = RegisterRequestHandler(Commands.MarketAvailableItems); + _ = RegisterRequestHandler(Commands.MarketItemsInRange); + _ = RegisterRequestHandler(Commands.MarketInsertStats); + _ = RegisterRequestHandler(Commands.MarketListFacilities); + _ = RegisterRequestHandler(Commands.MarketInsertAverageForCF); + _ = RegisterRequestHandler(Commands.MarketGlobalAveragePrices); + _ = RegisterRequestHandler(Commands.MarketModifyOrder); + _ = RegisterRequestHandler(Commands.MarketCreateGammaPlasmaOrders); + _ = RegisterRequestHandler(Commands.MarketRemoveItems); + _ = RegisterRequestHandler(Commands.MarketCleanUp); + + + + _ = RegisterRequestHandler(Commands.TradeBegin); + _ = RegisterRequestHandler(Commands.TradeCancel); + _ = RegisterRequestHandler(Commands.TradeSetOffer); + _ = RegisterRequestHandler(Commands.TradeAccept); + _ = RegisterRequestHandler(Commands.TradeRetractOffer); + + + _ = RegisterRequestHandler(Commands.GetRobotInfo).OnActivated(e => e.Instance.ForFitting = false); + _ = RegisterRequestHandler(Commands.GetRobotFittingInfo); + _ = RegisterRequestHandler(Commands.SelectActiveRobot); + _ = RegisterRequestHandler(Commands.RequestStarterRobot); + _ = RegisterRequestHandler(Commands.RobotEmpty); + _ = RegisterRequestHandler(Commands.SetRobotTint); + + _ = RegisterRequestHandler(Commands.FittingPresetList); + _ = RegisterRequestHandler(Commands.FittingPresetSave); + _ = RegisterRequestHandler(Commands.FittingPresetDelete); + _ = RegisterRequestHandler(Commands.FittingPresetApply); + + _ = RegisterRequestHandler(Commands.RobotTemplateAdd); + _ = RegisterRequestHandler(Commands.RobotTemplateUpdate); + _ = RegisterRequestHandler(Commands.RobotTemplateDelete); + _ = RegisterRequestHandler(Commands.RobotTemplateList); + _ = RegisterRequestHandler(Commands.RobotTemplateBuild); + + _ = RegisterRequestHandler(Commands.EquipModule); + _ = RegisterRequestHandler(Commands.ChangeModule); + _ = RegisterRequestHandler(Commands.RemoveModule); + _ = RegisterRequestHandler(Commands.EquipAmmo); + _ = RegisterRequestHandler(Commands.ChangeAmmo); + _ = RegisterRequestHandler(Commands.UnequipAmmo); + _ = RegisterRequestHandler(Commands.PackItems); + _ = RegisterRequestHandler(Commands.UnpackItems); + _ = RegisterRequestHandler(Commands.TrashItems); + _ = RegisterRequestHandler(Commands.RelocateItems); + _ = RegisterRequestHandler(Commands.StackSelection); + _ = RegisterRequestHandler(Commands.UnstackAmount); + _ = RegisterRequestHandler(Commands.SetItemName); + _ = RegisterRequestHandler(Commands.StackTo); + _ = RegisterRequestHandler(Commands.ServerMessage); + _ = RegisterRequestHandler(Commands.RequestInfiniteBox); + _ = RegisterRequestHandler(Commands.DecorCategoryList); + _ = RegisterRequestHandler(Commands.PollGet); + _ = RegisterRequestHandler(Commands.PollAnswer); + _ = RegisterRequestHandler(Commands.ForceDock); + _ = RegisterRequestHandler(Commands.ForceDockAdmin); + _ = RegisterRequestHandler(Commands.GetItemSummary); + + _ = RegisterRequestHandler(Commands.ProductionHistory); + _ = RegisterRequestHandler(Commands.GetResearchLevels).SingleInstance(); + _ = RegisterRequestHandler(Commands.ProductionComponentsList); + _ = RegisterRequestHandler(Commands.ProductionRefine); + _ = RegisterRequestHandler(Commands.ProductionRefineQuery); + _ = RegisterRequestHandler(Commands.ProductionCPRGInfo); + _ = RegisterRequestHandler(Commands.ProductionCPRGForge); + _ = RegisterRequestHandler(Commands.ProductionCPRGForgeQuery); + _ = RegisterRequestHandler(Commands.ProductionGetCprgFromLine); + _ = RegisterRequestHandler(Commands.ProductionGetCprgFromLineQuery); + _ = RegisterRequestHandler(Commands.ProductionLineSetRounds); + _ = RegisterRequestHandler(Commands.ProductionPrototypeStart); + _ = RegisterRequestHandler(Commands.ProductionPrototypeQuery); + _ = RegisterRequestHandler(Commands.ProductionInsuranceQuery); + _ = RegisterRequestHandler(Commands.ProductionInsuranceList); + _ = RegisterRequestHandler(Commands.ProductionInsuranceBuy); + _ = RegisterRequestHandler(Commands.ProductionInsuranceDelete); + _ = RegisterRequestHandler(Commands.ProductionMergeResearchKitsMulti); + _ = RegisterRequestHandler(Commands.ProductionMergeResearchKitsMultiQuery); + _ = RegisterRequestHandler(Commands.ProductionQueryLineNextRound); + _ = RegisterRequestHandler(Commands.ProductionReprocess); + _ = RegisterRequestHandler(Commands.ProductionReprocessQuery); + _ = RegisterRequestHandler(Commands.ProductionRepair); + _ = RegisterRequestHandler(Commands.ProductionRepairQuery); + _ = RegisterRequestHandler(Commands.ProductionResearch); + _ = RegisterRequestHandler(Commands.ProductionResearchQuery); + _ = RegisterRequestHandler(Commands.ProductionInProgress); + _ = RegisterRequestHandler(Commands.ProductionCancel); + _ = RegisterRequestHandler(Commands.ProductionFacilityInfo); + _ = RegisterRequestHandler(Commands.ProductionLineList); + _ = RegisterRequestHandler(Commands.ProductionLineCalibrate); + _ = RegisterRequestHandler(Commands.ProductionLineDelete); + _ = RegisterRequestHandler(Commands.ProductionLineStart); + _ = RegisterRequestHandler(Commands.ProductionFacilityDescription); + _ = RegisterRequestHandler(Commands.ProductionInProgressCorporation); //admin - RegisterRequestHandler(Commands.ProductionRemoveFacility); - RegisterRequestHandler(Commands.ProductionSpawnComponents); - RegisterRequestHandler(Commands.ProductionScaleComponentsAmount); - RegisterRequestHandler(Commands.ProductionUnrepairItem); - RegisterRequestHandler(Commands.ProductionFacilityOnOff); - RegisterRequestHandler(Commands.ProductionForceEnd); - RegisterRequestHandler(Commands.ProductionServerInfo); - RegisterRequestHandler(Commands.ProductionSpawnCPRG); - RegisterRequestHandler(Commands.ProductionGetInsurance); - RegisterRequestHandler(Commands.ProductionSetInsurance); - - RegisterRequestHandler(Commands.CreateCorporationHangarStorage); - RegisterRequestHandler(Commands.DockAll); - RegisterRequestHandler(Commands.ReturnCorporateOwnedItems); - - RegisterRequestHandler(Commands.RelayOpen); - RegisterRequestHandler(Commands.RelayClose); - RegisterRequestHandler(Commands.ZoneSaveLayer); - RegisterRequestHandler(Commands.ZoneRemoveObject); - RegisterRequestHandler(Commands.ZoneDebugLOS); - RegisterRequestHandler(Commands.ZoneSetBaseDetails); - RegisterRequestHandler(Commands.ZoneSelfDestruct); - RegisterRequestHandler(Commands.ZoneSOS); - RegisterRequestHandler(Commands.ZoneCopyGroundType); //OPP - - RegisterRequestHandler(Commands.ZoneGetZoneObjectDebugInfo); - RegisterRequestHandler(Commands.ZoneDrawBlockingByEid); - - - RegisterRequestHandler(Commands.GangCreate); - RegisterRequestHandler(Commands.GangDelete); - RegisterRequestHandler(Commands.GangLeave); - RegisterRequestHandler(Commands.GangKick); - RegisterRequestHandler(Commands.GangInfo); - RegisterRequestHandler(Commands.GangSetLeader); - RegisterRequestHandler(Commands.GangSetRole); - RegisterRequestHandler(Commands.GangInvite); - RegisterRequestHandler(Commands.GangInviteReply); - - RegisterRequestHandler(Commands.TechTreeInfo); - RegisterRequestHandler(Commands.TechTreeUnlock); - RegisterRequestHandler(Commands.TechTreeResearch); - RegisterRequestHandler(Commands.TechTreeDonate); - RegisterRequestHandler(Commands.TechTreeGetLogs); - - - RegisterRequestHandler(Commands.TransportAssignmentSubmit); - RegisterRequestHandler(Commands.TransportAssignmentList); - RegisterRequestHandler(Commands.TransportAssignmentCancel); - RegisterRequestHandler(Commands.TransportAssignmentTake); - RegisterRequestHandler(Commands.TransportAssignmentLog); - RegisterRequestHandler(Commands.TransportAssignmentContainerInfo); - RegisterRequestHandler(Commands.TransportAssignmentRunning); - RegisterRequestHandler(Commands.TransportAssignmentRetrieve); - RegisterRequestHandler(Commands.TransportAssignmentListContent); - RegisterRequestHandler(Commands.TransportAssignmentGiveUp); - RegisterRequestHandler(Commands.TransportAssignmentDeliver); - - - RegisterRequestHandler(Commands.SetStanding); - RegisterRequestHandler(Commands.ForceStanding); - RegisterRequestHandler(Commands.ForceFactionStandings); - RegisterRequestHandler(Commands.GetStandingForDefaultCorporations); - RegisterRequestHandler(Commands.GetStandingForDefaultAlliances); - RegisterRequestHandler(Commands.StandingList); - RegisterRequestHandler(Commands.StandingHistory); - RegisterRequestHandler(Commands.ReloadStandingForCharacter); - - RegisterRequestHandler(Commands.MailList); - RegisterRequestHandler(Commands.MailUsedFolders); - RegisterRequestHandler(Commands.MailSend); - RegisterRequestHandler(Commands.MailDelete); - RegisterRequestHandler(Commands.MailOpen); - RegisterRequestHandler(Commands.MailMoveToFolder); - RegisterRequestHandler(Commands.MailDeleteFolder); - RegisterRequestHandler(Commands.MailNewCount); - RegisterRequestHandler(Commands.MassMailOpen); - RegisterRequestHandler(Commands.MassMailDelete); - RegisterRequestHandler(Commands.MassMailSend); - RegisterRequestHandler(Commands.MassMailList); - RegisterRequestHandler(Commands.MassMailNewCount); - - - RegisterRequestHandler(Commands.ServerShutDownState); - RegisterRequestHandler(Commands.ServerShutDown); - RegisterRequestHandler(Commands.ServerShutDownCancel); + _ = RegisterRequestHandler(Commands.ProductionRemoveFacility); + _ = RegisterRequestHandler(Commands.ProductionSpawnComponents); + _ = RegisterRequestHandler(Commands.ProductionScaleComponentsAmount); + _ = RegisterRequestHandler(Commands.ProductionUnrepairItem); + _ = RegisterRequestHandler(Commands.ProductionFacilityOnOff); + _ = RegisterRequestHandler(Commands.ProductionForceEnd); + _ = RegisterRequestHandler(Commands.ProductionServerInfo); + _ = RegisterRequestHandler(Commands.ProductionSpawnCPRG); + _ = RegisterRequestHandler(Commands.ProductionGetInsurance); + _ = RegisterRequestHandler(Commands.ProductionSetInsurance); + + _ = RegisterRequestHandler(Commands.CreateCorporationHangarStorage); + _ = RegisterRequestHandler(Commands.DockAll); + _ = RegisterRequestHandler(Commands.ReturnCorporateOwnedItems); + + _ = RegisterRequestHandler(Commands.RelayOpen); + _ = RegisterRequestHandler(Commands.RelayClose); + _ = RegisterRequestHandler(Commands.ZoneSaveLayer); + _ = RegisterRequestHandler(Commands.ZoneRemoveObject); + _ = RegisterRequestHandler(Commands.ZoneDebugLOS); + _ = RegisterRequestHandler(Commands.ZoneSetBaseDetails); + _ = RegisterRequestHandler(Commands.ZoneSelfDestruct); + _ = RegisterRequestHandler(Commands.ZoneSOS); + _ = RegisterRequestHandler(Commands.ZoneCopyGroundType); //OPP + + _ = RegisterRequestHandler(Commands.ZoneGetZoneObjectDebugInfo); + _ = RegisterRequestHandler(Commands.ZoneDrawBlockingByEid); + + + _ = RegisterRequestHandler(Commands.GangCreate); + _ = RegisterRequestHandler(Commands.GangDelete); + _ = RegisterRequestHandler(Commands.GangLeave); + _ = RegisterRequestHandler(Commands.GangKick); + _ = RegisterRequestHandler(Commands.GangInfo); + _ = RegisterRequestHandler(Commands.GangSetLeader); + _ = RegisterRequestHandler(Commands.GangSetRole); + _ = RegisterRequestHandler(Commands.GangInvite); + _ = RegisterRequestHandler(Commands.GangInviteReply); + + _ = RegisterRequestHandler(Commands.TechTreeInfo); + _ = RegisterRequestHandler(Commands.TechTreeUnlock); + _ = RegisterRequestHandler(Commands.TechTreeResearch); + _ = RegisterRequestHandler(Commands.TechTreeDonate); + _ = RegisterRequestHandler(Commands.TechTreeGetLogs); + + + _ = RegisterRequestHandler(Commands.TransportAssignmentSubmit); + _ = RegisterRequestHandler(Commands.TransportAssignmentList); + _ = RegisterRequestHandler(Commands.TransportAssignmentCancel); + _ = RegisterRequestHandler(Commands.TransportAssignmentTake); + _ = RegisterRequestHandler(Commands.TransportAssignmentLog); + _ = RegisterRequestHandler(Commands.TransportAssignmentContainerInfo); + _ = RegisterRequestHandler(Commands.TransportAssignmentRunning); + _ = RegisterRequestHandler(Commands.TransportAssignmentRetrieve); + _ = RegisterRequestHandler(Commands.TransportAssignmentListContent); + _ = RegisterRequestHandler(Commands.TransportAssignmentGiveUp); + _ = RegisterRequestHandler(Commands.TransportAssignmentDeliver); + + + _ = RegisterRequestHandler(Commands.SetStanding); + _ = RegisterRequestHandler(Commands.ForceStanding); + _ = RegisterRequestHandler(Commands.ForceFactionStandings); + _ = RegisterRequestHandler(Commands.GetStandingForDefaultCorporations); + _ = RegisterRequestHandler(Commands.GetStandingForDefaultAlliances); + _ = RegisterRequestHandler(Commands.StandingList); + _ = RegisterRequestHandler(Commands.StandingHistory); + _ = RegisterRequestHandler(Commands.ReloadStandingForCharacter); + + _ = RegisterRequestHandler(Commands.MailList); + _ = RegisterRequestHandler(Commands.MailUsedFolders); + _ = RegisterRequestHandler(Commands.MailSend); + _ = RegisterRequestHandler(Commands.MailDelete); + _ = RegisterRequestHandler(Commands.MailOpen); + _ = RegisterRequestHandler(Commands.MailMoveToFolder); + _ = RegisterRequestHandler(Commands.MailDeleteFolder); + _ = RegisterRequestHandler(Commands.MailNewCount); + _ = RegisterRequestHandler(Commands.MassMailOpen); + _ = RegisterRequestHandler(Commands.MassMailDelete); + _ = RegisterRequestHandler(Commands.MassMailSend); + _ = RegisterRequestHandler(Commands.MassMailList); + _ = RegisterRequestHandler(Commands.MassMailNewCount); + + + _ = RegisterRequestHandler(Commands.ServerShutDownState); + _ = RegisterRequestHandler(Commands.ServerShutDown); + _ = RegisterRequestHandler(Commands.ServerShutDownCancel); RegisterZoneRequestHandlers(); //Admin tool commands - RegisterRequestHandler(Commands.GetAccountsWithCharacters); - RegisterRequestHandler(Commands.AccountGet); - RegisterRequestHandler(Commands.AccountUpdate); - RegisterRequestHandler(Commands.AccountCreate); - RegisterRequestHandler(Commands.ChangeSessionPassword); - RegisterRequestHandler(Commands.AccountBan); - RegisterRequestHandler(Commands.AccountUnban); - RegisterRequestHandler(Commands.AccountDelete); - RegisterRequestHandler(Commands.ServerInfoGet); - RegisterRequestHandler(Commands.ServerInfoSet); + _ = RegisterRequestHandler(Commands.GetAccountsWithCharacters); + _ = RegisterRequestHandler(Commands.AccountGet); + _ = RegisterRequestHandler(Commands.AccountUpdate); + _ = RegisterRequestHandler(Commands.AccountCreate); + _ = RegisterRequestHandler(Commands.ChangeSessionPassword); + _ = RegisterRequestHandler(Commands.AccountBan); + _ = RegisterRequestHandler(Commands.AccountUnban); + _ = RegisterRequestHandler(Commands.AccountDelete); + _ = RegisterRequestHandler(Commands.ServerInfoGet); + _ = RegisterRequestHandler(Commands.ServerInfoSet); // Open account commands - RegisterRequestHandler(Commands.AccountOpenCreate); + _ = RegisterRequestHandler(Commands.AccountOpenCreate); // Event GM Commands - RegisterRequestHandler(Commands.EPBonusSet); + _ = RegisterRequestHandler(Commands.EPBonusSet); } private void RegisterRobotTemplates() { - _builder.Register(x => + _ = _builder.Register(x => { - var relations = x.Resolve(); - return (definition => + IRobotTemplateRelations relations = x.Resolve(); + return definition => { return relations.GetRelatedTemplateOrDefault(definition); - }); + }; }); - _builder.RegisterType().AsSelf().As(); - _builder.Register(x => + _ = _builder.RegisterType().AsSelf().As(); + _ = _builder.Register(x => { return new CachedRobotTemplateReader(x.Resolve()); }).AsSelf().As().SingleInstance().OnActivated(e => e.Instance.Init()); - _builder.RegisterType().As(); - _builder.RegisterType().As().SingleInstance().OnActivated(e => + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType().As().SingleInstance().OnActivated(e => { e.Instance.Init(); }); - _builder.RegisterType().As().PropertiesAutowired().SingleInstance(); + _ = _builder.RegisterType().As().PropertiesAutowired().SingleInstance(); - _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); } private void RegisterTerrains() { - _builder.Register>>(x => + _ = _builder.Register>>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { - var reader = ctx.Resolve(); - var listener = new OreNpcSpawner(zone, ctx.Resolve(), reader); - var eventListenerService = ctx.Resolve(); + IMineralConfigurationReader reader = ctx.Resolve(); + OreNpcSpawner listener = new OreNpcSpawner(zone, ctx.Resolve(), reader); + EventListenerService eventListenerService = ctx.Resolve(); eventListenerService.AttachListener(listener); if (zone is TrainingZone) { - var repo = ctx.Resolve(); - var config = new GravelConfiguration(zone); - var layer = new GravelLayer(zone.Size.Width, zone.Size.Height, config, repo); + GravelRepository repo = ctx.Resolve(); + GravelConfiguration config = new GravelConfiguration(zone); + GravelLayer layer = new GravelLayer(zone.Size.Width, zone.Size.Height, config, repo); layer.LoadMineralNodes(); return new[] { layer }; } - var nodeGeneratorFactory = new MineralNodeGeneratorFactory(zone); + MineralNodeGeneratorFactory nodeGeneratorFactory = new MineralNodeGeneratorFactory(zone); - var materialLayers = new List(); + List materialLayers = new List(); - foreach (var configuration in reader.ReadAll().Where(c => c.ZoneId == zone.Id)) + foreach (IMineralConfiguration configuration in reader.ReadAll().Where(c => c.ZoneId == zone.Id)) { - var repo = new MineralNodeRepository(zone, configuration.Type); + MineralNodeRepository repo = new MineralNodeRepository(zone, configuration.Type); switch (configuration.ExtractionType) { case MineralExtractionType.Solid: { - var layer = new OreLayer(zone.Size.Width, zone.Size.Height, configuration, repo, nodeGeneratorFactory, eventListenerService); + OreLayer layer = new OreLayer(zone.Size.Width, zone.Size.Height, configuration, repo, nodeGeneratorFactory, eventListenerService); layer.LoadMineralNodes(); materialLayers.Add(layer); break; } case MineralExtractionType.Liquid: { - var layer = new LiquidLayer(zone.Size.Width, zone.Size.Height, configuration, repo, nodeGeneratorFactory, eventListenerService); + LiquidLayer layer = new LiquidLayer(zone.Size.Width, zone.Size.Height, configuration, repo, nodeGeneratorFactory, eventListenerService); layer.LoadMineralNodes(); materialLayers.Add(layer); break; @@ -2331,42 +2356,42 @@ private void RegisterTerrains() }; }); - _builder.RegisterType(); - _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterGeneric(typeof(IntervalLayerSaver<>)).InstancePerDependency(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterGeneric(typeof(IntervalLayerSaver<>)).InstancePerDependency(); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { - var terrain = ctx.Resolve(); + Terrain terrain = ctx.Resolve(); - var size = zone.Configuration.Size; + System.Drawing.Size size = zone.Configuration.Size; - var loader = ctx.Resolve(); + ILayerFileIO loader = ctx.Resolve(); - var blocks = loader.Load(zone, LayerType.Blocks); + BlockingInfo[] blocks = loader.Load(zone, LayerType.Blocks); terrain.Blocks = new Layer(LayerType.Blocks, blocks, size.Width, size.Height); - var controls = loader.Load(zone, LayerType.Control); + TerrainControlInfo[] controls = loader.Load(zone, LayerType.Control); terrain.Controls = new Layer(LayerType.Control, controls, size.Width, size.Height); - var plants = loader.Load(zone, LayerType.Plants); + PlantInfo[] plants = loader.Load(zone, LayerType.Plants); terrain.Plants = new Layer(LayerType.Plants, plants, size.Width, size.Height); - var altitude = loader.Load(zone, LayerType.Altitude); + ushort[] altitude = loader.Load(zone, LayerType.Altitude); AltitudeLayer altitudeLayer; if (zone.Configuration.Terraformable) { - var originalAltitude = new Layer(LayerType.OriginalAltitude, altitude, size.Width, size.Height); - var blend = loader.LoadLayerData(zone, "altitude_blend"); - var blendLayer = new Layer(LayerType.Blend, blend, size.Width, size.Height); + Layer originalAltitude = new Layer(LayerType.OriginalAltitude, altitude, size.Width, size.Height); + ushort[] blend = loader.LoadLayerData(zone, "altitude_blend"); + Layer blendLayer = new Layer(LayerType.Blend, blend, size.Width, size.Height); altitudeLayer = new TerraformableAltitude(originalAltitude, blendLayer, altitude); } else @@ -2379,13 +2404,13 @@ private void RegisterTerrains() if (!zone.Configuration.Terraformable) { - var b = new PassableMapBuilder(terrain.Blocks, terrain.Slope, zone.GetPassablePositionFromDb()); + PassableMapBuilder b = new PassableMapBuilder(terrain.Blocks, terrain.Slope, zone.GetPassablePositionFromDb()); terrain.Passable = b.Build(); } terrain.Materials = ctx.Resolve>>().Invoke(zone).ToDictionary(m => m.Type); - var layerSavers = new CompositeProcess(); + CompositeProcess layerSavers = new CompositeProcess(); layerSavers.AddProcess(ctx.Resolve.Factory>().Invoke(terrain.Blocks, zone)); layerSavers.AddProcess(ctx.Resolve.Factory>().Invoke(terrain.Controls, zone)); layerSavers.AddProcess(ctx.Resolve.Factory>().Invoke(terrain.Plants, zone)); @@ -2400,68 +2425,60 @@ private void RegisterTerrains() private void RegisterIntrusions() { - RegisterRequestHandler(Commands.BaseGetOwnershipInfo); - RegisterRequestHandler(Commands.IntrusionGetPauseTime); - RegisterRequestHandler(Commands.IntrusionSetPauseTime); - RegisterRequestHandler(Commands.IntrusionUpgradeFacility); - RegisterRequestHandler(Commands.SetIntrusionSiteMessage); - RegisterRequestHandler(Commands.GetIntrusionLog); - RegisterRequestHandler(Commands.GetIntrusionStabilityLog); - RegisterRequestHandler(Commands.GetStabilityBonusThresholds); - RegisterRequestHandler(Commands.GetIntrusionSiteInfo); - RegisterRequestHandler(Commands.GetIntrusionPublicLog); - RegisterRequestHandler(Commands.GetIntrusionMySitesLog); - - RegisterZoneRequestHandler(Commands.IntrusionSAPGetItemInfo); - RegisterZoneRequestHandler(Commands.IntrusionSAPSubmitItem); - RegisterZoneRequestHandler(Commands.IntrusionSiteSetEffectBonus); - RegisterZoneRequestHandler(Commands.IntrusionSetDefenseThreshold); - - RegisterZoneRequestHandler(Commands.GetRobotFittingInfo); + _ = RegisterRequestHandler(Commands.BaseGetOwnershipInfo); + _ = RegisterRequestHandler(Commands.IntrusionGetPauseTime); + _ = RegisterRequestHandler(Commands.IntrusionSetPauseTime); + _ = RegisterRequestHandler(Commands.IntrusionUpgradeFacility); + _ = RegisterRequestHandler(Commands.SetIntrusionSiteMessage); + _ = RegisterRequestHandler(Commands.GetIntrusionLog); + _ = RegisterRequestHandler(Commands.GetIntrusionStabilityLog); + _ = RegisterRequestHandler(Commands.GetStabilityBonusThresholds); + _ = RegisterRequestHandler(Commands.GetIntrusionSiteInfo); + _ = RegisterRequestHandler(Commands.GetIntrusionPublicLog); + _ = RegisterRequestHandler(Commands.GetIntrusionMySitesLog); + + _ = RegisterZoneRequestHandler(Commands.IntrusionSAPGetItemInfo); + _ = RegisterZoneRequestHandler(Commands.IntrusionSAPSubmitItem); + _ = RegisterZoneRequestHandler(Commands.IntrusionSiteSetEffectBonus); + _ = RegisterZoneRequestHandler(Commands.IntrusionSetDefenseThreshold); + + _ = RegisterZoneRequestHandler(Commands.GetRobotFittingInfo); } private void RegisterRifts() { - _builder.Register>(x => + _ = _builder.Register>(x => { return zone => { - if (zone.Configuration.Terraformable) - { - return new PvpRiftSpawnPositionFinder(zone); - } - - return new PveRiftSpawnPositionFinder(zone); + return zone.Configuration.Terraformable ? new PvpRiftSpawnPositionFinder(zone) : (RiftSpawnPositionFinder)new PveRiftSpawnPositionFinder(zone); }; }); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { if (zone is TrainingZone) + { return null; + } if (zone is StrongHoldZone) { - var strongHoldExitConfigCount = Db.Query().CommandText("SELECT COUNT(*) FROM strongholdexitconfig WHERE zoneid = @zoneId;") + int strongHoldExitConfigCount = Db.Query().CommandText("SELECT COUNT(*) FROM strongholdexitconfig WHERE zoneid = @zoneId;") .SetParameter("@zoneId", zone.Id) .ExecuteScalar(); - if (strongHoldExitConfigCount < 1) - { - return null; - } - - return ctx.Resolve(new TypedParameter(typeof(IZone), zone)); + return strongHoldExitConfigCount < 1 ? null : (IRiftManager)ctx.Resolve(new TypedParameter(typeof(IZone), zone)); } - var zoneConfigs = Db.Query().CommandText("SELECT maxrifts FROM zoneriftsconfig WHERE zoneid = @zoneId") + List zoneConfigs = Db.Query().CommandText("SELECT maxrifts FROM zoneriftsconfig WHERE zoneid = @zoneId") .SetParameter("@zoneId", zone.Id) .Execute(); if (zoneConfigs.Count < 1) @@ -2469,16 +2486,16 @@ private void RegisterRifts() return null; } - var record = zoneConfigs[0]; - var maxrifts = record.GetValue("maxrifts"); + System.Data.IDataRecord record = zoneConfigs[0]; + int maxrifts = record.GetValue("maxrifts"); if (maxrifts < 1) { return null; } - var spawnTime = TimeRange.FromLength(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5)); - var finder = ctx.Resolve>().Invoke(zone); + TimeRange spawnTime = TimeRange.FromLength(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5)); + RiftSpawnPositionFinder finder = ctx.Resolve>().Invoke(zone); return ctx.Resolve(new TypedParameter(typeof(IZone), zone), new NamedParameter("spawnTime", spawnTime), new NamedParameter("spawnPositionFinder", finder)); }; }); @@ -2486,14 +2503,14 @@ private void RegisterRifts() private void RegisterRelics() { - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { - var numRelicConfigs = Db.Query().CommandText("SELECT id FROM relicspawninfo WHERE zoneid = @zoneId") + int numRelicConfigs = Db.Query().CommandText("SELECT id FROM relicspawninfo WHERE zoneid = @zoneId") .SetParameter("@zoneId", zone.Id) .Execute().Count; if (numRelicConfigs < 1) @@ -2501,15 +2518,15 @@ private void RegisterRelics() return null; } - var zoneConfigs = Db.Query().CommandText("SELECT maxspawn FROM reliczoneconfig WHERE zoneid = @zoneId") + List zoneConfigs = Db.Query().CommandText("SELECT maxspawn FROM reliczoneconfig WHERE zoneid = @zoneId") .SetParameter("@zoneId", zone.Id) .Execute(); if (zoneConfigs.Count < 1) { return null; } - var record = zoneConfigs[0]; - var maxspawn = record.GetValue("maxspawn"); + System.Data.IDataRecord record = zoneConfigs[0]; + int maxspawn = record.GetValue("maxspawn"); if (maxspawn < 1) { return null; @@ -2522,14 +2539,14 @@ private void RegisterRelics() private void RegisterZones() { - _builder.RegisterType().AsSelf().As(); + _ = _builder.RegisterType().AsSelf().As(); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.Register(c => + _ = _builder.Register(c => { return new WeatherService(new TimeRange(TimeSpan.FromMinutes(30), TimeSpan.FromHours(1))); }).OnActivated(e => @@ -2537,34 +2554,34 @@ private void RegisterZones() e.Context.Resolve().AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromMinutes(5))); }).As(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.Register>(x => + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { return new WeatherEventListener(ctx.Resolve(), zone); }; }); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { - var listener = new EnvironmentalEffectHandler(zone); + EnvironmentalEffectHandler listener = new EnvironmentalEffectHandler(zone); ctx.Resolve().AttachListener(listener); return listener; }; }); - _builder.RegisterType().AsSelf().As(); - _builder.RegisterType().AsSelf().As(); + _ = _builder.RegisterType().AsSelf().As(); + _ = _builder.RegisterType().AsSelf().As(); - _builder.Register(x => + _ = _builder.Register(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { return new ZoneUnitService @@ -2575,14 +2592,14 @@ private void RegisterZones() }; }); - _builder.RegisterType().As(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As().SingleInstance(); void RegisterZone(ZoneType type) where T : Zone { - _builder.RegisterType().Keyed(type).OnActivated(e => + _ = _builder.RegisterType().Keyed(type).OnActivated(e => { e.Context.Resolve().AddProcess(e.Instance.ToAsync()); }); @@ -2593,27 +2610,27 @@ void RegisterZone(ZoneType type) where T : Zone RegisterZone(ZoneType.Training); RegisterZone(ZoneType.Stronghold); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().As(); + _ = _builder.RegisterType().As(); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return zone => { return new StrongholdPlayerStateManager(zone, ctx.Resolve()); }; }); - _builder.Register>(x => + _ = _builder.Register>(x => { - var ctx = x.Resolve(); + IComponentContext ctx = x.Resolve(); return configuration => { - var zone = ctx.ResolveKeyed(configuration.Type); + Zone zone = ctx.ResolveKeyed(configuration.Type); zone.Configuration = configuration; zone.Listener = new TcpListener(new IPEndPoint(IPAddress.Any, configuration.ListenerPort)); zone.ZoneEffectHandler = ctx.Resolve>().Invoke(zone); @@ -2648,7 +2665,7 @@ void RegisterZone(ZoneType type) where T : Zone } ctx.Resolve().AttachListener(new NpcReinforcementSpawner(zone, ctx.Resolve())); - var listener = ctx.Resolve>().Invoke(zone); + WeatherEventListener listener = ctx.Resolve>().Invoke(zone); listener.Subscribe(zone.Weather); zone.LoadUnits(); @@ -2656,15 +2673,15 @@ void RegisterZone(ZoneType type) where T : Zone }; }); - _builder.Register(c => c.Resolve()).As(); - _builder.RegisterType().OnActivated(e => + _ = _builder.Register(c => c.Resolve()).As(); + _ = _builder.RegisterType().OnActivated(e => { - foreach (var c in e.Context.Resolve().GetAll()) + foreach (ZoneConfiguration c in e.Context.Resolve().GetAll()) { - var zoneFactory = e.Context.Resolve>(); - var zone = zoneFactory(c); + Func zoneFactory = e.Context.Resolve>(); + IZone zone = zoneFactory(c); - e.Context.Resolve>().Invoke(zone); + _ = e.Context.Resolve>().Invoke(zone); Logger.Info("------------------"); Logger.Info("--"); @@ -2673,49 +2690,49 @@ void RegisterZone(ZoneType type) where T : Zone Logger.Info("------------------"); e.Instance.Zones.Add(zone); - }; + } }).SingleInstance(); - _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().OnActivated(e => { - var pm = e.Context.Resolve(); + IProcessManager pm = e.Context.Resolve(); pm.AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(1))); }).As().InstancePerDependency(); - _builder.RegisterType().OnActivated(e => e.Instance.Initialize()).InstancePerDependency(); - _builder.RegisterType(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().OnActivated(e => e.Instance.Initialize()).InstancePerDependency(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().OnActivated(e => { - var pm = e.Context.Resolve(); + IProcessManager pm = e.Context.Resolve(); pm.AddProcess(e.Instance.ToAsync().AsTimed(TimeSpan.FromSeconds(5))); }).As().InstancePerDependency(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType().As().SingleInstance(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); - _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().As().SingleInstance(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType(); - _builder.RegisterType().OnActivated(e => + _ = _builder.RegisterType().OnActivated(e => { - var pm = e.Context.Resolve(); + IProcessManager pm = e.Context.Resolve(); pm.AddProcess(e.Instance.AsTimed(TimeSpan.FromMilliseconds(PBSHighwayHandler.DRAW_INTERVAL)).ToAsync()); }); - _builder.RegisterType(); - _builder.RegisterType().SingleInstance(); - _builder.RegisterType().As(); + _ = _builder.RegisterType(); + _ = _builder.RegisterType().SingleInstance(); + _ = _builder.RegisterType().As(); - _builder.RegisterType() + _ = _builder.RegisterType() .As() .PropertiesAutowired() .SingleInstance(); - _builder.RegisterType().SingleInstance().As(); + _ = _builder.RegisterType().SingleInstance().As(); } private IRegistrationBuilder @@ -2726,147 +2743,149 @@ private IRegistrationBuilder(Commands.TeleportGetChannelList); - RegisterZoneRequestHandler(Commands.TeleportToZoneObject); - RegisterZoneRequestHandler(Commands.TeleportUse); - RegisterZoneRequestHandler(Commands.TeleportQueryWorldChannels); - RegisterZoneRequestHandler(Commands.JumpAnywhere); - RegisterZoneRequestHandler(Commands.MovePlayer); - RegisterZoneRequestHandler(Commands.ZoneDrawStatMap); - RegisterZoneRequestHandler(Commands.MissionStartFromZone); - RegisterZoneRequestHandler(Commands.ItemShopBuy); - RegisterZoneRequestHandler(Commands.ItemShopList); - RegisterZoneRequestHandler(Commands.ZoneMoveUnit); - RegisterZoneRequestHandler(Commands.ZoneGetQueueInfo); - RegisterZoneRequestHandler(Commands.ZoneSetQueueLength); - RegisterZoneRequestHandler(Commands.ZoneCancelEnterQueue); - RegisterZoneRequestHandler(Commands.ZoneGetBuildings); - - RegisterZoneRequestHandler(Commands.Dock); - - RegisterZoneRequestHandler(Commands.ZoneDecorAdd); - RegisterZoneRequestHandler(Commands.ZoneDecorSet); - RegisterZoneRequestHandler(Commands.ZoneDecorDelete); - RegisterZoneRequestHandler(Commands.ZoneDecorLock); - RegisterZoneRequestHandler(Commands.ZoneDrawDecorEnvironment); - RegisterZoneRequestHandler(Commands.ZoneSampleDecorEnvironment); - RegisterZoneRequestHandler(Commands.ZoneDrawDecorEnvByDef); - RegisterZoneRequestHandler(Commands.ZoneDrawAllDecors); - RegisterZoneRequestHandler(Commands.ZoneEnvironmentDescriptionList); - RegisterZoneRequestHandler(Commands.ZoneSampleEnvironment); - RegisterZoneRequestHandler(Commands.ZoneCreateTeleportColumn); - - RegisterZoneRequestHandler(Commands.PackItems); - RegisterZoneRequestHandler(Commands.UnpackItems); - RegisterZoneRequestHandler(Commands.TrashItems); - RegisterZoneRequestHandler(Commands.RelocateItems); - RegisterZoneRequestHandler(Commands.StackItems); - RegisterZoneRequestHandler(Commands.StackSelection); - RegisterZoneRequestHandler(Commands.UnstackAmount); - RegisterZoneRequestHandler(Commands.SetItemName); - RegisterZoneRequestHandler(Commands.ListContainer); - RegisterZoneRequestHandler(Commands.EquipModule); - RegisterZoneRequestHandler(Commands.RemoveModule); - RegisterZoneRequestHandler(Commands.ChangeModule); - RegisterZoneRequestHandler(Commands.EquipAmmo); - RegisterZoneRequestHandler(Commands.UnequipAmmo); - RegisterZoneRequestHandler(Commands.ChangeAmmo); - - RegisterZoneRequestHandler(Commands.MissionGetSupply); - RegisterZoneRequestHandler(Commands.MissionSpotPlace); - RegisterZoneRequestHandler(Commands.MissionSpotUpdate); - RegisterZoneRequestHandler(Commands.ZoneUpdateStructure); - RegisterZoneRequestHandler(Commands.RemoveMissionStructure); - RegisterZoneRequestHandler(Commands.KioskInfo); - RegisterZoneRequestHandler(Commands.KioskSubmitItem); - RegisterZoneRequestHandler(Commands.AlarmStart); - RegisterZoneRequestHandler(Commands.TriggerMissionStructure); - - RegisterZoneRequestHandler(Commands.ZoneUploadScanResult); + _ = RegisterZoneRequestHandler(Commands.TeleportGetChannelList); + _ = RegisterZoneRequestHandler(Commands.TeleportToZoneObject); + _ = RegisterZoneRequestHandler(Commands.TeleportUse); + _ = RegisterZoneRequestHandler(Commands.TeleportQueryWorldChannels); + _ = RegisterZoneRequestHandler(Commands.JumpAnywhere); + _ = RegisterZoneRequestHandler(Commands.MovePlayer); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawStatMap); + _ = RegisterZoneRequestHandler(Commands.MissionStartFromZone); + _ = RegisterZoneRequestHandler(Commands.ItemShopBuy); + _ = RegisterZoneRequestHandler(Commands.ItemShopList); + _ = RegisterZoneRequestHandler(Commands.ZoneMoveUnit); + _ = RegisterZoneRequestHandler(Commands.ZoneGetQueueInfo); + _ = RegisterZoneRequestHandler(Commands.ZoneSetQueueLength); + _ = RegisterZoneRequestHandler(Commands.ZoneCancelEnterQueue); + _ = RegisterZoneRequestHandler(Commands.ZoneGetBuildings); + + _ = RegisterZoneRequestHandler(Commands.Dock); + + _ = RegisterZoneRequestHandler(Commands.ZoneDecorAdd); + _ = RegisterZoneRequestHandler(Commands.ZoneDecorSet); + _ = RegisterZoneRequestHandler(Commands.ZoneDecorDelete); + _ = RegisterZoneRequestHandler(Commands.ZoneDecorLock); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawDecorEnvironment); + _ = RegisterZoneRequestHandler(Commands.ZoneSampleDecorEnvironment); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawDecorEnvByDef); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawAllDecors); + _ = RegisterZoneRequestHandler(Commands.ZoneEnvironmentDescriptionList); + _ = RegisterZoneRequestHandler(Commands.ZoneSampleEnvironment); + _ = RegisterZoneRequestHandler(Commands.ZoneCreateTeleportColumn); + + _ = RegisterZoneRequestHandler(Commands.PackItems); + _ = RegisterZoneRequestHandler(Commands.UnpackItems); + _ = RegisterZoneRequestHandler(Commands.TrashItems); + _ = RegisterZoneRequestHandler(Commands.RelocateItems); + _ = RegisterZoneRequestHandler(Commands.StackItems); + _ = RegisterZoneRequestHandler(Commands.StackSelection); + _ = RegisterZoneRequestHandler(Commands.UnstackAmount); + _ = RegisterZoneRequestHandler(Commands.SetItemName); + _ = RegisterZoneRequestHandler(Commands.ListContainer); + _ = RegisterZoneRequestHandler(Commands.EquipModule); + _ = RegisterZoneRequestHandler(Commands.RemoveModule); + _ = RegisterZoneRequestHandler(Commands.ChangeModule); + _ = RegisterZoneRequestHandler(Commands.EquipAmmo); + _ = RegisterZoneRequestHandler(Commands.UnequipAmmo); + _ = RegisterZoneRequestHandler(Commands.ChangeAmmo); + + _ = RegisterZoneRequestHandler(Commands.MissionGetSupply); + _ = RegisterZoneRequestHandler(Commands.MissionSpotPlace); + _ = RegisterZoneRequestHandler(Commands.MissionSpotUpdate); + _ = RegisterZoneRequestHandler(Commands.ZoneUpdateStructure); + _ = RegisterZoneRequestHandler(Commands.RemoveMissionStructure); + _ = RegisterZoneRequestHandler(Commands.KioskInfo); + _ = RegisterZoneRequestHandler(Commands.KioskSubmitItem); + _ = RegisterZoneRequestHandler(Commands.AlarmStart); + _ = RegisterZoneRequestHandler(Commands.TriggerMissionStructure); + + _ = RegisterZoneRequestHandler(Commands.ZoneUploadScanResult); //admin - RegisterZoneRequestHandler(Commands.ZoneEntityChangeState); - RegisterZoneRequestHandler(Commands.ZoneRemoveByDefinition); - RegisterZoneRequestHandler(Commands.ZoneMakeGotoXY); - RegisterZoneRequestHandler(Commands.ZoneDrawBeam); - RegisterZoneRequestHandler(Commands.ZoneSetRuntimeZoneEntityName); - RegisterZoneRequestHandler(Commands.ZoneCheckRoaming); - RegisterZoneRequestHandler(Commands.ZonePBSTest); - RegisterZoneRequestHandler(Commands.ZonePBSFixOrphaned); - RegisterZoneRequestHandler(Commands.ZoneFixPBS); - RegisterZoneRequestHandler(Commands.ZoneServerMessage); - RegisterZoneRequestHandler(Commands.ZonePlaceWall); - RegisterZoneRequestHandler(Commands.ZoneClearWalls); - RegisterZoneRequestHandler(Commands.ZoneHealAllWalls); - RegisterZoneRequestHandler(Commands.ZoneTerraformTest); - RegisterZoneRequestHandler(Commands.ZoneForceDeconstruct); - RegisterZoneRequestHandler(Commands.ZoneSetReinforceCounter); - RegisterZoneRequestHandler(Commands.ZoneRestoreOriginalGamma); - RegisterZoneRequestHandler(Commands.ZoneSwitchDegrade); - RegisterZoneRequestHandler(Commands.ZoneKillNPlants); - RegisterZoneRequestHandler(Commands.ZoneDisplayMissionRandomPoints); - RegisterZoneRequestHandler(Commands.ZoneDisplayMissionSpots); - RegisterZoneRequestHandler(Commands.NpcCheckCondition); - RegisterZoneRequestHandler(Commands.ZoneClearLayer); - RegisterZoneRequestHandler(Commands.ZonePutPlant); - RegisterZoneRequestHandler(Commands.ZoneSetPlantsSpeed); - RegisterZoneRequestHandler(Commands.ZoneGetPlantsMode); - RegisterZoneRequestHandler(Commands.ZoneSetPlantsMode); - RegisterZoneRequestHandler(Commands.ZoneCreateGarden); - RegisterZoneRequestHandler(Commands.ZoneCreateIsland); - RegisterZoneRequestHandler(Commands.ZoneCreateTerraformLimit); - RegisterZoneRequestHandler(Commands.ZoneSetLayerWithBitMap); - RegisterZoneRequestHandler(Commands.ZoneDrawBlockingByDefinition); - RegisterZoneRequestHandler(Commands.ZoneCleanBlockingByDefinition); - RegisterZoneRequestHandler(Commands.ZoneCleanObstacleBlocking); - RegisterZoneRequestHandler(Commands.ZoneFillGroundTypeRandom); - - - - RegisterZoneRequestHandler(Commands.NpcListSafeSpawnPoint); - RegisterZoneRequestHandler(Commands.NpcPlaceSafeSpawnPoint); - RegisterZoneRequestHandler(Commands.NpcAddSafeSpawnPoint); - RegisterZoneRequestHandler(Commands.NpcSetSafeSpawnPoint); - RegisterZoneRequestHandler(Commands.NpcDeleteSafeSpawnPoint); - RegisterZoneRequestHandler(Commands.ZoneListPresences); - RegisterZoneRequestHandler(Commands.ZoneNpcFlockNew); - RegisterZoneRequestHandler(Commands.ZoneNpcFlockSet); - RegisterZoneRequestHandler(Commands.ZoneNpcFlockDelete); - RegisterZoneRequestHandler(Commands.ZoneNpcFlockKill); - RegisterZoneRequestHandler(Commands.ZoneNpcFlockSetParameter); - - RegisterZoneRequestHandler(Commands.GetRifts); - RegisterZoneRequestHandler(Commands.UseItem); - RegisterZoneRequestHandler(Commands.GateSetName); - RegisterZoneRequestHandler(Commands.ProximityProbeRemove); - RegisterZoneRequestHandler(Commands.FieldTerminalInfo); - - RegisterZoneRequestHandler(Commands.PBSFeedableInfo); - RegisterZoneRequestHandler(Commands.PBSFeedItems); - RegisterZoneRequestHandler(Commands.PBSMakeConnection); - RegisterZoneRequestHandler(Commands.PBSBreakConnection); - RegisterZoneRequestHandler(Commands.PBSRenameNode); - RegisterZoneRequestHandler(Commands.PBSSetConnectionWeight); - RegisterZoneRequestHandler(Commands.PBSSetOnline); - RegisterZoneRequestHandler(Commands.PBSGetNetwork); - RegisterZoneRequestHandler(Commands.PBSCheckDeployment); - RegisterZoneRequestHandler(Commands.PBSSetStandingLimit); - RegisterZoneRequestHandler(Commands.PBSNodeInfo); - RegisterZoneRequestHandler(Commands.PBSGetTerritories); - RegisterZoneRequestHandler(Commands.PBSSetTerritoryVisibility); - RegisterZoneRequestHandler(Commands.PBSSetBaseDeconstruct); - RegisterZoneRequestHandler(Commands.PBSSetReinforceOffset); - RegisterZoneRequestHandler(Commands.PBSSetEffect); - RegisterZoneRequestHandler(Commands.ZoneDrawRamp); - RegisterZoneRequestHandler(Commands.ZoneSmooth); + _ = RegisterZoneRequestHandler(Commands.ZoneEntityChangeState); + _ = RegisterZoneRequestHandler(Commands.ZoneRemoveByDefinition); + _ = RegisterZoneRequestHandler(Commands.ZoneMakeGotoXY); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawBeam); + _ = RegisterZoneRequestHandler(Commands.ZoneSetRuntimeZoneEntityName); + _ = RegisterZoneRequestHandler(Commands.ZoneCheckRoaming); + _ = RegisterZoneRequestHandler(Commands.ZonePBSTest); + _ = RegisterZoneRequestHandler(Commands.ZonePBSFixOrphaned); + _ = RegisterZoneRequestHandler(Commands.ZoneFixPBS); + _ = RegisterZoneRequestHandler(Commands.ZoneServerMessage); + _ = RegisterZoneRequestHandler(Commands.ZonePlaceWall); + _ = RegisterZoneRequestHandler(Commands.ZoneClearWalls); + _ = RegisterZoneRequestHandler(Commands.ZoneHealAllWalls); + _ = RegisterZoneRequestHandler(Commands.ZoneTerraformTest); + _ = RegisterZoneRequestHandler(Commands.ZoneForceDeconstruct); + _ = RegisterZoneRequestHandler(Commands.ZoneSetReinforceCounter); + _ = RegisterZoneRequestHandler(Commands.ZoneRestoreOriginalGamma); + _ = RegisterZoneRequestHandler(Commands.ZoneSwitchDegrade); + _ = RegisterZoneRequestHandler(Commands.ZoneKillNPlants); + _ = RegisterZoneRequestHandler(Commands.ZoneDisplayMissionRandomPoints); + _ = RegisterZoneRequestHandler(Commands.ZoneDisplayMissionSpots); + _ = RegisterZoneRequestHandler(Commands.NpcCheckCondition); + _ = RegisterZoneRequestHandler(Commands.ZoneClearLayer); + _ = RegisterZoneRequestHandler(Commands.ZonePutPlant); + _ = RegisterZoneRequestHandler(Commands.ZoneSetPlantsSpeed); + _ = RegisterZoneRequestHandler(Commands.ZoneGetPlantsMode); + _ = RegisterZoneRequestHandler(Commands.ZoneSetPlantsMode); + _ = RegisterZoneRequestHandler(Commands.ZoneCreateGarden); + _ = RegisterZoneRequestHandler(Commands.ZoneCreateIsland); + _ = RegisterZoneRequestHandler(Commands.ZoneCreateTerraformLimit); + _ = RegisterZoneRequestHandler(Commands.ZoneSetLayerWithBitMap); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawBlockingByDefinition); + _ = RegisterZoneRequestHandler(Commands.ZoneCleanBlockingByDefinition); + _ = RegisterZoneRequestHandler(Commands.ZoneCleanObstacleBlocking); + _ = RegisterZoneRequestHandler(Commands.ZoneFillGroundTypeRandom); + + + + _ = RegisterZoneRequestHandler(Commands.NpcListSafeSpawnPoint); + _ = RegisterZoneRequestHandler(Commands.NpcPlaceSafeSpawnPoint); + _ = RegisterZoneRequestHandler(Commands.NpcAddSafeSpawnPoint); + _ = RegisterZoneRequestHandler(Commands.NpcSetSafeSpawnPoint); + _ = RegisterZoneRequestHandler(Commands.NpcDeleteSafeSpawnPoint); + _ = RegisterZoneRequestHandler(Commands.ZoneListPresences); + _ = RegisterZoneRequestHandler(Commands.ZoneNpcFlockNew); + _ = RegisterZoneRequestHandler(Commands.ZoneNpcFlockSet); + _ = RegisterZoneRequestHandler(Commands.ZoneNpcFlockDelete); + _ = RegisterZoneRequestHandler(Commands.ZoneNpcFlockKill); + _ = RegisterZoneRequestHandler(Commands.ZoneNpcFlockSetParameter); + + _ = RegisterZoneRequestHandler(Commands.GetRifts); + _ = RegisterZoneRequestHandler(Commands.UseItem); + _ = RegisterZoneRequestHandler(Commands.GateSetName); + + _ = RegisterZoneRequestHandler(Commands.ProximityProbeRemove); + + _ = RegisterZoneRequestHandler(Commands.FieldTerminalInfo); + + _ = RegisterZoneRequestHandler(Commands.PBSFeedableInfo); + _ = RegisterZoneRequestHandler(Commands.PBSFeedItems); + _ = RegisterZoneRequestHandler(Commands.PBSMakeConnection); + _ = RegisterZoneRequestHandler(Commands.PBSBreakConnection); + _ = RegisterZoneRequestHandler(Commands.PBSRenameNode); + _ = RegisterZoneRequestHandler(Commands.PBSSetConnectionWeight); + _ = RegisterZoneRequestHandler(Commands.PBSSetOnline); + _ = RegisterZoneRequestHandler(Commands.PBSGetNetwork); + _ = RegisterZoneRequestHandler(Commands.PBSCheckDeployment); + _ = RegisterZoneRequestHandler(Commands.PBSSetStandingLimit); + _ = RegisterZoneRequestHandler(Commands.PBSNodeInfo); + _ = RegisterZoneRequestHandler(Commands.PBSGetTerritories); + _ = RegisterZoneRequestHandler(Commands.PBSSetTerritoryVisibility); + _ = RegisterZoneRequestHandler(Commands.PBSSetBaseDeconstruct); + _ = RegisterZoneRequestHandler(Commands.PBSSetReinforceOffset); + _ = RegisterZoneRequestHandler(Commands.PBSSetEffect); + _ = RegisterZoneRequestHandler(Commands.ZoneDrawRamp); + _ = RegisterZoneRequestHandler(Commands.ZoneSmooth); } private void RegisterPBS() { - _builder.RegisterGeneric(typeof(PBSObjectHelper<>)); - _builder.RegisterGeneric(typeof(PBSReinforceHandler<>)); - _builder.RegisterType(); + _ = _builder.RegisterGeneric(typeof(PBSObjectHelper<>)); + _ = _builder.RegisterGeneric(typeof(PBSReinforceHandler<>)); + _ = _builder.RegisterType(); } } } \ No newline at end of file diff --git a/src/Perpetuum.ExportedTypes/AggregateField.cs b/src/Perpetuum.ExportedTypes/AggregateField.cs index feaaef482..1797a52a1 100644 --- a/src/Perpetuum.ExportedTypes/AggregateField.cs +++ b/src/Perpetuum.ExportedTypes/AggregateField.cs @@ -5,428 +5,440 @@ namespace Perpetuum.ExportedTypes { - public enum AggregateField - { - undefined = 0, - accuracy = 1, - accuracy_modifier = 2, - aggrorange = 7, - aggrorange_modifier = 8, - ammo_reload_time = 9, - ammo_reload_time_modifier = 10, - aoe_explosion_radius = 12, - aoe_explosion_radius_modifier = 13, - armor_current = 575, - armor_max = 16, - armor_max_modifier = 17, - armor_repair_amount = 19, - armor_repair_amount_modifier = 20, - armor_repair_cycle_time_modifier = 22, - armor_repair_optimal_range_modifier = 23, - blob_effect = 595, - blob_emission = 587, - blob_emission_modifier = 590, - blob_emission_modifier_modifier = 598, - blob_emission_radius = 588, - blob_emission_radius_modifier = 591, - blob_level_high = 593, - blob_level_high_modifier = 594, - blob_level_low = 589, - blob_level_low_modifier = 592, - chemical_damage_to_core_modifier = 621, - construction_charge_amount = 647, + public enum AggregateField + { + undefined = 0, + accuracy = 1, + accuracy_modifier = 2, + aggrorange = 7, + aggrorange_modifier = 8, + ammo_reload_time = 9, + ammo_reload_time_modifier = 10, + aoe_explosion_radius = 12, + aoe_explosion_radius_modifier = 13, + armor_current = 575, + armor_max = 16, + armor_max_modifier = 17, + armor_repair_amount = 19, + armor_repair_amount_modifier = 20, + armor_repair_cycle_time_modifier = 22, + armor_repair_optimal_range_modifier = 23, + blob_effect = 595, + blob_emission = 587, + blob_emission_modifier = 590, + blob_emission_modifier_modifier = 598, + blob_emission_radius = 588, + blob_emission_radius_modifier = 591, + blob_level_high = 593, + blob_level_high_modifier = 594, + blob_level_low = 589, + blob_level_low_modifier = 592, + chemical_damage_to_core_modifier = 621, + construction_charge_amount = 647, construction_charge_techmax = 666, control_speed_boost_time_add = 505, - core_added = 24, - core_current = 574, - core_max = 26, - core_max_modifier = 27, - core_recharge_time = 29, - core_recharge_time_modifier = 30, - core_usage = 32, - core_usage_armor_hardener_modifier = 33, - core_usage_armor_repair_modifier = 34, - core_usage_cargo_scanner_modifier = 35, - core_usage_chassis_scanner_modifier = 36, - core_usage_cloaking_modifier = 37, - core_usage_detection_modul_modifier = 610, - core_usage_drillers_modifier = 38, - core_usage_energy_neutralizers_modifier = 39, - core_usage_energy_transfers_modifier = 40, - core_usage_energy_vampires_modifier = 41, - core_usage_energytorpedo_modifier = 42, - core_usage_gang_assist_module_modifier = 658, - core_usage_harvester_modifier = 43, - core_usage_industrial_aoe_modifier = 44, - core_usage_industrial_scanner_modifier = 45, - core_usage_ioncannon_modifier = 46, - core_usage_laser_modifier = 47, - core_usage_missile_modifier = 657, - core_usage_plasma_modifier = 48, - core_usage_projectile_modifier = 656, - core_usage_railgun_modifier = 49, - core_usage_remote_armor_repair_modifier = 50, - core_usage_remote_sensor_booster_modifier = 51, - core_usage_sensor_booster_modifier = 53, - core_usage_sensor_dampener_modifier = 54, - core_usage_sensor_jammer_modifier = 55, - core_usage_shield_generator_modifier = 56, - core_usage_shield_hardener_modifier = 57, - core_usage_stealth_modul_modifier = 612, - core_usage_terraformer_modifier = 58, - core_usage_weapon_modifier = 59, - core_usage_webber_modifier = 60, - cpu_current = 61, - cpu_max = 62, - cpu_max_modifier = 63, - cpu_usage = 64, - cpu_usage_armor_modifier = 65, - cpu_usage_detection_modul_modifier = 609, - cpu_usage_engineering_modifier = 66, - cpu_usage_ew_modifier = 67, - cpu_usage_gathering_modifier = 68, - cpu_usage_large_energy_neutralizer_modifier = 69, - cpu_usage_large_energy_transfer_modifier = 70, - cpu_usage_large_energy_vampire_modifier = 71, - cpu_usage_large_energytorpedo_modifier = 72, - cpu_usage_large_industrial_aoe_modifier = 73, - cpu_usage_large_ioncannon_modifier = 74, - cpu_usage_large_laser_modifier = 75, - cpu_usage_large_missile_modifier = 76, - cpu_usage_large_plasma_modifier = 77, - cpu_usage_large_projectile_modifier = 78, - cpu_usage_large_railgun_modifier = 79, - cpu_usage_medium_energy_neutralizer_modifier = 80, - cpu_usage_medium_energy_transfer_modifier = 81, - cpu_usage_medium_energy_vampire_modifier = 82, - cpu_usage_medium_energytorpedo_modifier = 83, - cpu_usage_medium_industrial_aoe_modifier = 84, - cpu_usage_medium_ioncannon_modifier = 85, - cpu_usage_medium_laser_modifier = 86, - cpu_usage_medium_missile_modifier = 87, - cpu_usage_medium_plasma_modifier = 88, - cpu_usage_medium_projectile_modifier = 89, - cpu_usage_medium_railgun_modifier = 90, - cpu_usage_mining_modifier = 91, - cpu_usage_remote_sensor_booster_modifier = 92, - cpu_usage_sensor_booster_modifier = 94, - cpu_usage_shield_generators_modifier = 581, - cpu_usage_small_energy_neutralizer_modifier = 95, - cpu_usage_small_energy_transfer_modifier = 96, - cpu_usage_small_energy_vampire_modifier = 97, - cpu_usage_small_energytorpedo_modifier = 98, - cpu_usage_small_industrial_aoe_modifier = 99, - cpu_usage_small_ioncannon_modifier = 100, - cpu_usage_small_laser_modifier = 101, - cpu_usage_small_missile_modifier = 102, - cpu_usage_small_plasma_modifier = 103, - cpu_usage_small_projectile_modifier = 104, - cpu_usage_small_railgun_modifier = 105, - cpu_usage_stealth_modul_modifier = 611, - cpu_usage_weapons_modifier = 106, - critical_damage_modifier = 645, - critical_damage_modifier_modifier = 646, - critical_hit_chance = 107, - critical_hit_chance_modifier = 108, - cycle_time = 110, - damage_chemical = 112, - damage_energytorpedo_modifier = 114, - damage_explosive = 115, - damage_industrial_aoe_modifier = 117, - damage_ioncannon_modifier = 122, - damage_kinetic = 123, - damage_large_energytorpedo_modifier = 125, - damage_large_industrial_aoe_modifier = 126, - damage_large_ioncannon_modifier = 127, - damage_large_laser_modifier = 128, - damage_large_missile_modifier = 129, - damage_large_plasma_modifier = 130, - damage_large_projectile_modifier = 131, - damage_large_railgun_modifier = 132, - damage_laser_modifier = 133, - damage_medium_energytorpedo_modifier = 134, - damage_medium_industrial_aoe_modifier = 135, - damage_medium_ioncannon_modifier = 136, - damage_medium_laser_modifier = 137, - damage_medium_missile_modifier = 138, - damage_medium_plasma_modifier = 139, - damage_medium_projectile_modifier = 140, - damage_medium_railgun_modifier = 141, - damage_missile_modifier = 142, - damage_modifier = 143, - damage_plasma_modifier = 145, - damage_projectile_modifier = 146, - damage_railgun_modifier = 147, - damage_small_energytorpedo_modifier = 148, - damage_small_industrial_aoe_modifier = 149, - damage_small_ioncannon_modifier = 150, - damage_small_laser_modifier = 151, - damage_small_missile_modifier = 152, - damage_small_plasma_modifier = 153, - damage_small_projectile_modifier = 154, - damage_small_railgun_modifier = 155, - damage_thermal = 156, + core_added = 24, + core_current = 574, + core_max = 26, + core_max_modifier = 27, + core_recharge_time = 29, + core_recharge_time_modifier = 30, + core_usage = 32, + core_usage_armor_hardener_modifier = 33, + core_usage_armor_repair_modifier = 34, + core_usage_cargo_scanner_modifier = 35, + core_usage_chassis_scanner_modifier = 36, + core_usage_cloaking_modifier = 37, + core_usage_detection_modul_modifier = 610, + core_usage_drillers_modifier = 38, + core_usage_energy_neutralizers_modifier = 39, + core_usage_energy_transfers_modifier = 40, + core_usage_energy_vampires_modifier = 41, + core_usage_energytorpedo_modifier = 42, + core_usage_gang_assist_module_modifier = 658, + core_usage_harvester_modifier = 43, + core_usage_industrial_aoe_modifier = 44, + core_usage_industrial_scanner_modifier = 45, + core_usage_ioncannon_modifier = 46, + core_usage_laser_modifier = 47, + core_usage_missile_modifier = 657, + core_usage_plasma_modifier = 48, + core_usage_projectile_modifier = 656, + core_usage_railgun_modifier = 49, + core_usage_remote_armor_repair_modifier = 50, + core_usage_remote_sensor_booster_modifier = 51, + core_usage_sensor_booster_modifier = 53, + core_usage_sensor_dampener_modifier = 54, + core_usage_sensor_jammer_modifier = 55, + core_usage_shield_generator_modifier = 56, + core_usage_shield_hardener_modifier = 57, + core_usage_stealth_modul_modifier = 612, + core_usage_terraformer_modifier = 58, + core_usage_weapon_modifier = 59, + core_usage_webber_modifier = 60, + cpu_current = 61, + cpu_max = 62, + cpu_max_modifier = 63, + cpu_usage = 64, + cpu_usage_armor_modifier = 65, + cpu_usage_detection_modul_modifier = 609, + cpu_usage_engineering_modifier = 66, + cpu_usage_ew_modifier = 67, + cpu_usage_gathering_modifier = 68, + cpu_usage_large_energy_neutralizer_modifier = 69, + cpu_usage_large_energy_transfer_modifier = 70, + cpu_usage_large_energy_vampire_modifier = 71, + cpu_usage_large_energytorpedo_modifier = 72, + cpu_usage_large_industrial_aoe_modifier = 73, + cpu_usage_large_ioncannon_modifier = 74, + cpu_usage_large_laser_modifier = 75, + cpu_usage_large_missile_modifier = 76, + cpu_usage_large_plasma_modifier = 77, + cpu_usage_large_projectile_modifier = 78, + cpu_usage_large_railgun_modifier = 79, + cpu_usage_medium_energy_neutralizer_modifier = 80, + cpu_usage_medium_energy_transfer_modifier = 81, + cpu_usage_medium_energy_vampire_modifier = 82, + cpu_usage_medium_energytorpedo_modifier = 83, + cpu_usage_medium_industrial_aoe_modifier = 84, + cpu_usage_medium_ioncannon_modifier = 85, + cpu_usage_medium_laser_modifier = 86, + cpu_usage_medium_missile_modifier = 87, + cpu_usage_medium_plasma_modifier = 88, + cpu_usage_medium_projectile_modifier = 89, + cpu_usage_medium_railgun_modifier = 90, + cpu_usage_mining_modifier = 91, + cpu_usage_remote_sensor_booster_modifier = 92, + cpu_usage_sensor_booster_modifier = 94, + cpu_usage_shield_generators_modifier = 581, + cpu_usage_small_energy_neutralizer_modifier = 95, + cpu_usage_small_energy_transfer_modifier = 96, + cpu_usage_small_energy_vampire_modifier = 97, + cpu_usage_small_energytorpedo_modifier = 98, + cpu_usage_small_industrial_aoe_modifier = 99, + cpu_usage_small_ioncannon_modifier = 100, + cpu_usage_small_laser_modifier = 101, + cpu_usage_small_missile_modifier = 102, + cpu_usage_small_plasma_modifier = 103, + cpu_usage_small_projectile_modifier = 104, + cpu_usage_small_railgun_modifier = 105, + cpu_usage_stealth_modul_modifier = 611, + cpu_usage_weapons_modifier = 106, + critical_damage_modifier = 645, + critical_damage_modifier_modifier = 646, + critical_hit_chance = 107, + critical_hit_chance_modifier = 108, + cycle_time = 110, + damage_chemical = 112, + damage_energytorpedo_modifier = 114, + damage_explosive = 115, + damage_industrial_aoe_modifier = 117, + damage_ioncannon_modifier = 122, + damage_kinetic = 123, + damage_large_energytorpedo_modifier = 125, + damage_large_industrial_aoe_modifier = 126, + damage_large_ioncannon_modifier = 127, + damage_large_laser_modifier = 128, + damage_large_missile_modifier = 129, + damage_large_plasma_modifier = 130, + damage_large_projectile_modifier = 131, + damage_large_railgun_modifier = 132, + damage_laser_modifier = 133, + damage_medium_energytorpedo_modifier = 134, + damage_medium_industrial_aoe_modifier = 135, + damage_medium_ioncannon_modifier = 136, + damage_medium_laser_modifier = 137, + damage_medium_missile_modifier = 138, + damage_medium_plasma_modifier = 139, + damage_medium_projectile_modifier = 140, + damage_medium_railgun_modifier = 141, + damage_missile_modifier = 142, + damage_modifier = 143, + damage_plasma_modifier = 145, + damage_projectile_modifier = 146, + damage_railgun_modifier = 147, + damage_small_energytorpedo_modifier = 148, + damage_small_industrial_aoe_modifier = 149, + damage_small_ioncannon_modifier = 150, + damage_small_laser_modifier = 151, + damage_small_missile_modifier = 152, + damage_small_plasma_modifier = 153, + damage_small_projectile_modifier = 154, + damage_small_railgun_modifier = 155, + damage_thermal = 156, damage_toxic = 660, damage_toxic_modifier = 661, damage_turret_modifier = 158, - decay_chance = 613, - default_effect_range = 585, - despawn_time = 580, - detection_range = 599, - detection_range_modifier = 600, - detection_strength = 601, - detection_strength_modifier = 602, - devastate_resilience = 510, - devastate_resilience_modifier = 511, - devastating_chance = 507, - devastating_chance_modifier = 508, - ecm_strength = 162, - ecm_strength_modifier = 163, - effect_armor_max_modifier = 165, - effect_aura_radius = 536, - effect_aura_radius_modifier = 537, - effect_blob_emission_modifier = 596, - effect_blob_emission_radius_modifier = 597, - effect_core_recharge_time_modifier = 166, - effect_core_usage_gathering_modifier = 530, - effect_critical_hit_chance_modifier = 533, - effect_detection_strength_modifier = 605, - effect_devastate_resilience_modifier = 535, - effect_devastating_chance_modifier = 534, - effect_enhancer_aura_radius_modifier = 539, - effect_enhancer_detection_strength_modifier = 606, - effect_enhancer_lock_resist_modifier = 630, - effect_enhancer_massiveness_modifier = 632, - effect_enhancer_sensor_booster_locking_range_modifier = 167, - effect_enhancer_sensor_booster_locking_time_modifier = 168, - effect_enhancer_sensor_dampener_locking_range_modifier = 169, - effect_enhancer_sensor_dampener_locking_time_modifier = 170, - effect_enhancer_sensor_strength_modifier = 631, - effect_enhancer_speed_max_modifier = 171, - effect_enhancer_stealth_strength_modifier = 608, - effect_ew_optimal_range_modifier = 529, - effect_gathering_cycle_time_modifier = 544, - effect_harvesting_amount_modifier = 636, - effect_harvesting_cycle_time_modifier = 172, - effect_lock_resist = 629, - effect_locking_range_modifier = 173, - effect_locking_time_modifier = 531, - effect_massiveness = 625, - effect_massivness_speed_max_modifier = 623, - effect_mining_amount_modifier = 635, - effect_mining_cycle_time_modifier = 174, - effect_mining_probe_accuracy_modifier = 637, - effect_missile_range_modifier = 653, - effect_optimal_range_modifier = 175, - effect_repair_amount_modifier = 532, - effect_resist_chemical = 176, - effect_resist_explosive = 177, - effect_resist_kinetic = 178, - effect_resist_thermal = 179, - effect_sensor_booster_locking_range_modifier = 180, - effect_sensor_booster_locking_time_modifier = 181, - effect_sensor_dampener_locking_range_modifier = 182, - effect_sensor_dampener_locking_time_modifier = 183, - effect_sensor_strength_modifier = 626, - effect_shield_absorbtion_modifier = 184, - effect_signature_radius_modifier = 185, - effect_speed_highway_modifier = 622, - effect_speed_max_add = 503, - effect_speed_max_modifier = 186, - effect_stealth_strength_modifier = 607, - effect_weapon_cycle_time_modifier = 528, - energy_dispersion = 545, - energy_dispersion_modifier = 546, - energy_neutralized_amount = 187, - energy_neutralized_amount_modifier = 188, - energy_neutralizer_optimal_range_modifier = 190, - energy_transfer_amount = 191, - energy_transfer_amount_modifier = 192, - energy_transferer_optimal_range_modifier = 194, - energy_vampire_optimal_range_modifier = 195, - energy_vampired_amount = 196, - energy_vampired_amount_modifier = 197, - energytorpedo_cycle_time_modifier = 199, - energytorpedo_falloff_modifier = 200, - energytorpedo_optimal_range_modifier = 201, - engineering_cycle_time_modifier = 202, - engineering_optimal_range_modifier = 624, - ew_optimal_range_modifier = 203, - explosion_radius = 204, - explosion_radius_modifier = 205, - explosive_damage_to_core_modifier = 620, - falloff = 207, - falloff_modifier = 208, - gang_effect_enhancer_armor_max_modifier = 516, - gang_effect_enhancer_core_recharge_time_modifier = 523, - gang_effect_enhancer_core_usage_gathering_modifier = 517, - gang_effect_enhancer_critical_hit_chance_modifier = 522, - gang_effect_enhancer_devastating_chance_modifier = 526, - gang_effect_enhancer_ew_optimal_range_modifier = 515, - gang_effect_enhancer_gathering_cycle_time_modifier = 524, - gang_effect_enhancer_locking_range_modifier = 518, - gang_effect_enhancer_locking_time_modifier = 519, - gang_effect_enhancer_repair_amount_modifier = 521, - gang_effect_enhancer_resilience_modifier = 527, - gang_effect_enhancer_shield_absorbtion_ratio_modifier = 525, - gang_effect_enhancer_signature_radius_modifier = 520, - gang_effect_enhancer_speed_max_modifier = 513, - gang_effect_enhancer_weapon_cycle_time_modifier = 514, - gathering_cycle_time_modifier = 542, - harvesting_amount_electroplant_modifier = 614, - harvesting_amount_helioptris_modifier = 210, - harvesting_amount_modifier = 211, - harvesting_amount_prismocitae_modifier = 212, - harvesting_amount_triandlus_modifier = 214, - harvesting_cycle_time_modifier = 215, - industrial_aoe_cycle_time_modifier = 216, - industrial_aoe_optimal_range_modifier_modifier = 217, - ioncannon_cycle_time_modifier = 218, - ioncannon_falloff_modifier = 219, - ioncannon_optimal_range_modifier = 220, - kinetic_damage_to_core_modifier = 618, - laser_ammo_cycle_time_modifier = 640, - laser_cycle_time_modifier = 221, - laser_falloff_modifier = 222, - laser_optimal_range_modifier = 223, - least_optimal = 338, - least_optimal_modifier = 340, - lock_resist = 627, - lock_resist_modifier = 628, - locked_targets_current = 224, - locked_targets_max = 225, - locked_targets_max_bonus = 226, - locking_range = 228, - locking_range_modifier = 229, - locking_time = 231, - locking_time_modifier = 232, - mass = 4, - mass_modifier = 5, - massiveness = 582, - massiveness_modifier = 583, - mining_amount_crude_modifier = 234, - mining_amount_epriton_modifier = 235, + decay_chance = 613, + default_effect_range = 585, + despawn_time = 580, + detection_range = 599, + detection_range_modifier = 600, + detection_strength = 601, + detection_strength_modifier = 602, + devastate_resilience = 510, + devastate_resilience_modifier = 511, + devastating_chance = 507, + devastating_chance_modifier = 508, + ecm_strength = 162, + ecm_strength_modifier = 163, + effect_armor_max_modifier = 165, + effect_aura_radius = 536, + effect_aura_radius_modifier = 537, + effect_blob_emission_modifier = 596, + effect_blob_emission_radius_modifier = 597, + effect_core_recharge_time_modifier = 166, + effect_core_usage_gathering_modifier = 530, + effect_critical_hit_chance_modifier = 533, + effect_detection_strength_modifier = 605, + effect_devastate_resilience_modifier = 535, + effect_devastating_chance_modifier = 534, + effect_enhancer_aura_radius_modifier = 539, + effect_enhancer_detection_strength_modifier = 606, + effect_enhancer_lock_resist_modifier = 630, + effect_enhancer_massiveness_modifier = 632, + effect_enhancer_sensor_booster_locking_range_modifier = 167, + effect_enhancer_sensor_booster_locking_time_modifier = 168, + effect_enhancer_sensor_dampener_locking_range_modifier = 169, + effect_enhancer_sensor_dampener_locking_time_modifier = 170, + effect_enhancer_sensor_strength_modifier = 631, + effect_enhancer_speed_max_modifier = 171, + effect_enhancer_stealth_strength_modifier = 608, + effect_ew_optimal_range_modifier = 529, + effect_gathering_cycle_time_modifier = 544, + effect_harvesting_amount_modifier = 636, + effect_harvesting_cycle_time_modifier = 172, + effect_lock_resist = 629, + effect_locking_range_modifier = 173, + effect_locking_time_modifier = 531, + effect_massiveness = 625, + effect_massivness_speed_max_modifier = 623, + effect_mining_amount_modifier = 635, + effect_mining_cycle_time_modifier = 174, + effect_mining_probe_accuracy_modifier = 637, + effect_missile_range_modifier = 653, + effect_optimal_range_modifier = 175, + effect_repair_amount_modifier = 532, + effect_resist_chemical = 176, + effect_resist_explosive = 177, + effect_resist_kinetic = 178, + effect_resist_thermal = 179, + effect_sensor_booster_locking_range_modifier = 180, + effect_sensor_booster_locking_time_modifier = 181, + effect_sensor_dampener_locking_range_modifier = 182, + effect_sensor_dampener_locking_time_modifier = 183, + trigger_mass = 667, + mine_detection_range = 668, + mine_detection_range_modifier = 669, + effect_mine_detection_range_modifier = 670, + effect_enhancer_mine_detection_range_modifier = 671, + effect_sensor_strength_modifier = 626, + effect_shield_absorbtion_modifier = 184, + effect_signature_radius_modifier = 185, + effect_speed_highway_modifier = 622, + effect_speed_max_add = 503, + effect_speed_max_modifier = 186, + effect_stealth_strength_modifier = 607, + effect_weapon_cycle_time_modifier = 528, + energy_dispersion = 545, + energy_dispersion_modifier = 546, + energy_neutralized_amount = 187, + energy_neutralized_amount_modifier = 188, + energy_neutralizer_optimal_range_modifier = 190, + energy_transfer_amount = 191, + energy_transfer_amount_modifier = 192, + energy_transferer_optimal_range_modifier = 194, + energy_vampire_optimal_range_modifier = 195, + energy_vampired_amount = 196, + energy_vampired_amount_modifier = 197, + energytorpedo_cycle_time_modifier = 199, + energytorpedo_falloff_modifier = 200, + energytorpedo_optimal_range_modifier = 201, + engineering_cycle_time_modifier = 202, + engineering_optimal_range_modifier = 624, + ew_optimal_range_modifier = 203, + explosion_radius = 204, + explosion_radius_modifier = 205, + explosive_damage_to_core_modifier = 620, + falloff = 207, + falloff_modifier = 208, + gang_effect_enhancer_armor_max_modifier = 516, + gang_effect_enhancer_core_recharge_time_modifier = 523, + gang_effect_enhancer_core_usage_gathering_modifier = 517, + gang_effect_enhancer_critical_hit_chance_modifier = 522, + gang_effect_enhancer_devastating_chance_modifier = 526, + gang_effect_enhancer_ew_optimal_range_modifier = 515, + gang_effect_enhancer_gathering_cycle_time_modifier = 524, + gang_effect_enhancer_locking_range_modifier = 518, + gang_effect_enhancer_locking_time_modifier = 519, + gang_effect_enhancer_repair_amount_modifier = 521, + gang_effect_enhancer_resilience_modifier = 527, + gang_effect_enhancer_shield_absorbtion_ratio_modifier = 525, + gang_effect_enhancer_signature_radius_modifier = 520, + gang_effect_enhancer_speed_max_modifier = 513, + gang_effect_enhancer_weapon_cycle_time_modifier = 514, + gathering_cycle_time_modifier = 542, + harvesting_amount_electroplant_modifier = 614, + harvesting_amount_helioptris_modifier = 210, + harvesting_amount_modifier = 211, + harvesting_amount_prismocitae_modifier = 212, + harvesting_amount_triandlus_modifier = 214, + harvesting_cycle_time_modifier = 215, + industrial_aoe_cycle_time_modifier = 216, + industrial_aoe_optimal_range_modifier_modifier = 217, + ioncannon_cycle_time_modifier = 218, + ioncannon_falloff_modifier = 219, + ioncannon_optimal_range_modifier = 220, + kinetic_damage_to_core_modifier = 618, + laser_ammo_cycle_time_modifier = 640, + laser_cycle_time_modifier = 221, + laser_falloff_modifier = 222, + laser_optimal_range_modifier = 223, + least_optimal = 338, + least_optimal_modifier = 340, + lock_resist = 627, + lock_resist_modifier = 628, + locked_targets_current = 224, + locked_targets_max = 225, + locked_targets_max_bonus = 226, + locking_range = 228, + locking_range_modifier = 229, + locking_time = 231, + locking_time_modifier = 232, + mass = 4, + mass_modifier = 5, + massiveness = 582, + massiveness_modifier = 583, + mining_amount_crude_modifier = 234, + mining_amount_epriton_modifier = 235, mining_amount_flux_modifier = 662, - mining_amount_gammaterial_modifier = 649, - mining_amount_imentium_modifier = 236, - mining_amount_liquizit_modifier = 237, - mining_amount_modifier = 238, - mining_amount_silgium_modifier = 648, - mining_amount_stermonit_modifier = 240, - mining_amount_titan_modifier = 241, - mining_cycle_time_crude_modifier = 242, - mining_cycle_time_epriton_modifier = 243, + mining_amount_gammaterial_modifier = 649, + mining_amount_imentium_modifier = 236, + mining_amount_liquizit_modifier = 237, + mining_amount_modifier = 238, + mining_amount_silgium_modifier = 648, + mining_amount_stermonit_modifier = 240, + mining_amount_titan_modifier = 241, + mining_cycle_time_crude_modifier = 242, + mining_cycle_time_epriton_modifier = 243, mining_cycle_time_flux_modifier = 663, - mining_cycle_time_gammaterial_modifier = 651, - mining_cycle_time_imentium_modifier = 244, - mining_cycle_time_liquizit_modifier = 245, - mining_cycle_time_modifier = 246, - mining_cycle_time_silgium_modifier = 650, - mining_cycle_time_stermonit_modifier = 247, - mining_cycle_time_titan_modifier = 248, - mining_probe_accuracy = 249, - mining_probe_accuracy_modifier = 250, - mining_probe_artifact_range = 615, - mining_probe_artifact_range_modifier = 616, - mining_probe_cycle_time_intrusion_modifier = 638, - mining_probe_intrusion_range = 633, - mining_probe_intrusion_range_modifier = 634, - mining_probe_range = 617, - mining_probe_tile_range_modifier = 252, - missile_ammo_cycle_time_modifier = 641, - missile_cycle_time_modifier = 253, - missile_miss = 341, - missile_miss_modifier = 342, + mining_cycle_time_gammaterial_modifier = 651, + mining_cycle_time_imentium_modifier = 244, + mining_cycle_time_liquizit_modifier = 245, + mining_cycle_time_modifier = 246, + mining_cycle_time_silgium_modifier = 650, + mining_cycle_time_stermonit_modifier = 247, + mining_cycle_time_titan_modifier = 248, + mining_probe_accuracy = 249, + mining_probe_accuracy_modifier = 250, + mining_probe_artifact_range = 615, + mining_probe_artifact_range_modifier = 616, + mining_probe_cycle_time_intrusion_modifier = 638, + mining_probe_intrusion_range = 633, + mining_probe_intrusion_range_modifier = 634, + mining_probe_range = 617, + mining_probe_tile_range_modifier = 252, + missile_ammo_cycle_time_modifier = 641, + missile_cycle_time_modifier = 253, + missile_miss = 341, + missile_miss_modifier = 342, missile_falloff_modifier = 658, missile_range_modifier = 254, - mobile_teleport_cooldown = 579, - mobile_teleport_range = 577, + mobile_teleport_cooldown = 579, + mobile_teleport_range = 577, module_missile_falloff_modifier = 659, module_missile_range_modifier = 586, - optimal_range = 255, - optimal_range_modifier = 256, + optimal_range = 255, + optimal_range_modifier = 256, pbs_tech_limit = 664, //OPP: a no-op field for localization in gamma effect pbs_turret_core_per_sec = 652, - plasma_cycle_time_modifier = 258, - plasma_falloff_modifier = 259, - plasma_optimal_range_modifier = 260, - powergrid_current = 261, - powergrid_max = 262, - powergrid_max_modifier = 263, - powergrid_usage = 265, - powergrid_usage_armor_modifier = 266, - powergrid_usage_engineering_modifier = 267, - powergrid_usage_ew_modifier = 268, - powergrid_usage_gathering_modifier = 269, - powergrid_usage_large_energytorpedo_modifier = 270, - powergrid_usage_large_industrial_aoe_modifier = 271, - powergrid_usage_large_ioncannon_modifier = 272, - powergrid_usage_large_laser_modifier = 273, - powergrid_usage_large_missile_modifier = 274, - powergrid_usage_large_plasma_modifier = 275, - powergrid_usage_large_projectile_modifier = 276, - powergrid_usage_large_railgun_modifier = 277, - powergrid_usage_medium_energytorpedo_modifier = 278, - powergrid_usage_medium_industrial_aoe_modifier = 279, - powergrid_usage_medium_ioncannon_modifier = 280, - powergrid_usage_medium_laser_modifier = 281, - powergrid_usage_medium_missile_modifier = 282, - powergrid_usage_medium_plasma_modifier = 283, - powergrid_usage_medium_projectile_modifier = 284, - powergrid_usage_medium_railgun_modifier = 285, - powergrid_usage_shield_generators_modifier = 287, - powergrid_usage_small_energytorpedo_modifier = 288, - powergrid_usage_small_industrial_aoe_modifier = 289, - powergrid_usage_small_ioncannon_modifier = 290, - powergrid_usage_small_laser_modifier = 291, - powergrid_usage_small_missile_modifier = 292, - powergrid_usage_small_plasma_modifier = 293, - powergrid_usage_small_projectile_modifier = 294, - powergrid_usage_small_railgun_modifier = 295, - powergrid_usage_weapons_modifier = 296, - projectile_ammo_cycle_time_modifier = 642, - projectile_cycle_time_modifier = 297, - projectile_falloff_modifier = 298, - projectile_optimal_range_modifier = 299, + plasma_cycle_time_modifier = 258, + plasma_falloff_modifier = 259, + plasma_optimal_range_modifier = 260, + powergrid_current = 261, + powergrid_max = 262, + powergrid_max_modifier = 263, + powergrid_usage = 265, + powergrid_usage_armor_modifier = 266, + powergrid_usage_engineering_modifier = 267, + powergrid_usage_ew_modifier = 268, + powergrid_usage_gathering_modifier = 269, + powergrid_usage_large_energytorpedo_modifier = 270, + powergrid_usage_large_industrial_aoe_modifier = 271, + powergrid_usage_large_ioncannon_modifier = 272, + powergrid_usage_large_laser_modifier = 273, + powergrid_usage_large_missile_modifier = 274, + powergrid_usage_large_plasma_modifier = 275, + powergrid_usage_large_projectile_modifier = 276, + powergrid_usage_large_railgun_modifier = 277, + powergrid_usage_medium_energytorpedo_modifier = 278, + powergrid_usage_medium_industrial_aoe_modifier = 279, + powergrid_usage_medium_ioncannon_modifier = 280, + powergrid_usage_medium_laser_modifier = 281, + powergrid_usage_medium_missile_modifier = 282, + powergrid_usage_medium_plasma_modifier = 283, + powergrid_usage_medium_projectile_modifier = 284, + powergrid_usage_medium_railgun_modifier = 285, + powergrid_usage_shield_generators_modifier = 287, + powergrid_usage_small_energytorpedo_modifier = 288, + powergrid_usage_small_industrial_aoe_modifier = 289, + powergrid_usage_small_ioncannon_modifier = 290, + powergrid_usage_small_laser_modifier = 291, + powergrid_usage_small_missile_modifier = 292, + powergrid_usage_small_plasma_modifier = 293, + powergrid_usage_small_projectile_modifier = 294, + powergrid_usage_small_railgun_modifier = 295, + powergrid_usage_weapons_modifier = 296, + projectile_ammo_cycle_time_modifier = 642, + projectile_cycle_time_modifier = 297, + projectile_falloff_modifier = 298, + projectile_optimal_range_modifier = 299, pvp_no_teleport = 665, //OPP: field to use with zoneeffect to indicate prevention of teleport w/ pvp flag railgun_ammo_cycle_time_modifier = 639, - railgun_cycle_time_modifier = 300, - railgun_falloff_modifier = 301, - railgun_optimal_range_modifier = 302, - reactor_radiation = 643, - reactor_radiation_modifier = 644, - received_repaired_modifier = 506, - resist_chemical = 303, - resist_chemical_modifier = 304, - resist_explosive = 306, - resist_explosive_modifier = 307, - resist_kinetic = 309, - resist_kinetic_modifier = 310, - resist_thermal = 312, - resist_thermal_modifier = 313, - sensor_strength = 315, - sensor_strength_eccm_modifier = 655, - sensor_strength_modifier = 316, - shield_absorbtion = 318, - shield_absorbtion_modifier = 319, - shield_cycle_time_modifier = 321, - shield_radius = 322, - signature_radius = 323, - signature_radius_modifier = 324, - slope = 326, - slope_modifier = 327, - speed_current = 576, - speed_max = 330, - speed_max_add = 504, - speed_max_modifier = 331, - stealth_strength = 603, - stealth_strength_modifier = 604, - terraforming_cycle_time_modifier = 333, - thermal_damage_to_core_modifier = 619, - tile_based_mining_probe_radius = 334, - turret_cycle_time_modifier = 335, - turret_fallof_modifier = 336, - turret_optimal_range_modifier = 337, - weapon_cycle_time_modifier = 540 - } + railgun_cycle_time_modifier = 300, + railgun_falloff_modifier = 301, + railgun_optimal_range_modifier = 302, + reactor_radiation = 643, + reactor_radiation_modifier = 644, + received_repaired_modifier = 506, + resist_chemical = 303, + resist_chemical_modifier = 304, + resist_explosive = 306, + resist_explosive_modifier = 307, + resist_kinetic = 309, + resist_kinetic_modifier = 310, + resist_thermal = 312, + resist_thermal_modifier = 313, + sensor_strength = 315, + sensor_strength_eccm_modifier = 655, + sensor_strength_modifier = 316, + shield_absorbtion = 318, + shield_absorbtion_modifier = 319, + shield_cycle_time_modifier = 321, + shield_radius = 322, + signature_radius = 323, + signature_radius_modifier = 324, + slope = 326, + slope_modifier = 327, + speed_current = 576, + speed_max = 330, + speed_max_add = 504, + speed_max_modifier = 331, + stealth_strength = 603, + stealth_strength_modifier = 604, + terraforming_cycle_time_modifier = 333, + thermal_damage_to_core_modifier = 619, + tile_based_mining_probe_radius = 334, + turret_cycle_time_modifier = 335, + turret_fallof_modifier = 336, + turret_optimal_range_modifier = 337, + weapon_cycle_time_modifier = 540, + remote_control_bandwidth_max = 672, + remote_control_bandwidth_max_modifier = 673, + remote_control_bandwidth_usage = 674, + remote_control_operational_range = 675, + remote_control_operational_range_modifier = 676, + remote_control_lifetime = 677, + remote_control_lifetime_modifier = 678, + } } diff --git a/src/Perpetuum.ExportedTypes/AttributeFlags.cs b/src/Perpetuum.ExportedTypes/AttributeFlags.cs index 372d39803..b7076e89f 100644 --- a/src/Perpetuum.ExportedTypes/AttributeFlags.cs +++ b/src/Perpetuum.ExportedTypes/AttributeFlags.cs @@ -5,71 +5,71 @@ namespace Perpetuum.ExportedTypes { - public enum AttributeFlags : long - { - activeModule = 4, - alwaysStackable = 11, - ammo_required = 18, - consumable = 24, - delayed_modul = 25, - deployable = 23, - engage_combat = 7, - fittingCapacityModifier = 5, - forceOneCycle = 21, - gang_assist_module = 12, - gangEffect = 20, - instantActivate = 32, - invulnerable = 1, - item = 2, - large = 17, - mainbase = 30, - medium = 16, - nonattackable = 28, - nonlockable = 27, - nonRecyclable = 31, - nonrelocatable = 22, - nonStackable = 10, - NOT_USED = 63, - offensive_module = 6, - onePerRobot = 3, - passiveModule = 19, - player = 0, - primary_locked_target = 13, - pvp_support = 26, - self_effect = 8, - self_target = 14, - small = 15, - targetIsRobot = 9, - undefined_33 = 33, - undefined_34 = 34, - undefined_35 = 35, - undefined_36 = 36, - undefined_37 = 37, - undefined_38 = 38, - undefined_39 = 39, - undefined_40 = 40, - undefined_41 = 41, - undefined_42 = 42, - undefined_43 = 43, - undefined_44 = 44, - undefined_45 = 45, - undefined_46 = 46, - undefined_47 = 47, - undefined_48 = 48, - undefined_49 = 49, - undefined_50 = 50, - undefined_51 = 51, - undefined_52 = 52, - undefined_53 = 53, - undefined_54 = 54, - undefined_55 = 55, - undefined_56 = 56, - undefined_57 = 57, - undefined_58 = 58, - undefined_59 = 59, - undefined_60 = 60, - undefined_61 = 61, - undefined_62 = 62, - usable = 29 - } + public enum AttributeFlags : long + { + player = 0, + invulnerable = 1, + item = 2, + onePerRobot = 3, + activeModule = 4, + fittingCapacityModifier = 5, + offensive_module = 6, + engage_combat = 7, + self_effect = 8, + targetIsRobot = 9, + nonStackable = 10, + alwaysStackable = 11, + gang_assist_module = 12, + primary_locked_target = 13, + self_target = 14, + small = 15, + medium = 16, + large = 17, + ammo_required = 18, + passiveModule = 19, + gangEffect = 20, + forceOneCycle = 21, + nonrelocatable = 22, + deployable = 23, + consumable = 24, + delayed_modul = 25, + pvp_support = 26, + nonlockable = 27, + nonattackable = 28, + usable = 29, + mainbase = 30, + nonRecyclable = 31, + instantActivate = 32, + undefined_33 = 33, + undefined_34 = 34, + undefined_35 = 35, + undefined_36 = 36, + undefined_37 = 37, + undefined_38 = 38, + undefined_39 = 39, + undefined_40 = 40, + undefined_41 = 41, + undefined_42 = 42, + undefined_43 = 43, + undefined_44 = 44, + undefined_45 = 45, + undefined_46 = 46, + undefined_47 = 47, + undefined_48 = 48, + undefined_49 = 49, + undefined_50 = 50, + undefined_51 = 51, + undefined_52 = 52, + undefined_53 = 53, + undefined_54 = 54, + undefined_55 = 55, + undefined_56 = 56, + undefined_57 = 57, + undefined_58 = 58, + undefined_59 = 59, + undefined_60 = 60, + undefined_61 = 61, + undefined_62 = 62, + NOT_USED = 63, + } } diff --git a/src/Perpetuum.ExportedTypes/CategoryFlags.cs b/src/Perpetuum.ExportedTypes/CategoryFlags.cs index 569bf135c..3e5954442 100644 --- a/src/Perpetuum.ExportedTypes/CategoryFlags.cs +++ b/src/Perpetuum.ExportedTypes/CategoryFlags.cs @@ -9,665 +9,715 @@ namespace Perpetuum.ExportedTypes public enum CategoryFlags : long { undefined = 0, - cf_active_hacking_sap = 0x0000000000030592, - cf_admin_items = 0x0000000000000196, - cf_aggrorange_decreasers = 0x000000000005050F, - cf_alarm_switch = 0x0000000001040696, - cf_alliance = 0x0000000000000282, + + cf_robots = 0x0000000000000001, + cf_noobot = 0x0000000000000101, + cf_runners = 0x0000000000000201, + cf_crawlers = 0x0000000000000301, + cf_mechs = 0x0000000000000401, + cf_heavy_mechs = 0x0000000000000501, + cf_walkers = 0x0000000000000601, + cf_gm_test = 0x0000000000000701, + cf_turrets = 0x0000000000000801, + cf_police_turret = 0x0000000000010801, + cf_hybrid_robot = 0x0000000000000901, + cf_test_robots = 0x0000000000000A01, + cf_test_robot_punchbags = 0x0000000000010A01, + cf_testnpc = 0x0000000000020A01, + cf_pelistal_robots = 0x0000000000000B01, + cf_pelistal_runners = 0x0000000000010B01, + cf_pelistal_crawlers = 0x0000000000020B01, + cf_pelistal_mechs = 0x0000000000030B01, + cf_pelistal_heavymechs = 0x0000000000040B01, + cf_thelodica_robots = 0x0000000000000C01, + cf_thelodica_runners = 0x0000000000010C01, + cf_thelodica_crawlers = 0x0000000000020C01, + cf_thelodica_mechs = 0x0000000000030C01, + cf_thelodica_heavymechs = 0x0000000000040C01, + cf_nuimqol_robots = 0x0000000000000D01, + cf_nuimqol_runners = 0x0000000000010D01, + cf_nuimqol_crawlers = 0x0000000000020D01, + cf_nuimqol_mechs = 0x0000000000030D01, + cf_nuimqol_heavymechs = 0x0000000000040D01, + cf_industrial_robots = 0x0000000000000E01, + cf_industrial_runners = 0x0000000000010E01, + cf_industrial_crawlers = 0x0000000000020E01, + cf_industrial_mechs = 0x0000000000030E01, + cf_industrial_heavymechs = 0x0000000000040E01, + cf_industrial_heavy_gliders = 0x0000000000050E01, + cf_syndicate_robots = 0x0000000000000F01, + cf_syndicate_runners = 0x0000000000010F01, + cf_syndicate_crawlers = 0x0000000000020F01, + cf_syndicate_mechs = 0x0000000000030F01, + cf_syndicate_heavymechs = 0x0000000000040F01, + cf_command_robots = 0x0000000000001001, + cf_combat_command_robots = 0x0000000000011001, + cf_ammo = 0x000000000000000A, - cf_ammo_calibration_programs = 0x0000000000030416, - cf_ammo_corebooster_calibration_programs = 0x000000000B030416, - cf_ammo_energy_torpedo_calibration_programs = 0x0000000009030416, - cf_ammo_harvesting_calibration_programs = 0x0000000007030416, - cf_ammo_industrial_aoe_calibration_programs = 0x000000000D030416, - cf_ammo_ioncannon_calibration_programs = 0x000000000A030416, - cf_ammo_laser_calibration_programs = 0x0000000002030416, - cf_ammo_mining_calibration_programs = 0x000000000C030416, - cf_ammo_mining_probe_calibration_programs = 0x000000000E030416, - cf_ammo_missile_calibration_programs = 0x0000000004030416, - cf_ammo_plasma_calibration_programs = 0x0000000008030416, - cf_ammo_projectile_calibration_programs = 0x0000000005030416, - cf_ammo_railgun_calibration_programs = 0x0000000001030416, - cf_ammo_terraforming_multi = 0x000000000001100A, - cf_aoe_calibration_programs = 0x0000000008020416, - cf_aoe_projectile = 0x000000000502070F, - cf_aoe_projectile_tile = 0x000000010502070F, - cf_aoe_projectile_unit = 0x000000020502070F, + cf_railgun_ammo = 0x000000000000010A, + cf_small_railgun_ammo = 0x000000000001010A, + cf_medium_railgun_ammo = 0x000000000002010A, + cf_large_railgun_ammo = 0x000000000003010A, + cf_laser_ammo = 0x000000000000020A, + cf_small_crystals = 0x000000000001020A, + cf_medium_crystals = 0x000000000002020A, + cf_large_crystals = 0x000000000003020A, + cf_projectile_ammo = 0x000000000000030A, + cf_small_projectile_ammo = 0x000000000001030A, + cf_medium_projectile_ammo = 0x000000000002030A, + cf_large_projectile_ammo = 0x000000000003030A, + cf_missile_ammo = 0x000000000000040A, + cf_small_missile_ammo = 0x000000000001040A, + cf_medium_missile_ammo = 0x000000000002040A, + cf_large_missile_ammo = 0x000000000003040A, + cf_mining_ammo = 0x000000000000050A, + cf_plasma_ammo = 0x000000000000060A, + cf_small_plasma_ammo = 0x000000000001060A, + cf_medium_plasma_ammo = 0x000000000002060A, + cf_large_plasma_ammo = 0x000000000003060A, + cf_core_booster_ammo = 0x000000000000070A, + cf_mining_probe_ammo = 0x000000000000090A, + cf_mining_probe_ammo_area = 0x000000000001090A, + cf_mining_probe_ammo_tile = 0x000000000002090A, + cf_mining_probe_ammo_one_tile = 0x000000000003090A, + cf_mining_probe_ammo_artifact = 0x000000000004090A, + cf_mining_probe_ammo_intrusion = 0x000000000005090A, + cf_mining_probe_ammo_direction = 0x000000000006090A, + cf_harvesting_ammo = 0x0000000000000A0A, + cf_ioncannon_ammo = 0x0000000000000B0A, + cf_small_ioncannon_ammo = 0x0000000000010B0A, + cf_medium_ioncannon_ammo = 0x0000000000020B0A, + cf_large_ioncannon_ammo = 0x0000000000030B0A, + cf_energytorpedo_ammo = 0x0000000000000C0A, + cf_small_energytorpedo_ammo = 0x0000000000010C0A, + cf_medium_energytorpedo_ammo = 0x0000000000020C0A, + cf_large_energytorpedo_ammo = 0x0000000000030C0A, + cf_industrial_aoe_tile_ammo = 0x0000000000000D0A, + cf_small_industrial_aoe_tile_ammo = 0x0000000000010D0A, + cf_medium_industrial_aoe_tile_ammo = 0x0000000000020D0A, + cf_large_industrial_aoe_tile_ammo = 0x0000000000030D0A, cf_aoe_unit_ammo = 0x0000000000000E0A, - cf_area_based = 0x0000000000020390, - cf_area_bomb = 0x0000000000020392, - cf_area_bomb_deployer = 0x0000000000020498, - cf_arena_guard = 0x0000000000000692, - cf_arena_teleport_deployer = 0x0000000000000698, - cf_armor_calibration_programs = 0x0000000001040416, + cf_small_aoe_unit_ammo = 0x0000000000010E0A, + cf_medium_aoe_unit_ammo = 0x0000000000020E0A, + cf_large_aoe_unit_ammo = 0x0000000000030E0A, + cf_blob_emission_modulator_ammo = 0x0000000000000F0A, + cf_terraforming_ammo = 0x000000000000100A, + cf_ammo_terraforming_multi = 0x000000000001100A, + cf_buoy_charger_ammo = 0x000000000002100A, + cf_construction_ammo_main = 0x000000000000110A, + cf_construction_ammo = 0x000000000001110A, + cf_wall_builder_ammo = 0x000000000002110A, + cf_remote_controlled_units = 0x000000000000120A, + cf_remote_controlled_turrets = 0x000000000001120A, + cf_sentry_turret_units = 0x000000000101120A, + cf_mining_turret_units = 0x000000000201120A, + cf_harvesting_turret_units = 0x000000000301120A, + cf_remote_controlled_combat_drones = 0x000000000002120A, + cf_pelistal_combat_drones_units = 0x000000000102120A, + cf_nuimqol_combat_drones_units = 0x000000000202120A, + cf_thelodica_combat_drones_units = 0x000000000302120A, + + cf_robot_equipment = 0x000000000000000F, cf_armor_equipment = 0x000000000000010F, - cf_armor_hardeners = 0x000000000004010F, cf_armor_plates = 0x000000000001010F, + cf_small_armor_plates = 0x000000000101010F, + cf_medium_armor_plates = 0x000000000201010F, + cf_large_armor_plates = 0x000000000301010F, cf_armor_repair_systems = 0x000000000002010F, - cf_armor_repair_upgrades = 0x000000000006010F, - cf_artifact_data = 0x0000000000000914, - cf_base = 0x0000000000000178, - cf_base_item_shop = 0x000000000002016E, - cf_basic_commodities = 0x0000000000000214, - cf_battle_stance_moduls = 0x000000000108040F, - cf_blob_emission_modulator = 0x000000000007050F, - cf_blob_emission_modulator_ammo = 0x0000000000000F0A, - cf_blob_emitter = 0x0000000000000292, - cf_buoy_charger_ammo = 0x000000000002100A, - cf_calibration_program_forge = 0x00000000000C036E, - cf_calibration_programs = 0x0000000000000416, - cf_cargo_scanner = 0x000000000003040F, - cf_chassis_calibration_programs = 0x0000000002050416, - cf_chassis_scanner = 0x000000000004040F, + cf_small_armor_repairers = 0x000000000102010F, + cf_medium_armor_repairers = 0x000000000202010F, + cf_large_armor_repairers = 0x000000000302010F, + cf_remote_armor_repairers = 0x000000000003010F, + cf_small_remote_armor_repairers = 0x000000000103010F, + cf_medium_remote_armor_repairers = 0x000000000203010F, + cf_large_remote_armor_repairers = 0x000000000303010F, + cf_armor_hardeners = 0x000000000004010F, cf_chemical_armor_hardeners = 0x000000000104010F, - cf_common_energy_cores = 0x0000000000010514, - cf_common_robotshards = 0x0000000000010414, - cf_component_items = 0x0000000000020595, - cf_construction_ammo = 0x000000000001110A, - cf_construction_ammo_main = 0x000000000000110A, - cf_construction_modules = 0x000000000009060F, - cf_consumable_boosters = 0x0000000000010996, - cf_consumable_items = 0x0000000000000996, - cf_container = 0x0000000000000015, - cf_container_capsule = 0x0000000000000298, + cf_kinetic_armor_hardeners = 0x000000000204010F, + cf_explosive_armor_hardeners = 0x000000000304010F, + cf_thermal_armor_hardeners = 0x000000000404010F, + cf_resistance_plating = 0x000000000504010F, + cf_lightweight_frame = 0x000000000005010F, + cf_armor_repair_upgrades = 0x000000000006010F, + cf_shield_equipment = 0x000000000000020F, + cf_shield_generators = 0x000000000001020F, + cf_small_shield_generator = 0x000000000101020F, + cf_medium_shield_generators = 0x000000000201020F, + cf_large_shield_generators = 0x000000000301020F, + cf_shield_hardener = 0x000000000002020F, + cf_engineering_equipment = 0x000000000000030F, + cf_energy_transferers = 0x000000000001030F, + cf_small_energy_transferers = 0x000000000101030F, + cf_medium_energy_transferers = 0x000000000201030F, + cf_large_energy_transferers = 0x000000000301030F, + cf_energy_vampires = 0x000000000002030F, + cf_small_energy_vampires = 0x000000000102030F, + cf_medium_energy_vampires = 0x000000000202030F, + cf_large_energy_vampires = 0x000000000302030F, + cf_energy_neutralizers = 0x000000000003030F, + cf_small_energy_neutralizers = 0x000000000103030F, + cf_medium_energy_neutralizers = 0x000000000203030F, + cf_large_energy_neutralizers = 0x000000000303030F, + cf_core_rechargers = 0x000000000004030F, + cf_powergrid_upgrades = 0x000000000005030F, + cf_walking_stabilizers = 0x000000000006030F, + cf_massmodifiers = 0x000000000007030F, cf_core_batteries = 0x000000000008030F, - cf_core_booster_ammo = 0x000000000000070A, + cf_small_core_batteries = 0x000000000108030F, + cf_medium_core_batteries = 0x000000000208030F, + cf_large_core_batteries = 0x000000000308030F, cf_core_boosters = 0x000000000009030F, - cf_core_rechargers = 0x000000000004030F, - cf_corporate_hangar = 0x0000000000060815, - cf_corporate_hangar_folder = 0x0000000000070815, - cf_corporation = 0x0000000000000182, - cf_courier_items = 0x0000000000000195, + cf_small_core_boosters = 0x000000000109030F, + cf_medium_core_boosters = 0x000000000209030F, + cf_large_core_boosters = 0x000000000309030F, + cf_maneuvering_equipment = 0x00000000000A030F, + cf_kers = 0x00000000000B030F, + cf_kinetic_kers = 0x00000000010B030F, + cf_explosive_kers = 0x00000000020B030F, + cf_thermal_kers = 0x00000000030B030F, + cf_neuralyzer = 0x00000000000C030F, + cf_energy_warfare_upgrades = 0x00000000000D030F, + cf_reactor_sealings = 0x00000000000E030F, + cf_landmine_detectors = 0x00000000000F030F, + cf_electronics_equipment = 0x000000000000040F, + cf_sensor_boosters = 0x000000000001040F, + cf_remote_sensor_boosters = 0x000000000002040F, + cf_cargo_scanner = 0x000000000003040F, + cf_chassis_scanner = 0x000000000004040F, + cf_industrial_scanner = 0x000000000005040F, cf_cpu_upgrades = 0x000000000006040F, - cf_crawler_calibration_programs = 0x0000000002010416, - cf_crawler_chassis = 0x0000000000020250, - cf_crawler_head = 0x0000000000020150, - cf_crawler_leg = 0x0000000000020350, - cf_crawlers = 0x0000000000000301, - cf_ct_capsules = 0x000000000003049B, - cf_ct_capsules_ammo = 0x000000000103049B, - cf_ct_capsules_ammo_laser = 0x000000010103049B, - cf_ct_capsules_ammo_missile = 0x000000040103049B, - cf_ct_capsules_ammo_projectile = 0x000000030103049B, - cf_ct_capsules_ammo_railgun = 0x000000020103049B, - cf_ct_capsules_equipment = 0x000000000203049B, - cf_ct_capsules_equipment_armor = 0x000000010203049B, - cf_ct_capsules_equipment_electronics = 0x000000030203049B, - cf_ct_capsules_equipment_engineering = 0x000000040203049B, - cf_ct_capsules_equipment_ewar = 0x000000020203049B, - cf_ct_capsules_equipment_industrial = 0x000000050203049B, - cf_ct_capsules_equipment_nexus = 0x000000080203049B, - cf_ct_capsules_equipment_shield = 0x000000060203049B, - cf_ct_capsules_equipment_weapons = 0x000000070203049B, - cf_ct_capsules_misc = 0x000000000403049B, - cf_ct_capsules_robot = 0x000000000303049B, - cf_ct_capsules_robot_industrial = 0x000000040303049B, - cf_ct_capsules_robot_industrial_assault = 0x000002040303049B, - cf_ct_capsules_robot_industrial_heavymech = 0x000004040303049B, - cf_ct_capsules_robot_industrial_light = 0x000001040303049B, - cf_ct_capsules_robot_industrial_mech = 0x000003040303049B, - cf_ct_capsules_robot_nuimqol = 0x000000030303049B, - cf_ct_capsules_robot_nuimqol_assault = 0x000002030303049B, - cf_ct_capsules_robot_nuimqol_heavymech = 0x000004030303049B, - cf_ct_capsules_robot_nuimqol_light = 0x000001030303049B, - cf_ct_capsules_robot_nuimqol_mech = 0x000003030303049B, - cf_ct_capsules_robot_pelistal = 0x000000010303049B, - cf_ct_capsules_robot_pelistal_assault = 0x000002010303049B, - cf_ct_capsules_robot_pelistal_heavymech = 0x000004010303049B, - cf_ct_capsules_robot_pelistal_light = 0x000001010303049B, - cf_ct_capsules_robot_pelistal_mech = 0x000003010303049B, - cf_ct_capsules_robot_syndicate = 0x000000050303049B, - cf_ct_capsules_robot_syndicate_assault = 0x000002050303049B, - cf_ct_capsules_robot_syndicate_heavymech = 0x000004050303049B, - cf_ct_capsules_robot_syndicate_light = 0x000001050303049B, - cf_ct_capsules_robot_syndicate_mech = 0x000003050303049B, - cf_ct_capsules_robot_thelodica = 0x000000020303049B, - cf_ct_capsules_robot_thelodica_assault = 0x000002020303049B, - cf_ct_capsules_robot_thelodica_heavymech = 0x000004020303049B, - cf_ct_capsules_robot_thelodica_light = 0x000001020303049B, - cf_ct_capsules_robot_thelodica_mech = 0x000003020303049B, - - cf_respec_token = 0x000000000004049B, - - cf_datashards = 0x0000000000000694, - cf_decor = 0x000000000000005A, - cf_decor_buildings = 0x000000000000055A, - cf_decor_general = 0x000000000001055A, - cf_decor_general_element = 0x000000000101055A, - cf_decor_nuimqol = 0x000000000003055A, - cf_decor_nuimqol_element = 0x000000000303055A, - cf_decor_nuimqol_general = 0x000000000103055A, - cf_decor_nuimqol_misc = 0x000000000000025A, - cf_decor_nuimqol_special = 0x000000000203055A, - cf_decor_pelistal = 0x000000000002055A, - cf_decor_pelistal_element = 0x000000000302055A, - cf_decor_pelistal_general = 0x000000000102055A, - cf_decor_pelistal_misc = 0x000000000000045A, - cf_decor_pelistal_special = 0x000000000202055A, - cf_decor_template = 0x000000000000065A, - cf_decor_thelodica = 0x000000000004055A, - cf_decor_thelodica_element = 0x000000000304055A, - cf_decor_thelodica_general = 0x000000000104055A, - cf_decor_thelodica_misc = 0x000000000000035A, - cf_decor_thelodica_special = 0x000000000204055A, - cf_default_alliance = 0x0000000000020282, - cf_default_corporation = 0x0000000000010182, - cf_deployable_structure = 0x0000000000000998, - cf_destrucion_sap = 0x0000000000010592, + cf_tracking_upgrades = 0x000000000007040F, + cf_stance_moduls = 0x000000000008040F, + cf_battle_stance_moduls = 0x000000000108040F, cf_detection_modules = 0x000000000009040F, - cf_documents = 0x0000000000000016, - cf_dogtags = 0x0000000000000091, - cf_drillers = 0x000000000001060F, - cf_dynamic_cprg = 0x0000000000000099, - cf_dynamic_teleports = 0x0000000000060278, + cf_stealth_modules = 0x00000000000A040F, + cf_target_painter = 0x00000000000B040F, + cf_remote_controllers = 0x00000000000C040F, + cf_electronic_warfare_equipment = 0x000000000000050F, + cf_webber = 0x000000000001050F, + cf_shortrange_webber = 0x000000000101050F, + cf_longrange_webber = 0x000000000201050F, + cf_sensor_jammers = 0x000000000002050F, + cf_sensor_dampeners = 0x000000000003050F, cf_eccm = 0x000000000004050F, + cf_aggrorange_decreasers = 0x000000000005050F, + cf_siege_hack_modules = 0x000000000006050F, + cf_blob_emission_modulator = 0x000000000007050F, cf_ecm_boosters = 0x000000000008050F, - cf_egg_deployers = 0x0000000000000498, - cf_eggs = 0x0000000000000392, - cf_electronic_warfare_equipment = 0x000000000000050F, - cf_electronics_equipment = 0x000000000000040F, - cf_energy_cores = 0x0000000000000514, - cf_energy_neutralizers = 0x000000000003030F, - cf_energy_transferers = 0x000000000001030F, - cf_energy_vampires = 0x000000000002030F, - cf_energy_warfare_upgrades = 0x00000000000D030F, + cf_supressor_boosters = 0x000000000009050F, + cf_gathering_equipment = 0x000000000000060F, + cf_drillers = 0x000000000001060F, + cf_small_drillers = 0x000000000101060F, + cf_medium_drillers = 0x000000000201060F, + cf_medium_drillers_old = 0x000000000002060F, + cf_industrial_turret_drillers = 0x000000000003060F, + cf_mining_upgrades = 0x000000000004060F, + cf_mining_probes = 0x000000000005060F, + cf_harvesters = 0x000000000006060F, + cf_small_harvesters = 0x000000000106060F, + cf_medium_harvesters = 0x000000000206060F, + cf_medium_harvesters_old = 0x000000000007060F, + cf_industrial_turret_harvesters = 0x000000000008060F, + cf_construction_modules = 0x000000000009060F, + cf_terraform_equipment = 0x00000000000A060F, + cf_weapons = 0x000000000000070F, + cf_lasers = 0x000000000001070F, + cf_small_lasers = 0x000000000101070F, + cf_medium_lasers = 0x000000000201070F, + cf_large_lasers = 0x000000000301070F, + cf_projectiles = 0x000000000002070F, + cf_single_projectile = 0x000000000402070F, + cf_small_single_projectile = 0x000000010402070F, + cf_medium_single_projectile = 0x000000020402070F, + cf_large_single_projectile = 0x000000030402070F, + cf_aoe_projectile = 0x000000000502070F, + cf_aoe_projectile_tile = 0x000000010502070F, + cf_small_aoe_projectile_tile = 0x000001010502070F, + cf_medium_aoe_tile = 0x000002010502070F, + cf_large_aoe_tile = 0x000003010502070F, + cf_aoe_projectile_unit = 0x000000020502070F, + cf_small_aoe_unit = 0x000001020502070F, + cf_medium_aoe_unit = 0x000002020502070F, + cf_large_aoe_unit = 0x000003020502070F, + cf_missiles = 0x000000000003070F, + cf_small_missile_launchers = 0x000000000103070F, + cf_medium_missile_launchers = 0x000000000203070F, + cf_large_missile_launchers = 0x000000000303070F, + cf_railguns = 0x000000000004070F, + cf_small_railguns = 0x000000000104070F, + cf_medium_railguns = 0x000000000204070F, + cf_large_railguns = 0x000000000304070F, + cf_weapon_upgrades = 0x000000000005070F, + cf_railgun_upgrades = 0x000000000105070F, + cf_projectile_upgrades = 0x000000000205070F, + cf_laser_upgrades = 0x000000000305070F, + cf_missile_upgrades = 0x000000000405070F, + cf_weapon_stabilizer = 0x000000000505070F, + cf_plasma = 0x000000000007070F, + cf_small_plasma = 0x000000000107070F, + cf_medium_plasma = 0x000000000307070F, + cf_large_plasma = 0x000000000407070F, + cf_ioncannon = 0x000000000008070F, + cf_small_ioncannon = 0x000000000108070F, + cf_medium_ioncannon = 0x000000000208070F, + cf_large_ioncannon = 0x000000000308070F, cf_energytorpedo = 0x000000000009070F, - cf_energytorpedo_ammo = 0x0000000000000C0A, - cf_energytorpedo_calibration_programs = 0x0000000007020416, - cf_engineering_calibration_programs = 0x0000000003040416, - cf_engineering_equipment = 0x000000000000030F, - cf_ep_boosters = 0x000000000001049B, - cf_ew_calibration_programs = 0x0000000002040416, - cf_ew_resist = 0x0000000000010A0F, - cf_explosive_armor_hardeners = 0x000000000304010F, - cf_explosive_kers = 0x00000000020B030F, - cf_field_accessories = 0x0000000000000098, - cf_field_containers = 0x0000000000020A15, - cf_field_terminal = 0x0000000000020178, - cf_gamma_commodities = 0x0000000000060214, - cf_gang_assist_calibration_programs = 0x0000000005040416, - cf_gang_assist_coordinated_manuevering = 0x000000000008090F, - cf_gang_assist_core_management = 0x00000000000C090F, - cf_gang_assist_defense = 0x000000000004090F, - cf_gang_assist_devastating = 0x00000000000B090F, + cf_small_energytorpedo = 0x000000000109070F, + cf_medium_energytorpedo = 0x000000000209070F, + cf_large_energytorpedo = 0x000000000309070F, + cf_industrial_aoe = 0x00000000000A070F, + cf_small_industrial_aoe = 0x00000000010A070F, + cf_medium_industrial_aoe = 0x00000000020A070F, + cf_large_industrial_aoe = 0x00000000030A070F, + cf_sentry_turret_guns = 0x00000000000C070F, + cf_terraforming_equipment = 0x000000000000080F, + cf_small_terraformer = 0x000000000001080F, + cf_terraforming_digger = 0x000000000002080F, + cf_terraforming_raiser = 0x000000000003080F, + cf_gang_assist_modules = 0x000000000000090F, + cf_gang_assist_speed = 0x000000000001090F, + cf_gang_assist_siege = 0x000000000002090F, cf_gang_assist_ewar = 0x000000000003090F, - cf_gang_assist_fast_extracting = 0x00000000000D090F, + cf_gang_assist_defense = 0x000000000004090F, cf_gang_assist_industry = 0x000000000005090F, cf_gang_assist_information = 0x000000000006090F, + cf_gang_assist_shared_dataprocessing = 0x000000000007090F, + cf_gang_assist_coordinated_manuevering = 0x000000000008090F, cf_gang_assist_maintance = 0x000000000009090F, - cf_gang_assist_modules = 0x000000000000090F, cf_gang_assist_precision_firing = 0x00000000000A090F, - cf_gang_assist_resilience = 0x00000000000F090F, - cf_gang_assist_shared_dataprocessing = 0x000000000007090F, + cf_gang_assist_devastating = 0x00000000000B090F, + cf_gang_assist_core_management = 0x00000000000C090F, + cf_gang_assist_fast_extracting = 0x00000000000D090F, cf_gang_assist_shield_calculations = 0x00000000000E090F, - cf_gang_assist_siege = 0x000000000002090F, - cf_gang_assist_speed = 0x000000000001090F, - cf_gate = 0x0000000000000A92, - cf_gathering_equipment = 0x000000000000060F, - cf_generic_random_items = 0x0000000000010595, - cf_geoscan_documents = 0x0000000000000695, + cf_gang_assist_resilience = 0x00000000000F090F, + cf_tactial_modules = 0x0000000000000A0F, + cf_ew_resist = 0x0000000000010A0F, + cf_lock_breaker = 0x0000000000020A0F, + cf_overcharged_armor_resist = 0x0000000000030A0F, + + cf_material = 0x0000000000000014, + cf_raw_material = 0x0000000000000114, + cf_organic = 0x0000000000010114, + cf_ore = 0x0000000000020114, + cf_liquid = 0x0000000000040114, cf_geothermal = 0x0000000000050114, - cf_gift_packages = 0x0000000000000896, - cf_gm_test = 0x0000000000000701, - cf_groups = 0x0000000000000082, - cf_harvesters = 0x000000000006060F, - cf_harvesting_ammo = 0x0000000000000A0A, - cf_head_calibration_programs = 0x0000000001050416, - cf_heavy_mechs = 0x0000000000000501, - cf_heavymech_calibration_programs = 0x0000000004010416, - cf_heavymech_chassis = 0x0000000000040250, - cf_heavymech_head = 0x0000000000040150, - cf_heavymech_leg = 0x0000000000040350, + cf_basic_commodities = 0x0000000000000214, + cf_primary_commodities = 0x0000000000010214, + cf_pelistal_commodities = 0x0000000000020214, + cf_thelodica_commodities = 0x0000000000030214, + cf_nuimqol_commodities = 0x0000000000040214, cf_hightier_commodities = 0x0000000000050214, - cf_hybrid_robot = 0x0000000000000901, - cf_ice = 0x000000000000029B, - cf_industrial_aoe = 0x00000000000A070F, - cf_industrial_aoe_calibration_programs = 0x000000000A020416, - cf_industrial_aoe_tile_ammo = 0x0000000000000D0A, - cf_industrial_crawlers = 0x0000000000020E01, - cf_industrial_egg_deployer = 0x0000000000040598, - cf_industrial_heavy_gliders = 0x0000000000050E01, - cf_industrial_heavymechs = 0x0000000000040E01, - cf_industrial_mechs = 0x0000000000030E01, - cf_industrial_robots = 0x0000000000000E01, - cf_industrial_runners = 0x0000000000010E01, - cf_industrial_scanner = 0x000000000005040F, - cf_industry_calibration_programs = 0x0000000004040416, - cf_indy_dogtags = 0x0000000000000591, - cf_infinite_capacity_box = 0x0000000000030815, + cf_gamma_commodities = 0x0000000000060214, + cf_soil = 0x0000000000000314, + cf_robotshards = 0x0000000000000414, + cf_common_robotshards = 0x0000000000010414, + cf_thelodica_robotshards = 0x0000000000020414, + cf_nuimqol_robotshards = 0x0000000000030414, + cf_pelistal_robotshards = 0x0000000000040414, + cf_energy_cores = 0x0000000000000514, + cf_common_energy_cores = 0x0000000000010514, + cf_thelodica_energy_cores = 0x0000000000020514, + cf_pelistal_energy_cores = 0x0000000000030514, + cf_nuimqol_energy_cores = 0x0000000000040514, + cf_reactor_plasma = 0x0000000000000614, + cf_rare_material = 0x0000000000000714, + cf_artifact_data = 0x0000000000000914, + + cf_container = 0x0000000000000015, cf_infinite_capacity_containers = 0x0000000000000815, - cf_inland_mobile_teleport_capsule = 0x0000000000010198, - cf_insurance_facility = 0x00000000000A036E, - cf_intel_documents = 0x0000000000000795, - cf_intrusion_objects = 0x0000000000000592, - cf_intrusion_pbs_deployers = 0x0000000000040498, - cf_intrusion_pbs_eggs = 0x0000000000040392, - cf_intrusion_turrets = 0x0000000000050592, - cf_ioncannon = 0x000000000008070F, - cf_ioncannon_ammo = 0x0000000000000B0A, - cf_ioncannon_calibration_programs = 0x0000000006020416, - cf_item_speed_boosters = 0x0000000000000396, - cf_item_supply = 0x0000000000050696, - cf_items = 0x0000000000000096, - cf_kernels = 0x0000000000000494, - cf_kers = 0x00000000000B030F, - cf_kinetic_armor_hardeners = 0x000000000204010F, - cf_kinetic_kers = 0x00000000010B030F, - cf_kiosk = 0x0000000000010696, - cf_large_aoe_tile = 0x000003010502070F, - cf_large_aoe_unit = 0x000003020502070F, - cf_large_aoe_unit_ammo = 0x0000000000030E0A, - cf_large_armor_plates = 0x000000000301010F, - cf_large_armor_repairers = 0x000000000302010F, - cf_large_core_batteries = 0x000000000308030F, - cf_large_core_boosters = 0x000000000309030F, - cf_large_crystals = 0x000000000003020A, - cf_large_energy_neutralizers = 0x000000000303030F, - cf_large_energy_transferers = 0x000000000301030F, - cf_large_energy_vampires = 0x000000000302030F, - cf_large_energytorpedo = 0x000000000309070F, - cf_large_energytorpedo_ammo = 0x0000000000030C0A, - cf_large_industrial_aoe = 0x00000000030A070F, - cf_large_industrial_aoe_tile_ammo = 0x0000000000030D0A, - cf_large_ioncannon = 0x000000000308070F, - cf_large_ioncannon_ammo = 0x0000000000030B0A, - cf_large_lasers = 0x000000000301070F, - cf_large_missile_ammo = 0x000000000003040A, - cf_large_missile_launchers = 0x000000000303070F, - cf_large_plasma = 0x000000000407070F, - cf_large_plasma_ammo = 0x000000000003060A, - cf_large_projectile_ammo = 0x000000000003030A, - cf_large_railgun_ammo = 0x000000000003010A, - cf_large_railguns = 0x000000000304070F, - cf_large_remote_armor_repairers = 0x000000000303010F, - cf_large_shield_generators = 0x000000000301020F, - cf_large_single_projectile = 0x000000030402070F, - cf_laser_ammo = 0x000000000000020A, - cf_laser_calibration_programs = 0x0000000002020416, - cf_laser_upgrades = 0x000000000305070F, - cf_lasers = 0x000000000001070F, - cf_leg_calibration_programs = 0x0000000003050416, - cf_lightweight_frame = 0x000000000005010F, - cf_limited_capacity_box = 0x0000000000040915, - cf_limited_capacity_containers = 0x0000000000000915, - cf_liquid = 0x0000000000040114, - cf_lock_breaker = 0x0000000000020A0F, - cf_logical_storage = 0x0000000000000017, - cf_longrange_webber = 0x000000000201050F, + cf_system_container = 0x0000000000010815, cf_loot = 0x0000000000020815, - cf_loot_container_object = 0x0000000000000192, + cf_infinite_capacity_box = 0x0000000000030815, + cf_public_container = 0x0000000000040815, + cf_public_corporation_hangar_storage = 0x0000000000050815, + cf_corporate_hangar = 0x0000000000060815, + cf_corporate_hangar_folder = 0x0000000000070815, + cf_volume_wrapper_container_old = 0x0000000000080815, + cf_limited_capacity_containers = 0x0000000000000915, + cf_private_container = 0x0000000000010915, + cf_robot_inventory = 0x0000000000030915, + cf_limited_capacity_box = 0x0000000000040915, cf_lootcontainers = 0x0000000000000A15, cf_lootonly_containers = 0x0000000000010A15, - cf_lottery_items = 0x000000000000049B, - cf_maneuvering_equipment = 0x00000000000A030F, - cf_markets = 0x000000000000016E, - cf_massmodifiers = 0x000000000007030F, - cf_material = 0x0000000000000014, - cf_material_scan_result = 0x0000000000000390, - cf_mech_calibration_programs = 0x0000000003010416, - cf_mech_chassis = 0x0000000000030250, - cf_mech_head = 0x0000000000030150, - cf_mech_leg = 0x0000000000030350, - cf_mechs = 0x0000000000000401, - cf_medium_aoe_tile = 0x000002010502070F, - cf_medium_aoe_unit = 0x000002020502070F, - cf_medium_aoe_unit_ammo = 0x0000000000020E0A, - cf_medium_armor_plates = 0x000000000201010F, - cf_medium_armor_repairers = 0x000000000202010F, - cf_medium_core_batteries = 0x000000000208030F, - cf_medium_core_boosters = 0x000000000209030F, - cf_medium_crystals = 0x000000000002020A, - cf_medium_drillers = 0x000000000201060F, - cf_medium_drillers_old = 0x000000000002060F, - cf_medium_energy_neutralizers = 0x000000000203030F, - cf_medium_energy_transferers = 0x000000000201030F, - cf_medium_energy_vampires = 0x000000000202030F, - cf_medium_energytorpedo = 0x000000000209070F, - cf_medium_energytorpedo_ammo = 0x0000000000020C0A, - cf_medium_harvesters = 0x000000000206060F, - cf_medium_harvesters_old = 0x000000000007060F, - cf_medium_industrial_aoe = 0x00000000020A070F, - cf_medium_industrial_aoe_tile_ammo = 0x0000000000020D0A, - cf_medium_ioncannon = 0x000000000208070F, - cf_medium_ioncannon_ammo = 0x0000000000020B0A, - cf_medium_lasers = 0x000000000201070F, - cf_medium_missile_ammo = 0x000000000002040A, - cf_medium_missile_launchers = 0x000000000203070F, - cf_medium_plasma = 0x000000000307070F, - cf_medium_plasma_ammo = 0x000000000002060A, - cf_medium_projectile_ammo = 0x000000000002030A, - cf_medium_railgun_ammo = 0x000000000002010A, - cf_medium_railguns = 0x000000000204070F, - cf_medium_remote_armor_repairers = 0x000000000203010F, - cf_medium_shield_generators = 0x000000000201020F, - cf_medium_single_projectile = 0x000000020402070F, - cf_mill = 0x000000000008036E, - cf_mining_ammo = 0x000000000000050A, - cf_mining_probe_ammo = 0x000000000000090A, - cf_mining_probe_ammo_area = 0x000000000001090A, - cf_mining_probe_ammo_artifact = 0x000000000004090A, - cf_mining_probe_ammo_direction = 0x000000000006090A, - cf_mining_probe_ammo_intrusion = 0x000000000005090A, - cf_mining_probe_ammo_one_tile = 0x000000000003090A, - cf_mining_probe_ammo_tile = 0x000000000002090A, + cf_field_containers = 0x0000000000020A15, + cf_volume_wrapper_container = 0x0000000000000B15, + + cf_documents = 0x0000000000000016, cf_mining_probe_result = 0x0000000000000316, cf_mining_probe_result_area = 0x0000000000010316, cf_mining_probe_result_tile = 0x0000000000020316, - cf_mining_probes = 0x000000000005060F, - cf_mining_upgrades = 0x000000000004060F, - cf_missile_ammo = 0x000000000000040A, + cf_calibration_programs = 0x0000000000000416, + cf_robot_calibration_programs = 0x0000000000010416, + cf_runner_calibration_programs = 0x0000000001010416, + cf_crawler_calibration_programs = 0x0000000002010416, + cf_mech_calibration_programs = 0x0000000003010416, + cf_heavymech_calibration_programs = 0x0000000004010416, + cf_walker_calibration_programs = 0x0000000005010416, + cf_weapon_calibration_programs = 0x0000000000020416, + cf_railgun_calibration_programs = 0x0000000001020416, + cf_laser_calibration_programs = 0x0000000002020416, + cf_plasmagun_calibration_programs = 0x0000000003020416, cf_missile_calibration_programs = 0x0000000004020416, - cf_missile_upgrades = 0x000000000405070F, - cf_missiles = 0x000000000003070F, - cf_mission_agent = 0x000000000000046E, - cf_mission_calibration_programs = 0x0000000000060416, - cf_mission_coin = 0x000000000000039B, - cf_mission_egg_deployer = 0x0000000000050598, - cf_mission_items = 0x0000000000000095, - cf_mission_mineral = 0x0000000000000495, - cf_mission_structures = 0x0000000000000696, - cf_mission_switch = 0x0000000000040696, - cf_mobile_arena_teleport = 0x0000000003060278, - cf_mobile_teleport = 0x0000000001060278, - cf_mobile_teleport_capsule = 0x0000000000000198, - cf_mobile_world_teleport = 0x0000000002060278, + cf_projectile_calibration_programs = 0x0000000005020416, + cf_ioncannon_calibration_programs = 0x0000000006020416, + cf_energytorpedo_calibration_programs = 0x0000000007020416, + cf_aoe_calibration_programs = 0x0000000008020416, + cf_weapon_upgrade_calibration_programs = 0x0000000009020416, + cf_industrial_aoe_calibration_programs = 0x000000000A020416, + cf_ammo_calibration_programs = 0x0000000000030416, + cf_ammo_railgun_calibration_programs = 0x0000000001030416, + cf_ammo_laser_calibration_programs = 0x0000000002030416, + cf_ammo_missile_calibration_programs = 0x0000000004030416, + cf_ammo_projectile_calibration_programs = 0x0000000005030416, + cf_ammo_harvesting_calibration_programs = 0x0000000007030416, + cf_ammo_plasma_calibration_programs = 0x0000000008030416, + cf_ammo_energy_torpedo_calibration_programs = 0x0000000009030416, + cf_ammo_ioncannon_calibration_programs = 0x000000000A030416, + cf_ammo_corebooster_calibration_programs = 0x000000000B030416, + cf_ammo_mining_calibration_programs = 0x000000000C030416, + cf_ammo_industrial_aoe_calibration_programs = 0x000000000D030416, + cf_ammo_mining_probe_calibration_programs = 0x000000000E030416, + cf_ammo_rcu_calibration_programs = 0x000000000F030416, cf_module_calibration_programs = 0x0000000000040416, - cf_neuralyzer = 0x00000000000C030F, - cf_noobot = 0x0000000000000101, - cf_npc = 0x000000000000008F, - cf_npc_egg_deployer = 0x0000000000000598, - cf_npc_eggs = 0x0000000000010392, - cf_npc_indy = 0x000000000000068F, - cf_npc_nuimqol = 0x000000000000048F, - cf_npc_pelistal = 0x000000000000058F, - cf_npc_police = 0x000000000000018F, - cf_npc_test = 0x000000000000028F, - cf_npc_thelodica = 0x000000000000038F, - cf_nuimqol_commodities = 0x0000000000040214, - cf_nuimqol_crawlers = 0x0000000000020D01, - cf_nuimqol_dogtags = 0x0000000000000391, - cf_nuimqol_egg_deployer = 0x0000000000010598, - cf_nuimqol_energy_cores = 0x0000000000040514, - cf_nuimqol_heavymechs = 0x0000000000040D01, - cf_nuimqol_mechs = 0x0000000000030D01, - cf_nuimqol_robots = 0x0000000000000D01, - cf_nuimqol_robotshards = 0x0000000000030414, - cf_nuimqol_runners = 0x0000000000010D01, - cf_ore = 0x0000000000020114, - cf_organic = 0x0000000000010114, - cf_others = 0x0000000000000296, - cf_outpost = 0x0000000001010178, - cf_outpost_mill = 0x000000000108036E, - cf_outpost_prototyper = 0x000000000109036E, + cf_armor_calibration_programs = 0x0000000001040416, + cf_ew_calibration_programs = 0x0000000002040416, + cf_engineering_calibration_programs = 0x0000000003040416, + cf_industry_calibration_programs = 0x0000000004040416, + cf_gang_assist_calibration_programs = 0x0000000005040416, + cf_electronics_equipment_calibration_programs = 0x0000000006040416, + cf_robot_component_calibration_programs = 0x0000000000050416, + cf_head_calibration_programs = 0x0000000001050416, + cf_chassis_calibration_programs = 0x0000000002050416, + cf_leg_calibration_programs = 0x0000000003050416, + cf_mission_calibration_programs = 0x0000000000060416, + cf_pbs_calibration_programs = 0x0000000000070416, + cf_random_calibration_programs = 0x0000000000080416, + + cf_logical_storage = 0x0000000000000017, + + cf_robot_components = 0x0000000000000050, + cf_robot_head = 0x0000000000000150, + cf_runner_head = 0x0000000000010150, + cf_crawler_head = 0x0000000000020150, + cf_mech_head = 0x0000000000030150, + cf_heavymech_head = 0x0000000000040150, + cf_walker_head = 0x0000000000050150, + cf_robot_chassis = 0x0000000000000250, + cf_runner_chassis = 0x0000000000010250, + cf_crawler_chassis = 0x0000000000020250, + cf_mech_chassis = 0x0000000000030250, + cf_heavymech_chassis = 0x0000000000040250, + cf_walker_chassis = 0x0000000000050250, + cf_robot_leg = 0x0000000000000350, + cf_runner_leg = 0x0000000000010350, + cf_crawler_leg = 0x0000000000020350, + cf_mech_leg = 0x0000000000030350, + cf_heavymech_leg = 0x0000000000040350, + cf_walker_leg = 0x0000000000050350, + + cf_decor = 0x000000000000005A, + cf_rock = 0x000000000000015A, + cf_decor_nuimqol_misc = 0x000000000000025A, + cf_decor_thelodica_misc = 0x000000000000035A, + cf_decor_pelistal_misc = 0x000000000000045A, + cf_decor_buildings = 0x000000000000055A, + cf_decor_general = 0x000000000001055A, + cf_decor_general_element = 0x000000000101055A, + cf_decor_pelistal = 0x000000000002055A, + cf_decor_pelistal_general = 0x000000000102055A, + cf_decor_pelistal_special = 0x000000000202055A, + cf_decor_pelistal_element = 0x000000000302055A, + cf_decor_nuimqol = 0x000000000003055A, + cf_decor_nuimqol_general = 0x000000000103055A, + cf_decor_nuimqol_special = 0x000000000203055A, + cf_decor_nuimqol_element = 0x000000000303055A, + cf_decor_thelodica = 0x000000000004055A, + cf_decor_thelodica_general = 0x000000000104055A, + cf_decor_thelodica_special = 0x000000000204055A, + cf_decor_thelodica_element = 0x000000000304055A, + cf_decor_template = 0x000000000000065A, + + cf_station_services = 0x000000000000006E, + cf_markets = 0x000000000000016E, + cf_public_market = 0x000000000001016E, + cf_base_item_shop = 0x000000000002016E, + cf_public_vendor = 0x000000000001026E, + cf_vendors = 0x000000000000026E, + cf_production_facilities = 0x000000000000036E, + cf_refinery_facility = 0x000000000001036E, cf_outpost_refinery = 0x000000000101036E, - cf_outpost_repair = 0x000000000105036E, + cf_pbs_refinery = 0x000000000201036E, + cf_reprocessor_facility = 0x000000000004036E, cf_outpost_reprocessor = 0x000000000104036E, + cf_pbs_reprocessor = 0x000000000204036E, + cf_repair_facility = 0x000000000005036E, + cf_outpost_repair = 0x000000000105036E, + cf_pbs_repair = 0x000000000205036E, + cf_research_lab = 0x000000000006036E, cf_outpost_research_lab = 0x000000000106036E, - cf_overcharged_armor_resist = 0x0000000000030A0F, - cf_package_activator = 0x000000000000019B, - cf_package_activator_credit = 0x000000000003019B, - cf_package_activator_ep = 0x000000000001019B, - cf_package_activator_spark = 0x000000000002019B, - cf_paints = 0x000000000002049B, - cf_passive_hacking_sap = 0x0000000000040592, - cf_pbs = 0x0000000000030492, - cf_pbs_armor_repairer = 0x0000000007030492, - cf_pbs_aura_emitter_capsules = 0x0000000000030E9A, - cf_pbs_basic_transmitter_capsules = 0x000000000001039A, - cf_pbs_battery_capsules = 0x000000000003039A, - cf_pbs_calibration_forge_nodes = 0x0000000803030492, - cf_pbs_calibration_programs = 0x0000000000070416, - cf_pbs_capsules = 0x000000000000009A, - cf_pbs_control_tower = 0x0000000008030492, - cf_pbs_control_tower_capsules = 0x000000000000119A, - cf_pbs_core_transmitter = 0x0000000002030492, - cf_pbs_core_transmitter_capsules = 0x000000000000039A, - cf_pbs_docking_base = 0x0000000009030492, - cf_pbs_docking_base_capsules = 0x000000000000019A, - cf_pbs_effect_emitter = 0x0000000005030492, - cf_pbs_effect_emitter_capsules = 0x0000000000000E9A, - cf_pbs_effect_supplier = 0x0000000004030492, - cf_pbs_effect_supplier_capsules = 0x0000000000000D9A, - cf_pbs_egg = 0x0000000000050392, - cf_pbs_energy_well = 0x000000000A030492, - cf_pbs_energy_well_capsules = 0x000000000000129A, - cf_pbs_ew_turret_capsules = 0x000000000004109A, - cf_pbs_highway_node = 0x000000000B030492, - cf_pbs_highway_node_capsule = 0x000000000000139A, - cf_pbs_laser_turret_capsules = 0x000000000002109A, - cf_pbs_masker_tower_capsules = 0x0000000000020E9A, + cf_pbs_reseach_lab = 0x000000000206036E, + cf_robot_assembler = 0x000000000007036E, + cf_mill = 0x000000000008036E, + cf_outpost_mill = 0x000000000108036E, cf_pbs_mill = 0x000000000208036E, - cf_pbs_mill_nodes = 0x0000000503030492, - cf_pbs_miner_tower_capsules = 0x0000000000010E9A, - cf_pbs_mining_towers = 0x000000000C030492, - cf_pbs_missile_turret_capsules = 0x000000000003109A, - cf_pbs_production_capsules = 0x000000000000049A, - cf_pbs_production_ct_merge_capsules = 0x000000000007049A, - cf_pbs_production_decoder_complex_capsules = 0x000000000008049A, - cf_pbs_production_mill_capsules = 0x000000000006049A, + cf_prototyper = 0x000000000009036E, + cf_outpost_prototyper = 0x000000000109036E, + cf_pbs_prototyper = 0x000000000209036E, + cf_insurance_facility = 0x00000000000A036E, + cf_research_kit_forge = 0x00000000000B036E, + cf_calibration_program_forge = 0x00000000000C036E, + cf_mission_agent = 0x000000000000046E, + + cf_structures = 0x0000000000000078, + cf_base = 0x0000000000000178, + cf_public_docking_base = 0x0000000000010178, + cf_outpost = 0x0000000001010178, + cf_training_docking_base = 0x0000000002010178, + cf_field_terminal = 0x0000000000020178, + cf_teleport_column = 0x0000000000000278, + cf_public_teleport_column = 0x0000000000010278, + cf_dynamic_teleports = 0x0000000000060278, + cf_mobile_teleport = 0x0000000001060278, + cf_mobile_world_teleport = 0x0000000002060278, + cf_mobile_arena_teleport = 0x0000000003060278, + cf_teleport_back_home = 0x0000000004060278, + cf_training_exit_teleport = 0x0000000000070278, + + cf_groups = 0x0000000000000082, + cf_corporation = 0x0000000000000182, + cf_default_corporation = 0x0000000000010182, + cf_private_corporation = 0x0000000000020182, + cf_alliance = 0x0000000000000282, + cf_private_alliance = 0x0000000000010282, + cf_default_alliance = 0x0000000000020282, + + cf_player = 0x000000000000008C, + + cf_police = 0x000000000000008E, + + cf_npc = 0x000000000000008F, + cf_npc_police = 0x000000000000018F, + cf_npc_test = 0x000000000000028F, + cf_npc_thelodica = 0x000000000000038F, + cf_npc_nuimqol = 0x000000000000048F, + cf_npc_pelistal = 0x000000000000058F, + cf_npc_indy = 0x000000000000068F, + + cf_scan_result = 0x0000000000000090, + cf_material_scan_result = 0x0000000000000390, + cf_tile_based = 0x0000000000010390, + cf_area_based = 0x0000000000020390, + + cf_dogtags = 0x0000000000000091, + cf_pelistal_dogtags = 0x0000000000000191, + cf_thelodica_dogtags = 0x0000000000000291, + cf_nuimqol_dogtags = 0x0000000000000391, + cf_syndicate_dogtags = 0x0000000000000491, + cf_indy_dogtags = 0x0000000000000591, + def_pbs_dogtags = 0x0000000000000691, + + cf_zone_objects = 0x0000000000000092, + cf_loot_container_object = 0x0000000000000192, + cf_blob_emitter = 0x0000000000000292, + cf_eggs = 0x0000000000000392, + cf_npc_eggs = 0x0000000000010392, + cf_area_bomb = 0x0000000000020392, + cf_intrusion_pbs_eggs = 0x0000000000040392, + cf_pbs_egg = 0x0000000000050392, + cf_player_built = 0x0000000000000492, + cf_proximity_probes = 0x0000000000010492, + cf_proximity_probe = 0x0000000002010492, + cf_wall_healer = 0x0000000000020492, + cf_pbs = 0x0000000000030492, + cf_pbs_reactor = 0x0000000001030492, + cf_pbs_core_transmitter = 0x0000000002030492, cf_pbs_production_nodes = 0x0000000003030492, - cf_pbs_production_prototyper_capsules = 0x000000000004049A, - cf_pbs_production_refinery_capsules = 0x000000000001049A, - cf_pbs_production_repair_capsules = 0x000000000003049A, - cf_pbs_production_reprocessor_capsules = 0x000000000002049A, - cf_pbs_production_research_lab_capsules = 0x000000000005049A, - cf_pbs_production_upgrade_capsules = 0x0000000000000C9A, + cf_pbs_reseach_lab_nodes = 0x0000000103030492, + cf_pbs_repair_nodes = 0x0000000203030492, cf_pbs_production_upgrade_nodes = 0x0000000303030492, - cf_pbs_prototyper = 0x000000000209036E, cf_pbs_prototyper_nodes = 0x0000000403030492, - cf_pbs_railgun_turret_capsules = 0x000000000001109A, - cf_pbs_reactor = 0x0000000001030492, - cf_pbs_reactor_booster = 0x0000000000000394, - cf_pbs_reactor_capsules = 0x000000000000029A, - cf_pbs_refinery = 0x000000000201036E, + cf_pbs_mill_nodes = 0x0000000503030492, cf_pbs_refinery_nodes = 0x0000000603030492, - cf_pbs_repair = 0x000000000205036E, - cf_pbs_repair_nodes = 0x0000000203030492, - cf_pbs_repairer_capsules = 0x0000000000000F9A, - cf_pbs_reprocessor = 0x000000000204036E, cf_pbs_reprocessor_nodes = 0x0000000703030492, - cf_pbs_reseach_lab = 0x000000000206036E, - cf_pbs_reseach_lab_nodes = 0x0000000103030492, + cf_pbs_calibration_forge_nodes = 0x0000000803030492, cf_pbs_research_kit_forge_nodes = 0x0000000903030492, + cf_pbs_effect_supplier = 0x0000000004030492, + cf_pbs_effect_emitter = 0x0000000005030492, cf_pbs_turret = 0x0000000006030492, - cf_pbs_turret_capsules = 0x000000000000109A, - cf_pbs_XL_transmitter_capsules = 0x000000000002039A, - cf_pelistal_commodities = 0x0000000000020214, - cf_pelistal_crawlers = 0x0000000000020B01, - cf_pelistal_dogtags = 0x0000000000000191, - cf_pelistal_egg_deployer = 0x0000000000020598, - cf_pelistal_energy_cores = 0x0000000000030514, - cf_pelistal_heavymechs = 0x0000000000040B01, - cf_pelistal_mechs = 0x0000000000030B01, - cf_pelistal_robots = 0x0000000000000B01, - cf_pelistal_robotshards = 0x0000000000040414, - cf_pelistal_runners = 0x0000000000010B01, - cf_plant_seed = 0x0000000000000398, - cf_plasma = 0x000000000007070F, - cf_plasma_ammo = 0x000000000000060A, - cf_plasma_bomb = 0x0000000000000898, - cf_plasmagun_calibration_programs = 0x0000000003020416, - cf_player = 0x000000000000008C, - cf_player_built = 0x0000000000000492, - cf_police = 0x000000000000008E, - cf_police_turret = 0x0000000000010801, - cf_portals = 0x0000000000000C92, - cf_powergrid_upgrades = 0x000000000005030F, - cf_primary_commodities = 0x0000000000010214, - cf_private_alliance = 0x0000000000010282, - cf_private_container = 0x0000000000010915, - cf_private_corporation = 0x0000000000020182, - cf_production_facilities = 0x000000000000036E, - cf_production_items = 0x0000000000000094, - cf_projectile_ammo = 0x000000000000030A, - cf_projectile_calibration_programs = 0x0000000005020416, - cf_projectile_upgrades = 0x000000000205070F, - cf_projectiles = 0x000000000002070F, - cf_prototyper = 0x000000000009036E, - cf_proximity_probe_deployer = 0x0000000000000798, - cf_proximity_probes = 0x0000000000010492, - cf_public_container = 0x0000000000040815, - cf_public_corporation_hangar_storage = 0x0000000000050815, - cf_public_docking_base = 0x0000000000010178, - cf_public_market = 0x000000000001016E, - cf_public_teleport_column = 0x0000000000010278, - cf_public_vendor = 0x000000000001026E, - cf_railgun_ammo = 0x000000000000010A, - cf_railgun_calibration_programs = 0x0000000001020416, - cf_railgun_upgrades = 0x000000000105070F, - cf_railguns = 0x000000000004070F, - cf_random_artifacts = 0x0000000000030595, - cf_random_calibration_programs = 0x0000000000080416, - cf_random_items = 0x0000000000000595, - cf_random_research_kits = 0x0000000000000594, - cf_rare_material = 0x0000000000000714, - cf_raw_material = 0x0000000000000114, - cf_reactor_cores = 0x0000000000000294, - cf_reactor_plasma = 0x0000000000000614, - cf_reactor_sealings = 0x00000000000E030F, - cf_redeemables = 0x000000000000009B, - cf_refinery_facility = 0x000000000001036E, - cf_remote_armor_repairers = 0x000000000003010F, - cf_remote_sensor_boosters = 0x000000000002040F, - cf_repair_facility = 0x000000000005036E, - cf_reprocessor_facility = 0x000000000004036E, - cf_research_kit_forge = 0x00000000000B036E, - cf_research_kits = 0x0000000000000194, - cf_research_lab = 0x000000000006036E, - cf_resistance_plating = 0x000000000504010F, - cf_rifts = 0x0000000000000B92, - cf_robot_assembler = 0x000000000007036E, - cf_robot_calibration_programs = 0x0000000000010416, - cf_robot_chassis = 0x0000000000000250, - cf_robot_component_calibration_programs = 0x0000000000050416, - cf_robot_components = 0x0000000000000050, - cf_robot_equipment = 0x000000000000000F, - cf_robot_head = 0x0000000000000150, - cf_robot_inventory = 0x0000000000030915, - cf_robot_leg = 0x0000000000000350, - cf_robots = 0x0000000000000001, - cf_robotshards = 0x0000000000000414, - cf_rock = 0x000000000000015A, - cf_runner_calibration_programs = 0x0000000001010416, - cf_runner_chassis = 0x0000000000010250, - cf_runner_head = 0x0000000000010150, - cf_runner_leg = 0x0000000000010350, - cf_runners = 0x0000000000000201, - cf_scan_result = 0x0000000000000090, - cf_sensor_boosters = 0x000000000001040F, - cf_sensor_dampeners = 0x000000000003050F, - cf_sensor_jammers = 0x000000000002050F, - cf_shield_equipment = 0x000000000000020F, - cf_shield_generators = 0x000000000001020F, - cf_shield_hardener = 0x000000000002020F, - cf_shortrange_webber = 0x000000000101050F, - cf_siege_hack_modules = 0x000000000006050F, - cf_simple_switch = 0x0000000002040696, - cf_single_projectile = 0x000000000402070F, - cf_small_aoe_projectile_tile = 0x000001010502070F, - cf_small_aoe_unit = 0x000001020502070F, - cf_small_aoe_unit_ammo = 0x0000000000010E0A, - cf_small_armor_plates = 0x000000000101010F, - cf_small_armor_repairers = 0x000000000102010F, - cf_small_core_batteries = 0x000000000108030F, - cf_small_core_boosters = 0x000000000109030F, - cf_small_crystals = 0x000000000001020A, - cf_small_drillers = 0x000000000101060F, - cf_small_energy_neutralizers = 0x000000000103030F, - cf_small_energy_transferers = 0x000000000101030F, - cf_small_energy_vampires = 0x000000000102030F, - cf_small_energytorpedo = 0x000000000109070F, - cf_small_energytorpedo_ammo = 0x0000000000010C0A, - cf_small_harvesters = 0x000000000106060F, - cf_small_industrial_aoe = 0x00000000010A070F, - cf_small_industrial_aoe_tile_ammo = 0x0000000000010D0A, - cf_small_ioncannon = 0x000000000108070F, - cf_small_ioncannon_ammo = 0x0000000000010B0A, - cf_small_lasers = 0x000000000101070F, - cf_small_missile_ammo = 0x000000000001040A, - cf_small_missile_launchers = 0x000000000103070F, - cf_small_plasma = 0x000000000107070F, - cf_small_plasma_ammo = 0x000000000001060A, - cf_small_projectile_ammo = 0x000000000001030A, - cf_small_railgun_ammo = 0x000000000001010A, - cf_small_railguns = 0x000000000104070F, - cf_small_remote_armor_repairers = 0x000000000103010F, - cf_small_shield_generator = 0x000000000101020F, - cf_small_single_projectile = 0x000000010402070F, - cf_small_terraformer = 0x000000000001080F, - cf_soil = 0x0000000000000314, + cf_pbs_armor_repairer = 0x0000000007030492, + cf_pbs_control_tower = 0x0000000008030492, + cf_pbs_docking_base = 0x0000000009030492, + cf_pbs_energy_well = 0x000000000A030492, + cf_pbs_highway_node = 0x000000000B030492, + cf_pbs_mining_towers = 0x000000000C030492, + cf_landmines = 0x00000000040492, + cf_light_landmines = 0x0000000001040492, + cf_medium_landmines = 0x0000000002040492, + cf_heavy_landmines = 0x0000000003040492, + cf_intrusion_objects = 0x0000000000000592, + cf_destrucion_sap = 0x0000000000010592, cf_specimen_processing_sap = 0x0000000000020592, - cf_stance_moduls = 0x000000000008040F, - cf_starter_item = 0x0000000000000395, - cf_station_services = 0x000000000000006E, - cf_stealth_modules = 0x00000000000A040F, - cf_structures = 0x0000000000000078, - cf_supressor_boosters = 0x000000000009050F, - cf_syndicate_crawlers = 0x0000000000020F01, - cf_syndicate_dogtags = 0x0000000000000491, - cf_syndicate_heavymechs = 0x0000000000040F01, - cf_syndicate_mechs = 0x0000000000030F01, - cf_syndicate_robots = 0x0000000000000F01, - cf_syndicate_runners = 0x0000000000010F01, - cf_system_container = 0x0000000000010815, - cf_tactial_modules = 0x0000000000000A0F, - cf_target_painter = 0x00000000000B040F, - cf_teleport_back_home = 0x0000000004060278, - cf_teleport_channel_enabler = 0x0000000000000892, - cf_teleport_column = 0x0000000000000278, + cf_active_hacking_sap = 0x0000000000030592, + cf_passive_hacking_sap = 0x0000000000040592, + cf_intrusion_turrets = 0x0000000000050592, + cf_arena_guard = 0x0000000000000692, cf_terraform_buoy = 0x0000000000000792, - cf_terraform_buoy_capsule = 0x0000000000000C98, - cf_terraform_equipment = 0x00000000000A060F, - cf_terraforming_ammo = 0x000000000000100A, - cf_terraforming_digger = 0x000000000002080F, - cf_terraforming_equipment = 0x000000000000080F, - cf_terraforming_raiser = 0x000000000003080F, - cf_test_robot_punchbags = 0x0000000000010A01, - cf_test_robots = 0x0000000000000A01, - cf_testnpc = 0x0000000000020A01, - cf_thelodica_commodities = 0x0000000000030214, - cf_thelodica_crawlers = 0x0000000000020C01, - cf_thelodica_dogtags = 0x0000000000000291, - cf_thelodica_egg_deployer = 0x0000000000030598, - cf_thelodica_energy_cores = 0x0000000000020514, - cf_thelodica_heavymechs = 0x0000000000040C01, - cf_thelodica_mechs = 0x0000000000030C01, - cf_thelodica_robots = 0x0000000000000C01, - cf_thelodica_robotshards = 0x0000000000020414, - cf_thelodica_runners = 0x0000000000010C01, - cf_thermal_armor_hardeners = 0x000000000404010F, - cf_thermal_kers = 0x00000000030B030F, - cf_tile_based = 0x0000000000010390, - cf_tracking_upgrades = 0x000000000007040F, - cf_training_docking_base = 0x0000000002010178, - cf_training_exit_teleport = 0x0000000000070278, + cf_teleport_channel_enabler = 0x0000000000000892, cf_training_items = 0x0000000000000992, - cf_turrets = 0x0000000000000801, + cf_gate = 0x0000000000000A92, + cf_rifts = 0x0000000000000B92, + cf_portals = 0x0000000000000C92, + cf_sentry_turrets = 0x0000000000000D92, + cf_mining_turrets = 0x0000000000000E92, + cf_harvesting_turrets = 0x0000000000000F92, + cf_combat_drones = 0x0000000000001092, + + cf_production_items = 0x0000000000000094, + cf_research_kits = 0x0000000000000194, + cf_reactor_cores = 0x0000000000000294, + cf_pbs_reactor_booster = 0x0000000000000394, + cf_kernels = 0x0000000000000494, + cf_random_research_kits = 0x0000000000000594, + cf_datashards = 0x0000000000000694, + + cf_mission_items = 0x0000000000000095, + cf_courier_items = 0x0000000000000195, cf_tutorial_industry_items = 0x0000000000000295, + cf_starter_item = 0x0000000000000395, + cf_mission_mineral = 0x0000000000000495, + cf_random_items = 0x0000000000000595, + cf_generic_random_items = 0x0000000000010595, + cf_component_items = 0x0000000000020595, + cf_random_artifacts = 0x0000000000030595, + cf_geoscan_documents = 0x0000000000000695, + cf_intel_documents = 0x0000000000000795, + + cf_items = 0x0000000000000096, + cf_admin_items = 0x0000000000000196, + cf_others = 0x0000000000000296, + cf_item_speed_boosters = 0x0000000000000396, cf_tutorial_punchbag = 0x0000000000000496, - cf_vendors = 0x000000000000026E, - cf_visibility_based_probe = 0x0000000002010492, - cf_volume_wrapper_container = 0x0000000000000B15, - cf_volume_wrapper_container_old = 0x0000000000080815, - cf_walker_calibration_programs = 0x0000000005010416, - cf_walker_chassis = 0x0000000000050250, - cf_walker_head = 0x0000000000050150, - cf_walker_leg = 0x0000000000050350, - cf_walkers = 0x0000000000000601, - cf_walking_stabilizers = 0x000000000006030F, - cf_wall_builder_ammo = 0x000000000002110A, - cf_wall_healer = 0x0000000000020492, - cf_wall_healer_capsule = 0x0000000000000A98, - cf_weapon_calibration_programs = 0x0000000000020416, - cf_weapon_stabilizer = 0x000000000505070F, - cf_weapon_upgrade_calibration_programs = 0x0000000009020416, - cf_weapon_upgrades = 0x000000000005070F, - cf_weapons = 0x000000000000070F, - cf_webber = 0x000000000001050F, - cf_world_mobile_teleport_capsule = 0x0000000000020198, + cf_mission_structures = 0x0000000000000696, + cf_kiosk = 0x0000000000010696, + cf_mission_switch = 0x0000000000040696, + cf_alarm_switch = 0x0000000001040696, + cf_simple_switch = 0x0000000002040696, + cf_item_supply = 0x0000000000050696, cf_zone_item_shop = 0x0000000000000796, - cf_zone_objects = 0x0000000000000092, - def_pbs_dogtags = 0x0000000000000691, + cf_gift_packages = 0x0000000000000896, + cf_consumable_items = 0x0000000000000996, + cf_consumable_boosters = 0x0000000000010996, + + cf_field_accessories = 0x0000000000000098, + cf_mobile_teleport_capsule = 0x0000000000000198, + cf_inland_mobile_teleport_capsule = 0x0000000000010198, + cf_world_mobile_teleport_capsule = 0x0000000000020198, + cf_container_capsule = 0x0000000000000298, + cf_plant_seed = 0x0000000000000398, + cf_egg_deployers = 0x0000000000000498, + cf_area_bomb_deployer = 0x0000000000020498, + cf_intrusion_pbs_deployers = 0x0000000000040498, + cf_npc_egg_deployer = 0x0000000000000598, + cf_nuimqol_egg_deployer = 0x0000000000010598, + cf_pelistal_egg_deployer = 0x0000000000020598, + cf_thelodica_egg_deployer = 0x0000000000030598, + cf_industrial_egg_deployer = 0x0000000000040598, + cf_mission_egg_deployer = 0x0000000000050598, + cf_arena_teleport_deployer = 0x0000000000000698, + cf_proximity_probe_deployer = 0x0000000000000798, + cf_plasma_bomb = 0x0000000000000898, + cf_deployable_structure = 0x0000000000000998, + cf_wall_healer_capsule = 0x0000000000000A98, + cf_terraform_buoy_capsule = 0x0000000000000C98, + cf_landmine_deployer = 0x0000000000000D98, + + cf_dynamic_cprg = 0x0000000000000099, + + cf_pbs_capsules = 0x000000000000009A, + cf_pbs_docking_base_capsules = 0x000000000000019A, + cf_pbs_reactor_capsules = 0x000000000000029A, + cf_pbs_core_transmitter_capsules = 0x000000000000039A, + cf_pbs_basic_transmitter_capsules = 0x000000000001039A, + cf_pbs_XL_transmitter_capsules = 0x000000000002039A, + cf_pbs_battery_capsules = 0x000000000003039A, + cf_pbs_production_capsules = 0x000000000000049A, + cf_pbs_production_refinery_capsules = 0x000000000001049A, + cf_pbs_production_reprocessor_capsules = 0x000000000002049A, + cf_pbs_production_repair_capsules = 0x000000000003049A, + cf_pbs_production_prototyper_capsules = 0x000000000004049A, + cf_pbs_production_research_lab_capsules = 0x000000000005049A, + cf_pbs_production_mill_capsules = 0x000000000006049A, + cf_pbs_production_ct_merge_capsules = 0x000000000007049A, + cf_pbs_production_decoder_complex_capsules = 0x000000000008049A, + cf_pbs_production_upgrade_capsules = 0x0000000000000C9A, + cf_pbs_effect_supplier_capsules = 0x0000000000000D9A, + cf_pbs_effect_emitter_capsules = 0x0000000000000E9A, + cf_pbs_miner_tower_capsules = 0x0000000000010E9A, + cf_pbs_masker_tower_capsules = 0x0000000000020E9A, + cf_pbs_aura_emitter_capsules = 0x0000000000030E9A, + cf_pbs_repairer_capsules = 0x0000000000000F9A, + cf_pbs_turret_capsules = 0x000000000000109A, + cf_pbs_railgun_turret_capsules = 0x000000000001109A, + cf_pbs_laser_turret_capsules = 0x000000000002109A, + cf_pbs_missile_turret_capsules = 0x000000000003109A, + cf_pbs_ew_turret_capsules = 0x000000000004109A, + cf_pbs_control_tower_capsules = 0x000000000000119A, + cf_pbs_energy_well_capsules = 0x000000000000129A, + cf_pbs_highway_node_capsule = 0x000000000000139A, + + cf_redeemables = 0x000000000000009B, + cf_package_activator = 0x000000000000019B, + cf_package_activator_ep = 0x000000000001019B, + cf_package_activator_spark = 0x000000000002019B, + cf_package_activator_credit = 0x000000000003019B, + cf_ice = 0x000000000000029B, + cf_mission_coin = 0x000000000000039B, + cf_lottery_items = 0x000000000000049B, + cf_ep_boosters = 0x000000000001049B, + cf_paints = 0x000000000002049B, + cf_ct_capsules = 0x000000000003049B, + cf_ct_capsules_ammo = 0x000000000103049B, + cf_ct_capsules_ammo_laser = 0x000000010103049B, + cf_ct_capsules_ammo_railgun = 0x000000020103049B, + cf_ct_capsules_ammo_projectile = 0x000000030103049B, + cf_ct_capsules_ammo_missile = 0x000000040103049B, + cf_ct_capsules_equipment = 0x000000000203049B, + cf_ct_capsules_equipment_armor = 0x000000010203049B, + cf_ct_capsules_equipment_ewar = 0x000000020203049B, + cf_ct_capsules_equipment_electronics = 0x000000030203049B, + cf_ct_capsules_equipment_engineering = 0x000000040203049B, + cf_ct_capsules_equipment_industrial = 0x000000050203049B, + cf_ct_capsules_equipment_shield = 0x000000060203049B, + cf_ct_capsules_equipment_weapons = 0x000000070203049B, + cf_ct_capsules_equipment_nexus = 0x000000080203049B, + cf_ct_capsules_robot = 0x000000000303049B, + cf_ct_capsules_robot_pelistal = 0x000000010303049B, + cf_ct_capsules_robot_pelistal_light = 0x000001010303049B, + cf_ct_capsules_robot_pelistal_assault = 0x000002010303049B, + cf_ct_capsules_robot_pelistal_mech = 0x000003010303049B, + cf_ct_capsules_robot_pelistal_heavymech = 0x000004010303049B, + cf_ct_capsules_robot_thelodica = 0x000000020303049B, + cf_ct_capsules_robot_thelodica_light = 0x000001020303049B, + cf_ct_capsules_robot_thelodica_assault = 0x000002020303049B, + cf_ct_capsules_robot_thelodica_mech = 0x000003020303049B, + cf_ct_capsules_robot_thelodica_heavymech = 0x000004020303049B, + cf_ct_capsules_robot_nuimqol = 0x000000030303049B, + cf_ct_capsules_robot_nuimqol_light = 0x000001030303049B, + cf_ct_capsules_robot_nuimqol_assault = 0x000002030303049B, + cf_ct_capsules_robot_nuimqol_mech = 0x000003030303049B, + cf_ct_capsules_robot_nuimqol_heavymech = 0x000004030303049B, + cf_ct_capsules_robot_industrial = 0x000000040303049B, + cf_ct_capsules_robot_industrial_light = 0x000001040303049B, + cf_ct_capsules_robot_industrial_assault = 0x000002040303049B, + cf_ct_capsules_robot_industrial_mech = 0x000003040303049B, + cf_ct_capsules_robot_industrial_heavymech = 0x000004040303049B, + cf_ct_capsules_robot_syndicate = 0x000000050303049B, + cf_ct_capsules_robot_syndicate_light = 0x000001050303049B, + cf_ct_capsules_robot_syndicate_assault = 0x000002050303049B, + cf_ct_capsules_robot_syndicate_mech = 0x000003050303049B, + cf_ct_capsules_robot_syndicate_heavymech = 0x000004050303049B, + cf_ct_capsules_robot_syndicate_commandbot = 0x000005050303049B, + cf_ct_capsules_misc = 0x000000000403049B, cf_respec_tokens = 0x000000000004049B, cf_spark_teleport_devices = 0x000000000005049B, } diff --git a/src/Perpetuum.ExportedTypes/EffectCategory.cs b/src/Perpetuum.ExportedTypes/EffectCategory.cs index 8b831bf54..836fa5ec6 100644 --- a/src/Perpetuum.ExportedTypes/EffectCategory.cs +++ b/src/Perpetuum.ExportedTypes/EffectCategory.cs @@ -4,55 +4,56 @@ namespace Perpetuum.ExportedTypes { - [System.Flags] - public enum EffectCategory : long - { - undefined = 0, - effcat_aggressor = 0x0000000000004000, - effcat_blob_emission_modulator = 0x0000000010000000, - effcat_consumable_effects = 0x0000008000000000, - effcat_detection_stealth = 0x0000000020000000, - effcat_eccm = 0x0000000100000000, - effcat_eccmcureable_effects = 0x0000000200000000, - effcat_gang_effect = 0x0000000000000040, - effcat_gang_effect_coordinated_maneuvering = 0x0000000000100000, - effcat_gang_effect_core_management = 0x0000000001000000, - effcat_gang_effect_defense = 0x0000000000000080, - effcat_gang_effect_ewar = 0x0000000000040000, - effcat_gang_effect_fast_extraction = 0x0000000002000000, - effcat_gang_effect_gathering = 0x0000000000000400, - effcat_gang_effect_information = 0x0000000000000100, - effcat_gang_effect_maintance = 0x0000000000400000, - effcat_gang_effect_precision_firing = 0x0000000000800000, - effcat_gang_effect_shared_dataprocessing = 0x0000000000080000, - effcat_gang_effect_shield_calculations = 0x0000000000200000, - effcat_gang_effect_siege = 0x0000000000000800, - effcat_gang_effect_speed = 0x0000000000000200, - effcat_highway = 0x0000000080000000, - effcat_intrusion_effect = 0x0000000800000000, - effcat_invulnerable = 0x0000000000010000, - effcat_jamm = 0x0000000000001000, - effcat_movement_imparing = 0x0000000000000001, - effcat_pbs_booster_effects = 0x0000001000000000, - effcat_pbs_engineering_aura = 0x0000020000000000, - effcat_pbs_gap_generator_effect = 0x0000002000000000, - effcat_pbs_industry_aura = 0x0000040000000000, - effcat_pbs_mining_tower_effect = 0x0000004000000000, - effcat_pbs_sensors_aura = 0x0000010000000000, - effcat_pvp_flag = 0x0000000000002000, - effcat_range_increasing = 0x0000000000000020, - effcat_resists = 0x0000000000000008, - effcat_safe_spot = 0x0000000004000000, - effcat_sensor_amplify = 0x0000000000000002, - effcat_sensor_supress = 0x0000000000000004, - effcat_shield = 0x0000000000000010, - effcat_speed_booster = 0x0000000000008000, - effcat_tag = 0x0000000000020000, - effcat_target_paint = 0x0000000040000000, - effcat_teleport_effects = 0x0000000008000000, - effcat_terrain_object_effects = 0x0000080000000000, - effcat_zero_core_drop = 0x0000000400000000, + [System.Flags] + public enum EffectCategory : long + { + undefined = 0, + effcat_movement_imparing = 0x0000000000000001, + effcat_sensor_amplify = 0x0000000000000002, + effcat_sensor_supress = 0x0000000000000004, + effcat_resists = 0x0000000000000008, + effcat_shield = 0x0000000000000010, + effcat_range_increasing = 0x0000000000000020, + effcat_gang_effect = 0x0000000000000040, + effcat_gang_effect_defense = 0x0000000000000080, + effcat_gang_effect_information = 0x0000000000000100, + effcat_gang_effect_speed = 0x0000000000000200, + effcat_gang_effect_gathering = 0x0000000000000400, + effcat_gang_effect_siege = 0x0000000000000800, + effcat_jamm = 0x0000000000001000, + effcat_pvp_flag = 0x0000000000002000, + effcat_aggressor = 0x0000000000004000, + effcat_speed_booster = 0x0000000000008000, + effcat_invulnerable = 0x0000000000010000, + effcat_tag = 0x0000000000020000, + effcat_gang_effect_ewar = 0x0000000000040000, + effcat_gang_effect_shared_dataprocessing = 0x0000000000080000, + effcat_gang_effect_coordinated_maneuvering = 0x0000000000100000, + effcat_gang_effect_shield_calculations = 0x0000000000200000, + effcat_gang_effect_maintance = 0x0000000000400000, + effcat_gang_effect_precision_firing = 0x0000000000800000, + effcat_gang_effect_core_management = 0x0000000001000000, + effcat_gang_effect_fast_extraction = 0x0000000002000000, + effcat_safe_spot = 0x0000000004000000, + effcat_teleport_effects = 0x0000000008000000, + effcat_blob_emission_modulator = 0x0000000010000000, + effcat_detection_stealth = 0x0000000020000000, + effcat_target_paint = 0x0000000040000000, + effcat_highway = 0x0000000080000000, + effcat_eccm = 0x0000000100000000, + effcat_eccmcureable_effects = 0x0000000200000000, + effcat_zero_core_drop = 0x0000000400000000, + effcat_intrusion_effect = 0x0000000800000000, + effcat_pbs_booster_effects = 0x0000001000000000, + effcat_pbs_gap_generator_effect = 0x0000002000000000, + effcat_pbs_mining_tower_effect = 0x0000004000000000, + effcat_consumable_effects = 0x0000008000000000, + effcat_pbs_sensors_aura = 0x0000010000000000, + effcat_pbs_engineering_aura = 0x0000020000000000, + effcat_pbs_industry_aura = 0x0000040000000000, + effcat_terrain_object_effects = 0x0000080000000000, effcat_zone_effects = 0x0000100000000000, // OPP: New Zone effects - effcat_environmental_effects = 0x0000200000000000 // OPP: New Zone effects + effcat_environmental_effects = 0x0000200000000000, // OPP: New Zone effects + effcat_mine_detection = 0x0000400000000000, // OPP: Mine detection } } diff --git a/src/Perpetuum.ExportedTypes/EffectType.cs b/src/Perpetuum.ExportedTypes/EffectType.cs index 97ef7bccd..54e22e25b 100644 --- a/src/Perpetuum.ExportedTypes/EffectType.cs +++ b/src/Perpetuum.ExportedTypes/EffectType.cs @@ -5,103 +5,103 @@ namespace Perpetuum.ExportedTypes { - public enum EffectType - { - undefined = 0, - effect_aggressor = 24, - effect_armor_hardener = 23, - effect_aura_gang_armor_max = 18, - effect_aura_gang_core_recharge_time = 35, - effect_aura_gang_core_usage_gathering = 21, - effect_aura_gang_critical_hit_chance = 34, - effect_aura_gang_ewar_optimal = 29, - effect_aura_gang_fast_extraction = 36, - effect_aura_gang_locking_range = 19, - effect_aura_gang_locking_time = 30, - effect_aura_gang_repaired_amount = 33, - effect_aura_gang_shield_absorbtion_ratio = 32, - effect_aura_gang_siege = 22, - effect_aura_gang_signature_radius = 31, - effect_aura_gang_speed = 20, - effect_blob_emission_modulator = 43, - effect_chemical_resist = 11, - effect_consumable_speed_max = 92, - effect_demobilizer = 2, - effect_despawn_timer = 39, - effect_detection = 44, - effect_eccm = 48, - effect_eccm_lockdrop = 49, - effect_explosive_resist = 14, - effect_extended_range = 17, - effect_highway = 47, - effect_intrusion_core_lvl1 = 53, - effect_intrusion_core_lvl2 = 61, - effect_intrusion_core_lvl3 = 68, - effect_intrusion_detection_lvl1 = 50, - effect_intrusion_detection_lvl2 = 58, - effect_intrusion_detection_lvl3 = 65, - effect_intrusion_engineering_lvl4_combined = 74, - effect_intrusion_geoscan_lvl1 = 57, - effect_intrusion_geoscan_lvl2 = 64, - effect_intrusion_geoscan_lvl3 = 71, - effect_intrusion_harvester_lvl1 = 55, - effect_intrusion_harvester_lvl2 = 62, - effect_intrusion_harvester_lvl3 = 69, - effect_intrusion_industrial_lvl4_combined = 73, - effect_intrusion_masking_lvl1 = 51, - effect_intrusion_masking_lvl2 = 59, - effect_intrusion_masking_lvl3 = 66, - effect_intrusion_mining_lvl1 = 52, - effect_intrusion_mining_lvl2 = 60, - effect_intrusion_mining_lvl3 = 67, - effect_intrusion_repair_lvl1 = 56, - effect_intrusion_repair_lvl2 = 63, - effect_intrusion_repair_lvl3 = 70, - effect_intrusion_signals_lvl4_combined = 72, - effect_invulnerable = 26, - effect_kinetic_resist = 12, - effect_pbs_booster_cycle_time_lvl1 = 78, - effect_pbs_booster_cycle_time_lvl2 = 81, - effect_pbs_booster_cycle_time_lvl3 = 84, - effect_pbs_booster_resist_lvl1 = 76, - effect_pbs_booster_resist_lvl2 = 79, - effect_pbs_booster_resist_lvl3 = 82, - effect_pbs_booster_sensor_lvl1 = 77, - effect_pbs_booster_sensor_lvl2 = 80, - effect_pbs_booster_sensor_lvl3 = 83, - effect_pbs_engineering_lvl1 = 94, - effect_pbs_engineering_lvl2 = 97, - effect_pbs_engineering_lvl3 = 100, - effect_pbs_gap_generator_masking_lvl1 = 85, - effect_pbs_gap_generator_masking_lvl2 = 86, - effect_pbs_gap_generator_masking_lvl3 = 87, - effect_pbs_industry_lvl1 = 95, - effect_pbs_industry_lvl2 = 98, - effect_pbs_industry_lvl3 = 101, - effect_pbs_mining_tower_gammaterial_lvl1 = 88, - effect_pbs_mining_tower_gammaterial_lvl2 = 89, - effect_pbs_mining_tower_gammaterial_lvl3 = 90, - effect_pbs_reinforce = 91, - effect_pbs_sensors_lvl1 = 93, - effect_pbs_sensors_lvl2 = 96, - effect_pbs_sensors_lvl3 = 99, - effect_pvp = 27, - effect_remote_sensor_boost = 4, - effect_safe_spot = 38, - effect_sensor_boost = 3, - effect_sensor_supress = 5, - effect_shield = 16, - effect_shield_hardener = 15, - effect_speed_booster = 25, - effect_stealth = 45, - effect_swiss_army_knife = 75, - effect_syndicate_area = 37, - effect_tag = 28, - effect_target_painting = 46, - effect_teleport_cooldown = 40, - effect_teleport_self_enabler = 102, - effect_teleport_sickness = 42, - effect_thermal_resist = 13, + public enum EffectType + { + undefined = 0, + effect_aggressor = 24, + effect_armor_hardener = 23, + effect_aura_gang_armor_max = 18, + effect_aura_gang_core_recharge_time = 35, + effect_aura_gang_core_usage_gathering = 21, + effect_aura_gang_critical_hit_chance = 34, + effect_aura_gang_ewar_optimal = 29, + effect_aura_gang_fast_extraction = 36, + effect_aura_gang_locking_range = 19, + effect_aura_gang_locking_time = 30, + effect_aura_gang_repaired_amount = 33, + effect_aura_gang_shield_absorbtion_ratio = 32, + effect_aura_gang_siege = 22, + effect_aura_gang_signature_radius = 31, + effect_aura_gang_speed = 20, + effect_blob_emission_modulator = 43, + effect_chemical_resist = 11, + effect_consumable_speed_max = 92, + effect_demobilizer = 2, + effect_despawn_timer = 39, + effect_detection = 44, + effect_eccm = 48, + effect_eccm_lockdrop = 49, + effect_explosive_resist = 14, + effect_extended_range = 17, + effect_highway = 47, + effect_intrusion_core_lvl1 = 53, + effect_intrusion_core_lvl2 = 61, + effect_intrusion_core_lvl3 = 68, + effect_intrusion_detection_lvl1 = 50, + effect_intrusion_detection_lvl2 = 58, + effect_intrusion_detection_lvl3 = 65, + effect_intrusion_engineering_lvl4_combined = 74, + effect_intrusion_geoscan_lvl1 = 57, + effect_intrusion_geoscan_lvl2 = 64, + effect_intrusion_geoscan_lvl3 = 71, + effect_intrusion_harvester_lvl1 = 55, + effect_intrusion_harvester_lvl2 = 62, + effect_intrusion_harvester_lvl3 = 69, + effect_intrusion_industrial_lvl4_combined = 73, + effect_intrusion_masking_lvl1 = 51, + effect_intrusion_masking_lvl2 = 59, + effect_intrusion_masking_lvl3 = 66, + effect_intrusion_mining_lvl1 = 52, + effect_intrusion_mining_lvl2 = 60, + effect_intrusion_mining_lvl3 = 67, + effect_intrusion_repair_lvl1 = 56, + effect_intrusion_repair_lvl2 = 63, + effect_intrusion_repair_lvl3 = 70, + effect_intrusion_signals_lvl4_combined = 72, + effect_invulnerable = 26, + effect_kinetic_resist = 12, + effect_pbs_booster_cycle_time_lvl1 = 78, + effect_pbs_booster_cycle_time_lvl2 = 81, + effect_pbs_booster_cycle_time_lvl3 = 84, + effect_pbs_booster_resist_lvl1 = 76, + effect_pbs_booster_resist_lvl2 = 79, + effect_pbs_booster_resist_lvl3 = 82, + effect_pbs_booster_sensor_lvl1 = 77, + effect_pbs_booster_sensor_lvl2 = 80, + effect_pbs_booster_sensor_lvl3 = 83, + effect_pbs_engineering_lvl1 = 94, + effect_pbs_engineering_lvl2 = 97, + effect_pbs_engineering_lvl3 = 100, + effect_pbs_gap_generator_masking_lvl1 = 85, + effect_pbs_gap_generator_masking_lvl2 = 86, + effect_pbs_gap_generator_masking_lvl3 = 87, + effect_pbs_industry_lvl1 = 95, + effect_pbs_industry_lvl2 = 98, + effect_pbs_industry_lvl3 = 101, + effect_pbs_mining_tower_gammaterial_lvl1 = 88, + effect_pbs_mining_tower_gammaterial_lvl2 = 89, + effect_pbs_mining_tower_gammaterial_lvl3 = 90, + effect_pbs_reinforce = 91, + effect_pbs_sensors_lvl1 = 93, + effect_pbs_sensors_lvl2 = 96, + effect_pbs_sensors_lvl3 = 99, + effect_pvp = 27, + effect_remote_sensor_boost = 4, + effect_safe_spot = 38, + effect_sensor_boost = 3, + effect_sensor_supress = 5, + effect_shield = 16, + effect_shield_hardener = 15, + effect_speed_booster = 25, + effect_stealth = 45, + effect_swiss_army_knife = 75, + effect_syndicate_area = 37, + effect_tag = 28, + effect_target_painting = 46, + effect_teleport_cooldown = 40, + effect_teleport_self_enabler = 102, + effect_teleport_sickness = 42, + effect_thermal_resist = 13, // New effects - OPP effect_beta_bonus = 103, effect_beta2_bonus = 104, @@ -120,6 +120,8 @@ public enum EffectType effect_gamma_t1 = 117, effect_gamma_t2 = 118, effect_gamma_t3 = 119, - effect_gamma_tc = 120 + effect_gamma_tc = 120, + effect_mine_detector = 121, + effect_tellesis = 122, } } diff --git a/src/Perpetuum.RequestHandlers/Characters/CharacterSelect.cs b/src/Perpetuum.RequestHandlers/Characters/CharacterSelect.cs index a2e1e744a..48e36298a 100644 --- a/src/Perpetuum.RequestHandlers/Characters/CharacterSelect.cs +++ b/src/Perpetuum.RequestHandlers/Characters/CharacterSelect.cs @@ -45,7 +45,7 @@ public void HandleRequest(IRequest request) { character.ZoneId = null; character.ZonePosition = null; - character.GetCurrentDockingBase()?.JoinChannel(character); + character.GetCurrentDockingBase()?.TryJoinChannel(character); } var corporation = character.GetCorporation(); diff --git a/src/Perpetuum.RequestHandlers/ProximityProbeGetRegistrationInfo.cs b/src/Perpetuum.RequestHandlers/ProximityProbeGetRegistrationInfo.cs index a9ab527d6..cbb86c7a6 100644 --- a/src/Perpetuum.RequestHandlers/ProximityProbeGetRegistrationInfo.cs +++ b/src/Perpetuum.RequestHandlers/ProximityProbeGetRegistrationInfo.cs @@ -18,7 +18,7 @@ public void HandleRequest(IRequest request) var probeEid = request.Data.GetOrDefault(k.eid); var character = request.Session.Character; - var probe = _unitHelper.GetUnitOrThrow(probeEid); + var probe = _unitHelper.GetUnitOrThrow(probeEid); probe.HasAccess(character).ThrowIfError(); var result = probe.GetProbeRegistrationInfo(); diff --git a/src/Perpetuum.RequestHandlers/ProximityProbeList.cs b/src/Perpetuum.RequestHandlers/ProximityProbeList.cs index 3d5ebaaa4..8747d9a07 100644 --- a/src/Perpetuum.RequestHandlers/ProximityProbeList.cs +++ b/src/Perpetuum.RequestHandlers/ProximityProbeList.cs @@ -21,10 +21,10 @@ public void HandleRequest(IRequest request) var corporation = character.GetPrivateCorporationOrThrow(); var role = corporation.GetMemberRole(character); - var allProbes = ProximityProbeBase.IsAllProbesVisible(role); - var probeEids = allProbes ? corporation.GetProximityProbeEids() : PBSRegisterHelper.PBSRegGetEidsByRegisteredCharacter(character); + var allProbes = ProximityDeviceBase.IsAllProbesVisible(role); + var probeEids = allProbes ? corporation.GetProximityProbeEids().Union(corporation.GetLandMineEids()) : PBSRegisterHelper.PBSRegGetEidsByRegisteredCharacter(character); - var probesDict = _zoneManager.Zones.GetUnits() + var probesDict = _zoneManager.Zones.GetUnits() .Where(probeBase => probeEids.Contains(probeBase.Eid)) .ToDictionary("c", p => p.ToDictionary()); diff --git a/src/Perpetuum.RequestHandlers/ProximityProbeRegisterSet.cs b/src/Perpetuum.RequestHandlers/ProximityProbeRegisterSet.cs index 0feef1e6a..424961f91 100644 --- a/src/Perpetuum.RequestHandlers/ProximityProbeRegisterSet.cs +++ b/src/Perpetuum.RequestHandlers/ProximityProbeRegisterSet.cs @@ -29,7 +29,7 @@ public void HandleRequest(IRequest request) playersToRegister.Length.ThrowIfEqual(0, ErrorCodes.WTFErrorMedicalAttentionSuggested); - var probe = _unitHelper.GetUnitOrThrow(probeEid); + var probe = _unitHelper.GetUnitOrThrow(probeEid); probe.HasAccess(character).ThrowIfError(); var corporation = character.GetPrivateCorporationOrThrow(); diff --git a/src/Perpetuum.RequestHandlers/ProximityProbeSetName.cs b/src/Perpetuum.RequestHandlers/ProximityProbeSetName.cs index 61db99fbf..7c7bb2edf 100644 --- a/src/Perpetuum.RequestHandlers/ProximityProbeSetName.cs +++ b/src/Perpetuum.RequestHandlers/ProximityProbeSetName.cs @@ -23,7 +23,7 @@ public void HandleRequest(IRequest request) var probeName = request.Data.GetOrDefault(k.name); var character = request.Session.Character; - var probe = _unitHelper.GetUnitOrThrow(probeEid); + var probe = _unitHelper.GetUnitOrThrow(probeEid); probe.HasAccess(character).ThrowIfError(); probe.Name = probeName; probe.Save(); diff --git a/src/Perpetuum.RequestHandlers/UseLotteryItem.cs b/src/Perpetuum.RequestHandlers/UseLotteryItem.cs index 7f0260681..9637c4512 100644 --- a/src/Perpetuum.RequestHandlers/UseLotteryItem.cs +++ b/src/Perpetuum.RequestHandlers/UseLotteryItem.cs @@ -1,3 +1,8 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Transactions; using Perpetuum.Accounting; using Perpetuum.Accounting.Characters; using Perpetuum.Common.Loggers.Transaction; @@ -6,11 +11,12 @@ using Perpetuum.EntityFramework; using Perpetuum.Host.Requests; using Perpetuum.Items; +using Perpetuum.Players; +using Perpetuum.RequestHandlers.Extensions; using Perpetuum.Robots; -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using System.Transactions; +using Perpetuum.Services.ExtensionService; +using Perpetuum.Services.Sparks.Teleports; +using Perpetuum.Zones; namespace Perpetuum.RequestHandlers { @@ -19,15 +25,18 @@ public class UseLotteryItem : IRequestHandler private readonly IEntityServices entityServices; private readonly IAccountManager accountManager; private readonly IAccountRepository accountRepository; + private readonly SparkTeleportHelper sparkTeleportHelper; public UseLotteryItem( IEntityServices entityServices, IAccountManager accountManager, - IAccountRepository accountRepository) + IAccountRepository accountRepository, + SparkTeleportHelper sparkTeleportHelper) { this.entityServices = entityServices; this.accountManager = accountManager; this.accountRepository = accountRepository; + this.sparkTeleportHelper = sparkTeleportHelper; } public void HandleRequest(IRequest request) diff --git a/src/Perpetuum.RequestHandlers/Zone/ProximityProbeRemove.cs b/src/Perpetuum.RequestHandlers/Zone/ProximityProbeRemove.cs index 0e8cac639..0825e8e24 100644 --- a/src/Perpetuum.RequestHandlers/Zone/ProximityProbeRemove.cs +++ b/src/Perpetuum.RequestHandlers/Zone/ProximityProbeRemove.cs @@ -12,7 +12,7 @@ public void HandleRequest(IZoneRequest request) { var eid = request.Data.GetOrDefault(k.eid); - var probeBase = request.Zone.GetUnit(eid) as ProximityProbeBase; + var probeBase = request.Zone.GetUnit(eid) as ProximityDeviceBase; if (probeBase == null) return; diff --git a/src/Perpetuum/Accounting/Characters/Character.cs b/src/Perpetuum/Accounting/Characters/Character.cs index e0d8d0775..178baac67 100644 --- a/src/Perpetuum/Accounting/Characters/Character.cs +++ b/src/Perpetuum/Accounting/Characters/Character.cs @@ -1,12 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Runtime.Caching; -using System.Threading.Tasks; -using System.Transactions; -using Newtonsoft.Json.Linq; -using System.Windows.Input; using Perpetuum.Common.Loggers.Transaction; using Perpetuum.Containers; using Perpetuum.Data; @@ -25,12 +16,19 @@ using Perpetuum.Units.DockingBases; using Perpetuum.Wallets; using Perpetuum.Zones; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.Caching; +using System.Threading.Tasks; +using System.Transactions; namespace Perpetuum.Accounting.Characters { public delegate Character CharacterFactory(int id); - public class Character : IEquatable,IComparable + public class Character : IEquatable, IComparable { private static Character _none; @@ -92,15 +90,15 @@ public static bool IsSystemCharacter(Character c) private const string LAST_RESPEC = "LastRespec"; public static ObjectCache CharacterCache { get; set; } - + public static CharacterFactory CharacterFactory { get; set; } public Character() { - + } - public Character(int id,IAccountManager accountManager, + public Character(int id, IAccountManager accountManager, Lazy zoneManager, DockingBaseHelper dockingBaseHelper, RobotHelper robotHelper, @@ -127,7 +125,9 @@ public Character(int id,IAccountManager accountManager, _walletHelper = walletHelper; if (id <= 0) + { id = 0; + } Id = id; } @@ -168,7 +168,7 @@ public bool IsOffensiveNick get => ReadValueFromDb(FIELD_OFFENSIVE_NICK); set { - WriteValueToDb(FIELD_OFFENSIVE_NICK,value); + WriteValueToDb(FIELD_OFFENSIVE_NICK, value); WriteValueToDb(FIELD_NICK_CORRECTED, !value); } } @@ -287,13 +287,10 @@ public Position? ZonePosition { get { - var x = ReadValueFromDb(FIELD_POSITION_X); - var y = ReadValueFromDb(FIELD_POSITION_Y); + double? x = ReadValueFromDb(FIELD_POSITION_X); + double? y = ReadValueFromDb(FIELD_POSITION_Y); - if (x == null || y == null) - return null; - - return new Position((double) x,(double) y); + return x == null || y == null ? null : (Position?)new Position((double)x, (double)y); } set { @@ -302,13 +299,13 @@ public Position? ZonePosition if (value != null) { - var p = (Position) value; + Position p = (Position)value; x = p.X; y = p.Y; } - WriteValueToDb(FIELD_POSITION_X,x); - WriteValueToDb(FIELD_POSITION_Y,y); + WriteValueToDb(FIELD_POSITION_X, x); + WriteValueToDb(FIELD_POSITION_Y, y); } } @@ -319,7 +316,7 @@ public long CorporationEid { WriteValueToDb(FIELD_CORPORATION_EID, value); - Db.Query().CommandText("update entities set parent=@corporationEID where eid=@characterEID") + _ = Db.Query().CommandText("update entities set parent=@corporationEID where eid=@characterEID") .SetParameter("@corporationEID", value) .SetParameter("@characterEID", Eid) .ExecuteNonQuery().ThrowIfEqual(0, ErrorCodes.SQLUpdateError); @@ -329,25 +326,25 @@ public long CorporationEid public long DefaultCorporationEid { get => ReadValueFromDb(FIELD_DEFAULT_CORPORATION_EID); - set => WriteValueToDb(FIELD_DEFAULT_CORPORATION_EID,value); + set => WriteValueToDb(FIELD_DEFAULT_CORPORATION_EID, value); } public long AllianceEid { get => ReadValueFromDb(FIELD_ALLIANCE_EID) ?? 0L; - set => WriteValueToDb(FIELD_ALLIANCE_EID,value == 0L ? (object) null : value); + set => WriteValueToDb(FIELD_ALLIANCE_EID, value == 0L ? (object)null : value); } public long ActiveRobotEid { get => ReadValueFromDb(FIELD_ACTIVE_CHASSIS) ?? 0; - set => WriteValueToDb(FIELD_ACTIVE_CHASSIS,value == 0L ? (object)null : value); + set => WriteValueToDb(FIELD_ACTIVE_CHASSIS, value == 0L ? (object)null : value); } public long CurrentDockingBaseEid { get => ReadValueFromDb(FIELD_BASE_EID); - set => WriteValueToDb(FIELD_BASE_EID,value); + set => WriteValueToDb(FIELD_BASE_EID, value); } public DateTime NextAvailableUndockTime @@ -379,29 +376,29 @@ public bool GlobalMuted public long? HomeBaseEid { get => ReadValueFromDb(FIELD_HOME_BASE_EID); - set => WriteValueToDb(FIELD_HOME_BASE_EID,value); + set => WriteValueToDb(FIELD_HOME_BASE_EID, value); } - private static string GetCacheKey(string prefix,object key) + private static string GetCacheKey(string prefix, object key) { return $"{prefix}_{key}"; } public void RemoveFromCache() { - CharacterCache.Remove(GetCacheKey(CACHE_KEY_ID_TO_EID, Id)); - CharacterCache.Remove(GetCacheKey(CACHE_KEY_EID_TO_ID, Eid)); + _ = CharacterCache.Remove(GetCacheKey(CACHE_KEY_ID_TO_EID, Id)); + _ = CharacterCache.Remove(GetCacheKey(CACHE_KEY_EID_TO_ID, Eid)); RemoveAccountIdFromCache(); } public void UpdateExtensionsCache(CharacterExtensionCollection extensions) { - CharacterCache.Set(this.Id.ToString(), extensions, new TimeSpan(0,1,0)); + CharacterCache.Set(Id.ToString(), extensions, new TimeSpan(0, 1, 0)); } private void RemoveAccountIdFromCache() { - CharacterCache.Remove(GetCacheKey(CACHE_KEY_ID_TO_ACCOUNTID, Id)); + _ = CharacterCache.Remove(GetCacheKey(CACHE_KEY_ID_TO_ACCOUNTID, Id)); } public override int GetHashCode() @@ -413,31 +410,21 @@ public int CompareTo(Character other) { return Id.CompareTo(other?.Id); } - + public override bool Equals(object obj) { - var other = obj as Character; + Character other = obj as Character; return other != Character.None && Equals(other); } public bool Equals(Character other) { - if (ReferenceEquals(null, other)) - return false; - if (ReferenceEquals(this, other)) - return true; - return Id == other.Id; + return !(other is null) && (ReferenceEquals(this, other) || Id == other.Id); } public static bool operator ==(Character left, Character right) { - if (ReferenceEquals(left, right)) - return true; - - if ((object)left == null || (object)right == null) - return false; - - return left.Equals(right); + return ReferenceEquals(left, right) || (left is object && right is object && left.Equals(right)); } public static bool operator !=(Character left, Character right) @@ -457,7 +444,7 @@ private string CreateCacheKey(string key) private T GetValueFromCache(string key) { - return CharacterCache.Get(CreateCacheKey(key),() => default(T)); + return CharacterCache.Get(CreateCacheKey(key), () => default(T)); } private void SetValueToCache(string key, T value) @@ -479,28 +466,28 @@ private void WriteValueToDb(string name, object value) private static T ReadValueFromDb(int id, string name) { - if (id == 0) - return default(T); - - return Db.Query().CommandText("select " + name + " from characters where characterid = @id").SetParameter("@id",id).ExecuteScalar(); + return id == 0 + ? default + : Db.Query().CommandText("select " + name + " from characters where characterid = @id").SetParameter("@id", id).ExecuteScalar(); } private static T ReadValueFromDb(long eid, string name) { - if (eid == 0) - return default(T); - - return Db.Query().CommandText("select " + name + " from characters where rooteid = @eid").SetParameter("@eid",eid).ExecuteScalar(); + return eid == 0 + ? default + : Db.Query().CommandText("select " + name + " from characters where rooteid = @eid").SetParameter("@eid", eid).ExecuteScalar(); } private static void WriteValueToDb(int id, string name, object value) { - if ( id == 0 ) + if (id == 0) + { return; + } - Db.Query().CommandText("update characters set " + name + " = @value where characterid = @id") - .SetParameter("@id",id) - .SetParameter("@value",value) + _ = Db.Query().CommandText("update characters set " + name + " = @value where characterid = @id") + .SetParameter("@id", id) + .SetParameter("@value", value) .ExecuteNonQuery().ThrowIfEqual(0, ErrorCodes.SQLUpdateError); } @@ -508,9 +495,11 @@ private static void WriteValueToDb(int id, string name, object value) public static Character GetByEid(long characterEid) { if (characterEid == 0L) + { return None; + } - var characterId = GetIdByEid(characterEid); + int characterId = GetIdByEid(characterEid); return CharacterFactory(characterId); } @@ -522,23 +511,17 @@ public static Character Get(int id) private static int GetCachedAccountId(int id) { - if (id == 0) - return 0; - - return CharacterCache.Get(GetCacheKey(CACHE_KEY_ID_TO_ACCOUNTID,id), () => ReadValueFromDb(id,FIELD_ACCOUNT_ID)); + return id == 0 ? 0 : CharacterCache.Get(GetCacheKey(CACHE_KEY_ID_TO_ACCOUNTID, id), () => ReadValueFromDb(id, FIELD_ACCOUNT_ID)); } private static long GetEid(int id) { - if (id == 0) - return 0L; - - return CharacterCache.Get(GetCacheKey(CACHE_KEY_ID_TO_EID, id), () => ReadValueFromDb(id, FIELD_ROOT_EID)); + return id == 0 ? 0L : CharacterCache.Get(GetCacheKey(CACHE_KEY_ID_TO_EID, id), () => ReadValueFromDb(id, FIELD_ROOT_EID)); } public static int GetIdByEid(long eid) { - return CharacterCache.Get(GetCacheKey(CACHE_KEY_EID_TO_ID, eid), () => ReadValueFromDb(eid,FIELD_CHARACTER_ID)); + return CharacterCache.Get(GetCacheKey(CACHE_KEY_EID_TO_ID, eid), () => ReadValueFromDb(eid, FIELD_CHARACTER_ID)); } public static bool Exists(int id) @@ -546,11 +529,11 @@ public static bool Exists(int id) return id != 0 && ReadValueFromDb(id, FIELD_CHARACTER_ID) > 0; } - public static void CheckNickAndThrowIfFailed(string nick, AccessLevel accessLevel,Account issuerAccount) + public static void CheckNickAndThrowIfFailed(string nick, AccessLevel accessLevel, Account issuerAccount) { nick = nick.Trim(); - nick.Length.ThrowIfLess(3, ErrorCodes.NickTooShort); - nick.Length.ThrowIfGreater(25, ErrorCodes.NickTooLong); + _ = nick.Length.ThrowIfLess(3, ErrorCodes.NickTooShort); + _ = nick.Length.ThrowIfGreater(25, ErrorCodes.NickTooLong); nick.AllowAscii().ThrowIfFalse(ErrorCodes.OnlyAsciiAllowed); if (!accessLevel.IsAdminOrGm()) @@ -559,7 +542,7 @@ public static void CheckNickAndThrowIfFailed(string nick, AccessLevel accessLeve } //check history - var inHistory = + int inHistory = Db.Query().CommandText("select count(*) from characternickhistory where nick=@nick and accountid != @accountID") .SetParameter("@accountID", issuerAccount.Id) .SetParameter("@nick", nick) @@ -568,9 +551,11 @@ public static void CheckNickAndThrowIfFailed(string nick, AccessLevel accessLeve //is nick belongs to an active of inavtive character - var owner = GetByNick(nick); + Character owner = GetByNick(nick); if (owner == Character.None) + { return; + } // ok, now we know that the nick is used in the characters table, lets check ownership and timeouts! @@ -578,8 +563,8 @@ public static void CheckNickAndThrowIfFailed(string nick, AccessLevel accessLeve owner.IsActive.ThrowIfTrue(ErrorCodes.NickTaken); //if the character is deleted and belongs to the issuer then it's ok - var b = owner.AccountId != issuerAccount.Id; - if (b && !(DateTime.Now.Subtract(owner.DeletedAt).TotalDays > 1)) + bool b = owner.AccountId != issuerAccount.Id; + if (b && (DateTime.Now.Subtract(owner.DeletedAt).TotalDays <= 1)) { throw new PerpetuumException(ErrorCodes.NickTaken); } @@ -593,13 +578,13 @@ public static IEnumerable GetCharactersDockedInBase(long baseEid) { return Db.Query().CommandText("select characterid from characters where docked=1 and baseEID=@baseEID and active=1 and inUse=1") .SetParameter("@baseEID", baseEid) - .Execute().Select(r => Get((int) r.GetValue(0))); + .Execute().Select(r => Get(r.GetValue(0))); } [UsedImplicitly] public static Character GetByNick(string nick) { - var id = Db.Query().CommandText("select characterid from characters where nick = @nick").SetParameter("@nick",nick).ExecuteScalar(); + int id = Db.Query().CommandText("select characterid from characters where nick = @nick").SetParameter("@nick", nick).ExecuteScalar(); return Get(id); } @@ -617,8 +602,8 @@ public void LogTransaction(TransactionLogEvent e) public IDictionary GetTransactionHistory(int offsetInDays) { - var later = DateTime.Now.AddDays(-offsetInDays); - var earlier = later.AddDays(-2); + DateTime later = DateTime.Now.AddDays(-offsetInDays); + DateTime earlier = later.AddDays(-2); const string sqlCmd = @"SELECT transactionType, amount, @@ -630,7 +615,7 @@ public IDictionary GetTransactionHistory(int offsetInDays) FROM charactertransactions WHERE characterid = @characterId AND transactiondate between @earlier AND @later and amount != 0"; - var result = Db.Query().CommandText(sqlCmd) + Dictionary result = Db.Query().CommandText(sqlCmd) .SetParameter("@characterId", Id) .SetParameter("@earlier", earlier) .SetParameter("@later", later) @@ -647,8 +632,8 @@ public bool IsInTraining() public void CheckNextAvailableUndockTimeAndThrowIfFailed() { - var nextAvailableUndockTime = NextAvailableUndockTime; - nextAvailableUndockTime.ThrowIfGreater(DateTime.Now, ErrorCodes.DockingTimerStillRunning, gex => gex.SetData("nextAvailable", nextAvailableUndockTime)); + DateTime nextAvailableUndockTime = NextAvailableUndockTime; + _ = nextAvailableUndockTime.ThrowIfGreater(DateTime.Now, ErrorCodes.DockingTimerStillRunning, gex => gex.SetData("nextAvailable", nextAvailableUndockTime)); } public void SendErrorMessage(Command command, ErrorCodes error) @@ -663,61 +648,67 @@ public MessageBuilder CreateErrorMessage(Command command, ErrorCodes error) public void CheckPrivilegedTransactionsAndThrowIfFailed() { - IsPrivilegedTransactionsAllowed().ThrowIfError(); + _ = IsPrivilegedTransactionsAllowed().ThrowIfError(); } public ErrorCodes IsPrivilegedTransactionsAllowed() { - var accessLevel = AccessLevel; - if (!accessLevel.IsAnyPrivilegeSet()) - return ErrorCodes.NoError; - - if (!accessLevel.IsAdminOrGm()) - return ErrorCodes.AccessDenied; - - return ErrorCodes.NoError; + AccessLevel accessLevel = AccessLevel; + return !accessLevel.IsAnyPrivilegeSet() + ? ErrorCodes.NoError + : !accessLevel.IsAdminOrGm() ? ErrorCodes.AccessDenied : ErrorCodes.NoError; } public bool IsRobotSelectedForOtherCharacter(long robotEid) { - var selectCheck = Db.Query().CommandText("select count(*) from characters where activechassis=@robotEID and characterID != @characterID") + int selectCheck = Db.Query().CommandText("select count(*) from characters where activechassis=@robotEID and characterID != @characterID") .SetParameter("@characterID", Id).SetParameter("@robotEID", robotEid) .ExecuteNonQuery(); if (selectCheck <= 0) + { return false; + } Logger.Error($"An evil attempt to select a robot twice happened. characterID:{Id} robotEID:{robotEid}"); return true; } - public IWallet GetWalletWithAccessCheck(bool useCorporationWallet,TransactionType transactionType,params CorporationRole[] roles) + public IWallet GetWalletWithAccessCheck(bool useCorporationWallet, TransactionType transactionType, params CorporationRole[] roles) { - var thisCharacter = this; - return GetWallet(useCorporationWallet,transactionType,role => + Character thisCharacter = this; + return GetWallet(useCorporationWallet, transactionType, role => { - if (role.IsAnyRole(CorporationRole.CEO,CorporationRole.DeputyCEO,CorporationRole.Accountant)) + if (role.IsAnyRole(CorporationRole.CEO, CorporationRole.DeputyCEO, CorporationRole.Accountant)) + { return true; + } if (!role.IsAnyRole(CorporationRole.CEO)) - thisCharacter._corporationManager.IsInJoinOrLeave(thisCharacter).ThrowIfError(); + { + _ = thisCharacter._corporationManager.IsInJoinOrLeave(thisCharacter).ThrowIfError(); + } return role.IsAnyRole(roles); }); } - public IWallet GetWallet(bool useCorporationWallet,TransactionType transactionType,Predicate accessChecker = null) + public IWallet GetWallet(bool useCorporationWallet, TransactionType transactionType, Predicate accessChecker = null) { if (!useCorporationWallet) + { return GetWallet(transactionType); + } - var privateCorporation = GetPrivateCorporationOrThrow(); + PrivateCorporation privateCorporation = GetPrivateCorporationOrThrow(); if (accessChecker != null) { - var role = privateCorporation.GetMemberRole(this); + CorporationRole role = privateCorporation.GetMemberRole(this); if (!accessChecker(role)) + { throw new PerpetuumException(ErrorCodes.InsufficientPrivileges); + } } return new CorporationWallet(privateCorporation); @@ -725,22 +716,22 @@ public IWallet GetWallet(bool useCorporationWallet,TransactionType trans public IWallet GetWallet(TransactionType transactionType) { - return _walletHelper.GetWallet(this,transactionType); + return _walletHelper.GetWallet(this, transactionType); } public void TransferCredit(Character target, long amount) { - _walletHelper.TransferCredit(this,target,amount); + _walletHelper.TransferCredit(this, target, amount); } public void AddToWallet(TransactionType transactionType, double amount) { - _walletHelper.AddToWallet(this,transactionType,amount); + _walletHelper.AddToWallet(this, transactionType, amount); } public void SubtractFromWallet(TransactionType transactionType, double amount) { - _walletHelper.SubtractFromWallet(this,transactionType,amount); + _walletHelper.SubtractFromWallet(this, transactionType, amount); } public ICharacterSocial GetSocial() @@ -758,13 +749,17 @@ public void ResetAllExtensions() DeleteAllSpentPoints(); //reset the actual extension levels - Db.Query().CommandText("delete characterextensions where characterid=@characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText( +@"DELETE ce FROM characterextensions ce +INNER JOIN extensions e +ON ce.extensionid = e.extensionid +WHERE characterid=@characterID AND e.active = 1 AND e.hidden = 0") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); //reset remove log - Db.Query().CommandText("delete extensionremovelog where characterid=@characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("DELETE extensionremovelog WHERE characterid=@characterID") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); //remove ram @@ -773,13 +768,13 @@ public void ResetAllExtensions() public void IncreaseExtensionLevel(int extensionId, int extensionLevel) { - Db.Query().CommandText("dbo.increaseExtensionLevel") + _ = Db.Query().CommandText("dbo.increaseExtensionLevel") .SetParameter("@characterID", Id) .SetParameter("@extensionID", extensionId) .SetParameter("@extensionLevel", extensionLevel) .ExecuteScalar().ThrowIfEqual(0, ErrorCodes.SQLExecutionError); - var thisCharacter = this; + Character thisCharacter = this; Transaction.Current.OnCommited(() => thisCharacter._characterExtensions.Remove(thisCharacter)); } @@ -795,13 +790,13 @@ public CharacterExtensionCollection GetExtensions() public void SetAllExtensionLevel(int level) { - var extensions = _extensionReader.GetExtensions().Values.Where(e => !e.hidden).Select(e => new Extension(e.id, level)); + IEnumerable extensions = _extensionReader.GetExtensions().Values.Where(e => !e.hidden).Select(e => new Extension(e.id, level)); SetExtensions(extensions); } public void SetExtensions(IEnumerable extensions) { - foreach (var extension in extensions) + foreach (Extension extension in extensions) { SetExtension(extension); } @@ -817,13 +812,13 @@ public void SetExtension(Extension extension) return; } - Db.Query().CommandText("dbo.setExtensionLevel") + _ = Db.Query().CommandText("dbo.setExtensionLevel") .SetParameter("@characterID", Id) .SetParameter("@extensionID", extension.id) .SetParameter("@extensionLevel", extension.level) .ExecuteScalar().ThrowIfEqual(0, ErrorCodes.SQLExecutionError); - var tmpCharacter = this; + Character tmpCharacter = this; Transaction.Current.OnCommited(() => tmpCharacter._characterExtensions.Remove(tmpCharacter)); } @@ -839,7 +834,7 @@ public double GetExtensionsBonusSummary(params string[] extensionNames) public double GetExtensionsBonusSummary(IEnumerable extensionIDs) { - var thisC = this; + Character thisC = this; return GetExtensions().SelectById(extensionIDs).Sum(e => e.level * thisC._extensionReader.GetExtensionByID(e.id).bonus); } @@ -855,7 +850,7 @@ public double GetExtensionBonus(int extensionId) public int GetExtensionLevelSummaryByName(params string[] extensionNames) { - var ex = GetExtensions(); + CharacterExtensionCollection ex = GetExtensions(); return _extensionReader.GetExtensionIDsByName(extensionNames).Sum(extensionId => ex.GetLevel(extensionId)); } @@ -880,21 +875,23 @@ public bool IsBlocked(Character otherCharacter) } [Pure] - public int AddExtensionPointsBoostAndLog(EpForActivityType activityType, int points) + public int AddExtensionPointsBoostAndLog(EpForActivityType activityType, int points) { if (points <= 0) + { return 0; + } - var account = GetAccount(); + Account account = GetAccount(); Debug.Assert(account != null, "account != null"); - return _accountManager.AddExtensionPointsBoostAndLog(account,this, activityType, points); + return _accountManager.AddExtensionPointsBoostAndLog(account, this, activityType, points); } [CanBeNull] public Task ReloadContainerOnZoneAsync() { - var character = this; + Character character = this; return Task.Run(() => character.ReloadContainerOnZone()); } @@ -913,9 +910,9 @@ public PublicContainer GetPublicContainerWithItems() return GetCurrentDockingBase().GetPublicContainerWithItems(this); } - public void SendItemErrorMessage(Command command,ErrorCodes error,Item item) + public void SendItemErrorMessage(Command command, ErrorCodes error, Item item) { - CreateErrorMessage(command,error) + CreateErrorMessage(command, error) .SetExtraInfo(d => { d["eid"] = item.Eid; @@ -926,25 +923,25 @@ public void SendItemErrorMessage(Command command,ErrorCodes error,Item item) public bool TechTreeNodeUnlocked(int definition) { if (_techTreeService.GetUnlockedNodes(Eid).Any(n => n.Definition == definition)) + { return true; + } - var hasRole = Corporation.GetRoleFromSql(this).HasRole(PresetCorporationRoles.CAN_LIST_TECHTREE); + bool hasRole = Corporation.GetRoleFromSql(this).HasRole(PresetCorporationRoles.CAN_LIST_TECHTREE); return hasRole && _techTreeService.GetUnlockedNodes(CorporationEid).Any(n => n.Definition == definition); } public bool HasTechTreeBonus(int definition) { - var hasRole = Corporation.GetRoleFromSql(this).HasRole(PresetCorporationRoles.CAN_LIST_TECHTREE); - if (!hasRole) - return false; - - return _techTreeService.GetUnlockedNodes(Eid).Any(n => n.Definition == definition) && (_techTreeService.GetUnlockedNodes(CorporationEid).Any(n => n.Definition == definition)); + bool hasRole = Corporation.GetRoleFromSql(this).HasRole(PresetCorporationRoles.CAN_LIST_TECHTREE); + return hasRole +&& _techTreeService.GetUnlockedNodes(Eid).Any(n => n.Definition == definition) && _techTreeService.GetUnlockedNodes(CorporationEid).Any(n => n.Definition == definition); } public DockingBase GetHomeBaseOrCurrentBase() { - var resultBaseEid = HomeBaseEid ?? 0L; - var wasHomeBase = true; + long resultBaseEid = HomeBaseEid ?? 0L; + bool wasHomeBase = true; if (resultBaseEid == 0) { @@ -952,9 +949,11 @@ public DockingBase GetHomeBaseOrCurrentBase() wasHomeBase = false; } - var dockingBase = _dockingBaseHelper.GetDockingBase(resultBaseEid); + DockingBase dockingBase = _dockingBaseHelper.GetDockingBase(resultBaseEid); if (dockingBase != null && dockingBase.IsDockingAllowed(this) == ErrorCodes.NoError) + { return _dockingBaseHelper.GetDockingBase(resultBaseEid); + } //docking would normally fail if (wasHomeBase) @@ -966,11 +965,11 @@ public DockingBase GetHomeBaseOrCurrentBase() //pick the race related homebase resultBaseEid = DefaultCorporation.GetDockingBaseEid(this); - var thisCharacter = this; + Character thisCharacter = this; //inform dead player about this state Transaction.Current.OnCommited(() => { - var info = new Dictionary + Dictionary info = new Dictionary { {k.characterID,thisCharacter.Id}, {k.baseEID, resultBaseEid}, @@ -983,9 +982,9 @@ public DockingBase GetHomeBaseOrCurrentBase() return _dockingBaseHelper.GetDockingBase(resultBaseEid); } - public void WriteItemTransactionLog(TransactionType transactionType,Item item) + public void WriteItemTransactionLog(TransactionType transactionType, Item item) { - var b = TransactionLogEvent.Builder().SetTransactionType(transactionType).SetCharacter(this).SetItem(item.Definition,item.Quantity); + TransactionLogEventBuilder b = TransactionLogEvent.Builder().SetTransactionType(transactionType).SetCharacter(this).SetItem(item.Definition, item.Quantity); LogTransaction(b); } @@ -993,8 +992,8 @@ public void SetActiveRobot(Robot robot) { ActiveRobotEid = robot?.Eid ?? 0L; - var thisCharacter = this; - var result = robot?.ToDictionary(); + Character thisCharacter = this; + Dictionary result = robot?.ToDictionary(); Transaction.Current.OnCommited(() => Message.Builder.SetCommand(Commands.RobotActivated) .WithData(result) .WrapToResult() @@ -1005,28 +1004,28 @@ public void SetActiveRobot(Robot robot) public void CleanGameRelatedData() { //corp founder - Db.Query().CommandText("update corporations set founder=NULL where founder=@characterId") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("update corporations set founder=NULL where founder=@characterId") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); - Db.Query().CommandText("delete characterextensions where characterid=@characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("delete characterextensions where characterid=@characterID") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); - Db.Query().CommandText("delete charactersettings where characterid=@characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("delete charactersettings where characterid=@characterID") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); - Db.Query().CommandText("delete charactersparks where characterid=@characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("delete charactersparks where characterid=@characterID") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); - Db.Query().CommandText("delete charactersparkteleports where characterid=@characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("delete charactersparkteleports where characterid=@characterID") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); - Db.Query().CommandText("delete from channelmembers where memberid = @characterID") - .SetParameter("@characterID",Id) + _ = Db.Query().CommandText("delete from channelmembers where memberid = @characterID") + .SetParameter("@characterID", Id) .ExecuteNonQuery(); TransportAssignment.CharacterDeleted(this); @@ -1047,7 +1046,7 @@ public Gang GetGang() [CanBeNull] public Alliance GetAlliance() { - var allianceEid = AllianceEid; + long allianceEid = AllianceEid; return allianceEid == 0L ? null : Alliance.GetOrThrow(allianceEid); } @@ -1058,14 +1057,14 @@ public bool IsRobotSelectedForCharacter(Robot robot) public DockingBase GetCurrentDockingBase() { - var baseEid = CurrentDockingBaseEid; + long baseEid = CurrentDockingBaseEid; return _dockingBaseHelper.GetDockingBase(baseEid); } [CanBeNull] public Player GetPlayerRobotFromZone() { - var zone = GetCurrentZone(); + IZone zone = GetCurrentZone(); return zone?.GetPlayer(this); } @@ -1084,17 +1083,17 @@ public ZoneConfiguration GetCurrentZoneConfiguration() return GetCurrentZone()?.Configuration ?? ZoneConfiguration.None; } - public IDictionary GetFullProfile() + public IDictionary GetFullProfile() { - var record = Db.Query().CommandText("select * from characters where characterid = @characterid") - .SetParameter("@characterid",Id) + System.Data.IDataRecord record = Db.Query().CommandText("select * from characters where characterid = @characterid") + .SetParameter("@characterid", Id) .ExecuteSingleRow().ThrowIfNull(ErrorCodes.CharacterNotFound); - var currentBaseEid = record.GetValue("baseEID"); - var dockingBase = _dockingBaseHelper.GetDockingBase(currentBaseEid); - var isInTraining = record.GetValue("raceID") == 0; + long currentBaseEid = record.GetValue("baseEID"); + DockingBase dockingBase = _dockingBaseHelper.GetDockingBase(currentBaseEid); + bool isInTraining = record.GetValue("raceID") == 0; - var profile = new Dictionary(21) + Dictionary profile = new Dictionary(21) { {k.raceID, record.GetValue("raceID")}, {k.creation, record.GetValue("creation")}, @@ -1122,7 +1121,7 @@ public IDictionary GetFullProfile() {k.isInTraining, isInTraining} }; - _techTreeService.AddInfoToDictionary(Eid,profile); + _techTreeService.AddInfoToDictionary(Eid, profile); return profile; } @@ -1134,7 +1133,7 @@ public PrivateCorporation GetPrivateCorporationOrThrow() [CanBeNull] public PrivateCorporation GetPrivateCorporation() { - return (GetCorporation() as PrivateCorporation); + return GetCorporation() as PrivateCorporation; } public Corporation GetCorporation() @@ -1144,28 +1143,30 @@ public Corporation GetCorporation() public DefaultCorporation GetDefaultCorporation() { - var eid = DefaultCorporationEid; + long eid = DefaultCorporationEid; return (DefaultCorporation)Corporation.GetOrThrow(eid); } public void DeleteAllSpentPoints() { //delete the spent points - Db.Query().CommandText("delete accountextensionspent where characterid=@characterID") + _ = Db.Query().CommandText("delete accountextensionspent where characterid=@characterID") .SetParameter("@characterID", Id) .ExecuteNonQuery(); } public void GetTableIndexForAccountExtensionSpent(int extensionId, int extensionLevel, ref int spentId, ref int spentPoints) { - var record = Db.Query().CommandText("select top 1 id,points from accountextensionspent where extensionid=@extensionID and extensionlevel=@extensionLevel and characterid=@characterID and points > 0 order by eventtime desc") + System.Data.IDataRecord record = Db.Query().CommandText("select top 1 id,points from accountextensionspent where extensionid=@extensionID and extensionlevel=@extensionLevel and characterid=@characterID and points > 0 order by eventtime desc") .SetParameter("@extensionLevel", extensionLevel) .SetParameter("@extensionID", extensionId) .SetParameter("@characterID", Id) .ExecuteSingleRow(); if (record == null) + { return; + } spentId = record.GetValue(0); spentPoints = record.GetValue(1); diff --git a/src/Perpetuum/EntityFramework/DefinitionConfig.cs b/src/Perpetuum/EntityFramework/DefinitionConfig.cs index 8f01bde5e..bfce9500f 100644 --- a/src/Perpetuum/EntityFramework/DefinitionConfig.cs +++ b/src/Perpetuum/EntityFramework/DefinitionConfig.cs @@ -142,7 +142,6 @@ public DefinitionConfig(IDataRecord record) network_node_range = record.GetValue("network_node_range"); _hitSize = record.GetValue("hitsize") ?? 1.41; - var tint = record.GetValue("tint"); if (!string.IsNullOrEmpty(tint)) diff --git a/src/Perpetuum/EntityFramework/EntityDefaultOptions.cs b/src/Perpetuum/EntityFramework/EntityDefaultOptions.cs index ec220c34e..9e661ad76 100644 --- a/src/Perpetuum/EntityFramework/EntityDefaultOptions.cs +++ b/src/Perpetuum/EntityFramework/EntityDefaultOptions.cs @@ -1,8 +1,10 @@ +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Perpetuum.ExportedTypes; using Perpetuum.GenXY; +using Perpetuum.Zones.RemoteControl; namespace Perpetuum.EntityFramework { @@ -174,5 +176,26 @@ public int SparkID return id; } } + + public int TurretId + { + get + { + var id = _dictionary.GetOrDefault(k.TurretId, 0); + Debug.Assert(id > 0); + + return id; + } + } + + public TurretType TurretType + { + get + { + var typeString = _dictionary.GetOrDefault("turretType"); + + return (TurretType)Enum.Parse(typeof(TurretType), typeString); + } + } } } \ No newline at end of file diff --git a/src/Perpetuum/ErrorCodes.cs b/src/Perpetuum/ErrorCodes.cs index 1580ced9e..39ffed3bf 100644 --- a/src/Perpetuum/ErrorCodes.cs +++ b/src/Perpetuum/ErrorCodes.cs @@ -711,5 +711,8 @@ public enum ErrorCodes MaxExpiringBasePerZoneReached, MaxExpiringBasePerZonePerCorpReached, RespecTokenIsNotReadyYet, + MaxBandwidthExceed, + RemoteControlledTurretInRange, + TurretNotDeployableNearObject, } } diff --git a/src/Perpetuum/Groups/Corporations/Corporation.Helpers.cs b/src/Perpetuum/Groups/Corporations/Corporation.Helpers.cs index c53966fa1..a42a99c78 100644 --- a/src/Perpetuum/Groups/Corporations/Corporation.Helpers.cs +++ b/src/Perpetuum/Groups/Corporations/Corporation.Helpers.cs @@ -50,6 +50,7 @@ public int GetMaximumProbeAmount() return CEO.GetExtensionLevel(maxProbesExtensionId); } + // TODO: Find a way to use joins instead of this public IEnumerable GetProximityProbeEids() { var probeDefinitions = EntityServices.Defaults.GetAll().GetDefinitionsByCategoryFlag(CategoryFlags.cf_proximity_probes); @@ -60,5 +61,23 @@ public IEnumerable GetProximityProbeEids() .Select(r => r.GetValue(0)) .ToArray(); } + + // TODO: Find a way to use joins instead of this + public IEnumerable GetLandMineEids() + { + var lightlandMineDefinitions = EntityServices.Defaults.GetAll().GetDefinitionsByCategoryFlag(CategoryFlags.cf_light_landmines); + var mediumlandMineDefinitions = EntityServices.Defaults.GetAll().GetDefinitionsByCategoryFlag(CategoryFlags.cf_medium_landmines); + var heavylandMineDefinitions = EntityServices.Defaults.GetAll().GetDefinitionsByCategoryFlag(CategoryFlags.cf_heavy_landmines); + var landMineDefinitions = lightlandMineDefinitions.Concat(mediumlandMineDefinitions).Concat(heavylandMineDefinitions); + + var queryStr = $"SELECT eid FROM entities WHERE owner=@corporationEID and definition in ({landMineDefinitions.ArrayToString()})"; + + return Db.Query() + .CommandText(queryStr) + .SetParameter("@corporationEID", Eid) + .Execute() + .Select(r => r.GetValue(0)) + .ToArray(); + } } } diff --git a/src/Perpetuum/Items/RespecToken.cs b/src/Perpetuum/Items/RespecToken.cs index 6e98a83d2..0ba18cd77 100644 --- a/src/Perpetuum/Items/RespecToken.cs +++ b/src/Perpetuum/Items/RespecToken.cs @@ -30,7 +30,7 @@ public void Activate( var epData = accountManager.GetEPData(account, character); accountManager.FreeLockedEp(account, (int)epData[k.lockedEp]); - + var defaultExtensions = character.GetDefaultExtensions(); character.ResetAllExtensions(); @@ -38,4 +38,4 @@ public void Activate( character.LastRespec = DateTime.Now; } } -} +} \ No newline at end of file diff --git a/src/Perpetuum/Items/SparkTeleportDevice.cs b/src/Perpetuum/Items/SparkTeleportDevice.cs index cdedfe94d..3ab15b923 100644 --- a/src/Perpetuum/Items/SparkTeleportDevice.cs +++ b/src/Perpetuum/Items/SparkTeleportDevice.cs @@ -1,16 +1,4 @@ -using Perpetuum.Accounting; -using Perpetuum.Accounting.Characters; -using Perpetuum.Common.Loggers.Transaction; -using Perpetuum.Data; -using Perpetuum.Host.Requests; -using Perpetuum.Players; -using Perpetuum.Robots; -using Perpetuum.Services.Sparks.Teleports; -using System; -using System.Collections.Generic; -using System.Transactions; - -namespace Perpetuum.Items +namespace Perpetuum.Items { public class SparkTeleportDevice : Item { diff --git a/src/Perpetuum/Keywords.cs b/src/Perpetuum/Keywords.cs index 98fd73323..d02553719 100644 --- a/src/Perpetuum/Keywords.cs +++ b/src/Perpetuum/Keywords.cs @@ -1220,5 +1220,8 @@ public class k public const string es_teleport_column = "teleport_column"; public const string es_admin_trashcan = "admin_trashcan"; public const string es_account_bound = "account_bound"; + + // Definition of field turret + public const string TurretId = "turretId"; } } \ No newline at end of file diff --git a/src/Perpetuum/Modules/ActiveModule.cs b/src/Perpetuum/Modules/ActiveModule.cs index 26c470da5..360f218d3 100644 --- a/src/Perpetuum/Modules/ActiveModule.cs +++ b/src/Perpetuum/Modules/ActiveModule.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; using Perpetuum.Containers; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; -using Perpetuum.Modules.Weapons; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Players; using Perpetuum.Robots; using Perpetuum.Units; @@ -13,173 +10,74 @@ using Perpetuum.Zones.Beams; using Perpetuum.Zones.Locking; using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.RemoteControl; using Perpetuum.Zones.Terrains; +using System; +using System.Collections.Generic; +using System.Diagnostics; namespace Perpetuum.Modules { - public class ModuleProperty : ItemProperty - { - protected readonly Module module; - private List _effectModifiers; - - public ModuleProperty(Module module, AggregateField field) : base(field) - { - this.module = module; - } - - public void AddEffectModifier(AggregateField field) - { - if ( _effectModifiers == null ) - _effectModifiers = new List(); - - _effectModifiers.Add(field); - } - - protected override double CalculateValue() - { - var m = module.GetPropertyModifier(Field); - ApplyEffectModifiers(ref m); - return m.Value; - } - - protected void ApplyEffectModifiers(ref ItemPropertyModifier m) - { - if (_effectModifiers == null) - return; - - foreach (var effectModifier in _effectModifiers) - { - module.ParentRobot?.ApplyEffectPropertyModifiers(effectModifier,ref m); - } - } - - protected override bool IsRelated(AggregateField field) - { - if (_effectModifiers != null) - { - if (_effectModifiers.Contains(field)) - return true; - } - - return base.IsRelated(field); - } - } - - public class CycleTimeProperty : ModuleProperty + public abstract partial class ActiveModule : Module { - private readonly ActiveModule _module; + private Lock _lock; + protected readonly ModuleProperty coreUsage; + protected readonly CycleTimeProperty cycleTime; + protected readonly ItemProperty falloff = ItemProperty.None; + protected readonly ModuleProperty optimalRange; - public CycleTimeProperty(ActiveModule module) : base(module, AggregateField.cycle_time) - { - _module = module; - } + private readonly CategoryFlags _ammoCategoryFlags; - protected override double CalculateValue() + public Lock Lock { - var cycleTime = _module.GetPropertyModifier(AggregateField.cycle_time); - - var ammo = _module.GetAmmo(); - ammo?.ModifyCycleTime(ref cycleTime); - - var driller = _module as DrillerModule; - if (driller != null) + [CanBeNull] + get => _lock; + set { - var miningAmmo = ammo as MiningAmmo; - if (miningAmmo != null) + if (_lock != null) { - miningAmmo.miningCycleTimeModifier.Update(); - var miningCycleTimeMod = miningAmmo.miningCycleTimeModifier.ToPropertyModifier(); - miningCycleTimeMod.Modify(ref cycleTime); + _lock.Changed -= LockChangedHandler; } - } - - ApplyEffectModifiers(ref cycleTime); - return cycleTime.Value; - } - } - - public class OptimalRangeProperty : ModuleProperty - { - private readonly ActiveModule _module; - public OptimalRangeProperty(ActiveModule module) : base(module,AggregateField.optimal_range) - { - _module = module; - AddEffectModifier(AggregateField.effect_optimal_range_modifier); - } - - protected override double CalculateValue() - { - var optimalRange = ItemPropertyModifier.Create(AggregateField.optimal_range); + _lock = value; - var ammo = _module.GetAmmo(); - if (module is MissileWeaponModule m) - { - if (ammo != null) + if (_lock != null) { - optimalRange = ammo.OptimalRangePropertyModifier; - var missileRangeMod = m.MissileRangeModifier.ToPropertyModifier(); - missileRangeMod.Modify(ref optimalRange); - module.ApplyRobotPropertyModifiers(ref optimalRange); + _lock.Changed += LockChangedHandler; } } - else - { - optimalRange = module.GetPropertyModifier(AggregateField.optimal_range); - ammo?.ModifyOptimalRange(ref optimalRange); - } - - ApplyEffectModifiers(ref optimalRange); - return optimalRange.Value; } - } - - public class FalloffProperty : ModuleProperty - { - public FalloffProperty(ActiveModule module) : base(module, AggregateField.falloff) - { - } + public bool IsRanged { get; private set; } - protected override double CalculateValue() + public override double Volume { - var falloff = ItemPropertyModifier.Create(AggregateField.falloff); - var ammo = ((ActiveModule)module).GetAmmo(); - if (module is MissileWeaponModule m) + get { + double volume = base.Volume; + Items.Ammos.Ammo ammo = GetAmmo(); + if (ammo != null) { - falloff = ammo.FalloffRangePropertyModifier; - var missileRangeMod = m.MissileFalloffModifier.ToPropertyModifier(); - missileRangeMod.Modify(ref falloff); - module.ApplyRobotPropertyModifiers(ref falloff); + volume += ammo.Volume; } + + return volume; } - else - { - falloff = module.GetPropertyModifier(AggregateField.falloff); - ammo?.ModifyFalloff(ref falloff); - } - ApplyEffectModifiers(ref falloff); - return falloff.Value; } - } + public TimeSpan CycleTime => TimeSpan.FromMilliseconds(cycleTime.Value); - public abstract partial class ActiveModule : Module - { - private Lock _lock; - protected readonly ModuleProperty coreUsage; - protected readonly CycleTimeProperty cycleTime; - protected readonly ItemProperty falloff = ItemProperty.None; - protected readonly ModuleProperty optimalRange; + public double CoreUsage => coreUsage.Value; - private readonly CategoryFlags _ammoCategoryFlags; + public double OptimalRange => optimalRange.Value; - protected ActiveModule(CategoryFlags ammoCategoryFlags,bool ranged = false) + public double Falloff => falloff.Value; + + protected ActiveModule(CategoryFlags ammoCategoryFlags, bool ranged = false) { IsRanged = ranged; - coreUsage = new ModuleProperty(this,AggregateField.core_usage); + coreUsage = new ModuleProperty(this, AggregateField.core_usage); AddProperty(coreUsage); cycleTime = new CycleTimeProperty(this); AddProperty(cycleTime); @@ -195,6 +93,10 @@ protected ActiveModule(CategoryFlags ammoCategoryFlags,bool ranged = false) _ammoCategoryFlags = ammoCategoryFlags; } + protected ActiveModule(bool ranged) : this(CategoryFlags.undefined, ranged) + { + } + public override void Initialize() { InitState(); @@ -202,59 +104,27 @@ public override void Initialize() base.Initialize(); } - - protected ActiveModule(bool ranged) : this(CategoryFlags.undefined,ranged) - { - } - - public TimeSpan CycleTime => TimeSpan.FromMilliseconds(cycleTime.Value); - - public double CoreUsage => coreUsage.Value; - - public double OptimalRange => optimalRange.Value; - - public double Falloff => falloff.Value; - - public Lock Lock - { - [CanBeNull] private get { return _lock; } - set - { - if (_lock != null) - _lock.Changed -= LockChangedHandler; - - _lock = value; - - if (_lock != null) - _lock.Changed += LockChangedHandler; - } - } - - public bool IsRanged { get; private set; } - public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } - private void LockChangedHandler(Lock @lock) + public override void UpdateRelatedProperties(AggregateField field) { - if (State.Type == ModuleStateType.Idle || State.Type == ModuleStateType.AmmoLoad) - return; - - var shutdown = @lock.State == LockState.Disabled || (ED.AttributeFlags.PrimaryLockedTarget && !@lock.Primary); - if (!shutdown) - return; + Items.Ammos.Ammo ammo = GetAmmo(); - State.SwitchTo(ModuleStateType.Shutdown); - _lock = null; + ammo?.UpdateRelatedProperties(field); + base.UpdateRelatedProperties(field); } - private bool IsInRange(Position position) + public bool IsInRange(Position position) { Debug.Assert(ParentRobot != null, "ParentRobot != null"); - return !IsRanged || ParentRobot.IsInRangeOf3D(position,OptimalRange + Falloff); + + return !IsRanged || ParentRobot.IsInRangeOf3D(position, OptimalRange + Falloff); } public void ForceUpdate() @@ -263,68 +133,74 @@ public void ForceUpdate() SendAmmoUpdatePacketToPlayer(); } - private BeamType GetBeamType() + public void Update(TimeSpan time) { - var ammo = GetAmmo(); - return ammo != null ? BeamHelper.GetBeamByDefinition(ammo.Definition) : BeamHelper.GetBeamByDefinition(Definition); + _states.Update(time); } - private void SendModuleStateToPlayer() + public override void UpdateAllProperties() { - var state = State; + base.UpdateAllProperties(); - var player = ParentRobot as Player; - if (player == null) - return; + Items.Ammos.Ammo ammo = GetAmmo(); - var packet = new Packet(ZoneCommand.ModuleChangeState); - Debug.Assert(ParentComponent != null, "ParentComponent != null"); - packet.AppendByte((byte)ParentComponent.Type); - packet.AppendByte((byte) Slot); - packet.AppendByte((byte)state.Type); + ammo?.UpdateAllProperties(); + } - var timed = state as ITimedModuleState; - if (timed == null) - { - packet.AppendInt(0); - packet.AppendInt(0); - } - else + public override void Unequip(Container container) + { + _ = UnequipAmmoToContainer(container); + base.Unequip(container); + } + + public override Dictionary ToDictionary() + { + Dictionary result = base.ToDictionary(); + + result.Add(k.ammoCategoryFlags, (long)_ammoCategoryFlags); + + Items.Ammos.Ammo ammo = GetAmmo(); + + if (ammo == null) { - packet.AppendInt((int)timed.Timer.Interval.TotalMilliseconds); - packet.AppendInt((int)timed.Timer.Elapsed.TotalMilliseconds); + return result; } - player.Session.SendPacket(packet); - } + result.Add(k.ammo, ammo.ToDictionary()); + result.Add(k.ammoQuantity, ammo.Quantity); - public void Update(TimeSpan time) - { - _states.Update(time); + return result; } protected abstract void OnAction(); protected virtual void HandleOffensivePVPCheck(Player parentPlayer, UnitLock unitLockTarget) { - if (parentPlayer != null) + if (parentPlayer != null && (unitLockTarget.Target as RemoteControlledCreature)?.CommandRobot is Player player) { - // pvp ellenorzes - (unitLockTarget.Target as Player)?.CheckPvp().ThrowIfError(); + _ = ((unitLockTarget.Target as Player)?.CheckPvp().ThrowIfError()); + _ = player.CheckPvp().ThrowIfError(); } } protected Lock GetLock() { - var currentLock = Lock.ThrowIfNull(ErrorCodes.LockTargetNotFound); - currentLock.State.ThrowIfNotEqual(LockState.Locked, ErrorCodes.LockIsInProgress); + Lock currentLock = Lock.ThrowIfNull(ErrorCodes.LockTargetNotFound); - var unitLockTarget = currentLock as UnitLock; - if (unitLockTarget != null) + _ = currentLock.State.ThrowIfNotEqual(LockState.Locked, ErrorCodes.LockIsInProgress); + + if (currentLock is UnitLock unitLockTarget) { IsInRange(unitLockTarget.Target.CurrentPosition).ThrowIfFalse(ErrorCodes.TargetOutOfRange); - var parentPlayer = ParentRobot as Player; + Player parentPlayer = ParentRobot as Player; + + if (parentPlayer is null && + ParentRobot is RemoteControlledCreature remoteControlledCreature && + remoteControlledCreature.CommandRobot is Player player) + { + parentPlayer = player; + } if (ED.AttributeFlags.OffensiveModule) { @@ -339,8 +215,7 @@ protected Lock GetLock() } else { - var terrainLockTarget = currentLock as TerrainLock; - if (terrainLockTarget != null) + if (currentLock is TerrainLock terrainLockTarget) { IsInRange(terrainLockTarget.Location).ThrowIfFalse(ErrorCodes.TargetOutOfRange); } @@ -349,17 +224,9 @@ protected Lock GetLock() return currentLock; } - public override void UpdateAllProperties() - { - base.UpdateAllProperties(); - - var ammo = GetAmmo(); - ammo?.UpdateAllProperties(); - } - protected void CreateBeam(Unit target, BeamState beamState) { - CreateBeam(target, beamState, 0, 0, 0); + _ = CreateBeam(target, beamState, 0, 0, 0); } protected int CreateBeam(Unit target, BeamState beamState, int duration, double bulletTime) @@ -367,72 +234,14 @@ protected int CreateBeam(Unit target, BeamState beamState, int duration, double return CreateBeam(target, beamState, duration, bulletTime, 0); } - private int CreateBeam(Unit target, BeamState beamState, int duration, double bulletTime,int visibility) - { - var delay = 0; - var beamType = GetBeamType(); - - if (beamType <= 0) - return delay; - - delay = BeamHelper.GetBeamDelay(beamType); - - if (duration == 0) - duration = (int)CycleTime.TotalMilliseconds; - - Debug.Assert(ParentComponent != null, "ParentComponent != null"); - var slot = ParentComponent.Type == RobotComponentType.Chassis ? Slot : 0xff; // -1 - - var builder = Beam.NewBuilder().WithType(beamType) - .WithSlot(slot) - .WithSource(ParentRobot) - .WithState(beamState) - .WithBulletTime(bulletTime) - .WithDuration(duration) - .WithTarget(target) - .WithVisibility(visibility); - - Zone.CreateBeam(builder); - return delay; - } - protected void CreateBeam(Position location, BeamState beamState) { - CreateBeam(location, beamState, 0, 0, 0); + _ = CreateBeam(location, beamState, 0, 0, 0); } protected int CreateBeam(Position location, BeamState beamState, int duration, double bulletTime) { - return CreateBeam(location, beamState, duration, bulletTime,0); - } - - private int CreateBeam(Position location, BeamState beamState, int duration, double bulletTime,int visibility) - { - var delay = 0; - var beamType = GetBeamType(); - - if (beamType <= 0) - return delay; - - delay = BeamHelper.GetBeamDelay(beamType); - - if (duration == 0) - duration = (int) CycleTime.TotalMilliseconds; - - Debug.Assert(ParentComponent != null, "ParentComponent != null"); - var slot = ParentComponent.Type == RobotComponentType.Chassis ? Slot : 0xff; // -1 - - var builder = Beam.NewBuilder().WithType(beamType) - .WithSlot(slot) - .WithSource(ParentRobot) - .WithState(beamState) - .WithBulletTime(bulletTime) - .WithDuration(duration) - .WithTargetPosition(location) - .WithVisibility(visibility); - - Zone.CreateBeam(builder); - return delay; + return CreateBeam(location, beamState, duration, bulletTime, 0); } protected override void OnUpdateProperty(AggregateField field) @@ -441,83 +250,95 @@ protected override void OnUpdateProperty(AggregateField field) { case AggregateField.core_usage: case AggregateField.effect_core_usage_gathering_modifier: - { - coreUsage.Update(); - break; - } + { + coreUsage.Update(); + + break; + } case AggregateField.cycle_time: case AggregateField.effect_weapon_cycle_time_modifier: case AggregateField.effect_gathering_cycle_time_modifier: - { - cycleTime.Update(); - break; - } + { + cycleTime.Update(); + + break; + } case AggregateField.optimal_range: case AggregateField.effect_optimal_range_modifier: case AggregateField.effect_ew_optimal_range_modifier: case AggregateField.module_missile_range_modifier: case AggregateField.effect_missile_range_modifier: - { - optimalRange.Update(); - break; - } + { + optimalRange.Update(); + + break; + } case AggregateField.falloff: - { - falloff.Update(); - break; - } + { + falloff.Update(); + + break; + } } base.OnUpdateProperty(field); } - public override void Unequip(Container container) - { - UnequipAmmoToContainer(container); - base.Unequip(container); - } - - protected double ModifyValueByOptimalRange(Unit target,double value) + protected double ModifyValueByOptimalRange(Unit target, double value) { Debug.Assert(ParentRobot != null, "ParentRobot != null"); - var distance = ParentRobot.GetDistance(target); + double distance = ParentRobot.GetDistance(target); + if (distance <= OptimalRange) + { return value; + } if (distance > OptimalRange + Falloff) + { return 0.0; + } + + double x = (distance - OptimalRange) / Falloff; + double m = (Math.Cos(x * Math.PI) / 2) + 0.5; - var x = (distance - OptimalRange) / Falloff; - var m = Math.Cos(x * Math.PI) / 2 + 0.5; return value * m; } protected LOSResult GetLineOfSight(Unit target) { Debug.Assert(ParentRobot != null, "ParentRobot != null"); - var visibility = ParentRobot.GetVisibility(target); + + IUnitVisibility visibility = ParentRobot.GetVisibility(target); + return visibility?.GetLineOfSight(IsCategory(CategoryFlags.cf_missiles)) ?? LOSResult.None; } protected LOSResult GetLineOfSight(Position location) { Debug.Assert(ParentRobot != null, "ParentRobot != null"); - var losResult = ParentRobot.Zone.IsInLineOfSight(ParentRobot,location,IsCategory(CategoryFlags.cf_missiles)); + + LOSResult losResult = ParentRobot.Zone.IsInLineOfSight(ParentRobot, location, IsCategory(CategoryFlags.cf_missiles)); + return losResult; } protected bool LOSCheckAndCreateBeam(Unit target) { - var result = GetLineOfSight(target); + LOSResult result = GetLineOfSight(target); + if (result.hit) { - var beamState = (result.blockingFlags != BlockingFlags.Undefined) ? BeamState.AlignToTerrain : BeamState.Hit; + BeamState beamState = (result.blockingFlags != BlockingFlags.Undefined) ? BeamState.AlignToTerrain : BeamState.Hit; + CreateBeam(result.position, beamState); + return false; } CreateBeam(target, BeamState.Hit); + return true; } @@ -526,52 +347,141 @@ protected void OnError(ErrorCodes error) SendModuleErrorToPlayer(error); } - private void SendModuleErrorToPlayer(ErrorCodes error) + private void LockChangedHandler(Lock @lock) + { + if (State.Type == ModuleStateType.Idle || State.Type == ModuleStateType.AmmoLoad) + { + return; + } + + bool shutdown = @lock.State == LockState.Disabled || (ED.AttributeFlags.PrimaryLockedTarget && !@lock.Primary); + + if (!shutdown) + { + return; + } + + State.SwitchTo(ModuleStateType.Shutdown); + _lock = null; + } + + private BeamType GetBeamType() + { + Items.Ammos.Ammo ammo = GetAmmo(); + + return ammo != null + ? BeamHelper.GetBeamByDefinition(ammo.Definition) + : BeamHelper.GetBeamByDefinition(Definition); + } + + private void SendModuleStateToPlayer() { - var player = ParentRobot as Player; - if (player == null) + IModuleState state = State; + + if (!(ParentRobot is Player player)) + { return; + } + + Packet packet = new Packet(ZoneCommand.ModuleChangeState); + + Debug.Assert(ParentComponent != null, "ParentComponent != null"); + packet.AppendByte((byte)ParentComponent.Type); + packet.AppendByte((byte)Slot); + packet.AppendByte((byte)state.Type); + + if (!(state is ITimedModuleState timed)) + { + packet.AppendInt(0); + packet.AppendInt(0); + } + else + { + packet.AppendInt((int)timed.Timer.Interval.TotalMilliseconds); + packet.AppendInt((int)timed.Timer.Elapsed.TotalMilliseconds); + } - var packet = new CombatLogPacket(error, this, _lock); player.Session.SendPacket(packet); } - public override Dictionary ToDictionary() + private int CreateBeam(Unit target, BeamState beamState, int duration, double bulletTime, int visibility) { - var result = base.ToDictionary(); + int delay = 0; + BeamType beamType = GetBeamType(); - result.Add(k.ammoCategoryFlags, (long)_ammoCategoryFlags); + if (beamType <= 0) + { + return delay; + } - var ammo = GetAmmo(); - if (ammo == null) - return result; + delay = BeamHelper.GetBeamDelay(beamType); - result.Add(k.ammo, ammo.ToDictionary()); - result.Add(k.ammoQuantity, ammo.Quantity); + if (duration == 0) + { + duration = (int)CycleTime.TotalMilliseconds; + } - return result; + Debug.Assert(ParentComponent != null, "ParentComponent != null"); + + int slot = ParentComponent.Type == RobotComponentType.Chassis ? Slot : 0xff; // -1 + BeamBuilder builder = Beam.NewBuilder().WithType(beamType) + .WithSlot(slot) + .WithSource(ParentRobot) + .WithState(beamState) + .WithBulletTime(bulletTime) + .WithDuration(duration) + .WithTarget(target) + .WithVisibility(visibility); + + Zone.CreateBeam(builder); + + return delay; } - public override double Volume + private int CreateBeam(Position location, BeamState beamState, int duration, double bulletTime, int visibility) { - get + int delay = 0; + BeamType beamType = GetBeamType(); + + if (beamType <= 0) { - var volume = base.Volume; + return delay; + } - var ammo = GetAmmo(); - if (ammo != null) - volume += ammo.Volume; + delay = BeamHelper.GetBeamDelay(beamType); - return volume; + if (duration == 0) + { + duration = (int)CycleTime.TotalMilliseconds; } + + Debug.Assert(ParentComponent != null, "ParentComponent != null"); + + int slot = ParentComponent.Type == RobotComponentType.Chassis ? Slot : 0xff; // -1 + BeamBuilder builder = Beam.NewBuilder().WithType(beamType) + .WithSlot(slot) + .WithSource(ParentRobot) + .WithState(beamState) + .WithBulletTime(bulletTime) + .WithDuration(duration) + .WithTargetPosition(location) + .WithVisibility(visibility); + + Zone.CreateBeam(builder); + + return delay; } - public override void UpdateRelatedProperties(AggregateField field) + private void SendModuleErrorToPlayer(ErrorCodes error) { - var ammo = GetAmmo(); - ammo?.UpdateRelatedProperties(field); + if (!(ParentRobot is Player player)) + { + return; + } - base.UpdateRelatedProperties(field); + CombatLogPacket packet = new CombatLogPacket(error, this, _lock); + + player.Session.SendPacket(packet); } } } \ No newline at end of file diff --git a/src/Perpetuum/Modules/ArmorRepairModule.cs b/src/Perpetuum/Modules/ArmorRepairModule.cs index dbeb02b57..cbd32bace 100644 --- a/src/Perpetuum/Modules/ArmorRepairModule.cs +++ b/src/Perpetuum/Modules/ArmorRepairModule.cs @@ -1,9 +1,10 @@ using System; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules { @@ -27,6 +28,7 @@ public override void UpdateProperty(AggregateField field) case AggregateField.effect_repair_amount_modifier: { armorRepairAmount.Update(); + return; } } @@ -36,14 +38,18 @@ public override void UpdateProperty(AggregateField field) protected void OnRepair(Unit target, double amount) { - if (amount <= 0.0) + if (amount <= 0.0) + { return; + } var armor = target.Armor; + target.Armor += amount; - var total = Math.Abs(armor - target.Armor); + var total = Math.Abs(armor - target.Armor); var packet = new CombatLogPacket(CombatLogType.ArmorRepair, target, ParentRobot, this); + packet.AppendDouble(amount); packet.AppendDouble(total); packet.Send(target, ParentRobot); @@ -59,14 +65,19 @@ public ArmorRepairModule() : base(false) public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override void OnAction() { var amount = armorRepairAmount.Value; + OnRepair(ParentRobot, amount); + var threatAmount = Math.Sqrt(amount).Clamp(1, 100); + ParentRobot.SpreadAssistThreatToNpcs(ParentRobot, new Threat(ThreatType.Support, threatAmount)); } } diff --git a/src/Perpetuum/Modules/BlobEmissionModulatorModule.cs b/src/Perpetuum/Modules/BlobEmissionModulatorModule.cs index a79aaee59..354094c76 100644 --- a/src/Perpetuum/Modules/BlobEmissionModulatorModule.cs +++ b/src/Perpetuum/Modules/BlobEmissionModulatorModule.cs @@ -2,6 +2,7 @@ using System.Linq; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Players; using Perpetuum.Units; using Perpetuum.Zones; diff --git a/src/Perpetuum/Modules/DrillerModule.cs b/src/Perpetuum/Modules/DrillerModule.cs index fa74c99a4..fed8937ad 100644 --- a/src/Perpetuum/Modules/DrillerModule.cs +++ b/src/Perpetuum/Modules/DrillerModule.cs @@ -1,31 +1,41 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using System.Transactions; using Perpetuum.Data; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Players; using Perpetuum.Services.MissionEngine.MissionTargets; using Perpetuum.Zones; using Perpetuum.Zones.Beams; using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.RemoteControl; using Perpetuum.Zones.Terrains; using Perpetuum.Zones.Terrains.Materials; using Perpetuum.Zones.Terrains.Materials.Minerals; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Transactions; namespace Perpetuum.Modules { public class DrillerModule : GathererModule { + private const int MAX_EP_PER_DAY = 1440; private readonly RareMaterialHandler _rareMaterialHandler; private readonly MaterialHelper _materialHelper; private readonly ItemProperty _miningAmountModifier; + private readonly ISet LIQUIDS = new HashSet(new int[] + { + (int)MaterialType.Crude, + (int)MaterialType.Liquizit, + (int)MaterialType.Epriton + }); - public DrillerModule(CategoryFlags ammoCategoryFlags,RareMaterialHandler rareMaterialHandler,MaterialHelper materialHelper) : base(ammoCategoryFlags, true) + public DrillerModule(CategoryFlags ammoCategoryFlags, RareMaterialHandler rareMaterialHandler, MaterialHelper materialHelper) + : base(ammoCategoryFlags, true) { _rareMaterialHandler = rareMaterialHandler; _materialHelper = materialHelper; @@ -36,31 +46,8 @@ public DrillerModule(CategoryFlags ammoCategoryFlags,RareMaterialHandler rareMat public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) - base.AcceptVisitor(visitor); - } - - private class MiningAmountModifierProperty : ModuleProperty - { - private readonly DrillerModule _module; - - public MiningAmountModifierProperty(DrillerModule module) : base(module, AggregateField.mining_amount_modifier) { - _module = module; - AddEffectModifier(AggregateField.effect_mining_amount_modifier); - } - - protected override double CalculateValue() - { - if (module.ParentRobot == null) - return 1.0; - - var m = module.ParentRobot.GetPropertyModifier(AggregateField.mining_amount_modifier); - - var ammo = (MiningAmmo)_module.GetAmmo(); - ammo?.ApplyMiningAmountModifier(ref m); - module.ParentRobot?.ApplyEffectPropertyModifiers(AggregateField.effect_mining_amount_modifier,ref m); - - return m.Value; + base.AcceptVisitor(visitor); } } @@ -72,6 +59,7 @@ public override void UpdateProperty(AggregateField field) case AggregateField.effect_mining_amount_modifier: { _miningAmountModifier.Update(); + return; } } @@ -79,76 +67,126 @@ public override void UpdateProperty(AggregateField field) base.UpdateProperty(field); } + public List Extract(MineralLayer layer, Point location, uint amount) + { + if (!layer.HasMineral(location)) + { + return new List(); + } + + MineralExtractor extractor = new MineralExtractor(location, amount, _materialHelper); + + layer.AcceptVisitor(extractor); + + return new List(extractor.Items); + } + protected override void OnAction() { - var zone = Zone; - if ( zone != null ) + IZone zone = Zone; + + if (zone != null) + { DoExtractMinerals(zone); + } ConsumeAmmo(); } - public List Extract(MineralLayer layer, Point location, uint amount) + protected override int CalculateEp(int materialType) { - if (!layer.HasMineral(location)) - return new List(); + DrillerModule[] activeGathererModules = this is RemoteControlledDrillerModule + ? ParentRobot.ActiveModules.OfType().Where(m => m.State.Type != ModuleStateType.Idle).ToArray() + : ParentRobot.ActiveModules.OfType().Where(m => m.State.Type != ModuleStateType.Idle).ToArray(); - var extractor = new MineralExtractor(location, amount,_materialHelper); - layer.AcceptVisitor(extractor); - return new List(extractor.Items); + if (activeGathererModules.Length == 0) + { + return 0; + } + + TimeSpan avgCycleTime = activeGathererModules.Select(m => m.CycleTime).Average(); + TimeSpan t = TimeSpan.FromDays(1).Divide(avgCycleTime); + double chance = (double)MAX_EP_PER_DAY / t.Ticks; + + chance /= activeGathererModules.Length; + + if (LIQUIDS.Contains(materialType)) + { + chance /= 2.0; + } + + double rand = FastRandom.NextDouble(); + + return rand <= chance ? 1 : 0; } - private void DoExtractMinerals(IZone zone) + public void DoExtractMinerals(IZone zone) { - var terrainLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); + TerrainLock terrainLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); - var ammo = GetAmmo() as MiningAmmo; - if (ammo == null) - return; + MaterialType materialType; + + if (ParentRobot is RemoteControlledCreature) + { + materialType = zone.Terrain.GetMaterialTypeAtPosition(terrainLock.Location); + } + else + { + if (!(GetAmmo() is MiningAmmo ammo)) + { + return; + } + + materialType = ammo.MaterialType; + } - var materialInfo = _materialHelper.GetMaterialInfo(ammo.MaterialType); + MaterialInfo materialInfo = _materialHelper.GetMaterialInfo(materialType); CheckEnablerEffect(materialInfo); - var mineralLayer = zone.Terrain.GetMineralLayerOrThrow(materialInfo.Type); - var materialAmount = materialInfo.Amount * _miningAmountModifier.Value; - var extractedMaterials = Extract(mineralLayer, terrainLock.Location,(uint) materialAmount); - extractedMaterials.Count.ThrowIfEqual(0, ErrorCodes.NoMineralOnTile); + MineralLayer mineralLayer = zone.Terrain.GetMineralLayerOrThrow(materialInfo.Type); + double materialAmount = materialInfo.Amount * _miningAmountModifier.Value; + List extractedMaterials = Extract(mineralLayer, terrainLock.Location, (uint)materialAmount); + _ = extractedMaterials.Count.ThrowIfEqual(0, ErrorCodes.NoMineralOnTile); extractedMaterials.AddRange(_rareMaterialHandler.GenerateRareMaterials(materialInfo.EntityDefault.Definition)); CreateBeam(terrainLock.Location, BeamState.AlignToTerrain); - using (var scope = Db.CreateTransaction()) + using (TransactionScope scope = Db.CreateTransaction()) { Debug.Assert(ParentRobot != null, "ParentRobot != null"); - var container = ParentRobot.GetContainer(); + + Robots.RobotInventory container = ParentRobot.GetContainer(); + Debug.Assert(container != null, "container != null"); container.EnlistTransaction(); - var player = ParentRobot as Player; - Debug.Assert(player != null,"player != null"); + Player player = ParentRobot is RemoteControlledCreature remoteControlledCreature && + remoteControlledCreature.CommandRobot is Player ownerPlayer + ? ownerPlayer + : ParentRobot as Player; + + Debug.Assert(player != null, "player != null"); - foreach (var material in extractedMaterials) + foreach (ItemInfo material in extractedMaterials) { - var item = (Item)Factory.CreateWithRandomEID(material.Definition); + Item item = (Item)Factory.CreateWithRandomEID(material.Definition); item.Owner = Owner; item.Quantity = material.Quantity; - container.AddItem(item, true); - var drilledMineralDefinition = material.Definition; - var drilledQuantity = material.Quantity; + int drilledMineralDefinition = material.Definition; + int drilledQuantity = material.Quantity; - player.MissionHandler.EnqueueMissionEventInfo(new DrillMineralEventInfo(player,drilledMineralDefinition,drilledQuantity,terrainLock.Location)); - player.Zone?.MiningLogHandler.EnqueueMiningLog(drilledMineralDefinition,drilledQuantity); + player.MissionHandler.EnqueueMissionEventInfo(new DrillMineralEventInfo(player, drilledMineralDefinition, drilledQuantity, terrainLock.Location)); + player.Zone?.MiningLogHandler.EnqueueMiningLog(drilledMineralDefinition, drilledQuantity); } //save container container.Save(); - OnGathererMaterial(zone, player, (int) materialInfo.Type); - + OnGathererMaterial(zone, player, (int)materialInfo.Type); Transaction.Current.OnCommited(() => container.SendUpdateToOwnerAsync()); scope.Complete(); } @@ -156,41 +194,19 @@ private void DoExtractMinerals(IZone zone) private void CheckEnablerEffect(MaterialInfo materialInfo) { - if ( !Zone.Configuration.Terraformable ) + if (!Zone.Configuration.Terraformable) + { return; + } - if (!materialInfo.EnablerExtensionRequired) + if (!materialInfo.EnablerExtensionRequired) + { return; + } - var containsEnablerEffect = ParentRobot.EffectHandler.ContainsEffect(EffectCategory.effcat_pbs_mining_tower_effect); - containsEnablerEffect.ThrowIfFalse(ErrorCodes.MiningEnablerEffectRequired); - } - - private const int MAX_EP_PER_DAY = 1440; - - private readonly ISet LIQUIDS = new HashSet(new int[]{ (int)MaterialType.Crude, (int)MaterialType.Liquizit, (int)MaterialType.Epriton }); - - protected override int CalculateEp(int materialType) - { - var activeGathererModules = ParentRobot.ActiveModules.OfType().Where(m => m.State.Type != ModuleStateType.Idle).ToArray(); - if (activeGathererModules.Length == 0) - return 0; - - var avgCycleTime = activeGathererModules.Select(m => m.CycleTime).Average(); - - var t = TimeSpan.FromDays(1).Divide(avgCycleTime); - var chance = (double)MAX_EP_PER_DAY / t.Ticks; - - chance /= activeGathererModules.Length; - - if (LIQUIDS.Contains(materialType)) - chance /= 2.0; - - var rand = FastRandom.NextDouble(); - if (rand <= chance) - return 1; + bool containsEnablerEffect = ParentRobot.EffectHandler.ContainsEffect(EffectCategory.effcat_pbs_mining_tower_effect); - return 0; + containsEnablerEffect.ThrowIfFalse(ErrorCodes.MiningEnablerEffectRequired); } } } \ No newline at end of file diff --git a/src/Perpetuum/Modules/EffectModules/DetectionModule.cs b/src/Perpetuum/Modules/EffectModules/DetectionModule.cs index 8d6d29f9d..59e52b90d 100644 --- a/src/Perpetuum/Modules/EffectModules/DetectionModule.cs +++ b/src/Perpetuum/Modules/EffectModules/DetectionModule.cs @@ -1,5 +1,6 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Zones.Effects; namespace Perpetuum.Modules.EffectModules diff --git a/src/Perpetuum/Modules/EffectModules/MineDetectorModule.cs b/src/Perpetuum/Modules/EffectModules/MineDetectorModule.cs new file mode 100644 index 000000000..bc0f9a5e1 --- /dev/null +++ b/src/Perpetuum/Modules/EffectModules/MineDetectorModule.cs @@ -0,0 +1,32 @@ +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; +using Perpetuum.Zones.Effects; + +namespace Perpetuum.Modules.EffectModules +{ + public class MineDetectorModule : EffectModule + { + private readonly ItemProperty mineDetectionRange; + + public MineDetectorModule() + { + mineDetectionRange = new ModuleProperty(this, AggregateField.effect_mine_detection_range_modifier); + AddProperty(mineDetectionRange); + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + base.AcceptVisitor(visitor); + } + + protected override void SetupEffect(EffectBuilder effectBuilder) + { + effectBuilder + .SetType(EffectType.effect_mine_detector) + .WithPropertyModifier(mineDetectionRange.ToPropertyModifier()); + } + } +} diff --git a/src/Perpetuum/Modules/EffectModules/RemoteSensorBoosterModule.cs b/src/Perpetuum/Modules/EffectModules/RemoteSensorBoosterModule.cs index 1df2a68b0..cf500cc5e 100644 --- a/src/Perpetuum/Modules/EffectModules/RemoteSensorBoosterModule.cs +++ b/src/Perpetuum/Modules/EffectModules/RemoteSensorBoosterModule.cs @@ -1,8 +1,10 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones.Effects; using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules.EffectModules { @@ -22,9 +24,12 @@ public RemoteSensorBoosterModule() : base(true) protected override bool CanApplyEffect(Unit target) { if (!ParentIsPlayer() || !(target is Npc)) + { return true; + } OnError(ErrorCodes.ThisModuleIsNotSupportedOnNPCs); + return false; } @@ -35,10 +40,11 @@ protected override void OnApplyingEffect(Unit target) protected override void SetupEffect(EffectBuilder effectBuilder) { - effectBuilder.SetType(EffectType.effect_remote_sensor_boost) - .SetSource(ParentRobot) - .WithPropertyModifier(_effectSensorBoosterLockingRangeModifier.ToPropertyModifier()) - .WithPropertyModifier(_effectSensorBoosterLockingTimeModifier.ToPropertyModifier()); + effectBuilder + .SetType(EffectType.effect_remote_sensor_boost) + .SetSource(ParentRobot) + .WithPropertyModifier(_effectSensorBoosterLockingRangeModifier.ToPropertyModifier()) + .WithPropertyModifier(_effectSensorBoosterLockingTimeModifier.ToPropertyModifier()); } } } \ No newline at end of file diff --git a/src/Perpetuum/Modules/EffectModules/SensorBoosterModule.cs b/src/Perpetuum/Modules/EffectModules/SensorBoosterModule.cs index aae306ea3..6d37943bc 100644 --- a/src/Perpetuum/Modules/EffectModules/SensorBoosterModule.cs +++ b/src/Perpetuum/Modules/EffectModules/SensorBoosterModule.cs @@ -1,9 +1,10 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones.Effects; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules.EffectModules { @@ -23,14 +24,17 @@ public SensorBoosterModule() public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override void SetupEffect(EffectBuilder effectBuilder) { - effectBuilder.SetType(EffectType.effect_sensor_boost) - .WithPropertyModifier(_effectSensorBoosterLockingRangeModifier.ToPropertyModifier()) - .WithPropertyModifier(_effectSensorBoosterLockingTimeModifier.ToPropertyModifier()); + effectBuilder + .SetType(EffectType.effect_sensor_boost) + .WithPropertyModifier(_effectSensorBoosterLockingRangeModifier.ToPropertyModifier()) + .WithPropertyModifier(_effectSensorBoosterLockingTimeModifier.ToPropertyModifier()); } diff --git a/src/Perpetuum/Modules/EffectModules/SensorDampenerModule.cs b/src/Perpetuum/Modules/EffectModules/SensorDampenerModule.cs index aa1e5c44f..1c4589c32 100644 --- a/src/Perpetuum/Modules/EffectModules/SensorDampenerModule.cs +++ b/src/Perpetuum/Modules/EffectModules/SensorDampenerModule.cs @@ -1,9 +1,10 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones.Effects; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules.EffectModules { @@ -16,7 +17,6 @@ public class SensorDampenerModule : EffectModule public SensorDampenerModule() : base(true) { optimalRange.AddEffectModifier(AggregateField.effect_ew_optimal_range_modifier); - _ecmStrength = new ModuleProperty(this,AggregateField.ecm_strength); AddProperty(_ecmStrength); _effectSensorDampenerLockingRangeModifier = new ModuleProperty(this, AggregateField.effect_sensor_dampener_locking_range_modifier); @@ -28,18 +28,23 @@ public SensorDampenerModule() : base(true) public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override bool CanApplyEffect(Unit target) { var targetSensorStrength = target.SensorStrength * FastRandom.NextDouble(); var rangedEcmStrength = ModifyValueByOptimalRange(target, _ecmStrength.Value); + if (targetSensorStrength < rangedEcmStrength) { return true; } + OnError(ErrorCodes.AccuracyCheckFailed); + return false; } @@ -50,7 +55,9 @@ protected override void OnApplyingEffect(Unit target) protected override void SetupEffect(EffectBuilder effectBuilder) { - effectBuilder.SetType(EffectType.effect_sensor_supress).SetSource(ParentRobot) + effectBuilder + .SetType(EffectType.effect_sensor_supress) + .SetSource(ParentRobot) .WithPropertyModifier(_effectSensorDampenerLockingRangeModifier.ToPropertyModifier()) .WithPropertyModifier(_effectSensorDampenerLockingTimeModifier.ToPropertyModifier()); } diff --git a/src/Perpetuum/Modules/EffectModules/ShieldGeneratorModule.cs b/src/Perpetuum/Modules/EffectModules/ShieldGeneratorModule.cs index 04d29bb52..9cf4c2066 100644 --- a/src/Perpetuum/Modules/EffectModules/ShieldGeneratorModule.cs +++ b/src/Perpetuum/Modules/EffectModules/ShieldGeneratorModule.cs @@ -2,6 +2,7 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Zones.Effects; namespace Perpetuum.Modules.EffectModules diff --git a/src/Perpetuum/Modules/EffectModules/StealthModule.cs b/src/Perpetuum/Modules/EffectModules/StealthModule.cs index 0762cab19..fbd6d6723 100644 --- a/src/Perpetuum/Modules/EffectModules/StealthModule.cs +++ b/src/Perpetuum/Modules/EffectModules/StealthModule.cs @@ -1,5 +1,6 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Zones.Effects; namespace Perpetuum.Modules.EffectModules diff --git a/src/Perpetuum/Modules/EffectModules/TargetBlinderModule.cs b/src/Perpetuum/Modules/EffectModules/TargetBlinderModule.cs index fe2a036a5..d90f0df7a 100644 --- a/src/Perpetuum/Modules/EffectModules/TargetBlinderModule.cs +++ b/src/Perpetuum/Modules/EffectModules/TargetBlinderModule.cs @@ -1,6 +1,7 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Zones.Effects; namespace Perpetuum.Modules.EffectModules diff --git a/src/Perpetuum/Modules/EffectModules/TargetPainterModule.cs b/src/Perpetuum/Modules/EffectModules/TargetPainterModule.cs index be95b5d81..c1c690c87 100644 --- a/src/Perpetuum/Modules/EffectModules/TargetPainterModule.cs +++ b/src/Perpetuum/Modules/EffectModules/TargetPainterModule.cs @@ -1,6 +1,7 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Zones.Effects; namespace Perpetuum.Modules.EffectModules diff --git a/src/Perpetuum/Modules/EffectModules/WebberModule.cs b/src/Perpetuum/Modules/EffectModules/WebberModule.cs index 7ebabc701..ec0046cf7 100644 --- a/src/Perpetuum/Modules/EffectModules/WebberModule.cs +++ b/src/Perpetuum/Modules/EffectModules/WebberModule.cs @@ -1,9 +1,10 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones.Effects; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules.EffectModules { @@ -21,7 +22,9 @@ public WebberModule() : base(true) public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override bool CanApplyEffect(Unit target) @@ -29,17 +32,24 @@ protected override bool CanApplyEffect(Unit target) if (FastRandom.NextDouble() > ModifyValueByOptimalRange(target, 1.0)) { OnError(ErrorCodes.AccuracyCheckFailed); + return false; } if (!IsCategory(CategoryFlags.cf_longrange_webber)) + { return true; + } var result = GetLineOfSight(target); + if (!result.hit) + { return true; + } OnError(ErrorCodes.LOSFailed); + return false; } @@ -51,12 +61,16 @@ protected override void OnApplyingEffect(Unit target) protected override void SetupEffect(EffectBuilder effectBuilder) { var effectProperty = _effectMassivnesSpeedMaxModifier.ToPropertyModifier(); + effectProperty.Add(effectBuilder.Owner.Massiveness); if (effectProperty.Value >= 1.0) + { effectProperty.ResetToDefaultValue(); + } - effectBuilder.SetType(EffectType.effect_demobilizer) + effectBuilder + .SetType(EffectType.effect_demobilizer) .SetSource(ParentRobot) .WithPropertyModifier(effectProperty); } diff --git a/src/Perpetuum/Modules/EnergyDispersionModule.cs b/src/Perpetuum/Modules/EnergyDispersionModule.cs index 68b47471d..7f210a02f 100644 --- a/src/Perpetuum/Modules/EnergyDispersionModule.cs +++ b/src/Perpetuum/Modules/EnergyDispersionModule.cs @@ -1,5 +1,6 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones.DamageProcessors; diff --git a/src/Perpetuum/Modules/EnergyNeutralizerModule.cs b/src/Perpetuum/Modules/EnergyNeutralizerModule.cs index 72fd313e2..2a3f85690 100644 --- a/src/Perpetuum/Modules/EnergyNeutralizerModule.cs +++ b/src/Perpetuum/Modules/EnergyNeutralizerModule.cs @@ -2,10 +2,11 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones; using Perpetuum.Zones.Locking.Locks; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules { @@ -22,7 +23,9 @@ public EnergyNeutralizerModule() public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override void OnAction() @@ -32,6 +35,7 @@ protected override void OnAction() if (!LOSCheckAndCreateBeam(unitLock.Target)) { OnError(ErrorCodes.LOSFailed); + return; } @@ -44,15 +48,18 @@ protected override void OnAction() if ( coreNeutralized > 0.0 ) { var core = unitLock.Target.Core; + unitLock.Target.Core -= coreNeutralized; coreNeutralizedDone = Math.Abs(core - unitLock.Target.Core); - unitLock.Target.OnCombatEvent(ParentRobot, new EnergyDispersionEventArgs(coreNeutralizedDone)); + var threatValue = (coreNeutralizedDone / 2) + 1; + unitLock.Target.AddThreat(ParentRobot, new Threat(ThreatType.EnWar, threatValue)); } var packet = new CombatLogPacket(CombatLogType.EnergyNeutralize, unitLock.Target, ParentRobot, this); + packet.AppendDouble(coreNeutralized); packet.AppendDouble(coreNeutralizedDone); packet.Send(unitLock.Target,ParentRobot); diff --git a/src/Perpetuum/Modules/EnergyTransfererModule.cs b/src/Perpetuum/Modules/EnergyTransfererModule.cs index 698f8a5b0..df1564673 100644 --- a/src/Perpetuum/Modules/EnergyTransfererModule.cs +++ b/src/Perpetuum/Modules/EnergyTransfererModule.cs @@ -1,10 +1,12 @@ using System; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones; using Perpetuum.Zones.Locking.Locks; using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules { @@ -27,10 +29,12 @@ protected override void OnAction() if (!LOSCheckAndCreateBeam(unitLock.Target)) { OnError(ErrorCodes.LOSFailed); + return; } var coreAmount = _energyTransferAmount.Value; + coreAmount = ModifyValueByOptimalRange(unitLock.Target,coreAmount); var coreNeutralized = 0.0; @@ -39,17 +43,19 @@ protected override void OnAction() if ( coreAmount > 0.0 ) { var core = ParentRobot.Core; + ParentRobot.Core -= coreAmount; coreNeutralized = Math.Abs(core - ParentRobot.Core); var targetCore = unitLock.Target.Core; + unitLock.Target.Core += coreNeutralized; coreTransfered = Math.Abs(targetCore - unitLock.Target.Core); - unitLock.Target.SpreadAssistThreatToNpcs(ParentRobot,new Threat(ThreatType.Support, coreAmount * 2)); } var packet = new CombatLogPacket(CombatLogType.EnergyTransfer, unitLock.Target, ParentRobot, this); + packet.AppendDouble(coreAmount); packet.AppendDouble(coreNeutralized); packet.AppendDouble(coreTransfered); diff --git a/src/Perpetuum/Modules/EnergyVampireModule.cs b/src/Perpetuum/Modules/EnergyVampireModule.cs index 3c75cdf2f..9875dd689 100644 --- a/src/Perpetuum/Modules/EnergyVampireModule.cs +++ b/src/Perpetuum/Modules/EnergyVampireModule.cs @@ -2,10 +2,11 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones; using Perpetuum.Zones.Locking.Locks; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules { @@ -22,7 +23,9 @@ public EnergyVampireModule() public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override void OnAction() @@ -32,11 +35,13 @@ protected override void OnAction() if (!LOSCheckAndCreateBeam(unitLock.Target)) { OnError(ErrorCodes.LOSFailed); + return; } // ennyit szedunk le a targettol var coreAmount = _energyVampiredAmount.Value; + ModifyValueByReactorRadiation(unitLock.Target,ref coreAmount); // optimalrange-el modositjuk coreAmount = ModifyValueByOptimalRange(unitLock.Target,coreAmount); @@ -47,20 +52,21 @@ protected override void OnAction() if ( coreAmount > 0.0 ) { var targetCore = unitLock.Target.Core; + unitLock.Target.Core -= coreAmount; coreNeutralized = Math.Abs(targetCore - unitLock.Target.Core); - unitLock.Target.OnCombatEvent(ParentRobot,new EnergyDispersionEventArgs(coreNeutralized)); // amit sikerult leszedni azt hozzaadjuk a robothoz var core = ParentRobot.Core; + ParentRobot.Core += coreNeutralized; coreTransfered = Math.Abs(core - ParentRobot.Core); - unitLock.Target.AddThreat(ParentRobot, new Threat(ThreatType.EnWar, coreTransfered + 1)); } var packet = new CombatLogPacket(CombatLogType.EnergyVampire, unitLock.Target, ParentRobot, this); + packet.AppendDouble(coreAmount); packet.AppendDouble(coreNeutralized); packet.AppendDouble(coreTransfered); diff --git a/src/Perpetuum/Modules/GangModule.cs b/src/Perpetuum/Modules/GangModule.cs index f8bac21be..4b40412da 100644 --- a/src/Perpetuum/Modules/GangModule.cs +++ b/src/Perpetuum/Modules/GangModule.cs @@ -1,6 +1,7 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; using Perpetuum.Modules.EffectModules; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Zones.Effects; namespace Perpetuum.Modules diff --git a/src/Perpetuum/Modules/GathererModule.cs b/src/Perpetuum/Modules/GathererModule.cs new file mode 100644 index 000000000..3013115d2 --- /dev/null +++ b/src/Perpetuum/Modules/GathererModule.cs @@ -0,0 +1,34 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Players; +using Perpetuum.Zones; + +namespace Perpetuum.Modules +{ + public abstract class GathererModule : ActiveModule + { + protected GathererModule(CategoryFlags ammoCategoryFlags, bool ranged = false) : base(ammoCategoryFlags, ranged) + { + coreUsage.AddEffectModifier(AggregateField.effect_core_usage_gathering_modifier); + cycleTime.AddEffectModifier(AggregateField.effect_gathering_cycle_time_modifier); + } + + protected abstract int CalculateEp(int materialType); + + protected void OnGathererMaterial(IZone zone, Player player, int materialType) + { + if (zone.Configuration.Type == ZoneType.Training) + { + return; + } + + var ep = CalculateEp(materialType); + + if (zone.Configuration.IsBeta) + { + ep *= 2; + } + + player.Character.AddExtensionPointsBoostAndLog(EpForActivityType.Gathering, ep); + } + } +} diff --git a/src/Perpetuum/Modules/HarvesterModule.cs b/src/Perpetuum/Modules/HarvesterModule.cs index a04d3f54f..652e3616c 100644 --- a/src/Perpetuum/Modules/HarvesterModule.cs +++ b/src/Perpetuum/Modules/HarvesterModule.cs @@ -1,63 +1,43 @@ -using System; -using System.Diagnostics; -using System.Linq; -using System.Transactions; -using Perpetuum.Data; +using Perpetuum.Data; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Players; using Perpetuum.Services.MissionEngine.MissionTargets; using Perpetuum.Zones; using Perpetuum.Zones.Beams; using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.RemoteControl; using Perpetuum.Zones.Terrains; -using Perpetuum.Zones.Terrains.Materials.Plants; using Perpetuum.Zones.Terrains.Materials.Plants.Harvesters; +using System; +using System.Diagnostics; +using System.Linq; +using System.Transactions; namespace Perpetuum.Modules { - public abstract class GathererModule : ActiveModule - { - protected GathererModule(CategoryFlags ammoCategoryFlags, bool ranged = false) : base(ammoCategoryFlags, ranged) - { - coreUsage.AddEffectModifier(AggregateField.effect_core_usage_gathering_modifier); - cycleTime.AddEffectModifier(AggregateField.effect_gathering_cycle_time_modifier); - } - - protected abstract int CalculateEp(int materialType); - - protected void OnGathererMaterial(IZone zone, Player player, int materialType) - { - if (zone.Configuration.Type == ZoneType.Training) return; - - var ep = CalculateEp(materialType); - - if (zone.Configuration.IsBeta) - ep *= 2; - - player.Character.AddExtensionPointsBoostAndLog(EpForActivityType.Gathering, ep); - } - } - public class HarvesterModule : GathererModule { + private const int MAX_EP_PER_DAY = 1440; private readonly PlantHarvester.Factory _plantHarvesterFactory; private readonly HarvestingAmountModifierProperty _harverstingAmountModifier; - public HarvesterModule(CategoryFlags ammoCategoryFlags,PlantHarvester.Factory plantHarvesterFactory) : base(ammoCategoryFlags, true) + public HarvesterModule(CategoryFlags ammoCategoryFlags, PlantHarvester.Factory plantHarvesterFactory) : base(ammoCategoryFlags, true) { _plantHarvesterFactory = plantHarvesterFactory; _harverstingAmountModifier = new HarvestingAmountModifierProperty(this); AddProperty(_harverstingAmountModifier); - cycleTime.AddEffectModifier(AggregateField.effect_harvesting_cycle_time_modifier); } public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } public override void UpdateProperty(AggregateField field) @@ -70,147 +50,100 @@ public override void UpdateProperty(AggregateField field) case AggregateField.effect_harvesting_amount_modifier: { _harverstingAmountModifier.Update(); + break; } } } - private const int MAX_EP_PER_DAY = 1440; - protected override int CalculateEp(int materialType) { - var activeGathererModules = ParentRobot.ActiveModules.OfType().Where(m => m.State.Type != ModuleStateType.Idle).ToArray(); + + HarvesterModule[] activeGathererModules = this is RemoteControlledHarvesterModule + ? ParentRobot.ActiveModules.OfType().Where(m => m.State.Type != ModuleStateType.Idle).ToArray() + : ParentRobot.ActiveModules.OfType().Where(m => m.State.Type != ModuleStateType.Idle).ToArray(); + if (activeGathererModules.Length == 0) + { return 0; + } - var avgCycleTime = activeGathererModules.Select(m => m.CycleTime).Average(); - - var t = TimeSpan.FromDays(1).Divide(avgCycleTime); - var chance = (double)MAX_EP_PER_DAY / t.Ticks; + TimeSpan avgCycleTime = activeGathererModules.Select(m => m.CycleTime).Average(); + TimeSpan t = TimeSpan.FromDays(1).Divide(avgCycleTime); + double chance = (double)MAX_EP_PER_DAY / t.Ticks; chance /= activeGathererModules.Length; - var rand = FastRandom.NextDouble(); - if (rand <= chance) - return 1; + double rand = FastRandom.NextDouble(); - return 0; + return rand <= chance ? 1 : 0; } protected override void OnAction() { - var zone = Zone; + IZone zone = Zone; + if (zone == null) + { return; + } DoHarvesting(zone); ConsumeAmmo(); } - private void DoHarvesting(IZone zone) + public void DoHarvesting(IZone zone) { - var terrainLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); + TerrainLock terrainLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); + CreateBeam(terrainLock.Location, BeamState.AlignToTerrain); - using (var scope = Db.CreateTransaction()) + using (TransactionScope scope = Db.CreateTransaction()) { using (new TerrainUpdateMonitor(zone)) { - var plantInfo = zone.Terrain.Plants.GetValue(terrainLock.Location); - var amountModifier = _harverstingAmountModifier.GetValueByPlantType(plantInfo.type); + Zones.Terrains.Materials.Plants.PlantInfo plantInfo = zone.Terrain.Plants.GetValue(terrainLock.Location); + double amountModifier = _harverstingAmountModifier.GetValueByPlantType(plantInfo.type); + IPlantHarvester plantHarvester = _plantHarvesterFactory(zone, amountModifier); - var harvestedPlants = plantHarvester.HarvestPlant(terrainLock.Location); + + System.Collections.Generic.IEnumerable harvestedPlants = plantHarvester.HarvestPlant(terrainLock.Location); Debug.Assert(ParentRobot != null, "ParentRobot != null"); - var container = ParentRobot.GetContainer(); + + Robots.RobotInventory container = ParentRobot.GetContainer(); + Debug.Assert(container != null, "container != null"); container.EnlistTransaction(); - var player = ParentRobot as Player; - Debug.Assert(player != null,"player != null"); + Player player = ParentRobot is RemoteControlledCreature remoteControlledCreature && + remoteControlledCreature.CommandRobot is Player ownerPlayer + ? ownerPlayer + : ParentRobot as Player; - foreach (var extractedMaterial in harvestedPlants) + Debug.Assert(player != null, "player != null"); + + foreach (ItemInfo extractedMaterial in harvestedPlants) { - var item = (Item)Factory.CreateWithRandomEID(extractedMaterial.Definition); + Item item = (Item)Factory.CreateWithRandomEID(extractedMaterial.Definition); + item.Owner = Owner; item.Quantity = extractedMaterial.Quantity; - container.AddItem(item, true); - var extractedHarvestDefinition = extractedMaterial.Definition; - var extractedQuantity = extractedMaterial.Quantity; + int extractedHarvestDefinition = extractedMaterial.Definition; + int extractedQuantity = extractedMaterial.Quantity; player.MissionHandler.EnqueueMissionEventInfo(new HarvestPlantEventInfo(player, extractedHarvestDefinition, extractedQuantity, terrainLock.Location)); player.Zone?.HarvestLogHandler.EnqueueHarvestLog(extractedHarvestDefinition, extractedQuantity); } - //everything went ok, save container container.Save(); - - OnGathererMaterial(zone, player, (int) plantInfo.type); - + OnGathererMaterial(zone, player, (int)plantInfo.type); Transaction.Current.OnCommited(() => container.SendUpdateToOwnerAsync()); scope.Complete(); } } } - - private class HarvestingAmountModifierProperty : ModuleProperty - { - public HarvestingAmountModifierProperty(HarvesterModule module) : base(module, AggregateField.harvesting_amount_modifier) - { - AddEffectModifier(AggregateField.effect_harvesting_amount_modifier); - } - - protected override double CalculateValue() - { - if (module.ParentRobot == null) - return 1.0; - - var p = module.ParentRobot.GetPropertyModifier(AggregateField.harvesting_amount_modifier); - ApplyEffectModifiers(ref p); - return p.Value; - } - - public double GetValueByPlantType(PlantType plantType) - { - var modifier = AggregateField.undefined; - - switch (plantType) - { - case PlantType.RustBush: - { - modifier = AggregateField.harvesting_amount_helioptris_modifier; - break; - } - case PlantType.SlimeRoot: - { - modifier = AggregateField.harvesting_amount_triandlus_modifier; - break; - } - case PlantType.ElectroPlant: - { - modifier = AggregateField.harvesting_amount_electroplant_modifier; - break; - } - case PlantType.TreeIron: - { - modifier = AggregateField.harvesting_amount_prismocitae_modifier; - break; - } - } - - var property = this.ToPropertyModifier(); - - if (module.ParentRobot != null && modifier != AggregateField.undefined) - { - var mod = module.ParentRobot.GetPropertyModifier(modifier); - mod.Modify(ref property); - } - - return property.Value; - } - } - } } \ No newline at end of file diff --git a/src/Perpetuum/Modules/Module.cs b/src/Perpetuum/Modules/Module.cs index 3391793fb..bdbad69fb 100644 --- a/src/Perpetuum/Modules/Module.cs +++ b/src/Perpetuum/Modules/Module.cs @@ -1,12 +1,13 @@ -using System.Collections.Generic; -using System.Linq; -using Perpetuum.Containers; +using Perpetuum.Containers; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Players; using Perpetuum.Robots; using Perpetuum.Zones; +using System.Collections.Generic; +using System.Linq; namespace Perpetuum.Modules { @@ -19,11 +20,11 @@ public Module() { _powerGridUsage = new ModuleProperty(this, AggregateField.powergrid_usage); AddProperty(_powerGridUsage); - _cpuUsage = new ModuleProperty(this,AggregateField.cpu_usage); + _cpuUsage = new ModuleProperty(this, AggregateField.cpu_usage); AddProperty(_cpuUsage); } - public ILookup PropertyModifiers { get; set; } + public ILookup PropertyModifiers { get; set; } public double PowerGridUsage { @@ -63,7 +64,7 @@ public bool ParentIsPlayer() public int Slot { get { return DynamicProperties.GetOrDefault(k.slot); } - set { DynamicProperties.Update(k.slot,value); } + set { DynamicProperties.Update(k.slot, value); } } public long ModuleFlag @@ -85,7 +86,7 @@ public override Dictionary ToDictionary() var result = base.ToDictionary(); result.Add(k.slot, Slot); - result.Add(k.state, (byte) ModuleStateType.Idle); + result.Add(k.state, (byte)ModuleStateType.Idle); return result; } @@ -109,7 +110,7 @@ public Packet BuildModuleInfoPacket() var packet = new Packet(ZoneCommand.ModuleInfoResult); packet.AppendByte((byte)ParentComponent.Type); - packet.AppendByte((byte) Slot); + packet.AppendByte((byte)Slot); var properties = Properties.ToList(); diff --git a/src/Perpetuum/Modules/ModuleProperties/CycleTimeProperty.cs b/src/Perpetuum/Modules/ModuleProperties/CycleTimeProperty.cs new file mode 100644 index 000000000..de4f8cdb4 --- /dev/null +++ b/src/Perpetuum/Modules/ModuleProperties/CycleTimeProperty.cs @@ -0,0 +1,42 @@ +using Perpetuum.ExportedTypes; + +namespace Perpetuum.Modules.ModuleProperties +{ + public class CycleTimeProperty : ModuleProperty + { + private readonly ActiveModule _module; + + public CycleTimeProperty(ActiveModule module) : base(module, AggregateField.cycle_time) + { + _module = module; + } + + protected override double CalculateValue() + { + var cycleTime = _module.GetPropertyModifier(AggregateField.cycle_time); + var ammo = _module.GetAmmo(); + + ammo?.ModifyCycleTime(ref cycleTime); + + var driller = _module as DrillerModule; + + if (driller != null) + { + var miningAmmo = ammo as MiningAmmo; + + if (miningAmmo != null) + { + miningAmmo.miningCycleTimeModifier.Update(); + + var miningCycleTimeMod = miningAmmo.miningCycleTimeModifier.ToPropertyModifier(); + + miningCycleTimeMod.Modify(ref cycleTime); + } + } + + ApplyEffectModifiers(ref cycleTime); + + return cycleTime.Value; + } + } +} diff --git a/src/Perpetuum/Modules/ModuleProperties/FalloffProperty.cs b/src/Perpetuum/Modules/ModuleProperties/FalloffProperty.cs new file mode 100644 index 000000000..eee5a69be --- /dev/null +++ b/src/Perpetuum/Modules/ModuleProperties/FalloffProperty.cs @@ -0,0 +1,41 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Modules.Weapons; + +namespace Perpetuum.Modules.ModuleProperties +{ + public class FalloffProperty : ModuleProperty + { + public FalloffProperty(ActiveModule module) : base(module, AggregateField.falloff) + { + } + + protected override double CalculateValue() + { + var falloff = ItemPropertyModifier.Create(AggregateField.falloff); + var ammo = ((ActiveModule)module).GetAmmo(); + + if (module is MissileWeaponModule m) + { + if (ammo != null) + { + falloff = ammo.FalloffRangePropertyModifier; + + var missileRangeMod = m.MissileFalloffModifier.ToPropertyModifier(); + + missileRangeMod.Modify(ref falloff); + module.ApplyRobotPropertyModifiers(ref falloff); + } + } + else + { + falloff = module.GetPropertyModifier(AggregateField.falloff); + ammo?.ModifyFalloff(ref falloff); + } + + ApplyEffectModifiers(ref falloff); + + return falloff.Value; + } + } +} diff --git a/src/Perpetuum/Modules/ModuleProperties/HarvestingAmountModifierProperty.cs b/src/Perpetuum/Modules/ModuleProperties/HarvestingAmountModifierProperty.cs new file mode 100644 index 000000000..c48f169fb --- /dev/null +++ b/src/Perpetuum/Modules/ModuleProperties/HarvestingAmountModifierProperty.cs @@ -0,0 +1,71 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Zones.Terrains.Materials.Plants; + +namespace Perpetuum.Modules.ModuleProperties +{ + public class HarvestingAmountModifierProperty : ModuleProperty + { + public HarvestingAmountModifierProperty(GathererModule module) : base(module, AggregateField.harvesting_amount_modifier) + { + AddEffectModifier(AggregateField.effect_harvesting_amount_modifier); + } + + public double GetValueByPlantType(PlantType plantType) + { + var modifier = AggregateField.undefined; + + switch (plantType) + { + case PlantType.RustBush: + { + modifier = AggregateField.harvesting_amount_helioptris_modifier; + + break; + } + case PlantType.SlimeRoot: + { + modifier = AggregateField.harvesting_amount_triandlus_modifier; + + break; + } + case PlantType.ElectroPlant: + { + modifier = AggregateField.harvesting_amount_electroplant_modifier; + + break; + } + case PlantType.TreeIron: + { + modifier = AggregateField.harvesting_amount_prismocitae_modifier; + + break; + } + } + + var property = this.ToPropertyModifier(); + + if (module.ParentRobot != null && modifier != AggregateField.undefined) + { + var mod = module.ParentRobot.GetPropertyModifier(modifier); + + mod.Modify(ref property); + } + + return property.Value; + } + + protected override double CalculateValue() + { + if (module.ParentRobot == null) + { + return 1.0; + } + + var p = module.ParentRobot.GetPropertyModifier(AggregateField.harvesting_amount_modifier); + + ApplyEffectModifiers(ref p); + + return p.Value; + } + } +} diff --git a/src/Perpetuum/Modules/ModuleProperties/MiningAmountModifierProperty.cs b/src/Perpetuum/Modules/ModuleProperties/MiningAmountModifierProperty.cs new file mode 100644 index 000000000..b96261939 --- /dev/null +++ b/src/Perpetuum/Modules/ModuleProperties/MiningAmountModifierProperty.cs @@ -0,0 +1,31 @@ +using Perpetuum.ExportedTypes; + +namespace Perpetuum.Modules.ModuleProperties +{ + public class MiningAmountModifierProperty : ModuleProperty + { + private readonly GathererModule _module; + + public MiningAmountModifierProperty(GathererModule module) : base(module, AggregateField.mining_amount_modifier) + { + _module = module; + AddEffectModifier(AggregateField.effect_mining_amount_modifier); + } + + protected override double CalculateValue() + { + if (module.ParentRobot == null) + { + return 1.0; + } + + var m = module.ParentRobot.GetPropertyModifier(AggregateField.mining_amount_modifier); + var ammo = (MiningAmmo)_module.GetAmmo(); + + ammo?.ApplyMiningAmountModifier(ref m); + module.ParentRobot?.ApplyEffectPropertyModifiers(AggregateField.effect_mining_amount_modifier, ref m); + + return m.Value; + } + } +} diff --git a/src/Perpetuum/Modules/ModuleProperties/ModuleProperty.cs b/src/Perpetuum/Modules/ModuleProperties/ModuleProperty.cs new file mode 100644 index 000000000..82d27dd1e --- /dev/null +++ b/src/Perpetuum/Modules/ModuleProperties/ModuleProperty.cs @@ -0,0 +1,59 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using System.Collections.Generic; + +namespace Perpetuum.Modules.ModuleProperties +{ + public class ModuleProperty : ItemProperty + { + protected readonly Module module; + private List _effectModifiers; + + public ModuleProperty(Module module, AggregateField field) : base(field) + { + this.module = module; + } + + public void AddEffectModifier(AggregateField field) + { + if (_effectModifiers == null) + { + _effectModifiers = new List(); + } + + _effectModifiers.Add(field); + } + + protected override double CalculateValue() + { + var m = module.GetPropertyModifier(Field); + + ApplyEffectModifiers(ref m); + + return m.Value; + } + + protected void ApplyEffectModifiers(ref ItemPropertyModifier m) + { + if (_effectModifiers == null) + { + return; + } + + foreach (var effectModifier in _effectModifiers) + { + module.ParentRobot?.ApplyEffectPropertyModifiers(effectModifier, ref m); + } + } + + protected override bool IsRelated(AggregateField field) + { + if (_effectModifiers != null && _effectModifiers.Contains(field)) + { + return true; + } + + return base.IsRelated(field); + } + } +} diff --git a/src/Perpetuum/Modules/ModuleProperties/OptimalRangeProperty.cs b/src/Perpetuum/Modules/ModuleProperties/OptimalRangeProperty.cs new file mode 100644 index 000000000..db42bd69f --- /dev/null +++ b/src/Perpetuum/Modules/ModuleProperties/OptimalRangeProperty.cs @@ -0,0 +1,45 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Modules.Weapons; + +namespace Perpetuum.Modules.ModuleProperties +{ + public class OptimalRangeProperty : ModuleProperty + { + private readonly ActiveModule _module; + + public OptimalRangeProperty(ActiveModule module) : base(module, AggregateField.optimal_range) + { + _module = module; + AddEffectModifier(AggregateField.effect_optimal_range_modifier); + } + + protected override double CalculateValue() + { + var optimalRange = ItemPropertyModifier.Create(AggregateField.optimal_range); + var ammo = _module.GetAmmo(); + + if (module is MissileWeaponModule m) + { + if (ammo != null) + { + optimalRange = ammo.OptimalRangePropertyModifier; + + var missileRangeMod = m.MissileRangeModifier.ToPropertyModifier(); + + missileRangeMod.Modify(ref optimalRange); + module.ApplyRobotPropertyModifiers(ref optimalRange); + } + } + else + { + optimalRange = module.GetPropertyModifier(AggregateField.optimal_range); + ammo?.ModifyOptimalRange(ref optimalRange); + } + + ApplyEffectModifiers(ref optimalRange); + + return optimalRange.Value; + } + } +} diff --git a/src/Perpetuum/Modules/RemoteArmorRepairModule.cs b/src/Perpetuum/Modules/RemoteArmorRepairModule.cs index 74177f3eb..660f87d2a 100644 --- a/src/Perpetuum/Modules/RemoteArmorRepairModule.cs +++ b/src/Perpetuum/Modules/RemoteArmorRepairModule.cs @@ -1,6 +1,7 @@ using Perpetuum.Units; using Perpetuum.Zones.Locking.Locks; using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; using Perpetuum.Zones.PBS; namespace Perpetuum.Modules @@ -16,19 +17,19 @@ protected override void OnAction() var unitLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); (ParentIsPlayer() && unitLock.Target is Npc).ThrowIfTrue(ErrorCodes.ThisModuleIsNotSupportedOnNPCs); - // csak pbs-re nezzuk ((unitLock.Target is IPBSObject) && unitLock.Target.Armor.Ratio(unitLock.Target.ArmorMax) >= 1.0).ThrowIfTrue(ErrorCodes.BuildingIsAtFullHealth); if (!LOSCheckAndCreateBeam(unitLock.Target)) { OnError(ErrorCodes.LOSFailed); + return; } var repairAmount = armorRepairAmount.Value; - repairAmount = ModifyValueByOptimalRange(unitLock.Target,repairAmount); + repairAmount = ModifyValueByOptimalRange(unitLock.Target,repairAmount); OnRepair(unitLock.Target,repairAmount); unitLock.Target.SpreadAssistThreatToNpcs(ParentRobot,new Threat(ThreatType.Support,repairAmount * 2)); } diff --git a/src/Perpetuum/Modules/RemoteControlledDrillerModule.cs b/src/Perpetuum/Modules/RemoteControlledDrillerModule.cs new file mode 100644 index 000000000..263e18751 --- /dev/null +++ b/src/Perpetuum/Modules/RemoteControlledDrillerModule.cs @@ -0,0 +1,31 @@ +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Zones.RemoteControl; +using Perpetuum.Zones.Terrains.Materials; + +namespace Perpetuum.Modules +{ + public class RemoteControlledDrillerModule : DrillerModule + { + public RemoteControlledDrillerModule(RareMaterialHandler rareMaterialHandler, MaterialHelper materialHelper) + : base(CategoryFlags.undefined, rareMaterialHandler, materialHelper) + { + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + protected override void OnAction() + { + if (Zone != null) + { + DoExtractMinerals(Zone); + } + } + } +} diff --git a/src/Perpetuum/Modules/RemoteControlledHarvesterModule.cs b/src/Perpetuum/Modules/RemoteControlledHarvesterModule.cs new file mode 100644 index 000000000..fb72ff92a --- /dev/null +++ b/src/Perpetuum/Modules/RemoteControlledHarvesterModule.cs @@ -0,0 +1,30 @@ +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Zones.RemoteControl; +using Perpetuum.Zones.Terrains.Materials.Plants.Harvesters; + +namespace Perpetuum.Modules +{ + public class RemoteControlledHarvesterModule : HarvesterModule + { + public RemoteControlledHarvesterModule(PlantHarvester.Factory plantHarvesterFactory) : base(CategoryFlags.undefined, plantHarvesterFactory) + { + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + protected override void OnAction() + { + if (Zone != null) + { + DoHarvesting(Zone); + } + } + } +} diff --git a/src/Perpetuum/Modules/RemoteControllerModule.cs b/src/Perpetuum/Modules/RemoteControllerModule.cs new file mode 100644 index 000000000..157b9c257 --- /dev/null +++ b/src/Perpetuum/Modules/RemoteControllerModule.cs @@ -0,0 +1,226 @@ +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; +using Perpetuum.Players; +using Perpetuum.Units; +using Perpetuum.Units.DockingBases; +using Perpetuum.Zones; +using Perpetuum.Zones.Beams; +using Perpetuum.Zones.Finders; +using Perpetuum.Zones.Finders.PositionFinders; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using Perpetuum.Zones.RemoteControl; +using Perpetuum.Zones.Teleporting; +using System; +using System.Linq; + +namespace Perpetuum.Modules +{ + public class RemoteControllerModule : ActiveModule + { + private const int SentryTurretHeight = 7; + private const double SpawnRangeMin = 2; + private const double SpawnRangeMax = 5; + private readonly ModuleProperty bandwidthMax; + private readonly ModuleProperty operationalRange; + private readonly ModuleProperty lifetime; + private BandwidthHandler bandwidthHandler; + + public double BandwidthMax => bandwidthMax.Value; + + public RemoteControllerModule(CategoryFlags ammoCategoryFlags) : base(ammoCategoryFlags, true) + { + optimalRange.AddEffectModifier(AggregateField.effect_ew_optimal_range_modifier); + + bandwidthMax = new ModuleProperty(this, AggregateField.remote_control_bandwidth_max); + AddProperty(bandwidthMax); + + operationalRange = new ModuleProperty(this, AggregateField.remote_control_operational_range); + AddProperty(operationalRange); + + lifetime = new ModuleProperty(this, AggregateField.remote_control_lifetime); + AddProperty(lifetime); + + InitBandwidthHandler(this); + } + + private void InitBandwidthHandler(RemoteControllerModule module) + { + bandwidthHandler = new BandwidthHandler(module); + } + + public void SyncRemoteChannels() + { + bandwidthHandler.Update(); + } + + public bool HasFreeBandwidthFor(RemoteControlledUnit unit) + { + return bandwidthHandler.HasFreeBandwidthFor(unit); + } + + public void UseRemoteChannel(RemoteControlledCreature turret) + { + bandwidthHandler.UseRemoteChannel(turret); + turret.RemoteChannelDeactivated += bandwidthHandler.OnRemoteChannelDeactivated; + bandwidthHandler.Update(); + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + public void CloseAllChannels() + { + bandwidthHandler.CloseAllChannels(); + } + + protected override void OnAction() + { + if (bandwidthHandler == null) + { + return; + } + + SyncRemoteChannels(); + + RemoteControlledUnit ammo = GetAmmo() as RemoteControlledUnit; + + HasFreeBandwidthFor(ammo).ThrowIfFalse(ErrorCodes.MaxBandwidthExceed); + + Position targetPosition; + + if (ammo.ED.Options.TurretType != TurretType.CombatDrone) + { + + Lock myLock = GetLock(); + + if (myLock is TerrainLock) + { + targetPosition = (myLock as TerrainLock).Location; + } + else if (myLock is UnitLock) + { + targetPosition = (myLock as UnitLock).Target.CurrentPosition; + } + else + { + OnError(ErrorCodes.InvalidLockType); + + return; + } + + Zone.Units + .OfType() + .WithinRange(Zone.FixZ(targetPosition), DistanceConstants.RCU_DEPLOY_RANGE_FROM_RCU) + .Any() + .ThrowIfTrue(ErrorCodes.RemoteControlledTurretInRange); + + LOSResult r = Zone.IsInLineOfSight(ParentRobot, targetPosition.AddToZ(SentryTurretHeight), false); + + if (r.hit) + { + OnError(ErrorCodes.LOSFailed); + + return; + } + } + else + { + targetPosition = GetSpawnPosition(ParentRobot.CurrentPosition); + } + + Player player = ParentRobot is Player robotAsPlayer + ? robotAsPlayer + : null; + + + if (player != null) + { + ammo.CheckEnablerExtensionsAndThrowIfFailed(player.Character, ErrorCodes.ExtensionLevelMismatchTerrain); + } + + RemoteControlledCreature remoteControlledCreature; + if (ammo.ED.Options.TurretType == TurretType.Sentry) + { + remoteControlledCreature = (SentryTurret)Factory.CreateWithRandomEID(ammo.ED.Options.TurretId); + remoteControlledCreature.Behavior = Behavior.Create(BehaviorType.RemoteControlledTurret); + + Position spawnPosition = Zone.FixZ(targetPosition); + + Zone.Units + .OfType() + .WithinRange(spawnPosition, DistanceConstants.RCU_DEPLOY_RANGE_FROM_BASE) + .Any() + .ThrowIfTrue(ErrorCodes.TurretNotDeployableNearObject); + + Zone.Units + .OfType() + .WithinRange(spawnPosition, DistanceConstants.RCU_DEPLOY_RANGE_FROM_TELEPORT) + .Any() + .ThrowIfTrue(ErrorCodes.TurretNotDeployableNearObject); + } + else if (ammo.ED.Options.TurretType == TurretType.Mining || ammo.ED.Options.TurretType == TurretType.Harvesting) + { + remoteControlledCreature = (IndustrialTurret)Factory.CreateWithRandomEID(ammo.ED.Options.TurretId); + (remoteControlledCreature as IndustrialTurret).SetTurretType(ammo.ED.Options.TurretType); + remoteControlledCreature.Behavior = Behavior.Create(BehaviorType.RemoteControlledTurret); + } + else if (ammo.ED.Options.TurretType == TurretType.CombatDrone) + { + remoteControlledCreature = (CombatDrone)Factory.CreateWithRandomEID(ammo.ED.Options.TurretId); + remoteControlledCreature.Behavior = Behavior.Create(BehaviorType.RemoteControlledDrone); + (remoteControlledCreature as CombatDrone).GuardRange = 5; + } + else + { + _ = PerpetuumException.Create(ErrorCodes.InvalidAmmoDefinition); + + return; + } + + remoteControlledCreature.SetCommandRobot(player ?? ParentRobot); + + remoteControlledCreature.Owner = ParentRobot.Owner; + remoteControlledCreature.SetBandwidthUsage(ammo.RemoteChannelBandwidthUsage); + + UseRemoteChannel(remoteControlledCreature); + + remoteControlledCreature.DespawnTime = TimeSpan.FromMilliseconds(lifetime.Value); + remoteControlledCreature.SetGroup(bandwidthHandler); + + ClosestWalkablePositionFinder finder = new ClosestWalkablePositionFinder(Zone, targetPosition); + Position position = finder.FindOrThrow(); + + remoteControlledCreature.HomePosition = position; + remoteControlledCreature.HomeRange = operationalRange.Value; + remoteControlledCreature.Orientation = FastRandom.NextInt(0, 3) * 0.25; + remoteControlledCreature.CallForHelp = true; + + BeamBuilder deployBeamBuilder = Beam.NewBuilder() + .WithType(BeamType.dock_in) + .WithSource(remoteControlledCreature.CommandRobot) + .WithTarget(remoteControlledCreature) + .WithState(BeamState.Hit) + .WithDuration(TimeSpan.FromSeconds(5)); + + remoteControlledCreature.AddToZone(Zone, position, ZoneEnterType.Default, deployBeamBuilder); + ConsumeAmmo(); + } + + private Position GetSpawnPosition(Position spawnOrigin) + { + double spawnRangeMin = SpawnRangeMin; + double spawnRangeMax = SpawnRangeMax; + Position spawnPosition = spawnOrigin.GetRandomPositionInRange2D(spawnRangeMin, spawnRangeMax).Clamp(Zone.Size); + + return spawnPosition; + } + } +} diff --git a/src/Perpetuum/Modules/SensorJammerModule.cs b/src/Perpetuum/Modules/SensorJammerModule.cs index 27791f5f9..3b0c2c15c 100644 --- a/src/Perpetuum/Modules/SensorJammerModule.cs +++ b/src/Perpetuum/Modules/SensorJammerModule.cs @@ -1,11 +1,12 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Robots; using Perpetuum.Units; using Perpetuum.Zones; using Perpetuum.Zones.DamageProcessors; using Perpetuum.Zones.Locking.Locks; -using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; namespace Perpetuum.Modules { @@ -23,17 +24,19 @@ public SensorJammerModule() : base(true) public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } protected override void OnAction() { var unitLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); var robot = unitLock.Target.ThrowIfNotType(ErrorCodes.InvalidTarget); - var success = false; var targetSensorStrength = robot.SensorStrength * FastRandom.NextDouble(); var rangedEcmStrength = ModifyValueByOptimalRange(robot, _ecmStrength.Value); + if (targetSensorStrength < rangedEcmStrength) { robot.ResetLocks(); @@ -42,9 +45,9 @@ protected override void OnAction() } var packet = new CombatLogPacket(CombatLogType.Jammer, robot,ParentRobot,this); + packet.AppendByte(success.ToByte()); packet.Send(ParentRobot,robot); - robot.OnCombatEvent(ParentRobot,new SensorJammerEventArgs(success)); } } diff --git a/src/Perpetuum/Modules/Weapons/FirearmWeaponModule.cs b/src/Perpetuum/Modules/Weapons/FirearmWeaponModule.cs index 8f05e7ff7..04ae4b9b3 100644 --- a/src/Perpetuum/Modules/Weapons/FirearmWeaponModule.cs +++ b/src/Perpetuum/Modules/Weapons/FirearmWeaponModule.cs @@ -1,4 +1,5 @@ using Perpetuum.ExportedTypes; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; namespace Perpetuum.Modules.Weapons diff --git a/src/Perpetuum/Modules/Weapons/MissileWeaponModule.cs b/src/Perpetuum/Modules/Weapons/MissileWeaponModule.cs index 71c2a092d..3c20334d4 100644 --- a/src/Perpetuum/Modules/Weapons/MissileWeaponModule.cs +++ b/src/Perpetuum/Modules/Weapons/MissileWeaponModule.cs @@ -1,6 +1,7 @@ using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; using Perpetuum.Items; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; namespace Perpetuum.Modules.Weapons diff --git a/src/Perpetuum/Modules/Weapons/WeaponAmmo.cs b/src/Perpetuum/Modules/Weapons/WeaponAmmo.cs index a959a65b3..cdfd2ba87 100644 --- a/src/Perpetuum/Modules/Weapons/WeaponAmmo.cs +++ b/src/Perpetuum/Modules/Weapons/WeaponAmmo.cs @@ -3,6 +3,7 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; using Perpetuum.Items.Ammos; +using Perpetuum.Zones.RemoteControl; namespace Perpetuum.Modules.Weapons { @@ -81,8 +82,10 @@ private IList CalculateCleanDamages() property = GetPropertyModifier(AggregateField.damage_explosive); - if (!property.HasValue) + if (!property.HasValue) + { return result; + } damageModifier.Modify(ref property); result.Add(new Damage(DamageType.Explosive, property.Value)); diff --git a/src/Perpetuum/Modules/Weapons/WeaponModule.cs b/src/Perpetuum/Modules/Weapons/WeaponModule.cs index 59faa97d1..0b4a31243 100644 --- a/src/Perpetuum/Modules/Weapons/WeaponModule.cs +++ b/src/Perpetuum/Modules/Weapons/WeaponModule.cs @@ -1,15 +1,15 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Perpetuum.EntityFramework; +using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; -using Perpetuum.Services.RiftSystem; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Units; using Perpetuum.Zones; using Perpetuum.Zones.Beams; using Perpetuum.Zones.Locking; using Perpetuum.Zones.Locking.Locks; using Perpetuum.Zones.Terrains; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; namespace Perpetuum.Modules.Weapons { @@ -18,12 +18,13 @@ public class WeaponModule : ActiveModule private readonly ModuleAction _action; public ModuleProperty DamageModifier { get; } + public ModuleProperty Accuracy { get; } public WeaponModule(CategoryFlags ammoCategoryFlags) : base(ammoCategoryFlags, true) { _action = new ModuleAction(this); - DamageModifier = new ModuleProperty(this,AggregateField.damage_modifier); + DamageModifier = new ModuleProperty(this, AggregateField.damage_modifier); AddProperty(DamageModifier); Accuracy = new ModuleProperty(this, AggregateField.accuracy); AddProperty(Accuracy); @@ -34,7 +35,38 @@ public WeaponModule(CategoryFlags ammoCategoryFlags) : base(ammoCategoryFlags, t public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } + } + + protected override void OnAction() + { + _action.DoAction(); + } + + protected virtual bool CheckAccuracy(Unit victim) + { + double rnd = FastRandom.NextDouble(); + bool isMiss = rnd * Accuracy.Value > victim.SignatureRadius; + + return isMiss; + } + + protected virtual IDamageBuilder GetDamageBuilder() + { + return DamageInfo.Builder + .WithAttacker(ParentRobot) + .WithOptimalRange(OptimalRange) + .WithFalloff(Falloff) + .WithDamages(GetCleanDamages()); + } + + private IEnumerable GetCleanDamages() + { + WeaponAmmo ammo = (WeaponAmmo)GetAmmo(); + + return ammo != null ? ammo.GetCleanDamages() : new Damage[0]; } private class ModuleAction : ILockVisitor @@ -50,7 +82,8 @@ public void DoAction() { _weapon.ParentRobot.HasShieldEffect.ThrowIfTrue(ErrorCodes.ShieldIsActive); - var currentLock = _weapon.GetLock(); + Lock currentLock = _weapon.GetLock(); + currentLock?.AcceptVisitor(this); } @@ -61,57 +94,66 @@ public void VisitLock(Lock @lock) public void VisitUnitLock(UnitLock unitLock) { - var victim = unitLock.Target; + Unit victim = unitLock.Target; victim.InZone.ThrowIfFalse(ErrorCodes.TargetNotFound); victim.States.Dead.ThrowIfTrue(ErrorCodes.TargetIsDead); - var err = victim.IsAttackable; + ErrorCodes err = victim.IsAttackable; + if (err != ErrorCodes.NoError) + { throw new PerpetuumException(err); + } victim.IsInvulnerable.ThrowIfTrue(ErrorCodes.TargetIsInvulnerable); - _weapon.ConsumeAmmo(); - var result = _weapon.GetLineOfSight(victim); + LOSResult result = _weapon.GetLineOfSight(victim); + if (result.hit) { DoDamageToPosition(result.position); _weapon.OnError(ErrorCodes.LOSFailed); + return; } - var distance = _weapon.ParentRobot.GetDistance(victim); - var bulletTime = _weapon.GetAmmo().BulletTime; - var flyTime = (int)((distance / bulletTime) * 1000); - var beamTime = (int)Math.Max(flyTime, _weapon.CycleTime.TotalMilliseconds); - - var miss = _weapon.CheckAccuracy(victim); + double distance = _weapon.ParentRobot.GetDistance(victim); + double bulletTime = _weapon.GetAmmo().BulletTime; + int flyTime = (int)(distance / bulletTime * 1000); + int beamTime = (int)Math.Max(flyTime, _weapon.CycleTime.TotalMilliseconds); + bool miss = _weapon.CheckAccuracy(victim); + if (miss) { - _weapon.CreateBeam(victim, BeamState.Miss,beamTime,bulletTime); + _ = _weapon.CreateBeam(victim, BeamState.Miss, beamTime, bulletTime); _weapon.OnError(ErrorCodes.AccuracyCheckFailed); + return; } - var delay = _weapon.CreateBeam(victim, BeamState.Hit, beamTime, bulletTime); + int delay = _weapon.CreateBeam(victim, BeamState.Hit, beamTime, bulletTime); + flyTime += delay; - var builder = _weapon.GetDamageBuilder(); - Task.Delay(flyTime).ContinueWith(t => victim.TakeDamage(builder.Build())); + IDamageBuilder builder = _weapon.GetDamageBuilder(); + + _ = Task.Delay(flyTime).ContinueWith(t => victim.TakeDamage(builder.Build())); } public void VisitTerrainLock(TerrainLock terrainLock) { - var location = terrainLock.Location; + Position location = terrainLock.Location; _weapon.ConsumeAmmo(); - var blockingInfo = _weapon?.ParentRobot?.Zone?.Terrain.Blocks.GetValue(terrainLock.Location) ?? BlockingInfo.None; - location = location.AddToZ(Math.Min(blockingInfo.Height,20)); + BlockingInfo blockingInfo = _weapon?.ParentRobot?.Zone?.Terrain.Blocks.GetValue(terrainLock.Location) ?? BlockingInfo.None; + + location = location.AddToZ(Math.Min(blockingInfo.Height, 20)); + + LOSResult losResult = _weapon.GetLineOfSight(location); - var losResult = _weapon.GetLineOfSight(location); if (losResult.hit && !location.IsEqual2D(losResult.position)) { location = losResult.position; @@ -123,23 +165,28 @@ public void VisitTerrainLock(TerrainLock terrainLock) private void DoDamageToPosition(Position location) { - var distance = _weapon.ParentRobot.CurrentPosition.TotalDistance3D(location); - var bulletTime = _weapon.GetAmmo().BulletTime; - var flyTime = (int)((distance / bulletTime) * 1000); + double distance = _weapon.ParentRobot.CurrentPosition.TotalDistance3D(location); + double bulletTime = _weapon.GetAmmo().BulletTime; + int flyTime = (int)(distance / bulletTime * 1000); + int beamTime = (int)Math.Max(flyTime, _weapon.CycleTime.TotalMilliseconds); - var beamTime = (int)Math.Max(flyTime, _weapon.CycleTime.TotalMilliseconds); flyTime += _weapon.CreateBeam(location, BeamState.Hit, beamTime, bulletTime); - var damage = _weapon.GetDamageBuilder().Build().CalculatePlantDamages(); + double damage = _weapon.GetDamageBuilder().Build().CalculatePlantDamages(); if (damage <= 0.0) + { return; + } + + IZone zone = _weapon.Zone; - var zone = _weapon.Zone; if (zone == null) + { return; + } - Task.Delay(flyTime).ContinueWith(t => DealDamageToPosition(zone, location, damage)); + _ = Task.Delay(flyTime).ContinueWith(t => DealDamageToPosition(zone, location, damage)); } private static void DealDamageToPosition(IZone zone, Position location, double damage) @@ -150,31 +197,5 @@ private static void DealDamageToPosition(IZone zone, Position location, double d } } } - - protected override void OnAction() - { - _action.DoAction(); - } - - protected virtual bool CheckAccuracy(Unit victim) - { - var rnd = FastRandom.NextDouble(); - var isMiss = rnd * Accuracy.Value > victim.SignatureRadius; - return isMiss; - } - - protected virtual IDamageBuilder GetDamageBuilder() - { - return DamageInfo.Builder.WithAttacker(ParentRobot) - .WithOptimalRange(OptimalRange) - .WithFalloff(Falloff) - .WithDamages(GetCleanDamages()); - } - - private IEnumerable GetCleanDamages() - { - var ammo = (WeaponAmmo)GetAmmo(); - return ammo != null ? ammo.GetCleanDamages() : new Damage[0]; - } } } \ No newline at end of file diff --git a/src/Perpetuum/Perpetuum.csproj b/src/Perpetuum/Perpetuum.csproj index 165a32c9f..8192ad755 100644 --- a/src/Perpetuum/Perpetuum.csproj +++ b/src/Perpetuum/Perpetuum.csproj @@ -259,8 +259,19 @@ + + + + + + + + + + + @@ -275,7 +286,9 @@ + + @@ -288,6 +301,7 @@ + @@ -652,6 +666,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -715,6 +798,8 @@ + + @@ -732,7 +817,7 @@ - + @@ -758,8 +843,8 @@ - - + + @@ -952,6 +1037,8 @@ + + @@ -1031,7 +1118,6 @@ - @@ -1079,7 +1165,7 @@ - + @@ -1263,6 +1349,7 @@ + diff --git a/src/Perpetuum/Players/ErrorPacketBuilder.cs b/src/Perpetuum/Players/ErrorPacketBuilder.cs new file mode 100644 index 000000000..cd276914a --- /dev/null +++ b/src/Perpetuum/Players/ErrorPacketBuilder.cs @@ -0,0 +1,20 @@ +using Perpetuum.Builders; +using Perpetuum.Zones; + +namespace Perpetuum.Players +{ + public class ErrorPacketBuilder : IBuilder + { + private readonly ErrorCodes error; + + public ErrorPacketBuilder(ErrorCodes error) + { + this.error = error; + } + + public Packet Build() + { + return new Packet(ZoneCommand.Error) { Error = error }; + } + } +} diff --git a/src/Perpetuum/Players/Player.cs b/src/Perpetuum/Players/Player.cs index cb6dbf829..a224a1c98 100644 --- a/src/Perpetuum/Players/Player.cs +++ b/src/Perpetuum/Players/Player.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using System.Transactions; -using Perpetuum.Accounting.Characters; +using Perpetuum.Accounting.Characters; using Perpetuum.Builders; using Perpetuum.Collections.Spatial; using Perpetuum.Common.Loggers.Transaction; @@ -25,7 +18,6 @@ using Perpetuum.Services.MissionEngine; using Perpetuum.Services.MissionEngine.MissionTargets; using Perpetuum.Services.MissionEngine.TransportAssignments; -using Perpetuum.Services.Strongholds; using Perpetuum.Timers; using Perpetuum.Units; using Perpetuum.Units.DockingBases; @@ -44,236 +36,140 @@ using Perpetuum.Zones.PBS; using Perpetuum.Zones.PlantTools; using Perpetuum.Zones.ProximityProbes; +using Perpetuum.Zones.RemoteControl; using Perpetuum.Zones.Teleporting; using Perpetuum.Zones.Teleporting.Strategies; using Perpetuum.Zones.Terrains; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Transactions; namespace Perpetuum.Players { - public class PlayerMovement + public sealed class Player : Robot, IBlobableUnit, IBlobEmitter { - private static readonly TimeSpan _minStepTime = TimeSpan.FromMilliseconds(50); - private static readonly TimeSpan _maxElapsedTime = TimeSpan.FromSeconds(1); - private readonly Player _player; + private readonly IExtensionReader extensionReader; + private readonly ICorporationManager corporationManager; + private readonly MissionHandler.Factory missionHandlerFactory; + private readonly ITeleportStrategyFactories teleportStrategyFactories; + private readonly DockingBaseHelper dockingBaseHelper; + private readonly CombatLogger.Factory combatLoggerFactory; + private readonly IBlobEmitter blobEmitter; + private readonly BlobHandler blobHandler; + private readonly PlayerMovement movement; + private readonly IntervalTimer combatTimer = new IntervalTimer(TimeSpan.FromSeconds(10)); + private CombatLogger combatLogger; + private PlayerMoveCheckQueue check; + private CancellableDespawnHelper despawnHelper; - public PlayerMovement(Player player) - { - _player = player; - } - - public void Update(TimeSpan elapsed) - { - var speed = _player.Speed; - if (speed <= 0.0) - return; + public static readonly TimeSpan NormalUndockDelay = TimeSpan.FromSeconds(7); + public const int ARKHE_REQUEST_TIMER_MINUTES_PVP = 3; + public const int ARKHE_REQUEST_TIMER_MINUTES_NPC = 1; - elapsed = elapsed.Min(_maxElapsedTime); + private bool HasAggressorEffect => EffectHandler.ContainsEffect(EffectType.effect_aggressor); - var angle = _player.Direction * MathHelper.PI2; - var vx = Math.Sin(angle) * speed; - var vy = Math.Cos(angle) * speed; + public long CorporationEid { get; set; } - var px = _player.CurrentPosition.X; - var py = _player.CurrentPosition.Y; + public IZoneSession Session { get; private set; } - while (elapsed > TimeSpan.Zero) - { - var time = _minStepTime; + public Character Character { get; set; } = Character.None; - if (elapsed < _minStepTime) - time = elapsed; + public bool HasGMStealth { get; set; } - elapsed -= _minStepTime; + public MissionHandler MissionHandler { get; private set; } - var nx = px + (vx * time.TotalSeconds); - var ny = py - (vy * time.TotalSeconds); + public bool HasSelfTeleportEnablerEffect => EffectHandler.ContainsEffect(EffectType.effect_teleport_self_enabler); - var dx = (int)px - (int)nx; - var dy = (int)py - (int)ny; + public Gang Gang { get; set; } - if (dx != 0 || dy != 0) - { - // csak akkor kell ha csempevaltas volt - if (!_player.IsWalkable((int)nx, (int)ny)) - { - //_player.Zone.CreateAlignedDebugBeam(BeamType.red_10sec, new Position(nx, ny)); - break; - } - } + public bool IsInSafeArea + { + get + { + IZone zone = Zone; - px = nx; - py = ny; - //_player.Zone.CreateAlignedDebugBeam(BeamType.blue_10sec, new Position(px, py)); + return zone != null +&& (zone.Configuration.Protected || + EffectHandler.ContainsEffect(EffectType.effect_syndicate_area) || + EffectHandler.ContainsEffect(EffectType.effect_safe_spot)); } - _player.TryMove(new Position(px, py)); - //_player.Zone.CreateAlignedDebugBeam(BeamType.orange_10sec, new Position(px, py)); } - } - - public class ErrorPacketBuilder : IBuilder - { - private readonly ErrorCodes _error; - public ErrorPacketBuilder(ErrorCodes error) + public override bool IsLockable { - _error = error; - } + get + { + bool isInvulnerable = IsInvulnerable; - public Packet Build() - { - return new Packet(ZoneCommand.Error) {Error = _error}; + return !isInvulnerable && base.IsLockable; + } } - } - public sealed class Player : Robot,IBlobableUnit,IBlobEmitter - { - private readonly IExtensionReader _extensionReader; - private readonly ICorporationManager _corporationManager; - private readonly MissionHandler.Factory _missionHandlerFactory; - private readonly ITeleportStrategyFactories _teleportStrategyFactories; - private readonly DockingBaseHelper _dockingBaseHelper; - private readonly CombatLogger.Factory _combatLoggerFactory; - private readonly IBlobEmitter _blobEmitter; - private readonly BlobHandler _blobHandler; - private readonly PlayerMovement _movement; - private CombatLogger _combatLogger; - private PlayerMoveCheckQueue _check; - private CancellableDespawnHelper _despawnHelper; - - public Player(IExtensionReader extensionReader, + public IBlobHandler BlobHandler => blobHandler; + + public double BlobEmission => blobEmitter.BlobEmission; + + public double BlobEmissionRadius => blobEmitter.BlobEmissionRadius; + + public Player( + IExtensionReader extensionReader, ICorporationManager corporationManager, MissionHandler.Factory missionHandlerFactory, ITeleportStrategyFactories teleportStrategyFactories, DockingBaseHelper dockingBaseHelper, - CombatLogger.Factory combatLoggerFactory - ) - { - _extensionReader = extensionReader; - _corporationManager = corporationManager; - _missionHandlerFactory = missionHandlerFactory; - _teleportStrategyFactories = teleportStrategyFactories; - _dockingBaseHelper = dockingBaseHelper; - _combatLoggerFactory = combatLoggerFactory; + CombatLogger.Factory combatLoggerFactory) + { + this.extensionReader = extensionReader; + this.corporationManager = corporationManager; + this.missionHandlerFactory = missionHandlerFactory; + this.teleportStrategyFactories = teleportStrategyFactories; + this.dockingBaseHelper = dockingBaseHelper; + this.combatLoggerFactory = combatLoggerFactory; Session = ZoneSession.None; - _movement = new PlayerMovement(this); - - _blobEmitter = new BlobEmitter(this); - _blobHandler = new BlobHandler(this); - } - - public long CorporationEid { get; set; } - public IZoneSession Session { get; private set; } - public Character Character { get; set; } = Character.None; - public bool HasGMStealth { get; set; } - - public bool TryMove(Position position) - { - if (!IsWalkable(position)) - return false; - - _check.EnqueueMove(position); - - CurrentPosition = position; - return true; - } - - public void SetSession(IZoneSession session) - { - Session = session; - } + movement = new PlayerMovement(this); - public MissionHandler MissionHandler { get; private set; } - - private bool HasAggressorEffect - { - get { return EffectHandler.ContainsEffect(EffectType.effect_aggressor); } - } - - public bool HasSelfTeleportEnablerEffect - { - get { return EffectHandler.ContainsEffect(EffectType.effect_teleport_self_enabler); } + blobEmitter = new BlobEmitter(this); + blobHandler = new BlobHandler(this); } - public Gang Gang { get; set; } - - public bool IsInSafeArea + public void EnableSelfTeleport(TimeSpan duration, int affectedZoneId = -1) { - get + if (affectedZoneId != -1 && Zone.Id != affectedZoneId) { - var zone = Zone; - if (zone == null) - return false; - - return zone.Configuration.Protected || EffectHandler.ContainsEffect(EffectType.effect_syndicate_area) || EffectHandler.ContainsEffect(EffectType.effect_safe_spot); + return; } + + ApplySelfTeleportEnablerEffect(duration); } - public override bool IsLockable + public bool TryMove(Position position) { - get + if (!IsWalkable(position)) { - var isInvulnerable = IsInvulnerable; - - if (isInvulnerable) - return false; - - return base.IsLockable; + return false; } - } - public IBlobHandler BlobHandler - { - get { return _blobHandler; } - } + check.EnqueueMove(position); + CurrentPosition = position; - public double BlobEmission - { - get { return _blobEmitter.BlobEmission; } + return true; } - public double BlobEmissionRadius + public void SetSession(IZoneSession session) { - get { return _blobEmitter.BlobEmissionRadius; } + Session = session; } - public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); - } - - protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) - { - base.OnEnterZone(zone, enterType); //aa - _check = PlayerMoveCheckQueue.Create(this, CurrentPosition); - - zone.SendPacketToGang(Gang, new GangUpdatePacketBuilder(Visibility.Visible, this)); - - MissionHandler = _missionHandlerFactory(zone, this); - MissionHandler.InitMissions(); - - Direction = FastRandom.NextDouble(); - - var p = DynamicProperties.GetProperty(k.pvpRemaining); - if (!p.HasValue) - return; - - ApplyPvPEffect(TimeSpan.FromMilliseconds(p.Value)); - p.Clear(); - } - - protected override void OnRemovedFromZone(IZone zone) - { - Session.SendPacket(ExitPacketBuilder); - zone.SendPacketToGang(Gang, new GangUpdatePacketBuilder(Visibility.Invisible, this)); - - _check.StopAndDispose(); - - if (!States.LocalTeleport) - Session.Stop(); - - base.OnRemovedFromZone(zone); + } } public override void OnUpdateToDb() @@ -286,26 +182,34 @@ public override void OnUpdateToDb() DynamicProperties.Update(k.currentCore, Core); } - var zone = Zone; + IZone zone = Zone; + if (zone == null || States.Dead) + { return; + } + + Character character = Character; - var character = Character; character.ZoneId = zone.Id; character.ZonePosition = CurrentPosition; - var p = DynamicProperties.GetProperty(k.pvpRemaining); + IDynamicProperty p = DynamicProperties.GetProperty(k.pvpRemaining); + Effect pvpEffect = EffectHandler.GetEffectsByType(EffectType.effect_pvp).FirstOrDefault(); - var pvpEffect = EffectHandler.GetEffectsByType(EffectType.effect_pvp).FirstOrDefault(); if (pvpEffect == null) { p.Clear(); + return; } - var effectTimer = pvpEffect.Timer; + IntervalTimer effectTimer = pvpEffect.Timer; + if (effectTimer != null) + { p.Value = (int)effectTimer.Remaining.TotalMilliseconds; + } } finally { @@ -313,49 +217,36 @@ public override void OnUpdateToDb() } } - protected override void OnUpdate(TimeSpan time) - { - base.OnUpdate(time); - UpdateCombat(time); - _movement.Update(time); - _blobHandler.Update(time); - MissionHandler.Update(time); - - _combatLogger?.Update(time); - _despawnHelper?.Update(time, this); - } - public void SetStrongholdDespawn(TimeSpan time, UnitDespawnStrategy strategy) { - if (_despawnHelper == null) + if (despawnHelper == null) { - _despawnHelper = CancellableDespawnHelper.Create(this, time); - _despawnHelper.DespawnStrategy = strategy; + despawnHelper = CancellableDespawnHelper.Create(this, time); + despawnHelper.DespawnStrategy = strategy; } } public void ClearStrongholdDespawn() { - _despawnHelper?.Cancel(this); - _despawnHelper = null; + despawnHelper?.Cancel(this); + despawnHelper = null; } public void SendModuleProcessError(Module module, ErrorCodes error) { - var packet = new Packet(ZoneCommand.ModuleEvaluateError); + Packet packet = new Packet(ZoneCommand.ModuleEvaluateError); packet.AppendByte((byte)module.ParentComponent.Type); - packet.AppendByte((byte) module.Slot); + packet.AppendByte((byte)module.Slot); packet.AppendInt((int)error); - Session.SendPacket(packet); } public void ApplyInvulnerableEffect() { RemoveInvulnerableEffect(); // Remove existing effect, set new - var builder = NewEffectBuilder().SetType(EffectType.effect_invulnerable); - builder.WithDurationModifier(0.75); //Reduce span of syndicate protection + EffectBuilder builder = NewEffectBuilder().SetType(EffectType.effect_invulnerable); + _ = builder.WithDurationModifier(0.75); //Reduce span of syndicate protection ApplyEffect(builder); } @@ -366,32 +257,34 @@ public void RemoveInvulnerableEffect() public void ApplyTeleportSicknessEffect() { - var zone = Zone; + IZone zone = Zone; + if (zone == null || zone is TrainingZone) + { return; + } - var effectBuilder = NewEffectBuilder().SetType(EffectType.effect_teleport_sickness); + EffectBuilder effectBuilder = NewEffectBuilder().SetType(EffectType.effect_teleport_sickness); if (HasPvpEffect) { - effectBuilder.WithDurationModifier(3.0); + _ = effectBuilder.WithDurationModifier(3.0); } ApplyEffect(effectBuilder); } - private void ApplyAggressorEffect() - { - ApplyEffect(NewEffectBuilder().SetType(EffectType.effect_aggressor)); - } - public void ApplySelfTeleportEnablerEffect(TimeSpan duration) { - var effect = EffectHandler.GetEffectsByType(EffectType.effect_teleport_self_enabler).FirstOrDefault(); + Effect effect = EffectHandler.GetEffectsByType(EffectType.effect_teleport_self_enabler).FirstOrDefault(); + if (effect != null) + { EffectHandler.Remove(effect); + } + + EffectBuilder builder = NewEffectBuilder().SetType(EffectType.effect_teleport_self_enabler).WithDuration(duration); - var builder = NewEffectBuilder().SetType(EffectType.effect_teleport_self_enabler).WithDuration(duration); ApplyEffect(builder); } @@ -402,38 +295,40 @@ public void RemoveSelfTeleportEnablerEffect() public void CheckDockingConditionsAndThrow(long baseEid, bool checkRange = true) { - if ( !Session.AccessLevel.IsAdminOrGm()) + if (!Session.AccessLevel.IsAdminOrGm()) { HasAggressorEffect.ThrowIfTrue(ErrorCodes.NotAllowedForAggressors); HasPvpEffect.ThrowIfTrue(ErrorCodes.CantDockThisState); HasTeleportSicknessEffect.ThrowIfTrue(ErrorCodes.CantDockThisState); } - var zone = Zone; + IZone zone = Zone; + if (zone == null) + { return; + } + + DockingBase dockingBase = dockingBaseHelper.GetDockingBase(baseEid); - var dockingBase = _dockingBaseHelper.GetDockingBase(baseEid); if (dockingBase == null) + { return; + } - if (dockingBase.Zone == zone) + if (dockingBase.Zone == zone && checkRange) { - // csak akkor van range check ha a terepen van - if (checkRange) - { - // alapbol van checkrange - dockingBase.IsInDockingRange(this).ThrowIfFalse(ErrorCodes.DockingOutOfRange); - } + dockingBase.IsInDockingRange(this).ThrowIfFalse(ErrorCodes.DockingOutOfRange); } - var currentAccess = Session.AccessLevel; + AccessLevel currentAccess = Session.AccessLevel; + if (!currentAccess.IsAdminOrGm()) { - dockingBase.IsDockingAllowed(Character).ThrowIfError(); + _ = dockingBase.IsDockingAllowed(Character).ThrowIfError(); } - DockToBase(zone,dockingBase); + DockToBase(zone, dockingBase); } /// @@ -445,426 +340,454 @@ public void DockToBase(IZone zone, DockingBase dockingBase) { States.Dock = true; - var publicContainer = dockingBase.GetPublicContainer(); + PublicContainer publicContainer = dockingBase.GetPublicContainer(); FullArmorRepair(); publicContainer.AddItem(this, false); publicContainer.Save(); - dockingBase.DockIn(Character,NormalUndockDelay,ZoneExitType.Docked); + dockingBase.DockIn(Character, NormalUndockDelay, ZoneExitType.Docked); Transaction.Current.OnCommited(() => { RemoveFromZone(); MissionHelper.MissionAdvanceDockInTarget(Character.Id, zone.Id, CurrentPosition); - TransportAssignment.DeliverTransportAssignmentAsync(Character); + _ = TransportAssignment.DeliverTransportAssignmentAsync(Character); }); } - public static readonly TimeSpan NormalUndockDelay = TimeSpan.FromSeconds(7); + public ErrorCodes CheckPvp() + { + IZone zone = Zone; + Debug.Assert(zone != null); - protected override void OnDead(Unit killer) - { - HandlePlayerDeadAsync(Zone, killer).ContinueWith(t => base.OnDead(killer)); + return !HasPvpEffect && (zone.Configuration.Protected || EffectHandler.ContainsEffect(EffectType.effect_syndicate_area)) + ? ErrorCodes.PvpIsNotAllowed + : ErrorCodes.NoError; } - private Task HandlePlayerDeadAsync(IZone zone, Unit killer) + public bool IsInDefaultCorporation() { - return Task.Run(() => HandlePlayerDead(zone, killer)); + return DefaultCorporationDataCache.IsCorporationDefault(CorporationEid); } - public const int ARKHE_REQUEST_TIMER_MINUTES_PVP = 3; - public const int ARKHE_REQUEST_TIMER_MINUTES_NPC = 1; - - - //ennek mindenkepp vegig kell futnia - private void HandlePlayerDead(IZone zone, Unit killer) + public override ItemPropertyModifier GetPropertyModifier(AggregateField field) { - using (var scope = Db.CreateTransaction()) - { - EnlistTransaction(); - try - { - killer = zone.ToPlayerOrGetOwnerPlayer(killer) ?? killer; + ItemPropertyModifier modifier = base.GetPropertyModifier(field); - SaveCombatLog(zone, killer); + if (Character == Character.None) + { + return modifier; + } - var character = Character; + CharacterExtensionCollection characterExtensions = Character.GetExtensions(); + System.Collections.Immutable.ImmutableDictionary extensions = extensionReader.GetExtensions(); + double extensionBonus = characterExtensions + .Select(e => extensions[e.id]) + .Where(e => e.aggregateField == field) + .Sum(e => characterExtensions.GetLevel(e.id) * e.bonus); - var dockingBase = character.GetHomeBaseOrCurrentBase(); - dockingBase.DockIn(character,NormalUndockDelay, ZoneExitType.Died); + extensionBonus += ExtensionBonuses + .Where(e => e.aggregateField == field) + .Sum(e => characterExtensions.GetLevel(e.extensionId) * e.bonus); - PlayerDeathLogger.Log.Write(zone, this, killer); + if (!extensionBonus.IsZero()) + { + ItemPropertyModifier m = ItemPropertyModifier.Create(field, extensionBonus); - //pay out insurance if needed - var wasInsured = InsuranceHelper.CheckInsuranceOnDeath(Eid, Definition); + m.NormalizeExtensionBonus(); + m.Modify(ref modifier); + } - if (!Session.AccessLevel.IsAdminOrGm()) - { - var robotInventory = GetContainer(); - Debug.Assert(robotInventory != null); + return modifier; + } - var lootItems = new List(); + public override void OnAggression(Unit victim) + { + base.OnAggression(victim); + AddInCombatWith(victim); - // minden fittelt modul - foreach (var module in Modules.Where(m => LootHelper.Roll())) - { - lootItems.Add(LootItemBuilder.Create(module).AsDamaged().Build()); + if (victim is ITaggable taggable) + { + taggable.Tag(this, TimeSpan.Zero); + } - var activeModule = module as ActiveModule; - var ammo = activeModule?.GetAmmo(); - if (ammo != null) - { - if (LootHelper.Roll()) - lootItems.Add(LootItemBuilder.Create(ammo).Build()); - } + if (IsUnitPVPAggro(victim)) + { + ApplyPvPEffect(); - // szedjuk le a robotrol - module.Parent = robotInventory.Eid; //in case the container is full + return; + } - //toroljuk is le, nem kell ez sehova mar - Repository.Delete(module); - } + if (!(victim is Player victimPlayer)) + { + return; + } - foreach (var item in robotInventory.GetItems(true).Where(i => i is VolumeWrapperContainer)) - { - //Transport assignments - var wrapper = item as VolumeWrapperContainer; - if (wrapper == null) - continue; + victimPlayer.Session.CancelLogout(); + ApplyPvPEffect(); - lootItems.AddRange(wrapper.GetLootItems()); - wrapper.SetAllowDelete(); - Repository.Delete(wrapper); - } + if (IsInSameCorporation(victimPlayer)) + { + return; + } - // elkerunk minden itemet a kontenerbol es valogatunk belole 50% szerint - foreach (var item in robotInventory.GetItems().Where(i => LootHelper.Roll() && !i.ED.AttributeFlags.NonStackable)) - { - var qtyMod = FastRandom.NextDouble(); - item.Quantity = (int)(item.Quantity * qtyMod); + if (HasPvpEffect && victimPlayer.HasPvpEffect) + { + return; + } + } - if (item.Quantity > 0) - { - lootItems.Add(LootItemBuilder.Create(item.Definition).SetQuantity(item.Quantity).SetRepackaged(item.ED.AttributeFlags.Repackable).Build()); - } - else - { - robotInventory.RemoveItemOrThrow(item); + public void OnPvpSupport(Unit target) + { + if (target is Player player && player.HasPvpEffect) + { + ApplyPvPEffect(); + } + } - //toroljuk is le, nem kell ez mar - Repository.Delete(item); - } - } + public override string InfoString => $"Player:{Character.Id}:{Definition}:{Eid}"; - //Check if paint was applied + paint drop chance - if (ED.Config.Tint != Tint && LootHelper.Roll(0.5)) - { - //Paint Query - //TODO: performance => cache paints in static collection - //TODO: performance => cache if painted, and paint entitydef on undock - EntityDefault paint = EntityDefault.Reader.GetAll() - .Where(i => i.CategoryFlags == CategoryFlags.cf_paints) - .Where(i => i.Config.Tint == Tint).First(); - if (paint != null) - { - lootItems.Add(LootItemBuilder.Create(paint.Definition).SetQuantity(1).SetDamaged(false).Build()); - } - } + public void SendInitSelf() + { + IZone zone = Zone; - if (lootItems.Count > 0) - { - var lootContainer = LootContainer.Create().AddLoot(lootItems).BuildAndAddToZone(zone, CurrentPosition); + Debug.Assert(zone != null, "zone != null"); + Session.SendPacket(EnterPacketBuilder); + Session.SendTerrainData(); + zone.SendBeamsToPlayer(this, GridDistricts.All); - if (lootContainer != null) - { - var b = TransactionLogEvent.Builder().SetTransactionType(TransactionType.PutLoot).SetCharacter(character).SetContainer(lootContainer.Eid); - foreach (var lootItem in lootItems) - { - b.SetItem(lootItem.ItemInfo.Definition,lootItem.ItemInfo.Quantity); - Character.LogTransaction(b); - } - } - } + IEnumerable lockPackets = GetLockPackets(); - var killedByPlayer = (killer != null && killer.IsPlayer()); + Session.SendPackets(lockPackets); - Trashcan.Get().MoveToTrash(this,Session.DisconnectTime, wasInsured, killedByPlayer,Session.InactiveTime); + foreach (IUnitVisibility visibility in GetVisibleUnits()) + { + Session.SendPacket(visibility.Target.EnterPacketBuilder); - character.NextAvailableRobotRequestTime = DateTime.Now.AddMinutes(killedByPlayer ? ARKHE_REQUEST_TIMER_MINUTES_PVP : ARKHE_REQUEST_TIMER_MINUTES_NPC); + if (!(visibility.Target is Robot robot)) + { + continue; + } - Robot activeRobot = null; + IEnumerable unitLockPackets = robot.GetLockPackets(); - if (!killedByPlayer) - { - activeRobot = dockingBase.CreateStarterRobotForCharacter(character); + Session.SendPackets(unitLockPackets); + } - if (activeRobot != null) - { - Transaction.Current.OnCommited(() => - { - var starterRobotInfo = new Dictionary - { - {k.baseEID, Eid}, - {k.robotEID, activeRobot.Eid} - }; + Session.SendPacket(new GangUpdatePacketBuilder(Visibility.Visible, zone.GetGangMembers(Gang))); + Session.SendPacket(zone.Weather.GetCurrentWeather().CreateUpdatePacket()); - Message.Builder.SetCommand(Commands.StarterRobotCreated).WithData(starterRobotInfo).ToCharacter(character).Send(); - }); - } - } + foreach (Effect effect in EffectHandler.Effects) + { + Session.SendPacket(new EffectPacketBuilder(effect, true)); + } - character.SetActiveRobot(activeRobot); - } - else - { - // mert rendesek vagyunk - this.Repair(); + foreach (ActiveModule module in ActiveModules) + { + module.ForceUpdate(); + } + } - // csak az adminok miatt kell - var container = dockingBase.GetPublicContainer(); - container.AddItem(this, false); - } + public void WriteFQLog(string message) + { + LogEvent e = new LogEvent + { + LogType = LogType.Info, + Tag = "FQ", + Message = $"{InfoString} - {message}", + }; - this.Save(); + Logger.Log(e); + } - scope.Complete(); + public void SendForceUpdate() + { + Session.SendPacket(new UnitUpdatePacketBuilder(this, UpdatePacketControl.ForceReposition)); + } + + public override void OnCombatEvent(Unit source, CombatEventArgs e) + { + base.OnCombatEvent(source, e); + + Player player = Zone.ToPlayerOrGetOwnerPlayer(source); + + if (player == null) + { + return; + } + + CombatLogger logger = LazyInitializer.EnsureInitialized(ref combatLogger, CreateCombatLogger); + + logger.Log(player, e); + } + + public static Player LoadPlayerAndAddToZone(IZone zone, Character character) + { + using (TransactionScope scope = Db.CreateTransaction()) + { + Player player = (Player)character.GetActiveRobot().ThrowIfNull(ErrorCodes.ARobotMustBeSelected); + + DockingBase dockingBase = null; + ZoneEnterType zoneEnterType; + Position spawnPosition; + + if (character.IsDocked) + { + zoneEnterType = ZoneEnterType.Undock; + dockingBase = character.GetCurrentDockingBase(); + spawnPosition = UndockSpawnPositionSelector.SelectSpawnPosition(dockingBase); + character.ZoneId = zone.Id; + character.ZonePosition = spawnPosition; + character.IsDocked = false; } - catch (Exception ex) + else { - Logger.Exception(ex); + zoneEnterType = ZoneEnterType.Teleport; + _ = zone.Id.ThrowIfNotEqual(character.ZoneId ?? -1, ErrorCodes.InvalidZoneId); + + Position? zonePosition = character.ZonePosition.ThrowIfNull(ErrorCodes.InvalidPosition); + + spawnPosition = (Position)zonePosition; } + + spawnPosition = zone.FixZ(spawnPosition); + + ClosestWalkablePositionFinder finder = new ClosestWalkablePositionFinder(zone, spawnPosition, player); + Position validPosition = finder.FindOrThrow(); + + ZoneStorage zoneStorage = zone.Configuration.GetStorage(); + + player.Parent = zoneStorage.Eid; + player.FullCoreRecharge(); + player.Save(); + + Transaction.Current.OnCommited(() => + { + dockingBase?.LeaveChannel(character); + player.CorporationEid = character.CorporationEid; + zone.SetGang(player); + player.AddToZone(zone, validPosition, zoneEnterType); + player.ApplyInvulnerableEffect(); + }); + + scope.Complete(); + + return player; } } - protected override void OnTileChanged() + [CanBeNull] + public Task TeleportToPositionAsync(Position target, bool applyTeleportSickness, bool applyInvulnerable) { - base.OnTileChanged(); + IZone zone = Zone; - var zone = Zone; if (zone == null) - return; + { + return null; + } - MissionHandler?.MissionUpdateOnTileChange(); + TeleportWithinZone teleport = teleportStrategyFactories.TeleportWithinZoneFactory(); - var controlInfo = zone.Terrain.Controls.GetValue(CurrentPosition); + if (teleport == null) + { + return null; + } - ApplyHighwayEffect(controlInfo.IsAnyHighway); + teleport.TargetPosition = target; + teleport.ApplyTeleportSickness = applyTeleportSickness; + teleport.ApplyInvulnerable = applyInvulnerable; - if (zone.Configuration.Protected) - return; + Task task = teleport.DoTeleportAsync(this); - //PVP zone - ApplySyndicateAreaEffect(controlInfo.SyndicateArea); + return task?.LogExceptions(); } - protected override void OnCellChanged(CellCoord lastCellCoord, CellCoord currentCellCoord) + public void SendStartProgressBar(Unit unit, TimeSpan timeout, TimeSpan start) { - base.OnCellChanged(lastCellCoord,currentCellCoord); + Dictionary data = unit.BaseInfoToDictionary(); - var zone = Zone; - if ( zone == null ) - return; + data.Add(k.timeOut, (int)timeout.TotalMilliseconds); + data.Add(k.started, (long)start.TotalMilliseconds); + data.Add(k.now, (long)start.TotalMilliseconds); + Message.Builder + .SetCommand(Commands.AlarmStart) + .WithData(data) + .ToCharacter(Character) + .Send(); + } - Task.Run(() => - { - var district = currentCellCoord.ComputeDistrict(lastCellCoord); - zone.SendBeamsToPlayer(this,district); - Session.SendTerrainData(); - }).LogExceptions(); + public void SendEndProgressBar(Unit unit, bool success = true) + { + Dictionary info = unit.BaseInfoToDictionary(); + + info.Add(k.success, success); + Message.Builder.SetCommand(Commands.AlarmOver).WithData(info).ToCharacter(Character).Send(); } - public ErrorCodes CheckPvp() + public void SendArtifactRadarBeam(Position targetPosition) { - var zone = Zone; - Debug.Assert(zone != null); + BeamBuilder builder = Beam.NewBuilder() + .WithType(BeamType.artifact_radar) + .WithSourcePosition(targetPosition) + .WithTargetPosition(targetPosition) + .WithState(BeamState.AlignToTerrain) + .WithDuration(TimeSpan.FromSeconds(30)); - if (!HasPvpEffect && (zone.Configuration.Protected || EffectHandler.ContainsEffect(EffectType.effect_syndicate_area))) - return ErrorCodes.PvpIsNotAllowed; + Session.SendBeam(builder); + } - return ErrorCodes.NoError; + public bool IsStandingMatch(long targetCorporationEid, double? standingLimit) + { + return corporationManager.IsStandingMatch(targetCorporationEid, CorporationEid, standingLimit); } - private void ApplySyndicateAreaEffect(bool apply) + public void ReloadContainer() { - if ( apply ) + if (Transaction.Current != null) { - var effectBuilder = NewEffectBuilder().SetType(EffectType.effect_syndicate_area); - ApplyEffect(effectBuilder); + Reload(); } else { - EffectHandler.RemoveEffectsByType(EffectType.effect_syndicate_area); + using (TransactionScope scope = Db.CreateTransaction()) + { + Reload(); + scope.Complete(); + } } } - private void ApplyHighwayEffect(bool apply) + public void UpdateCorporationOnZone(long newCorporationEid) { - if (apply) + CorporationEid = newCorporationEid; + + Character[] playersOnZone = Zone.GetCharacters().ToArray(); + + if (playersOnZone.Length <= 0) { - var effectBuilder = NewEffectBuilder().SetType(EffectType.effect_highway) - .WithPropertyModifier(ItemPropertyModifier.Create(AggregateField.effect_speed_highway_modifier, 1.0)); - ApplyEffect(effectBuilder); + return; } - else + + Dictionary result = new Dictionary { - EffectHandler.RemoveEffectsByType(EffectType.effect_highway); - } - } + {k.corporationEID, newCorporationEid}, + {k.characterID, Character.Id}, + }; - private bool IsInSameCorporation(Player player) - { - return (CorporationEid == player.CorporationEid) && !IsInDefaultCorporation(); + Message.Builder.SetCommand(Commands.CharacterUpdate).WithData(result).ToCharacters(playersOnZone).Send(); } - public bool IsInDefaultCorporation() + public override void UpdateVisibilityOf(Unit target) { - return DefaultCorporationDataCache.IsCorporationDefault(CorporationEid); + target.UpdatePlayerVisibility(this); } - public override ItemPropertyModifier GetPropertyModifier(AggregateField field) + public void SetCombatState(bool state) { - var modifier = base.GetPropertyModifier(field); - - if (Character == Character.None) - return modifier; + States.Combat = state; + combatTimer.Reset(); - var characterExtensions = Character.GetExtensions(); - var extensions = _extensionReader.GetExtensions(); + if (state) + { + Session.ResetLogoutTimer(); + } + } - var extensionBonus = characterExtensions.Select(e => extensions[e.id]) - .Where(e => e.aggregateField == field) - .Sum(e => characterExtensions.GetLevel(e.id) * e.bonus); + public void AddInCombatWith(Unit enemy) + { + SetCombatState(true); - extensionBonus += ExtensionBonuses.Where(e => e.aggregateField == field).Sum(e => characterExtensions.GetLevel(e.extensionId) * e.bonus); + Player enemyPlayer = enemy as Player; - if (!extensionBonus.IsZero()) - { - var m = ItemPropertyModifier.Create(field,extensionBonus); - m.NormalizeExtensionBonus(); - m.Modify(ref modifier); - } + enemyPlayer?.SetCombatState(true); + } - return modifier; + public bool IsInSameCorporation(Player player) + { + return (CorporationEid == player.CorporationEid) && !IsInDefaultCorporation(); } - private bool IsUnitPVPAggro(Unit unit) + public bool IsUnitPVPAggro(Unit unit) { - return unit is MobileTeleport - || unit is IPBSObject - || unit is WallHealer - || unit is ProximityProbeBase - || (unit is BlobEmitterUnit b && b.IsPlayerSpawned); + return unit is MobileTeleport || + unit is IPBSObject || + unit is WallHealer || + unit is ProximityDeviceBase || + (unit is BlobEmitterUnit b && b.IsPlayerSpawned) || + (unit is RemoteControlledCreature remoteControlledCreature && + remoteControlledCreature.CommandRobot is Player); } - public override void OnAggression(Unit victim) + protected override void OnDead(Unit killer) { - base.OnAggression(victim); + _ = HandlePlayerDeadAsync(Zone, killer).ContinueWith(t => base.OnDead(killer)); + } - AddInCombatWith(victim); + protected override void OnTileChanged() + { + base.OnTileChanged(); - if (victim is ITaggable taggable) - taggable.Tag(this, TimeSpan.Zero); + IZone zone = Zone; - if (IsUnitPVPAggro(victim)) + if (zone == null) { - ApplyPvPEffect(); return; } - if (!(victim is Player victimPlayer)) - return; - - victimPlayer.Session.CancelLogout(); + MissionHandler?.MissionUpdateOnTileChange(); - ApplyPvPEffect(); + TerrainControlInfo controlInfo = zone.Terrain.Controls.GetValue(CurrentPosition); - if (IsInSameCorporation(victimPlayer)) - return; - - if (HasPvpEffect && victimPlayer.HasPvpEffect) - return; - } + ApplyHighwayEffect(controlInfo.IsAnyHighway); - public void OnPvpSupport(Unit target) - { - if (target is Player player && player.HasPvpEffect) + if (zone.Configuration.Protected) { - ApplyPvPEffect(); + return; } - } - public override string InfoString - { - get { return $"Player:{Character.Id}:{Definition}:{Eid}"; } + ApplySyndicateAreaEffect(controlInfo.SyndicateArea); } - public void SendInitSelf() + protected override void OnCellChanged(CellCoord lastCellCoord, CellCoord currentCellCoord) { - var zone = Zone; - Debug.Assert(zone != null, "zone != null"); + base.OnCellChanged(lastCellCoord, currentCellCoord); - Session.SendPacket(EnterPacketBuilder); + IZone zone = Zone; - // terrain - Session.SendTerrainData(); - - // beams - zone.SendBeamsToPlayer(this,GridDistricts.All); - - // elkuldjuk az osszes lockot - var lockPackets = GetLockPackets(); - Session.SendPackets(lockPackets); - - foreach (var visibility in GetVisibleUnits()) - { - Session.SendPacket(visibility.Target.EnterPacketBuilder); - - var robot = visibility.Target as Robot; - if (robot == null) - continue; - - var unitLockPackets = robot.GetLockPackets(); - Session.SendPackets(unitLockPackets); - } - - Session.SendPacket(new GangUpdatePacketBuilder(Visibility.Visible, zone.GetGangMembers(Gang))); - Session.SendPacket(zone.Weather.GetCurrentWeather().CreateUpdatePacket()); - - foreach (var effect in EffectHandler.Effects) + if (zone == null) { - Session.SendPacket(new EffectPacketBuilder(effect, true)); + return; } - foreach (var module in ActiveModules) + _ = Task.Run(() => { - module.ForceUpdate(); - } + GridDistricts district = currentCellCoord.ComputeDistrict(lastCellCoord); + zone.SendBeamsToPlayer(this, district); + Session.SendTerrainData(); + }).LogExceptions(); } - public void WriteFQLog(string message) + protected override void UpdateUnitVisibility(Unit target) { - var e = new LogEvent - { - LogType = LogType.Info, - Tag = "FQ", - Message = $"{InfoString} - {message}" - }; - - Logger.Log(e); + UpdateVisibility(target); } - private void SendError(ErrorCodes error) + protected internal override void UpdatePlayerVisibility(Player player) { - Session.SendPacket(new ErrorPacketBuilder(error)); + UpdateVisibility(player); } - public void SendForceUpdate() + protected override bool IsDetected(Unit target) { - Session.SendPacket(new UnitUpdatePacketBuilder(this, UpdatePacketControl.ForceReposition)); + return Gang.IsMember(target) || base.IsDetected(target); } + protected override bool IsHostileFor(Unit unit) + { + return unit.IsHostile(this); + } protected override void OnBroadcastPacket(IBuilder packetBuilder) { @@ -872,54 +795,35 @@ protected override void OnBroadcastPacket(IBuilder packetBuilder) Session.SendPacket(packetBuilder.Build()); } - protected override void OnUnitVisibilityUpdated(Unit target,Visibility visibility) + protected override void OnUnitVisibilityUpdated(Unit target, Visibility visibility) { switch (visibility) { case Visibility.Visible: - { - target.BroadcastPacket += OnUnitBroadcastPacket; - target.Updated += OnUnitUpdated; - Session.SendPacket(target.EnterPacketBuilder); - break; - } + { + target.BroadcastPacket += OnUnitBroadcastPacket; + target.Updated += OnUnitUpdated; + Session.SendPacket(target.EnterPacketBuilder); + + break; + } case Visibility.Invisible: - { - target.BroadcastPacket -= OnUnitBroadcastPacket; - target.Updated -= OnUnitUpdated; - Session.SendPacket(target.ExitPacketBuilder); - break; - } + { + target.BroadcastPacket -= OnUnitBroadcastPacket; + target.Updated -= OnUnitUpdated; + Session.SendPacket(target.ExitPacketBuilder); + + break; + } } if (Gang.IsMember(target)) { - Session.SendPacket(new GangUpdatePacketBuilder(visibility,(Player) target)); + Session.SendPacket(new GangUpdatePacketBuilder(visibility, (Player)target)); } - base.OnUnitVisibilityUpdated(target,visibility); - } - - private void OnUnitUpdated(Unit unit, UnitUpdatedEventArgs e) - { - if (!Gang.IsMember(unit)) - return; - - var send = (e.UpdateTypes & UnitUpdateTypes.Visibility) > 0 || (e.UpdatedProperties != null && e.UpdatedProperties.Any(p => p.Field.IsPublic())); - if (!send) - return; - - var v = Visibility.Invisible; - if (unit.InZone) - v = Visibility.Visible; - - Session.SendPacket(new GangUpdatePacketBuilder(v,(Player) unit)); - } - - private void OnUnitBroadcastPacket(Unit sender, Packet packet) - { - Session.SendPacket(packet); + base.OnUnitVisibilityUpdated(target, visibility); } protected override void OnLockStateChanged(Lock @lock) @@ -928,18 +832,13 @@ protected override void OnLockStateChanged(Lock @lock) if (@lock is UnitLock u) { - var player = u.Target as Player; + Player player = u.Target as Player; + player?.Session.CancelLogout(); if (@lock.State == LockState.Locked) { - // !! - // this will enqueue primary, secondary, and will also fire if a primary is converted to secondary - // !! - - var npc = u.Target as Npc; - - if (npc != null) + if (u.Target is Npc npc) { MissionHandler.EnqueueMissionEventInfo(new LockUnitEventInfo(this, npc, npc.CurrentPosition)); MissionHandler.SignalParticipationByLocking(npc.GetMissionGuid()); @@ -949,28 +848,32 @@ protected override void OnLockStateChanged(Lock @lock) if (@lock.State == LockState.Inprogress && EffectHandler.ContainsEffect(EffectType.effect_invulnerable)) { - EffectHandler.RemoveEffectsByType(EffectType.effect_invulnerable); + EffectHandler.RemoveEffectsByType(EffectType.effect_invulnerable); } } protected override void OnEffectChanged(Effect effect, bool apply) { - base.OnEffectChanged(effect,apply); + base.OnEffectChanged(effect, apply); - if (!apply) + if (!apply) + { return; + } switch (effect.Type) { case EffectType.effect_demobilizer: { OnCombatEvent(effect.Source, new DemobilizerEventArgs()); + break; } case EffectType.effect_sensor_supress: { - OnCombatEvent(effect.Source,new SensorDampenerEventArgs()); + OnCombatEvent(effect.Source, new SensorDampenerEventArgs()); + break; } } @@ -982,260 +885,327 @@ protected override void OnLockError(Lock @lock, ErrorCodes error) base.OnLockError(@lock, error); } - public override void OnCombatEvent(Unit source, CombatEventArgs e) + protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) { - base.OnCombatEvent(source, e); + base.OnEnterZone(zone, enterType); + check = PlayerMoveCheckQueue.Create(this, CurrentPosition); + zone.SendPacketToGang(Gang, new GangUpdatePacketBuilder(Visibility.Visible, this)); + MissionHandler = missionHandlerFactory(zone, this); + MissionHandler.InitMissions(); + Direction = FastRandom.NextDouble(); - var player = Zone.ToPlayerOrGetOwnerPlayer(source); - if (player == null) + IDynamicProperty p = DynamicProperties.GetProperty(k.pvpRemaining); + + if (!p.HasValue) + { return; + } - var logger = LazyInitializer.EnsureInitialized(ref _combatLogger, CreateCombatLogger); - logger.Log(player,e); + ApplyPvPEffect(TimeSpan.FromMilliseconds(p.Value)); + p.Clear(); } - private CombatLogger CreateCombatLogger() + protected override void OnRemovedFromZone(IZone zone) { - var logger = _combatLoggerFactory(this); - logger.Expired = () => + Session.SendPacket(ExitPacketBuilder); + zone.SendPacketToGang(Gang, new GangUpdatePacketBuilder(Visibility.Invisible, this)); + check.StopAndDispose(); + + if (!States.LocalTeleport) { - _combatLogger = null; - }; - return logger; + Session.Stop(); + } + + base.OnRemovedFromZone(zone); } - private void SaveCombatLog(IZone zone, Unit killer) + protected override void OnUpdate(TimeSpan time) { - _combatLogger?.Save(zone,killer); + base.OnUpdate(time); + UpdateCombat(time); + movement.Update(time); + blobHandler.Update(time); + MissionHandler.Update(time); + combatLogger?.Update(time); + despawnHelper?.Update(time, this); } - public static Player LoadPlayerAndAddToZone(IZone zone,Character character) + private void OnUnitUpdated(Unit unit, UnitUpdatedEventArgs e) { - using (var scope = Db.CreateTransaction()) + if (!Gang.IsMember(unit)) { - var player = (Player)character.GetActiveRobot().ThrowIfNull(ErrorCodes.ARobotMustBeSelected); - - DockingBase dockingBase = null; - - ZoneEnterType zoneEnterType; - Position spawnPosition; - if (character.IsDocked) - { - // ha bazisrol jott - zoneEnterType = ZoneEnterType.Undock; + return; + } - dockingBase = character.GetCurrentDockingBase(); - spawnPosition = UndockSpawnPositionSelector.SelectSpawnPosition(dockingBase); + bool send = (e.UpdateTypes & UnitUpdateTypes.Visibility) > 0 || (e.UpdatedProperties != null && e.UpdatedProperties.Any(p => p.Field.IsPublic())); - character.ZoneId = zone.Id; - character.ZonePosition = spawnPosition; - character.IsDocked = false; - } - else - { - // ha teleportalt - zoneEnterType = ZoneEnterType.Teleport; + if (!send) + { + return; + } - zone.Id.ThrowIfNotEqual(character.ZoneId ?? -1, ErrorCodes.InvalidZoneId); + Visibility v = Visibility.Invisible; - var zonePosition = character.ZonePosition.ThrowIfNull(ErrorCodes.InvalidPosition); - spawnPosition = (Position)zonePosition; - } + if (unit.InZone) + { + v = Visibility.Visible; + } - spawnPosition = zone.FixZ(spawnPosition); + Session.SendPacket(new GangUpdatePacketBuilder(v, (Player)unit)); + } - // keresunk neki valami jo poziciot - var finder = new ClosestWalkablePositionFinder(zone, spawnPosition, player); - var validPosition = finder.FindOrThrow(); + private void OnUnitBroadcastPacket(Unit sender, Packet packet) + { + Session.SendPacket(packet); + } - // parentoljuk a zonahoz <<< NAGYON FONTOS - TILOS MASHOGY kulonben bennmaradnak a (pbs) bazison a robotok, es pl letorlodnek amikor kilovik a bazist - var zoneStorage = zone.Configuration.GetStorage(); - player.Parent = zoneStorage.Eid; - player.FullCoreRecharge(); + private void UpdateCombat(TimeSpan time) + { + if (!States.Combat) + { + return; + } - // elmentjuk - player.Save(); + _ = combatTimer.Update(time); - // csak akkor rakjuk ki ha volt rendes commit - Transaction.Current.OnCommited(() => - { - dockingBase?.LeaveChannel(character); + if (!combatTimer.Passed) + { + return; + } - player.CorporationEid = character.CorporationEid; - zone.SetGang(player); + SetCombatState(false); + } - player.AddToZone(zone,validPosition,zoneEnterType); - player.ApplyInvulnerableEffect(); - }); + private void Reload() + { + RobotInventory container = GetContainer(); - scope.Complete(); - return player; - } + Debug.Assert(container != null, "container != null"); + container.EnlistTransaction(); + container.ReloadItems(Character); + container.SendUpdateToOwner(); } - [CanBeNull] - public Task TeleportToPositionAsync(Position target, bool applyTeleportSickness, bool applyInvulnerable) + private CombatLogger CreateCombatLogger() { - var zone = Zone; - if (zone == null) - return null; + CombatLogger logger = combatLoggerFactory(this); - var teleport = _teleportStrategyFactories.TeleportWithinZoneFactory(); - if (teleport == null) - return null; + logger.Expired = () => + { + combatLogger = null; + }; - teleport.TargetPosition = target; - teleport.ApplyTeleportSickness = applyTeleportSickness; - teleport.ApplyInvulnerable = applyInvulnerable; - var task = teleport.DoTeleportAsync(this); - return task?.LogExceptions(); + return logger; } - public override void UpdateVisibilityOf(Unit target) + private void SaveCombatLog(IZone zone, Unit killer) { - target.UpdatePlayerVisibility(this); + combatLogger?.Save(zone, killer); } - protected override void UpdateUnitVisibility(Unit target) + private void ApplySyndicateAreaEffect(bool apply) { - UpdateVisibility(target); + if (apply) + { + EffectBuilder effectBuilder = NewEffectBuilder().SetType(EffectType.effect_syndicate_area); + ApplyEffect(effectBuilder); + } + else + { + EffectHandler.RemoveEffectsByType(EffectType.effect_syndicate_area); + } } - protected internal override void UpdatePlayerVisibility(Player player) + private void ApplyHighwayEffect(bool apply) { - UpdateVisibility(player); + if (apply) + { + EffectBuilder effectBuilder = NewEffectBuilder() + .SetType(EffectType.effect_highway) + .WithPropertyModifier(ItemPropertyModifier.Create(AggregateField.effect_speed_highway_modifier, 1.0)); + + ApplyEffect(effectBuilder); + } + else + { + EffectHandler.RemoveEffectsByType(EffectType.effect_highway); + } } - protected override bool IsDetected(Unit target) + private void SendError(ErrorCodes error) { - if ( Gang.IsMember(target) ) - return true; - - return base.IsDetected(target); + Session.SendPacket(new ErrorPacketBuilder(error)); } - protected override bool IsHostileFor(Unit unit) + private Task HandlePlayerDeadAsync(IZone zone, Unit killer) { - return unit.IsHostile(this); + return Task.Run(() => HandlePlayerDead(zone, killer)); } - private void UpdateCombat(TimeSpan time) + private void HandlePlayerDead(IZone zone, Unit killer) { - if (!States.Combat) - return; + using (TransactionScope scope = Db.CreateTransaction()) + { + EnlistTransaction(); - _combatTimer.Update(time); + try + { + killer = zone.ToPlayerOrGetOwnerPlayer(killer) ?? killer; - if ( !_combatTimer.Passed) - return; + SaveCombatLog(zone, killer); - SetCombatState(false); - } + Character character = Character; + DockingBase dockingBase = character.GetHomeBaseOrCurrentBase(); - private void SetCombatState(bool state) - { - States.Combat = state; - _combatTimer.Reset(); + dockingBase.DockIn(character, NormalUndockDelay, ZoneExitType.Died); - if ( state ) - Session.ResetLogoutTimer(); - } + PlayerDeathLogger.Log.Write(zone, this, killer); - private readonly IntervalTimer _combatTimer = new IntervalTimer(TimeSpan.FromSeconds(10)); + bool wasInsured = InsuranceHelper.CheckInsuranceOnDeath(Eid, Definition); - private void AddInCombatWith(Unit enemy) - { - SetCombatState(true); + if (!Session.AccessLevel.IsAdminOrGm()) + { + RobotInventory robotInventory = GetContainer(); - var enemyPlayer = enemy as Player; - enemyPlayer?.SetCombatState(true); - } + Debug.Assert(robotInventory != null); - public void SendStartProgressBar(Unit unit, TimeSpan timeout, TimeSpan start) - { - var data = unit.BaseInfoToDictionary(); + List lootItems = new List(); - data.Add(k.timeOut, (int)timeout.TotalMilliseconds); - data.Add(k.started, (long)start.TotalMilliseconds); - data.Add(k.now, (long)start.TotalMilliseconds); + foreach (Module module in Modules.Where(m => LootHelper.Roll())) + { + lootItems.Add(LootItemBuilder.Create(module).AsDamaged().Build()); + ActiveModule activeModule = module as ActiveModule; + Items.Ammos.Ammo ammo = activeModule?.GetAmmo(); - Message.Builder.SetCommand(Commands.AlarmStart).WithData(data).ToCharacter(Character).Send(); - } + if (ammo != null && LootHelper.Roll()) + { + lootItems.Add(LootItemBuilder.Create(ammo).Build()); + } - public void SendEndProgressBar( Unit unit, bool success = true) - { - var info = unit.BaseInfoToDictionary(); - info.Add(k.success, success); - Message.Builder.SetCommand(Commands.AlarmOver).WithData(info).ToCharacter(Character).Send(); - } + module.Parent = robotInventory.Eid; - public void SendArtifactRadarBeam(Position targetPosition) - { - var builder = Beam.NewBuilder() - .WithType(BeamType.artifact_radar) - .WithSourcePosition(targetPosition) - .WithTargetPosition(targetPosition) - .WithState(BeamState.AlignToTerrain) - .WithDuration(TimeSpan.FromSeconds(30)); + Repository.Delete(module); + } - Session.SendBeam(builder); - } + foreach (Item item in robotInventory.GetItems(true).Where(i => i is VolumeWrapperContainer)) + { + if (!(item is VolumeWrapperContainer wrapper)) + { + continue; + } - public bool IsStandingMatch(long targetCorporationEid, double? standingLimit) - { - return _corporationManager.IsStandingMatch(targetCorporationEid, CorporationEid, standingLimit); - } + lootItems.AddRange(wrapper.GetLootItems()); + wrapper.SetAllowDelete(); + Repository.Delete(wrapper); + } - public void ReloadContainer() - { - void Reload() - { - var container = GetContainer(); - Debug.Assert(container != null,"container != null"); + foreach (Item item in robotInventory + .GetItems() + .Where(i => LootHelper.Roll() && !i.ED.AttributeFlags.NonStackable)) + { + double qtyMod = FastRandom.NextDouble(); - container.EnlistTransaction(); - container.ReloadItems(Character); - container.SendUpdateToOwner(); - } + item.Quantity = (int)(item.Quantity * qtyMod); - if (Transaction.Current != null) - Reload(); - else - { - using (var scope = Db.CreateTransaction()) - { - Reload(); - scope.Complete(); - } - } - } + if (item.Quantity > 0) + { + lootItems.Add( + LootItemBuilder + .Create(item.Definition) + .SetQuantity(item.Quantity) + .SetRepackaged(item.ED.AttributeFlags.Repackable) + .Build()); + } + else + { + robotInventory.RemoveItemOrThrow(item); + Repository.Delete(item); + } + } - public void UpdateCorporationOnZone(long newCorporationEid) - { - CorporationEid = newCorporationEid; + if (ED.Config.Tint != Tint && LootHelper.Roll(0.5)) + { + EntityDefault paint = EntityDefault.Reader.GetAll() + .Where(i => i.CategoryFlags == CategoryFlags.cf_paints) + .Where(i => i.Config.Tint == Tint).First(); - var playersOnZone = Zone.GetCharacters().ToArray(); - if (playersOnZone.Length <= 0) - return; + if (paint != null) + { + lootItems.Add(LootItemBuilder.Create(paint.Definition).SetQuantity(1).SetDamaged(false).Build()); + } + } - var result = new Dictionary - { - {k.corporationEID, newCorporationEid}, - {k.characterID, Character.Id}, - }; + if (lootItems.Count > 0) + { + LootContainer lootContainer = LootContainer.Create() + .AddLoot(lootItems) + .BuildAndAddToZone(zone, CurrentPosition); - Message.Builder.SetCommand(Commands.CharacterUpdate).WithData(result).ToCharacters(playersOnZone).Send(); - } + if (lootContainer != null) + { + TransactionLogEventBuilder b = TransactionLogEvent.Builder() + .SetTransactionType(TransactionType.PutLoot) + .SetCharacter(character) + .SetContainer(lootContainer.Eid); - public void EnableSelfTeleport(TimeSpan duration, int affectedZoneId = -1) - { - if (affectedZoneId != -1 && Zone.Id != affectedZoneId) - return; + foreach (LootItem lootItem in lootItems) + { + _ = b.SetItem(lootItem.ItemInfo.Definition, lootItem.ItemInfo.Quantity); + Character.LogTransaction(b); + } + } + } - ApplySelfTeleportEnablerEffect(duration); - } + bool killedByPlayer = killer != null && killer.IsPlayer(); + + Trashcan.Get() + .MoveToTrash(this, Session.DisconnectTime, wasInsured, killedByPlayer, Session.InactiveTime); + + character.NextAvailableRobotRequestTime = + DateTime.Now.AddMinutes(killedByPlayer ? ARKHE_REQUEST_TIMER_MINUTES_PVP : ARKHE_REQUEST_TIMER_MINUTES_NPC); + + Robot activeRobot = null; + + if (!killedByPlayer) + { + activeRobot = dockingBase.CreateStarterRobotForCharacter(character); + + if (activeRobot != null) + { + Transaction.Current.OnCommited(() => + { + Dictionary starterRobotInfo = new Dictionary + { + {k.baseEID, Eid}, + {k.robotEID, activeRobot.Eid} + }; + + Message.Builder.SetCommand(Commands.StarterRobotCreated).WithData(starterRobotInfo).ToCharacter(character).Send(); + }); + } + } + + character.SetActiveRobot(activeRobot); + } + else + { + this.Repair(); + PublicContainer container = dockingBase.GetPublicContainer(); + container.AddItem(this, false); + } + + Save(); + + scope.Complete(); + } + catch (Exception ex) + { + Logger.Exception(ex); + } + } + } } } diff --git a/src/Perpetuum/Players/PlayerMovement.cs b/src/Perpetuum/Players/PlayerMovement.cs new file mode 100644 index 000000000..75e5d8bbd --- /dev/null +++ b/src/Perpetuum/Players/PlayerMovement.cs @@ -0,0 +1,63 @@ +using System; + +namespace Perpetuum.Players +{ + public class PlayerMovement + { + private static readonly TimeSpan minStepTime = TimeSpan.FromMilliseconds(50); + private static readonly TimeSpan maxElapsedTime = TimeSpan.FromSeconds(1); + private readonly Player player; + + public PlayerMovement(Player player) + { + this.player = player; + } + + public void Update(TimeSpan elapsed) + { + var speed = player.Speed; + + if (speed <= 0.0) + { + return; + } + + elapsed = elapsed.Min(maxElapsedTime); + + var angle = player.Direction * MathHelper.PI2; + var vx = Math.Sin(angle) * speed; + var vy = Math.Cos(angle) * speed; + var px = player.CurrentPosition.X; + var py = player.CurrentPosition.Y; + + while (elapsed > TimeSpan.Zero) + { + var time = minStepTime; + + if (elapsed < minStepTime) + { + time = elapsed; + } + + elapsed -= minStepTime; + + var nx = px + (vx * time.TotalSeconds); + var ny = py - (vy * time.TotalSeconds); + + var dx = (int)px - (int)nx; + var dy = (int)py - (int)ny; + + if ((dx != 0 || dy != 0) && + !player.IsWalkable((int)nx, (int)ny)) + { + break; + } + + px = nx; + py = ny; + } + + player.TryMove(new Position(px, py)); + } + } +} diff --git a/src/Perpetuum/Robots/Robot.Locking.cs b/src/Perpetuum/Robots/Robot.Locking.cs index 153a39496..662bf7632 100644 --- a/src/Perpetuum/Robots/Robot.Locking.cs +++ b/src/Perpetuum/Robots/Robot.Locking.cs @@ -35,16 +35,32 @@ public UnitLock GetLockByUnit(Unit unit) return _lockHandler.GetLockByUnit(unit); } + [CanBeNull] + public TerrainLock GetLockByPosition(Position position) + { + return _lockHandler.GetLockByPosition(position); + } + public Lock GetPrimaryLock() { return _lockHandler.GetPrimaryLock(); } + public IEnumerable GetSecondaryLocks() + { + return _lockHandler.GetSecondaryLocks(); + } + public bool IsInLockingRange(Unit unit) { return _lockHandler.IsInLockingRange(unit); } + public bool IsInLockingRange(Position position) + { + return _lockHandler.IsInLockingRange(position); + } + public void ResetLocks() { _lockHandler.ResetLocks(); @@ -70,6 +86,11 @@ public void AddLock(Unit target, bool isPrimary) _lockHandler.AddLock(target, isPrimary); } + public void AddLock(Position target, bool isPrimary) + { + _lockHandler.AddLock(target, isPrimary); + } + public void AddLock(Lock newLock) { _lockHandler.AddLock(newLock); diff --git a/src/Perpetuum/Robots/Robot.Properties.cs b/src/Perpetuum/Robots/Robot.Properties.cs index 34f674e9a..c6eb91f31 100644 --- a/src/Perpetuum/Robots/Robot.Properties.cs +++ b/src/Perpetuum/Robots/Robot.Properties.cs @@ -11,87 +11,100 @@ namespace Perpetuum.Robots { partial class Robot { - private UnitOptionalProperty _decay; - private UnitOptionalProperty _tint; - - private ItemProperty _powerGridMax; - private ItemProperty _powerGrid; - private ItemProperty _cpuMax; - private ItemProperty _cpu; - private ItemProperty _ammoReloadTime; - private ItemProperty _missileHitChance; - private ItemProperty _decayChance; + private UnitOptionalProperty decay; + private UnitOptionalProperty tint; + + private ItemProperty powerGridMax; + private ItemProperty powerGrid; + private ItemProperty cpuMax; + private ItemProperty cpu; + private ItemProperty ammoReloadTime; + private ItemProperty missileHitChance; + private ItemProperty decayChance; + private ItemProperty mineDetectionRange; private void InitProperties() { - _decay = new UnitOptionalProperty(this, UnitDataType.Decay, k.decay, () => 255); - OptionalProperties.Add(_decay); + decay = new UnitOptionalProperty(this, UnitDataType.Decay, k.decay, () => 255); + OptionalProperties.Add(decay); + + tint = new UnitOptionalProperty(this,UnitDataType.Tint,k.tint,() => ED.Config.Tint); + OptionalProperties.Add(tint); - _tint = new UnitOptionalProperty(this,UnitDataType.Tint,k.tint,() => ED.Config.Tint); - OptionalProperties.Add(_tint); + powerGridMax = new UnitProperty(this, AggregateField.powergrid_max, AggregateField.powergrid_max_modifier); + AddProperty(powerGridMax); - _powerGridMax = new UnitProperty(this, AggregateField.powergrid_max, AggregateField.powergrid_max_modifier); - AddProperty(_powerGridMax); + powerGrid = new PowerGridProperty(this); + AddProperty(powerGrid); - _powerGrid = new PowerGridProperty(this); - AddProperty(_powerGrid); + cpuMax = new UnitProperty(this, AggregateField.cpu_max, AggregateField.cpu_max_modifier); + AddProperty(cpuMax); - _cpuMax = new UnitProperty(this, AggregateField.cpu_max, AggregateField.cpu_max_modifier); - AddProperty(_cpuMax); + cpu = new CpuProperty(this); + AddProperty(cpu); - _cpu = new CpuProperty(this); - AddProperty(_cpu); + ammoReloadTime = new UnitProperty(this, AggregateField.ammo_reload_time, AggregateField.ammo_reload_time_modifier); + AddProperty(ammoReloadTime); - _ammoReloadTime = new UnitProperty(this, AggregateField.ammo_reload_time, AggregateField.ammo_reload_time_modifier); - AddProperty(_ammoReloadTime); + missileHitChance = new UnitProperty(this, AggregateField.missile_miss, AggregateField.missile_miss_modifier); + AddProperty(missileHitChance); - _missileHitChance = new UnitProperty(this, AggregateField.missile_miss, AggregateField.missile_miss_modifier); - AddProperty(_missileHitChance); + decayChance = new DecayChanceProperty(this); + AddProperty(decayChance); - _decayChance = new DecayChanceProperty(this); - AddProperty(_decayChance); + mineDetectionRange = new UnitProperty( + this, + AggregateField.mine_detection_range, + AggregateField.undefined, + AggregateField.effect_mine_detection_range_modifier); + AddProperty(mineDetectionRange); } private double PowerGridMax { - get { return _powerGridMax.Value; } + get { return powerGridMax.Value; } } public double PowerGrid { - get { return _powerGrid.Value; } + get { return powerGrid.Value; } } private double CpuMax { - get { return _cpuMax.Value; } + get { return cpuMax.Value; } } public double Cpu { - get { return _cpu.Value; } + get { return cpu.Value; } } public TimeSpan AmmoReloadTime { - get { return TimeSpan.FromMilliseconds(_ammoReloadTime.Value); } + get { return TimeSpan.FromMilliseconds(ammoReloadTime.Value); } } public double MissileHitChance { - get { return _missileHitChance.Value; } + get { return missileHitChance.Value; } } public int Decay { - private get { return _decay.Value; } - set { _decay.Value = value & 255; } + private get { return decay.Value; } + set { decay.Value = value & 255; } } public Color Tint { - get { return _tint.Value; } - set { _tint.Value = value; } + get { return tint.Value; } + set { tint.Value = value; } + } + + public double MineDetectionRange + { + get { return mineDetectionRange.Value; } } public override void UpdateRelatedProperties(AggregateField field) diff --git a/src/Perpetuum/Robots/Robot.cs b/src/Perpetuum/Robots/Robot.cs index 0d9d9776d..7d836390d 100644 --- a/src/Perpetuum/Robots/Robot.cs +++ b/src/Perpetuum/Robots/Robot.cs @@ -1,14 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; using Perpetuum.Accounting.Characters; using Perpetuum.Builders; -using Perpetuum.Common; using Perpetuum.Containers; using Perpetuum.Containers.SystemContainers; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; - using Perpetuum.Items; using Perpetuum.Items.Templates; using Perpetuum.Modules; @@ -19,86 +14,107 @@ using Perpetuum.Zones.DamageProcessors; using Perpetuum.Zones.Locking; using Perpetuum.Zones.Locking.Locks; +using System; +using System.Collections.Generic; +using System.Linq; namespace Perpetuum.Robots { - - public class RobotInfoPacketBuilder : IBuilder + public abstract partial class Robot : Unit { - private readonly Robot _robot; - private readonly ZoneCommand _command; + private Lazy> _modules; + private Lazy> _activeModules; + private Lazy> _components; + private Lazy> _robotComponents; - public RobotInfoPacketBuilder(Robot robot,ZoneCommand command = ZoneCommand.RobotInfo) - { - _robot = robot; - _command = command; - } + public RobotHelper RobotHelper { protected get; set; } + public InsuranceHelper InsuranceHelper { protected get; set; } - public Packet Build() + public RobotTemplate Template { get; set; } + + public bool IsSelected => RobotHelper.IsSelected(this); + + public override double Health => IsRepackaged + ? base.Health + : ArmorMax > 0.0 && Armor > 0.0 + ? Armor.Ratio(ArmorMax) * 100 + : base.Health; + + public override double Mass => RobotComponents.Sum(c => c.Mass); + + public bool HasModule => Modules.Any(); + + public bool IsItemsInContainer { - var infoPacket = new Packet(_command); - infoPacket.AppendLong(_robot.Eid); - AppendRobotProperties(infoPacket); - return infoPacket; + get + { + if (IsRepackaged) + { + return false; + } + + RobotInventory robotInventory = GetContainer(); + + return robotInventory != null && robotInventory.HasChildren; + } } - private void AppendRobotProperties(Packet infoPacket) - { - var properties = _robot.Properties.Where(p => p.HasValue).ToArray(); + public override bool IsStackable => base.IsStackable && IsRepackaged; + + public IEnumerable ExtensionBonusEnablerExtensions => ExtensionBonuses.Select(cb => new Extension(cb.extensionId, 1)); + + protected IEnumerable ExtensionBonuses => RobotComponents.SelectMany(component => component.ExtensionBonuses); - infoPacket.AppendInt(properties.Length); + public IEnumerable Modules => _modules.Value; - foreach (var property in properties) + public IEnumerable ActiveModules => _activeModules.Value; + + public IEnumerable Components => _components.Value; + + public IEnumerable RobotComponents => _robotComponents.Value; + + public override double Volume + { + get { - infoPacket.AppendProperty(property); + if (IsRepackaged) + { + return base.Volume; + } + + double volume = RobotComponents.Sum(c => c.Volume); + + volume *= Quantity; + + return volume; } } - } - public abstract partial class Robot : Unit - { + public bool IsTrashed => Trashcan.IsItemTrashed(this); + protected Robot() { InitLockHander(); InitProperties(); } - public RobotHelper RobotHelper { protected get; set; } - public InsuranceHelper InsuranceHelper { protected get; set; } - - public RobotTemplate Template { get; set; } - public override void Initialize() { InitComponents(); base.Initialize(); } - private Lazy> _modules; - private Lazy> _activeModules; - private Lazy> _components; - private Lazy> _robotComponents; - private void InitComponents() - { - _components = new Lazy>(() => Children.OfType().ToArray()); - _robotComponents = new Lazy>(() => Components.OfType().ToArray()); - _modules = new Lazy>(() => RobotComponents.SelectMany(c => c.Modules).ToArray()); - _activeModules = new Lazy>(() => Modules.OfType().ToArray()); - } - - protected virtual void OnLockError(Lock @lock, ErrorCodes error) - { - } - public override void AcceptVisitor(IEntityVisitor visitor) { if (!TryAcceptVisitor(this, visitor)) + { base.AcceptVisitor(visitor); + } } public void VisitModules(IEntityVisitor visitor) { - foreach (var module in Modules) + foreach (Module module in Modules) { module.AcceptVisitor(visitor); } @@ -106,7 +122,7 @@ public void VisitModules(IEntityVisitor visitor) public void VisitRobotComponents(IEntityVisitor visitor) { - foreach (var component in RobotComponents) + foreach (RobotComponent component in RobotComponents) { component.AcceptVisitor(visitor); } @@ -114,82 +130,37 @@ public void VisitRobotComponents(IEntityVisitor visitor) public void VisitRobotInventory(IEntityVisitor visitor) { - var container = GetContainer(); + RobotInventory container = GetContainer(); + container?.AcceptVisitor(visitor); } public override IDictionary GetDebugInfo() { - var info = base.GetDebugInfo(); - info.Add("locksCount", _lockHandler.Count); - return info; - } - - public bool IsSelected => RobotHelper.IsSelected(this); - - public override double Health - { - get - { - if (IsRepackaged) - { - return base.Health; - } - - return ArmorMax > 0.0 && Armor > 0.0 - ? Armor.Ratio(ArmorMax) * 100 - : base.Health; - } - } + IDictionary info = base.GetDebugInfo(); - public override double Mass - { - get { return RobotComponents.Sum(c => c.Mass); } - } - - protected virtual void OnLockStateChanged(Lock @lock) - { - States.LockSomething = _lockHandler.Count > 0; - - var unitLock = @lock as UnitLock; - if (unitLock != null) - { - UpdateTypes |= UnitUpdateTypes.Lock; - UpdateVisibilityOf(unitLock.Target); - } - - var builder = new AnonymousBuilder(() => LockPacketBuilder.BuildPacket(@lock)); - OnBroadcastPacket(builder.ToProxy()); - } - - protected override void OnUpdate(TimeSpan time) - { - base.OnUpdate(time); - - _lockHandler.Update(time); + info.Add("locksCount", _lockHandler.Count); - foreach (var robotComponent in RobotComponents) - { - robotComponent.Update(time); - } + return info; } public void FullArmorRepair() { - DynamicProperties.Update(k.armor,1.0); + DynamicProperties.Update(k.armor, 1.0); Armor = ArmorMax; } public void FullCoreRecharge() { - var currentCore = DynamicProperties.GetOrAdd(k.currentCore); - - var coreMaxValue = CoreMax; + double currentCore = DynamicProperties.GetOrAdd(k.currentCore); + double coreMaxValue = CoreMax; if (currentCore >= coreMaxValue) + { return; + } - DynamicProperties.Update(k.currentCore,coreMaxValue); + DynamicProperties.Update(k.currentCore, coreMaxValue); Core = CoreMax; } @@ -199,111 +170,57 @@ public RobotInventory GetContainer() return Children.OfType().FirstOrDefault(); } - protected internal override double ComputeHeight() - { - return RobotComponents.Sum(c => c.ComputeHeight()); - } - - public bool HasModule - { - get { return Modules.Any(); } - } - - public bool IsItemsInContainer - { - get - { - if (IsRepackaged) - return false; - - var robotInventory = GetContainer(); - if (robotInventory == null) - return false; - - return robotInventory.HasChildren; - } - } - public void StopAllModules() { - foreach (var module in ActiveModules) + foreach (ActiveModule module in ActiveModules) { module.State.SwitchTo(ModuleStateType.Idle); } } - protected override void OnDamageTaken(Unit source, DamageTakenEventArgs e) - { - base.OnDamageTaken(source, e); - - var decayChance = _decayChance.Value; - var random = FastRandom.NextDouble(); - - if (decayChance >= random) - { - var d = Decay; - if (d > 0) - { - d--; - Decay = d; - } - } - } - public override void OnDeleteFromDb() { InsuranceHelper.DeleteAndInform(this); base.OnDeleteFromDb(); } - public void EmptyRobot(Character character,Container targetContainer,bool withContainer = true) + public void EmptyRobot(Character character, Container targetContainer, bool withContainer = true) { - foreach (var module in Modules) + foreach (Module module in Modules) { module.Unequip(targetContainer); } if (!withContainer) + { return; + } - var container = GetContainer(); - container?.RelocateItems(character, character, container.GetItems(), targetContainer); - } + RobotInventory container = GetContainer(); - public override bool IsStackable - { - get { return base.IsStackable && IsRepackaged; } + container?.RelocateItems(character, character, container.GetItems(), targetContainer); } public override Dictionary ToDictionary() { - var dictionary = base.ToDictionary(); + Dictionary dictionary = base.ToDictionary(); - foreach (var component in RobotComponents) + foreach (RobotComponent component in RobotComponents) { dictionary.Add(component.ComponentName, component.ToDictionary()); } - var container = GetContainer(); + RobotInventory container = GetContainer(); - if ( container != null ) + if (container != null) { - dictionary.Add(k.container,container.ToDictionary()); + dictionary.Add(k.container, container.ToDictionary()); } dictionary.Add(k.decay, Decay); dictionary.Add(k.tint, Tint); - return dictionary; - } - public IEnumerable ExtensionBonusEnablerExtensions - { - get { return ExtensionBonuses.Select(cb => new Extension(cb.extensionId, 1)); } - } - - protected IEnumerable ExtensionBonuses - { - get { return RobotComponents.SelectMany(component => component.ExtensionBonuses); } + return dictionary; } [CanBeNull] @@ -336,82 +253,125 @@ public RobotComponent GetRobotComponent(RobotComponentType componentType) return RobotComponents.FirstOrDefault(c => c.Type == componentType); } - public IEnumerable Modules - { - get { return _modules.Value; } - } - - public IEnumerable ActiveModules - { - get { return _activeModules.Value; } - } - - public IEnumerable Components - { - get { return _components.Value; } - } - - public IEnumerable RobotComponents - { - get { return _robotComponents.Value; } - } - - public void CheckEnergySystemAndThrowIfFailed(Module module, bool isRemoving=false) + public void CheckEnergySystemAndThrowIfFailed(Module module, bool isRemoving = false) { if (!CheckPowerGridForModule(module, isRemoving)) + { throw PerpetuumException.Create(ErrorCodes.OutOfPowergrid); + } if (!CheckCpuForModule(module, isRemoving)) + { throw PerpetuumException.Create(ErrorCodes.OutOfCpu); + } } public void CheckEnergySystemAndThrowIfFailed() { if (PowerGrid < 0) + { throw PerpetuumException.Create(ErrorCodes.OutOfPowergrid).SetData("powerGrid", Math.Abs(PowerGridMax - PowerGrid)).SetData("powerGridMax", PowerGridMax); + } if (Cpu < 0) + { throw PerpetuumException.Create(ErrorCodes.OutOfCpu).SetData("cpu", Math.Abs(CpuMax - Cpu)).SetData("cpuMax", CpuMax); + } } public void CreateComponents() { - foreach (var component in Template.BuildComponents()) + foreach (Item component in Template.BuildComponents()) { AddChild(component); } } - protected override bool IsDetected(Unit target) + [CanBeNull] + public T GetRobotComponent() where T : RobotComponent { - if (_lockHandler.IsLocked(target)) - return true; + return RobotComponents.OfType().FirstOrDefault(); + } - return base.IsDetected(target); + protected virtual void OnLockError(Lock @lock, ErrorCodes error) + { } - public override double Volume + protected virtual void OnLockStateChanged(Lock @lock) { - get + States.LockSomething = _lockHandler.Count > 0; + + + if (@lock is UnitLock unitLock) { - if (IsRepackaged) - return base.Volume; + UpdateTypes |= UnitUpdateTypes.Lock; + UpdateVisibilityOf(unitLock.Target); + } - var volume = RobotComponents.Sum(c => c.Volume); - volume *= Quantity; - return volume; + AnonymousBuilder builder = new AnonymousBuilder(() => LockPacketBuilder.BuildPacket(@lock)); + + OnBroadcastPacket(builder.ToProxy()); + } + + protected override void OnUpdate(TimeSpan time) + { + base.OnUpdate(time); + + _lockHandler.Update(time); + + foreach (RobotComponent robotComponent in RobotComponents) + { + robotComponent.Update(time); } } - public bool IsTrashed + protected internal override double ComputeHeight() { - get { return Trashcan.IsItemTrashed(this); } + return RobotComponents.Sum(c => c.ComputeHeight()); } - [CanBeNull] - public T GetRobotComponent() where T : RobotComponent + protected override void OnDamageTaken(Unit source, DamageTakenEventArgs e) { - return RobotComponents.OfType().FirstOrDefault(); + base.OnDamageTaken(source, e); + + double decayChance = this.decayChance.Value; + double random = FastRandom.NextDouble(); + + if (decayChance >= random) + { + int d = Decay; + + if (d > 0) + { + d--; + Decay = d; + } + } + } + + protected override bool IsDetected(Unit target) + { + return _lockHandler.IsLocked(target) || base.IsDetected(target); + } + + protected override void OnBeforeRemovedFromZone(IZone zone) + { + Module remoteController = Modules?.FirstOrDefault(x => x is RemoteControllerModule); + + if (remoteController != null) + { + (remoteController as RemoteControllerModule).CloseAllChannels(); + } + + base.OnBeforeRemovedFromZone(zone); + } + + private void InitComponents() + { + _components = new Lazy>(() => Children.OfType().ToArray()); + _robotComponents = new Lazy>(() => Components.OfType().ToArray()); + _modules = new Lazy>(() => RobotComponents.SelectMany(c => c.Modules).ToArray()); + _activeModules = new Lazy>(() => Modules.OfType().ToArray()); } } } diff --git a/src/Perpetuum/Robots/RobotInfoPacketBuilder.cs b/src/Perpetuum/Robots/RobotInfoPacketBuilder.cs new file mode 100644 index 000000000..f93a596b4 --- /dev/null +++ b/src/Perpetuum/Robots/RobotInfoPacketBuilder.cs @@ -0,0 +1,40 @@ +using Perpetuum.Builders; +using Perpetuum.Common; +using Perpetuum.Zones; +using System.Linq; + +namespace Perpetuum.Robots +{ + public class RobotInfoPacketBuilder : IBuilder + { + private readonly Robot _robot; + private readonly ZoneCommand _command; + + public RobotInfoPacketBuilder(Robot robot, ZoneCommand command = ZoneCommand.RobotInfo) + { + _robot = robot; + _command = command; + } + + public Packet Build() + { + var infoPacket = new Packet(_command); + infoPacket.AppendLong(_robot.Eid); + AppendRobotProperties(infoPacket); + + return infoPacket; + } + + private void AppendRobotProperties(Packet infoPacket) + { + var properties = _robot.Properties.Where(p => p.HasValue).ToArray(); + + infoPacket.AppendInt(properties.Length); + + foreach (var property in properties) + { + infoPacket.AppendProperty(property); + } + } + } +} diff --git a/src/Perpetuum/Services/Channels/ChannelManager.cs b/src/Perpetuum/Services/Channels/ChannelManager.cs index fb4b17617..5b349a017 100644 --- a/src/Perpetuum/Services/Channels/ChannelManager.cs +++ b/src/Perpetuum/Services/Channels/ChannelManager.cs @@ -54,6 +54,11 @@ private void SessionOnCharacterSelected(ISession session, Character character) var channel = UpdateChannel(channelName, c => c.SetMember(member)); channel?.SendMemberOnlineStateToAll(_sessionManager, member, true); } + + if (character.IsDocked) + { + character.GetCurrentDockingBase()?.TryJoinChannel(character); + } } private void SessionOnCharacterDeselected(ISession session, Character character) diff --git a/src/Perpetuum/Services/EventServices/EventMessages/NpcReinforcementsMessage.cs b/src/Perpetuum/Services/EventServices/EventMessages/NpcReinforcementsMessage.cs index 2f85f73ed..15371152b 100644 --- a/src/Perpetuum/Services/EventServices/EventMessages/NpcReinforcementsMessage.cs +++ b/src/Perpetuum/Services/EventServices/EventMessages/NpcReinforcementsMessage.cs @@ -6,13 +6,14 @@ public class NpcReinforcementsMessage : IEventMessage { public EventType Type => EventType.NpcReinforce; - public Npc Npc { get; } + public SmartCreature SmartCreature { get; } + public int ZoneId { get; } - public NpcReinforcementsMessage(Npc npc, int zoneID) + public NpcReinforcementsMessage(SmartCreature smartCreature, int zoneID) { ZoneId = zoneID; - Npc = npc; + SmartCreature = smartCreature; } } } diff --git a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs index d3078dfae..dc8788f37 100644 --- a/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs +++ b/src/Perpetuum/Services/EventServices/EventProcessors/NpcSpawnEventHandlers/NpcReinforcementSpawner.cs @@ -44,7 +44,7 @@ protected override bool CheckMessage(IEventMessage inMsg, out NpcReinforcementsM protected override void CheckReinforcements(NpcReinforcementsMessage msg) { - var info = msg.Npc.BossInfo; + var info = msg.SmartCreature.BossInfo; if (!_reinforcementsByNpc.ContainsKey(info)) { var reinforcements = _npcReinforcementsRepo.CreateNpcBossAddSpawn(info, msg.ZoneId); @@ -54,7 +54,7 @@ protected override void CheckReinforcements(NpcReinforcementsMessage msg) protected override bool CheckState(NpcReinforcementsMessage msg) { - if (msg.Npc.BossInfo.IsDead) + if (msg.SmartCreature.BossInfo.IsDead) { CleanupAllReinforcements(msg); return true; @@ -65,20 +65,20 @@ protected override bool CheckState(NpcReinforcementsMessage msg) private void UpdateAggro(NpcReinforcementsMessage msg) { - var info = msg.Npc.BossInfo; + var info = msg.SmartCreature.BossInfo; if (_reinforcementsByNpc.ContainsKey(info)) { var activeWaves = _reinforcementsByNpc[info].GetAllActiveWaves().Where(w => w.ActivePresence != null); foreach (var wave in activeWaves) { - SpreadAggro(wave.ActivePresence, msg.Npc); + SpreadAggro(wave.ActivePresence, msg.SmartCreature); } } } protected override void CleanupAllReinforcements(NpcReinforcementsMessage msg) { - var info = msg.Npc.BossInfo; + var info = msg.SmartCreature.BossInfo; if (_reinforcementsByNpc.ContainsKey(info)) { var activeWaves = _reinforcementsByNpc[info].GetAllActiveWaves(); @@ -92,33 +92,33 @@ protected override void CleanupAllReinforcements(NpcReinforcementsMessage msg) protected override Position FindSpawnPosition(NpcReinforcementsMessage msg, int maxRange) { - var finder = new RandomWalkableAroundPositionFinder(_zone, msg.Npc.CurrentPosition, maxRange); + var finder = new RandomWalkableAroundPositionFinder(_zone, msg.SmartCreature.CurrentPosition, maxRange); if (finder.Find(out Position result)) { return result; } - return msg.Npc.CurrentPosition; + return msg.SmartCreature.CurrentPosition; } protected override INpcReinforcementWave GetNextWave(NpcReinforcementsMessage msg) { - var npc = msg.Npc; + var npc = msg.SmartCreature; var percent = 1.0 - npc.ArmorPercentage; return _reinforcementsByNpc[npc.BossInfo].GetNextPresence(percent); } protected override void OnSpawning(Presence pres, NpcReinforcementsMessage msg) { - SpreadAggro(pres, msg.Npc); + SpreadAggro(pres, msg.SmartCreature); } - private void SpreadAggro(Presence presenceToAggro, Npc npcWithAggro) + private void SpreadAggro(Presence presenceToAggro, SmartCreature smartCreatureWithAggro) { foreach (var npc in presenceToAggro.Flocks.GetMembers()) { - foreach (var threat in npcWithAggro.ThreatManager.Hostiles) + foreach (var threat in smartCreatureWithAggro.ThreatManager.Hostiles) { - npc.AddDirectThreat(threat.unit, threat.Threat + FastRandom.NextDouble(5, 10)); + npc.AddDirectThreat(threat.Unit, threat.Threat + FastRandom.NextDouble(5, 10)); } } } diff --git a/src/Perpetuum/Units/DockingBases/DockingBase.cs b/src/Perpetuum/Units/DockingBases/DockingBase.cs index 8a340a5a0..78bd3aad2 100644 --- a/src/Perpetuum/Units/DockingBases/DockingBase.cs +++ b/src/Perpetuum/Units/DockingBases/DockingBase.cs @@ -167,7 +167,7 @@ public void DockIn(Character character,TimeSpan undockDelay) character.ZoneId = null; character.ZonePosition = null; - Transaction.Current.OnCommited(() => JoinChannel(character)); + Transaction.Current.OnCommited(() => TryJoinChannel(character)); } protected IEnumerable GetCharacters() @@ -250,7 +250,7 @@ public Robot CreateStarterRobotForCharacter(Character character,bool setActive = protected virtual bool CanCreateEquippedStartRobot => Zone?.Configuration.Protected ?? false; - public virtual void JoinChannel(Character character) + protected virtual void JoinChannel(Character character) { ChannelManager.JoinChannel(ChannelName,character,ChannelMemberRole.Undefined,null); } @@ -260,6 +260,22 @@ public void LeaveChannel(Character character) ChannelManager.LeaveChannel(ChannelName,character); } + /// + /// Check and joins/leave character in/from the docking base chat, if possible. + /// + /// Character being checked. + public void TryJoinChannel(Character character) + { + if (IsDockingAllowed(character) == ErrorCodes.NoError) + { + JoinChannel(character); + + return; + } + + LeaveChannel(character); + } + public static bool Exists(long baseEid) { return Db.Query().CommandText("select eid from zoneentities where eid=@baseEid").SetParameter("@baseEid", baseEid).ExecuteScalar() > 0 || diff --git a/src/Perpetuum/Units/TagHelper.cs b/src/Perpetuum/Units/TagHelper.cs index af3dbbd20..ee4ce8723 100644 --- a/src/Perpetuum/Units/TagHelper.cs +++ b/src/Perpetuum/Units/TagHelper.cs @@ -10,10 +10,14 @@ public class TagHelper public void DoTagging(T target,Player tagger,TimeSpan duration) where T:Unit,ITaggable { var currentTagger = target.GetTagger(); + if (currentTagger != null) + { return; + } var builder = target.NewEffectBuilder().SetType(EffectType.effect_tag).SetSource(tagger).WithDuration(duration); + target.ApplyEffect(builder); } @@ -21,10 +25,14 @@ public void DoTagging(T target,Player tagger,TimeSpan duration) where T:Unit, public static Player GetTagger(T tagable) where T:Unit,ITaggable { var zone = tagable.Zone; + if (zone == null) + { return null; + } var tag = tagable.EffectHandler.GetEffectsByType(EffectType.effect_tag).FirstOrDefault(); + return tag?.Source as Player; } } diff --git a/src/Perpetuum/Units/Unit.Visibility.cs b/src/Perpetuum/Units/Unit.Visibility.cs index 7ce73ab54..22dd5cc21 100644 --- a/src/Perpetuum/Units/Unit.Visibility.cs +++ b/src/Perpetuum/Units/Unit.Visibility.cs @@ -7,6 +7,9 @@ using Perpetuum.Players; using Perpetuum.Robots; using Perpetuum.Zones; +using Perpetuum.Zones.RemoteControl; +using Perpetuum.Zones.LandMines; +using Perpetuum.Zones.NpcSystem; namespace Perpetuum.Units { @@ -46,6 +49,16 @@ protected internal virtual void UpdatePlayerVisibility(Player player) // unit => player nem latjak egymast } + protected internal virtual void UpdateUnitVisibility(SentryTurret turret) + { + + } + + protected internal virtual void UpdateUnitVisibility(Npc npc) + { + + } + public virtual void UpdateVisibilityOf(Unit target) { target.UpdateUnitVisibility(this); @@ -98,14 +111,22 @@ protected virtual void OnUnitVisibilityUpdated(Unit target, Visibility visibilit protected virtual bool IsDetected(Unit target) { - var robot = target as Robot; - if (robot != null) + double range; + + if (target is LandMine) + { + range = (this as Robot).MineDetectionRange; + } else { - if (robot.IsLocked(this)) + var robot = target as Robot; + if (robot != null && robot.IsLocked(this)) + { return true; + } + + range = 100 / Math.Max(1, target.StealthStrength) * Math.Max(1, DetectionStrength); } - var range = 100 / Math.Max(1, target.StealthStrength) * Math.Max(1, DetectionStrength); return IsInRangeOf3D(target, range); } diff --git a/src/Perpetuum/Units/Unit.cs b/src/Perpetuum/Units/Unit.cs index e59ed4393..70f3deaa4 100644 --- a/src/Perpetuum/Units/Unit.cs +++ b/src/Perpetuum/Units/Unit.cs @@ -1,13 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Numerics; -using System.Threading; -using System.Threading.Tasks; -using Perpetuum.Builders; +using Perpetuum.Builders; using Perpetuum.Collections.Spatial; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; @@ -26,9 +17,20 @@ using Perpetuum.Zones.Eggs; using Perpetuum.Zones.Gates; using Perpetuum.Zones.Locking; +using Perpetuum.Zones.NpcSystem; using Perpetuum.Zones.PBS; using Perpetuum.Zones.PBS.DockingBases; using Perpetuum.Zones.PBS.Turrets; +using Perpetuum.Zones.RemoteControl; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Threading; +using System.Threading.Tasks; namespace Perpetuum.Units { @@ -48,13 +50,13 @@ protected override double CalculateValue() var speedMaxMod = _owner.GetPropertyModifier(AggregateField.speed_max_modifier); speedMaxMod.Modify(ref speedMax); - _owner.ApplyEffectPropertyModifiers(AggregateField.effect_speed_max_modifier,ref speedMax); - _owner.ApplyEffectPropertyModifiers(AggregateField.effect_massivness_speed_max_modifier,ref speedMax); + _owner.ApplyEffectPropertyModifiers(AggregateField.effect_speed_max_modifier, ref speedMax); + _owner.ApplyEffectPropertyModifiers(AggregateField.effect_massivness_speed_max_modifier, ref speedMax); if (_owner.ActualMass > 0) speedMax.Multiply(_owner.Mass / _owner.ActualMass); - _owner.ApplyEffectPropertyModifiers(AggregateField.effect_speed_highway_modifier,ref speedMax); + _owner.ApplyEffectPropertyModifiers(AggregateField.effect_speed_highway_modifier, ref speedMax); return speedMax.Value; } @@ -74,10 +76,10 @@ protected override bool IsRelated(AggregateField field) } } - + public delegate void UnitEventHandler(Unit unit); public delegate void UnitEventHandler(Unit unit, T args); - public delegate void UnitEventHandler(Unit unit, T1 args1, T2 args2); + public delegate void UnitEventHandler(Unit unit, T1 args1, T2 args2); public abstract partial class Unit : Item { @@ -117,7 +119,7 @@ public abstract partial class Unit : Item private ItemProperty _reactorRadiation; private ItemProperty _signatureRadius; private ItemProperty _slope; - + private readonly Lazy _height; protected Unit() @@ -185,7 +187,7 @@ public double CurrentSpeed get => _currentSpeed; set { - if ( Math.Abs(_currentSpeed - value) < double.Epsilon ) + if (Math.Abs(_currentSpeed - value) < double.Epsilon) return; _currentSpeed = value; @@ -198,7 +200,7 @@ public double Direction get => _direction; set { - if ( Math.Abs(_direction - value) < double.Epsilon ) + if (Math.Abs(_direction - value) < double.Epsilon) return; _direction = value; @@ -211,7 +213,7 @@ public double Orientation get => _orientation; set { - if ( Math.Abs(_orientation - value) < double.Epsilon ) + if (Math.Abs(_orientation - value) < double.Epsilon) return; _orientation = value; @@ -227,7 +229,7 @@ public virtual ErrorCodes IsAttackable { get { - if ( !ED.AttributeFlags.NonAttackable && !States.Dead) + if (!ED.AttributeFlags.NonAttackable && !States.Dead) return ErrorCodes.NoError; return ErrorCodes.TargetIsNonAttackable; @@ -298,7 +300,7 @@ public Position CurrentPosition /// public void Update(TimeSpan time) { - if ( !InZone || States.Dead ) + if (!InZone || States.Dead) return; OnUpdate(time); @@ -308,7 +310,7 @@ public void Update(TimeSpan time) protected virtual void OnUpdate(TimeSpan time) { - _coreRecharger.RechargeCore(this,time); + _coreRecharger.RechargeCore(this, time); EffectHandler.Update(time); @@ -360,7 +362,7 @@ protected virtual void OnBroadcastPacket(IBuilder packetBuilder) BroadcastPacket?.Invoke(this, packetBuilder.Build()); } - protected virtual void OnEffectChanged(Effect effect,bool apply) + protected virtual void OnEffectChanged(Effect effect, bool apply) { EffectChanged?.Invoke(this, effect, apply); @@ -374,15 +376,15 @@ protected virtual void OnEffectChanged(Effect effect,bool apply) public void SendRefreshUnitPacket() { - OnBroadcastPacket(UnitEnterPacketBuilder.Create(this,ZoneEnterType.Update).ToProxy()); + OnBroadcastPacket(UnitEnterPacketBuilder.Create(this, ZoneEnterType.Update).ToProxy()); } - public void AddToZone(IZone zone,Position position,ZoneEnterType enterType = ZoneEnterType.Default,IBeamBuilder enterBeamBuilder = null) + public void AddToZone(IZone zone, Position position, ZoneEnterType enterType = ZoneEnterType.Default, IBeamBuilder enterBeamBuilder = null) { _zone = zone; CurrentPosition = zone.FixZ(position); - OnEnterZone(zone,enterType); + OnEnterZone(zone, enterType); zone.AddUnit(this); @@ -401,16 +403,21 @@ protected virtual void OnEnterZone(IZone zone, ZoneEnterType enterType) { } public void RemoveFromZone(IBeamBuilder exitBeamBuilder = null) { IZone zone; - if ((zone = Interlocked.CompareExchange(ref _zone,null,_zone)) == null) + + if ((zone = Interlocked.CompareExchange(ref _zone, null, _zone)) == null) + { return; + } Debug.Assert(zone != null, "zone != null"); if (exitBeamBuilder != null) + { zone.CreateBeam(exitBeamBuilder); + } + OnBeforeRemovedFromZone(zone); zone.RemoveUnit(this); - OnRemovedFromZone(zone); zone.UpdateUnitRelations(this); RemovedFromZone?.Invoke(this); @@ -418,6 +425,8 @@ public void RemoveFromZone(IBeamBuilder exitBeamBuilder = null) protected virtual void OnRemovedFromZone(IZone zone) { } + protected virtual void OnBeforeRemovedFromZone(IZone zone) { } + public void TakeDamage(DamageInfo damageInfo) { _damageProcessor.TakeDamage(damageInfo); @@ -427,7 +436,7 @@ public void TakeDamage(DamageInfo damageInfo) protected virtual void OnDamageTaken(Unit source, DamageTakenEventArgs e) { - DamageTaken?.Invoke(this,source, e); + DamageTaken?.Invoke(this, source, e); var packet = new CombatLogPacket(CombatLogType.Damage, this, source); packet.AppendByte((byte)(e.IsCritical ? 1 : 0)); @@ -440,7 +449,7 @@ protected virtual void OnDamageTaken(Unit source, DamageTakenEventArgs e) Armor -= e.TotalDamage; - OnCombatEvent(source,e); + OnCombatEvent(source, e); if (Armor <= 0.0) { @@ -450,7 +459,7 @@ protected virtual void OnDamageTaken(Unit source, DamageTakenEventArgs e) public virtual void OnCombatEvent(Unit source, CombatEventArgs e) { - + } @@ -474,10 +483,10 @@ private void OnUpdated(UnitUpdatedEventArgs e) protected virtual void DoExplosion() { var zone = Zone; - if ( zone == null ) + if (zone == null) return; - if ( zone.Configuration.Protected ) + if (zone.Configuration.Protected) return; var damageBuilder = GetExplosionDamageBuilder(); @@ -519,7 +528,7 @@ private IDamageBuilder GetExplosionDamageBuilder() return damageBuilder; } - private class KillDetectorHelper : IEntityVisitor,IEntityVisitor,IEntityVisitor + private class KillDetectorHelper : IEntityVisitor, IEntityVisitor, IEntityVisitor { public KillDetectorHelper() { @@ -552,7 +561,7 @@ public void Visit(PBSObject pbsObject) public void Kill(Unit killer = null) { - if (!Monitor.TryEnter(_killSync) ) + if (!Monitor.TryEnter(_killSync)) return; try @@ -589,11 +598,11 @@ protected virtual bool CanBeKilled() return true; } - public event Action Dead; + public event Action Dead; protected virtual void OnDead(Unit killer) { - Dead?.Invoke(killer,this); + Dead?.Invoke(killer, this); DoExplosion(); @@ -618,13 +627,13 @@ protected virtual void OnTileChanged() TileChanged?.Invoke(this); } - protected virtual void OnCellChanged(CellCoord lastCellCoord, CellCoord currentCellCoord) {} + protected virtual void OnCellChanged(CellCoord lastCellCoord, CellCoord currentCellCoord) { } public override Dictionary ToDictionary() { var result = base.ToDictionary(); - if (!InZone) + if (!InZone) return result; result.Add(k.px, CurrentPosition.X); @@ -709,17 +718,17 @@ public void ApplyPvPEffect(TimeSpan duration) public virtual bool IsWalkable(Vector2 position) { - return Zone.IsWalkable((int) position.X, (int) position.Y, Slope); + return Zone.IsWalkable((int)position.X, (int)position.Y, Slope); } public virtual bool IsWalkable(Position position) { - return Zone.IsWalkable((int) position.X,(int)position.Y, Slope); + return Zone.IsWalkable((int)position.X, (int)position.Y, Slope); } - public virtual bool IsWalkable(int x,int y) + public virtual bool IsWalkable(int x, int y) { - return Zone.IsWalkable(x, y,Slope); + return Zone.IsWalkable(x, y, Slope); } public virtual IDictionary GetDebugInfo() @@ -759,7 +768,7 @@ private class UnitEnterPacketBuilder : IBuilder private readonly ZoneEnterType _enterType; private readonly Unit _unit; - private UnitEnterPacketBuilder(Unit unit,ZoneEnterType enterType) + private UnitEnterPacketBuilder(Unit unit, ZoneEnterType enterType) { _unit = unit; _enterType = enterType; @@ -798,7 +807,7 @@ public Packet Build() if (primaryLock != null) { packet.AppendByte(1); - LockPacketBuilder.AppendTo(primaryLock,packet); + LockPacketBuilder.AppendTo(primaryLock, packet); } else { @@ -849,12 +858,12 @@ private static void WriteRobotComponent(BinaryWriter bw, RobotComponent componen if (component == null) { bw.Write(0); - bw.Write((byte) 0); + bw.Write((byte)0); return; } bw.Write(component.Definition); - bw.Write((byte) component.MaxSlots); + bw.Write((byte)component.MaxSlots); for (var i = 0; i < component.MaxSlots; i++) { @@ -871,7 +880,7 @@ private static void WriteModule(BinaryWriter bw, Module module) public static IBuilder Create(Unit unit, ZoneEnterType enterType) { - return new UnitEnterPacketBuilder(unit,enterType); + return new UnitEnterPacketBuilder(unit, enterType); } } @@ -913,15 +922,26 @@ public Packet Build() } } - protected bool IsHostile(Unit unit) + protected virtual bool IsHostileFor(Unit unit) { return false; } + + public bool IsHostile(Unit unit) { return unit.IsHostileFor(this); } - protected virtual bool IsHostileFor(Unit unit) { return false; } - internal virtual bool IsHostile(Player player) { return false; } - internal virtual bool IsHostile(AreaBomb bomb) { return false; } - internal virtual bool IsHostile(Gate gate) { return false; } + public virtual bool IsHostile(Player player) { return false; } + + internal virtual bool IsHostile(AreaBomb bomb) { return false; } + + internal virtual bool IsHostile(Gate gate) { return false; } + + internal virtual bool IsHostile(SentryTurret turret) { return false; } + + internal virtual bool IsHostile(IndustrialTurret turret) { return false; } + + internal virtual bool IsHostile(Npc npc) { return false; } + + internal virtual bool IsHostile(CombatDrone drone) { return false; } public void StopMoving() { diff --git a/src/Perpetuum/Units/UnitDespawnHelper.cs b/src/Perpetuum/Units/UnitDespawnHelper.cs index b0656902f..43ea641bd 100644 --- a/src/Perpetuum/Units/UnitDespawnHelper.cs +++ b/src/Perpetuum/Units/UnitDespawnHelper.cs @@ -1,7 +1,7 @@ -using System; using Perpetuum.ExportedTypes; using Perpetuum.Timers; using Perpetuum.Zones.Effects; +using System; namespace Perpetuum.Units { @@ -21,10 +21,7 @@ public class UnitDespawnHelper : IUnitDespawnHelper public UnitDespawnerCanApplyEffect CanApplyDespawnEffect { protected get; set; } public UnitDespawnStrategy DespawnStrategy { protected get; set; } - public virtual EffectType DespawnEffect - { - get { return EffectType.effect_despawn_timer; } - } + public virtual EffectType DespawnEffect => EffectType.effect_despawn_timer; protected readonly TimeSpan _despawnTime; protected readonly EffectToken _effectToken = EffectToken.NewToken(); @@ -47,7 +44,9 @@ public virtual void Update(TimeSpan time, Unit unit) TryReApplyDespawnEffect(unit); if (HasEffectOrPending(unit)) + { return; + } CanApplyDespawnEffect = null; if (DespawnStrategy != null) @@ -64,20 +63,24 @@ public virtual void Update(TimeSpan time, Unit unit) private void TryReApplyDespawnEffect(Unit unit) { - var canApplyDespawnEffect = CanApplyDespawnEffect; + UnitDespawnerCanApplyEffect canApplyDespawnEffect = CanApplyDespawnEffect; if (canApplyDespawnEffect == null) + { return; + } - var applyDespawnEffect = canApplyDespawnEffect(unit); + bool applyDespawnEffect = canApplyDespawnEffect(unit); if (!applyDespawnEffect) + { return; + } ApplyDespawnEffect(unit); } protected void ApplyDespawnEffect(Unit unit) { - var effectBuilder = unit.NewEffectBuilder().SetType(DespawnEffect).WithDuration(_despawnTime).WithToken(_effectToken); + EffectBuilder effectBuilder = unit.NewEffectBuilder().SetType(DespawnEffect).WithDuration(_despawnTime).WithToken(_effectToken); unit.ApplyEffect(effectBuilder); } @@ -88,18 +91,16 @@ public override string ToString() public static UnitDespawnHelper Create(Unit unit, TimeSpan despawnTime) { - var helper = new UnitDespawnHelper(despawnTime); + UnitDespawnHelper helper = new UnitDespawnHelper(despawnTime); helper.ApplyDespawnEffect(unit); + return helper; } } public class CancellableDespawnHelper : UnitDespawnHelper { - public override EffectType DespawnEffect - { - get { return EffectType.effect_stronghold_despawn_timer; } - } + public override EffectType DespawnEffect => EffectType.effect_stronghold_despawn_timer; private CancellableDespawnHelper(TimeSpan despawnTime) : base(despawnTime) { } private bool _canceled = false; @@ -119,15 +120,17 @@ public override void Update(TimeSpan time, Unit unit) _timer.Update(time).IsPassed(() => { if (_canceled || HasEffectOrPending(unit)) + { return; + } DespawnStrategy?.Invoke(unit); }); } - public new static CancellableDespawnHelper Create(Unit unit, TimeSpan despawnTime) + public static new CancellableDespawnHelper Create(Unit unit, TimeSpan despawnTime) { - var helper = new CancellableDespawnHelper(despawnTime); + CancellableDespawnHelper helper = new CancellableDespawnHelper(despawnTime); helper.ApplyDespawnEffect(unit); return helper; } diff --git a/src/Perpetuum/Units/UnitExtensions.cs b/src/Perpetuum/Units/UnitExtensions.cs index 24f8af8f3..260e36c4a 100644 --- a/src/Perpetuum/Units/UnitExtensions.cs +++ b/src/Perpetuum/Units/UnitExtensions.cs @@ -1,12 +1,13 @@ -using System.Collections.Generic; -using System.Linq; using Perpetuum.ExportedTypes; using Perpetuum.Log; using Perpetuum.Players; using Perpetuum.Players.ExtensionMethods; using Perpetuum.Zones; using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; using Perpetuum.Zones.PBS; +using System.Collections.Generic; +using System.Linq; namespace Perpetuum.Units { @@ -21,23 +22,25 @@ public static void AddDirectThreat(this Unit unit, Unit hostile, double threatVa unit.UpdateVisibilityOf(hostile); } - unit.AddThreat(hostile,new Threat(ThreatType.Direct, threatValue)); + unit.AddThreat(hostile, new Threat(ThreatType.Direct, threatValue)); } - public static void AddThreat(this Unit unit,Unit hostile,Threat threat) + public static void AddThreat(this Unit unit, Unit hostile, Threat threat) { - if (unit is Npc npc && npc.CanAddThreatTo(hostile, threat)) - npc.AddThreat(hostile, threat, true); + if (unit is SmartCreature smartCreature && smartCreature.CanAddThreatTo(hostile, threat)) + { + smartCreature.AddThreat(hostile, threat, true); + } } - public static bool TryGetConstructionRadius(this Unit unit,out int radius) + public static bool TryGetConstructionRadius(this Unit unit, out int radius) { radius = 0; if (unit?.ED.Config.constructionRadius == null) return false; - radius = (int) unit.ED.Config.constructionRadius; + radius = (int)unit.ED.Config.constructionRadius; return true; } @@ -51,7 +54,7 @@ public static int GetItemWorkRangeOrDefault(this Unit unit) if (unit == null || unit.ED.Config.item_work_range == null) return 0; - return (int) unit.ED.Config.item_work_range; + return (int)unit.ED.Config.item_work_range; } @@ -70,7 +73,7 @@ public static int GetCycleTimeMs(this Unit unit) return 0; if (unit.ED.Config.cycle_time != null) - return (int) unit.ED.Config.cycle_time; + return (int)unit.ED.Config.cycle_time; return 30000; } @@ -92,7 +95,7 @@ public static int GetConstructionRadius(this Unit unit) return 0; if (unit.ED.Config.constructionRadius != null) - return (int) unit.ED.Config.constructionRadius; + return (int)unit.ED.Config.constructionRadius; Logger.Error("consistency error. no construction radius was defined for definition: " + unit.Definition + " " + unit.ED.Name); return 10; @@ -100,7 +103,7 @@ public static int GetConstructionRadius(this Unit unit) - public static void AddEffectsDebugInfo(this Unit unit, IDictionary info) + public static void AddEffectsDebugInfo(this Unit unit, IDictionary info) { var effects = new Dictionary(); var counter = 0; @@ -120,9 +123,9 @@ public static IDictionary GetMiniDebugInfo(this Unit unit) return new Dictionary { {k.name, unit.Name}, - {k.eid, unit.Eid}, - {k.definitionName, unit.ED.Name}, - {k.owner, unit.Owner}, + {k.eid, unit.Eid}, + {k.definitionName, unit.ED.Name}, + {k.owner, unit.Owner}, {k.state, unit.States.ToString()} }; } @@ -133,7 +136,7 @@ public static int GetTransmitRadius(this Unit unit) return 0; if (unit.ED.Config.transmitradius != null) - return (int) unit.ED.Config.transmitradius; + return (int)unit.ED.Config.transmitradius; Logger.Error("consistency error. no transmitRadius was defined for definition: " + unit.Definition + " " + unit.ED.Name); return 0; @@ -150,20 +153,20 @@ public static double GetCoreTransferred(this Unit unit) Logger.Error("coreTransferred not defined for " + unit); return 100; - + } public static double GetTransferEfficiency(this Unit unit) { if (unit.ED.Config.transferEfficiency != null) - return ((double) unit.ED.Config.transferEfficiency).Clamp(); + return ((double)unit.ED.Config.transferEfficiency).Clamp(); Logger.Error("transferEfficiency not defined for " + unit); return 0.8; } - public static void KillAll(this IEnumerable units,Unit killer = null) + public static void KillAll(this IEnumerable units, Unit killer = null) { foreach (var unit in units) { @@ -171,22 +174,29 @@ public static void KillAll(this IEnumerable units,Unit killer = null) } } - public static void SpreadAssistThreatToNpcs(this Unit unit, Unit assistant,Threat threat) + public static void SpreadAssistThreatToNpcs(this Unit unit, Unit assistant, Threat threat) { - if ( unit == null || assistant == null) + if (unit == null || assistant == null) + { return; + } - foreach (var npc in unit.GetWitnessUnits()) + foreach (var smartCreature in unit.GetWitnessUnits()) { - npc.AddAssistThreat(assistant,unit,threat); + smartCreature.AddAssistThreat(assistant, unit, threat); } } - + public static bool IsPlayer(this Unit unit) { return unit is Player; } public static void SendPacketToWitnessPlayers(this Unit source, Packet packet, bool sendSelf = false) { + if (source == null) + { + return; + } + if (sendSelf) { (source as Player)?.Session.SendPacket(packet); @@ -196,12 +206,12 @@ public static void SendPacketToWitnessPlayers(this Unit source, Packet packet, b } - public static IEnumerable WithinRange(this IEnumerable units,Position position,double distance) where T : Unit + public static IEnumerable WithinRange(this IEnumerable units, Position position, double distance) where T : Unit { return units.Where(unit => unit.IsInRangeOf3D(position, distance)); } - public static IEnumerable WithinRange2D(this IEnumerable units,Position position,double distance) where T : Unit + public static IEnumerable WithinRange2D(this IEnumerable units, Position position, double distance) where T : Unit { return units.Where(unit => unit.CurrentPosition.IsInRangeOf2D(position, distance)); } @@ -235,7 +245,7 @@ public static T GetNearestUnit(this IEnumerable units, Position position) return nearestUnit; } - public static IEnumerable GetAllByCategoryFlags(this IEnumerable units, CategoryFlags cf) where T:Unit + public static IEnumerable GetAllByCategoryFlags(this IEnumerable units, CategoryFlags cf) where T : Unit { return units.Where(u => u.ED.CategoryFlags.IsCategory(cf)).ToArray(); } diff --git a/src/Perpetuum/Zones/DistanceConstants.cs b/src/Perpetuum/Zones/DistanceConstants.cs index aa0e8271c..e31b53fda 100644 --- a/src/Perpetuum/Zones/DistanceConstants.cs +++ b/src/Perpetuum/Zones/DistanceConstants.cs @@ -5,11 +5,11 @@ namespace Perpetuum.Zones public class DistanceConstants { public const double TERRAIN_DEGRADE_DISTANCE_FROM_PBS = 75.0; - + public const double KIOSK_USE_DISTANCE = 3.0; public const double SWITCH_USE_DISTANCE = 3.0; public const double ITEMSUPPLY_USE_DISTANCE = 3.0; - + public const double ALARMSWITCH_STAYCLOSE_DISTANCE = 14.0; public const double ITEM_SHOP_DISTANCE = 3.0; public const double AREA_BOMB_DISTANCE_TO_STATIONS = 90.0; @@ -19,7 +19,7 @@ public class DistanceConstants public const double MOBILE_TELEPORT_USE_RANGE = 8.0; public const double INTRUSION_SAP_DEFENSE_RANGE = 100.0; public const double PLANT_MIN_DISTANCE_FROM_SAP = 40; - + public const double MAX_TERRAFORM_LEVEL_DIFFERENCE = 8.0; public const double MAX_TERRAFORM_ALTITUDE_PLAYER_VS_TARGET_DIFFERENCE = 20.0; public const double MOBILE_WORLD_TELEPORT_RANGE = 3072; @@ -29,9 +29,13 @@ public class DistanceConstants public const double PLANT_MIN_DISTANCE_FROM_BASE = 100.0; public const double PLANT_MAX_DISTANCE_FROM_OUTPOST = 300.0; + public const double LANDMINE_DEPLOY_RANGE_FROM_BASE = 100.0; + public const double LANDMINE_DEPLOY_RANGE_FROM_TELEPORT = 100.0; + public const double LANDMINE_DEPLOY_RANGE_FROM_LANDMINE = 5.0; + public const double PLANT_MIN_DISTANCE_FROM_PBS = 5.0; public const double PLANT_MAX_DISTANCE_FROM_PBS = 150.0; - + public const double NPC_EGG_DISTANCE_ON_PVE_ZONES = 50.0; public const double PBS_NODE_USE_DISTANCE = 10.0; public const double TERRAFORM_MIN_RANGE_FROM_OBJECTS = 25.0; @@ -53,17 +57,21 @@ public class DistanceConstants public const double PBS_DIST_FROM_TELEPORT = 200; + public const double RCU_DEPLOY_RANGE_FROM_BASE = 100.0; + public const double RCU_DEPLOY_RANGE_FROM_TELEPORT = 100.0; + public const double RCU_DEPLOY_RANGE_FROM_RCU = 2.0; + public static Dictionary GetEnumDictionary() { - var result = new Dictionary(); + Dictionary result = new Dictionary(); - var type = typeof (DistanceConstants); // Get type pointer - var fields = type.GetFields(); // Obtain all fields - foreach (var field in fields) // Loop through fields + System.Type type = typeof(DistanceConstants); // Get type pointer + System.Reflection.FieldInfo[] fields = type.GetFields(); // Obtain all fields + foreach (System.Reflection.FieldInfo field in fields) // Loop through fields { - var name = field.Name; // Get string name - var temp = field.GetValue(null); // Get value - + string name = field.Name; // Get string name + object temp = field.GetValue(null); // Get value + if (temp is double) { result.Add(name, temp); diff --git a/src/Perpetuum/Zones/Effects/GangEffect.cs b/src/Perpetuum/Zones/Effects/GangEffect.cs index 520782e4d..c49458590 100644 --- a/src/Perpetuum/Zones/Effects/GangEffect.cs +++ b/src/Perpetuum/Zones/Effects/GangEffect.cs @@ -1,7 +1,9 @@ -using System.Collections.Generic; using Perpetuum.Groups.Gangs; using Perpetuum.Players; using Perpetuum.Units; +using Perpetuum.Zones.RemoteControl; +using System.Collections.Generic; +using System.Linq; namespace Perpetuum.Zones.Effects { @@ -14,13 +16,20 @@ protected override void OnTick() { if (Owner != Source) { - var gang = ((Player)Owner).Gang; - // ha nincs mar gangben vagy a forras mar nincs gangben + Gang gang = Owner is Player player + ? player.Gang + : Owner is RemoteControlledCreature remoteControlledCreature && + remoteControlledCreature.CommandRobot is Player ownerPlayer + ? ownerPlayer.Gang + : null; + if (gang == null || !gang.IsMember((Player)Source)) { OnRemoved(); + return; } + } base.OnTick(); @@ -28,8 +37,12 @@ protected override void OnTick() protected override IEnumerable GetTargets(IZone zone) { - var player = (Player)Owner; - return zone.GetGangMembers(player.Gang).WithinRange(Owner.CurrentPosition, Radius); + Player player = (Player)Owner; + IEnumerable gangMembers = zone.GetGangMembers(player.Gang); + IEnumerable alliedTurrets = zone.GetAlliedTurretsByPlayers(new[] { player }.Union(gangMembers)); + IEnumerable alliedUnits = gangMembers.Union(alliedTurrets); + + return alliedUnits.WithinRange(Owner.CurrentPosition, Radius); } } diff --git a/src/Perpetuum/Zones/Effects/ZoneEffects/ZoneEffectHandler.cs b/src/Perpetuum/Zones/Effects/ZoneEffects/ZoneEffectHandler.cs index 730996f5d..8b80c3025 100644 --- a/src/Perpetuum/Zones/Effects/ZoneEffects/ZoneEffectHandler.cs +++ b/src/Perpetuum/Zones/Effects/ZoneEffects/ZoneEffectHandler.cs @@ -1,6 +1,7 @@ using Perpetuum.Log; using Perpetuum.Players; using Perpetuum.Units; +using Perpetuum.Zones.RemoteControl; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -72,7 +73,7 @@ private IEnumerable GetEffects() private Func CanApplyEffect(ZoneEffect effect) { - return u => !u.EffectHandler.ContainsEffect(effect.Effect) && (!effect.PlayerOnly || u is Player); + return u => !u.EffectHandler.ContainsEffect(effect.Effect) && (!effect.PlayerOnly || u is Player || u is RemoteControlledCreature); } public void OnEnterZone(Unit unit) diff --git a/src/Perpetuum/Zones/ProximityProbes/PBSRegisterHelper.cs b/src/Perpetuum/Zones/Helpers/PBSRegisterHelper.cs similarity index 100% rename from src/Perpetuum/Zones/ProximityProbes/PBSRegisterHelper.cs rename to src/Perpetuum/Zones/Helpers/PBSRegisterHelper.cs diff --git a/src/Perpetuum/Zones/LandMines/LandMine.cs b/src/Perpetuum/Zones/LandMines/LandMine.cs new file mode 100644 index 000000000..dbaacada1 --- /dev/null +++ b/src/Perpetuum/Zones/LandMines/LandMine.cs @@ -0,0 +1,96 @@ +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Modules.Weapons; +using Perpetuum.Players; +using Perpetuum.Timers; +using Perpetuum.Units; +using Perpetuum.Units.DockingBases; +using Perpetuum.Zones.Beams; +using Perpetuum.Zones.ProximityProbes; +using Perpetuum.Zones.Teleporting; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Perpetuum.Zones.LandMines +{ + public class LandMine : ProximityDeviceBase + { + private const int BeamDistance = 600; + private readonly IntervalTimer gracePeriodInterval = new IntervalTimer(TimeSpan.FromSeconds(15)); + + public int TriggerMass => ED.Options.GetOption("triggerMass"); + + protected override void OnUpdate(TimeSpan time) + { + if (!gracePeriodInterval.Passed) + { + _ = gracePeriodInterval.Update(time); + + return; + } + + base.OnUpdate(time); + } + + public override void OnUnitsFound(List unitsFound) + { + if (unitsFound.Exists(x => x.ActualMass > TriggerMass)) + { + unitsFound[0].Zone.CreateBeam( + BeamType.plant_bomb_explosion,//.timebomb_explosion, + builder => builder + .WithPosition(CurrentPosition) + .WithState(BeamState.Hit) + .WithVisibility(BeamDistance)); + + // There be explosion + IDamageBuilder damageBuilder = DamageInfo.Builder.WithAttacker(this) + .WithDamage(DamageType.Chemical, ED.Config.damage_chemical ?? 5000.0) + .WithDamage(DamageType.Explosive, ED.Config.damage_explosive ?? 5000.0) + .WithDamage(DamageType.Kinetic, ED.Config.damage_kinetic ?? 5000.0) + .WithDamage(DamageType.Thermal, ED.Config.damage_thermal ?? 5000.0) + .WithDamage(DamageType.Toxic, ED.Config.damage_toxic ?? 5000.0) + .WithOptimalRange(2) + .WithFalloff(ED.Config.item_work_range ?? 30.0) + .WithExplosionRadius(ED.Config.explosion_radius ?? 50.0); + + unitsFound[0].Zone.DoAoeDamageAsync(damageBuilder); + + OnDead(unitsFound[0]); + } + } + + #region probe functions + + [CanBeNull] + public override List GetNoticedUnits() + { + return GetVisibleUnits().Select(v => v.Target).OfType().ToList(); + } + + protected override bool IsDetected(Unit target) + { + double range = ED.Config.item_work_range ?? 5.0; + + return IsInRangeOf3D(target, range); + } + + public override void CheckDeploymentAndThrow(IZone zone, Position spawnPosition) + { + zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.LANDMINE_DEPLOY_RANGE_FROM_BASE).Any().ThrowIfTrue(ErrorCodes.NotDeployableNearObject); + zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.LANDMINE_DEPLOY_RANGE_FROM_TELEPORT).Any().ThrowIfTrue(ErrorCodes.TeleportIsInRange); + zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.LANDMINE_DEPLOY_RANGE_FROM_LANDMINE).Any().ThrowIfTrue(ErrorCodes.TooCloseToOtherDevice); + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + #endregion + } +} diff --git a/src/Perpetuum/Zones/LandMines/LandMineDeployer.cs b/src/Perpetuum/Zones/LandMines/LandMineDeployer.cs new file mode 100644 index 000000000..b52c3e4a3 --- /dev/null +++ b/src/Perpetuum/Zones/LandMines/LandMineDeployer.cs @@ -0,0 +1,82 @@ +using Perpetuum.Deployers; +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Groups.Corporations; +using Perpetuum.Players; +using Perpetuum.Units; +using Perpetuum.Units.DockingBases; +using Perpetuum.Zones.Eggs; +using Perpetuum.Zones.Teleporting; +using System; +using System.Linq; + +namespace Perpetuum.Zones.LandMines +{ + public class LandMineDeployer : ItemDeployer + { + private readonly IEntityServices _entityServices; + + public LandMineDeployer(IEntityServices entityServices) : base(entityServices) + { + _entityServices = entityServices; + } + + protected override Unit CreateDeployableItem(IZone zone, Position spawnPosition, Player player) + { + zone.Configuration.Protected.ThrowIfTrue(ErrorCodes.OnlyUnProtectedZonesAllowed); + + var corporation = player.Character.GetPrivateCorporationOrThrow(); + + var maxLandMines = 100; // corporation.GetMaximumProbeAmount(); + corporation.GetLandMineEids().Count().ThrowIfGreaterOrEqual(maxLandMines, ErrorCodes.MaximumAmountOfProbesReached); + + var landMine = (LandMine)_entityServices.Factory.CreateWithRandomEID(DeployableItemEntityDefault); + landMine.CheckDeploymentAndThrow(zone, spawnPosition); //Enforce min-distance separations + landMine.Owner = corporation.Eid; + var zoneStorage = zone.Configuration.GetStorage(); + landMine.Parent = zoneStorage.Eid; + landMine.Save(); + + zone.UnitService.AddUserUnit(landMine, spawnPosition); + + var initialMembers = corporation.GetMembersWithAnyRoles(CorporationRole.CEO, CorporationRole.DeputyCEO).Select(cm => cm.character).ToList(); + initialMembers.Add(player.Character); + + landMine.Init(initialMembers.Distinct()); + landMine.SetDespawnTime(this.ProximityProbeDespawnTime); + + return landMine; + } + + protected override ErrorCodes CanDeploy(IZone zone, Unit unit, Position spawnPosition, Player player) + { + if (zone.Configuration.Protected) + return ErrorCodes.OnlyUnProtectedZonesAllowed; + + if (!zone.Configuration.Terraformable) + { + if (zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.LANDMINE_DEPLOY_RANGE_FROM_BASE).Any()) + return ErrorCodes.NotDeployableNearObject; + + if (zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.LANDMINE_DEPLOY_RANGE_FROM_TELEPORT).Any()) + return ErrorCodes.NotDeployableNearObject; + } + else + { + if (zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.LANDMINE_DEPLOY_RANGE_FROM_LANDMINE).Any()) + return ErrorCodes.TooCloseToOtherDevice; + } + + return base.CanDeploy(zone, unit, spawnPosition, player); + } + + private TimeSpan ProximityProbeDespawnTime + { + get + { + var m = GetPropertyModifier(AggregateField.despawn_time); + return TimeSpan.FromMilliseconds((int)m.Value); + } + } + } +} diff --git a/src/Perpetuum/Zones/Locking/LockHandler.cs b/src/Perpetuum/Zones/Locking/LockHandler.cs index e6c139678..c73fe2d71 100644 --- a/src/Perpetuum/Zones/Locking/LockHandler.cs +++ b/src/Perpetuum/Zones/Locking/LockHandler.cs @@ -10,6 +10,7 @@ using Perpetuum.Units; using Perpetuum.Zones.Blobs; using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.Locking.UnitProperties; namespace Perpetuum.Zones.Locking { @@ -19,32 +20,20 @@ public class LockHandler private readonly ItemProperty _lockingTime; private readonly ItemProperty _maxTargetingRange; private readonly ItemProperty _maxLockedTargets; - private List _locks = new List(); private readonly ConcurrentQueue _newLocks = new ConcurrentQueue(); private readonly ConcurrentQueue _removedLocks = new ConcurrentQueue(); + private List _locks = new List(); private int _dirty; - public LockHandler(Robot owner) - { - _owner = owner; - _lockingTime = new LockingTimeProperty(owner); - owner.AddProperty(_lockingTime); + public double MaxTargetingRange { get { return _maxTargetingRange.Value; } } - _maxTargetingRange = new MaxTargetingRangeProperty(owner); - owner.AddProperty(_maxTargetingRange); + private int MaxLockedTargets { get { return (int)_maxLockedTargets.Value; } } - _maxLockedTargets = new MaxLockedTargetsProperty(owner); - owner.AddProperty(_maxLockedTargets); + public int Count { get { return _locks.Count; } } - if (owner is IBlobableUnit) - { - owner.PropertyChanged += OnOwnerPropertyChanged; - } - } + public event LockEventHandler LockStateChanged; - public double MaxTargetingRange { get { return _maxTargetingRange.Value; } } - private int MaxLockedTargets { get { return (int) _maxLockedTargets.Value; } } - public int Count { get { return _locks.Count; } } + public event LockEventHandler LockError; public List Locks { @@ -56,67 +45,55 @@ public bool HasFreeLockSlot get { return Count < MaxLockedTargets; } } - private void OnOwnerPropertyChanged(Item unit, ItemProperty property) + public LockHandler(Robot owner) { - if (property.Field != AggregateField.blob_effect) - return; + _owner = owner; + _lockingTime = new LockingTimeProperty(owner); + owner.AddProperty(_lockingTime); + _maxTargetingRange = new MaxTargetingRangeProperty(owner); + owner.AddProperty(_maxTargetingRange); + _maxLockedTargets = new MaxLockedTargetsProperty(owner); + owner.AddProperty(_maxLockedTargets); - _lockingTime.Update(); - _maxTargetingRange.Update(); + if (owner is IBlobableUnit) + { + owner.PropertyChanged += OnOwnerPropertyChanged; + } } public void AddLock(long targetEid, bool isPrimary) { var targetUnit = _owner.Zone?.GetUnit(targetEid); + if (targetUnit == null) + { return; + } AddLock(targetUnit,isPrimary); } public void AddLock(Unit target, bool isPrimary) { - AddLock(new UnitLock(_owner) { Target = target, Primary = isPrimary }); - } - - public void AddLock(Lock newLock) - { - _newLocks.Enqueue(newLock); - Interlocked.Exchange(ref _dirty, 1); - } - - private void RemoveLock(Lock @lock) - { - _removedLocks.Enqueue(@lock); - Interlocked.Exchange(ref _dirty, 1); - } - - private void ProcessRemovedLocks(IList locks) - { - Lock removedLock; - while (_removedLocks.TryDequeue(out removedLock)) + AddLock(new UnitLock(_owner) { - locks.Remove(removedLock); - } + Target = target, + Primary = isPrimary, + }); } - public event LockEventHandler LockStateChanged; - - private void OnLockStateChanged(Lock @lock) + public void AddLock(Position position, bool isPrimary) { - if (@lock.State == LockState.Disabled) + AddLock(new TerrainLock(_owner, position) { - RemoveLock(@lock); - } - - LockStateChanged?.Invoke(@lock); + Primary = isPrimary, + }); } - public event LockEventHandler LockError; - - private void OnLockError(Lock @lock, ErrorCodes error) + public void AddLock(Lock newLock) { - LockError?.Invoke(@lock, error); + _newLocks.Enqueue(newLock); + Interlocked.Exchange(ref _dirty, 1); } public void Update(TimeSpan time) @@ -140,76 +117,30 @@ public void Update(TimeSpan time) @lock.Update(time); if (!ValidateLock(@lock)) - @lock.Cancel(); - } - } - - private void ProcessNewLocks(IList locks) - { - Lock newLock; - while (_newLocks.TryDequeue(out newLock)) - { - if (locks.Any(l => l.Equals(newLock))) - continue; - // if you are a tooladmin then lock up anything you want. - // this is easier than making special bots to work with terrain. - if (locks.Count >= MaxLockedTargets && _owner.GetCharacter().AccessLevel != AccessLevel.toolAdmin) - { - OnLockError(newLock,ErrorCodes.MaxLockedTargetExceed); - continue; - } - - if (!ValidateLock(newLock)) - continue; - - if (newLock.Primary) { - var currentPrimaryLock = locks.FirstOrDefault(l => l.Primary); - if (currentPrimaryLock != null) - currentPrimaryLock.Primary = false; + @lock.Cancel(); } - - - - locks.Add(newLock); - - newLock.Changed += OnLockStateChanged; - - var lockingTime = TimeSpan.Zero; - - var terrainLock = newLock as TerrainLock; - if (terrainLock == null) - lockingTime = TimeSpan.FromMilliseconds(_lockingTime.Value); - - newLock.Start(lockingTime); } } - private bool ValidateLock(Lock newLock) - { - var validator = new LockValidator(this); - newLock.AcceptVisitor(validator); - - if (validator.Error == ErrorCodes.NoError) - return true; - - OnLockError(newLock, validator.Error); - return false; - } - public void SetPrimaryLock(Lock primaryLock) { var currentPrimaryLock = GetPrimaryLock(); + if (currentPrimaryLock != null) { if (currentPrimaryLock == primaryLock) + { return; + } currentPrimaryLock.Primary = false; } if (primaryLock != null) + { primaryLock.Primary = true; + } } public void SetPrimaryLock(long lockId) @@ -222,7 +153,9 @@ public void SetPrimaryLock(long lockId) public Lock GetLock(long lockId) { if (lockId == 0) + { return null; + } return _locks.FirstOrDefault(l => l.Id == lockId); } @@ -230,6 +163,7 @@ public Lock GetLock(long lockId) public void CancelLock(long lockId) { var l = GetLock(lockId); + l?.Cancel(); } @@ -247,6 +181,11 @@ public Lock GetPrimaryLock() return _locks.FirstOrDefault(l => l.Primary); } + public IEnumerable GetSecondaryLocks() + { + return _locks.Where(l => !l.Primary); + } + public bool IsLocked(Unit unit) { return _locks.OfType().Any(l => unit.Eid == l.Target.Eid); @@ -259,9 +198,9 @@ public UnitLock GetLockByUnit(Unit unit) } [CanBeNull] - private UnitLock GetLockByEid(long unitEid) + public TerrainLock GetLockByPosition(Position position) { - return _locks.OfType().FirstOrDefault(l => l.Target.Eid == unitEid); + return GetLockByPositionString(position.ToString()); } public bool IsInLockingRange(Unit target) @@ -274,66 +213,122 @@ public bool IsInLockingRange(Position targetPosition) return _owner.CurrentPosition.IsInRangeOf3D(targetPosition, MaxTargetingRange); } - private class LockingTimeProperty : UnitProperty + private void OnOwnerPropertyChanged(Item unit, ItemProperty property) { - public LockingTimeProperty(Unit owner) - : base(owner, AggregateField.locking_time, - AggregateField.locking_time_modifier, - // effektek - AggregateField.effect_sensor_booster_locking_time_modifier, - AggregateField.effect_sensor_dampener_locking_time_modifier, - AggregateField.effect_locking_time_modifier) { } - - protected override double CalculateValue() + if (property.Field != AggregateField.blob_effect) { - var v = base.CalculateValue(); + return; + } - var blobableUnit = owner as IBlobableUnit; - blobableUnit?.BlobHandler.ApplyBlobPenalty(ref v, -5); + _lockingTime.Update(); + _maxTargetingRange.Update(); + } - return v; - } + private void RemoveLock(Lock @lock) + { + _removedLocks.Enqueue(@lock); + Interlocked.Exchange(ref _dirty, 1); } - private class MaxLockedTargetsProperty : UnitProperty + private void ProcessRemovedLocks(IList locks) { - public MaxLockedTargetsProperty(Unit owner) : base(owner, AggregateField.locked_targets_max) + Lock removedLock; + + while (_removedLocks.TryDequeue(out removedLock)) { + locks.Remove(removedLock); } + } - protected override double CalculateValue() + private void OnLockError(Lock @lock, ErrorCodes error) + { + LockError?.Invoke(@lock, error); + } + + private void OnLockStateChanged(Lock @lock) + { + if (@lock.State == LockState.Disabled) { - var v = base.CalculateValue(); + RemoveLock(@lock); + } - if (owner.GetCharacter() == Character.None) - return v; + LockStateChanged?.Invoke(@lock); + } - var lockedTargetsMaxBonus = owner.GetPropertyModifier(AggregateField.locked_targets_max_bonus); - v = Math.Min(lockedTargetsMaxBonus.Value + 1, v); + private bool ValidateLock(Lock newLock) + { + var validator = new LockValidator(this); - return v; + newLock.AcceptVisitor(validator); + + if (validator.Error == ErrorCodes.NoError) + { + return true; } + + OnLockError(newLock, validator.Error); + + return false; } - private class MaxTargetingRangeProperty : UnitProperty + private void ProcessNewLocks(IList locks) { - public MaxTargetingRangeProperty(Unit owner) - : base(owner, AggregateField.locking_range, - AggregateField.locking_range_modifier, - //effektek - AggregateField.effect_sensor_booster_locking_range_modifier, - AggregateField.effect_sensor_dampener_locking_range_modifier, - AggregateField.effect_locking_range_modifier) { } - - protected override double CalculateValue() + Lock newLock; + + while (_newLocks.TryDequeue(out newLock)) { - var v = base.CalculateValue(); + if (locks.Any(l => l.Equals(newLock))) + { + continue; + } + + // if you are a tooladmin then lock up anything you want. + // this is easier than making special bots to work with terrain. + if (locks.Count >= MaxLockedTargets && _owner.GetCharacter().AccessLevel != AccessLevel.toolAdmin) + { + OnLockError(newLock, ErrorCodes.MaxLockedTargetExceed); - var blobableUnit = owner as IBlobableUnit; - blobableUnit?.BlobHandler.ApplyBlobPenalty(ref v, 0.5); + continue; + } - return v; + if (!ValidateLock(newLock)) + continue; + + if (newLock.Primary) + { + var currentPrimaryLock = locks.FirstOrDefault(l => l.Primary); + + if (currentPrimaryLock != null) + { + currentPrimaryLock.Primary = false; + } + } + + locks.Add(newLock); + newLock.Changed += OnLockStateChanged; + + var lockingTime = TimeSpan.Zero; + var terrainLock = newLock as TerrainLock; + + if (terrainLock == null) + { + lockingTime = TimeSpan.FromMilliseconds(_lockingTime.Value); + } + + newLock.Start(lockingTime); } } + + [CanBeNull] + private UnitLock GetLockByEid(long unitEid) + { + return _locks.OfType().FirstOrDefault(l => l.Target.Eid == unitEid); + } + + [CanBeNull] + private TerrainLock GetLockByPositionString(string positionString) + { + return _locks.OfType().FirstOrDefault(l => l.Location.ToString() == positionString); + } } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/Locking/Locks/TerraformDirection.cs b/src/Perpetuum/Zones/Locking/Locks/TerraformDirection.cs new file mode 100644 index 000000000..f43fb946d --- /dev/null +++ b/src/Perpetuum/Zones/Locking/Locks/TerraformDirection.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.Locking.Locks +{ + public enum TerraformDirection + { + Undefined, + Lower, + Raise, + } +} diff --git a/src/Perpetuum/Zones/Locking/Locks/TerrainLock.cs b/src/Perpetuum/Zones/Locking/Locks/TerrainLock.cs index a34cf27f7..2cf3d723e 100644 --- a/src/Perpetuum/Zones/Locking/Locks/TerrainLock.cs +++ b/src/Perpetuum/Zones/Locking/Locks/TerrainLock.cs @@ -1,52 +1,13 @@ -using Perpetuum.Builders; using Perpetuum.Robots; using Perpetuum.Zones.Terrains.Terraforming; namespace Perpetuum.Zones.Locking.Locks { - public enum TerraformDirection - { - Undefined, - Lower, - Raise - } - - public class TerrainLockParametersPacketBuilder : IBuilder - { - private readonly TerrainLock _terrainLock; - - public TerrainLockParametersPacketBuilder(TerrainLock terrainLock) - { - _terrainLock = terrainLock; - } - - public Packet Build() - { - var packet = new Packet(ZoneCommand.TerrainLockParameters); - - packet.AppendLong(_terrainLock.Id); - packet.AppendByte((byte) _terrainLock.TerraformType); - packet.AppendByte((byte) _terrainLock.TerraformDirection); - packet.AppendByte((byte) _terrainLock.Radius); - packet.AppendByte((byte) _terrainLock.Falloff); - - return packet; - } - } - - public class TerrainLock : Lock { private const int MAX_RADIUS = 5; - - private int _radius; - public TerrainLock(Robot owner,Position location) : base(owner) - { - Location = location; - } - public TerraformType TerraformType { get; set; } public TerraformDirection TerraformDirection { get; set; } @@ -58,6 +19,11 @@ public int Radius public int Falloff { get; set; } + public TerrainLock(Robot owner,Position location) : base(owner) + { + Location = location; + } + public override void AcceptVisitor(ILockVisitor visitor) { visitor.VisitTerrainLock(this); @@ -68,9 +34,12 @@ public override void AcceptVisitor(ILockVisitor visitor) public override bool Equals(Lock other) { if (base.Equals(other)) + { return true; + } var terrainLockTarget = other as TerrainLock; + return terrainLockTarget != null && Equals(Location, terrainLockTarget.Location); } } diff --git a/src/Perpetuum/Zones/Locking/Locks/TerrainLockParametersPacketBuilder.cs b/src/Perpetuum/Zones/Locking/Locks/TerrainLockParametersPacketBuilder.cs new file mode 100644 index 000000000..b8ac3d8a9 --- /dev/null +++ b/src/Perpetuum/Zones/Locking/Locks/TerrainLockParametersPacketBuilder.cs @@ -0,0 +1,27 @@ +using Perpetuum.Builders; + +namespace Perpetuum.Zones.Locking.Locks +{ + public class TerrainLockParametersPacketBuilder : IBuilder + { + private readonly TerrainLock _terrainLock; + + public TerrainLockParametersPacketBuilder(TerrainLock terrainLock) + { + _terrainLock = terrainLock; + } + + public Packet Build() + { + var packet = new Packet(ZoneCommand.TerrainLockParameters); + + packet.AppendLong(_terrainLock.Id); + packet.AppendByte((byte)_terrainLock.TerraformType); + packet.AppendByte((byte)_terrainLock.TerraformDirection); + packet.AppendByte((byte)_terrainLock.Radius); + packet.AppendByte((byte)_terrainLock.Falloff); + + return packet; + } + } +} diff --git a/src/Perpetuum/Zones/Locking/UnitProperties/LockingTimeProperty.cs b/src/Perpetuum/Zones/Locking/UnitProperties/LockingTimeProperty.cs new file mode 100644 index 000000000..2164eafa4 --- /dev/null +++ b/src/Perpetuum/Zones/Locking/UnitProperties/LockingTimeProperty.cs @@ -0,0 +1,27 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Units; +using Perpetuum.Zones.Blobs; + +namespace Perpetuum.Zones.Locking.UnitProperties +{ + public class LockingTimeProperty : UnitProperty + { + public LockingTimeProperty(Unit owner) + : base(owner, AggregateField.locking_time, + AggregateField.locking_time_modifier, + AggregateField.effect_sensor_booster_locking_time_modifier, + AggregateField.effect_sensor_dampener_locking_time_modifier, + AggregateField.effect_locking_time_modifier) + { } + + protected override double CalculateValue() + { + var v = base.CalculateValue(); + + var blobableUnit = owner as IBlobableUnit; + blobableUnit?.BlobHandler.ApplyBlobPenalty(ref v, -5); + + return v; + } + } +} diff --git a/src/Perpetuum/Zones/Locking/UnitProperties/MaxLockedTargetsProperty.cs b/src/Perpetuum/Zones/Locking/UnitProperties/MaxLockedTargetsProperty.cs new file mode 100644 index 000000000..29c84ff03 --- /dev/null +++ b/src/Perpetuum/Zones/Locking/UnitProperties/MaxLockedTargetsProperty.cs @@ -0,0 +1,31 @@ +using Perpetuum.Accounting.Characters; +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Units; +using System; + +namespace Perpetuum.Zones.Locking.UnitProperties +{ + public class MaxLockedTargetsProperty : UnitProperty + { + public MaxLockedTargetsProperty(Unit owner) : base(owner, AggregateField.locked_targets_max) + { + } + + protected override double CalculateValue() + { + var v = base.CalculateValue(); + + if (owner.GetCharacter() == Character.None) + { + return v; + } + + var lockedTargetsMaxBonus = owner.GetPropertyModifier(AggregateField.locked_targets_max_bonus); + + v = Math.Min(lockedTargetsMaxBonus.Value + 1, v); + + return v; + } + } +} diff --git a/src/Perpetuum/Zones/Locking/UnitProperties/MaxTargetingRangeProperty.cs b/src/Perpetuum/Zones/Locking/UnitProperties/MaxTargetingRangeProperty.cs new file mode 100644 index 000000000..b85d3e82d --- /dev/null +++ b/src/Perpetuum/Zones/Locking/UnitProperties/MaxTargetingRangeProperty.cs @@ -0,0 +1,27 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Units; +using Perpetuum.Zones.Blobs; + +namespace Perpetuum.Zones.Locking.UnitProperties +{ + public class MaxTargetingRangeProperty : UnitProperty + { + public MaxTargetingRangeProperty(Unit owner) + : base(owner, AggregateField.locking_range, + AggregateField.locking_range_modifier, + AggregateField.effect_sensor_booster_locking_range_modifier, + AggregateField.effect_sensor_dampener_locking_range_modifier, + AggregateField.effect_locking_range_modifier) + { } + + protected override double CalculateValue() + { + var v = base.CalculateValue(); + var blobableUnit = owner as IBlobableUnit; + + blobableUnit?.BlobHandler.ApplyBlobPenalty(ref v, 0.5); + + return v; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/ActiveAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/ActiveAI.cs new file mode 100644 index 000000000..92a3aa2c2 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/ActiveAI.cs @@ -0,0 +1,138 @@ +using Perpetuum.Timers; +using Perpetuum.Units; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.Locking; +using Perpetuum.Zones.Terrains; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class ActiveAI : TurretAI + { + private readonly Turret _turret; + private readonly List _moduleActivators; + private readonly TimeSpan _minCycleTime; + private readonly IntervalTimer _primarySelectTimer = new IntervalTimer(0); + + public ActiveAI(Turret turret) : base(turret) + { + _turret = turret; + + _moduleActivators = new List(); + + _minCycleTime = TimeSpan.FromSeconds(5); + + foreach (var module in _turret.ActiveModules) + { + _moduleActivators.Add(new ModuleActivator(module)); + _minCycleTime = _minCycleTime.Min(module.CycleTime); + } + } + + public override void Enter() + { + foreach (var unitVisibility in _turret.GetVisibleUnits()) + { + _turret.LockHostile(unitVisibility.Target); + } + + base.Enter(); + } + + public override void Exit() + { + _turret.StopAllModules(); + _turret.ResetLocks(); + base.Exit(); + } + + public override void AttackHostile(Unit unit) + { + if (!_turret.IsHostile(unit)) + { + return; + } + + _turret.LockHostile(unit); + base.AttackHostile(unit); + } + + public override void Update(TimeSpan time) + { + if (!SelectPrimaryTarget(time)) + { + return; + } + + foreach (var activator in _moduleActivators) + { + activator.Update(time); + } + + base.Update(time); + } + + private bool SelectPrimaryTarget(TimeSpan time) + { + var locks = _turret.GetLocks().Where(l => l.State == LockState.Locked).ToArray(); + + if (locks.Length <= 0) + { + return false; + } + + _primarySelectTimer.Update(time); + + if (_primarySelectTimer.Passed) + { + _primarySelectTimer.Interval = FastRandom.NextTimeSpan(_minCycleTime); + + var validLocks = new List(); + + foreach (var l in locks) + { + var unitLock = (UnitLock)l; + + if (unitLock.Primary) + { + continue; + } + + var visibility = _turret.GetVisibility(unitLock.Target); + + if (visibility == null) + { + continue; + } + + var r = visibility.GetLineOfSight(false); + + if (r != null && r.hit && (r.blockingFlags & BlockingFlags.Plant) == 0) + { + continue; + } + + validLocks.Add(unitLock); + } + + if (validLocks.Count > 0) + { + var newPrimary = validLocks.RandomElement(); + + _turret.SetPrimaryLock(newPrimary); + + return true; + } + } + + return locks.Any(l => l.Primary); + } + + public override void ToActiveAI() + { + // nem csinal semmit + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/AggressorAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/AggressorAI.cs new file mode 100644 index 000000000..13811aa2a --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/AggressorAI.cs @@ -0,0 +1,39 @@ +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class AggressorAI : CombatAI + { + public AggressorAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Exit() + { + this.source?.Cancel(); + + base.Exit(); + } + + public override void Update(TimeSpan time) + { + if (!smartCreature.IsInHomeRange) + { + smartCreature.AI.Push(new HomingAI(smartCreature)); + + return; + } + + if (!smartCreature.ThreatManager.IsThreatened) + { + ReturnToHomePosition(); + + return; + } + + this.UpdateHostile(time); + + base.Update(time); + } + + protected override void ToAggressorAI() { } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/BaseAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/BaseAI.cs new file mode 100644 index 000000000..520161bd3 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/BaseAI.cs @@ -0,0 +1,63 @@ +using Perpetuum.Log; +using Perpetuum.StateMachines; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using Perpetuum.Zones.NpcSystem.AI.CombatDrones; +using System; +using System.Diagnostics; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public abstract class BaseAI : IState + { + protected readonly SmartCreature smartCreature; + + protected BaseAI(SmartCreature smartCreature) + { + this.smartCreature = smartCreature; + } + + public virtual void Enter() + { + WriteLog("enter state = " + GetType().Name); + } + + public virtual void Exit() + { + smartCreature.StopMoving(); + WriteLog("exit state = " + GetType().Name); + } + + public abstract void Update(TimeSpan time); + + protected virtual void ToHomeAI() + { + this.smartCreature.AI.Push(new HomingAI(smartCreature)); + } + + protected virtual void ToAggressorAI() + { + if (this.smartCreature.Behavior.Type == BehaviorType.Passive) + { + return; + } + + this.smartCreature.AI.Push(new AggressorAI(smartCreature)); + } + + protected virtual void ToAttackCombatDroneAI() + { + this.smartCreature.AI.Push(new AttackCombatDroneAI(smartCreature)); + } + + [Conditional("DEBUG")] + protected void WriteLog(string message) + { + Logger.DebugInfo($"SmartCreatureAI: {message}"); + } + + protected virtual void ToEscortCombatDroneAI() + { + this.smartCreature.AI.Push(new EscortCombatDroneAI(smartCreature)); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/AggressiveBehavior.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/AggressiveBehavior.cs new file mode 100644 index 000000000..4d701aabf --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/AggressiveBehavior.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public class AggressiveBehavior : Behavior + { + public AggressiveBehavior() : base(BehaviorType.Aggressive) + { + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/Behavior.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/Behavior.cs new file mode 100644 index 000000000..cd5181937 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/Behavior.cs @@ -0,0 +1,31 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public class Behavior + { + public BehaviorType Type { get; private set; } + + protected Behavior(BehaviorType type) + { + Type = type; + } + + public static Behavior Create(BehaviorType type) + { + switch (type) + { + case BehaviorType.Neutral: + return new NeutralBehavior(); + case BehaviorType.Aggressive: + return new AggressiveBehavior(); + case BehaviorType.Passive: + return new PassiveBehavior(); + case BehaviorType.RemoteControlledTurret: + return new RemoteControlledTurretBehavior(); + case BehaviorType.RemoteControlledDrone: + return new RemoteControlledDroneBehavior(); + default: + return new PassiveBehavior(); + } + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/BehaviorType.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/BehaviorType.cs new file mode 100644 index 000000000..cf90931a3 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/BehaviorType.cs @@ -0,0 +1,11 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public enum BehaviorType + { + Passive, + Neutral, + Aggressive, + RemoteControlledTurret, + RemoteControlledDrone, + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/NeutralBehavior.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/NeutralBehavior.cs new file mode 100644 index 000000000..64a412026 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/NeutralBehavior.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public class NeutralBehavior : Behavior + { + public NeutralBehavior() : base(BehaviorType.Neutral) + { + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/PassiveBehavior.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/PassiveBehavior.cs new file mode 100644 index 000000000..43e695fb2 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/PassiveBehavior.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public class PassiveBehavior : Behavior + { + public PassiveBehavior() : base(BehaviorType.Passive) + { + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/RemoteControlledDroneBehavior.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/RemoteControlledDroneBehavior.cs new file mode 100644 index 000000000..dbb94b943 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/RemoteControlledDroneBehavior.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public class RemoteControlledDroneBehavior : Behavior + { + public RemoteControlledDroneBehavior() : base(BehaviorType.RemoteControlledDrone) + { + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/RemoteControlledTurretBehavior.cs b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/RemoteControlledTurretBehavior.cs new file mode 100644 index 000000000..3e2ca33c9 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Behaviors/RemoteControlledTurretBehavior.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.AI.Behaviors +{ + public class RemoteControlledTurretBehavior : Behavior + { + public RemoteControlledTurretBehavior() : base(BehaviorType.RemoteControlledTurret) + { + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs b/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs new file mode 100644 index 000000000..01f85849e --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/BodyPullThreatHelper.cs @@ -0,0 +1,183 @@ +using Perpetuum.EntityFramework; +using Perpetuum.Modules.Weapons; +using Perpetuum.Players; +using Perpetuum.Units; +using Perpetuum.Zones.Eggs; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using Perpetuum.Zones.NpcSystem.ThreatManaging; +using Perpetuum.Zones.RemoteControl; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class BodyPullThreatHelper : + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor + { + private readonly SmartCreature smartCreature; + + public BodyPullThreatHelper(SmartCreature smartCreature) + { + this.smartCreature = smartCreature; + } + + public void Visit(Player player) + { + if (smartCreature.Behavior.Type != BehaviorType.Aggressive && + smartCreature.Behavior.Type != BehaviorType.RemoteControlledTurret && + smartCreature.Behavior.Type != BehaviorType.RemoteControlledDrone) + { + return; + } + + if (player.HasTeleportSicknessEffect) + { + return; + } + + if (smartCreature is RemoteControlledCreature remoteControlledCreature && + (remoteControlledCreature.CommandRobot is Player) && + player.Zone.Configuration.IsAlpha && + !player.HasPvpEffect && + !remoteControlledCreature.CommandRobot.HasPvpEffect) + { + return; + } + + if (smartCreature.ThreatManager.Hostiles.Any(h => h.Unit.Eid == player.Eid)) + { + return; + } + + if (!smartCreature.IsInAggroRange(player)) + { + return; + } + + double threat = Threat.BODY_PULL + FastRandom.NextDouble(0, 5); + + smartCreature.AddThreat(player, new Threat(ThreatType.Bodypull, threat)); + } + + public void Visit(AreaBomb bomb) + { + if (!smartCreature.IsInAggroRange(bomb)) + { + return; + } + + if (!smartCreature.ActiveModules.Any(m => m is WeaponModule)) + { + return; + } + + Flocks.ISmartCreatureGroup group = smartCreature.Group; + + if (group != null && group.Members.Any(m => m.ThreatManager.Contains(bomb))) + { + return; + } + + double threat = Threat.BODY_PULL; + + if (smartCreature.ThreatManager.IsThreatened) + { + Hostile h = smartCreature.ThreatManager.GetMostHatedHostile(); + + if (h != null) + { + threat = h.Threat * 100; + } + } + + smartCreature.AddThreat(bomb, new Threat(ThreatType.Bodypull, threat + FastRandom.NextDouble(0, 5))); + } + + public void Visit(Npc npc) + { + if (smartCreature.Behavior.Type != BehaviorType.RemoteControlledTurret && + smartCreature.Behavior.Type != BehaviorType.RemoteControlledDrone) + { + return; + } + + if (!smartCreature.ActiveModules.Any(m => m is WeaponModule)) + { + return; + } + + if (smartCreature.ThreatManager.Hostiles.Any(h => h.Unit.Eid == npc.Eid)) + { + return; + } + + if (!smartCreature.IsInAggroRange(npc)) + { + return; + } + + double threat = Threat.BODY_PULL + FastRandom.NextDouble(0, 5); + + smartCreature.AddThreat(npc, new Threat(ThreatType.Bodypull, threat)); + } + + public void Visit(SentryTurret sentryTurret) + { + if (smartCreature.Behavior.Type != BehaviorType.RemoteControlledTurret && + smartCreature.Behavior.Type != BehaviorType.RemoteControlledDrone) + { + return; + } + + if (!smartCreature.ActiveModules.Any(m => m is WeaponModule)) + { + return; + } + + if (smartCreature.ThreatManager.Hostiles.Any(h => h.Unit.Eid == sentryTurret.Eid)) + { + return; + } + + if (!smartCreature.IsInAggroRange(sentryTurret)) + { + return; + } + + double threat = Threat.BODY_PULL + FastRandom.NextDouble(0, 5); + + smartCreature.AddThreat(sentryTurret, new Threat(ThreatType.Bodypull, threat)); + } + + public void Visit(CombatDrone combatDrone) + { + if (smartCreature.Behavior.Type != BehaviorType.RemoteControlledTurret && + smartCreature.Behavior.Type != BehaviorType.RemoteControlledDrone) + { + return; + } + + if (!smartCreature.ActiveModules.Any(m => m is WeaponModule)) + { + return; + } + + if (smartCreature.ThreatManager.Hostiles.Any(h => h.Unit.Eid == combatDrone.Eid)) + { + return; + } + + if (!smartCreature.IsInAggroRange(combatDrone)) + { + return; + } + + double threat = Threat.BODY_PULL + FastRandom.NextDouble(0, 5); + + smartCreature.AddThreat(combatDrone, new Threat(ThreatType.Bodypull, threat)); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/CombatAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/CombatAI.cs new file mode 100644 index 000000000..4b5b9eb07 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/CombatAI.cs @@ -0,0 +1,485 @@ +using Perpetuum.Collections; +using Perpetuum.Modules.Weapons; +using Perpetuum.PathFinders; +using Perpetuum.Timers; +using Perpetuum.Units; +using Perpetuum.Zones.Locking; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.Movements; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using Perpetuum.Zones.NpcSystem.TargettingStrategies; +using Perpetuum.Zones.NpcSystem.ThreatManaging; +using Perpetuum.Zones.Terrains; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class CombatAI : BaseAI + { + private const int UpdateFrequency = 1650; + private const int Sqrt2 = 141; + private const int Weight = 1000; + private readonly IntervalTimer processHostilesTimer = new IntervalTimer(UpdateFrequency); + private readonly IntervalTimer primarySelectTimer = new IntervalTimer(UpdateFrequency); + private List moduleActivators; + private TimeSpan hostilesUpdateFrequency = TimeSpan.FromMilliseconds(UpdateFrequency); + private CombatPrimaryLockSelectionStrategySelector stratSelector; + private Position lastTargetPosition; + private PathMovement movement; + private PathMovement nextMovement; + + public CancellationTokenSource source; + + public bool IsNpcHasMissiles { get; set; } = false; + + public CombatAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Enter() + { + stratSelector = InitSelector(); + moduleActivators = this.smartCreature.ActiveModules + .Select(m => new ModuleActivator(m)) + .ToList(); + IsNpcHasMissiles = this.smartCreature.ActiveModules + .OfType() + .Any(); + processHostilesTimer.Update(hostilesUpdateFrequency); + primarySelectTimer.Update(hostilesUpdateFrequency); + + base.Enter(); + } + + public override void Update(TimeSpan time) + { + UpdateHostiles(time); + UpdatePrimaryTarget(time); + RunModules(time); + } + + protected virtual CombatPrimaryLockSelectionStrategySelector InitSelector() + { + return CombatPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(CombatPrimaryLockSelectionStrategy.Hostile, 9) + .WithStrategy(CombatPrimaryLockSelectionStrategy.Random, 1) + .Build(); + } + + protected void UpdateHostiles(TimeSpan time) + { + processHostilesTimer.Update(time); + + if (processHostilesTimer.Passed) + { + processHostilesTimer.Reset(); + ProcessHostiles(); + } + } + + protected void UpdatePrimaryTarget(TimeSpan time) + { + primarySelectTimer.Update(time); + + if (primarySelectTimer.Passed) + { + var success = SelectPrimaryTarget(); + SetPrimaryUpdateDelay(success); + } + } + + protected void RunModules(TimeSpan time) + { + foreach (var activator in moduleActivators) + { + activator.Update(time); + } + } + + protected virtual TimeSpan SetPrimaryDwellTime() + { + return FastRandom.NextTimeSpan(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10)); + } + + protected virtual void SetPrimaryUpdateDelay(bool newPrimary) + { + if (newPrimary) + { + primarySelectTimer.Interval = SetPrimaryDwellTime(); + } + else if (GetValidLocks().Length > 0) + { + primarySelectTimer.Interval = TimeSpan.FromSeconds(1); + } + else if (this.smartCreature.GetLocks().Count > 0) + { + primarySelectTimer.Interval = TimeSpan.FromSeconds(1.5); + } + else + { + primarySelectTimer.Interval = TimeSpan.FromSeconds(3.5); + } + } + + protected bool IsAttackable(Hostile hostile) + { + if (!hostile.Unit.InZone) + { + return false; + } + + if (hostile.Unit.States.Dead) + { + return false; + } + + if (!hostile.Unit.IsLockable) + { + return false; + } + + if (hostile.Unit.IsAttackable != ErrorCodes.NoError) + { + return false; + } + + if (hostile.Unit.IsInvulnerable) + { + return false; + } + + if (this.smartCreature.Behavior.Type == BehaviorType.Neutral && hostile.IsExpired) + { + return false; + } + + var isVisible = this.smartCreature.IsVisible(hostile.Unit); + + if (!isVisible) + { + return false; + } + + return true; + } + + protected virtual void ProcessHostiles() + { + var hostileEnumerator = this.smartCreature.ThreatManager.Hostiles.GetEnumerator(); + + while (hostileEnumerator.MoveNext()) + { + var hostile = hostileEnumerator.Current; + + if (!IsAttackable(hostile)) + { + this.smartCreature.ThreatManager.Remove(hostile); + this.smartCreature.AddPseudoThreat(hostile.Unit); + + continue; + } + + if (!this.smartCreature.IsInLockingRange(hostile.Unit)) + { + continue; + } + + SetLockForHostile(hostile); + } + } + + protected bool TryMakeFreeLockSlotFor(Hostile hostile) + { + if (this.smartCreature.HasFreeLockSlot) + { + return true; + } + + this.smartCreature.ThreatManager.Hostiles + .Where(x => x.Threat == 0) + .ForEach(x => this.smartCreature.GetLockByUnit(x.Unit).Cancel()); + + var weakestLock = this.smartCreature.ThreatManager.Hostiles + .SkipWhile(x => x != hostile) + .Skip(1) + .Select(x => this.smartCreature.GetLockByUnit(x.Unit)) + .LastOrDefault(); + + if (weakestLock == null) + { + return false; + } + + weakestLock.Cancel(); + + return true; + } + + protected Hostile GetPrimaryOrMostHatedHostile() + { + var primaryHostile = GetPrimaryHostile(); + + if (primaryHostile != null) + { + return primaryHostile; + } + + return this.smartCreature.ThreatManager.GetMostHatedHostile(); + } + + protected Hostile GetPrimaryHostile() + { + return this.smartCreature.ThreatManager.Hostiles + .Where(h => h.Unit == (this.smartCreature.GetPrimaryLock() as UnitLock)?.Target) + .FirstOrDefault(); + } + + protected virtual void ReturnToHomePosition() + { + smartCreature.AI.Pop(); + smartCreature.AI.Push(new HomingAI(smartCreature)); + this.WriteLog("Enter evade mode."); + } + + protected Task> FindNewAttackPositionAsync(Unit hostile) + { + this.source?.Cancel(); + this.source = new CancellationTokenSource(); + + return Task.Run(() => FindNewAttackPosition(hostile, this.source.Token), this.source.Token); + } + + protected void UpdateHostile(TimeSpan time, bool moveThreatToPseudoThreat = true) + { + var mostHated = GetPrimaryOrMostHatedHostile(); + + if (mostHated == null) + { + return; + } + + if (!mostHated.Unit.CurrentPosition.IsEqual2D(this.lastTargetPosition)) + { + this.lastTargetPosition = mostHated.Unit.CurrentPosition; + + var findNewTargetPosition = false; + + if (!smartCreature.IsInRangeOf3D(mostHated.Unit, smartCreature.BestActionRange)) + { + findNewTargetPosition = true; + } + else + { + var visibility = smartCreature.GetVisibility(mostHated.Unit); + + if (visibility != null) + { + var r = visibility.GetLineOfSight(this.IsNpcHasMissiles); + + if (r.hit) + { + findNewTargetPosition = true; + } + } + } + + if (findNewTargetPosition) + { + FindNewAttackPositionAsync(mostHated.Unit).ContinueWith(t => + { + if (t.IsCanceled) + { + return; + } + + var path = t.Result; + + if (path == null) + { + if (moveThreatToPseudoThreat) + { + smartCreature.ThreatManager.Remove(mostHated); + smartCreature.AddPseudoThreat(mostHated.Unit); + } + + return; + } + + Interlocked.Exchange(ref this.nextMovement, new PathMovement(path)); + }); + } + } + + if (this.nextMovement != null) + { + movement = Interlocked.Exchange(ref this.nextMovement, null); + movement.Start(this.smartCreature); + } + + this.movement?.Update(this.smartCreature, time); + } + + private void SetLockForHostile(Hostile hostile) + { + var mostHated = GetPrimaryOrMostHatedHostile() == hostile; + var combatLock = this.smartCreature.GetLockByUnit(hostile.Unit); + + if (combatLock == null) + { + if (TryMakeFreeLockSlotFor(hostile)) + { + this.smartCreature.AddLock(hostile.Unit, mostHated); + } + } + else + { + if (mostHated && !combatLock.Primary) + { + this.smartCreature.SetPrimaryLock(combatLock.Id); + } + } + } + + private bool IsLockValidTarget(UnitLock unitLock) + { + if (unitLock == null || unitLock.State != LockState.Locked) + { + return false; + } + + var visibility = this.smartCreature.GetVisibility(unitLock.Target); + + if (visibility == null) + { + return false; + } + + var r = visibility.GetLineOfSight(IsNpcHasMissiles); + + if (r != null && r.hit && (r.blockingFlags & BlockingFlags.Plant) == 0) + { + return false; + } + + return unitLock.Target.GetDistance(this.smartCreature) < this.smartCreature.MaxActionRange; + } + + private UnitLock[] GetValidLocks() + { + return this.smartCreature + .GetLocks() + .Select(l => (UnitLock)l) + .Where(u => IsLockValidTarget(u)) + .ToArray(); + } + + private bool SelectPrimaryTarget() + { + var validLocks = GetValidLocks(); + + if (validLocks.Length < 1) + { + return false; + } + + return stratSelector?.TryUseStrategy(smartCreature, validLocks) ?? false; + } + + private List FindNewAttackPosition(Unit hostile, CancellationToken cancellationToken) + { + var end = hostile.CurrentPosition.GetRandomPositionInRange2D(0, smartCreature.BestActionRange - 1).ToPoint(); + + smartCreature.StopMoving(); + + var maxNode = Math.Pow(smartCreature.HomeRange, 2) * Math.PI; + var priorityQueue = new PriorityQueue((int)maxNode); + var startNode = new Node(smartCreature.CurrentPosition); + + priorityQueue.Enqueue(startNode); + + var closed = new HashSet + { + startNode.position + }; + + Node current; + + while (priorityQueue.TryDequeue(out current)) + { + if (cancellationToken.IsCancellationRequested) + { + return null; + } + + if (IsValidAttackPosition(hostile, current.position)) + { + return BuildPath(current); + } + + foreach (var n in current.position.GetNeighbours()) + { + if (closed.Contains(n)) + { + continue; + } + + closed.Add(n); + + if (!smartCreature.IsWalkable(n.X, n.Y)) + { + continue; + } + + if (!n.IsInRange(smartCreature.HomePosition, smartCreature.HomeRange)) + { + continue; + } + + var newG = current.g + (n.X - current.position.X == 0 || n.Y - current.position.Y == 0 ? 100 : Sqrt2); + var newH = Heuristic.Manhattan.Calculate(n.X, n.Y, end.X, end.Y) * Weight; + var newNode = new Node(n) + { + g = newG, + f = newG + newH, + parent = current + }; + + priorityQueue.Enqueue(newNode); + } + } + + return null; + } + + private bool IsValidAttackPosition(Unit hostile, Point position) + { + var position3 = smartCreature.Zone.FixZ(position.ToPosition()).AddToZ(smartCreature.Height); + + if (!hostile.CurrentPosition.IsInRangeOf3D(position3, smartCreature.BestActionRange)) + { + return false; + } + + var r = smartCreature.Zone.IsInLineOfSight(position3, hostile, false); + + return !r.hit; + } + + private static List BuildPath(Node current) + { + var stack = new Stack(); + var node = current; + + while (node != null) + { + stack.Push(node.position); + node = node.parent; + } + + return stack.ToList(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/AttackCombatDroneAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/AttackCombatDroneAI.cs new file mode 100644 index 000000000..0541705db --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/AttackCombatDroneAI.cs @@ -0,0 +1,47 @@ +using Perpetuum.Zones.NpcSystem.TargettingStrategies; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI.CombatDrones +{ + public class AttackCombatDroneAI : CombatAI + { + public AttackCombatDroneAI(SmartCreature smartCreature) : base(smartCreature) { } + + protected override CombatPrimaryLockSelectionStrategySelector InitSelector() + { + return CombatPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(CombatPrimaryLockSelectionStrategy.HostileOrClosest, 1) + .Build(); + } + + public override void Exit() + { + this.source?.Cancel(); + + base.Exit(); + } + + public override void Update(TimeSpan time) + { + if (!smartCreature.ThreatManager.IsThreatened) + { + ReturnToHomePosition(); + + return; + } + + this.UpdateHostile(time, false); + + base.Update(time); + } + + protected override void ToAggressorAI() { } + + protected override void ReturnToHomePosition() + { + smartCreature.AI.Pop(); + smartCreature.AI.Push(new EscortCombatDroneAI(smartCreature)); + this.WriteLog("Returning to command robot."); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/EscortCombatDroneAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/EscortCombatDroneAI.cs new file mode 100644 index 000000000..8aafc94cd --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/EscortCombatDroneAI.cs @@ -0,0 +1,80 @@ +using Perpetuum.PathFinders; +using Perpetuum.Zones.Movements; +using Perpetuum.Zones.RemoteControl; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI.CombatDrones +{ + public class EscortCombatDroneAI : CombatAI + { + private PathMovement movement; + private readonly double maxReturnGuardRadius; + private readonly PathFinder pathFinder; + + public EscortCombatDroneAI(SmartCreature smartCreature) : base(smartCreature) + { + this.maxReturnGuardRadius = ((this.smartCreature as CombatDrone).GuardRange * 0.4).Clamp(3, 20); + this.pathFinder = new AStarFinder(Heuristic.Manhattan, smartCreature.IsWalkable); + } + + public override void Enter() + { + var randomHome = this.smartCreature.Zone.FindPassablePointInRadius(this.smartCreature.HomePosition, (int)this.maxReturnGuardRadius); + + if (randomHome == default) + { + randomHome = this.smartCreature.HomePosition; + } + + pathFinder + .FindPathAsync(this.smartCreature.CurrentPosition, randomHome) + .ContinueWith(t => + { + var path = t.Result; + + if (path == null) + { + WriteLog("Path not found! (" + this.smartCreature.CurrentPosition + " => " + this.smartCreature.HomePosition + ")"); + + var f = new AStarFinder(Heuristic.Manhattan, (x, y) => true); + + path = f.FindPath(this.smartCreature.CurrentPosition, this.smartCreature.HomePosition); + + if (path == null) + { + WriteLog("Safe path not found! (" + this.smartCreature.CurrentPosition + " => " + this.smartCreature.HomePosition + ")"); + } + } + + this.movement = new PathMovement(path); + this.movement.Start(this.smartCreature); + }); + + base.Enter(); + } + + public override void Update(TimeSpan time) + { + if (this.smartCreature.ThreatManager.IsThreatened) + { + this.ToAttackCombatDroneAI(); + + return; + } + + if (this.movement != null) + { + this.movement.Update(this.smartCreature, time); + + if (this.movement.Arrived) + { + this.smartCreature.AI.Pop(); + + return; + } + } + + base.Update(time); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs new file mode 100644 index 000000000..4565833ea --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/CombatDrones/GuardCombatDroneAI.cs @@ -0,0 +1,44 @@ +using Perpetuum.Zones.Movements; +using Perpetuum.Zones.RemoteControl; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI.CombatDrones +{ + public class GuardCombatDroneAI : BaseAI + { + private RandomMovement movement; + + public GuardCombatDroneAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Enter() + { + this.smartCreature.StopAllModules(); + this.smartCreature.ResetLocks(); + + this.movement = new RandomMovement(this.smartCreature.HomePosition, (this.smartCreature as CombatDrone).GuardRange); + + movement.Start(this.smartCreature); + + base.Enter(); + } + + public override void Update(TimeSpan time) + { + if (!(this.smartCreature as CombatDrone).IsInGuardRange) + { + this.ToEscortCombatDroneAI(); + + return; + } + + if (this.smartCreature.ThreatManager.IsThreatened) + { + this.ToAttackCombatDroneAI(); + + return; + } + + this.movement?.Update(this.smartCreature, time); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/HarvestingIndustrialTurretAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/HarvestingIndustrialTurretAI.cs new file mode 100644 index 000000000..8d0fd6cf9 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/HarvestingIndustrialTurretAI.cs @@ -0,0 +1,27 @@ +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class HarvestingIndustrialTurretAI : StationaryIndustrialAI + { + public HarvestingIndustrialTurretAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Update(TimeSpan time) + { + FindIndustrialTargets(time); + + base.Update(time); + } + + public void FindIndustrialTargets(TimeSpan time) + { + UpdateFrequency.Update(time); + + if (UpdateFrequency.Passed) + { + UpdateFrequency.Reset(); + smartCreature.LookingForHarvestingTargets(); + } + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/HarvestingTurretIndustrialAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/HarvestingTurretIndustrialAI.cs new file mode 100644 index 000000000..f418cfa97 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/HarvestingTurretIndustrialAI.cs @@ -0,0 +1,16 @@ +using Perpetuum.Zones.NpcSystem.TargettingStrategies; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class HarvestingTurretIndustrialAI : StationaryIndustrialAI + { + public HarvestingTurretIndustrialAI(SmartCreature smartCreature) : base(smartCreature) { } + + protected override IndustrialPrimaryLockSelectionStrategySelector InitSelector() + { + return IndustrialPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(IndustrialPrimaryLockSelectionStrategy.MostFertilePlantWithinOptimal, 1) + .Build(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/HomingAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/HomingAI.cs new file mode 100644 index 000000000..81da49e66 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/HomingAI.cs @@ -0,0 +1,75 @@ +using Perpetuum.PathFinders; +using Perpetuum.Zones.Movements; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class HomingAI : CombatAI + { + private PathMovement movement; + private readonly double maxReturnHomeRadius; + private readonly PathFinder pathFinder; + + public HomingAI(SmartCreature smartCreature) : base(smartCreature) + { + this.maxReturnHomeRadius = (smartCreature.HomeRange * 0.4).Clamp(3, 20); + this.pathFinder = new AStarFinder(Heuristic.Manhattan, smartCreature.IsWalkable); + } + + public override void Enter() + { + var randomHome = this.smartCreature.Zone.FindPassablePointInRadius(this.smartCreature.HomePosition, (int)this.maxReturnHomeRadius); + + if (randomHome == default) + { + randomHome = this.smartCreature.HomePosition; + } + + pathFinder + .FindPathAsync(this.smartCreature.CurrentPosition, randomHome) + .ContinueWith(t => + { + var path = t.Result; + + if (path == null) + { + WriteLog("Path not found! (" + this.smartCreature.CurrentPosition + " => " + this.smartCreature.HomePosition + ")"); + + var f = new AStarFinder(Heuristic.Manhattan, (x, y) => true); + + path = f.FindPath(this.smartCreature.CurrentPosition, this.smartCreature.HomePosition); + + if (path == null) + { + WriteLog("Safe path not found! (" + this.smartCreature.CurrentPosition + " => " + this.smartCreature.HomePosition + ")"); + } + } + + this.movement = new PathMovement(path); + this.movement.Start(this.smartCreature); + }); + + base.Enter(); + } + + public override void Update(TimeSpan time) + { + if (this.movement != null) + { + this.movement.Update(this.smartCreature, time); + + if (this.movement.Arrived) + { + this.smartCreature.AI.Pop(); + + return; + } + } + + base.Update(time); + } + + protected override void ToHomeAI() { } + protected override void ToAggressorAI() { } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/IdleAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/IdleAI.cs new file mode 100644 index 000000000..43e9a5628 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/IdleAI.cs @@ -0,0 +1,43 @@ +using Perpetuum.Zones.Movements; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class IdleAI : BaseAI + { + private RandomMovement movement; + + public IdleAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Enter() + { + this.smartCreature.StopAllModules(); + this.smartCreature.ResetLocks(); + + this.movement = new RandomMovement(this.smartCreature.HomePosition, this.smartCreature.HomeRange); + + movement.Start(this.smartCreature); + + base.Enter(); + } + + public override void Update(TimeSpan time) + { + if (!this.smartCreature.IsInHomeRange) + { + this.ToHomeAI(); + + return; + } + + if (this.smartCreature.ThreatManager.IsThreatened) + { + this.ToAggressorAI(); + + return; + } + + this.movement?.Update(this.smartCreature, time); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/InactiveAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/InactiveAI.cs new file mode 100644 index 000000000..9a7e7dbd0 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/InactiveAI.cs @@ -0,0 +1,24 @@ +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class InactiveAI : TurretAI + { + private readonly Turret _turret; + + public InactiveAI(Turret turret) : base(turret) + { + _turret = turret; + } + + public override void Enter() + { + _turret.StopAllModules(); + _turret.ResetLocks(); + base.Enter(); + } + + public override void ToInactiveAI() + { + // nem csinal semmit + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/IndustrialAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/IndustrialAI.cs new file mode 100644 index 000000000..a77586071 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/IndustrialAI.cs @@ -0,0 +1,275 @@ +using Perpetuum.Timers; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.Locking; +using Perpetuum.Zones.NpcSystem.TargettingStrategies; +using Perpetuum.Zones.NpcSystem.ThreatManaging; +using System; +using System.Collections.Generic; +using System.Linq; +using Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using Perpetuum.Zones.RemoteControl; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class IndustrialAI : BaseAI + { + private const int UpdateFrequency = 1650; + private const int EjectFrequency = 300000; + private const double VolumeToEject = 10.0; + private readonly IntervalTimer processIndustrialTargetsTimer = new IntervalTimer(UpdateFrequency); + private readonly IntervalTimer processEjectTimer = new IntervalTimer(EjectFrequency); + private IntervalTimer primarySelectTimer; + private List moduleActivators; + private TimeSpan industrialTargetsUpdateFrequency = TimeSpan.FromMilliseconds(UpdateFrequency); + private TimeSpan ejectCargoFrequency = TimeSpan.FromMilliseconds(EjectFrequency); + private IndustrialPrimaryLockSelectionStrategySelector stratSelector; + + public IndustrialAI(SmartCreature smartCreature) : base(smartCreature) + { + primarySelectTimer = new IntervalTimer((this.smartCreature.ActiveModules.Max(x => x?.CycleTime.Milliseconds) ?? 0) + UpdateFrequency); + } + + public override void Enter() + { + stratSelector = InitSelector(); + moduleActivators = this.smartCreature.ActiveModules + .Select(m => new ModuleActivator(m)) + .ToList(); + processIndustrialTargetsTimer.Update(industrialTargetsUpdateFrequency); + processEjectTimer.Update(ejectCargoFrequency); + primarySelectTimer.Update(industrialTargetsUpdateFrequency); + + base.Enter(); + } + + public override void Update(TimeSpan time) + { + UpdateIndustrialTargets(time); + UpdatePrimaryTarget(time); + RunModules(time); + EjectCargo(time); + } + + protected virtual IndustrialPrimaryLockSelectionStrategySelector InitSelector() + { + return IndustrialPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(IndustrialPrimaryLockSelectionStrategy.RichestTile, 9) + .Build(); + } + + protected void UpdateIndustrialTargets(TimeSpan time) + { + processIndustrialTargetsTimer.Update(time); + + if (processIndustrialTargetsTimer.Passed) + { + processIndustrialTargetsTimer.Reset(); + ProcessIndustrialTargets(); + } + } + + protected void UpdatePrimaryTarget(TimeSpan time) + { + primarySelectTimer.Update(time); + + if (primarySelectTimer.Passed) + { + var success = SelectPrimaryTarget(); + + SetPrimaryUpdateDelay(success); + } + } + + protected void RunModules(TimeSpan time) + { + foreach (var activator in moduleActivators) + { + activator.Update(time); + } + } + + protected void EjectCargo(TimeSpan time) + { + processEjectTimer.Update(time); + + if (processEjectTimer.Passed) + { + processEjectTimer.Reset(); + (smartCreature as IndustrialTurret).EjectCargo(smartCreature.Zone); + } + } + + protected virtual TimeSpan SetPrimaryDwellTime() + { + return FastRandom.NextTimeSpan(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10)); + } + + protected virtual void SetPrimaryUpdateDelay(bool newPrimary) + { + if (newPrimary) + { + primarySelectTimer.Interval = SetPrimaryDwellTime(); + } + else if (GetValidLocks().Length > 0) + { + primarySelectTimer.Interval = TimeSpan.FromSeconds(1); + } + else if (this.smartCreature.GetLocks().Count > 0) + { + primarySelectTimer.Interval = TimeSpan.FromSeconds(1.5); + } + else + { + primarySelectTimer.Interval = TimeSpan.FromSeconds(3.5); + } + } + + protected bool IsAttackable(Hostile hostile) + { + if (!hostile.Unit.InZone) + { + return false; + } + + if (hostile.Unit.States.Dead) + { + return false; + } + + if (!hostile.Unit.IsLockable) + { + return false; + } + + if (hostile.Unit.IsAttackable != ErrorCodes.NoError) + { + return false; + } + + if (hostile.Unit.IsInvulnerable) + { + return false; + } + + if (this.smartCreature.Behavior.Type == BehaviorType.Neutral && hostile.IsExpired) + { + return false; + } + + var isVisible = this.smartCreature.IsVisible(hostile.Unit); + + if (!isVisible) + { + return false; + } + + return true; + } + + protected virtual void ProcessIndustrialTargets() + { + if (!this.smartCreature.IndustrialValueManager.IndustrialTargets.Any()) + { + if (this.smartCreature.GetLocks().Any()) + { + this.smartCreature.ResetLocks(); + } + + return; + } + + var industrialTargetsEnumerator = this.smartCreature.IndustrialValueManager.IndustrialTargets.GetEnumerator(); + + while (industrialTargetsEnumerator.MoveNext()) + { + var industrialTarget = industrialTargetsEnumerator.Current; + + if (!this.smartCreature.IsInLockingRange(industrialTarget.Position)) + { + continue; + } + + SetLockForIndustrialTarget(industrialTarget); + } + } + + protected bool TryMakeFreeLockSlotFor(IndustrialTarget industrialTarget) + { + if (this.smartCreature.HasFreeLockSlot) + { + return true; + } + + this.smartCreature.GetSecondaryLocks().ForEach(x => x.Cancel()); + + return true; + } + + protected IndustrialTarget GetMostValuableIndustrialTarget() + { + var primaryTarget = this.smartCreature.IndustrialValueManager.IndustrialTargets + .Where(h => h.Position == (this.smartCreature.GetPrimaryLock() as TerrainLock)?.Location) + .FirstOrDefault(); + + if (primaryTarget != null) + { + return primaryTarget; + } + + return this.smartCreature.IndustrialValueManager.GetMostValuableIndustrialTarget(); + } + + private void SetLockForIndustrialTarget(IndustrialTarget industrialTarget) + { + var mostValuable = GetMostValuableIndustrialTarget() == industrialTarget; + var industrialLock = this.smartCreature.GetLockByPosition(industrialTarget.Position); + + if (industrialLock == null) + { + if (TryMakeFreeLockSlotFor(industrialTarget)) + { + this.smartCreature.AddLock(industrialTarget.Position, mostValuable); + } + } + else + { + if (mostValuable && !industrialLock.Primary) + { + this.smartCreature.SetPrimaryLock(industrialLock.Id); + } + } + } + + private bool IsLockValidTarget(TerrainLock industrialLock) + { + if (industrialLock == null || industrialLock.State != LockState.Locked) + { + return false; + } + + return industrialLock.Location.IsInRangeOf2D(this.smartCreature.PositionWithHeight, this.smartCreature.MaxActionRange); + } + + private TerrainLock[] GetValidLocks() + { + return this.smartCreature + .GetLocks() + .Select(l => (TerrainLock)l) + .Where(u => IsLockValidTarget(u)) + .ToArray(); + } + + private bool SelectPrimaryTarget() + { + var validLocks = GetValidLocks(); + + if (validLocks.Length < 1) + { + return false; + } + + return stratSelector?.TryUseStrategy(smartCreature, validLocks) ?? false; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/MiningIndustrialTurretAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/MiningIndustrialTurretAI.cs new file mode 100644 index 000000000..4153946e0 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/MiningIndustrialTurretAI.cs @@ -0,0 +1,27 @@ +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class MiningIndustrialTurretAI : StationaryIndustrialAI + { + public MiningIndustrialTurretAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Update(TimeSpan time) + { + FindIndustrialTargets(time); + + base.Update(time); + } + + public void FindIndustrialTargets(TimeSpan time) + { + UpdateFrequency.Update(time); + + if (UpdateFrequency.Passed) + { + UpdateFrequency.Reset(); + smartCreature.LookingForMiningTargets(); + } + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/ModuleActivator.cs b/src/Perpetuum/Zones/NpcSystem/AI/ModuleActivator.cs new file mode 100644 index 000000000..d173755ea --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/ModuleActivator.cs @@ -0,0 +1,413 @@ +using Perpetuum.EntityFramework; +using Perpetuum.Modules; +using Perpetuum.Modules.EffectModules; +using Perpetuum.Modules.Weapons; +using Perpetuum.Timers; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.Terrains; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class ModuleActivator : + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor, + IEntityVisitor + { + private const double ENERGY_INJECTOR_THRESHOLD = 0.65; + private const double ARMOR_REPAIR_THRESHOLD = 0.95; + private const double ARMOR_REPAIR_CORE_THRESHOLD = 0.35; + private const double SENSOR_DAMPENER_CORE_THRESHOLD = 0.55; + private const double SHIELD_ARMOR_THRESHOLD = 0.35; + private const double SENSOR_JAMMER_CORE_THRESHOLD = 0.55; + private const double WEBBER_CORE_THRESHOLD = 0.55; + private const double PAINTER_CORE_THRESHOLD = 0.65; + private const double BLOBBER_CORE_THRESHOLD = 0.55; + private const double BLINDER_CORE_THRESHOLD = 0.55; + private const double ENERGY_NEUTRALIZER_CORE_THRESHOLD = 0.55; + private const double ENERGY_VAMPIRE_CORE_THRESHOLD = 0.05; + + private readonly IntervalTimer _timer; + private readonly ActiveModule _module; + + public ModuleActivator(ActiveModule module) + { + _module = module; + _timer = new IntervalTimer(TimeSpan.FromSeconds(1), true); + } + + public void Update(TimeSpan time) + { + _ = _timer.Update(time); + + if (!_timer.Passed) + { + return; + } + + _timer.Reset(); + + if (_module.State.Type != ModuleStateType.Idle) + { + return; + } + + _module.AcceptVisitor(this); + } + + public void Visit(MissileWeaponModule module) + { + bool hasShieldEffect = module.ParentRobot.HasShieldEffect; + + if (hasShieldEffect) + { + return; + } + + UnitLock primaryLock = module.ParentRobot.GetFinishedPrimaryLock(); + + if (primaryLock == null) + { + return; + } + + Units.IUnitVisibility visibility = module.ParentRobot.GetVisibility(primaryLock.Target); + + if (visibility == null) + { + return; + } + + LOSResult result = visibility.GetLineOfSight(true); + + TryActiveModule(result, primaryLock); + } + + public void Visit(WeaponModule module) + { + bool hasShieldEffect = module.ParentRobot.HasShieldEffect; + + if (hasShieldEffect) + { + return; + } + + UnitLock primaryLock = module.ParentRobot.GetFinishedPrimaryLock(); + + if (primaryLock == null) + { + return; + } + + Units.IUnitVisibility visibility = module.ParentRobot.GetVisibility(primaryLock.Target); + + if (visibility == null) + { + return; + } + + LOSResult result = visibility.GetLineOfSight(false); + + TryActiveModule(result, primaryLock); + } + + public void Visit(ArmorRepairModule module) + { + if (module.ParentRobot.ArmorPercentage >= ARMOR_REPAIR_THRESHOLD) + { + return; + } + + if (module.ParentRobot.CorePercentage < ARMOR_REPAIR_CORE_THRESHOLD) + { + return; + } + + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(ShieldGeneratorModule module) + { + if (module.ParentRobot.ArmorPercentage >= SHIELD_ARMOR_THRESHOLD) + { + return; + } + + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(SensorJammerModule module) + { + if (module.ParentRobot.CorePercentage < SENSOR_JAMMER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(SensorDampenerModule module) + { + if (module.ParentRobot.CorePercentage < SENSOR_DAMPENER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(WebberModule module) + { + if (module.ParentRobot.CorePercentage < WEBBER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(TargetPainterModule module) + { + if (module.ParentRobot.CorePercentage < PAINTER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(BlobEmissionModulatorModule module) + { + if (module.ParentRobot.Zone.Configuration.Protected) + { + return; + } + + if (module.ParentRobot.CorePercentage < BLOBBER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(TargetBlinderModule module) + { + if (module.ParentRobot.CorePercentage < BLINDER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(EnergyNeutralizerModule module) + { + if (module.ParentRobot.CorePercentage < ENERGY_NEUTRALIZER_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + Units.IUnitVisibility visibility = module.ParentRobot.GetVisibility(lockTarget.Target); + + if (visibility == null) + { + return; + } + + LOSResult r = visibility.GetLineOfSight(false); + + if (r != null && r.hit) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(EnergyVampireModule module) + { + if (module.ParentRobot.CorePercentage < ENERGY_VAMPIRE_CORE_THRESHOLD) + { + return; + } + + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + Units.IUnitVisibility visibility = module.ParentRobot.GetVisibility(lockTarget.Target); + + if (visibility == null) + { + return; + } + + LOSResult r = visibility.GetLineOfSight(false); + + if (r != null && r.hit) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(SensorBoosterModule module) + { + if (module.State.Type == ModuleStateType.Idle) + { + module.State.SwitchTo(ModuleStateType.AutoRepeat); + } + } + + public void Visit(ArmorHardenerModule module) + { + if (module.State.Type == ModuleStateType.Idle) + { + module.State.SwitchTo(ModuleStateType.AutoRepeat); + } + } + + public void Visit(CoreBoosterModule module) + { + if (module.ParentRobot.CorePercentage > ENERGY_INJECTOR_THRESHOLD) + { + return; + } + + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(RemoteControlledDrillerModule module) + { + TerrainLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockIndustrialTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(RemoteControlledHarvesterModule module) + { + TerrainLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockIndustrialTargetFor(module); + + if (lockTarget == null) + { + return; + } + + module.Lock = lockTarget; + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + public void Visit(RemoteControllerModule module) + { + UnitLock lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); + + if (lockTarget == null) + { + return; + } + + Units.IUnitVisibility visibility = module.ParentRobot.GetVisibility(lockTarget.Target); + + if (visibility == null) + { + return; + } + + module.State.SwitchTo(ModuleStateType.Oneshot); + } + + private void TryActiveModule(LOSResult result, UnitLock primaryLock) + { + if (result.hit && !result.blockingFlags.HasFlag(BlockingFlags.Plant)) + { + return; + } + + _module.Lock = primaryLock; + _module.State.SwitchTo(ModuleStateType.Oneshot); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/Node.cs b/src/Perpetuum/Zones/NpcSystem/AI/Node.cs new file mode 100644 index 000000000..36cb79c40 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/Node.cs @@ -0,0 +1,28 @@ +using System; +using System.Drawing; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class Node : IComparable + { + public readonly Point position; + public Node parent; + public int g; + public int f; + + public Node(Point position) + { + this.position = position; + } + + public int CompareTo(Node other) + { + return f - other.f; + } + + public override int GetHashCode() + { + return position.GetHashCode(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/NullAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/NullAI.cs new file mode 100644 index 000000000..21314aadd --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/NullAI.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class NullAI : TurretAI + { + public NullAI(Turret turret) : base(turret) + { + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/SentryTurretCombatAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/SentryTurretCombatAI.cs new file mode 100644 index 000000000..f07320916 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/SentryTurretCombatAI.cs @@ -0,0 +1,16 @@ +using Perpetuum.Zones.NpcSystem.TargettingStrategies; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class SentryTurretCombatAI : StationaryCombatAI + { + public SentryTurretCombatAI(SmartCreature smartCreature) : base(smartCreature) { } + + protected override CombatPrimaryLockSelectionStrategySelector InitSelector() + { + return CombatPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(CombatPrimaryLockSelectionStrategy.HostileOrClosest, 1) + .Build(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/SentryTurretIdleAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/SentryTurretIdleAI.cs new file mode 100644 index 000000000..8ba044afa --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/SentryTurretIdleAI.cs @@ -0,0 +1,19 @@ +using Perpetuum.Zones.NpcSystem.AI.Behaviors; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class SentryTurretIdleAI : StationaryIdleAI + { + public SentryTurretIdleAI(SmartCreature smartCreature) : base(smartCreature) { } + + protected override void ToAggressorAI() + { + if (this.smartCreature.Behavior.Type == BehaviorType.Passive) + { + return; + } + + this.smartCreature.AI.Push(new SentryTurretCombatAI(this.smartCreature)); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/StationaryCombatAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/StationaryCombatAI.cs new file mode 100644 index 000000000..812c4e80e --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/StationaryCombatAI.cs @@ -0,0 +1,46 @@ +using Perpetuum.Timers; +using Perpetuum.Zones.NpcSystem.TargettingStrategies; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class StationaryCombatAI : CombatAI + { + private readonly IntervalTimer updateFrequency = new IntervalTimer(650); + + public StationaryCombatAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Update(TimeSpan time) + { + FindHostiles(time); + + base.Update(time); + } + + protected override CombatPrimaryLockSelectionStrategySelector InitSelector() + { + return CombatPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(CombatPrimaryLockSelectionStrategy.Hostile, 1) + .WithStrategy(CombatPrimaryLockSelectionStrategy.Closest, 2) + .WithStrategy(CombatPrimaryLockSelectionStrategy.OptimalRange, 3) + .WithStrategy(CombatPrimaryLockSelectionStrategy.Random, 10) + .Build(); + } + + protected override TimeSpan SetPrimaryDwellTime() + { + return FastRandom.NextTimeSpan(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(25)); + } + + private void FindHostiles(TimeSpan time) + { + updateFrequency.Update(time); + + if (updateFrequency.Passed) + { + updateFrequency.Reset(); + smartCreature.LookingForHostiles(); + } + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/StationaryIdleAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/StationaryIdleAI.cs new file mode 100644 index 000000000..5ddec3337 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/StationaryIdleAI.cs @@ -0,0 +1,37 @@ +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class StationaryIdleAI : BaseAI + { + public StationaryIdleAI(SmartCreature smartCreature) : base(smartCreature) { } + + public override void Enter() + { + this.smartCreature.StopAllModules(); + this.smartCreature.ResetLocks(); + base.Enter(); + } + + public override void Update(TimeSpan time) + { + if (this.smartCreature.ThreatManager.IsThreatened) + { + ToAggressorAI(); + } + } + + protected override void ToHomeAI() { } + + protected override void ToAggressorAI() + { + if (this.smartCreature.Behavior.Type == BehaviorType.Passive) + { + return; + } + + this.smartCreature.AI.Push(new StationaryCombatAI(this.smartCreature)); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/StationaryIndustrialAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/StationaryIndustrialAI.cs new file mode 100644 index 000000000..2fc130358 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/StationaryIndustrialAI.cs @@ -0,0 +1,25 @@ +using Perpetuum.Timers; +using Perpetuum.Zones.NpcSystem.TargettingStrategies; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public class StationaryIndustrialAI : IndustrialAI + { + public readonly IntervalTimer UpdateFrequency = new IntervalTimer(5000); + + public StationaryIndustrialAI(SmartCreature smartCreature) : base(smartCreature) { } + + protected override IndustrialPrimaryLockSelectionStrategySelector InitSelector() + { + return IndustrialPrimaryLockSelectionStrategySelector.Create() + .WithStrategy(IndustrialPrimaryLockSelectionStrategy.RichestTile, 1) + .Build(); + } + + protected override TimeSpan SetPrimaryDwellTime() + { + return FastRandom.NextTimeSpan(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5)); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/AI/TurretAI.cs b/src/Perpetuum/Zones/NpcSystem/AI/TurretAI.cs new file mode 100644 index 000000000..a393c0c34 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/AI/TurretAI.cs @@ -0,0 +1,51 @@ +using Perpetuum.StateMachines; +using Perpetuum.Units; +using System; + +namespace Perpetuum.Zones.NpcSystem.AI +{ + public abstract class TurretAI : IState + { + private readonly Turret _turret; + + protected TurretAI(Turret turret) + { + _turret = turret; + } + + public virtual void Enter() + { + WriteLog("Turret AI:" + GetType().Name); + } + + public virtual void Exit() + { + WriteLog("Turret AI:" + GetType().Name); + } + + public virtual void Update(TimeSpan time) + { + + } + + protected void WriteLog(string message) + { + // Logger.Info(message); + } + + public virtual void ToInactiveAI() + { + _turret.AIStateMachine.ChangeState(new InactiveAI(_turret)); + } + + public virtual void ToActiveAI() + { + _turret.AIStateMachine.ChangeState(new ActiveAI(_turret)); + } + + public virtual void AttackHostile(Unit unit) + { + + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/Creature.cs b/src/Perpetuum/Zones/NpcSystem/Creature.cs index 51055949e..b9a424829 100644 --- a/src/Perpetuum/Zones/NpcSystem/Creature.cs +++ b/src/Perpetuum/Zones/NpcSystem/Creature.cs @@ -5,6 +5,7 @@ using Perpetuum.Units; using Perpetuum.Zones.Effects; using Perpetuum.Zones.Eggs; +using Perpetuum.Zones.LandMines; using Perpetuum.Zones.Locking; using Perpetuum.Zones.Locking.Locks; @@ -14,7 +15,7 @@ public abstract class Creature : Robot { protected override void UpdateUnitVisibility(Unit target) { - if (target is AreaBomb) + if (target is AreaBomb || target is LandMine) { UpdateVisibility(target); } @@ -95,5 +96,25 @@ public UnitLock SelectOptimalLockTargetFor(ActiveModule module) return locks.RandomElement(); } + + [CanBeNull] + public TerrainLock SelectOptimalLockIndustrialTargetFor(ActiveModule module) + { + var range = module.OptimalRange; + var locks = GetLocks().OfType().Where(industrialLock => + { + if (industrialLock.State != LockState.Locked) + { + return false; + } + + return true; + + }).ToArray(); + + var primaryLock = locks.FirstOrDefault(l => l.Primary); + + return primaryLock; + } } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/NpcSystem/Flocks/Flock.cs b/src/Perpetuum/Zones/NpcSystem/Flocks/Flock.cs index 7469e5f9d..1511955b8 100644 --- a/src/Perpetuum/Zones/NpcSystem/Flocks/Flock.cs +++ b/src/Perpetuum/Zones/NpcSystem/Flocks/Flock.cs @@ -1,126 +1,119 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; using Perpetuum.EntityFramework; using Perpetuum.Log; using Perpetuum.Services.Looting; using Perpetuum.Units; using Perpetuum.Zones.Finders.PositionFinders; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; using Perpetuum.Zones.NpcSystem.Presences; using Perpetuum.Zones.NpcSystem.Presences.InterzonePresences; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; namespace Perpetuum.Zones.NpcSystem.Flocks { - public interface INpcGroup - { - string Name { get; } - IEnumerable Members { get; } - void AddDebugInfoToDictionary(IDictionary dictionary); - } - - public delegate Flock FlockFactory(IFlockConfiguration flockConfiguration,Presence presence); + public delegate Flock FlockFactory(IFlockConfiguration flockConfiguration, Presence presence); public class Flock { + private ImmutableList members = ImmutableList.Empty; + public ILootService LootService { get; set; } - public IEntityServices EntityService { get; set; } - private ImmutableList _members = ImmutableList.Empty; + public IEntityServices EntityService { get; set; } public IFlockConfiguration Configuration { get; } + public Presence Presence { get; } public NpcBossInfo BossInfo { get { return Configuration.BossInfo; } } + public bool IsBoss { get { return BossInfo != null; } } public int Id => Configuration.ID; public int HomeRange => Configuration.HomeRange; + public Position SpawnOrigin { get; } + + public IReadOnlyCollection Members => members; + + public int MembersCount => members.Count; + + public event Action AllMembersDead; + + public event Action NpcCreated; + public Flock(IFlockConfiguration configuration, Presence presence) { Configuration = configuration; Presence = presence; - SpawnOrigin = SpawnOriginSelector(presence); } - public Position SpawnOrigin { get; } - - public IReadOnlyCollection Members => _members; - - private void AddMember(Npc npc) + public virtual IDictionary ToDictionary() { - ImmutableInterlocked.Update(ref _members, m => m.Add(npc)); - npc.Dead += OnMemberDead; - } + var dictionary = new Dictionary + { + {k.ID, Configuration.ID}, + {k.presenceID, Presence.Configuration.ID}, + {k.definition, Configuration.EntityDefault.Definition}, + {k.name, Configuration.Name}, + {k.spawnRangeMin, Configuration.SpawnRange.Min}, + {k.spawnRangeMax, Configuration.SpawnRange.Max}, + {k.flockMemberCount, Configuration.FlockMemberCount}, + {k.respawnSeconds, Configuration.RespawnTime.Seconds}, + {k.homeRange, HomeRange}, + {k.totalSpawnCount, Configuration.TotalSpawnCount}, + {k.spawnOriginX,SpawnOrigin.intX}, + {k.spawnOriginY,SpawnOrigin.intY} + }; - private void RemoveMember(Npc npc) - { - ImmutableInterlocked.Update(ref _members, m => m.Remove(npc)); + return dictionary; } - - protected virtual void OnMemberDead(Unit killer,Unit npc) + public void SpawnAllMembers() { - RemoveMember((Npc) npc); + var totalToSpawn = Configuration.FlockMemberCount - MembersCount; - if (_members.Count <= 0) + for (var i = 0; i < totalToSpawn; i++) { - OnAllMembersDead(); + CreateMemberInZone(); } - } - - public event Action AllMembersDead; - private void OnAllMembersDead() - { - AllMembersDead?.Invoke(this); + Log($"{Configuration.FlockMemberCount} NPCs created"); } - public virtual IDictionary ToDictionary() + public virtual void Update(TimeSpan time) { - var dictionary = new Dictionary { - {k.ID, Configuration.ID}, - {k.presenceID, Presence.Configuration.ID}, - {k.definition, Configuration.EntityDefault.Definition}, - {k.name, Configuration.Name}, - {k.spawnRangeMin, Configuration.SpawnRange.Min}, - {k.spawnRangeMax, Configuration.SpawnRange.Max}, - {k.flockMemberCount, Configuration.FlockMemberCount}, - {k.respawnSeconds, Configuration.RespawnTime.Seconds}, - {k.homeRange, HomeRange}, - {k.totalSpawnCount, Configuration.TotalSpawnCount}, - {k.spawnOriginX,SpawnOrigin.intX}, - {k.spawnOriginY,SpawnOrigin.intY} - }; - return dictionary; } - public int MembersCount => _members.Count; - - public virtual void Update(TimeSpan time) + public override string ToString() { + return $"{Configuration.Name}:{Configuration.ID}"; } - public void SpawnAllMembers() + public void RemoveAllMembersFromZone(bool withTeleportExit = false) { - var totalToSpawn = Configuration.FlockMemberCount - MembersCount; - for (var i = 0; i < totalToSpawn; i++) + foreach (var npc in Members) { - CreateMemberInZone(); - } + if (withTeleportExit) + { + npc.States.Teleport = true; + } - Log($"{Configuration.FlockMemberCount} NPCs created"); + npc.RemoveFromZone(); + RemoveMember(npc); + } } protected virtual void CreateMemberInZone() { var npc = (Npc)EntityService.Factory.Create(Configuration.EntityDefault, EntityIDGenerator.Random); - var zone = Presence.Zone; var spawnPosition = GetSpawnPosition(SpawnOrigin); var finder = new ClosestWalkablePositionFinder(zone, spawnPosition, npc); + if (!finder.Find(out spawnPosition)) { Log($"invalid spawnposition in CreateMemberInZone: {spawnPosition} {Configuration.Name} {Presence.Configuration.Name} zone:{zone.Id}"); @@ -148,12 +141,22 @@ protected virtual void CreateMemberInZone() Log($"member spawned to zone:{zone.Id} EID:{npc.Eid}"); } + protected virtual void OnMemberDead(Unit killer, Unit npc) + { + RemoveMember((Npc)npc); + + if (members.Count <= 0) + { + OnAllMembersDead(); + } + } + protected virtual Position GetSpawnPosition(Position spawnOrigin) { var spawnRangeMin = Configuration.SpawnRange.Min; var spawnRangeMax = Configuration.SpawnRange.Max.Min(HomeRange); - var spawnPosition = spawnOrigin.GetRandomPositionInRange2D(spawnRangeMin, spawnRangeMax).Clamp(Presence.Zone.Size); + return spawnPosition; } @@ -162,80 +165,74 @@ protected virtual Position GetHomePosition(Position spawnOrigin) return spawnOrigin; } - public event Action NpcCreated; - protected virtual void OnNpcCreated(Npc npc) { NpcCreated?.Invoke(npc); } - private NpcBehavior GetBehavior() + protected void Log(string message) { + Logger.Info($"[Flock] ({ToString()}) - {message}"); + } - if( Presence is InterzonePresence) - { - return NpcBehavior.Create(Configuration.BehaviorType); - } - else if(Configuration.BehaviorType == NpcBehaviorType.Aggressive && Presence is DynamicPresenceExtended) - { - // This is needed to prevent the super class from matching the next condition, which overrides the behaviour type! - return NpcBehavior.Create(Configuration.BehaviorType); - } - else if (Configuration.BehaviorType == NpcBehaviorType.Aggressive && Presence is DynamicPresence) - { - // hogy ne tamadjanak be mindenkit rogton - return NpcBehavior.Create(NpcBehaviorType.Neutral); - } - - return NpcBehavior.Create(Configuration.BehaviorType); + private void AddMember(Npc npc) + { + ImmutableInterlocked.Update(ref members, m => m.Add(npc)); + npc.Dead += OnMemberDead; } - protected void Log(string message) + private void RemoveMember(Npc npc) { - Logger.Info($"[Flock] ({ToString()}) - {message}"); + ImmutableInterlocked.Update(ref members, m => m.Remove(npc)); } - public override string ToString() + private void OnAllMembersDead() { - return $"{Configuration.Name}:{Configuration.ID}"; + AllMembersDead?.Invoke(this); } - public void RemoveAllMembersFromZone(bool withTeleportExit = false) + private Behavior GetBehavior() { - foreach (var npc in Members) - { - if (withTeleportExit) - npc.States.Teleport = true; - npc.RemoveFromZone(); - RemoveMember(npc); + if (Presence is InterzonePresence) + { + return Behavior.Create(Configuration.BehaviorType); + } + else if (Configuration.BehaviorType == BehaviorType.Aggressive && Presence is DynamicPresenceExtended) + { + return Behavior.Create(Configuration.BehaviorType); + } + else if (Configuration.BehaviorType == BehaviorType.Aggressive && Presence is DynamicPresence) + { + return Behavior.Create(BehaviorType.Neutral); } + + return Behavior.Create(Configuration.BehaviorType); } private Position SpawnOriginSelector(Presence presence) { switch (presence) { - case InterzonePresence ip: - { - return Configuration.SpawnOrigin; - } - case DynamicPresence dp: - { - return dp.DynamicPosition; - } - case RandomPresence rp: - { - return rp.SpawnOriginForRandomPresence; - } + case InterzonePresence interzonePresense: + { + return Configuration.SpawnOrigin; + } + case DynamicPresence dynamicPresence: + { + return dynamicPresence.DynamicPosition; + } + case RandomPresence randomPresense: + { + return randomPresense.SpawnOriginForRandomPresence; + } case IRoamingPresence roaming: - { - return roaming.SpawnOrigin; - } + { + return roaming.SpawnOrigin; + } } return Configuration.SpawnOrigin; } - } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfiguration.cs b/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfiguration.cs index dda773c7c..1f1245d31 100644 --- a/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfiguration.cs +++ b/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfiguration.cs @@ -1,32 +1,49 @@ -using System; using Perpetuum.EntityFramework; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using System; namespace Perpetuum.Zones.NpcSystem.Flocks { public class FlockConfiguration : IFlockConfiguration { public int ID { get; set; } + public string Name { get; set; } + public int PresenceID { get; set; } + public int FlockMemberCount { get; set; } + public Position SpawnOrigin { get; set; } + public IntRange SpawnRange { get; set; } + public int TotalSpawnCount { get; set; } + public string Note { get; set; } + public double RespawnMultiplierLow { get; set; } + public bool IsCallForHelp { get; set; } + public bool Enabled { get; set; } - public NpcBehaviorType BehaviorType { get; set; } + + public BehaviorType BehaviorType { get; set; } + public NpcSpecialType SpecialType { get; set; } - public NpcBossInfo BossInfo { get; set; } + + public NpcBossInfo BossInfo { get; set; } + public int HomeRange { get; set; } + public EntityDefault EntityDefault { get; set; } + public TimeSpan RespawnTime { get; set; } public FlockConfiguration() { - BehaviorType = NpcBehaviorType.Neutral; - HomeRange = (int) DistanceConstants.MAX_NPC_FLOCK_HOME_RANGE; + BehaviorType = BehaviorType.Neutral; + HomeRange = (int)DistanceConstants.MAX_NPC_FLOCK_HOME_RANGE; } public override string ToString() diff --git a/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfigurationRepository.cs b/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfigurationRepository.cs index 345f8e335..f2946f4e8 100644 --- a/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfigurationRepository.cs +++ b/src/Perpetuum/Zones/NpcSystem/Flocks/FlockConfigurationRepository.cs @@ -1,8 +1,9 @@ +using Perpetuum.Data; +using Perpetuum.EntityFramework; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; using System; using System.Collections.Generic; using System.Linq; -using Perpetuum.Data; -using Perpetuum.EntityFramework; namespace Perpetuum.Zones.NpcSystem.Flocks { @@ -10,7 +11,7 @@ public class FlockConfigurationRepository : IFlockConfigurationRepository { private readonly NpcBossInfoBuilder _bossBuilder; private readonly FlockConfigurationBuilder.Factory _flockConfigurationBuilderFactory; - private readonly Dictionary _flockConfigurations = new Dictionary(); + private readonly Dictionary _flockConfigurations = new Dictionary(); public FlockConfigurationRepository(FlockConfigurationBuilder.Factory flockConfigurationBuilderFactory, NpcBossInfoBuilder bossBuilder) { @@ -21,9 +22,11 @@ public FlockConfigurationRepository(FlockConfigurationBuilder.Factory flockConfi public void LoadAllConfig() { var records = Db.Query().CommandText("select * from npcflock").Execute(); + foreach (var r in records) { var builder = _flockConfigurationBuilderFactory(); + builder.With(c => { c.ID = r.GetValue("id"); @@ -40,11 +43,13 @@ public void LoadAllConfig() c.RespawnMultiplierLow = r.GetValue("respawnmultiplierlow"); c.IsCallForHelp = r.GetValue("iscallforhelp"); c.Enabled = r.GetValue("enabled"); - c.BehaviorType = (NpcBehaviorType) r.GetValue("behaviorType"); - c.SpecialType = (NpcSpecialType) r.GetValue("npcSpecialType"); + c.BehaviorType = (BehaviorType)r.GetValue("behaviorType"); + c.SpecialType = (NpcSpecialType)r.GetValue("npcSpecialType"); c.BossInfo = _bossBuilder.GetBossInfoByFlockID(c.ID, c); }); + var config = builder.Build(); + _flockConfigurations[config.ID] = config; } } @@ -70,6 +75,7 @@ public void Insert(IFlockConfiguration item) (name,presenceid,flockmembercount,definition,spawnoriginX,spawnoriginY,spawnrangeMin,spawnrangeMax,respawnseconds,totalspawncount,homerange,note,respawnmultiplierlow) values (@name,@presenceID,@flockMemberCount,@definition,@spawnOriginX,@spawnOriginY,@spawnRangeMin,@spawnRangeMax,@respawnSeconds,@totalSpawnCount,@homeRange,@note,@respawnMultiplierLow); select cast(scope_identity() as int)"; + var id = Db.Query().CommandText(query) .SetParameter("@name", item.Name) .SetParameter("@presenceID", item.PresenceID) @@ -87,7 +93,9 @@ public void Insert(IFlockConfiguration item) .ExecuteScalar().ThrowIfEqual(0, ErrorCodes.SQLInsertError); if (item is FlockConfiguration fc) + { fc.ID = id; + } } public void Update(IFlockConfiguration item) @@ -123,14 +131,17 @@ public void Update(IFlockConfiguration item) .SetParameter("@respawnMultiplierLow", item.RespawnMultiplierLow) .SetParameter("@note", item.Note) .ExecuteNonQuery(); - if ( res == 0 ) + + if (res == 0) + { throw new PerpetuumException(ErrorCodes.SQLUpdateError); + } } public void Delete(IFlockConfiguration item) { Db.Query().CommandText("delete npcflock where id=@ID") - .SetParameter("@ID",item.ID) + .SetParameter("@ID", item.ID) .ExecuteNonQuery().ThrowIfEqual(0, ErrorCodes.SQLDeleteError); } } diff --git a/src/Perpetuum/Zones/NpcSystem/Flocks/IFlockConfiguration.cs b/src/Perpetuum/Zones/NpcSystem/Flocks/IFlockConfiguration.cs index c1e601c69..643a9fb79 100644 --- a/src/Perpetuum/Zones/NpcSystem/Flocks/IFlockConfiguration.cs +++ b/src/Perpetuum/Zones/NpcSystem/Flocks/IFlockConfiguration.cs @@ -1,26 +1,43 @@ -using System; using Perpetuum.EntityFramework; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using System; namespace Perpetuum.Zones.NpcSystem.Flocks { public interface IFlockConfiguration { int ID { get; } - int PresenceID { get;} + + int PresenceID { get; } + double RespawnMultiplierLow { get; } + int HomeRange { get; } + TimeSpan RespawnTime { get; } + int FlockMemberCount { get; } + int TotalSpawnCount { get; } + string Name { get; } + bool Enabled { get; } + IntRange SpawnRange { get; } + EntityDefault EntityDefault { get; } + Position SpawnOrigin { get; } + string Note { get; } + bool IsCallForHelp { get; } - NpcBehaviorType BehaviorType { get; } + + BehaviorType BehaviorType { get; } + NpcSpecialType SpecialType { get; } + NpcBossInfo BossInfo { get; } } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/NpcSystem/Flocks/ISmartCreatureGroup.cs b/src/Perpetuum/Zones/NpcSystem/Flocks/ISmartCreatureGroup.cs new file mode 100644 index 000000000..adba578a8 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/Flocks/ISmartCreatureGroup.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Perpetuum.Zones.NpcSystem.Flocks +{ + public interface ISmartCreatureGroup + { + string Name { get; } + + IEnumerable Members { get; } + + void AddDebugInfoToDictionary(IDictionary dictionary); + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IIndustrialValueManager.cs b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IIndustrialValueManager.cs new file mode 100644 index 000000000..a86776d19 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IIndustrialValueManager.cs @@ -0,0 +1,17 @@ +using System.Collections.Immutable; + +namespace Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement +{ + public interface IIndustrialValueManager + { + bool IsValuable { get; } + + ImmutableSortedSet IndustrialTargets { get; } + + bool Contains(Position tile); + + void Remove(IndustrialTarget industrialTarget); + + void Clear(); + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialTarget.cs b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialTarget.cs new file mode 100644 index 000000000..782c576aa --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialTarget.cs @@ -0,0 +1,83 @@ +using Perpetuum.Timers; +using Perpetuum.Units; +using Perpetuum.Zones.NpcSystem.ThreatManaging; +using System; + +namespace Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement +{ + public class IndustrialTarget : IComparable + { + private static readonly TimeSpan _threatTimeOut = TimeSpan.FromSeconds(30); + + private double _industrialValue; + + public readonly Position Position; + + public TimeSpan LastIndistrialValueUpdate { get; private set; } + + public double IndustrialValue + { + get + { + return _industrialValue; + } + private set + { + if (Math.Abs(_industrialValue - value) <= double.Epsilon) + { + return; + } + + _industrialValue = value; + OnIndustrialValueUpdated(); + } + } + + public bool IsExpired + { + get + { + return (GlobalTimer.Elapsed - LastIndistrialValueUpdate) >= _threatTimeOut; + } + } + + public event Action Updated; + + public IndustrialTarget(Position position) + { + this.Position = position; + IndustrialValue = 0.0; + } + + public void AddIndustrialValue(IndustrialValue industrialValue) + { + if (industrialValue.value <= 0.0) + { + return; + } + + IndustrialValue += industrialValue.value; + } + + private void OnIndustrialValueUpdated() + { + LastIndistrialValueUpdate = GlobalTimer.Elapsed; + Updated?.Invoke(this); + } + + public int CompareTo(IndustrialTarget other) + { + if (other._industrialValue < _industrialValue) + { + return -1; + } + + if (other._industrialValue > _industrialValue) + { + return 1; + } + + return 0; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValue.cs b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValue.cs new file mode 100644 index 000000000..6590887bd --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValue.cs @@ -0,0 +1,28 @@ +namespace Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement +{ + public struct IndustrialValue + { + public const double CommonMineral = 10; + public const double RareMineral = 25; + public const double CommonPlant = 10; + public const double RarePlant = 25; + public readonly IndustrialValueType type; + public readonly double value; + + public IndustrialValue(IndustrialValueType type, double value) + { + this.type = type; + this.value = value; + } + + public override string ToString() + { + return $"{type} = {value}"; + } + + public static IndustrialValue Multiply(IndustrialValue threat, double multiplier) + { + return new IndustrialValue(threat.type, threat.value * multiplier); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueExtensions.cs b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueExtensions.cs new file mode 100644 index 000000000..063e5fb04 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueExtensions.cs @@ -0,0 +1,11 @@ +namespace Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement +{ + public static class IndustrialValueExtensions + { + [CanBeNull] + public static IndustrialTarget GetMostValuableIndustrialTarget(this IIndustrialValueManager manager) + { + return manager.IndustrialTargets.Min; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueManager.cs b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueManager.cs new file mode 100644 index 000000000..8603391f9 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueManager.cs @@ -0,0 +1,73 @@ +using System.Collections.Immutable; +using System.Linq; +using System.Text; + +namespace Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement +{ + public class IndustrialValueManager : IIndustrialValueManager + { + private ImmutableDictionary _industrialTargets = ImmutableDictionary.Empty; + + public ImmutableSortedSet IndustrialTargets + { + get { return _industrialTargets.Values.ToImmutableSortedSet(); } + } + + public bool IsValuable + { + get { return !_industrialTargets.IsEmpty; } + } + + public IndustrialTarget GetOrAddIndustrialTargetWithValue(Position tile, IndustrialValueType valueType, double value) + { + return ImmutableInterlocked.GetOrAdd(ref _industrialTargets, tile.ToString(), eid => + { + var industrialTarget = new IndustrialTarget(tile); + + industrialTarget.AddIndustrialValue(new IndustrialValue(valueType, value)); + + return industrialTarget; + }); + } + + public bool Contains(Position tile) + { + return _industrialTargets.ContainsKey(tile.ToString()); + } + + public void Clear() + { + _industrialTargets = _industrialTargets.Clear(); + } + + public void Remove(IndustrialTarget industrialTarget) + { + ImmutableInterlocked.TryRemove(ref _industrialTargets, industrialTarget.Position.ToString(), out _); + } + + public string ToDebugString() + { + if (_industrialTargets.Count == 0) + { + return string.Empty; + } + + var sb = new StringBuilder(); + + sb.AppendLine(); + sb.AppendLine("========== THREAT =========="); + sb.AppendLine(); + + foreach (var industrialTarget in _industrialTargets.Values.OrderByDescending(h => h.IndustrialValue)) + { + sb.AppendFormat(" {0} ({1}) => {2}", "Industrial Target", industrialTarget.Position.ToString(), industrialTarget.IndustrialValue); + sb.AppendLine(); + } + + sb.AppendLine(); + sb.AppendLine("============================"); + + return sb.ToString(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueType.cs b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueType.cs new file mode 100644 index 000000000..5d3144cd6 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/IndustrialTargetsManagement/IndustrialValueType.cs @@ -0,0 +1,9 @@ +namespace Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement +{ + public enum IndustrialValueType + { + Undefined, + Mineral, + Plant, + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/NPCBossInfo.cs b/src/Perpetuum/Zones/NpcSystem/NPCBossInfo.cs index 938c029cb..7ec7deafa 100644 --- a/src/Perpetuum/Zones/NpcSystem/NPCBossInfo.cs +++ b/src/Perpetuum/Zones/NpcSystem/NPCBossInfo.cs @@ -1,83 +1,17 @@ -using Perpetuum.Data; -using Perpetuum.Players; +using Perpetuum.Players; using Perpetuum.Services.EventServices; using Perpetuum.Services.EventServices.EventMessages; using Perpetuum.Services.RiftSystem; using Perpetuum.Timers; using Perpetuum.Units; using Perpetuum.Zones.Intrusion; -using Perpetuum.Zones.NpcSystem.Flocks; using System; using System.Collections.Generic; -using System.Data; using System.Linq; using System.Threading.Tasks; namespace Perpetuum.Zones.NpcSystem { - public class NpcBossInfoBuilder - { - private readonly ICustomRiftConfigReader _customRiftConfigReader; - private readonly EventListenerService _eventChannel; - public NpcBossInfoBuilder(ICustomRiftConfigReader customRiftConfigReader, EventListenerService eventChannel) - { - _customRiftConfigReader = customRiftConfigReader; - _eventChannel = eventChannel; - } - - public NpcBossInfo CreateBossInfoFromDB(IDataRecord record) - { - var id = record.GetValue("id"); - var flockid = record.GetValue("flockid"); - var respawnFactor = record.GetValue("respawnNoiseFactor"); - var lootSplit = record.GetValue("lootSplitFlag"); - var outpostEID = record.GetValue("outpostEID"); - var stabilityPts = record.GetValue("stabilityPts"); - var overrideRelations = record.GetValue("overrideRelations"); - var deathMessage = record.GetValue("customDeathMessage"); - var aggressMessage = record.GetValue("customAggressMessage"); - var riftConfigId = record.GetValue("riftConfigId"); - var riftConfig = _customRiftConfigReader.GetById(riftConfigId ?? -1); - var announce = record.GetValue("isAnnounced"); - - var info = new NpcBossInfo(_eventChannel, - id, - flockid, - respawnFactor, - lootSplit, - outpostEID, - stabilityPts, - overrideRelations, - deathMessage, - aggressMessage, - riftConfig, - announce - ); - return info; - } - - public NpcBossInfo GetBossInfoByFlockID(int flockid, IFlockConfiguration config) - { - var bossInfos = Db.Query() - .CommandText(@"SELECT TOP 1 id, flockid, respawnNoiseFactor, lootSplitFlag, outpostEID, - stabilityPts, overrideRelations, customDeathMessage, customAggressMessage, riftConfigId, - isAnnounced - FROM dbo.npcbossinfo WHERE flockid=@flockid;") - .SetParameter("@flockid", flockid) - .Execute() - .Select(CreateBossInfoFromDB); - - var info = bossInfos.SingleOrDefault(); - if(info == null) - { - return null; - } - info.RespawnTime = config.RespawnTime; - return info; - } - } - - /// /// Specifies the behavior of a Boss-type NPC with various settings /// @@ -92,21 +26,39 @@ public class NpcBossInfo private readonly string _aggroMsg; private readonly CustomRiftConfig _riftConfig; private bool _speak; - - public int FlockId { get; } - public TimeSpan RespawnTime { get; set; } + private bool overrideRelations; + private readonly TimeKeeper _onDamageDebounce = new TimeKeeper(TimeSpan.FromSeconds(5)); + private readonly TimeKeeper _aggroDebounce = new TimeKeeper(TimeSpan.FromSeconds(5)); private bool IsOutpostBoss { get { return _outpostEID != null; } } + private int StabilityPoints { get { return _stabilityPts ?? 0; } } - private bool OverrideRelations { get; } + private bool HasRiftToSpawn { get { return _riftConfig != null; } } + public int FlockId { get; } + + public TimeSpan RespawnTime { get; set; } + public bool IsLootSplit { get; } + public bool IsDead { get; private set; } public bool IsAnnounced { get; private set; } - public NpcBossInfo(EventListenerService eventChannel, int id, int flockid, double? respawnNoiseFactor, bool lootSplit, long? outpostEID, int? stabilityPts, bool overrideRelations, string customDeathMsg, string customAggroMsg, CustomRiftConfig riftConfig, bool announce) + public NpcBossInfo( + EventListenerService eventChannel, + int id, + int flockid, + double? respawnNoiseFactor, + bool lootSplit, + long? outpostEID, + int? stabilityPts, + bool overrideRelations, + string customDeathMsg, + string customAggroMsg, + CustomRiftConfig riftConfig, + bool announce) { _eventChannel = eventChannel; _id = id; @@ -115,7 +67,7 @@ public NpcBossInfo(EventListenerService eventChannel, int id, int flockid, doubl IsLootSplit = lootSplit; _outpostEID = outpostEID; _stabilityPts = stabilityPts; - OverrideRelations = overrideRelations; + this.overrideRelations = overrideRelations; _deathMsg = customDeathMsg; _aggroMsg = customAggroMsg; _riftConfig = riftConfig; @@ -142,18 +94,18 @@ public void OnAggro(Player aggressor) HandleBossOutpostAggro(aggressor); } - // Timer to buffer excessive decrease frequency of messages from OnDamageTaken - private readonly TimeKeeper _onDamageDebounce = new TimeKeeper(TimeSpan.FromSeconds(5)); + + /// /// Handle events to dispatch when the npc boss takes damage /// - /// The npc Boss killed - /// Player damager - public void OnDamageTaken(Npc npc, Player aggressor) + /// The npc Boss killed + /// Player damager + public void OnDamageTaken(SmartCreature smartCreature, Player aggressor) { if (_onDamageDebounce.Expired) { - PublishMessage(new NpcReinforcementsMessage(npc, npc.Zone.Id)); + PublishMessage(new NpcReinforcementsMessage(smartCreature, smartCreature.Zone.Id)); _onDamageDebounce.Reset(); } } @@ -184,13 +136,51 @@ public void OnRespawn() AnnouceRespawn(); } + public override bool Equals(object obj) + { + return Equals(obj as NpcBossInfo); + } + + public bool Equals(NpcBossInfo other) + { + return other != null && ReferenceEquals(this, other) || other._id == _id && other.FlockId == FlockId; + } + + public override int GetHashCode() + { + unchecked + { + int hash = 23; + + hash = hash * 31 + _id.GetHashCode(); + hash = hash * 31 + FlockId.GetHashCode(); + + return hash; + } + } + + /// + /// Apply any respawn timer modifiers + /// + /// normal respawn time of npc + /// modified respawn time of npc + public TimeSpan GetNextSpawnTime(TimeSpan respawnTime) + { + var factor = _respawnNoiseFactor ?? 0.0; + + return respawnTime.Multiply(FastRandom.NextDouble(1.0 - factor, 1.0 + factor)); + } + private void AnnouceRespawn() { if (!IsAnnounced) + { return; + } var randomDelay = FastRandom.NextTimeSpan(RespawnTime.Divide(5), RespawnTime.Divide(2)); var timeStamp = DateTime.UtcNow; + Task.Delay(randomDelay).ContinueWith((t) => { PublishMessage(new NpcStateMessage(FlockId, NpcState.Alive, timeStamp)); @@ -200,22 +190,13 @@ private void AnnouceRespawn() private void AnnounceDeath() { if (!IsAnnounced) + { return; + } PublishMessage(new NpcStateMessage(FlockId, NpcState.Dead, DateTime.UtcNow)); } - /// - /// Apply any respawn timer modifiers - /// - /// normal respawn time of npc - /// modified respawn time of npc - public TimeSpan GetNextSpawnTime(TimeSpan respawnTime) - { - var factor = _respawnNoiseFactor ?? 0.0; - return respawnTime.Multiply(FastRandom.NextDouble(1.0 - factor, 1.0 + factor)); - } - private void HandleBossOutpostAggro(Player aggressor) { if (IsOutpostBoss) @@ -224,9 +205,6 @@ private void HandleBossOutpostAggro(Player aggressor) } } - - // Timer to buffer excessive decrease frequency of messages from OnDamageTaken - private readonly TimeKeeper _aggroDebounce = new TimeKeeper(TimeSpan.FromSeconds(5)); private void CommunicateAggression(Unit aggressor) { if (_aggroDebounce.Expired && _speak) @@ -245,22 +223,30 @@ private void CommunicateDeath(Unit aggressor) private void HandleBossOutpostDeath(Npc npc, Unit killer) { if (!IsOutpostBoss) + { return; + } var zone = npc.Zone; + IEnumerable outposts = zone.Units.OfType(); + var outpost = outposts.First(o => o.Eid == _outpostEID); + if (outpost is Outpost) { - var participants = npc.ThreatManager.Hostiles.Select(x => zone.ToPlayerOrGetOwnerPlayer(x.unit)).ToList(); + var participants = npc.ThreatManager.Hostiles + .Select(x => zone.ToPlayerOrGetOwnerPlayer(x.Unit)) + .ToList(); var builder = StabilityAffectingEvent.Builder() .WithOutpost(outpost as Outpost) - .WithOverrideRelations(OverrideRelations) + .WithOverrideRelations(overrideRelations) .WithSapDefinition(npc.Definition) .WithSapEntityID(npc.Eid) .WithPoints(StabilityPoints) .AddParticipants(participants) .WithWinnerCorp(zone.ToPlayerOrGetOwnerPlayer(killer).CorporationEid); + PublishMessage(builder.Build()); } } @@ -268,7 +254,9 @@ private void HandleBossOutpostDeath(Npc npc, Unit killer) private void SpawnPortal(Npc npc, Unit killer) { if (!HasRiftToSpawn) + { return; + } PublishMessage(new SpawnPortalMessage(npc.Zone.Id, npc.CurrentPosition, _riftConfig)); } @@ -281,30 +269,9 @@ private void SendMessage(Unit src, string msg) } } - private void PublishMessage (IEventMessage eventMessage) + private void PublishMessage(IEventMessage eventMessage) { _eventChannel.PublishMessage(eventMessage); } - - public override bool Equals(object obj) - { - return Equals(obj as NpcBossInfo); - } - - public bool Equals(NpcBossInfo other) - { - return other != null && ReferenceEquals(this, other) || other._id == _id && other.FlockId == FlockId; - } - - public override int GetHashCode() - { - unchecked - { - int hash = 23; - hash = hash * 31 + _id.GetHashCode(); - hash = hash * 31 + FlockId.GetHashCode(); - return hash; - } - } } } diff --git a/src/Perpetuum/Zones/NpcSystem/Npc.cs b/src/Perpetuum/Zones/NpcSystem/Npc.cs index d98f913e0..40ff31c43 100644 --- a/src/Perpetuum/Zones/NpcSystem/Npc.cs +++ b/src/Perpetuum/Zones/NpcSystem/Npc.cs @@ -1,932 +1,192 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.Linq; -using System.Numerics; -using System.Threading; -using System.Threading.Tasks; -using Perpetuum.Collections; using Perpetuum.Data; using Perpetuum.EntityFramework; -using Perpetuum.ExportedTypes; -using Perpetuum.Items; using Perpetuum.Log; -using Perpetuum.Modules.Weapons; -using Perpetuum.PathFinders; using Perpetuum.Players; using Perpetuum.Services.Looting; using Perpetuum.Services.MissionEngine; using Perpetuum.Services.MissionEngine.MissionTargets; -using Perpetuum.StateMachines; -using Perpetuum.Timers; using Perpetuum.Units; -using Perpetuum.Zones.DamageProcessors; using Perpetuum.Zones.Eggs; -using Perpetuum.Zones.Locking; -using Perpetuum.Zones.Locking.Locks; -using Perpetuum.Zones.Movements; -using Perpetuum.Zones.NpcSystem.Flocks; -using Perpetuum.Zones.Terrains; +using Perpetuum.Zones.RemoteControl; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Numerics; +using System.Threading.Tasks; namespace Perpetuum.Zones.NpcSystem { - - public enum NpcBehaviorType - { - Passive, - Neutral, - Aggressive - } - - public enum NpcSpecialType - { - Normal, - Boss - } - - public abstract class NpcAI : IState - { - protected readonly Npc npc; - - protected NpcAI(Npc npc) - { - this.npc = npc; - } - - public virtual void Enter() - { - WriteLog("enter state = " + GetType().Name); - } - - public virtual void Exit() - { - npc.StopMoving(); - WriteLog("exit state = " + GetType().Name); - } - - public abstract void Update(TimeSpan time); - - protected virtual void ToHomeAI() - { - npc.AI.Push(new HomingAI(npc)); - } - - protected virtual void ToAggressorAI() - { - if (npc.Behavior.Type == NpcBehaviorType.Passive) - return; - - npc.AI.Push(new AggressorAI(npc)); - } - - [Conditional("DEBUG")] - protected void WriteLog(string message) - { - //Logger.DebugInfo($"NpcAI: {message}"); - } - } - - public class IdleAI : NpcAI - { - private RandomMovement _movement; - - public IdleAI(Npc npc) : base(npc) { } - - public override void Enter() - { - npc.StopAllModules(); - npc.ResetLocks(); - _movement = new RandomMovement(npc.HomePosition, npc.HomeRange); - _movement.Start(npc); - base.Enter(); - } - - public override void Update(TimeSpan time) - { - if (!npc.IsInHomeRange) - { - ToHomeAI(); - return; - } - - if (npc.ThreatManager.IsThreatened) - { - ToAggressorAI(); - return; - } - - _movement?.Update(npc, time); - } - } - - public class StationaryIdleAI : NpcAI - { - public StationaryIdleAI(Npc npc) : base(npc) { } - - public override void Enter() - { - npc.StopAllModules(); - npc.ResetLocks(); - base.Enter(); - } - - public override void Update(TimeSpan time) - { - if (npc.ThreatManager.IsThreatened) - { - ToAggressorAI(); - } - } - - protected override void ToHomeAI() { } - - protected override void ToAggressorAI() - { - if (npc.Behavior.Type == NpcBehaviorType.Passive) - return; - - npc.AI.Push(new StationaryCombatAI(npc)); - } - } - - public class StationaryCombatAI : CombatAI - { - private readonly IntervalTimer _updateFrequency = new IntervalTimer(650); - public StationaryCombatAI(Npc npc) : base(npc) { } - - protected override PrimaryLockSelectionStrategySelector InitSelector() - { - return PrimaryLockSelectionStrategySelector.Create() - .WithStrategy(PrimaryLockStrategy.Hostile, 1) - .WithStrategy(PrimaryLockStrategy.Closest, 2) - .WithStrategy(PrimaryLockStrategy.OptimalRange, 3) - .WithStrategy(PrimaryLockStrategy.Random, 10) - .Build(); - } - - public override void Update(TimeSpan time) - { - FindHostiles(time); - base.Update(time); - } - - private void FindHostiles(TimeSpan time) - { - _updateFrequency.Update(time); - if (_updateFrequency.Passed) - { - _updateFrequency.Reset(); - npc.LookingForHostiles(); - } - } - - protected override TimeSpan SetPrimaryDwellTime() - { - return FastRandom.NextTimeSpan(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(25)); - } - } - - public class CombatAI : NpcAI - { - private List _moduleActivators; - protected bool _npcHasMissiles = false; - private const int UPDATE_FREQ = 1650; - private TimeSpan _hostilesUpdateFrequency = TimeSpan.FromMilliseconds(UPDATE_FREQ); - private readonly IntervalTimer _processHostilesTimer = new IntervalTimer(UPDATE_FREQ); - private readonly IntervalTimer _primarySelectTimer = new IntervalTimer(UPDATE_FREQ); - private PrimaryLockSelectionStrategySelector _stratSelector; - public CombatAI(Npc npc) : base(npc) { } - - protected virtual PrimaryLockSelectionStrategySelector InitSelector() - { - return PrimaryLockSelectionStrategySelector.Create() - .WithStrategy(PrimaryLockStrategy.Hostile, 9) - .WithStrategy(PrimaryLockStrategy.Random, 1) - .Build(); - } - - public override void Enter() - { - _stratSelector = InitSelector(); - _moduleActivators = npc.ActiveModules.Select(m => new ModuleActivator(m)).ToList(); - _npcHasMissiles = npc.ActiveModules.OfType().Any(); - _processHostilesTimer.Update(_hostilesUpdateFrequency); - _primarySelectTimer.Update(_hostilesUpdateFrequency); - base.Enter(); - } - - public override void Update(TimeSpan time) - { - UpdateHostiles(time); - UpdatePrimaryTarget(time); - RunModules(time); - } - - protected void UpdateHostiles(TimeSpan time) - { - _processHostilesTimer.Update(time); - if (_processHostilesTimer.Passed) - { - _processHostilesTimer.Reset(); - ProcessHostiles(); - } - } - - protected void UpdatePrimaryTarget(TimeSpan time) - { - _primarySelectTimer.Update(time); - if (_primarySelectTimer.Passed) - { - var success = SelectPrimaryTarget(); - SetPrimaryUpdateDelay(success); - } - } - - protected void RunModules(TimeSpan time) - { - foreach (var activator in _moduleActivators) - { - activator.Update(time); - } - } - - private UnitLock[] GetValidLocks() - { - return npc.GetLocks().Select(l => (UnitLock)l).Where(u => IsLockValidTarget(u)).ToArray(); - } - - private bool SelectPrimaryTarget() - { - var validLocks = GetValidLocks(); - if (validLocks.Length < 1) - return false; - - return _stratSelector?.TryUseStrategy(npc, validLocks) ?? false; - } - - private bool IsLockValidTarget(UnitLock unitLock) - { - if (unitLock == null || unitLock.State != LockState.Locked) - return false; - - var visibility = npc.GetVisibility(unitLock.Target); - if (visibility == null) - return false; - - var r = visibility.GetLineOfSight(_npcHasMissiles); - if (r != null) - { - if (r.hit && (r.blockingFlags & BlockingFlags.Plant) == 0) - return false; - } - return unitLock.Target.GetDistance(npc) < npc.MaxCombatRange; - } - - protected virtual TimeSpan SetPrimaryDwellTime() - { - return FastRandom.NextTimeSpan(TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10)); - } - - protected virtual void SetPrimaryUpdateDelay(bool newPrimary) - { - if (newPrimary) - { - _primarySelectTimer.Interval = SetPrimaryDwellTime(); - } - else if (GetValidLocks().Length > 0) - { - _primarySelectTimer.Interval = TimeSpan.FromSeconds(1); - } - else if (npc.GetLocks().Count > 0) - { - _primarySelectTimer.Interval = TimeSpan.FromSeconds(1.5); - } - else - { - _primarySelectTimer.Interval = TimeSpan.FromSeconds(3.5); - } - } - - protected bool IsAttackable(Hostile hostile) - { - if (!hostile.unit.InZone) - return false; - - if (hostile.unit.States.Dead) - return false; - - if (!hostile.unit.IsLockable) - return false; - - if (hostile.unit.IsAttackable != ErrorCodes.NoError) - return false; - - if (hostile.unit.IsInvulnerable) - return false; - - if (npc.Behavior.Type == NpcBehaviorType.Neutral) - { - if (hostile.IsExpired) - return false; - } - - var isVisible = npc.IsVisible(hostile.unit); - if (!isVisible) - return false; - - return true; - } - - private void SetLockForHostile(Hostile hostile) - { - var mostHated = GetPrimaryOrMostHatedHostile() == hostile; - - var l = npc.GetLockByUnit(hostile.unit); - if (l == null) - { - if (TryMakeFreeLockSlotFor(hostile)) - npc.AddLock(hostile.unit, mostHated); - } - else - { - if (mostHated && !l.Primary) - npc.SetPrimaryLock(l.Id); - } - } - - protected virtual void ProcessHostiles() - { - var hostileEnumerator = npc.ThreatManager.Hostiles.GetEnumerator(); - while (hostileEnumerator.MoveNext()) - { - var hostile = hostileEnumerator.Current; - if (!IsAttackable(hostile)) - { - npc.ThreatManager.Remove(hostile); - npc.AddPseudoThreat(hostile.unit); - continue; - } - - if (!npc.IsInLockingRange(hostile.unit)) - continue; - - SetLockForHostile(hostile); - } - } - - protected bool TryMakeFreeLockSlotFor(Hostile hostile) - { - if (npc.HasFreeLockSlot) - return true; - - var weakestLock = npc.ThreatManager.Hostiles.SkipWhile(h => h != hostile).Skip(1).Select(h => npc.GetLockByUnit(h.unit)).LastOrDefault(); - if (weakestLock == null) - return false; - - weakestLock.Cancel(); - return true; - } - - protected Hostile GetPrimaryOrMostHatedHostile() - { - var primaryHostile = npc.ThreatManager.Hostiles.Where(h => h.unit == (npc.GetPrimaryLock() as UnitLock)?.Target).FirstOrDefault(); - if (primaryHostile != null) - return primaryHostile; - return npc.ThreatManager.GetMostHatedHostile(); - } - } - - public class HomingAI : CombatAI - { - private PathMovement _movement; - private readonly double _maxReturnHomeRadius; - private readonly PathFinder _pathFinder; - - public HomingAI(Npc npc) : base(npc) - { - _maxReturnHomeRadius = (npc.HomeRange * 0.4).Clamp(3, 20); - _pathFinder = new AStarFinder(Heuristic.Manhattan, npc.IsWalkable); - } - - public override void Enter() - { - var randomHome = npc.Zone.FindPassablePointInRadius(npc.HomePosition, (int)_maxReturnHomeRadius); - if(randomHome == default) - { - randomHome = npc.HomePosition; - } - _pathFinder.FindPathAsync(npc.CurrentPosition, randomHome).ContinueWith(t => - { - var path = t.Result; - if (path == null) - { - WriteLog("Path not found! (" + npc.CurrentPosition + " => " + npc.HomePosition + ")"); - - var f = new AStarFinder(Heuristic.Manhattan,(x,y) => true); - path = f.FindPath(npc.CurrentPosition, npc.HomePosition); - - if (path == null) - { - WriteLog("Safe path not found! (" + npc.CurrentPosition + " => " + npc.HomePosition + ")"); - } - } - - _movement = new PathMovement(path); - _movement.Start(npc); - npc.BossInfo?.OnDeAggro(); - }); - - base.Enter(); - } - - public override void Update(TimeSpan time) - { - if (_movement != null) - { - _movement.Update(npc, time); - - if (_movement.Arrived) - { - npc.AI.Pop(); - return; - } - } - - base.Update(time); - } - - protected override void ToHomeAI() { } - protected override void ToAggressorAI() { } - } - - public class AggressorAI : CombatAI + public class Npc : SmartCreature, ITaggable { - public AggressorAI(Npc npc) : base(npc){ } - - protected override void ToAggressorAI(){ } - - public override void Exit() - { - _source?.Cancel(); - - base.Exit(); - } - - public override void Update(TimeSpan time) - { - if (!npc.IsInHomeRange) - { - npc.AI.Push(new HomingAI(npc)); - return; - } + private readonly TagHelper tagHelper; - if (!npc.ThreatManager.IsThreatened) - { - EnterEvadeMode(); - return; - } - - UpdateHostile(time); - - base.Update(time); - } - - private void EnterEvadeMode() - { - npc.AI.Pop(); - npc.AI.Push(new HomingAI(npc)); - WriteLog("Enter evade mode."); - } - - private Position _lastTargetPosition; - private PathMovement _movement; - private PathMovement _nextMovement; - - private void UpdateHostile(TimeSpan time) + public Npc(TagHelper tagHelper) { - var mostHated = GetPrimaryOrMostHatedHostile(); - if (mostHated == null) - return; - - if (!mostHated.unit.CurrentPosition.IsEqual2D(_lastTargetPosition)) - { - _lastTargetPosition = mostHated.unit.CurrentPosition; - - var findNewTargetPosition = false; - - if (!npc.IsInRangeOf3D(mostHated.unit, npc.BestCombatRange)) - { - findNewTargetPosition = true; - } - else - { - var visibility = npc.GetVisibility(mostHated.unit); - if (visibility != null) - { - var r = visibility.GetLineOfSight(_npcHasMissiles); - if (r.hit) - findNewTargetPosition = true; - } - } - - if (findNewTargetPosition) - { - FindNewAttackPositionAsync(mostHated.unit).ContinueWith(t => - { - if (t.IsCanceled) - return; - - var path = t.Result; - if (path == null) - { - npc.ThreatManager.Remove(mostHated); - npc.AddPseudoThreat(mostHated.unit); - return; - } - - Interlocked.Exchange(ref _nextMovement,new PathMovement(path)); - }); - } - } - - if (_nextMovement != null) - { - _movement = Interlocked.Exchange(ref _nextMovement, null); - _movement.Start(npc); - } - - _movement?.Update(npc, time); + this.tagHelper = tagHelper; } - private CancellationTokenSource _source; - - private const int SQRT2 = 141; - private const int WEIGHT = 1000; + public NpcSpecialType SpecialType { get; set; } - private Task> FindNewAttackPositionAsync(Unit hostile) - { - _source?.Cancel(); + public int EP { get; private set; } - _source = new CancellationTokenSource(); - return Task.Run(() => FindNewAttackPosition(hostile, _source.Token), _source.Token); - } + public ILootGenerator LootGenerator { get; set; } - private List FindNewAttackPosition(Unit hostile,CancellationToken cancellationToken) + public void Tag(Player tagger, TimeSpan duration) { - var end = hostile.CurrentPosition.GetRandomPositionInRange2D(0, npc.BestCombatRange - 1).ToPoint(); - - npc.StopMoving(); - - var maxNode = Math.Pow(npc.HomeRange, 2) * Math.PI; - var pq = new PriorityQueue((int) maxNode); - var startNode = new Node(npc.CurrentPosition); - - pq.Enqueue(startNode); - - var closed = new HashSet(); - closed.Add(startNode.position); - - Node current; - while (pq.TryDequeue(out current)) - { - if (cancellationToken.IsCancellationRequested) - return null; - - if (IsValidAttackPosition(hostile, current.position)) - return BuildPath(current); - - foreach (var n in current.position.GetNeighbours()) - { - if (closed.Contains(n)) - continue; - - closed.Add(n); - - if (!npc.IsWalkable(n.X, n.Y)) - continue; - - if (!n.IsInRange(npc.HomePosition, npc.HomeRange)) - continue; - - var newG = current.g + (n.X - current.position.X == 0 || n.Y - current.position.Y == 0 ? 100 : SQRT2); - var newH = Heuristic.Manhattan.Calculate(n.X, n.Y, end.X, end.Y) * WEIGHT; - - var newNode = new Node(n) - { - g = newG, - f = newG + newH, - parent = current - }; - - pq.Enqueue(newNode); - } - } - - return null; + tagHelper.DoTagging(this, tagger, duration); } - private bool IsValidAttackPosition(Unit hostile,Point position) + [CanBeNull] + public Player GetTagger() { - var position3 = npc.Zone.FixZ(position.ToPosition()).AddToZ(npc.Height); - - if (!hostile.CurrentPosition.IsInRangeOf3D(position3, npc.BestCombatRange)) - return false; - - var r = npc.Zone.IsInLineOfSight(position3, hostile, false); - return !r.hit; + return TagHelper.GetTagger(this); } - private static List BuildPath(Node current) + public override void AcceptVisitor(IEntityVisitor visitor) { - var stack = new Stack(); - - var node = current; - while (node != null) + if (!TryAcceptVisitor(this, visitor)) { - stack.Push(node.position); - node = node.parent; + base.AcceptVisitor(visitor); } - - return stack.ToList(); } - private class Node : IComparable + public override IDictionary GetDebugInfo() { - public readonly Point position; - public Node parent; - public int g; - public int f; - - public Node(Point position) - { - this.position = position; - } - - public int CompareTo(Node other) - { - return f - other.f; - } - - public override int GetHashCode() - { - return position.GetHashCode(); - } - } - } + var info = base.GetDebugInfo(); + var homeDistance = HomePosition.TotalDistance2D(CurrentPosition); - public class NpcBehavior - { - public NpcBehaviorType Type { get; private set; } + info.Add("homePositionX", HomePosition.intX); + info.Add("homePositionY", HomePosition.intY); + info.Add("homeRange", HomeRange); + info.Add("homeDistance", homeDistance); + info.Add("coreMax", CoreMax); + info.Add("coreCurrent", Core); + info.Add("bestCombatRange", BestActionRange); - protected NpcBehavior(NpcBehaviorType type) - { - Type = type; - } + var currentAI = AI.Current; - public static NpcBehavior Create(NpcBehaviorType type) - { - switch (type) + if (currentAI != null) { - case NpcBehaviorType.Neutral: - return new NeutralBehavior(); - case NpcBehaviorType.Aggressive: - return new AggressiveBehavior(); - case NpcBehaviorType.Passive: - return new PassiveBehavior(); - default: - return new PassiveBehavior(); + info.Add("fsm", currentAI.GetType().Name); } - } - } - - public class PassiveBehavior : NpcBehavior - { - public PassiveBehavior() : base(NpcBehaviorType.Passive) - { - } - } - - public class NeutralBehavior : NpcBehavior - { - public NeutralBehavior() : base(NpcBehaviorType.Neutral) - { - } - } - - public class AggressiveBehavior : NpcBehavior - { - public AggressiveBehavior() : base(NpcBehaviorType.Aggressive) - { - } - } - - public class Npc : Creature, ITaggable - { - private readonly TagHelper _tagHelper; - private const double CALL_FOR_HELP_ARMOR_THRESHOLD = 0.2; - private readonly ThreatManager _threatManager; - private Lazy _maxCombatRange; - private Lazy _optimalCombatRange; - private TimeSpan _lastHelpCalled; - private readonly IPseudoThreatManager _pseudoThreatManager; - - public Npc(TagHelper tagHelper) - { - _maxCombatRange = new Lazy(CalculateMaxCombatRange); - _optimalCombatRange = new Lazy(CalculateCombatRange); - _tagHelper = tagHelper; - _threatManager = new ThreatManager(); - AI = new StackFSM(); - _pseudoThreatManager = new PseudoThreatManager(); - } - public NpcBehavior Behavior { get; set; } - public NpcSpecialType SpecialType { get; set; } - public NpcBossInfo BossInfo { get; set; } - public int EP { get; private set; } + info.Add("threat", ThreatManager.ToDebugString()); + Group?.AddDebugInfoToDictionary(info); + info.Add("ismission", GetMissionGuid() != Guid.Empty); - [CanBeNull] - private INpcGroup _group; - - public void SetGroup(INpcGroup group) - { - _group = group; - } - - public INpcGroup Group - { - get { return _group; } - } - - public StackFSM AI { get; private set; } - - public IThreatManager ThreatManager - { - get { return _threatManager; } - } - - public ILootGenerator LootGenerator { get; set; } - - public double HomeRange { get; set; } - public Position HomePosition { get; set; } - - public bool IsInHomeRange - { - get { return CurrentPosition.IsInRangeOf2D(HomePosition, HomeRange); } + return info; } - public int BestCombatRange + protected override void OnDead(Unit killer) { - get { return _optimalCombatRange.Value; } - } + var zone = Zone; + var tagger = GetTagger(); - public int MaxCombatRange - { - get { return _maxCombatRange.Value; } - } + Debug.Assert(zone != null, "zone != null"); - public bool IsStationary - { - get { return MaxSpeed.IsZero(); } + BossInfo?.OnDeath(this, killer); + HandleNpcDeadAsync(zone, killer, tagger) + .ContinueWith((t) => base.OnDead(killer)) + .LogExceptions(); } - public void Tag(Player tagger,TimeSpan duration) + public override bool IsWalkable(Vector2 position) { - _tagHelper.DoTagging(this,tagger,duration); + return Zone.IsWalkableForNpc((int)position.X, (int)position.Y, Slope); } - [CanBeNull] - public Player GetTagger() + public override bool IsWalkable(Position position) { - return TagHelper.GetTagger(this); + return Zone.IsWalkableForNpc((int)position.X, (int)position.Y, Slope); } - public void AddThreat(Unit hostile, Threat threat, bool spreadToGroup) + public override bool IsWalkable(int x, int y) { - if (hostile.IsPlayer()) - { - BossInfo?.OnAggro(hostile as Player); - } - _threatManager.GetOrAddHostile(hostile).AddThreat(threat); - - RemovePseudoThreat(hostile); - - if (!spreadToGroup) - return; - - var group = _group; - if (@group == null) - return; - - var t = Threat.Multiply(threat, 0.5); - - foreach (var member in @group.Members) - { - if (member == this) - continue; - member.AddThreat(hostile,t,false); - } + return Zone.IsWalkableForNpc(x, y, Slope); } - public void AddPseudoThreat(Unit hostile) + protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) { - _pseudoThreatManager.AddOrRefreshExisting(hostile); + SetEP(zone); + + base.OnEnterZone(zone, enterType); } - private readonly IntervalTimer _psuedoUpdateFreq = new IntervalTimer(TimeSpan.FromMilliseconds(650)); - private void UpdatePseudoThreats(TimeSpan time) + private void SetEP(IZone zone) { - _psuedoUpdateFreq.Update(time); - if (_psuedoUpdateFreq.Passed) + if (zone.Configuration.Type == ZoneType.Training) { - _pseudoThreatManager.Update(_psuedoUpdateFreq.Elapsed); - _psuedoUpdateFreq.Reset(); + EP = 0; + return; } - } - private void RemovePseudoThreat(Unit hostile) - { - _pseudoThreatManager.Remove(hostile); - } + var ep = NpcEp.GetEpForNpc(this); - public override void AcceptVisitor(IEntityVisitor visitor) - { - if (!TryAcceptVisitor(this, visitor)) - base.AcceptVisitor(visitor); + if (zone.Configuration.IsBeta) + ep *= 2; + + EP = ep; + Logger.DebugInfo($"Ep4Npc:{ep} def:{Definition} {ED.Name}"); } - protected override void OnPropertyChanged(ItemProperty property) + public override string InfoString { - base.OnPropertyChanged(property); - - switch (property.Field) + get { - case AggregateField.locking_range: + var infoString = $"Npc:{ED.Name}:{Eid}"; + + var zone = Zone; + if (zone != null) { - _optimalCombatRange = new Lazy(CalculateCombatRange); - _maxCombatRange = new Lazy(CalculateMaxCombatRange); - break; + infoString += " z:" + zone.Id; } - case AggregateField.armor_current: - { - var percentage = Armor.Ratio(ArmorMax); - if (percentage <= CALL_FOR_HELP_ARMOR_THRESHOLD) - { - CallingForHelp(); - } - break; + if (Group != null) + { + infoString += " g:" + Group.Name; } + + return infoString; } } - public override IDictionary GetDebugInfo() + public override bool IsHostile(Player player) { - var info = base.GetDebugInfo(); - var homeDistance = HomePosition.TotalDistance2D(CurrentPosition); - - info.Add("homePositionX", HomePosition.intX); - info.Add("homePositionY", HomePosition.intY); - info.Add("homeRange", HomeRange); - info.Add("homeDistance", homeDistance); - info.Add("coreMax", CoreMax); - info.Add("coreCurrent", Core); - info.Add("bestCombatRange", BestCombatRange); - - var currentAI = AI.Current; - if (currentAI != null) - info.Add("fsm", currentAI.GetType().Name); - - info.Add("threat", _threatManager.ToDebugString()); - - _group?.AddDebugInfoToDictionary(info); - - info.Add("ismission",GetMissionGuid() != Guid.Empty); + return true; + } - return info; + internal override bool IsHostile(AreaBomb bomb) + { + return true; } - protected override void OnDamageTaken(Unit source, DamageTakenEventArgs e) + internal override bool IsHostile(SentryTurret turret) { - base.OnDamageTaken(source, e); + return true; + } - var player = Zone.ToPlayerOrGetOwnerPlayer(source); - if (player == null) - return; + internal override bool IsHostile(IndustrialTurret turret) + { + return true; + } - BossInfo?.OnDamageTaken(this, player); - AddThreat(player, new Threat(ThreatType.Damage, e.TotalDamage * 0.9), true); + internal override bool IsHostile(CombatDrone drone) + { + return true; } - protected override void OnDead(Unit killer) + protected override bool IsHostileFor(Unit unit) { - var zone = Zone; - var tagger = GetTagger(); - Debug.Assert(zone != null, "zone != null"); + return unit.IsHostile(this); + } - BossInfo?.OnDeath(this, killer); - HandleNpcDeadAsync(zone, killer, tagger).ContinueWith((t) => base.OnDead(killer)).LogExceptions(); + protected override void UpdateUnitVisibility(Unit target) + { + if (target is RemoteControlledCreature) + { + UpdateVisibility(target); + } } private Task HandleNpcDeadAsync(IZone zone, Unit killer, Player tagger) @@ -940,29 +200,30 @@ private void HandleNpcDead([NotNull] IZone zone, Unit killer, Player tagger) using (var scope = Db.CreateTransaction()) { - if (BossInfo?.IsLootSplit ?? false) { - //Boss - Split loot equally to all participants List participants = new List(); - participants = ThreatManager.Hostiles.Select(x => zone.ToPlayerOrGetOwnerPlayer(x.unit)).ToList(); + participants = ThreatManager.Hostiles.Select(x => zone.ToPlayerOrGetOwnerPlayer(x.Unit)).ToList(); + if (participants.Count > 0) { ISplittableLootGenerator splitLooter = new SplittableLootGenerator(LootGenerator); List lootGenerators = splitLooter.GetGenerators(participants.Count); + for (var i = 0; i < participants.Count; i++) { - LootContainer.Create().SetOwner(participants[i]).AddLoot(lootGenerators[i]).BuildAndAddToZone(zone, participants[i].CurrentPosition); + LootContainer.Create() + .SetOwner(participants[i]) + .AddLoot(lootGenerators[i]) + .BuildAndAddToZone(zone, participants[i].CurrentPosition); } } } else { - //Normal case: loot can awarded in full to tagger LootContainer.Create().SetOwner(tagger).AddLoot(LootGenerator).BuildAndAddToZone(zone, CurrentPosition); } - var killerPlayer = zone.ToPlayerOrGetOwnerPlayer(killer); if (GetMissionGuid() != Guid.Empty) @@ -976,28 +237,31 @@ private void HandleNpcDead([NotNull] IZone zone, Unit killer, Player tagger) Logger.DebugInfo(" >>>> independent NPC."); if (killerPlayer != null) + { EnqueueKill(killerPlayer, killer); + } } if (EP > 0) { var awardedPlayers = new List(); - foreach (var hostile in ThreatManager.Hostiles) + + foreach (var hostile in ThreatManager.Hostiles.Where(x => x.Unit is Player)) { - var playerUnit = hostile.unit; + var playerUnit = hostile.Unit; var hostilePlayer = zone.ToPlayerOrGetOwnerPlayer(playerUnit); + hostilePlayer?.Character.AddExtensionPointsBoostAndLog(EpForActivityType.Npc, EP); awardedPlayers.Add(playerUnit); } - _pseudoThreatManager.AwardPseudoThreats(awardedPlayers, zone, EP); + PseudoThreatManager.AwardPseudoThreats(awardedPlayers, zone, EP); } scope.Complete(); } } - /// /// This occurs when aoe kills the npc. /// Background task that searches for the related missionguid and sumbits the kill for that specific player @@ -1006,13 +270,10 @@ private void SearchForMissionOwnerAndSubmitKill(IZone zone, Unit killerUnit) { var missionGuid = GetMissionGuid(); var missionOwner = MissionHelper.FindMissionOwnerByGuid(missionGuid); - var missionOwnerPlayer = zone.GetPlayer(missionOwner); + if (missionOwnerPlayer == null) { - //the owner is not this zone - //address the mission plugin directly - var info = new Dictionary { {k.characterID, missionOwner.Id}, @@ -1021,7 +282,7 @@ private void SearchForMissionOwnerAndSubmitKill(IZone zone, Unit killerUnit) {k.definition, ED.Definition}, {k.increase ,1}, {k.zoneID, zone.Id}, - {k.position, killerUnit.CurrentPosition} + {k.position, killerUnit.CurrentPosition}, }; if (killerUnit is Player killerPlayer && killerPlayer.Character.Id != missionOwner.Id) @@ -1031,317 +292,27 @@ private void SearchForMissionOwnerAndSubmitKill(IZone zone, Unit killerUnit) Task.Run(() => { - MissionHelper.MissionProcessor.NpcGotKilledInAway(missionOwner,missionGuid,info); + MissionHelper.MissionProcessor.NpcGotKilledInAway(missionOwner, missionGuid, info); }); + return; } - - //local enqueue, this is the proper player, we can skip gang + EnqueueKill(missionOwnerPlayer, killerUnit); } private void EnqueueKill(Player missionOwnerPlayer, Unit killerUnit) { var eventSourcePlayer = missionOwnerPlayer; - var killerPlayer = killerUnit as Player; - if (killerPlayer != null && !killerPlayer.Equals(missionOwnerPlayer)) + + if (killerUnit is Player killerPlayer && !killerPlayer.Equals(missionOwnerPlayer)) { eventSourcePlayer = killerPlayer; } Logger.DebugInfo($" >>>> EventSource: botName:{eventSourcePlayer.Name} o:{eventSourcePlayer.Owner} characterId:{eventSourcePlayer.Character.Id} MissionOwner: botName:{missionOwnerPlayer.Name} o:{missionOwnerPlayer.Owner} characterId:{missionOwnerPlayer.Character.Id}"); - //local enqueue, this is the proper player, we can skip gang missionOwnerPlayer.MissionHandler.EnqueueMissionEventInfoLocally(new KillEventInfo(eventSourcePlayer, this, CurrentPosition)); } - - protected override void OnTileChanged() - { - base.OnTileChanged(); - LookingForHostiles(); - } - - public void LookingForHostiles() - { - foreach (var visibility in GetVisibleUnits()) - { - AddBodyPullThreat(visibility.Target); - } - } - - protected override void OnUpdate(TimeSpan time) - { - base.OnUpdate(time); - - AI.Update(time); - - UpdatePseudoThreats(time); - } - - protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) - { - SetEP(zone); - States.Aggressive = Behavior.Type == NpcBehaviorType.Aggressive; - - base.OnEnterZone(zone, enterType); - - if (IsStationary) - { - AI.Push(new StationaryIdleAI(this)); - } - else - { - AI.Push(new IdleAI(this)); - } - } - - private void SetEP(IZone zone) - { - if (zone.Configuration.Type == ZoneType.Training) - { - EP = 0; - return; - } - - var ep = NpcEp.GetEpForNpc(this); - - if (zone.Configuration.IsBeta) - ep *= 2; - - EP = ep; - Logger.DebugInfo($"Ep4Npc:{ep} def:{Definition} {ED.Name}"); - } - - public override string InfoString - { - get - { - var s = $"Npc:{ED.Name}:{Eid}"; - - var zone = Zone; - if (zone != null) - { - s += " z:" + zone.Id; - } - - if (_group != null) - s += " g:" + _group.Name; - - return s; - } - } - - private const double AGGRO_RANGE = 30; - - private bool IsInAggroRange(Unit target) - { - return IsStationary || IsInRangeOf3D(target, AGGRO_RANGE); - } - - private readonly TimeKeeper _debounceLockChange = new TimeKeeper(TimeSpan.FromSeconds(2.5)); - protected override void OnUnitLockStateChanged(Lock @lock) - { - if (!_debounceLockChange.Expired) - return; - - var unitLock = @lock as UnitLock; - if (unitLock == null) - return; - - if (unitLock.Target != this) - return; - - if (unitLock.State != LockState.Locked) - return; - - var threatValue = unitLock.Primary ? Threat.LOCK_PRIMARY : Threat.LOCK_SECONDARY; - AddThreat(unitLock.Owner, new Threat(ThreatType.Lock, threatValue), true); - _debounceLockChange.Reset(); - } - - private readonly TimeKeeper _debounceBodyPull = new TimeKeeper(TimeSpan.FromSeconds(2.5)); - protected override void OnUnitTileChanged(Unit target) - { - if (!_debounceBodyPull.Expired) - return; - - AddBodyPullThreat(target); - _debounceBodyPull.Reset(); - } - - internal override bool IsHostile(Player player) - { - return true; - } - - internal override bool IsHostile(AreaBomb bomb) - { - return true; - } - - /// - /// This determines if threat can be added to a target based on the following: - /// - Is the target already on the threat manager - /// - Or is the npc non-passive and the Threat is of some defined type - /// - /// Unit target - /// Threat threat - /// If the target can be a threat - public bool CanAddThreatTo(Unit target, Threat threat) - { - if (_threatManager.Contains(target)) - return true; - - if (Behavior.Type == NpcBehaviorType.Passive) - return false; - - return threat.type != ThreatType.Undefined; - } - - private void AddBodyPullThreat(Unit enemy) - { - if ( !IsHostile(enemy)) - return; - - var helper = new BodyPullThreatHelper(this); - enemy.AcceptVisitor(helper); - } - - public bool CallForHelp { private get; set; } - - private void CallingForHelp() - { - if (!CallForHelp) - return; - - if (!GlobalTimer.IsPassed(ref _lastHelpCalled, TimeSpan.FromSeconds(5))) - return; - - var group = _group; - if (group == null) - return; - - foreach (var member in group.Members.Where(flockMember => flockMember != this)) - { - member.HelpingFor(this); - } - } - - private void HelpingFor(Npc caller) - { - if (Armor.Ratio(ArmorMax) < CALL_FOR_HELP_ARMOR_THRESHOLD) - return; - - _threatManager.Clear(); - foreach (var hostile in caller.ThreatManager.Hostiles) - { - AddThreat(hostile.unit,new Threat(ThreatType.Undefined,hostile.Threat),true); - } - } - - public void AddAssistThreat(Unit assistant, Unit target, Threat threat) - { - if ( !_threatManager.Contains(target) ) - return; - - if ( !CanAddThreatTo(assistant,threat)) - return; - - AddThreat(assistant,threat,true); - } - - private int CalculateCombatRange() - { - double range = (int)ActiveModules.Where(m => m.IsRanged) - .Select(module => module.OptimalRange) - .Concat(new[] { MaxTargetingRange }) - .Min(); - - range *= BEST_COMBAT_RANGE_MODIFIER; - range = Math.Max(3, range); - return (int) range; - } - - private int CalculateMaxCombatRange() - { - double range = ActiveModules.Where(m => m.IsRanged) - .Select(module => (int)(module.OptimalRange + module.Falloff)) - .Max(); - - range = Math.Max(3, range); - return (int)range; - } - - private const double BEST_COMBAT_RANGE_MODIFIER = 0.9; - - private class BodyPullThreatHelper : IEntityVisitor,IEntityVisitor - { - private readonly Npc _npc; - - public BodyPullThreatHelper(Npc npc) - { - _npc = npc; - } - - public void Visit(Player player) - { - if (_npc.Behavior.Type != NpcBehaviorType.Aggressive) - return; - - if (player.HasTeleportSicknessEffect) - return; - - if (_npc.ThreatManager.Hostiles.Any(h => h.unit.Eid == player.Eid)) - return; - - if (!_npc.IsInAggroRange(player)) - return; - - var threat = Threat.BODY_PULL + FastRandom.NextDouble(0, 5); - _npc.AddThreat(player, new Threat(ThreatType.Bodypull, threat)); - } - - public void Visit(AreaBomb bomb) - { - if (!_npc.IsInAggroRange(bomb)) - return; - - // csak akkor ha van is mivel tamadni - if (!_npc.ActiveModules.Any(m => m is WeaponModule)) - return; - - // ha valaki mar foglalkozik a bombaval akkor ne csinaljon semmit - - var g = _npc._group; - if (g != null && g.Members.Any(m => m.ThreatManager.Contains(bomb))) - return; - - var threat = Threat.BODY_PULL; - if (_npc.ThreatManager.IsThreatened) - { - var h = _npc.ThreatManager.GetMostHatedHostile(); - if (h != null) - threat = h.Threat*100; - } - - _npc.AddThreat(bomb, new Threat(ThreatType.Bodypull, threat + FastRandom.NextDouble(0, 5))); - } - } - - public override bool IsWalkable(Vector2 position) - { - return Zone.IsWalkableForNpc((int)position.X, (int)position.Y, Slope); - } - - public override bool IsWalkable(Position position) - { - return Zone.IsWalkableForNpc((int)position.X, (int)position.Y, Slope); - } - - public override bool IsWalkable(int x, int y) - { - return Zone.IsWalkableForNpc(x, y, Slope); - } - } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/NpcSystem/NpcBossInfoBuilder.cs b/src/Perpetuum/Zones/NpcSystem/NpcBossInfoBuilder.cs new file mode 100644 index 000000000..72ad96fd4 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/NpcBossInfoBuilder.cs @@ -0,0 +1,76 @@ +using Perpetuum.Data; +using Perpetuum.Services.EventServices; +using Perpetuum.Services.RiftSystem; +using Perpetuum.Zones.NpcSystem.Flocks; +using System.Data; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem +{ + public class NpcBossInfoBuilder + { + private readonly ICustomRiftConfigReader _customRiftConfigReader; + private readonly EventListenerService _eventChannel; + + public NpcBossInfoBuilder(ICustomRiftConfigReader customRiftConfigReader, EventListenerService eventChannel) + { + _customRiftConfigReader = customRiftConfigReader; + _eventChannel = eventChannel; + } + + public NpcBossInfo CreateBossInfoFromDB(IDataRecord record) + { + var id = record.GetValue("id"); + var flockid = record.GetValue("flockid"); + var respawnFactor = record.GetValue("respawnNoiseFactor"); + var lootSplit = record.GetValue("lootSplitFlag"); + var outpostEID = record.GetValue("outpostEID"); + var stabilityPts = record.GetValue("stabilityPts"); + var overrideRelations = record.GetValue("overrideRelations"); + var deathMessage = record.GetValue("customDeathMessage"); + var aggressMessage = record.GetValue("customAggressMessage"); + var riftConfigId = record.GetValue("riftConfigId"); + var riftConfig = _customRiftConfigReader.GetById(riftConfigId ?? -1); + var announce = record.GetValue("isAnnounced"); + var info = new NpcBossInfo( + _eventChannel, + id, + flockid, + respawnFactor, + lootSplit, + outpostEID, + stabilityPts, + overrideRelations, + deathMessage, + aggressMessage, + riftConfig, + announce + ); + + return info; + } + + public NpcBossInfo GetBossInfoByFlockID(int flockid, IFlockConfiguration config) + { + var bossInfos = Db.Query() + .CommandText(@"SELECT TOP 1 id, flockid, respawnNoiseFactor, lootSplitFlag, outpostEID, + stabilityPts, overrideRelations, customDeathMessage, customAggressMessage, riftConfigId, + isAnnounced + FROM dbo.npcbossinfo WHERE flockid=@flockid;") + .SetParameter("@flockid", flockid) + .Execute() + .Select(CreateBossInfoFromDB); + + var info = bossInfos.SingleOrDefault(); + + if (info == null) + { + return null; + } + + info.RespawnTime = config.RespawnTime; + + return info; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/NpcSpecialType.cs b/src/Perpetuum/Zones/NpcSystem/NpcSpecialType.cs new file mode 100644 index 000000000..808935d19 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/NpcSpecialType.cs @@ -0,0 +1,8 @@ +namespace Perpetuum.Zones.NpcSystem +{ + public enum NpcSpecialType + { + Normal, + Boss + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingState.cs b/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingState.cs new file mode 100644 index 000000000..9f0533962 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingState.cs @@ -0,0 +1,60 @@ +using Perpetuum.Zones.NpcSystem.AI; +using Perpetuum.Zones.NpcSystem.Flocks; +using System; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem.Presences.PathFinders +{ + public class RoamingState : NullRoamingState + { + public RoamingState(IRoamingPresence presence) : base(presence) + { + } + + public override void Update(TimeSpan time) + { + if (IsRunningTask) + { + return; + } + + var members = GetAllMembers(); + + if (IsDeadAndExiting(members)) + { + return; + } + + if (IsAllNotIdle(members)) + { + return; + } + + RunTask(() => FindNextRoamingPosition(), t => { }); + } + + private bool IsAllNotIdle(Npc[] members) + { + var idleMembersCount = members.Select(m => m.AI.Current).OfType().Count(); + + return idleMembersCount < members.Length; + } + + private void FindNextRoamingPosition() + { +#if DEBUG + _presence.Log("finding new roaming position. current: " + _presence.CurrentRoamingPosition); +#endif + var nextRoamingPosition = _presence.PathFinder.FindNextRoamingPosition(_presence); +#if DEBUG + _presence.Log("next roaming position: " + nextRoamingPosition + " dist:" + _presence.CurrentRoamingPosition.Distance(nextRoamingPosition)); +#endif + _presence.CurrentRoamingPosition = nextRoamingPosition; + + foreach (var npc in _presence.Flocks.GetMembers()) + { + npc.HomePosition = _presence.CurrentRoamingPosition.ToPosition(); + } + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingStates.cs b/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingStates.cs index 6acf6ae6b..aa58b3e9e 100644 --- a/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingStates.cs +++ b/src/Perpetuum/Zones/NpcSystem/Presences/PathFinders/RoamingStates.cs @@ -203,47 +203,4 @@ public virtual void Update(TimeSpan time) IsDeadAndExiting(members); } } - - public class RoamingState : NullRoamingState - { - public RoamingState(IRoamingPresence presence) : base(presence) { } - - private bool IsAllNotIdle(Npc[] members) - { - var idleMembersCount = members.Select(m => m.AI.Current).OfType().Count(); - return idleMembersCount < members.Length; - } - - public override void Update(TimeSpan time) - { - if (IsRunningTask) - return; - - var members = GetAllMembers(); - if (IsDeadAndExiting(members)) - return; - - if (IsAllNotIdle(members)) - return; - - RunTask(() => FindNextRoamingPosition(), t => { }); - } - - private void FindNextRoamingPosition() - { -#if DEBUG - _presence.Log("finding new roaming position. current: " + _presence.CurrentRoamingPosition); -#endif - var nextRoamingPosition = _presence.PathFinder.FindNextRoamingPosition(_presence); -#if DEBUG - _presence.Log("next roaming position: " + nextRoamingPosition + " dist:" + _presence.CurrentRoamingPosition.Distance(nextRoamingPosition)); -#endif - _presence.CurrentRoamingPosition = nextRoamingPosition; - - foreach (var npc in _presence.Flocks.GetMembers()) - { - npc.HomePosition = _presence.CurrentRoamingPosition.ToPosition(); - } - } - } } diff --git a/src/Perpetuum/Zones/NpcSystem/Presences/Presence.cs b/src/Perpetuum/Zones/NpcSystem/Presences/Presence.cs index a390d17cc..6bd1996ac 100644 --- a/src/Perpetuum/Zones/NpcSystem/Presences/Presence.cs +++ b/src/Perpetuum/Zones/NpcSystem/Presences/Presence.cs @@ -1,17 +1,19 @@ +using Perpetuum.Log; +using Perpetuum.Timers; +using Perpetuum.Zones.NpcSystem.Flocks; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Perpetuum.Log; -using Perpetuum.Timers; -using Perpetuum.Zones.NpcSystem.Flocks; namespace Perpetuum.Zones.NpcSystem.Presences { - public class Presence : INpcGroup + public class Presence : ISmartCreatureGroup { - public int ID { get; private set; } private ImmutableHashSet _flocks = ImmutableHashSet.Empty; + private readonly IntervalTimer _updateTimer = new IntervalTimer(TimeSpan.FromSeconds(2)); + + public int ID { get; private set; } public IPresenceConfiguration Configuration { get; private set; } @@ -22,35 +24,22 @@ public class Presence : INpcGroup public IEnumerable Flocks => _flocks; - public Presence(IZone zone, IPresenceConfiguration configuration) - { - Zone = zone; - Configuration = configuration; - ID = Configuration.ID; - } - public FlockFactory FlockFactory { private get; set; } - protected void ClearFlocks() - { - Flock[] removedFlocks = null; + public virtual Area Area => Configuration.Area; - ImmutableInterlocked.Update(ref _flocks, f => - { - removedFlocks = f.ToArray(); - return f.Clear(); - }); + public string Name => Configuration.Name; - foreach (var flock in removedFlocks) - { - flock.RemoveAllMembersFromZone(true); - } + public IEnumerable Members + { + get { return _flocks.SelectMany(f => f.Members); } } - private void AddFlock(Flock flock) + public Presence(IZone zone, IPresenceConfiguration configuration) { - ImmutableInterlocked.Update(ref _flocks, f => f.Add(flock)); - OnFlockAdded(flock); + Zone = zone; + Configuration = configuration; + ID = Configuration.ID; } public void RemoveFlock(Flock flock) @@ -59,32 +48,14 @@ public void RemoveFlock(Flock flock) OnFlockRemoved(flock); } - protected virtual void OnFlockAdded(Flock flock) - { - Log($"Flock added. {flock.Configuration.Name}"); - flock.NpcCreated += OnFlockNpcCreated; - } - - private void OnFlockNpcCreated(Npc npc) - { - npc.SetGroup(this); - } - - private void OnFlockRemoved(Flock flock) - { - flock.NpcCreated -= OnFlockNpcCreated; - flock.RemoveAllMembersFromZone(true); - Log($"Flock removed. {flock.Configuration.Name}"); - } - - private readonly IntervalTimer _updateTimer = new IntervalTimer(TimeSpan.FromSeconds(2)); - public void Update(TimeSpan time) { _updateTimer.Update(time); if (!_updateTimer.Passed) + { return; + } OnUpdate(_updateTimer.Elapsed); @@ -96,8 +67,6 @@ public void Update(TimeSpan time) _updateTimer.Reset(); } - protected virtual void OnUpdate(TimeSpan time) { } - public IDictionary ToDictionary(bool withFlock = false) { var result = new Dictionary @@ -117,37 +86,21 @@ public IDictionary ToDictionary(bool withFlock = false) if (withFlock) { var counter = 0; - var dictionary = Flocks.Select(f => f.ToDictionary()).ToDictionary, string, object>(o => "f" + counter++, o => o); + var dictionary = Flocks + .Select(f => f.ToDictionary()) + .ToDictionary, string, object>(o => "f" + counter++, o => o); + result.Add(k.flock, dictionary); } return result; } - protected void CreateAndAddFlocks(IEnumerable configurations) - { - var builder = _flocks.ToBuilder(); - - foreach (var configuration in configurations) - { - var flock = CreateFlock(configuration); - builder.Add(flock); - OnFlockAdded(flock); - } - - _flocks = builder.ToImmutable(); - } - - protected Flock CreateAndAddFlock(int flockID) - { - var configuration = FlockConfigurationRepository.Get(flockID); - return CreateAndAddFlock(configuration); - } - public Flock CreateAndAddFlock(IFlockConfiguration configuration) { var flock = CreateFlock(configuration); AddFlock(flock); + return flock; } @@ -156,11 +109,10 @@ public Flock CreateFlock(IFlockConfiguration flockConfiguration) return FlockFactory(flockConfiguration, this); } - public virtual Area Area => Configuration.Area; - public virtual void LoadFlocks() { var configs = FlockConfigurationRepository.GetAllByPresence(this).Where(t => t.Enabled); + CreateAndAddFlocks(configs); } @@ -169,21 +121,82 @@ public override string ToString() return $"{Name}:{Configuration.ID}:{Zone.Id}"; } - public string Name => Configuration.Name; + public void AddDebugInfoToDictionary(IDictionary dictionary) + { + + } - public IEnumerable Members + public virtual void Log(string message) { - get { return _flocks.SelectMany(f => f.Members); } + Logger.Info($"[Presence] ({ToString()}) - {message}"); } - public void AddDebugInfoToDictionary(IDictionary dictionary) + protected void ClearFlocks() { + Flock[] removedFlocks = null; + + ImmutableInterlocked.Update( + ref _flocks, + f => + { + removedFlocks = f.ToArray(); + return f.Clear(); + }); + + foreach (var flock in removedFlocks) + { + flock.RemoveAllMembersFromZone(true); + } } - public virtual void Log(string message) + protected virtual void OnFlockAdded(Flock flock) { - Logger.Info($"[Presence] ({ToString()}) - {message}"); + Log($"Flock added. {flock.Configuration.Name}"); + flock.NpcCreated += OnFlockNpcCreated; + } + + protected virtual void OnUpdate(TimeSpan time) + { + } + + protected void CreateAndAddFlocks(IEnumerable configurations) + { + var builder = _flocks.ToBuilder(); + + foreach (var configuration in configurations) + { + var flock = CreateFlock(configuration); + builder.Add(flock); + OnFlockAdded(flock); + } + + _flocks = builder.ToImmutable(); + } + + protected Flock CreateAndAddFlock(int flockID) + { + var configuration = FlockConfigurationRepository.Get(flockID); + + return CreateAndAddFlock(configuration); + } + + private void AddFlock(Flock flock) + { + ImmutableInterlocked.Update(ref _flocks, f => f.Add(flock)); + OnFlockAdded(flock); + } + + private void OnFlockNpcCreated(Npc npc) + { + npc.SetGroup(this); + } + + private void OnFlockRemoved(Flock flock) + { + flock.NpcCreated -= OnFlockNpcCreated; + flock.RemoveAllMembersFromZone(true); + Log($"Flock removed. {flock.Configuration.Name}"); } } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/NpcSystem/PrimaryTargetStrategy.cs b/src/Perpetuum/Zones/NpcSystem/PrimaryTargetStrategy.cs deleted file mode 100644 index 981088237..000000000 --- a/src/Perpetuum/Zones/NpcSystem/PrimaryTargetStrategy.cs +++ /dev/null @@ -1,110 +0,0 @@ -using Perpetuum.Collections; -using Perpetuum.Zones.Locking.Locks; -using System.Collections.Generic; -using System.Linq; - -namespace Perpetuum.Zones.NpcSystem -{ - public enum PrimaryLockStrategy - { - Random, - Hostile, - Closest, - OptimalRange - } - - public delegate bool TargetSelectionStrategy(Npc npc, UnitLock[] locks); - - public static class Strategies - { - public static Dictionary All = new Dictionary() - { - { PrimaryLockStrategy.Random, TargetRandom }, - { PrimaryLockStrategy.Hostile, TargetMostHated }, - { PrimaryLockStrategy.Closest, TargetClosest }, - { PrimaryLockStrategy.OptimalRange, TargetWithinOptimal } - }; - - public static TargetSelectionStrategy GetStrategy(PrimaryLockStrategy strategyType) - { - return All.GetOrDefault(strategyType); - } - - public static bool TryInvokeStrategy(PrimaryLockStrategy strategyType, Npc npc, UnitLock[] locks) - { - var strat = GetStrategy(strategyType); - if (strat == null) - return false; - return strat(npc, locks); - } - - private static bool TargetMostHated(Npc npc, UnitLock[] locks) - { - var hostiles = npc.ThreatManager.Hostiles; - var hostileLocks = locks.Where(u => hostiles.Any(h => h.unit.Eid == u.Target.Eid)); - var mostHostileLock = hostileLocks.OrderByDescending(u => hostiles.Where(h => h.unit.Eid == u.Target.Eid).FirstOrDefault()?.Threat ?? 0).FirstOrDefault(); - return TrySetPrimaryLock(npc, mostHostileLock); - } - - private static bool TargetWithinOptimal(Npc npc, UnitLock[] locks) - { - return TrySetPrimaryLock(npc, locks.Where(k => k.Target.GetDistance(npc) < npc.BestCombatRange).RandomElement()); - } - - private static bool TargetClosest(Npc npc, UnitLock[] locks) - { - return TrySetPrimaryLock(npc, locks.OrderBy(u => u.Target.GetDistance(npc)).First()); - } - - private static bool TargetRandom(Npc npc, UnitLock[] locks) - { - return TrySetPrimaryLock(npc, locks.RandomElement()); - } - - private static bool TrySetPrimaryLock(Npc npc, Lock l) - { - if (l == null) return false; - npc.SetPrimaryLock(l); - return true; - } - } - - - - public class PrimaryLockSelectionStrategySelector - { - private readonly WeightedCollection _selection; - public PrimaryLockSelectionStrategySelector(WeightedCollection selection) - { - _selection = selection; - } - public bool TryUseStrategy(Npc npc, UnitLock[] locks) - { - var stratType = _selection.GetRandom(); - return Strategies.TryInvokeStrategy(stratType, npc, locks); - } - public static PrimaryLockSelectionStrategyBuilder Create() - { - return new PrimaryLockSelectionStrategyBuilder(); - } - - public class PrimaryLockSelectionStrategyBuilder - { - private readonly WeightedCollection _selection; - public PrimaryLockSelectionStrategyBuilder() - { - _selection = new WeightedCollection(); - } - public PrimaryLockSelectionStrategyBuilder WithStrategy(PrimaryLockStrategy strategy, int weight = 1) - { - _selection.Add(strategy, weight); - return this; - } - - public PrimaryLockSelectionStrategySelector Build() - { - return new PrimaryLockSelectionStrategySelector(_selection); - } - } - } -} diff --git a/src/Perpetuum/Zones/NpcSystem/SmartCreature.cs b/src/Perpetuum/Zones/NpcSystem/SmartCreature.cs new file mode 100644 index 000000000..279e3c426 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/SmartCreature.cs @@ -0,0 +1,488 @@ +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Players; +using Perpetuum.StateMachines; +using Perpetuum.Timers; +using Perpetuum.Units; +using Perpetuum.Zones.DamageProcessors; +using Perpetuum.Zones.Locking; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.NpcSystem.AI; +using Perpetuum.Zones.NpcSystem.AI.Behaviors; +using Perpetuum.Zones.NpcSystem.AI.CombatDrones; +using Perpetuum.Zones.NpcSystem.Flocks; +using Perpetuum.Zones.NpcSystem.IndustrialTargetsManagement; +using Perpetuum.Zones.NpcSystem.ThreatManaging; +using Perpetuum.Zones.RemoteControl; +using Perpetuum.Zones.Scanning.Results; +using Perpetuum.Zones.Terrains; +using Perpetuum.Zones.Terrains.Materials; +using Perpetuum.Zones.Terrains.Materials.Minerals; +using Perpetuum.Zones.Terrains.Materials.Plants; +using System; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem +{ + public class SmartCreature : Creature + { + private const double AggroRange = 30; + private const double BestComnatRangeModifier = 0.9; + private const double BaseCallForHelpArmorThreshold = 0.2; + private readonly TimeKeeper debounceBodyPull = new TimeKeeper(TimeSpan.FromSeconds(2.5)); + private readonly TimeKeeper debounceLockChange = new TimeKeeper(TimeSpan.FromSeconds(2.5)); + private readonly IntervalTimer pseudoUpdateFreq = new IntervalTimer(TimeSpan.FromMilliseconds(650)); + private Lazy maxActionRange; + private Lazy optimalActionRange; + private TimeSpan lastHelpCalled; + + [CanBeNull] + private ISmartCreatureGroup group; + + public StackFSM AI { get; private set; } + + public Behavior Behavior { get; set; } + + public double HomeRange { get; set; } + + public Position HomePosition { get; set; } + + public ThreatManager ThreatManager { get; } + + public PseudoThreatManager PseudoThreatManager { get; } + + public IndustrialValueManager IndustrialValueManager { get; } + + public int BestActionRange => optimalActionRange.Value; + + public int MaxActionRange => maxActionRange.Value; + + public bool IsInHomeRange => CurrentPosition.IsInRangeOf2D(HomePosition, HomeRange); + + public ISmartCreatureGroup Group => group; + + public virtual bool IsStationary => MaxSpeed.IsZero(); + + public virtual double CallForHelpArmorThreshold => BaseCallForHelpArmorThreshold; + + public bool CallForHelp { private get; set; } + + public NpcBossInfo BossInfo { get; set; } + + public SmartCreature() + { + RecalculateMaxCombatRange(); + RecalculateOptimalCombatRange(); + ThreatManager = new ThreatManager(); + AI = new StackFSM(); + PseudoThreatManager = new PseudoThreatManager(); + IndustrialValueManager = new IndustrialValueManager(); + } + + public virtual void LookingForHostiles() + { + foreach (IUnitVisibility visibility in GetVisibleUnits()) + { + AddBodyPullThreat(visibility.Target); + } + } + + public void LookingForMiningTargets() + { + IndustrialValueManager.Clear(); + + Area area = Zone.CreateArea(CurrentPosition, BestActionRange); + + MaterialType[] availableMaterialTypes = Zone.Terrain.GetAvailableMineralTypes(); + + foreach (MaterialType materialType in availableMaterialTypes) + { + MineralScanResultBuilder builder = MineralScanResultBuilder.Create(Zone, materialType); + + builder.ScanArea = area; + builder.ScanAccuracy = 100.0; + + MineralScanResult result = builder.Build(); + + + if (Zone.Terrain.GetMaterialLayer(materialType) is MineralLayer mineralLayer) + { + if (result.FoundAny) + { + System.Collections.Generic.IEnumerable valuablePositions = result.Area + .GetPositions() + .Where(x => mineralLayer.HasMineral(x)) + .Select(x => Zone.FixZ(x)) + .Where(x => x.IsInRangeOf3D(PositionWithHeight, BestActionRange)); + + foreach (Position valuablePosition in valuablePositions) + { + MineralNode mineralNode = mineralLayer.GetNode(valuablePosition); + + _ = IndustrialValueManager.GetOrAddIndustrialTargetWithValue(valuablePosition.Center, IndustrialValueType.Mineral, mineralNode.GetValue(valuablePosition)); + } + } + } + } + } + + public void LookingForHarvestingTargets() + { + IndustrialValueManager.Clear(); + + Area area = Zone.CreateArea(CurrentPosition, BestActionRange); + + PlantType[] availablePlantTypes = Zone.Terrain.GetAvailablePlantTypes(); + + foreach (PlantType plantType in availablePlantTypes) + { + System.Collections.Generic.List plants = Zone.GetPlantPositionsInArea(plantType, area); + + if (plants.Any()) + { + System.Collections.Generic.IEnumerable valuablePositions = plants + .Select(x => Zone.FixZ(x)) + .Where(x => x.IsInRangeOf2D(CurrentPosition, BestActionRange)); + + foreach (Position valuablePosition in valuablePositions) + { + PlantInfo plant = Zone.Terrain.Plants.GetValue(valuablePosition.intX, valuablePosition.intY); + + if (plant.material > 0) + { + _ = IndustrialValueManager.GetOrAddIndustrialTargetWithValue(valuablePosition.Center, IndustrialValueType.Plant, plant.material); + } + } + } + } + } + + public void AddPseudoThreat(Unit hostile) + { + PseudoThreatManager.AddOrRefreshExisting(hostile); + } + + public void SetGroup(ISmartCreatureGroup group) + { + this.group = group; + } + + public void RecalculateOptimalCombatRange() + { + optimalActionRange = new Lazy(CalculateCombatRange); + } + + public void RecalculateMaxCombatRange() + { + maxActionRange = new Lazy(CalculateMaxCombatRange); + } + + protected override void OnPropertyChanged(ItemProperty property) + { + base.OnPropertyChanged(property); + + switch (property.Field) + { + case AggregateField.locking_range: + { + RecalculateOptimalCombatRange(); + RecalculateMaxCombatRange(); + + break; + } + case AggregateField.armor_current: + { + double percentage = Armor.Ratio(ArmorMax); + + if (percentage <= CallForHelpArmorThreshold) + { + CallingForHelp(); + } + + break; + } + } + } + + protected override void OnUnitLockStateChanged(Lock @lock) + { + if (!debounceLockChange.Expired) + { + return; + } + + + if (!(@lock is UnitLock unitLock)) + { + return; + } + + if (unitLock.Target != this) + { + return; + } + + if (unitLock.State != LockState.Locked) + { + return; + } + + double threatValue = unitLock.Primary + ? Threat.LOCK_PRIMARY + : Threat.LOCK_SECONDARY; + + AddThreat(unitLock.Owner, new Threat(ThreatType.Lock, threatValue), true); + debounceLockChange.Reset(); + } + + protected override void OnUnitTileChanged(Unit target) + { + if (!debounceBodyPull.Expired) + { + return; + } + + AddBodyPullThreat(target); + debounceBodyPull.Reset(); + } + + protected void AddBodyPullThreat(Unit enemy) + { + if (!IsHostile(enemy)) + { + return; + } + + BodyPullThreatHelper helper = new BodyPullThreatHelper(this); + + enemy.AcceptVisitor(helper); + } + + private int CalculateCombatRange() + { + double range = (int)ActiveModules + .Where(m => m.IsRanged) + .Select(module => module.OptimalRange) + .Concat(new[] { MaxTargetingRange }) + .Min(); + range *= BestComnatRangeModifier; + range = Math.Max(3, range); + + return (int)range; + } + + private int CalculateMaxCombatRange() + { + double range = ActiveModules + .Where(m => m.IsRanged) + .Select(module => (int)(module.OptimalRange + module.Falloff)) + .Max(); + range = Math.Max(3, range); + + return (int)range; + } + + public bool IsInAggroRange(Unit target) + { + return this is CombatDrone || IsStationary || IsInRangeOf3D(target, AggroRange); + } + + public virtual void AddThreat(Unit hostile, Threat threat, bool spreadToGroup) + { + if (hostile is RemoteControlledCreature) + { + threat = Threat.Multiply(threat, 100); + } + + if (hostile.IsPlayer()) + { + BossInfo?.OnAggro(hostile as Player); + } + + ThreatManager.GetOrAddHostile(hostile).AddThreat(threat); + + RemovePseudoThreat(hostile); + + if (!spreadToGroup) + { + return; + } + + ISmartCreatureGroup group = Group; + if (@group == null) + { + return; + } + + Threat multipliedThreat = Threat.Multiply(threat, 0.5); + + foreach (SmartCreature member in @group.Members) + { + if (member == this) + { + continue; + } + + member.AddThreat(hostile, multipliedThreat, false); + } + } + + /// + /// This determines if threat can be added to a target based on the following: + /// - Is the target already on the threat manager + /// - Or is the npc non-passive and the Threat is of some defined type + /// + /// Unit target + /// Threat threat + /// If the target can be a threat + public bool CanAddThreatTo(Unit target, Threat threat) + { + return ThreatManager.Contains(target) || (Behavior.Type != BehaviorType.Passive && threat.type != ThreatType.Undefined); + } + + public void AddAssistThreat(Unit assistant, Unit target, Threat threat) + { + if (!ThreatManager.Contains(target)) + { + return; + } + + if (!CanAddThreatTo(assistant, threat)) + { + return; + } + + AddThreat(assistant, threat, true); + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + protected override void OnTileChanged() + { + base.OnTileChanged(); + LookingForHostiles(); + } + + protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) + { + States.Aggressive = Behavior.Type == BehaviorType.Aggressive; + + base.OnEnterZone(zone, enterType); + + if (this is SentryTurret) + { + AI.Push(new SentryTurretCombatAI(this)); + } + else if (this is IndustrialTurret) + { + if ((this as IndustrialTurret).TurretType == TurretType.Mining) + { + AI.Push(new MiningIndustrialTurretAI(this)); + } + else + { + AI.Push(new HarvestingIndustrialTurretAI(this)); + } + } + else if (this is CombatDrone) + { + AI.Push(new GuardCombatDroneAI(this)); + } + else if (IsStationary) + { + AI.Push(new StationaryIdleAI(this)); + } + else + { + AI.Push(new IdleAI(this)); + } + } + + protected override void OnDamageTaken(Unit source, DamageTakenEventArgs e) + { + base.OnDamageTaken(source, e); + + Player player = Zone.ToPlayerOrGetOwnerPlayer(source); + + if (player == null) + { + return; + } + + BossInfo?.OnDamageTaken(this, player); + AddThreat(player, new Threat(ThreatType.Damage, e.TotalDamage * 0.9), true); + } + + protected override void OnUpdate(TimeSpan time) + { + base.OnUpdate(time); + + AI.Update(time); + + UpdatePseudoThreats(time); + } + + private void RemovePseudoThreat(Unit hostile) + { + PseudoThreatManager.Remove(hostile); + } + + private void UpdatePseudoThreats(TimeSpan time) + { + _ = pseudoUpdateFreq.Update(time); + + if (pseudoUpdateFreq.Passed) + { + PseudoThreatManager.Update(pseudoUpdateFreq.Elapsed); + pseudoUpdateFreq.Reset(); + } + } + + private void CallingForHelp() + { + if (!CallForHelp) + { + return; + } + + if (!GlobalTimer.IsPassed(ref lastHelpCalled, TimeSpan.FromSeconds(5))) + { + return; + } + + ISmartCreatureGroup group = Group; + + if (group == null) + { + return; + } + + foreach (SmartCreature member in group.Members.Where(flockMember => flockMember != this)) + { + member.HelpingFor(this); + } + } + + private void HelpingFor(SmartCreature caller) + { + if (Armor.Ratio(ArmorMax) < CallForHelpArmorThreshold) + { + return; + } + + ThreatManager.Clear(); + + foreach (Hostile hostile in caller.ThreatManager.Hostiles) + { + AddThreat(hostile.Unit, new Threat(ThreatType.Undefined, hostile.Threat), true); + } + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategy.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategy.cs new file mode 100644 index 000000000..d6b6baf9b --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategy.cs @@ -0,0 +1,12 @@ +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public enum CombatPrimaryLockSelectionStrategy + { + Random, + Hostile, + Closest, + OptimalRange, + HostileOrClosest, + PropagatedPrimary, + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategyBuilder.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategyBuilder.cs new file mode 100644 index 000000000..5aaf6e13e --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategyBuilder.cs @@ -0,0 +1,26 @@ +using Perpetuum.Collections; + +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public class CombatPrimaryLockSelectionStrategyBuilder + { + private readonly WeightedCollection selection; + + public CombatPrimaryLockSelectionStrategyBuilder() + { + selection = new WeightedCollection(); + } + + public CombatPrimaryLockSelectionStrategyBuilder WithStrategy(CombatPrimaryLockSelectionStrategy strategy, int weight = 1) + { + selection.Add(strategy, weight); + + return this; + } + + public CombatPrimaryLockSelectionStrategySelector Build() + { + return new CombatPrimaryLockSelectionStrategySelector(selection); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategySelector.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategySelector.cs new file mode 100644 index 000000000..852b7abc4 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatPrimaryLockSelectionStrategySelector.cs @@ -0,0 +1,27 @@ +using Perpetuum.Collections; +using Perpetuum.Zones.Locking.Locks; + +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public class CombatPrimaryLockSelectionStrategySelector + { + private readonly WeightedCollection primaryLockSelectionStrategies; + + public CombatPrimaryLockSelectionStrategySelector(WeightedCollection primaryLockSelectionStrategies) + { + this.primaryLockSelectionStrategies = primaryLockSelectionStrategies; + } + + public bool TryUseStrategy(SmartCreature smartCreature, UnitLock[] locks) + { + var primaryLockSelectionStrategy = primaryLockSelectionStrategies.GetRandom(); + + return CombatStrategies.TryInvokeStrategy(primaryLockSelectionStrategy, smartCreature, locks); + } + + public static CombatPrimaryLockSelectionStrategyBuilder Create() + { + return new CombatPrimaryLockSelectionStrategyBuilder(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatStrategies.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatStrategies.cs new file mode 100644 index 000000000..eca6ccc23 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/CombatStrategies.cs @@ -0,0 +1,100 @@ +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.RemoteControl; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public delegate bool CombatTargetSelectionStrategy(SmartCreature smartCreature, UnitLock[] locks); + + public static class CombatStrategies + { + public static Dictionary All = + new Dictionary() + { + { CombatPrimaryLockSelectionStrategy.Random, TargetRandom }, + { CombatPrimaryLockSelectionStrategy.Hostile, TargetMostHated }, + { CombatPrimaryLockSelectionStrategy.Closest, TargetClosest }, + { CombatPrimaryLockSelectionStrategy.OptimalRange, TargetWithinOptimal }, + { CombatPrimaryLockSelectionStrategy.HostileOrClosest, TargetMostHatedOrClosest }, + { CombatPrimaryLockSelectionStrategy.PropagatedPrimary, TargetPropagatedPrimary }, + }; + + public static CombatTargetSelectionStrategy GetStrategy(CombatPrimaryLockSelectionStrategy strategyType) + { + return All.GetOrDefault(strategyType); + } + + public static bool TryInvokeStrategy(CombatPrimaryLockSelectionStrategy strategyType, SmartCreature smartCreature, UnitLock[] locks) + { + var primaryLockSelectionStrategy = GetStrategy(strategyType); + + if (primaryLockSelectionStrategy == null) + { + return false; + } + + return primaryLockSelectionStrategy(smartCreature, locks); + } + + private static bool TargetPropagatedPrimary(SmartCreature smartCreature, UnitLock[] locks) + { + var propagatedPrimary = locks.FirstOrDefault(x => x.Target == ((smartCreature as RemoteControlledCreature).CommandRobot.GetPrimaryLock() as UnitLock)?.Target); + + if (propagatedPrimary == null) + { + smartCreature.ResetLocks(); + } + + return TrySetPrimaryLock(smartCreature, propagatedPrimary); + } + + private static bool TargetMostHated(SmartCreature smartCreature, UnitLock[] locks) + { + var hostiles = smartCreature.ThreatManager.Hostiles; + var hostileLocks = locks.Where(u => hostiles.Any(h => h.Unit.Eid == u.Target.Eid)); + var mostHostileLock = hostileLocks + .OrderByDescending(u => hostiles.Where(h => h.Unit.Eid == u.Target.Eid).FirstOrDefault()?.Threat ?? 0) + .FirstOrDefault(); + + return TrySetPrimaryLock(smartCreature, mostHostileLock); + } + + private static bool TargetWithinOptimal(SmartCreature smartCreature, UnitLock[] locks) + { + return TrySetPrimaryLock( + smartCreature, + locks + .Where(k => k.Target.GetDistance(smartCreature) < smartCreature.BestActionRange) + .RandomElement()); + } + + private static bool TargetClosest(SmartCreature smartCreature, UnitLock[] locks) + { + return TrySetPrimaryLock(smartCreature, locks.OrderBy(u => u.Target.GetDistance(smartCreature)).First()); + } + + private static bool TargetRandom(SmartCreature smartCreature, UnitLock[] locks) + { + return TrySetPrimaryLock(smartCreature, locks.RandomElement()); + } + + private static bool TargetMostHatedOrClosest(SmartCreature smartCreature, UnitLock[] locks) + { + return TargetMostHated(smartCreature, locks) || TargetClosest(smartCreature, locks); + } + + private static bool TrySetPrimaryLock(SmartCreature smartCreature, Lock targetLock) + { + if (targetLock == null) + { + return false; + } + + smartCreature.SetPrimaryLock(targetLock); + + return true; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategy.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategy.cs new file mode 100644 index 000000000..dfd2d9f2d --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategy.cs @@ -0,0 +1,8 @@ +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public enum IndustrialPrimaryLockSelectionStrategy + { + RichestTile, + MostFertilePlantWithinOptimal, + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategyBuilder.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategyBuilder.cs new file mode 100644 index 000000000..21ea59080 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategyBuilder.cs @@ -0,0 +1,26 @@ +using Perpetuum.Collections; + +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public class IndustrialPrimaryLockSelectionStrategyBuilder + { + private readonly WeightedCollection selection; + + public IndustrialPrimaryLockSelectionStrategyBuilder() + { + selection = new WeightedCollection(); + } + + public IndustrialPrimaryLockSelectionStrategyBuilder WithStrategy(IndustrialPrimaryLockSelectionStrategy strategy, int weight = 1) + { + selection.Add(strategy, weight); + + return this; + } + + public IndustrialPrimaryLockSelectionStrategySelector Build() + { + return new IndustrialPrimaryLockSelectionStrategySelector(selection); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategySelector.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategySelector.cs new file mode 100644 index 000000000..513568f65 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialPrimaryLockSelectionStrategySelector.cs @@ -0,0 +1,27 @@ +using Perpetuum.Collections; +using Perpetuum.Zones.Locking.Locks; + +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public class IndustrialPrimaryLockSelectionStrategySelector + { + private readonly WeightedCollection primaryLockSelectionStrategies; + + public IndustrialPrimaryLockSelectionStrategySelector(WeightedCollection primaryLockSelectionStrategies) + { + this.primaryLockSelectionStrategies = primaryLockSelectionStrategies; + } + + public bool TryUseStrategy(SmartCreature smartCreature, TerrainLock[] locks) + { + var primaryLockSelectionStrategy = primaryLockSelectionStrategies.GetRandom(); + + return IndustrialStrategies.TryInvokeStrategy(primaryLockSelectionStrategy, smartCreature, locks); + } + + public static IndustrialPrimaryLockSelectionStrategyBuilder Create() + { + return new IndustrialPrimaryLockSelectionStrategyBuilder(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialStrategies.cs b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialStrategies.cs new file mode 100644 index 000000000..dfb4714b6 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/TargettingStrategies/IndustrialStrategies.cs @@ -0,0 +1,63 @@ +using Perpetuum.Zones.Locking.Locks; +using System.Collections.Generic; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem.TargettingStrategies +{ + public delegate bool IndustrialTargetSelectionStrategy(SmartCreature smartCreature, TerrainLock[] locks); + + public static class IndustrialStrategies + { + public static Dictionary All = + new Dictionary() + { + { IndustrialPrimaryLockSelectionStrategy.RichestTile, TargetRichestTile }, + }; + + public static IndustrialTargetSelectionStrategy GetStrategy(IndustrialPrimaryLockSelectionStrategy strategyType) + { + return All.GetOrDefault(strategyType); + } + + public static bool TryInvokeStrategy(IndustrialPrimaryLockSelectionStrategy strategyType, SmartCreature smartCreature, TerrainLock[] locks) + { + var industrialLockSelectionStrategy = GetStrategy(strategyType); + + if (industrialLockSelectionStrategy == null) + { + return false; + } + + return industrialLockSelectionStrategy(smartCreature, locks); + } + + private static bool TargetRichestTile(SmartCreature smartCreature, TerrainLock[] locks) + { + var industrialTargets = smartCreature.IndustrialValueManager.IndustrialTargets; + + if (!industrialTargets.Any()) + { + return false; + } + + var industrialTargetLocks = locks.Where(u => industrialTargets.Any(h => h.Position.ToString() == u.Location.ToString())); + var mostHostileLock = industrialTargetLocks + .OrderByDescending(u => industrialTargets.FirstOrDefault(h => h.Position.ToString() == u.Location.ToString())?.IndustrialValue ?? 0) + .FirstOrDefault(); + + return TrySetPrimaryLock(smartCreature, mostHostileLock); + } + + private static bool TrySetPrimaryLock(SmartCreature smartCreature, Lock targetLock) + { + if (targetLock == null) + { + return false; + } + + smartCreature.SetPrimaryLock(targetLock); + + return true; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/Hostile.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/Hostile.cs new file mode 100644 index 000000000..e6c5ab374 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/Hostile.cs @@ -0,0 +1,82 @@ +using Perpetuum.Timers; +using Perpetuum.Units; +using System; + +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public class Hostile : IComparable + { + private static readonly TimeSpan _threatTimeOut = TimeSpan.FromSeconds(30); + + private double _threat; + + public readonly Unit Unit; + + public TimeSpan LastThreatUpdate { get; private set; } + + public double Threat + { + get + { + return _threat; + } + private set + { + if (Math.Abs(_threat - value) <= double.Epsilon) + { + return; + } + + _threat = value; + OnThreatUpdated(); + } + } + + public bool IsExpired + { + get + { + return (GlobalTimer.Elapsed - LastThreatUpdate) >= _threatTimeOut; + } + } + + public event Action Updated; + + public Hostile(Unit unit) + { + this.Unit = unit; + Threat = 0.0; + } + + public void AddThreat(Threat threat) + { + if (threat.value <= 0.0) + { + return; + } + + Threat += threat.value; + } + + private void OnThreatUpdated() + { + LastThreatUpdate = GlobalTimer.Elapsed; + Updated?.Invoke(this); + } + + public int CompareTo(Hostile other) + { + if (other._threat < _threat) + { + return -1; + } + + if (other._threat > _threat) + { + return 1; + } + + return 0; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/IPseudoThreatManager.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/IPseudoThreatManager.cs new file mode 100644 index 000000000..eb7eef928 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/IPseudoThreatManager.cs @@ -0,0 +1,20 @@ +using Perpetuum.Units; +using System; +using System.Collections.Generic; + +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + /// + /// Manager of PseudoThreats + /// Processes and manages an internal collection of players aggressive to an npc + /// but not on the npc's ThreatManager. + /// For awarding players a portion of the total ep reward. + /// + public interface IPseudoThreatManager + { + void Update(TimeSpan time); + void AddOrRefreshExisting(Unit hostile); + void Remove(Unit hostile); + void AwardPseudoThreats(List alreadyAwarded, IZone zone, int ep); + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/IThreatManager.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/IThreatManager.cs new file mode 100644 index 000000000..8d1216418 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/IThreatManager.cs @@ -0,0 +1,18 @@ +using Perpetuum.Units; +using System.Collections.Immutable; + +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public interface IThreatManager + { + bool IsThreatened { get; } + + bool Contains(Unit hostile); + + void Remove(Hostile hostile); + + ImmutableSortedSet Hostiles { get; } + + void Clear(); + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/PseudoThreat.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/PseudoThreat.cs new file mode 100644 index 000000000..73f031893 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/PseudoThreat.cs @@ -0,0 +1,37 @@ +using Perpetuum.Units; +using System; + +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + /// + /// An expirable record of a player that is aggressing an npc but the npc is + /// not capable of attacking back (removed from the ThreatManager) + /// + public class PseudoThreat + { + private TimeSpan _lastUpdated = TimeSpan.Zero; + private TimeSpan Expiration = TimeSpan.FromMinutes(1); + + public Unit Unit { get; } + + public bool IsExpired + { + get { return _lastUpdated > Expiration; } + } + + public PseudoThreat(Unit unit) + { + Unit = unit; + } + + public void RefreshThreat() + { + _lastUpdated = TimeSpan.Zero; + } + + public void Update(TimeSpan time) + { + _lastUpdated += time; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/PseudoThreatManager.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/PseudoThreatManager.cs new file mode 100644 index 000000000..07c5ca444 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/PseudoThreatManager.cs @@ -0,0 +1,85 @@ +using Perpetuum.Comparers; +using Perpetuum.Units; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public class PseudoThreatManager : IPseudoThreatManager + { + private readonly List _pseudoThreats; + private readonly object _lock; + + public PseudoThreatManager() + { + _pseudoThreats = new List(); + _lock = new object(); + } + + public bool IsThreatened + { + get { return _pseudoThreats.Any(); } + } + + public void AwardPseudoThreats(List alreadyAwarded, IZone zone, int ep) + { + var pseudoHostileUnits = new List(); + + lock (_lock) + { + pseudoHostileUnits = _pseudoThreats.Select(p => p.Unit).Except(alreadyAwarded, new EntityComparer()).Cast().ToList(); + } + + foreach (var unit in pseudoHostileUnits) + { + var hostilePlayer = zone.ToPlayerOrGetOwnerPlayer(unit); + + hostilePlayer?.Character.AddExtensionPointsBoostAndLog(EpForActivityType.Npc, ep / 2); + } + } + + public void AddOrRefreshExisting(Unit hostile) + { + lock (_lock) + { + var existing = _pseudoThreats.Where(x => x.Unit == hostile).FirstOrDefault(); + + if (existing != null) + { + existing.RefreshThreat(); + + return; + } + + _pseudoThreats.Add(new PseudoThreat(hostile)); + } + } + + public void Remove(Unit hostile) + { + lock (_lock) + { + _pseudoThreats.RemoveAll(x => x.Unit == hostile); + } + } + + public void Update(TimeSpan time) + { + lock (_lock) + { + foreach (var threat in _pseudoThreats) + { + threat.Update(time); + } + + CleanExpiredThreats(); + } + } + + private void CleanExpiredThreats() + { + _pseudoThreats.RemoveAll(threat => threat.IsExpired); + } + } +} \ No newline at end of file diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/Threat.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/Threat.cs new file mode 100644 index 000000000..96ece33f3 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/Threat.cs @@ -0,0 +1,33 @@ +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public struct Threat + { + + public const double WEBBER = 25; + public const double LOCK_PRIMARY = 2.0; + public const double LOCK_SECONDARY = 1.0; + public const double SENSOR_DAMPENER = 25.0; + public const double BODY_PULL = 1.0; + public const double SENSOR_BOOSTER = 15; + public const double REMOTE_SENSOR_BOOSTER = 15; + + public readonly ThreatType type; + public readonly double value; + + public Threat(ThreatType type, double value) + { + this.type = type; + this.value = value; + } + + public override string ToString() + { + return $"{type} = {value}"; + } + + public static Threat Multiply(Threat threat, double multiplier) + { + return new Threat(threat.type, threat.value * multiplier); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatExtensions.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatExtensions.cs new file mode 100644 index 000000000..d7534d7d5 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatExtensions.cs @@ -0,0 +1,11 @@ +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public static class ThreatExtensions + { + [CanBeNull] + public static Hostile GetMostHatedHostile(this IThreatManager manager) + { + return manager.Hostiles.Min; + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatManager.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatManager.cs new file mode 100644 index 000000000..f7b134fe8 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatManager.cs @@ -0,0 +1,72 @@ +using Perpetuum.Units; +using System.Collections.Immutable; +using System.Linq; +using System.Text; + +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public class ThreatManager : IThreatManager + { + private ImmutableDictionary _hostiles = ImmutableDictionary.Empty; + + public ImmutableSortedSet Hostiles + { + get { return _hostiles.Values.ToImmutableSortedSet(); } + } + + public bool IsThreatened + { + get { return !_hostiles.IsEmpty; } + } + + public Hostile GetOrAddHostile(Unit unit) + { + return ImmutableInterlocked.GetOrAdd(ref _hostiles, unit.Eid, eid => + { + var h = new Hostile(unit); + + return h; + }); + } + + public bool Contains(Unit unit) + { + return _hostiles.ContainsKey(unit.Eid); + } + + public void Clear() + { + _hostiles.Clear(); + } + + public void Remove(Hostile hostile) + { + ImmutableInterlocked.TryRemove(ref _hostiles, hostile.Unit.Eid, out hostile); + } + + public string ToDebugString() + { + if (_hostiles.Count == 0) + { + return string.Empty; + } + + var sb = new StringBuilder(); + + sb.AppendLine(); + sb.AppendLine("========== THREAT =========="); + sb.AppendLine(); + + foreach (var hostile in _hostiles.Values.OrderByDescending(h => h.Threat)) + { + sb.AppendFormat(" {0} ({1}) => {2}", hostile.Unit.ED.Name, hostile.Unit.Eid, hostile.Threat); + sb.AppendLine(); + } + + sb.AppendLine(); + sb.AppendLine("============================"); + + return sb.ToString(); + } + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatType.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatType.cs new file mode 100644 index 000000000..b7d264ea4 --- /dev/null +++ b/src/Perpetuum/Zones/NpcSystem/ThreatManagement/ThreatType.cs @@ -0,0 +1,16 @@ +namespace Perpetuum.Zones.NpcSystem.ThreatManaging +{ + public enum ThreatType + { + Undefined, + Bodypull, + Damage, + Support, + Lock, + Buff, + Debuff, + Direct, + EnWar, + Ewar, + } +} diff --git a/src/Perpetuum/Zones/NpcSystem/ThreatManager.cs b/src/Perpetuum/Zones/NpcSystem/ThreatManager.cs deleted file mode 100644 index f7922779e..000000000 --- a/src/Perpetuum/Zones/NpcSystem/ThreatManager.cs +++ /dev/null @@ -1,310 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Text; -using Perpetuum.Comparers; -using Perpetuum.Timers; -using Perpetuum.Units; - -namespace Perpetuum.Zones.NpcSystem -{ - public enum ThreatType - { - Undefined, - Bodypull, - Damage, - Support, - Lock, - Buff, - Debuff, - Direct, - EnWar, - Ewar - } - - public struct Threat - { - - public const double WEBBER = 25; - public const double LOCK_PRIMARY = 2.0; - public const double LOCK_SECONDARY = 1.0; - public const double SENSOR_DAMPENER = 25.0; - public const double BODY_PULL = 1.0; - public const double SENSOR_BOOSTER = 15; - public const double REMOTE_SENSOR_BOOSTER = 15; - - public readonly ThreatType type; - public readonly double value; - - public Threat(ThreatType type, double value) - { - this.type = type; - this.value = value; - } - - public override string ToString() - { - return $"{type} = {value}"; - } - - public static Threat Multiply(Threat threat, double multiplier) - { - return new Threat(threat.type,threat.value * multiplier); - } - } - - public class Hostile : IComparable - { - private static readonly TimeSpan _threatTimeOut = TimeSpan.FromSeconds(30); - - private double _threat; - - public readonly Unit unit; - - public TimeSpan LastThreatUpdate { get; private set; } - - public event Action Updated; - - public Hostile(Unit unit) - { - this.unit = unit; - Threat = 0.0; - } - - public void AddThreat(Threat threat) - { - if ( threat.value <= 0.0 ) - return; - - Threat += threat.value; - } - - public bool IsExpired - { - get { return (GlobalTimer.Elapsed - LastThreatUpdate) >= _threatTimeOut; } - } - - public double Threat - { - get { return _threat; } - private set - { - if (Math.Abs(_threat - value) <= double.Epsilon) - return; - - _threat = value; - - OnThreatUpdated(); - } - } - - private void OnThreatUpdated() - { - LastThreatUpdate = GlobalTimer.Elapsed; - - Updated?.Invoke(this); - } - - public int CompareTo(Hostile other) - { - if (other._threat < _threat) - return -1; - - if (other._threat > _threat) - return 1; - - return 0; - } - } - - public interface IThreatManager - { - bool IsThreatened { get; } - bool Contains(Unit hostile); - void Remove(Hostile hostile); - ImmutableSortedSet Hostiles { get; } - } - - public static class ThreatExtensions - { - [CanBeNull] - public static Hostile GetMostHatedHostile(this IThreatManager manager) - { - return manager.Hostiles.Min; - } - } - - public class ThreatManager : IThreatManager - { - private ImmutableDictionary _hostiles = ImmutableDictionary.Empty; - - public Hostile GetOrAddHostile(Unit unit) - { - return ImmutableInterlocked.GetOrAdd(ref _hostiles, unit.Eid, eid => - { - var h = new Hostile(unit); - return h; - }); - } - - public ImmutableSortedSet Hostiles - { - get { return _hostiles.Values.ToImmutableSortedSet(); } - } - - public bool IsThreatened - { - get { return !_hostiles.IsEmpty; } - } - - public bool Contains(Unit unit) - { - return _hostiles.ContainsKey(unit.Eid); - } - - public void Clear() - { - _hostiles.Clear(); - } - - public void Remove(Hostile hostile) - { - ImmutableInterlocked.TryRemove(ref _hostiles, hostile.unit.Eid, out hostile); - } - - public string ToDebugString() - { - if ( _hostiles.Count == 0 ) - return string.Empty; - - var sb = new StringBuilder(); - - sb.AppendLine(); - sb.AppendLine("========== THREAT =========="); - sb.AppendLine(); - - foreach (var hostile in _hostiles.Values.OrderByDescending(h => h.Threat)) - { - sb.AppendFormat(" {0} ({1}) => {2}", hostile.unit.ED.Name,hostile.unit.Eid, hostile.Threat); - sb.AppendLine(); - } - - sb.AppendLine(); - sb.AppendLine("============================"); - - return sb.ToString(); - } - } - - /// - /// Manager of PseudoThreats - /// Processes and manages an internal collection of players aggressive to an npc - /// but not on the npc's ThreatManager. - /// For awarding players a portion of the total ep reward. - /// - public interface IPseudoThreatManager - { - void Update(TimeSpan time); - void AddOrRefreshExisting(Unit hostile); - void Remove(Unit hostile); - void AwardPseudoThreats(List alreadyAwarded, IZone zone, int ep); - } - - - public class PseudoThreatManager : IPseudoThreatManager - { - private readonly List _pseudoThreats; - private readonly object _lock; - - public PseudoThreatManager() - { - _pseudoThreats = new List(); - _lock = new object(); - } - - public void AwardPseudoThreats(List alreadyAwarded, IZone zone, int ep) - { - var pseudoHostileUnits = new List(); - lock (_lock) - { - pseudoHostileUnits = _pseudoThreats.Select(p => p.Unit).Except(alreadyAwarded, new EntityComparer()).Cast().ToList(); - } - foreach (var unit in pseudoHostileUnits) - { - var hostilePlayer = zone.ToPlayerOrGetOwnerPlayer(unit); - hostilePlayer?.Character.AddExtensionPointsBoostAndLog(EpForActivityType.Npc, ep / 2); - } - } - - public void AddOrRefreshExisting(Unit hostile) - { - lock (_lock) - { - var existing = _pseudoThreats.Where(x => x.Unit == hostile).FirstOrDefault(); - if (existing != null) - { - existing.RefreshThreat(); - return; - } - _pseudoThreats.Add(new PseudoThreat(hostile)); - } - } - - public void Remove(Unit hostile) - { - lock(_lock) - _pseudoThreats.RemoveAll(x => x.Unit == hostile); - } - - public void Update(TimeSpan time) - { - lock (_lock) - { - foreach (var threat in _pseudoThreats) - { - threat.Update(time); - } - CleanExpiredThreats(); - } - } - - private void CleanExpiredThreats() - { - _pseudoThreats.RemoveAll(threat => threat.IsExpired); - } - } - - - /// - /// An expirable record of a player that is aggressing an npc but the npc is - /// not capable of attacking back (removed from the ThreatManager) - /// - public class PseudoThreat - { - private TimeSpan _lastUpdated = TimeSpan.Zero; - private TimeSpan Expiration = TimeSpan.FromMinutes(1); - - public PseudoThreat(Unit unit) - { - Unit = unit; - } - - public Unit Unit { get; } - - public bool IsExpired - { - get { return _lastUpdated > Expiration; } - } - - public void RefreshThreat() - { - _lastUpdated = TimeSpan.Zero; - } - - public void Update(TimeSpan time) - { - _lastUpdated += time; - } - } -} diff --git a/src/Perpetuum/Zones/NpcSystem/Turret.cs b/src/Perpetuum/Zones/NpcSystem/Turret.cs index 0bb57a2d4..c04c9e025 100644 --- a/src/Perpetuum/Zones/NpcSystem/Turret.cs +++ b/src/Perpetuum/Zones/NpcSystem/Turret.cs @@ -1,320 +1,40 @@ using System; -using System.Collections.Generic; -using System.Linq; using Perpetuum.EntityFramework; -using Perpetuum.Modules; -using Perpetuum.Modules.EffectModules; -using Perpetuum.Modules.Weapons; using Perpetuum.Players; using Perpetuum.StateMachines; -using Perpetuum.Timers; using Perpetuum.Units; using Perpetuum.Zones.Effects; -using Perpetuum.Zones.Locking; -using Perpetuum.Zones.Locking.Locks; -using Perpetuum.Zones.Terrains; +using Perpetuum.Zones.NpcSystem.AI; namespace Perpetuum.Zones.NpcSystem { - public class ModuleActivator : IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor, - IEntityVisitor + public class Turret : Creature { - private readonly IntervalTimer _timer; - private readonly ActiveModule _module; - - public ModuleActivator(ActiveModule module) - { - _module = module; - _timer = new IntervalTimer(TimeSpan.FromSeconds(1),true); - } - - public void Update(TimeSpan time) - { - _timer.Update(time); - - if (!_timer.Passed) - return; - - _timer.Reset(); - - if (_module.State.Type != ModuleStateType.Idle) - return; - - _module.AcceptVisitor(this); - } - - private void TryActiveModule(LOSResult result, UnitLock primaryLock) - { - if (result.hit && !result.blockingFlags.HasFlag(BlockingFlags.Plant)) - return; - - _module.Lock = primaryLock; - _module.State.SwitchTo(ModuleStateType.Oneshot); - } - - public void Visit(MissileWeaponModule module) - { - var hasShieldEffect = module.ParentRobot.HasShieldEffect; - if (hasShieldEffect) - return; - - var primaryLock = module.ParentRobot.GetFinishedPrimaryLock(); - if (primaryLock == null) - return; - - var visibility = module.ParentRobot.GetVisibility(primaryLock.Target); - if (visibility == null) - return; - - var result = visibility.GetLineOfSight(true); - TryActiveModule(result, primaryLock); - } - - public void Visit(WeaponModule module) - { - var hasShieldEffect = module.ParentRobot.HasShieldEffect; - if (hasShieldEffect) - return; - - var primaryLock = module.ParentRobot.GetFinishedPrimaryLock(); - if (primaryLock == null) - return; - - var visibility = module.ParentRobot.GetVisibility(primaryLock.Target); - if (visibility == null) - return; - - var result = visibility.GetLineOfSight(false); - TryActiveModule(result,primaryLock); - } - - private const double ARMOR_REPAIR_THRESHOLD = 0.95; - private const double ARMOR_REPAIR_CORE_THRESHOLD = 0.35; - - public void Visit(ArmorRepairModule module) - { - if (module.ParentRobot.ArmorPercentage >= ARMOR_REPAIR_THRESHOLD) - return; - - if (module.ParentRobot.CorePercentage < ARMOR_REPAIR_CORE_THRESHOLD) - return; - - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double SHIELD_ARMOR_THRESHOLD = 0.35; - - public void Visit(ShieldGeneratorModule module) - { - if (module.ParentRobot.ArmorPercentage >= SHIELD_ARMOR_THRESHOLD) - return; - - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double SENSOR_JAMMER_CORE_THRESHOLD = 0.55; - - public void Visit(SensorJammerModule module) - { - if ( module.ParentRobot.CorePercentage < SENSOR_JAMMER_CORE_THRESHOLD ) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if (lockTarget == null) - return; - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double SENSOR_DAMPENER_CORE_THRESHOLD = 0.55; - - public void Visit(SensorDampenerModule module) - { - if (module.ParentRobot.CorePercentage < SENSOR_DAMPENER_CORE_THRESHOLD) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if (lockTarget == null) - return; - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double WEBBER_CORE_THRESHOLD = 0.55; - - public void Visit(WebberModule module) - { - if (module.ParentRobot.CorePercentage < WEBBER_CORE_THRESHOLD) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if (lockTarget == null) - return; - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double PAINTER_CORE_THRESHOLD = 0.65; - - public void Visit(TargetPainterModule module) - { - if (module.ParentRobot.CorePercentage < PAINTER_CORE_THRESHOLD) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if (lockTarget == null) - return; - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double BLOBBER_CORE_THRESHOLD = 0.55; - - public void Visit(BlobEmissionModulatorModule module) - { - if (module.ParentRobot.Zone.Configuration.Protected) - return; - - if (module.ParentRobot.CorePercentage < BLOBBER_CORE_THRESHOLD) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if (lockTarget == null) - return; - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - - private const double BLINDER_CORE_THRESHOLD = 0.55; - - public void Visit(TargetBlinderModule module) - { - if (module.ParentRobot.CorePercentage < BLINDER_CORE_THRESHOLD) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if (lockTarget == null) - return; - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - - private const double ENERGY_NEUTRALIZER_CORE_THRESHOLD = 0.55; - - public void Visit(EnergyNeutralizerModule module) - { - if (module.ParentRobot.CorePercentage < ENERGY_NEUTRALIZER_CORE_THRESHOLD) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if ( lockTarget == null ) - return; - - var visibility = module.ParentRobot.GetVisibility(lockTarget.Target); - if (visibility == null) - return; - - var r = visibility.GetLineOfSight(false); - if (r != null) - { - if (r.hit) - return; - } - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - private const double ENERGY_VAMPIRE_CORE_THRESHOLD = 0.05; - - public void Visit(EnergyVampireModule module) - { - if ( module.ParentRobot.CorePercentage < ENERGY_VAMPIRE_CORE_THRESHOLD ) - return; - - var lockTarget = ((Creature)module.ParentRobot).SelectOptimalLockTargetFor(module); - if ( lockTarget == null ) - return; - - var visibility = module.ParentRobot.GetVisibility(lockTarget.Target); - if (visibility == null) - return; - - var r = visibility.GetLineOfSight(false); - if (r != null) - { - if (r.hit) - return; - } - - module.Lock = lockTarget; - module.State.SwitchTo(ModuleStateType.Oneshot); - } - - public void Visit(SensorBoosterModule module) - { - if (module.State.Type == ModuleStateType.Idle) - { - module.State.SwitchTo(ModuleStateType.AutoRepeat); - } - } + private readonly NullAI _nullAI; + private readonly FiniteStateMachine _aiStateMachine; - public void Visit(ArmorHardenerModule module) + protected TurretAI AI { - if (module.State.Type == ModuleStateType.Idle) - { - module.State.SwitchTo(ModuleStateType.AutoRepeat); - } + get { return _aiStateMachine.Current ?? _nullAI; } } - private const double ENERGY_INJECTOR_THRESHOLD = 0.65; - - public void Visit(CoreBoosterModule module) + public FiniteStateMachine AIStateMachine { - if (module.ParentRobot.CorePercentage > ENERGY_INJECTOR_THRESHOLD) - return; - - module.State.SwitchTo(ModuleStateType.Oneshot); + get { return _aiStateMachine; } } - } - - - - public class Turret : Creature - { - private readonly NullAI _nullAI; - private readonly FiniteStateMachine _ai; protected Turret() { _nullAI = new NullAI(this); - _ai = new FiniteStateMachine(); + _aiStateMachine = new FiniteStateMachine(); } - protected TurretAI AI + public override void AcceptVisitor(IEntityVisitor visitor) { - get { return _ai.Current ?? _nullAI; } + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } } protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) @@ -338,222 +58,30 @@ protected override void OnUnitEffectChanged(Unit unit, Effect effect, bool apply base.OnUnitEffectChanged(unit, effect, apply); } - public override void AcceptVisitor(IEntityVisitor visitor) - { - if (!TryAcceptVisitor(this, visitor)) - base.AcceptVisitor(visitor); - } - protected override void OnUpdate(TimeSpan time) { - _ai.Update(time); + _aiStateMachine.Update(time); base.OnUpdate(time); } - protected void LockHostile(Unit unit,bool force = false) + public void LockHostile(Unit unit,bool force = false) { if (IsLocked(unit)) + { return; + } if (!force && !IsHostile(unit)) + { return; + } AddLock(unit, false); } - internal override bool IsHostile(Player player) + public override bool IsHostile(Player player) { return true; } - - protected abstract class TurretAI : IState - { - private readonly Turret _turret; - - protected TurretAI(Turret turret) - { - _turret = turret; - } - - public virtual void Enter() - { - WriteLog("Turret AI:" + GetType().Name); - } - - public virtual void Exit() - { - WriteLog("Turret AI:" + GetType().Name); - } - - public virtual void Update(TimeSpan time) - { - - } - - protected void WriteLog(string message) - { -// Logger.Info(message); - } - - public virtual void ToInactiveAI() - { - _turret._ai.ChangeState(new InactiveAI(_turret)); - } - - public virtual void ToActiveAI() - { - _turret._ai.ChangeState(new ActiveAI(_turret)); - } - - public virtual void AttackHostile(Unit unit) - { - - } - } - - private class NullAI : TurretAI - { - public NullAI(Turret turret) : base(turret) - { - } - } - - private class InactiveAI : TurretAI - { - private readonly Turret _turret; - - public InactiveAI(Turret turret) : base(turret) - { - _turret = turret; - } - - public override void Enter() - { - _turret.StopAllModules(); - _turret.ResetLocks(); - base.Enter(); - } - - public override void ToInactiveAI() - { - // nem csinal semmit - } - } - - private class ActiveAI : TurretAI - { - private readonly Turret _turret; - - private readonly List _moduleActivators; - - public ActiveAI(Turret turret) : base(turret) - { - _turret = turret; - - _moduleActivators = new List(); - - _minCycleTime = TimeSpan.FromSeconds(5); - - foreach (var module in _turret.ActiveModules) - { - _moduleActivators.Add(new ModuleActivator(module)); - _minCycleTime = _minCycleTime.Min(module.CycleTime); - } - } - - public override void Enter() - { - foreach (var unitVisibility in _turret.GetVisibleUnits()) - { - _turret.LockHostile(unitVisibility.Target); - } - - base.Enter(); - } - - private readonly TimeSpan _minCycleTime; - - public override void Exit() - { - _turret.StopAllModules(); - _turret.ResetLocks(); - base.Exit(); - } - - public override void AttackHostile(Unit unit) - { - if (!_turret.IsHostile(unit)) - return; - - _turret.LockHostile(unit); - base.AttackHostile(unit); - } - - private readonly IntervalTimer _primarySelectTimer = new IntervalTimer(0); - - public override void Update(TimeSpan time) - { - if ( !SelectPrimaryTarget(time) ) - return; - - foreach (var activator in _moduleActivators) - { - activator.Update(time); - } - - base.Update(time); - } - - private bool SelectPrimaryTarget(TimeSpan time) - { - var locks = _turret.GetLocks().Where(l => l.State == LockState.Locked).ToArray(); - if (locks.Length <= 0) - return false; - - _primarySelectTimer.Update(time); - - if (_primarySelectTimer.Passed) - { - _primarySelectTimer.Interval = FastRandom.NextTimeSpan(_minCycleTime); - - var validLocks = new List(); - - foreach (var l in locks) - { - var unitLock = (UnitLock)l; - - if (unitLock.Primary) - continue; - - var visibility = _turret.GetVisibility(unitLock.Target); - if (visibility == null) - continue; - - var r = visibility.GetLineOfSight(false); - if (r != null) - { - if (r.hit && (r.blockingFlags & BlockingFlags.Plant) == 0) - continue; - } - - validLocks.Add(unitLock); - } - - if (validLocks.Count > 0) - { - var newPrimary = validLocks.RandomElement(); - _turret.SetPrimaryLock(newPrimary); - return true; - } - } - - return locks.Any(l => l.Primary); - } - - public override void ToActiveAI() - { - // nem csinal semmit - } - } } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/PBS/DockingBases/ExpiringPBSDockingBase.cs b/src/Perpetuum/Zones/PBS/DockingBases/ExpiringPBSDockingBase.cs index 4d46802a9..8adb00bc9 100644 --- a/src/Perpetuum/Zones/PBS/DockingBases/ExpiringPBSDockingBase.cs +++ b/src/Perpetuum/Zones/PBS/DockingBases/ExpiringPBSDockingBase.cs @@ -106,7 +106,7 @@ protected override void OnUpdate(TimeSpan time) base.OnUpdate(time); } - public override void JoinChannel(Character character) + protected override void JoinChannel(Character character) { base.JoinChannel(character); ChannelManager.Announcement(ChannelName, _announcer, $"Base is going to expire in: {Remaining.ToHumanTimeString()}"); diff --git a/src/Perpetuum/Zones/PBS/Turrets/PBSTurret.cs b/src/Perpetuum/Zones/PBS/Turrets/PBSTurret.cs index 4af9f87f1..72207dee7 100644 --- a/src/Perpetuum/Zones/PBS/Turrets/PBSTurret.cs +++ b/src/Perpetuum/Zones/PBS/Turrets/PBSTurret.cs @@ -196,7 +196,7 @@ public double BlobEmissionRadius get { return _blobEmitter.BlobEmissionRadius; } } - internal override bool IsHostile(Player player) + public override bool IsHostile(Player player) { return IsHostileCorporation(player.CorporationEid); } diff --git a/src/Perpetuum/Zones/ProximityProbes/ProximityDevice.cs b/src/Perpetuum/Zones/ProximityProbes/ProximityDevice.cs new file mode 100644 index 000000000..fbf8db883 --- /dev/null +++ b/src/Perpetuum/Zones/ProximityProbes/ProximityDevice.cs @@ -0,0 +1,342 @@ +using Perpetuum.Accounting.Characters; +using Perpetuum.EntityFramework; +using Perpetuum.ExportedTypes; +using Perpetuum.Groups.Corporations; +using Perpetuum.Log; +using Perpetuum.Players; +using Perpetuum.Timers; +using Perpetuum.Units; +using Perpetuum.Units.DockingBases; +using Perpetuum.Zones.PBS; +using Perpetuum.Zones.Teleporting; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Perpetuum.Zones.ProximityProbes +{ + public interface ICharactersRegistered + { + Character[] GetRegisteredCharacters(); + void ReloadRegistration(); + int GetMaxRegisteredCount(); + } + + //ez van kinn a terepen + public abstract class ProximityDeviceBase : Unit, ICharactersRegistered + { + private readonly CharactersRegisterHelper _charactersRegisterHelper; + private IntervalTimer _probingInterval = new IntervalTimer(TimeSpan.FromSeconds(10)); + private UnitDespawnHelper _despawnHelper; + + protected ProximityDeviceBase() + { + _charactersRegisterHelper = new CharactersRegisterHelper(this); + } + + public ICorporationManager CorporationManager { get; set; } + + public virtual void CheckDeploymentAndThrow(IZone zone, Position spawnPosition) + { + zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.PROXIMITY_PROBE_DEPLOY_RANGE_FROM_BASE).Any().ThrowIfTrue(ErrorCodes.NotDeployableNearObject); + zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.PROXIMITY_PROBE_DEPLOY_RANGE_FROM_TELEPORT).Any().ThrowIfTrue(ErrorCodes.TeleportIsInRange); + zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.PROXIMITY_PROBE_DEPLOY_RANGE_FROM_PROBE).Any().ThrowIfTrue(ErrorCodes.TooCloseToOtherDevice); + } + + public void SetDespawnTime(TimeSpan despawnTime) + { + _despawnHelper = UnitDespawnHelper.Create(this, despawnTime); + _despawnHelper.DespawnStrategy = Kill; + } + + // TODO: have to find better solution + public UnitDespawnHelper GetDespawnHelper() + { + return _despawnHelper; + } + + protected internal override void UpdatePlayerVisibility(Player player) + { + UpdateVisibility(player); + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + protected override void OnUpdate(TimeSpan time) + { + base.OnUpdate(time); + + _ = _probingInterval.Update(time); + + if (!_probingInterval.Passed) + { + return; + } + + _probingInterval.Reset(); + + if (IsActive) + { + //detect + List robotsNearMe = GetNoticedUnits(); + + //do something + OnUnitsFound(robotsNearMe); + } + + if (_despawnHelper == null) + { + Items.ItemPropertyModifier m = GetPropertyModifier(AggregateField.despawn_time); + TimeSpan timespan = TimeSpan.FromMilliseconds((int)m.Value); + SetDespawnTime(timespan); + } + + _despawnHelper.Update(time, this); + } + + protected virtual bool IsActive => true; + + #region registration + + //ezt kell hivogatni requestbol, ha valtozott + public void ReloadRegistration() + { + _charactersRegisterHelper.ReloadRegistration(); + } + + public Character[] GetRegisteredCharacters() + { + return _charactersRegisterHelper.GetRegisteredCharacters(); + } + + public int GetMaxRegisteredCount() + { + return _charactersRegisterHelper.GetMaxRegisteredCount(); + } + + #endregion + + #region probe functions + + // egy adott pillanatban kiket lat + [CanBeNull] + public abstract List GetNoticedUnits(); + + protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) + { + base.OnEnterZone(zone, enterType); + _probingInterval = new IntervalTimer(GetProximityCheckInterval(), true); + } + + public virtual void OnDeviceDead() + { + //uccso info a regisztraltaknak + SendDeviceDead(); + PBSRegisterHelper.ClearMembersFromSql(Eid); + Zone.UnitService.RemoveUserUnit(this); + Logger.Info("probe got deleted " + Eid); + } + + public virtual void OnDeviceCreated() + { + //elso info arrol hogy letrejott + + Logger.Info("probe created " + Eid); + + SendDeviceCreated(); + + } + + + public virtual void OnUnitsFound(List unitsFound) + { + //itt lehet mindenfele, pl most kuldunk egy kommandot amire a kliens terkepet frissit + + if (unitsFound.Count <= 0) + { + return; + } + + Character[] registerdCharacters = GetRegisteredCharacters(); + + if (registerdCharacters.Length <= 0) + { + return; + } + + Dictionary infoDict = CreateInfoDictionaryForProximityProbe(unitsFound); + + Message.Builder.SetCommand(Commands.ProximityProbeInfo).WithData(infoDict).ToCharacters(registerdCharacters).Send(); + } + + #endregion + + protected override void OnDead(Unit killer) + { + OnDeviceDead(); + base.OnDead(killer); + } + + public Dictionary GetProbeInfo(bool includeRegistered = true) + { + Dictionary info = BaseInfoToDictionary(); + + Dictionary probeDict = new Dictionary(); + + if (includeRegistered) + { + probeDict.Add(k.registered, GetRegisteredCharacters().GetCharacterIDs().ToArray()); + } + + probeDict.Add(k.zoneID, Zone.Id); + probeDict.Add(k.x, CurrentPosition.X); + probeDict.Add(k.y, CurrentPosition.Y); + info.Add("probe", probeDict); + return info; + } + + /// + /// All info included + /// + /// + public override Dictionary ToDictionary() + { + return GetProbeInfo(); + } + + public void SendDeviceCreated() + { + IEnumerable membersToInfom = GetAllPossibleMembersToInfom(); + Message.Builder.SetCommand(Commands.ProximityProbeCreated).WithData(ToDictionary()).ToCharacters(membersToInfom).Send(); + } + + public void SendUpdateToAllPossibleMembers() + { + IEnumerable members = GetAllPossibleMembersToInfom(); + + Message.Builder.SetCommand(Commands.ProximityProbeUpdate).WithData(ToDictionary()).ToCharacters(members).Send(); + } + + private void SendDeviceDead() + { + IEnumerable membersToInfom = GetAllPossibleMembersToInfom(); + + Message.Builder.SetCommand(Commands.ProximityProbeDead).WithData(ToDictionary()).ToCharacters(membersToInfom).Send(); + } + + public IEnumerable GetAllPossibleMembersToInfom() + { + return GetRegisteredCharacters().Concat(GetProximityBoard(Owner)).Distinct(); + } + + private IEnumerable GetProximityBoard(long corporationEid) + { + const CorporationRole roleMask = CorporationRole.CEO | CorporationRole.DeputyCEO | CorporationRole.Accountant; + return CorporationManager.LoadCorporationMembersWithAnyRole(corporationEid, roleMask); + } + + public Dictionary CreateInfoDictionaryForProximityProbe(List unitsFound) + { + Dictionary infoDict = GetProbeInfo(false); + + Dictionary unitsInfo = unitsFound.ToDictionary("c", p => + { + return new Dictionary + { + {k.characterID, p.Character.Id}, + {k.x, p.CurrentPosition.X}, + {k.y, p.CurrentPosition.Y} + }; + }); + + infoDict.Add(k.units, unitsInfo); + + return infoDict; + } + + public void Init(IEnumerable summonerCharacters) + { + PBSRegisterHelper.WriteRegistersToDb(Eid, summonerCharacters); + _probingInterval.Interval = TimeSpan.FromMilliseconds(GetProximityCheckInterval()); + } + + public virtual int GetProximityCheckInterval() + { + DefinitionConfig config = EntityDefault.Get(Definition).Config; + + if (config.cycle_time == null) + { + Logger.Error("consistency error in proximity device. interval not defined. " + Definition + " " + ED.Name); + return 150000; + } + + return ((int)config.cycle_time) + FastRandom.NextInt(0, 250); + } + + public bool IsRegistered(Character character) + { + return GetRegisteredCharacters().Contains(character); + } + + public ErrorCodes HasAccess(Character character) + { + if (IsRegistered(character)) + { + return ErrorCodes.NoError; + } + + long corporationEid = character.CorporationEid; + + if (corporationEid != Owner) + { + return ErrorCodes.AccessDenied; + } + + CorporationRole role = Corporation.GetRoleFromSql(character); + + return IsAllProbesVisible(role) ? ErrorCodes.NoError : ErrorCodes.AccessDenied; + } + + public Dictionary GetProbeRegistrationInfo() + { + Corporation ownerCorporation = Corporation.GetOrThrow(Owner); + int maxRegistered = ownerCorporation.GetMaximumRegisteredProbesAmount(); + int currentRegistered = GetRegisteredCharacters().Length; + int boardMembers = ownerCorporation.GetBoardMembersCount(); + + Dictionary result = new Dictionary + { + {k.eid, Eid }, + {"maxRegistered", maxRegistered}, + {"freeSlots", maxRegistered - (currentRegistered - boardMembers).Clamp(0, int.MaxValue)}, + {"currentlyRegistered", currentRegistered}, + {"boardMembers", boardMembers}, + }; + + return result; + } + + public static bool IsAllProbesVisible(CorporationRole role) + { + return role.IsAnyRole(CorporationRole.CEO, CorporationRole.DeputyCEO); + } + + public override void OnInsertToDb() + { + DynamicProperties.Update(k.currentCore, Core); + base.OnInsertToDb(); + } + + public override void OnUpdateToDb() + { + DynamicProperties.Update(k.currentCore, Core); + base.OnUpdateToDb(); + } + } +} diff --git a/src/Perpetuum/Zones/ProximityProbes/ProximityProbe.cs b/src/Perpetuum/Zones/ProximityProbes/ProximityProbe.cs index 796845818..0cfb05719 100644 --- a/src/Perpetuum/Zones/ProximityProbes/ProximityProbe.cs +++ b/src/Perpetuum/Zones/ProximityProbes/ProximityProbe.cs @@ -1,320 +1,57 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Perpetuum.Accounting.Characters; using Perpetuum.EntityFramework; using Perpetuum.ExportedTypes; -using Perpetuum.Groups.Corporations; -using Perpetuum.Log; using Perpetuum.Players; -using Perpetuum.Timers; -using Perpetuum.Units; -using Perpetuum.Units.DockingBases; -using Perpetuum.Zones.PBS; -using Perpetuum.Zones.Teleporting; +using Perpetuum.Zones.Blobs.BlobEmitters; +using System.Collections.Generic; +using System.Linq; namespace Perpetuum.Zones.ProximityProbes { - public interface ICharactersRegistered + public class ProximityProbe : ProximityDeviceBase, IBlobEmitter { - Character[] GetRegisteredCharacters(); - void ReloadRegistration(); - int GetMaxRegisteredCount(); - } - - //ez van kinn a terepen - public abstract class ProximityProbeBase : Unit , ICharactersRegistered - { - private readonly CharactersRegisterHelper _charactersRegisterHelper; - private IntervalTimer _probingInterval = new IntervalTimer(TimeSpan.FromSeconds(10)); - private UnitDespawnHelper _despawnHelper; - - protected ProximityProbeBase() - { - _charactersRegisterHelper = new CharactersRegisterHelper(this); - } - - public ICorporationManager CorporationManager { get; set; } - - public virtual void CheckDeploymentAndThrow(IZone zone, Position spawnPosition) - { - zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.PROXIMITY_PROBE_DEPLOY_RANGE_FROM_BASE).Any().ThrowIfTrue(ErrorCodes.NotDeployableNearObject); - zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.PROXIMITY_PROBE_DEPLOY_RANGE_FROM_TELEPORT).Any().ThrowIfTrue(ErrorCodes.TeleportIsInRange); - zone.Units.OfType().WithinRange(spawnPosition, DistanceConstants.PROXIMITY_PROBE_DEPLOY_RANGE_FROM_PROBE).Any().ThrowIfTrue(ErrorCodes.TooCloseToOtherDevice); - } - - public void SetDespawnTime(TimeSpan despawnTime) - { - _despawnHelper = UnitDespawnHelper.Create(this, despawnTime); - _despawnHelper.DespawnStrategy = Kill; - } - protected internal override void UpdatePlayerVisibility(Player player) { UpdateVisibility(player); } - public override void AcceptVisitor(IEntityVisitor visitor) + public override List GetNoticedUnits() { - if (!TryAcceptVisitor(this, visitor)) - base.AcceptVisitor(visitor); + return GetVisibleUnits().Select(v => v.Target).OfType().ToList(); } - protected override void OnUpdate(TimeSpan time) + protected override bool IsActive { - base.OnUpdate(time); - - _probingInterval.Update(time); - - if (!_probingInterval.Passed) - return; - - _probingInterval.Reset(); - - if (IsActive) - { - //detect - var robotsNearMe = GetNoticedUnits(); - - //do something - OnUnitsFound(robotsNearMe); - } - - if (_despawnHelper == null) + get { - var m = GetPropertyModifier(AggregateField.despawn_time); - var timespan = TimeSpan.FromMilliseconds((int)m.Value); - SetDespawnTime(timespan); + double coreRatio = Core.Ratio(CoreMax); + return coreRatio > 0.98; } - - _despawnHelper.Update(time, this); - } - - protected virtual bool IsActive => true; - - #region registration - - //ezt kell hivogatni requestbol, ha valtozott - public void ReloadRegistration() - { - _charactersRegisterHelper.ReloadRegistration(); - } - - public Character[] GetRegisteredCharacters() - { - return _charactersRegisterHelper.GetRegisteredCharacters(); - } - - public int GetMaxRegisteredCount() - { - return _charactersRegisterHelper.GetMaxRegisteredCount(); - } - - #endregion - - #region probe functions - - // egy adott pillanatban kiket lat - [CanBeNull] - public abstract List GetNoticedUnits(); - - protected override void OnEnterZone(IZone zone, ZoneEnterType enterType) - { - base.OnEnterZone(zone, enterType); - _probingInterval = new IntervalTimer(GetProbeInterval(), true); - } - - public virtual void OnProbeDead() - { - //uccso info a regisztraltaknak - SendProbeDead(); - PBSRegisterHelper.ClearMembersFromSql(Eid); - Zone.UnitService.RemoveUserUnit(this); - Logger.Info("probe got deleted " + Eid); - } - - public virtual void OnProbeCreated() - { - //elso info arrol hogy letrejott - - Logger.Info("probe created " + Eid); - - SendProbeCreated(); - - } - - - public virtual void OnUnitsFound(List unitsFound) - { - //itt lehet mindenfele, pl most kuldunk egy kommandot amire a kliens terkepet frissit - - if (unitsFound.Count <= 0) return; - - var registerdCharacters = GetRegisteredCharacters(); - - if (registerdCharacters.Length <= 0) return; - - var infoDict = CreateInfoDictionaryForProximityProbe(unitsFound); - - Message.Builder.SetCommand(Commands.ProximityProbeInfo).WithData(infoDict).ToCharacters(registerdCharacters).Send(); } - #endregion - - protected override void OnDead(Unit killer) + public double BlobEmission { - OnProbeDead(); - base.OnDead(killer); - } - - public Dictionary GetProbeInfo(bool includeRegistered = true) - { - var info = BaseInfoToDictionary(); - - var probeDict = new Dictionary(); - - if (includeRegistered) + get { - probeDict.Add(k.registered, GetRegisteredCharacters().GetCharacterIDs().ToArray()); + Items.ItemPropertyModifier blobEmission = GetPropertyModifier(AggregateField.blob_emission); + return blobEmission.Value; } - - probeDict.Add(k.zoneID, Zone.Id); - probeDict.Add(k.x, CurrentPosition.X); - probeDict.Add(k.y, CurrentPosition.Y); - info.Add("probe", probeDict); - return info; - } - - /// - /// All info included - /// - /// - public override Dictionary ToDictionary() - { - return GetProbeInfo(); - } - - public void SendProbeCreated() - { - var membersToInfom = GetAllPossibleMembersToInfom(); - Message.Builder.SetCommand(Commands.ProximityProbeCreated).WithData(ToDictionary()).ToCharacters(membersToInfom).Send(); - } - - public void SendUpdateToAllPossibleMembers() - { - var members = GetAllPossibleMembersToInfom(); - - Message.Builder.SetCommand(Commands.ProximityProbeUpdate).WithData(ToDictionary()).ToCharacters(members).Send(); } - private void SendProbeDead() + public double BlobEmissionRadius { - var membersToInfom = GetAllPossibleMembersToInfom(); - - Message.Builder.SetCommand(Commands.ProximityProbeDead).WithData(ToDictionary()).ToCharacters(membersToInfom).Send(); - } - - public IEnumerable GetAllPossibleMembersToInfom() - { - return GetRegisteredCharacters().Concat(GetProximityBoard(Owner)).Distinct(); - } - - private IEnumerable GetProximityBoard(long corporationEid) - { - const CorporationRole roleMask = CorporationRole.CEO | CorporationRole.DeputyCEO | CorporationRole.Accountant; - return CorporationManager.LoadCorporationMembersWithAnyRole(corporationEid,roleMask); - } - - public Dictionary CreateInfoDictionaryForProximityProbe( List unitsFound) - { - var infoDict = GetProbeInfo(false); - - var unitsInfo = unitsFound.ToDictionary("c", p => + get { - return new Dictionary - { - {k.characterID, p.Character.Id}, - {k.x, p.CurrentPosition.X}, - {k.y, p.CurrentPosition.Y} - }; - }); - - infoDict.Add(k.units, unitsInfo); - - return infoDict; - } - - public void InitProbe(IEnumerable summonerCharacters ) - { - PBSRegisterHelper.WriteRegistersToDb(Eid, summonerCharacters); - _probingInterval.Interval = TimeSpan.FromMilliseconds(GetProbeInterval()); - } - - public virtual int GetProbeInterval() - { - var config = EntityDefault.Get(Definition).Config; - - if (config.cycle_time == null) - { - Logger.Error("consistency error in proximityProbe. interval not defined. " + Definition + " " + ED.Name); - return 150000; + Items.ItemPropertyModifier blobEmissionRadius = GetPropertyModifier(AggregateField.blob_emission_radius); + return blobEmissionRadius.Value; } - - return ((int) config.cycle_time) + FastRandom.NextInt(0,250); - } - - public bool IsRegistered(Character character) - { - return GetRegisteredCharacters().Contains(character); } - public ErrorCodes HasAccess(Character character) + public override void AcceptVisitor(IEntityVisitor visitor) { - if (IsRegistered(character)) - { - return ErrorCodes.NoError; - } - - var corporationEid = character.CorporationEid; - - if (corporationEid != Owner) - { - return ErrorCodes.AccessDenied; - } - - var role = Corporation.GetRoleFromSql(character); - - if (IsAllProbesVisible(role)) + if (!TryAcceptVisitor(this, visitor)) { - return ErrorCodes.NoError; + base.AcceptVisitor(visitor); } - - return ErrorCodes.AccessDenied; - } - - public Dictionary GetProbeRegistrationInfo() - { - var ownerCorporation = Corporation.GetOrThrow(Owner); - var maxRegistered = ownerCorporation.GetMaximumRegisteredProbesAmount(); - var currentRegistered = GetRegisteredCharacters().Length; - var boardMembers = ownerCorporation.GetBoardMembersCount(); - - var result = new Dictionary - { - {k.eid, Eid }, - {"maxRegistered", maxRegistered}, - {"freeSlots", (maxRegistered - (currentRegistered - boardMembers).Clamp(0, int.MaxValue))}, - {"currentlyRegistered", currentRegistered}, - {"boardMembers", boardMembers}, - }; - - return result; - } - - public static bool IsAllProbesVisible(CorporationRole role) - { - return role.IsAnyRole(CorporationRole.CEO, CorporationRole.DeputyCEO); } } - -} +} \ No newline at end of file diff --git a/src/Perpetuum/Zones/ProximityProbes/ProximityProbeDeployer.cs b/src/Perpetuum/Zones/ProximityProbes/ProximityProbeDeployer.cs index 9c2db44d3..7a55ece82 100644 --- a/src/Perpetuum/Zones/ProximityProbes/ProximityProbeDeployer.cs +++ b/src/Perpetuum/Zones/ProximityProbes/ProximityProbeDeployer.cs @@ -9,13 +9,13 @@ namespace Perpetuum.Zones.ProximityProbes { - public class VisibilityBasedProbeDeployer : ItemDeployer + public class ProximityProbeDeployer : ItemDeployer { - private readonly IEntityServices _entityServices; + private readonly IEntityServices entityServices; - public VisibilityBasedProbeDeployer(IEntityServices entityServices) : base(entityServices) + public ProximityProbeDeployer(IEntityServices entityServices) : base(entityServices) { - _entityServices = entityServices; + this.entityServices = entityServices; } protected override Unit CreateDeployableItem(IZone zone, Position spawnPosition, Player player) @@ -27,7 +27,7 @@ protected override Unit CreateDeployableItem(IZone zone, Position spawnPosition, var maxProbes = corporation.GetMaximumProbeAmount(); corporation.GetProximityProbeEids().Count().ThrowIfGreaterOrEqual(maxProbes, ErrorCodes.MaximumAmountOfProbesReached); - var probe = (ProximityProbeBase)_entityServices.Factory.CreateWithRandomEID(DeployableItemEntityDefault); + var probe = (ProximityDeviceBase)entityServices.Factory.CreateWithRandomEID(DeployableItemEntityDefault); probe.CheckDeploymentAndThrow(zone, spawnPosition); //Enforce min-distance separations probe.Owner = corporation.Eid; var zoneStorage = zone.Configuration.GetStorage(); @@ -39,7 +39,7 @@ protected override Unit CreateDeployableItem(IZone zone, Position spawnPosition, var initialMembers = corporation.GetMembersWithAnyRoles(CorporationRole.CEO, CorporationRole.DeputyCEO).Select(cm => cm.character).ToList(); initialMembers.Add(player.Character); - probe.InitProbe( initialMembers.Distinct() ); + probe.Init( initialMembers.Distinct() ); probe.SetDespawnTime(this.ProximityProbeDespawnTime); return probe; } diff --git a/src/Perpetuum/Zones/ProximityProbes/VisibilityBasedProximityProbe.cs b/src/Perpetuum/Zones/ProximityProbes/VisibilityBasedProximityProbe.cs deleted file mode 100644 index ad42b5a7e..000000000 --- a/src/Perpetuum/Zones/ProximityProbes/VisibilityBasedProximityProbe.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Perpetuum.ExportedTypes; -using Perpetuum.Players; -using Perpetuum.Zones.Blobs.BlobEmitters; - -namespace Perpetuum.Zones.ProximityProbes -{ - public class VisibilityBasedProximityProbe : ProximityProbeBase , IBlobEmitter - { - protected internal override void UpdatePlayerVisibility(Player player) - { - UpdateVisibility(player); - } - - public override List GetNoticedUnits() - { - return GetVisibleUnits().Select(v=>v.Target).OfType().ToList(); - } - - protected override bool IsActive - { - get - { - var coreRatio = Core.Ratio(CoreMax); - return coreRatio > 0.98; - } - } - - public double BlobEmission - { - get - { - var blobEmission = GetPropertyModifier(AggregateField.blob_emission); - return blobEmission.Value; - } - } - - public double BlobEmissionRadius - { - get - { - var blobEmissionRadius = GetPropertyModifier(AggregateField.blob_emission_radius); - return blobEmissionRadius.Value; - } - } - - public override void OnInsertToDb() - { - DynamicProperties.Update(k.currentCore, Core); - base.OnInsertToDb(); - } - - public override void OnUpdateToDb() - { - DynamicProperties.Update(k.currentCore, Core); - base.OnUpdateToDb(); - } - } -} \ No newline at end of file diff --git a/src/Perpetuum/Zones/RemoteControl/BandwidthHandler.cs b/src/Perpetuum/Zones/RemoteControl/BandwidthHandler.cs new file mode 100644 index 000000000..7a05b8711 --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/BandwidthHandler.cs @@ -0,0 +1,161 @@ +using Perpetuum.Items; +using Perpetuum.Modules; +using Perpetuum.Units; +using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.Flocks; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Perpetuum.Zones.RemoteControl +{ + public class BandwidthHandler : ISmartCreatureGroup + { + private readonly RemoteControllerModule owner; + private List channels = new List(); + private readonly ConcurrentQueue newChannels = new ConcurrentQueue(); + private readonly ConcurrentQueue deactivatedChannels = new ConcurrentQueue(); + private int dirty; + + public string Name => owner.ParentRobot.GetCharacter().Nick; + + public IEnumerable Members => channels.Select(x => x.Turret); + + public BandwidthHandler(RemoteControllerModule owner) + { + this.owner = owner; + } + + public double BandwidthUsed + { + get + { + return channels.Any() + ? channels.Sum(x => x.Turret?.RemoteChannelBandwidthUsage ?? 0) + : 0; + } + } + + public List Turrets + { + get { return channels; } + } + + public bool HasFreeBandwidthFor(RemoteControlledUnit unit) + { + return BandwidthUsed <= owner.BandwidthMax - unit.RemoteChannelBandwidthUsage; + } + + public void UseRemoteChannel(RemoteControlledCreature turret) + { + UseRemoteChannel(new RemoteChannel(owner, turret)); + } + + public void UseRemoteChannel(RemoteChannel newChannel) + { + newChannels.Enqueue(newChannel); + Interlocked.Exchange(ref dirty, 1); + } + + public void OnRemoteChannelDeactivated(RemoteControlledCreature turret) + { + var channel = GetRemoteChannelByUnit(turret); + + if (channel != null) + { + ReleaseRemoteChannel(channel); + turret.RemoteChannelDeactivated -= OnRemoteChannelDeactivated; + } + + Update(); + } + + public void CloseAllChannels() + { + foreach (var channel in channels) + { + channel.Turret.Kill(); + ReleaseRemoteChannel(channel); + } + + Update(); + } + + private void ReleaseRemoteChannel(RemoteChannel channel) + { + deactivatedChannels.Enqueue(channel); + Interlocked.Exchange(ref dirty, 1); + } + + private void ProcessReleasedChannels(IList channels) + { + RemoteChannel releasedChannel; + + while (deactivatedChannels.TryDequeue(out releasedChannel)) + { + channels.Remove(releasedChannel); + } + } + + public void Update() + { + if (Interlocked.CompareExchange(ref dirty, 0, 1) == 1) + { + var channelsToProcess = this.channels.ToList(); + + try + { + ProcessReleasedChannels(channelsToProcess); + ProcessNewChannels(channelsToProcess); + } + finally + { + this.channels = channelsToProcess; + } + } + } + + private void ProcessNewChannels(IList channels) + { + RemoteChannel newChannel; + while (newChannels.TryDequeue(out newChannel)) + { + if (channels.Any(l => l.Equals(newChannel))) + { + continue; + } + + channels.Add(newChannel); + } + } + + [CanBeNull] + public RemoteChannel GetRemoteChannel(long channelId) + { + if (channelId == 0) + { + return null; + } + + return channels.Find(l => l.Id == channelId); + } + + [CanBeNull] + public RemoteChannel GetRemoteChannelByUnit(Unit unit) + { + return GetRemoteChannelByEid(unit.Eid); + } + + public void AddDebugInfoToDictionary(IDictionary dictionary) + { + // Do nothing + } + + [CanBeNull] + private RemoteChannel GetRemoteChannelByEid(long unitEid) + { + return channels.OfType().FirstOrDefault(l => l.Turret.Eid == unitEid); + } + } +} diff --git a/src/Perpetuum/Zones/RemoteControl/CombatDrone.cs b/src/Perpetuum/Zones/RemoteControl/CombatDrone.cs new file mode 100644 index 000000000..54a84988b --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/CombatDrone.cs @@ -0,0 +1,97 @@ +using Perpetuum.EntityFramework; +using Perpetuum.Players; +using Perpetuum.Services.Standing; +using Perpetuum.Units; +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.NpcSystem; +using System; + +namespace Perpetuum.Zones.RemoteControl +{ + public class CombatDrone : RemoteControlledCreature + { + public double GuardRange { get; set; } + + public override bool IsStationary => false; + + public CombatDrone(IStandingHandler standingHandler) + : base(standingHandler) + { + } + + public bool IsInGuardRange => CurrentPosition.IsInRangeOf2D(HomePosition, GuardRange); + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + public override bool IsHostile(Player player) + { + return IsHostilePlayer(player); + } + + public override void OnAggression(Unit victim) + { + CommandRobot.OnAggression(victim); + } + + protected override bool IsHostileFor(Unit unit) + { + return unit.IsHostile(this); + } + + protected override void OnUpdate(TimeSpan time) + { + HomePosition = CommandRobot.CurrentPosition; + base.OnUpdate(time); + } + + protected override bool IsDetected(Unit target) + { + return IsCommandBotPrimaryLock(target) && base.IsDetected(target); + } + + internal override bool IsHostile(Npc npc) + { + return true; + } + + internal override bool IsHostile(CombatDrone drone) + { + return !(drone.CommandRobot is Player player) || IsHostilePlayer(player); + } + + internal override bool IsHostile(SentryTurret turret) + { + return !(turret.CommandRobot is Player player) || IsHostilePlayer(player); + } + + protected override void OnUnitLockStateChanged(Lock @lock) + { + // Do nothing + } + + protected override void UpdateUnitVisibility(Unit target) + { + if (target is Npc || + target is RemoteControlledCreature) + { + UpdateVisibility(target); + } + } + + private bool IsCommandBotPrimaryLock(Unit unit) + { + Lock primaryLock = CommandRobot.GetPrimaryLock(); + + return primaryLock != null && + primaryLock.State == Locking.LockState.Locked && + primaryLock is UnitLock && + (primaryLock as UnitLock).Target == unit; + } + } +} diff --git a/src/Perpetuum/Zones/RemoteControl/IndustrialTurret.cs b/src/Perpetuum/Zones/RemoteControl/IndustrialTurret.cs new file mode 100644 index 000000000..04680ac6a --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/IndustrialTurret.cs @@ -0,0 +1,109 @@ +using Perpetuum.Data; +using Perpetuum.Log; +using Perpetuum.Players; +using Perpetuum.Services.Looting; +using Perpetuum.Services.Standing; +using Perpetuum.Units; +using Perpetuum.Zones.NpcSystem; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Transactions; + +namespace Perpetuum.Zones.RemoteControl +{ + public class IndustrialTurret : RemoteControlledCreature + { + public TurretType TurretType { get; private set; } + + public IndustrialTurret(IStandingHandler standingHandler) + : base(standingHandler) + { + } + + public void SetTurretType(TurretType turretType) + { + TurretType = turretType; + } + + protected override bool IsHostileFor(Unit unit) + { + return unit.IsHostile(this); + } + + public override bool IsHostile(Player player) + { + return false; + } + + internal override bool IsHostile(Npc npc) + { + return false; + } + + protected override void OnBeforeRemovedFromZone(IZone zone) + { + EjectCargo(zone); + base.OnBeforeRemovedFromZone(zone); + } + + public void EjectCargo(IZone zone) + { + using (TransactionScope scope = Db.CreateTransaction()) + { + try + { + Robots.RobotInventory robotInventory = GetContainer(); + + Debug.Assert(robotInventory != null); + + List lootItems = new List(); + + foreach (Items.Item item in robotInventory + .GetItems() + .Where(i => !i.ED.AttributeFlags.NonStackable)) + { + if (item.Quantity > 0) + { + lootItems.Add( + LootItemBuilder + .Create(item.Definition) + .SetQuantity(item.Quantity) + .SetRepackaged(item.ED.AttributeFlags.Repackable) + .Build()); + } + + robotInventory.RemoveItemOrThrow(item); + Repository.Delete(item); + } + + if (lootItems.Count > 0) + { + _ = LootContainer.Create() + .AddLoot(lootItems) + .BuildAndAddToZone(zone, CurrentPosition); + } + + Save(); + + scope.Complete(); + } + catch (Exception ex) + { + Logger.Exception(ex); + } + } + } + + protected override void OnUpdate(TimeSpan time) + { + if (!IsInOperationalRange) + { + Kill(); + } + + base.OnUpdate(time); + } + } +} diff --git a/src/Perpetuum/Zones/RemoteControl/RemoteChannel.cs b/src/Perpetuum/Zones/RemoteControl/RemoteChannel.cs new file mode 100644 index 000000000..188f31da6 --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/RemoteChannel.cs @@ -0,0 +1,39 @@ +using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Modules; + +namespace Perpetuum.Zones.RemoteControl +{ + public delegate void RemoteChannelEventHandler(RemoteControlledCreature turret); + public delegate void RemoteChannelEventHandler(RemoteChannel channel, T arg); + + public class RemoteChannel + { + public long Id { get; private set; } + + public RemoteControllerModule Owner { get; private set; } + + public RemoteControlledCreature Turret { get; set; } + + public RemoteChannel(RemoteControllerModule owner, RemoteControlledCreature turret) + { + Id = FastRandom.NextLong(); + Owner = owner; + Turret = turret; + } + + public virtual bool Equals(Lock other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + + if (ReferenceEquals(this, other)) + { + return true; + } + + return Id == other.Id; + } + } +} diff --git a/src/Perpetuum/Zones/RemoteControl/RemoteControlledCreature.cs b/src/Perpetuum/Zones/RemoteControl/RemoteControlledCreature.cs new file mode 100644 index 000000000..c7f7a980a --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/RemoteControlledCreature.cs @@ -0,0 +1,110 @@ +using Perpetuum.Players; +using Perpetuum.Robots; +using Perpetuum.Services.Standing; +using Perpetuum.Units; +using Perpetuum.Zones.NpcSystem; +using Perpetuum.Zones.NpcSystem.ThreatManaging; +using System; + +namespace Perpetuum.Zones.RemoteControl +{ + public class RemoteControlledCreature : SmartCreature + { + private const double SentryTurretCallForHelpArmorThreshold = 0.8; + private UnitDespawnHelper despawnHelper; + private readonly IStandingHandler standingHandler; + private const double StandingLimit = 0.0; + + public event RemoteChannelEventHandler RemoteChannelDeactivated; + + public Robot CommandRobot { get; private set; } + + public double RemoteChannelBandwidthUsage { get; private set; } + + public TimeSpan DespawnTime + { + set => despawnHelper = UnitDespawnHelper.Create(this, value); + } + + public bool IsInOperationalRange => CurrentPosition.IsInRangeOf2D(CommandRobot.CurrentPosition, HomeRange); + + public override bool IsStationary => true; + + public override double CallForHelpArmorThreshold => SentryTurretCallForHelpArmorThreshold; + + public RemoteControlledCreature(IStandingHandler standingHandler) + { + this.standingHandler = standingHandler; + } + + public void SetCommandRobot(Robot commandRobot) + { + CommandRobot = commandRobot; + } + + public void SetBandwidthUsage(double value) + { + RemoteChannelBandwidthUsage = value; + } + + public override void AddThreat(Unit hostile, Threat threat, bool spreadToGroup) + { + if (hostile.IsPlayer() && CommandRobot == (hostile as Player)) + { + return; + } + + base.AddThreat(hostile, threat, spreadToGroup); + } + + protected override void OnUpdate(TimeSpan time) + { + base.OnUpdate(time); + despawnHelper?.Update(time, this); + } + + protected override void OnBeforeRemovedFromZone(IZone zone) + { + RemoteChannelDeactivated(this); + } + + protected bool IsHostilePlayer(Player targetPlayer) + { + if (!(CommandRobot is Player player)) + { + return true; + } + + if (player == targetPlayer) + { + return false; + } + + if (Zone.Configuration.IsAlpha && !player.HasPvpEffect && !targetPlayer.HasPvpEffect) + { + return false; + } + + if (player == targetPlayer) + { + return false; + } + + if (player.Gang != null && player.Gang.IsMember(targetPlayer.Character)) + { + return false; + } + + double corporationStanding = standingHandler.GetStanding(player.CorporationEid, targetPlayer.CorporationEid); + + if (corporationStanding > StandingLimit) + { + return false; + } + + double personalStanding = standingHandler.GetStanding(Owner, targetPlayer.Character.Eid); + + return personalStanding <= StandingLimit; + } + } +} diff --git a/src/Perpetuum/Zones/RemoteControl/RemoteControlledUnit.cs b/src/Perpetuum/Zones/RemoteControl/RemoteControlledUnit.cs new file mode 100644 index 000000000..0319fc4ad --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/RemoteControlledUnit.cs @@ -0,0 +1,24 @@ +using Perpetuum.ExportedTypes; +using Perpetuum.Items; +using Perpetuum.Items.Ammos; + +namespace Perpetuum.Zones.RemoteControl +{ + public class RemoteControlledUnit : Ammo + { + private ItemProperty remoteChannelBandwidthUsage = ItemProperty.None; + + public override void Initialize() + { + remoteChannelBandwidthUsage = new AmmoProperty(this, AggregateField.remote_control_bandwidth_usage); + AddProperty(remoteChannelBandwidthUsage); + + base.Initialize(); + } + + public double RemoteChannelBandwidthUsage + { + get { return remoteChannelBandwidthUsage.Value; } + } + } +} diff --git a/src/Perpetuum/Zones/RemoteControl/SentryTurret.cs b/src/Perpetuum/Zones/RemoteControl/SentryTurret.cs new file mode 100644 index 000000000..d67e382c8 --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/SentryTurret.cs @@ -0,0 +1,74 @@ +using Perpetuum.EntityFramework; +using Perpetuum.Players; +using Perpetuum.Services.Standing; +using Perpetuum.Units; +using Perpetuum.Zones.NpcSystem; +using System; + +namespace Perpetuum.Zones.RemoteControl +{ + public class SentryTurret : RemoteControlledCreature + { + public SentryTurret(IStandingHandler standingHandler) + : base(standingHandler) + { + } + + public override void AcceptVisitor(IEntityVisitor visitor) + { + if (!TryAcceptVisitor(this, visitor)) + { + base.AcceptVisitor(visitor); + } + } + + protected override bool IsHostileFor(Unit unit) + { + return unit.IsHostile(this); + } + + public override bool IsHostile(Player targetPlayer) + { + return IsHostilePlayer(targetPlayer); + } + + public override void OnAggression(Unit victim) + { + CommandRobot.OnAggression(victim); + } + + internal override bool IsHostile(Npc npc) + { + return true; + } + + internal override bool IsHostile(CombatDrone drone) + { + return !(drone.CommandRobot is Player player) || IsHostilePlayer(player); + } + + internal override bool IsHostile(SentryTurret turret) + { + return !(turret.CommandRobot is Player player) || IsHostilePlayer(player); + } + + protected override void UpdateUnitVisibility(Unit target) + { + if (target is Npc || + target is RemoteControlledCreature) + { + UpdateVisibility(target); + } + } + + protected override void OnUpdate(TimeSpan time) + { + if (!IsInOperationalRange) + { + Kill(); + } + + base.OnUpdate(time); + } + } +} \ No newline at end of file diff --git a/src/Perpetuum/Zones/RemoteControl/TurretType.cs b/src/Perpetuum/Zones/RemoteControl/TurretType.cs new file mode 100644 index 000000000..0e7cfd0a8 --- /dev/null +++ b/src/Perpetuum/Zones/RemoteControl/TurretType.cs @@ -0,0 +1,10 @@ +namespace Perpetuum.Zones.RemoteControl +{ + public enum TurretType + { + Sentry, + Mining, + Harvesting, + CombatDrone, + } +} diff --git a/src/Perpetuum/Zones/Scanning/Modules/GeoScannerModule.cs b/src/Perpetuum/Zones/Scanning/Modules/GeoScannerModule.cs index 97bb4a4a4..f058d9522 100644 --- a/src/Perpetuum/Zones/Scanning/Modules/GeoScannerModule.cs +++ b/src/Perpetuum/Zones/Scanning/Modules/GeoScannerModule.cs @@ -1,6 +1,7 @@ using Perpetuum.ExportedTypes; using Perpetuum.Items; using Perpetuum.Modules; +using Perpetuum.Modules.ModuleProperties; using Perpetuum.Players; using Perpetuum.Zones.Scanning.Results; using Perpetuum.Zones.Scanning.Scanners; diff --git a/src/Perpetuum/Zones/Scanning/Modules/ItemScannerModule.cs b/src/Perpetuum/Zones/Scanning/Modules/ItemScannerModule.cs index b2a22ae62..d21254f7a 100644 --- a/src/Perpetuum/Zones/Scanning/Modules/ItemScannerModule.cs +++ b/src/Perpetuum/Zones/Scanning/Modules/ItemScannerModule.cs @@ -1,11 +1,12 @@ -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using Perpetuum.Items; using Perpetuum.Modules; using Perpetuum.Players; using Perpetuum.Units; using Perpetuum.Zones.Locking.Locks; +using Perpetuum.Zones.RemoteControl; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; namespace Perpetuum.Zones.Scanning.Modules { @@ -13,48 +14,58 @@ public abstract class ItemScannerModule : ActiveModule { protected ItemScannerModule() : base(true) { - + } protected override void HandleOffensivePVPCheck(Player parentPlayer, UnitLock unitLockTarget) { - if (unitLockTarget.Target is Player targetPlayer) + Player targetPlayer = unitLockTarget.Target is Player player + ? player + : unitLockTarget.Target is RemoteControlledCreature remoteControlledCreature && + remoteControlledCreature.CommandRobot is Player ownerPlayer + ? ownerPlayer + : null; + + if (targetPlayer == null) + { + return; + } + + if (targetPlayer.HasPvpEffect || !targetPlayer.Zone.Configuration.Protected) { - if (targetPlayer != null && targetPlayer.HasPvpEffect || !targetPlayer.Zone.Configuration.Protected) - { - return; - } - if (parentPlayer != null) - { - parentPlayer.CheckPvp().ThrowIfError(); - } + return; } + + _ = (parentPlayer?.CheckPvp().ThrowIfError()); } protected override void OnAction() { - var unitLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); - var probability = GetProbability(unitLock.Target); + UnitLock unitLock = GetLock().ThrowIfNotType(ErrorCodes.InvalidLockType); + double probability = GetProbability(unitLock.Target); - var scannedItems = ScanItems(unitLock.Target).Where(i => FastRandom.NextDouble() <= probability).ToArray(); + ItemInfo[] scannedItems = ScanItems(unitLock.Target).Where(i => FastRandom.NextDouble() <= probability).ToArray(); - var packet = BuildScanResultPacket(unitLock.Target, scannedItems, probability); - var player = (Player) ParentRobot; + Packet packet = BuildScanResultPacket(unitLock.Target, scannedItems, probability); + Player player = (Player)ParentRobot; Debug.Assert(player != null, "player != null"); player.Session.SendPacket(packet); - OnTargetScanned(player,unitLock.Target); + OnTargetScanned(player, unitLock.Target); } + protected abstract IEnumerable ScanItems(Unit target); + + protected abstract Packet BuildScanResultPacket(Unit target, ItemInfo[] scannedItems, double probability); + + protected abstract void OnTargetScanned(Player player, Unit target); + private double GetProbability(Unit target) { - var probability = 1.0; - probability = ModifyValueByOptimalRange(target,probability); + double probability = 1.0; + probability = ModifyValueByOptimalRange(target, probability); + return probability; } - - protected abstract IEnumerable ScanItems(Unit target); - protected abstract Packet BuildScanResultPacket(Unit target, ItemInfo[] scannedItems, double probability); - protected abstract void OnTargetScanned(Player player, Unit target); } } \ No newline at end of file diff --git a/src/Perpetuum/Zones/Scanning/Scanners/Scanner.Tile.cs b/src/Perpetuum/Zones/Scanning/Scanners/Scanner.Tile.cs index fa4d6b8aa..25a197a1e 100644 --- a/src/Perpetuum/Zones/Scanning/Scanners/Scanner.Tile.cs +++ b/src/Perpetuum/Zones/Scanning/Scanners/Scanner.Tile.cs @@ -10,8 +10,8 @@ public partial class Scanner : IEntityVisitor public void Visit(TileScannerAmmo ammo) { var area = _zone.CreateArea(_player.CurrentPosition, ammo.ScanRange); - var builder = MineralScanResultBuilder.Create(_player.Zone, ammo.MaterialType); + builder.ScanArea = area; builder.ScanAccuracy = _module.ScanAccuracy; @@ -20,6 +20,7 @@ public void Visit(TileScannerAmmo ammo) _module.LastScanResult = result; var mineralLayer = _zone.Terrain.GetMaterialLayer(ammo.MaterialType) as MineralLayer; + if (mineralLayer != null) { if (result.FoundAny) diff --git a/src/Perpetuum/Zones/Terrains/Materials/Plants/Harvesters/PlantHarvester.cs b/src/Perpetuum/Zones/Terrains/Materials/Plants/Harvesters/PlantHarvester.cs index dc23c68a4..406046b76 100644 --- a/src/Perpetuum/Zones/Terrains/Materials/Plants/Harvesters/PlantHarvester.cs +++ b/src/Perpetuum/Zones/Terrains/Materials/Plants/Harvesters/PlantHarvester.cs @@ -34,18 +34,16 @@ public IEnumerable HarvestPlant(Position position) if (pi.material <= 0) { - //elfogyott a material a novenybol - //megoljuk erobol pi.Clear(); - pi.state = 1; //force kidoles :) - //kill the blocking as well + pi.state = 1; _zone.Terrain.ClearPlantBlocking(position); } - //resulting material var quantity = GetHarvestedAmountPerCycle(plantRule); + result.Add(new ItemInfo(plantRule.FruitDefinition, quantity)); result.AddRange(_rareMaterialHandler.GenerateRareMaterials(plantRule.FruitDefinition)); + return pi; }); diff --git a/src/Perpetuum/Zones/Terrains/TerrainExtensions.cs b/src/Perpetuum/Zones/Terrains/TerrainExtensions.cs index 6e8248b47..77b5293f8 100644 --- a/src/Perpetuum/Zones/Terrains/TerrainExtensions.cs +++ b/src/Perpetuum/Zones/Terrains/TerrainExtensions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Drawing; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -90,6 +92,22 @@ public static int CountPlantsInArea(this IZone zone, PlantType plantType, Area a return counter; } + public static List GetPlantPositionsInArea(this IZone zone, PlantType plantType, Area area) + { + var result = new List(); + + zone.ForEachAreaInclusive(area, (x, y) => + { + var pi = zone.Terrain.Plants.GetValue(x, y); + if (pi.type == plantType) + { + result.Add(new Position(x, y)); + } + }); + + return result; + } + public static void ForEachAll(this IZone zone, Action action) { for (var y = 0; y < zone.Size.Height; y++) @@ -299,6 +317,38 @@ public static MineralLayer GetMineralLayerOrThrow(this ITerrain terrain, Materia return terrain.GetMaterialLayer(type).ThrowIfNotType(ErrorCodes.NoSuchMineralOnZone); } + public static MaterialType GetMaterialTypeAtPosition(this ITerrain terrain, Position position) + { + MaterialType[] materials = Enum.GetValues(typeof(MaterialType)) as MaterialType[]; + + var layer = materials + .Select(x => terrain.GetMaterialLayer(x)) + .Where(x => x is MineralLayer) + .FirstOrDefault(x => (x as MineralLayer).Nodes.Any(y => y.Area.Contains(position))); + + return layer == null + ? MaterialType.Undefined + : (layer as MineralLayer).Type; + } + + public static MaterialType[] GetAvailableMineralTypes(this ITerrain terrain) + { + MaterialType[] materials = Enum.GetValues(typeof(MaterialType)) as MaterialType[]; + + return materials + .Where(x => terrain.GetMaterialLayer(x) != null) + .ToArray(); + } + + public static PlantType[] GetAvailablePlantTypes(this ITerrain terrain) + { + PlantType[] materials = Enum.GetValues(typeof(PlantType)) as PlantType[]; + + return materials + .Where(x => terrain.Plants.RawData.Any(y => y.type == x && y.material > 0)) + .ToArray(); + } + private const int GZIP_THRESHOLD = 260; [CanBeNull] diff --git a/src/Perpetuum/Zones/Zone.cs b/src/Perpetuum/Zones/Zone.cs index 983193fa2..9858f5e82 100644 --- a/src/Perpetuum/Zones/Zone.cs +++ b/src/Perpetuum/Zones/Zone.cs @@ -27,6 +27,7 @@ using Perpetuum.Zones.Decors; using Perpetuum.Zones.Effects.ZoneEffects; using Perpetuum.Zones.Environments; +using Perpetuum.Zones.LandMines; using Perpetuum.Zones.NpcSystem.Presences; using Perpetuum.Zones.NpcSystem.SafeSpawnPoints; using Perpetuum.Zones.PBS; @@ -126,7 +127,7 @@ public override void Stop() SaveUnitsToDb(); SaveUnitsToDb(); SaveUnitsToDb(); - SaveUnitsToDb(); + SaveUnitsToDb(); } private void OnGangMemberJoined(Gang gang, Character character) diff --git a/src/Perpetuum/Zones/ZoneConfiguration.cs b/src/Perpetuum/Zones/ZoneConfiguration.cs index f99d61f95..2a47eec6b 100644 --- a/src/Perpetuum/Zones/ZoneConfiguration.cs +++ b/src/Perpetuum/Zones/ZoneConfiguration.cs @@ -104,7 +104,7 @@ public sealed class ZoneConfiguration public int RaceId { get; set; } public string Note { get; set; } - public string ListenerAddress { get; set; } + public string ListenerAddress { get; set; } = "127.0.0.1"; public int ListenerPort { get; set; } public int? TimeLimitMinutes { get; set; } diff --git a/src/Perpetuum/Zones/ZoneExtensions.Gang.cs b/src/Perpetuum/Zones/ZoneExtensions.Gang.cs index de593ee1a..a1a039815 100644 --- a/src/Perpetuum/Zones/ZoneExtensions.Gang.cs +++ b/src/Perpetuum/Zones/ZoneExtensions.Gang.cs @@ -4,6 +4,7 @@ using Perpetuum.Builders; using Perpetuum.Groups.Gangs; using Perpetuum.Players; +using Perpetuum.Zones.RemoteControl; namespace Perpetuum.Zones { @@ -33,6 +34,19 @@ public static IEnumerable GetGangMembers(this IZone zone, Gang gang) return gang == null ? new Player[0] : zone.Players.Where(player => player.Gang == gang); } + public static IEnumerable GetAlliedTurretsByPlayers(this IZone zone, IEnumerable players) + { + return !players.Any() + ? new RemoteControlledCreature[0] + : zone.Units + .Where(x => x is RemoteControlledCreature) + .Join( + players, + turret => ((RemoteControlledCreature)turret).CommandRobot, + player => player, + (turret, player) => (RemoteControlledCreature)turret); + } + public static void SendPacketToGang(this IZone zone, Gang gang, IBuilder packetBuidler, long exceptMemberEid = 0L) { var packet = packetBuidler.Build(); diff --git a/src/Perpetuum/Zones/ZoneExtensions.Unit.cs b/src/Perpetuum/Zones/ZoneExtensions.Unit.cs index 03698e0e6..76e333868 100644 --- a/src/Perpetuum/Zones/ZoneExtensions.Unit.cs +++ b/src/Perpetuum/Zones/ZoneExtensions.Unit.cs @@ -9,6 +9,7 @@ using Perpetuum.Units; using Perpetuum.Zones.Blobs; using Perpetuum.Zones.Gates; +using Perpetuum.Zones.LandMines; using Perpetuum.Zones.PBS; using Perpetuum.Zones.PBS.DockingBases; using Perpetuum.Zones.ProximityProbes; @@ -43,7 +44,7 @@ public static Dictionary GetBuildingsDictionaryForCharacter(this { var count = 0; var buildingsDict = zone.Units - .NotOf().Types().Type() + .NotOf().Types().Type() .Where(u => { if (u is PBSDockingBase pbsDockingBase) @@ -79,7 +80,7 @@ public static IEnumerable GetTeleportColumns(this IZone zone) public static IEnumerable GetStaticUnits(this IZone zone) { - return zone.Units.NotOf().Types(); + return zone.Units.NotOf().Types(); } [NotNull] diff --git a/src/Perpetuum/Zones/ZoneExtensions.cs b/src/Perpetuum/Zones/ZoneExtensions.cs index 0deb7077e..55a8e0067 100644 --- a/src/Perpetuum/Zones/ZoneExtensions.cs +++ b/src/Perpetuum/Zones/ZoneExtensions.cs @@ -1,10 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Security.Cryptography; -using System.Threading; -using System.Threading.Tasks; using Perpetuum.Builders; using Perpetuum.Groups.Corporations; using Perpetuum.IO; @@ -12,6 +5,13 @@ using Perpetuum.Modules.Weapons; using Perpetuum.Units; using Perpetuum.Zones.Terrains; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Security.Cryptography; +using System.Threading; +using System.Threading.Tasks; namespace Perpetuum.Zones { @@ -23,9 +23,9 @@ public interface ILayerFileIO public static class LayerFileIOExtensions { - public static T[] Load(this ILayerFileIO dataIO,IZone zone,LayerType layerType) where T : struct + public static T[] Load(this ILayerFileIO dataIO, IZone zone, LayerType layerType) where T : struct { - return dataIO.LoadLayerData(zone,layerType.ToString()); + return dataIO.LoadLayerData(zone, layerType.ToString()); } } @@ -38,28 +38,30 @@ public LayerFileIO(IFileSystem fileSystem) _fileSystem = fileSystem; } - public T[] LoadLayerData(IZone zone,string name) where T : struct + public T[] LoadLayerData(IZone zone, string name) where T : struct { - var path = zone.CreateTerrainDataFilename(name); - var data = _fileSystem.ReadLayer(path); + string path = zone.CreateTerrainDataFilename(name); + T[] data = _fileSystem.ReadLayer(path); Logger.Info("Layer data loaded. (" + name + ") zone:" + zone.Id); return data; } public void SaveLayerToDisk(IZone zone, ILayer layer) where T : struct { - var baseFilename = zone.CreateTerrainDataFilename(layer.LayerType.ToString().ToLower(),""); + string baseFilename = zone.CreateTerrainDataFilename(layer.LayerType.ToString().ToLower(), ""); - using (var md5 = MD5.Create()) + using (MD5 md5 = MD5.Create()) { - var tmpFn = baseFilename + "tmp" + DateTime.Now.Ticks + ".bin"; - var layerData = layer.RawData.ToByteArray(); - _fileSystem.WriteLayer(tmpFn,layerData); + string tmpFn = baseFilename + "tmp" + DateTime.Now.Ticks + ".bin"; + byte[] layerData = layer.RawData.ToByteArray(); + _fileSystem.WriteLayer(tmpFn, layerData); if (!md5.ComputeHash(layerData).SequenceEqual(md5.ComputeHash(_fileSystem.ReadLayerAsByteArray(tmpFn)))) + { return; + } - _fileSystem.MoveLayerFile(tmpFn,baseFilename + "bin"); + _fileSystem.MoveLayerFile(tmpFn, baseFilename + "bin"); Logger.Info("Layer saved. (" + baseFilename + ")"); } } @@ -67,7 +69,7 @@ public void SaveLayerToDisk(IZone zone, ILayer layer) where T : struct public static partial class ZoneExtensions { - public static List FindWalkableArea(this IZone zone, Area area, int size,double slope = 4.0) + public static List FindWalkableArea(this IZone zone, Area area, int size, double slope = 4.0) { area = area.Clamp(zone.Size); while (true) @@ -77,28 +79,31 @@ public static List FindWalkableArea(this IZone zone, Area area, int size, { startPosition = area.GetRandomPosition(); - if (!zone.Terrain.Blocks.GetValue(startPosition).Island && zone.IsWalkable(startPosition,slope)) + if (!zone.Terrain.Blocks.GetValue(startPosition).Island && zone.IsWalkable(startPosition, slope)) + { break; + } } - var p = FindWalkableArea(zone, startPosition, area, size,slope); + List p = FindWalkableArea(zone, startPosition, area, size, slope); if (p != null) + { return p; + } Thread.Sleep(1); } } [CanBeNull] - public static List FindWalkableArea(this IZone zone,Point startPosition, Area area, int size,double slope = 4.0) + public static List FindWalkableArea(this IZone zone, Point startPosition, Area area, int size, double slope = 4.0) { - var q = new Queue(); + Queue q = new Queue(); q.Enqueue(startPosition); - var closed = new HashSet {startPosition}; + HashSet closed = new HashSet { startPosition }; - var result = new List(); - Point position; - while (q.TryDequeue(out position)) + List result = new List(); + while (q.TryDequeue(out Point position)) { result.Add(position); @@ -108,15 +113,19 @@ public static List FindWalkableArea(this IZone zone,Point startPosition, return result; } - foreach (var np in position.GetNonDiagonalNeighbours()) + foreach (Point np in position.GetNonDiagonalNeighbours()) { if (closed.Contains(np)) + { continue; + } - closed.Add(np); + _ = closed.Add(np); - if (!area.Contains(np) || !zone.IsWalkable(np,slope)) + if (!area.Contains(np) || !zone.IsWalkable(np, slope)) + { continue; + } q.Enqueue(np); } @@ -136,18 +145,18 @@ public static List FindWalkableArea(this IZone zone,Point startPosition, /// True if tiles checked are walkable public static bool CheckLinearPath(this IZone zone, Point start, Point end, double slope = 4.0) { - var x = start.X; - var y = start.Y; - var deltaX = Math.Abs(end.X - x); - var deltaY = Math.Abs(end.Y - y); - var travelDist = deltaX + deltaY; - var xIncrement = (end.X > x) ? 1 : -1; - var yIncrement = (end.Y > y) ? 1 : -1; - var error = deltaX - deltaY; + int x = start.X; + int y = start.Y; + int deltaX = Math.Abs(end.X - x); + int deltaY = Math.Abs(end.Y - y); + int travelDist = deltaX + deltaY; + int xIncrement = (end.X > x) ? 1 : -1; + int yIncrement = (end.Y > y) ? 1 : -1; + int error = deltaX - deltaY; deltaX *= 2; deltaY *= 2; - - for (var i = 0; i <= travelDist; i++) + + for (int i = 0; i <= travelDist; i++) { if (!zone.IsWalkable(x, y, slope)) { @@ -170,19 +179,19 @@ public static bool CheckLinearPath(this IZone zone, Point start, Point end, doub public static bool IsTerrainConditionsMatchInRange(this IZone zone, Position centerPosition, int range, double slope) { - var totalTiles = range * range * 4; + int totalTiles = range * range * 4; - var illegalsFound = 0; + int illegalsFound = 0; - for (var j = centerPosition.intY - range; j < centerPosition.intY + range; j++) + for (int j = centerPosition.intY - range; j < centerPosition.intY + range; j++) { - for (var i = centerPosition.intX - range; i < centerPosition.intX + range; i++) + for (int i = centerPosition.intX - range; i < centerPosition.intX + range; i++) { - var cPos = new Position(i, j); + Position cPos = new Position(i, j); if (centerPosition.IsInRangeOf2D(cPos, range)) { - var blockInfo = zone.Terrain.Blocks.GetValue(i, j); + BlockingInfo blockInfo = zone.Terrain.Blocks.GetValue(i, j); if (blockInfo.Height > 0 || blockInfo.NonNaturally || blockInfo.Plant || !zone.Terrain.Slope.CheckSlope(cPos.intX, cPos.intY, slope)) { @@ -192,34 +201,38 @@ public static bool IsTerrainConditionsMatchInRange(this IZone zone, Position cen } } - var troubleFactor = illegalsFound / (double)totalTiles; + double troubleFactor = illegalsFound / (double)totalTiles; Logger.Info("trouble factor: " + troubleFactor); if (troubleFactor > 0.5) { - Logger.Warning("illegal tiles coverage: " + troubleFactor * 100 + "%"); + Logger.Warning("illegal tiles coverage: " + (troubleFactor * 100) + "%"); return false; } return true; } - public static void DoAoeDamageAsync(this IZone zone,IBuilder damageBuilder) + public static void DoAoeDamageAsync(this IZone zone, IBuilder damageBuilder) { - Task.Run(() => DoAoeDamage(zone, damageBuilder)); + _ = Task.Run(() => DoAoeDamage(zone, damageBuilder)); } - public static void DoAoeDamage(this IZone zone,IBuilder damageBuilder) + public static void DoAoeDamage(this IZone zone, IBuilder damageBuilder) { - var damageInfo = damageBuilder.Build(); - var units = zone.Units.WithinRange(damageInfo.sourcePosition, damageInfo.Range); + DamageInfo damageInfo = damageBuilder.Build(); + IEnumerable units = zone.Units + .WithinRange(damageInfo.sourcePosition, damageInfo.Range) + .Where(x => !x.HasTeleportSicknessEffect || x.HasPvpEffect); - foreach (var unit in units) + foreach (Unit unit in units) { - var losResult = zone.IsInLineOfSight(damageInfo.attacker, unit, false); + LOSResult losResult = zone.IsInLineOfSight(damageInfo.attacker, unit, false); if (losResult.hit) + { continue; + } unit.TakeDamage(damageInfo); } @@ -244,16 +257,20 @@ public static string CreateTerrainDataFilename(int zoneId, string name, string e public static Position FindPassablePointInRadius(this IZone zone, Position origin, int radius) { - var counter = 0; + int counter = 0; while (true) { counter++; if (counter > MAX_SAMPLES) - return default(Position); + { + return default; + } - var randomPos = origin.GetRandomPositionInRange2D(0, radius).Clamp(zone.Size); + Position randomPos = origin.GetRandomPositionInRange2D(0, radius).Clamp(zone.Size); if (zone.Terrain.IsPassable(randomPos)) + { return randomPos; + } } } @@ -262,16 +279,16 @@ public static bool IsValidPosition(this IZone zone, int x, int y) return x >= 0 && x < zone.Size.Width && y >= 0 && y < zone.Size.Height; } - public static void UpdateCorporation(this IZone zone,CorporationCommand command,Dictionary data) + public static void UpdateCorporation(this IZone zone, CorporationCommand command, Dictionary data) { - zone.CorporationHandler.HandleCorporationCommand(command,data); + zone.CorporationHandler.HandleCorporationCommand(command, data); } - public static Position ToWorldPosition(this IZone zone,Position position) + public static Position ToWorldPosition(this IZone zone, Position position) { - var zx = zone.Configuration.WorldPosition.X; - var zy = zone.Configuration.WorldPosition.Y; - return position.GetWorldPosition(zx,zy); + int zx = zone.Configuration.WorldPosition.X; + int zy = zone.Configuration.WorldPosition.Y; + return position.GetWorldPosition(zx, zy); } } } \ No newline at end of file