private async Task SetupEntries() { var componentId = GameObject.Lot.GetComponentId(ComponentId.VendorComponent); var vendorComponent = await ClientCache.FindAsync <Core.Client.VendorComponent>(componentId); var matrices = ClientCache.FindAll <Core.Client.LootMatrix>(vendorComponent.LootMatrixIndex); var shopItems = new List <ShopEntry>(); foreach (var matrix in matrices) { shopItems.AddRange(ClientCache.FindAll <LootTable>(matrix.LootTableIndex) .ToArray().Select(lootTable => { Debug.Assert(lootTable.Itemid != null, "lootTable.Itemid != null"); Debug.Assert(lootTable.SortPriority != null, "lootTable.SortPriority != null"); return(new ShopEntry { Lot = new Lot(lootTable.Itemid.Value), SortPriority = lootTable.SortPriority.Value }); })); } Entries = shopItems.ToArray(); }
/// <summary> /// Creates the scripted activity component. /// </summary> protected ScriptedActivityComponent() { _random = new Random(); Listen(OnStart, async() => { if (!GameObject.Settings.TryGetValue("activityID", out var id)) { return; } // Get the activity info. var activityId = (int)id; ActivityInfo = await ClientCache.FindAsync <Activities>(activityId); if (ActivityInfo == default) { Logger.Error($"{GameObject} has an invalid activityID: {activityId}"); return; } // Get and sort the activities. Rewards = ClientCache.FindAll <ActivityRewards>(activityId).ToSortedList((a, b) => { if (a.ChallengeRating != b.ChallengeRating) { return((a.ChallengeRating ?? 1) - (b.ChallengeRating ?? 1)); } return((a.ActivityRating ?? -1) - (b.ActivityRating ?? -1)); }).ToArray(); });
/// <summary> /// Loads the inventory for the game object, only for non-player GameObjects does this automatically equip the /// items as the component cannot know when the inventory manager component will be available to load the /// items from. /// </summary> private async Task LoadAsync() { if (!(GameObject is Player)) { var component = ClientCache.FindAll <ComponentsRegistry>(GameObject.Lot).FirstOrDefault(c => c.Componenttype == (int)ComponentId.InventoryComponent); var itemTemplates = ClientCache.FindAll <Core.Client.InventoryComponent>(component.Componentid) .Where(i => i.Itemid != default).ToArray(); foreach (var itemTemplate in itemTemplates) { if (itemTemplate.Itemid == default) { continue; } var lot = (Lot)itemTemplate.Itemid; var componentId = lot.GetComponentId(ComponentId.ItemComponent); var itemComponent = await ClientCache.FindAsync <ItemComponent>(componentId); if (itemComponent.ItemType == default) { continue; } var item = await Item.Instantiate(GameObject, lot, default, (uint)(itemTemplate.Count ?? 1));
/// <summary> /// Instantiates an item using static information. /// </summary> /// <param name="owner">The owner of this item</param> /// <param name="lot">The lot of this item</param> /// <param name="inventory">The inventory to add the item to, if left empty, this item will be left unmanaged</param> /// <param name="count">The count of the item to add</param> /// <param name="slot">The slot to add the item to</param> /// <param name="extraInfo">Optional LDD to set on the item</param> /// <param name="objectId">Explicit object Id for this item, generally only used for player instance items</param> /// <param name="rootItem">The root item this item is based on</param> /// <param name="isEquipped">Whether the game object has this item equipped or not</param> /// <param name="isBound">Whether the game object has bound this item or not</param> /// <param name="lootType">Where this item came from</param> /// <remarks>Note that <c>Start</c> still needs to be called on the item to be registered properly in the world.</remarks> /// <returns>The instantiated item or <c>null</c> if no slot could be acquired or if the item couldn't be added to the inventory</returns> public static async Task <Item> Instantiate(GameObject owner, Lot lot, Inventory inventory, uint count, uint slot = default, LegoDataDictionary extraInfo = default, ObjectId objectId = default, Item rootItem = default, bool isEquipped = false, bool isBound = false, LootType lootType = LootType.None) { // Try to find the slot at which this item should be inserted if no explicit slot is provided if (inventory != default && slot == default) { try { slot = inventory.ClaimSlot(); } catch (InventoryFullException) { return(null); } } var itemTemplate = (await ClientCache.FindAsync <Core.Client.Objects>(lot)); var itemRegistryEntry = (await ClientCache.FindAllAsync <ComponentsRegistry>(lot)).FirstOrDefault( r => r.Componenttype == (int)ComponentId.ItemComponent ); if (itemRegistryEntry == default) { return(default);
public async Task PlayEmoteHandler(PlayEmoteMessage message, Player player) { var animation = await ClientCache.FindAsync <Emotes>(message.EmoteId); player.Zone.BroadcastMessage(new PlayAnimationMessage { Associate = player, AnimationId = animation.AnimationName, Priority = 0.4f, Scale = 1, }); player.Zone.ExcludingMessage(new EmotePlayedMessage { Associate = player, EmoteId = message.EmoteId, Target = message.Target }, player); if (player.TryGetComponent <MissionInventoryComponent>(out var missionInventoryComponent)) { await missionInventoryComponent.UseEmoteAsync(message.Target, message.EmoteId); } if (message.Target?.OnEmoteReceived != default) { await message.Target.OnEmoteReceived.InvokeAsync(message.EmoteId, player); } }
protected RailActivatorComponent() { Listen(OnStart, async() => { RailActivatorComponentId = GameObject.Lot.GetComponentId(ComponentId.RailActivator); var railComponent = await ClientCache.FindAsync <Core.Client.RailActivatorComponent>(RailActivatorComponentId); ActivatorDamageImmune = (bool)GameObject.Settings["rail_activator_damage_immune"]; LoopSound = (string)GameObject.Settings["rail_loop_sound"]; NoAggro = (bool)GameObject.Settings["rail_no_aggro"]; NotifyActivatorArrived = (bool)GameObject.Settings["rail_notify_activator_arrived"]; Path = (string)GameObject.Settings["rail_path"]; // TODO: investigate why PathDirection 0 makes the movement a straight line instead of the reverse path PathDirection = (bool)GameObject.Settings["rail_path_direction"]; PathStart = (uint)GameObject.Settings["rail_path_start"]; ShowNameBillboard = (bool)GameObject.Settings["rail_show_name_billboard"]; UseDb = (bool)GameObject.Settings["rail_use_db"]; StartAnim = railComponent.StartAnim; LoopAnim = railComponent.LoopAnim; StopAnim = railComponent.StopAnim; StartSound = railComponent.StartSound; StopSound = railComponent.StopSound; // these 3 fields can be null var startEffect = railComponent.StartEffectID; if (startEffect != null) { var split = startEffect.Split(':'); StartEffectId = int.Parse(split[0]); StartEffectType = split[1]; } var duringEffect = railComponent.EffectIDs; if (duringEffect != null) { var split = duringEffect.Split(':'); DuringEffectId = int.Parse(split[0]); DuringEffectType = split[1]; } var stopEffect = railComponent.StopEffectID; if (stopEffect != null) { var split = stopEffect.Split(':'); StopEffectId = int.Parse(split[0]); StopEffectType = split[1]; } CameraLocked = railComponent.CameraLocked ?? true; CollisionEnabled = railComponent.PlayerCollision ?? false; Listen(GameObject.OnInteract, OnInteract); }); }
public async Task Buy(Lot lot, uint count, Player player) { var componentId = lot.GetComponentId(ComponentId.ItemComponent); var itemComponent = await ClientCache.FindAsync <ItemComponent>(componentId); if (count == default || itemComponent.BaseValue <= 0) { return; } var character = player.GetComponent <CharacterComponent>(); var cost = (uint)((itemComponent.BaseValue ?? 0) * count); if (cost > character.Currency) { return; } // If we have to buy this with an alternative currency if (itemComponent.CurrencyLOT != null) { var alternativeCurrencyLot = (Lot)itemComponent.CurrencyLOT; var alternativeCurrencyCost = itemComponent.AltCurrencyCost ?? 0; var inventory = player.GetComponent <InventoryManagerComponent>(); if (alternativeCurrencyCost > inventory.FindItems(alternativeCurrencyLot) .Select(i => (int)i.Count).Sum()) { return; } await inventory.RemoveLotAsync(alternativeCurrencyLot, (uint)alternativeCurrencyCost); } character.Currency -= cost; await player.GetComponent <InventoryManagerComponent>().AddLotAsync(lot, count, lootType: LootType.Vendor); player.Message(new VendorTransactionResultMessage { Associate = GameObject, Result = TransactionResult.Success }); await OnBuy.InvokeAsync(lot, count, player); }
protected DestructibleComponent() { OnSmashed = new Event <GameObject, Player>(); OnResurrect = new Event(); Listen(OnStart, async() => { if (GameObject.Settings.TryGetValue("respawn", out var resTimer)) { ResurrectTime = resTimer switch { uint timer => timer, float timer => timer, int timer => timer, _ => ResurrectTime }; } var container = GameObject.AddComponent <LootContainerComponent>(); await container.CollectDetailsAsync(); GameObject.Layer = StandardLayer.Smashable; var entry = GameObject.Lot.GetComponentId(ComponentId.DestructibleComponent); var cdClientComponent = (await ClientCache.FindAsync <Core.Client.DestructibleComponent>(entry)); if (cdClientComponent == default) { Logger.Error($"{GameObject} has a corrupt Destructible Component of id: {entry}"); } if (GameObject.TryGetComponent(out DestroyableComponent stats)) { Stats = stats; Listen(Stats.OnDeath, async() => { await SmashAsync( Stats.LatestDamageSource, Stats.LatestDamageSource is Player player ? player : default,
public async void StartCombatAI() { SkillComponent = GameObject.GetComponent <SkillComponent>(); DestructibleComponent = GameObject.GetComponent <DestructibleComponent>(); QuickBuildComponent = GameObject.GetComponent <QuickBuildComponent>(); Stats = GameObject.GetComponent <DestroyableComponent>(); foreach (var skillEntry in SkillComponent.DefaultSkillSet) { var skillInfo = await ClientCache.FindAsync <SkillBehavior>(skillEntry.SkillId); SkillEntries.Add(new NpcSkillEntry { SkillId = skillEntry.SkillId, Cooldown = 0, AbilityCooldown = (skillInfo.Cooldown ?? 1) * 1000, Tree = await BehaviorTree.FromSkillAsync((int)skillEntry.SkillId) }); } Zone.Update(GameObject, delta => CalculateCombat(delta), 1); }
public override Task LoadAsync() { Listen(Zone.OnPlayerLoad, player => { Listen(player.OnFireServerEvent, async(eventName, message) => { if (eventName == "ZonePlayer") { var launchpad = message.Associate.GetComponent <RocketLaunchpadComponent>(); var id = launchpad.GameObject.Lot.GetComponentId(ComponentId.RocketLaunchComponent); var launchpadComponent = await ClientCache.FindAsync <RocketLaunchpadControlComponent>(id); // TargetZone is 0 for the LUP launchpad, ignore it if (launchpadComponent.TargetZone != null && launchpadComponent.TargetZone != 0) { var target = (ZoneId)launchpadComponent.TargetZone; // We don't want to lock up the server on a world server request, as it may take time. var _ = Task.Run(async() => { player.GetComponent <CharacterComponent>().LaunchedRocketFrom = Zone.ZoneId; var success = await player.SendToWorldAsync(target); if (!success) { player.SendChatMessage($"Failed to transfer to {target}, please try later."); } }); } } }); return(Task.CompletedTask); }); return(Task.CompletedTask); }
/// <summary> /// Loads generic CdClient information about the mission. /// </summary> private async Task LoadTemplateAsync() { var mission = await ClientCache.FindAsync <Core.Client.Missions>(MissionId); PrerequisiteMissions = mission.PrereqMissionID; IsMission = mission.IsMission ?? true; IsChoiceReward = (mission.IsChoiceReward ?? false) && IsMission; DefinedType = mission.Definedtype; DefinedSubType = mission.Definedsubtype; // Possible stat rewards RewardMaxHealth = mission.Rewardmaxhealth ?? 0; RewardMaxImagination = mission.Rewardmaximagination ?? 0; RewardMaxInventory = mission.Rewardmaxinventory ?? 0; RewardCurrency = mission.Rewardcurrency ?? 0; RewardCurrencyRepeatable = mission.Rewardcurrencyrepeatable ?? 0; RewardScore = mission.LegoScore ?? 0; Repeatable = mission.Repeatable ?? false; CooldownTime = mission.CooldownTime ?? 0; // Emotes RewardEmote1 = mission.Rewardemote ?? -1; RewardEmote2 = mission.Rewardemote2 ?? -1; RewardEmote3 = mission.Rewardemote3 ?? -1; RewardEmote4 = mission.Rewardemote4 ?? -1; // First optional reward item RewardItem1 = mission.Rewarditem1 ?? 0; RewardItem1Count = mission.Rewarditem1count ?? 1; RewardItem1Repeatable = mission.Rewarditem1repeatable ?? 0; RewardItem1RepeatableCount = mission.Rewarditem1repeatcount ?? 1; // Second optional reward item RewardItem2 = mission.Rewarditem2 ?? 0; RewardItem2Count = mission.Rewarditem2count ?? 1; RewardItem2Repeatable = mission.Rewarditem2repeatable ?? 0; RewardItem2RepeatableCount = mission.Rewarditem2repeatcount ?? 1; // Third optional reward item RewardItem3 = mission.Rewarditem3 ?? 0; RewardItem3Count = mission.Rewarditem3count ?? 1; RewardItem3Repeatable = mission.Rewarditem3repeatable ?? 0; RewardItem3RepeatableCount = mission.Rewarditem3repeatcount ?? 1; // Fourth optional reward item RewardItem4 = mission.Rewarditem4 ?? 0; RewardItem4Count = mission.Rewarditem4count ?? 1; RewardItem4Repeatable = mission.Rewarditem4repeatable ?? 0; RewardItem4RepeatableCount = mission.Rewarditem4repeatcount ?? 1; // Optional increment for vault inventory size RewardBankInventory = mission.Rewardbankinventory ?? 0; // Load all the tasks for this mission var tasks = await ClientCache.MissionTasksWithMissionIdCacheTable.FindAllAsync <MissionTasks>(MissionId); Tasks = new List <MissionTaskInstance>(); var index = 0; foreach (var task in tasks) { var taskType = (MissionTaskType)(task.TaskType ?? 0); if (!TaskTypes.TryGetValue(taskType, out var type)) { Logger.Debug($"No {nameof(MissionTaskInstance)} for {taskType} found."); continue; } if (task.Uid != null) { var instance = (MissionTaskInstance)Activator.CreateInstance(type, this, task.Uid.Value, index); if (instance == default || task.Uid == default) { Logger.Error($"Invalid task: {type} [{task.Uid}]"); continue; } instance.LoadTemplate(task); Tasks.Add(instance); } index++; } }