public override bool TryGiveItemStack(ItemStack itemstack) { if (itemstack == null || itemstack.StackSize == 0) { return(false); } ItemSlot dummySlot = new DummySlot(null); dummySlot.Itemstack = itemstack.Clone(); ItemStackMoveOperation op = new ItemStackMoveOperation(World, EnumMouseButton.Left, 0, EnumMergePriority.AutoMerge, itemstack.StackSize); WeightedSlot wslot = inv.GetBestSuitedSlot(dummySlot, new List <ItemSlot>()); if (wslot.weight > 0) { dummySlot.TryPutInto(wslot.slot, ref op); itemstack.StackSize -= op.MovedQuantity; WatchedAttributes.MarkAllDirty(); return(op.MovedQuantity > 0); } return(false); }
private void IsColliding(EntityPos pos, double impactSpeed) { pos.Motion.Set(0, 0, 0); if (!beforeCollided && World is IServerWorldAccessor && World.ElapsedMilliseconds > msCollide + 500) { if (impactSpeed >= 0.07) { World.PlaySoundAt(new AssetLocation("sounds/arrow-impact"), this, null, false, 32); // Slighty randomize orientation to make it a bit more realistic //pos.Yaw += (float)(World.Rand.NextDouble() * 0.05 - 0.025); //pos.Roll += (float)(World.Rand.NextDouble() * 0.05 - 0.025); // Resend position to client WatchedAttributes.MarkAllDirty(); int leftDurability = ProjectileStack == null ? 1 : ProjectileStack.Attributes.GetInt("durability", 1); if (leftDurability <= 0) { Die(); } } TryAttackEntity(impactSpeed); msCollide = World.ElapsedMilliseconds; beforeCollided = true; } }
private void IsColliding(EntityPos pos, double impactSpeed) { pos.Motion.Set(0, 0, 0); if (!beforeCollided && World is IServerWorldAccessor && World.ElapsedMilliseconds > msCollide + 500) { if (impactSpeed >= 0.07) { World.PlaySoundAt(new AssetLocation("sounds/arrow-impact"), this, null, false, 32); // Resend position to client WatchedAttributes.MarkAllDirty(); if (DamageStackOnImpact) { ProjectileStack.Collectible.DamageItem(World, this, new DummySlot(ProjectileStack)); } int leftDurability = ProjectileStack == null ? 1 : ProjectileStack.Attributes.GetInt("durability", 1); if (leftDurability <= 0) { Die(); } } TryAttackEntity(impactSpeed); msCollide = World.ElapsedMilliseconds; beforeCollided = true; } }
public override void OnInteract(EntityAgent byEntity, ItemSlot slot, Vec3d hitPosition, EnumInteractMode mode) { base.OnInteract(byEntity, slot, hitPosition, mode); if ((byEntity as EntityPlayer)?.Controls.Sneak == true && mode == EnumInteractMode.Interact && byEntity.World.Side == EnumAppSide.Server) { inv.DiscardAll(); WatchedAttributes.MarkAllDirty(); } }
public override void OnGameTick(float dt) { base.OnGameTick(dt); if (ShouldDespawn) { return; } EntityPos pos = LocalPos; stuck = Collided; if (stuck) { pos.Pitch = GameMath.PIHALF; pos.Roll = 0; pos.Yaw = GameMath.PIHALF; } else { pos.Pitch = (World.ElapsedMilliseconds / 300f) % GameMath.TWOPI; pos.Roll = 0; pos.Yaw = (World.ElapsedMilliseconds / 400f) % GameMath.TWOPI; } if (stuck) { if (!beforeCollided && World is IServerWorldAccessor) { float strength = GameMath.Clamp((float)motionBeforeCollide.Length() * 4, 0, 1); if (CollidedHorizontally) { pos.Motion.X = motionBeforeCollide.X * 0.8f; pos.Motion.Z = motionBeforeCollide.Z * 0.8f; if (strength > 0.08f && World.Rand.NextDouble() > 0.2f) { World.SpawnCubeParticles(LocalPos.XYZ.OffsetCopy(0, 0.2, 0), ProjectileStack, 0.2f, 20); Die(); } } if (CollidedVertically && motionBeforeCollide.Y <= 0) { pos.Motion.Y = GameMath.Clamp(motionBeforeCollide.Y * -0.4f, -0.1f, 0.1f); } World.PlaySoundAt(new AssetLocation("sounds/thud"), this, null, false, 32, strength); // Slighty randomize orientation to make it a bit more realistic //pos.Yaw += (float)(World.Rand.NextDouble() * 0.05 - 0.025); //pos.Roll += (float)(World.Rand.NextDouble() * 0.05 - 0.025); // Resend position to client WatchedAttributes.MarkAllDirty(); } beforeCollided = true; return; } if (World is IServerWorldAccessor) { Entity entity = World.GetNearestEntity(ServerPos.XYZ, 5f, 5f, (e) => { if (e.EntityId == this.EntityId || (FiredBy != null && e.EntityId == FiredBy.EntityId && World.ElapsedMilliseconds - msLaunch < 500) || !e.IsInteractable) { return(false); } double dist = e.CollisionBox.ToDouble().Translate(e.ServerPos.X, e.ServerPos.Y, e.ServerPos.Z).ShortestDistanceFrom(ServerPos.X, ServerPos.Y, ServerPos.Z); return(dist < 0.5f); }); if (entity != null) { bool didDamage = entity.ReceiveDamage(new DamageSource() { Source = EnumDamageSource.Entity, SourceEntity = FiredBy == null ? this : FiredBy, Type = EnumDamageType.BluntAttack }, Damage); World.PlaySoundAt(new AssetLocation("sounds/thud"), this, null, false, 32); World.SpawnCubeParticles(entity.LocalPos.XYZ.OffsetCopy(0, 0.2, 0), ProjectileStack, 0.2f, 20); if (FiredBy is EntityPlayer && didDamage) { World.PlaySoundFor(new AssetLocation("sounds/player/projectilehit"), (FiredBy as EntityPlayer).Player, false, 24); } Die(); return; } } beforeCollided = false; motionBeforeCollide.Set(pos.Motion.X, pos.Motion.Y, pos.Motion.Z); SetRotation(); }
public override void OnGameTick(float dt) { base.OnGameTick(dt); if (ShouldDespawn) { return; } EntityPos pos = SidedPos; stuck = Collided; pos.Pitch = GameMath.PIHALF; pos.Roll = 0; pos.Yaw = GameMath.PIHALF; if (stuck) { if (!beforeCollided && World is IServerWorldAccessor) { float strength = GameMath.Clamp((float)motionBeforeCollide.Length() * 4, 0, 1); if (CollidedHorizontally || CollidedVertically) { OnImpact(); return; } // Resend position to client WatchedAttributes.MarkAllDirty(); } beforeCollided = true; return; } if (World is IServerWorldAccessor) { Entity entity = World.GetNearestEntity(ServerPos.XYZ, 5f, 5f, (e) => { if (e.EntityId == this.EntityId || (FiredBy != null && e.EntityId == FiredBy.EntityId && World.ElapsedMilliseconds - msLaunch < 500) || !e.IsInteractable) { return(false); } double dist = e.CollisionBox.ToDouble().Translate(e.ServerPos.X, e.ServerPos.Y, e.ServerPos.Z).ShortestDistanceFrom(ServerPos.X, ServerPos.Y, ServerPos.Z); return(dist < 0.5f); }); if (entity != null) { entity.ReceiveDamage(new DamageSource() { Source = EnumDamageSource.Entity, SourceEntity = this, Type = EnumDamageType.BluntAttack }, Damage); OnImpact(); return; } } beforeCollided = false; motionBeforeCollide.Set(pos.Motion.X, pos.Motion.Y, pos.Motion.Z); }
public override void OnInteract(EntityAgent byEntity, ItemSlot slot, Vec3d hitPosition, EnumInteractMode mode) { IPlayer plr = (byEntity as EntityPlayer)?.Player; if (plr != null && !byEntity.World.Claims.TryAccess(plr, Pos.AsBlockPos, EnumBlockAccessFlags.Use)) { plr.InventoryManager.ActiveHotbarSlot.MarkDirty(); WatchedAttributes.MarkAllDirty(); return; } if (mode == EnumInteractMode.Interact && byEntity.RightHandItemSlot != null) { ItemSlot handslot = byEntity.RightHandItemSlot; if (handslot.Empty) { // Start from armor slot because it can't wear clothes atm for (int i = 0; i < GearInventory.Count; i++) { ItemSlot gslot = GearInventory[i]; if (gslot.Empty) { continue; } if (gslot.TryPutInto(byEntity.World, handslot) > 0) { return; } } } else { if (!ItemSlotCharacter.IsDressType(slot.Itemstack, EnumCharacterDressType.ArmorBody) && !ItemSlotCharacter.IsDressType(slot.Itemstack, EnumCharacterDressType.ArmorHead) && !ItemSlotCharacter.IsDressType(slot.Itemstack, EnumCharacterDressType.ArmorLegs)) { (byEntity.World.Api as ICoreClientAPI)?.TriggerIngameError(this, "cantplace", "Cannot place dresses on armor stands"); return; } } WeightedSlot sinkslot = GearInventory.GetBestSuitedSlot(handslot); if (sinkslot.weight > 0 && sinkslot.slot != null) { handslot.TryPutInto(byEntity.World, sinkslot.slot); return; } bool empty = true; for (int i = 0; i < GearInventory.Count; i++) { ItemSlot gslot = GearInventory[i]; empty &= gslot.Empty; } if (empty && byEntity.Controls.Sneak) { ItemStack stack = new ItemStack(byEntity.World.GetItem(new AssetLocation("armorstand"))); if (!byEntity.TryGiveItemStack(stack)) { byEntity.World.SpawnItemEntity(stack, ServerPos.XYZ); } Die(); return; } } if (!Alive || World.Side == EnumAppSide.Client || mode == 0) { //base.OnInteract(byEntity, slot, hitPosition, mode); return; } base.OnInteract(byEntity, slot, hitPosition, mode); }
private void RefreshBuyingSellingInventory(float refreshChance = 1.1f) { if (TradeProps == null) { return; } TradeProps.Buying.List.Shuffle(World.Rand); int buyingQuantity = Math.Min(TradeProps.Buying.List.Length, TradeProps.Buying.MaxItems); TradeProps.Selling.List.Shuffle(World.Rand); int sellingQuantity = Math.Min(TradeProps.Selling.List.Length, TradeProps.Selling.MaxItems); // Pick quantity items from the trade list that the trader doesn't already sell // Slots 0..15: Selling slots // Slots 16..19: Buying cart // Slots 20..35: Buying slots // Slots 36..39: Selling cart // Slot 40: Money slot Stack <TradeItem> newBuyItems = new Stack <TradeItem>(); Stack <TradeItem> newsellItems = new Stack <TradeItem>(); ItemSlotTrade[] sellingSlots = Inventory.SellingSlots; ItemSlotTrade[] buyingSlots = Inventory.BuyingSlots; #region Avoid duplicate sales for (int i = 0; i < TradeProps.Selling.List.Length; i++) { if (newsellItems.Count >= sellingQuantity) { break; } TradeItem item = TradeProps.Selling.List[i]; item.Resolve(World, "tradeItem resolver"); bool alreadySelling = sellingSlots.Any((slot) => slot?.Itemstack != null && slot.TradeItem.Stock > 0 && item.ResolvedItemstack?.Equals(World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes) == true); if (!alreadySelling) { newsellItems.Push(item); } } for (int i = 0; i < TradeProps.Buying.List.Length; i++) { if (newBuyItems.Count >= buyingQuantity) { break; } TradeItem item = TradeProps.Buying.List[i]; item.Resolve(World, "tradeItem resolver"); bool alreadySelling = buyingSlots.Any((slot) => slot?.Itemstack != null && slot.TradeItem.Stock > 0 && item.ResolvedItemstack?.Equals(World, slot.Itemstack, GlobalConstants.IgnoredStackAttributes) == true); if (!alreadySelling) { newBuyItems.Push(item); } } #endregion replaceTradeItems(newBuyItems, buyingSlots, buyingQuantity, refreshChance); replaceTradeItems(newsellItems, sellingSlots, sellingQuantity, refreshChance); ITreeAttribute tree = GetOrCreateTradeStore(); Inventory.ToTreeAttributes(tree); WatchedAttributes.MarkAllDirty(); }
public override void OnGameTick(float dt) { base.OnGameTick(dt); if (ShouldDespawn) { return; } if (OnGround && CanCollect(null)) { Api.World.SpawnItemEntity(ProjectileStack, ServerPos.XYZ); Die(); return; } EntityPos pos = SidedPos; pos.Pitch = World.ElapsedMilliseconds / 250f % GameMath.TWOPI; pos.Roll = World.ElapsedMilliseconds / 250f % GameMath.TWOPI; pos.Yaw = World.ElapsedMilliseconds / 250f % GameMath.TWOPI; if (Collided) { if (!beforeCollided && World is IServerWorldAccessor) { float strength = GameMath.Clamp((float)motionBeforeCollide.Length() * 4, 0, 1); if (CollidedHorizontally) { pos.Motion.X = motionBeforeCollide.X * 0.8f; pos.Motion.Z = motionBeforeCollide.Z * 0.8f; } if (CollidedVertically && motionBeforeCollide.Y <= 0) { pos.Motion.Y = GameMath.Clamp(motionBeforeCollide.Y * -0.4f, -0.1f, 0.1f); } World.PlaySoundAt(new AssetLocation("game:sounds/thud"), this, null, false, 32, strength); WatchedAttributes.MarkAllDirty(); } beforeCollided = true; return; } if (World is IServerWorldAccessor && ((ItemCage)ProjectileStack.Item)?.IsEmpty == true) { Entity entity = World.GetNearestEntity(ServerPos.XYZ, 5f, 5f, (e) => { if (e.EntityId == this.EntityId || (FiredBy != null && e.EntityId == FiredBy.EntityId && World.ElapsedMilliseconds - launchMs < 500) || !e.IsInteractable) { return(false); } double dist = e.CollisionBox.ToDouble().Translate(e.ServerPos.X, e.ServerPos.Y, e.ServerPos.Z).ShortestDistanceFrom(ServerPos.X, ServerPos.Y, ServerPos.Z); return(dist < 0.5f); }); if (entity != null && (entity as EntityPlayer) == null && entity.Alive) { bool didDamage = entity.ReceiveDamage(new DamageSource() { Source = EnumDamageSource.Entity, SourceEntity = FiredBy ?? (this), Type = EnumDamageType.BluntAttack }, Damage); World.PlaySoundAt(new AssetLocation("game:sounds/thud"), this, null, false, 32); World.SpawnCubeParticles(entity.SidedPos.XYZ.OffsetCopy(0, 0.2, 0), ProjectileStack, 0.2f, 20); if (FiredBy is EntityPlayer && didDamage) { World.PlaySoundFor(new AssetLocation("game:sounds/player/projectilehit"), (FiredBy as EntityPlayer).Player, false, 24); } if (entity.GetBehavior("health") is EntityBehaviorHealth behavior) { float captureChance = ProjectileStack.Collectible.Attributes["defaultcapturechance"].AsFloat(); ItemStack baitStack = ProjectileStack.Attributes.GetItemstack("bait"); baitStack?.ResolveBlockOrItem(entity.World); if (baitStack != null && Core.AllBaits.TryGetValue(baitStack.Collectible.Code, out var captureEntities)) { foreach (var captureEntity in captureEntities) { if (captureEntity.Code == entity.Code.ToString()) { captureChance = captureEntity.CaptureChance; break; } } } float efficiency = ProjectileStack.Collectible.Attributes["efficiency"].AsFloat(); captureChance += (1 - behavior.Health / behavior.MaxHealth) * efficiency; // -1% hp = (+1% * efficiency) capture chance if (captureChance < random.NextDouble()) { float breakChance = ProjectileStack.Collectible.Attributes["breakchance"].AsFloat(); if (breakChance >= random.NextDouble()) { FiredBy.SendMessage(Lang.Get(ConstantsCore.ModId + ":cage-broken")); } else { FiredBy.SendMessage(Lang.Get(ConstantsCore.ModId + ":cage-mistake")); //Api.World.SpawnItemEntity(ProjectileStack, ServerPos.XYZ); AssetLocation caseCode = ProjectileStack.Collectible.CodeWithVariant("type", "case"); ItemStack caseStack = new ItemStack(Api.World.GetItem(caseCode)); Api.World.SpawnItemEntity(caseStack, ServerPos.XYZ); } } else { AssetLocation location = ProjectileStack.Item?.CodeWithVariant("type", "full"); ItemStack full = new ItemStack(Api.World.GetItem(location)); SaveEntityInAttributes(entity, full, "capture"); full.Attributes.SetString("capturename", entity.GetName()); Api.World.SpawnItemEntity(full, entity.Pos.XYZ); FiredBy.SendMessage(Lang.Get(ConstantsCore.ModId + ":cage-captured")); entity.Die(EnumDespawnReason.Removed); } Die(); } } } beforeCollided = false; motionBeforeCollide.Set(pos.Motion.X, pos.Motion.Y, pos.Motion.Z); }