private InteractResult Blast(InteractionContext context, Vector3i blockPosition) { //todo: make it use the hammer's calories and durability if it's selected Vector3i minTop = blockPosition + new Vector3i(-2, -1, -2); Vector3i maxTop = blockPosition + new Vector3i(2, -1, 2); Vector3i minBottom = minTop + new Vector3i(0, -5, 0); Vector3i maxBottom = maxTop + new Vector3i(0, -5, 0); var pack = new GameActionPack(); var range = new WorldRange(minBottom, maxTop); foreach (var blockPos in range.XYZIterInc()) { var blockType = World.GetBlock(blockPos).GetType(); if (RubbleObject.BecomesRubble(blockType)) { AtomicActions.DeleteBlockNow(this.CreateMultiblockContext(context)); RubbleObject.TrySpawnFromBlock(context.Player, blockType, blockPos, 4); } } return(InteractResult.Success); }
public override InteractResult OnActLeft(InteractionContext context) { // Try delete tree debris with reduced XP multiplier. if (context.HasBlock && context.Block.Get <TreeDebris>() is TreeDebris treeDebris) { // Create game action pack, compose and try to perform. using (var pack = new GameActionPack()) { // Add debris items to inventory. foreach (var x in ((TreeSpecies)EcoSim.GetSpecies(treeDebris.Species)).DebrisResources) { pack.AddToInventory(context.Player?.User.Inventory, Item.Get(x.Key), x.Value.RandInt, context.Player?.User); } // Create multiblock context with reduced XP multiplier for cleaning debris. var multiblockContext = this.CreateMultiblockContext(context); multiblockContext.ActionDescription = Localizer.DoStr("clean up tree debris"); multiblockContext.ExperiencePerAction *= 0.1f; // Add block deletion to the pack and try to perform it. pack.DeleteBlock(multiblockContext); return((InteractResult)pack.TryPerform()); } } // Try interact with a world object. if (context.Target is WorldObject) { return(this.BasicToolOnWorldObjectCheck(context)); } // Fallback (try to damage target). return(base.OnActLeft(context)); }
private InteractResult PlaceBlockFill(InteractionContext context, Vector3i blockPosition) { int rotation = 0; BlueprintInstance blueprintInstance = null; if (context.Parameters != null) { BSONValue val; if (context.Parameters.TryGetValue("formRotation", out val)) { rotation = val.Int32Value; } if (context.Parameters.TryGetValue("blueprint", out val)) { blueprintInstance = new BlueprintInstance(new Blueprint(), Vector3i.Zero); blueprintInstance.FromBson(val.ObjectValue); } } var creatingItem = context.CarriedItem as BlockItem; if (creatingItem == null) { return(InteractResult.NoOp); } // TODO SJS: Verify all the blocks are created from the same type var form = context.Player?.User.Inventory.Carried.SelectedForm?.FormType.Name; var blockType = BlockFormManager.GetBlockTypeToCreate(context.Player, context.SelectedItem, context.CarriedItem, form, rotation); // Let's give up! (Let the carried type handle it) if (form == null || blockType == null || blueprintInstance == null) { return(InteractResult.NoOp); } // Create game action pack, fill it and try to perform. using (var pack = new GameActionPack()) { // Fill the pack. foreach (var blockPos in blueprintInstance) { pack.PlaceBlock( context: this.CreateMultiblockContext(context.Player, blockPos.Offset.SingleItemAsEnumerable()), blockType: BlockManager.FromId(blockPos.BlockId), createBlockAction: true, removeFromInv: context.Player?.User.Inventory, itemToRemove: creatingItem.GetType()); } // Try to perform created actions. return((InteractResult)pack.TryPerform(false)); } }
public override InteractResult OnActLeft(InteractionContext context) { if (context.HasBlock && context.Block.Is <Minable>()) { var user = context.Player.User; var item = context.Block is IRepresentsItem?Item.Get((IRepresentsItem)context.Block) : null; var totalDamageToTarget = user.BlockHitCache.MemorizeHit(context.Block.GetType(), context.BlockPosition.Value, this.Tier.GetCurrentValue(context.Player.User) * this.Damage); if (context.Block.Get <Minable>().Hardness <= totalDamageToTarget) { var result = AtomicActions.DeleteBlockNow(this.CreateMultiblockContext(context), spawnRubble: false); //Spawn the rubble if needed if (result.Success) { var forced = context.Player.User.Talentset.HasTalent(typeof(MiningLuckyBreakTalent)) ? 4 : -1; if (RubbleObject.TrySpawnFromBlock(context.Player, context.Block.GetType(), context.BlockPosition.Value, forced)) { var addition = item != null ? " " + item.UILink() : string.Empty; this.AddExperience(user, 1f, new LocString(Localizer.Format("mining") + addition)); user.UserUI.OnCreateRubble.Invoke(item.DisplayName.NotTranslated); user.BlockHitCache.ForgetHit(context.BlockPosition.Value); } } return((InteractResult)result); } else { return((InteractResult)AtomicActions.UseToolNow(this.CreateMultiblockContext(context))); } } else if (context.Target is RubbleObject) { var rubble = (RubbleObject)context.Target; if (rubble.IsBreakable) { using var pack = new GameActionPack(); pack.UseTool(this.CreateMultiblockContext(context)); pack.AddPostEffect(() => rubble.Breakup(context.Player)); return((InteractResult)pack.TryPerform(false)); } return(InteractResult.NoOp); } if (context.Target is WorldObject) { return(this.BasicToolOnWorldObjectCheck(context)); } return(base.OnActLeft(context)); }
void ApplyAction(User user, INetObject target, INetObject tool, GameActionPack pack) { // only apply talent when object picked up by hands, not with tool like excavator or skid steer if (tool != null) { return; } if (target is RubbleObject rubble) { this.ApplyTalent(user, rubble, pack); } }
public override void OnAreaValid(GameActionPack pack, Player player, Vector3i position, Quaternion rotation) { var deed = PropertyManager.FindConnectedDeedOrCreate(player.User, position.XZ); foreach (var plotPosition in PlotUtil.GetAllPropertyPos(position, virtualOccupancy)) { if (!this.IsPlotAuthorized(plotPosition, player.User, out var canClaimPlot)) { return; } if (canClaimPlot) { pack.ClaimProperty(deed, player.User, player.User.Inventory, plotPosition, requirePapers: false); } } if (!pack.EarlyResult) { return; } pack.AddPostEffect(() => { var camp = WorldObjectManager.ForceAdd(typeof(CampsiteObject), player.User, position, rotation, false); var stockpile = WorldObjectManager.ForceAdd(typeof(TinyStockpileObject), player.User, position + rotation.RotateVector(Vector3i.Right * 3), rotation, false); player.User.OnWorldObjectPlaced.Invoke(camp); player.User.Markers.Add(camp.Position3i + Vector3i.Up, camp.UILinkContent(), false); var storage = camp.GetComponent <PublicStorageComponent>(); var changeSet = new InventoryChangeSet(storage.Inventory); PlayerDefaults.GetDefaultCampsiteInventory().ForEach(x => changeSet.AddItems(x.Key, x.Value, storage.Inventory)); //If we're running a settlement system, create the homestead item now and fill it with homestead-specific claim papers. if (SettlementPluginConfig.Obj.SettlementSystemEnabled) { var marker = WorldObjectManager.ForceAdd(typeof(HomesteadMarkerObject), player.User, position + rotation.RotateVector(new Vector3i(3, 0, 3)), rotation, false); var markerComp = marker.GetComponent <SettlementMarkerComponent>(); markerComp.Settlement.Citizenship.AddSpawnedClaims(this.bonusPapers); markerComp.UpdateSpawnedClaims(); } else { //For the old system, add the papers to the tent. if (this.bonusPapers > 0) { changeSet.AddItems(typeof(PropertyClaimItem), this.bonusPapers); } } changeSet.Apply(); }); }
// TODO: create atomic actions covering the case and utilize them. public override void BlockInteraction(Vector3i pos, Quaternion rot, VehicleComponent vehicle, Inventory inv = null) { if (inv == null) { return; } if (!this.enabled) { return; } foreach (var offset in area) { var stack = inv.GroupedStacks.Where(x => x.Item is SeedItem).FirstOrDefault(); if (stack == null) { return; } SeedItem seed = stack.Item as SeedItem; var targetPos = (rot.RotateVector(offset) + pos).XYZi; Result authResult = ServiceHolder <IAuthManager> .Obj.IsAuthorized(targetPos, vehicle.Driver.User, AccessType.ConsumerAccess, null); if (authResult.Success) { if (World.GetBlock(targetPos + Vector3i.Down).Is <Tilled>() && World.GetBlock(targetPos).Is <Empty>()) { var pack = new GameActionPack(); pack.AddGameAction(new PlantSeeds() { Species = seed.Species.GetType(), ActionLocation = targetPos, Citizen = vehicle.Driver.User, ToolUsed = this }); var changes = new InventoryChangeSet(inv, vehicle.Driver.User); changes.RemoveItem(seed.Type); pack.AddChangeSet(changes); if (pack.TryPerform()) { var plant = EcoSim.PlantSim.SpawnPlant(seed.Species, targetPos); plant.Tended = true; } } } } }
private void ApplyTalent(User user, RubbleObject target, GameActionPack pack) { if (!(target is IRepresentsItem representsItem)) { return; } var itemType = representsItem.RepresentedItemType; // max stack size minus currently picking item var numToTake = Item.GetMaxStackSize(itemType) - 1; if (numToTake <= 0) { return; } var carrying = user.Carrying; if (!carrying.Empty()) { // ReSharper disable once PossibleNullReferenceException because Empty checked if (carrying.Item.Type != itemType || carrying.Quantity >= numToTake) { return; } // adjust to currently carrying item count numToTake -= carrying.Quantity; } //Get the changeset already in the action pack var numTaken = 0; var player = user.Player; var userInventory = user.Inventory; var checkedPlots = new Dictionary <Vector2i, bool>(); // A dictionary to cache auth checks for objects within the same plots. foreach (var rubble in NetObjectManager.GetObjectsWithin(target.Position, this.PickUpRange).OfType <RubbleObject>()) { var plotPosition = rubble.Position.XZi.ToPlotPosition(); var positionIsNew = !checkedPlots.ContainsKey(plotPosition); if (!positionIsNew && !checkedPlots[plotPosition]) { continue; // If we already failed to pickup something on this plot position, there's no need to proceed (we'll fail auth again). } if (rubble == target || rubble.IsBreakable) { continue; } if (!(rubble is IRepresentsItem rubbleRepresentsItem) || rubbleRepresentsItem.RepresentedItemType != itemType) { continue; } var addedToPack = pack.PickupRubbles(player, userInventory, rubble.SingleItemAsEnumerable(), itemType, checkAuthFirst: positionIsNew, notificate: false); // Check auth before adding to the pack if the position is new. if (addedToPack && ++numTaken == numToTake) { break; } if (positionIsNew) { checkedPlots.Add(plotPosition, addedToPack); // Add auth check for this plot to the dictionary. } } }