public bool ServerGather(IStaticWorldObject worldObject, ICharacter character) { var lootDroplist = GetPublicState(worldObject).ProtoCharacterMob .LootDroplist; var dropItemContext = new DropItemContext(character, worldObject); CreateItemResult dropItemResult; var attemptRemains = 200; do { dropItemResult = lootDroplist.TryDropToCharacterOrGround(character, character.TilePosition, dropItemContext, out _); } // ensure that at least something is spawned... // perhaps that's not a good idea, but we have an attempts limit while (dropItemResult.TotalCreatedCount == 0 && --attemptRemains > 0); // probably the attempts limit exceeded and nothing is spawned // we don't consider this as an issue as the probability of this is too rare Logger.Info(this + " was gathered", character); NotificationSystem.ServerSendItemsNotification(character, dropItemResult); character.ServerAddSkillExperience <SkillHunting>(SkillHunting.ExperienceForGather); Server.World.DestroyObject(worldObject); return(true); }
public bool ServerOnHackingStage(IStaticWorldObject worldObject, ICharacter character) { var publicState = GetPublicState(worldObject); publicState.HackingProgressPercent += 100 / this.HackingStagesNumber; if (publicState.HackingProgressPercent < 100) { return(true); } Server.World.DestroyObject(worldObject); var lootDroplist = this.LootDroplist; var dropItemContext = new DropItemContext(character, worldObject); var dropItemResult = lootDroplist.TryDropToCharacterOrGround( character, character.TilePosition, dropItemContext, out _, probabilityMultiplier: this.ServerGetDropListProbabilityMultiplier(worldObject)); if (dropItemResult.TotalCreatedCount > 0) { NotificationSystem.ServerSendItemsNotification(character, dropItemResult); var skillExperienceToAdd = SkillSearching.ExperienceAddWhenSearching * SearchSkillExperienceMultiplier; character.ServerAddSkillExperience <SkillSearching>(skillExperienceToAdd); } ServerObjectUseObserver.NotifyObjectUsed(character, worldObject); this.ServerOnHacked(character, worldObject); return(true); }
private void ServerOnMineralStageMined( WeaponFinalCache weaponCache, IStaticWorldObject mineralObject, int damageStage) { var byCharacter = weaponCache.Character; var byWeaponProto = weaponCache.ProtoWeapon; Logger.Info( $"{mineralObject} current damage stage changed to {damageStage}. Dropping items for that stage", byCharacter); try { var dropItemsList = this.DropItemsConfig.GetForStage(damageStage); var dropItemContext = new DropItemContext(byCharacter, mineralObject, byWeaponProto, weaponCache.ProtoExplosive); var objectDrone = weaponCache.Drone; if (objectDrone != null) { // drop resources into the internal storage of the drone var storageItemsContainer = ((IProtoDrone)objectDrone.ProtoGameObject) .ServerGetStorageItemsContainer(objectDrone); dropItemsList.TryDropToContainer(storageItemsContainer, dropItemContext); } else if (byWeaponProto is IProtoItemWeaponMelee) { var result = dropItemsList.TryDropToCharacterOrGround(byCharacter, mineralObject.TilePosition, dropItemContext, groundContainer: out _); if (result.TotalCreatedCount > 0) { NotificationSystem.ServerSendItemsNotification(byCharacter, result); } } else { // not a melee weapon or cannot drop to the character inventory - drop on the ground only dropItemsList.TryDropToGround(mineralObject.TilePosition, dropItemContext, out _); } } finally { if (byWeaponProto is IProtoItemToolMining || weaponCache.ProtoExplosive is ObjectBombMining) { // add experience proportional to the mineral structure points (effectively - for the time spent on mining) var exp = SkillProspecting.ExperienceAddPerStructurePoint; exp *= this.StructurePointsMax / this.DamageStagesCount; byCharacter?.ServerAddSkillExperience <SkillProspecting>(exp); } } }
public static bool ServerRollExtraLoot(DropItemContext context) { if (!context.HasCharacter) { return(false); } var character = context.Character; var extraLootProbability = character.SharedGetFinalStatMultiplier(StatName.SearchingExtraLoot) - 1.0; return(RandomHelper.RollWithProbability(extraLootProbability)); }
protected override void ServerOnStaticObjectDestroyedByCharacter( ICharacter byCharacter, IProtoItemWeapon byWeaponProto, IStaticWorldObject targetObject) { base.ServerOnStaticObjectDestroyedByCharacter(byCharacter, byWeaponProto, targetObject); // drop chance and gained experience depends on the vegetation growth stage var growthProgressFraction = this.GrowthStagesCount > 0 ? GetPublicState(targetObject).GrowthStage / (double)this.GrowthStagesCount : 1; growthProgressFraction = MathHelper.Clamp(growthProgressFraction, 0.1, 1); try { var dropItemContext = new DropItemContext(byCharacter, targetObject); if (byWeaponProto is IProtoItemWeaponMelee) { // a melee weapon - try drop items to character var result = this.DroplistOnDestroy.TryDropToCharacter( byCharacter, dropItemContext, probabilityMultiplier: growthProgressFraction); if (result.IsEverythingCreated) { NotificationSystem.ServerSendItemsNotification(byCharacter, result); return; } result.Rollback(); } // not a melee weapon or cannot drop to character - drop on the ground only this.DroplistOnDestroy.TryDropToGround( targetObject.TilePosition, dropItemContext, probabilityMultiplier: growthProgressFraction, groundContainer: out _); } finally { if (byWeaponProto is IProtoItemToolWoodcutting) { // add experience proportional to the tree structure points (effectively - for the time spent on woodcutting) var exp = SkillWoodcutting.ExperienceAddPerStructurePoint; exp *= this.StructurePointsMax * growthProgressFraction; byCharacter?.ServerAddSkillExperience <SkillWoodcutting>(exp); } } }
public bool ServerGather(IStaticWorldObject worldObject, ICharacter character) { //MOD PublicState publicState = GetPublicState(worldObject); var lootDroplist = publicState.ProtoCharacterMob.LootDroplist; var dropItemContext = new DropItemContext(character, worldObject); CreateItemResult dropItemResultFinal = new CreateItemResult(); var level = publicState.Level; for (int i = 0; i < level; i++) { CreateItemResult dropItemResult; var attemptRemains = 200; do { dropItemResult = lootDroplist.TryDropToCharacterOrGround(character, character.TilePosition, dropItemContext, out _); dropItemResultFinal.MergeWith(dropItemResult); } // ensure that at least something is spawned... // perhaps that's not a good idea, but we have an attempts limit while (dropItemResult.TotalCreatedCount == 0 && --attemptRemains > 0); } if (!dropItemResultFinal.IsEverythingCreated) { Logger.Warning("Not all loot items were provided by " + worldObject + " - there is not enough space in inventory and around the character"); } // probably the attempts limit exceeded and nothing is spawned // we don't consider this as an issue as the probability of this is too rare Logger.Info(worldObject + " was gathered", character); Server.World.DestroyObject(worldObject); NotificationSystem.ServerSendItemsNotification(character, dropItemResultFinal); character.ServerAddSkillExperience <SkillHunting>(SkillHunting.ExperienceForGather * level); return(true); }
public static bool OnlyBeforeT4SpecializedOrPvE(DropItemContext context) { if (PveSystem.ServerIsPvE) { return(true); } if (Api.IsEditor) { return(true); } var timeRemains = TechConstants.PvpTechTimeGameTier4Specialized - Api.Server.Game.SecondsSinceWorldCreation; return(timeRemains > 0); }
private void ServerOnDamageStageIncreased( [CanBeNull] ICharacter byCharacter, IProtoItemWeapon byWeaponProto, IStaticWorldObject mineralObject, int damageStage) { Logger.Info( $"{mineralObject} current damage stage changed to {damageStage}. Dropping items for that stage", byCharacter); try { var dropItemsList = this.DropItemsConfig.GetForStage(damageStage); var dropItemContext = new DropItemContext(byCharacter, mineralObject, byWeaponProto); if (byWeaponProto is IProtoItemWeaponMelee) { var result = dropItemsList.TryDropToCharacter(byCharacter, dropItemContext); if (result.IsEverythingCreated) { NotificationSystem.ServerSendItemsNotification( byCharacter, result); return; } result.Rollback(); } // not a melee weapon or cannot drop to the character inventory - drop on the ground only dropItemsList.TryDropToGround(mineralObject.TilePosition, dropItemContext, out _); } finally { if (byWeaponProto is IProtoItemToolMining) { // add experience proportional to the mineral structure points (effectively - for the time spent on mining) var exp = SkillMining.ExperienceAddPerStructurePoint; exp *= this.StructurePointsMax / DamageStagesCount; byCharacter?.ServerAddSkillExperience <SkillMining>(exp); } } }
public static bool ConditionHasDeviceEquipped(DropItemContext context) { // Please note: checking this condition will also automatically deduct the device's durability. if (!context.HasCharacter) { return(false); } // find the device var itemDevice = context.Character.SharedGetPlayerContainerEquipment() .GetItemsOfProto(protoItemKeiniteCollector) .FirstOrDefault(); if (itemDevice is null) { // don't have an equipped device return(false); } ItemDurabilitySystem.ServerModifyDurability(itemDevice, -DurabilityDecreasePerUse); return(true); }
static bool T5SpecializedPvPOnly(DropItemContext context) => !PveSystem.ServerIsPvE && ServerTechTimeGateHelper.IsAvailableT5Specialized(context);
public static bool IsAvailableT3Basic(DropItemContext context) { return(IsTimeGateFinished(TechConstants.PvpTechTimeGameTier3Basic)); }
public static bool IsAvailableT5Specialized(DropItemContext context) { return(IsTimeGateFinished(TechConstants.PvpTechTimeGameTier5Specialized)); }
public static bool IsAvailableT3Basic(DropItemContext context) { return(IsTimeGateFinished(TechTier.Tier3, isSpecialized: false)); }
protected override void ServerOnStaticObjectDestroyedByCharacter( ICharacter byCharacter, WeaponFinalCache weaponCache, IStaticWorldObject targetObject) { base.ServerOnStaticObjectDestroyedByCharacter(byCharacter, weaponCache, targetObject); // drop chance and gained experience depends on the vegetation growth stage var growthProgressFraction = this.SharedGetGrowthProgress(targetObject); growthProgressFraction = MathHelper.Clamp(growthProgressFraction, 0.1, 1); try { var dropItemsList = this.DroplistOnDestroy; var dropItemContext = new DropItemContext(byCharacter, targetObject, weaponCache.ProtoWeapon, weaponCache.ProtoExplosive); var objectDrone = weaponCache.Drone; if (objectDrone is not null) { // drop resources into the internal storage of the drone var storageItemsContainer = ((IProtoDrone)objectDrone.ProtoGameObject) .ServerGetStorageItemsContainer(objectDrone); dropItemsList.TryDropToContainer(storageItemsContainer, dropItemContext, probabilityMultiplier: growthProgressFraction); } else if (weaponCache.ProtoWeapon is IProtoItemWeaponMelee) { // a melee weapon - try drop items to character var result = dropItemsList.TryDropToCharacterOrGround( byCharacter, targetObject.TilePosition, dropItemContext, groundContainer: out _, probabilityMultiplier: growthProgressFraction); if (result.TotalCreatedCount > 0) { NotificationSystem.ServerSendItemsNotification(byCharacter, result); } } else { // not a melee weapon or cannot drop to character - drop on the ground only dropItemsList.TryDropToGround( targetObject.TilePosition, dropItemContext, probabilityMultiplier: growthProgressFraction, groundContainer: out _); } } finally { if (weaponCache.ProtoWeapon is IProtoItemToolWoodcutting) { // add experience proportional to the vegetation structure points // (effectively - for the time spent on woodcutting) var exp = SkillLumbering.ExperienceAddPerStructurePoint; exp *= this.StructurePointsMax * growthProgressFraction; byCharacter?.ServerAddSkillExperience <SkillLumbering>(exp); } } }
public bool ServerGather(IStaticWorldObject worldObject, ICharacter character) { var privateState = GetPrivateState(worldObject); if (privateState.IsDropListSpawned) { // this loot container was already search - drop list was already spawned return(true); } // spawn items accordingly to the droplist privateState.IsDropListSpawned = true; var skillExperienceToAdd = SkillSearching.ExperienceAddWhenSearching * this.SearchingSkillExperienceMultiplier; var lootDroplist = this.ServerGetLootDroplist(worldObject); var dropItemContext = new DropItemContext(character, worldObject); CreateItemResult dropItemResult; if (this.IsAutoTakeAll) { // try to simply pickup the content dropItemResult = lootDroplist.TryDropToCharacter(character, dropItemContext, sendNoFreeSpaceNotification: false); if (dropItemResult.IsEverythingCreated && dropItemResult.TotalCreatedCount > 0) { NotificationSystem.ServerSendItemsNotification(character, dropItemResult); Server.World.DestroyObject(worldObject); // destroy object after success pickup character.ServerAddSkillExperience <SkillSearching>(skillExperienceToAdd); ServerLootEventHelper.OnLootReceived(character, worldObject); return(true); } dropItemResult.Rollback(); } // create a container and drop items there var attemptRemains = 100; var itemsContainer = privateState.ItemsContainer; do { dropItemResult = lootDroplist.TryDropToContainer(itemsContainer, dropItemContext); } // ensure that at least something is spawned... // perhaps that's not a good idea, but we have an attempts limit while (dropItemResult.TotalCreatedCount == 0 && --attemptRemains > 0); Server.Items.SetSlotsCount(itemsContainer, itemsContainer.OccupiedSlotsCount); character.ServerAddSkillExperience <SkillSearching>(skillExperienceToAdd); ServerLootEventHelper.OnLootReceived(character, worldObject); Server.World.EnterPrivateScope(character, worldObject); // register private scope exit on interaction cancel InteractionCheckerSystem.SharedRegister( character, worldObject, finishAction: isAbort => { if (worldObject.IsDestroyed) { return; } Server.World.ExitPrivateScope(character, worldObject); if (isAbort) { // notify client this.CallClient(character, _ => _.ClientRemote_FinishInteraction(worldObject)); } if (this.IsAutoDestroyWhenLooted) { // container was closed - destroy it Server.World.DestroyObject(worldObject); } }); Logger.Important($"Started object interaction with {worldObject} for {character}"); this.CallClient(character, _ => _.ClientRemote_OnContainerOpened(worldObject)); return(true); }
public bool ServerGather(IStaticWorldObject worldObject, ICharacter character) { var privateState = GetPrivateState(worldObject); if (privateState.IsDropListSpawned) { // this loot container was already search - drop list was already spawned return(true); } // spawn items accordingly to the droplist privateState.IsDropListSpawned = true; var lootDroplist = this.ServerGetLootDroplist(worldObject); var dropItemContext = new DropItemContext(character, worldObject); CreateItemResult dropItemResult; var attemptRemains = 100; var itemsContainer = privateState.ItemsContainer; do { dropItemResult = lootDroplist.TryDropToContainer(itemsContainer, dropItemContext); } // ensure that at least something is spawned... // perhaps that's not a good idea, but we have an attempts limit while (dropItemResult.TotalCreatedCount == 0 && --attemptRemains > 0); Server.Items.SetSlotsCount(itemsContainer, (byte)itemsContainer.OccupiedSlotsCount); character.ServerAddSkillExperience <SkillSearching>(SkillSearching.ExperienceAddWhenSearching); Server.World.EnterPrivateScope(character, worldObject); // register private scope exit on interaction cancel InteractionCheckerSystem.SharedRegister( character, worldObject, finishAction: isAbort => { if (worldObject.IsDestroyed) { return; } Server.World.ExitPrivateScope(character, worldObject); if (isAbort) { // notify client this.CallClient(character, _ => _.ClientRemote_FinishInteraction(worldObject)); } if (this.IsAutoDestroyWhenLooted) { // container was closed - destroy it Server.World.DestroyObject(worldObject); } }); Logger.Important($"Started object interaction with {worldObject} for {character}"); this.CallClient(character, _ => _.ClientRemote_OnContainerOpened(worldObject)); return(true); }
public static bool IsAvailableT5Specialized(DropItemContext context) { return(IsTimeGateFinished(TechTier.Tier5, isSpecialized: true)); }