private void GatherDresses(EnumCharacterDressType type)
        {
            List <ItemStack> dresses = new List <ItemStack>();

            dresses.Add(null);

            string stringtype = type.ToString().ToLowerInvariant();

            IList <Item> items = capi.World.Items;

            for (int i = 0; i < items.Count; i++)
            {
                Item item = items[i];
                if (item == null || item.Code == null || item.Attributes == null)
                {
                    continue;
                }

                string clothcat = item.Attributes["clothescategory"]?.AsString();
                bool   allow    = item.Attributes["inCharacterCreationDialog"]?.AsBool() == true;

                if (allow && clothcat?.ToLowerInvariant() == stringtype)
                {
                    dresses.Add(new ItemStack(item));
                }
            }

            DressesByDressType[type]       = dresses.ToArray();
            DressPositionByTressType[type] = 0;
        }
        private ItemSlot onNewSlot(int slotId, InventoryGeneric self)
        {
            EnumCharacterDressType type = (EnumCharacterDressType)slotId;
            ItemSlotCharacter      slot = new ItemSlotCharacter(type, self);

            iconByDressType.TryGetValue(type, out slot.BackgroundIcon);

            return(slot);
        }
Exemple #3
0
        /// <summary>
        /// Checks to see what dress type the given item is.
        /// </summary>
        /// <param name="itemstack"></param>
        /// <param name="dressType"></param>
        /// <returns></returns>
        public static bool IsDressType(IItemStack itemstack, EnumCharacterDressType dressType)
        {
            if (itemstack == null || itemstack.Collectible.Attributes == null)
            {
                return(false);
            }

            string stackDressType = itemstack.Collectible.Attributes["clothescategory"].AsString();

            return(stackDressType != null && dressType.ToString().Equals(stackDressType, StringComparison.InvariantCultureIgnoreCase));
        }
        protected override ItemSlot NewSlot(int slotId)
        {
            if (slotId == 15)
            {
                return(new ItemSlotSurvival(this));
            }

            EnumCharacterDressType type = (EnumCharacterDressType)slotId;
            ItemSlotCharacter      slot = new ItemSlotCharacter(type, this);

            iconByDressType.TryGetValue(type, out slot.BackgroundIcon);

            return(slot);
        }
        public override void OnLoaded(ICoreAPI api)
        {
            base.OnLoaded(api);

            string strdress           = Attributes["clothescategory"].AsString();
            EnumCharacterDressType dt = EnumCharacterDressType.Unknown;

            Enum.TryParse(strdress, true, out dt);
            DressType = dt;


            JsonObject jsonObj = Attributes?["footStepSound"];

            if (jsonObj?.Exists == true)
            {
                string soundloc = jsonObj.AsString(null);
                if (soundloc != null)
                {
                    AssetLocation loc = AssetLocation.Create(soundloc, Code.Domain).WithPathPrefixOnce("sounds/");

                    if (soundloc.EndsWith("*"))
                    {
                        loc.Path       = loc.Path.TrimEnd('*');
                        FootStepSounds = api.Assets.GetLocations(loc.Path, loc.Domain).ToArray();
                    }
                    else
                    {
                        FootStepSounds = new AssetLocation[] { loc };
                    }
                }
            }

            jsonObj = Attributes?["statModifiers"];
            if (jsonObj?.Exists == true)
            {
                try
                {
                    StatModifers = jsonObj.AsObject <StatModifiers>();
                }
                catch (Exception e)
                {
                    api.World.Logger.Error("Failed loading statModifiers for item/block {0}. Will ignore. Exception: {1}", Code, e);
                    StatModifers = null;
                }
            }

            ProtectionModifiers defMods = null;

            jsonObj = Attributes?["defaultProtLoss"];
            if (jsonObj?.Exists == true)
            {
                try
                {
                    defMods = jsonObj.AsObject <ProtectionModifiers>();
                }
                catch (Exception e)
                {
                    api.World.Logger.Error("Failed loading defaultProtLoss for item/block {0}. Will ignore. Exception: {1}", Code, e);
                }
            }

            jsonObj = Attributes?["protectionModifiers"];
            if (jsonObj?.Exists == true)
            {
                try
                {
                    ProtectionModifiers = jsonObj.AsObject <ProtectionModifiers>();
                }
                catch (Exception e)
                {
                    api.World.Logger.Error("Failed loading protectionModifiers for item/block {0}. Will ignore. Exception: {1}", Code, e);
                    ProtectionModifiers = null;
                }
            }


            if (ProtectionModifiers != null && ProtectionModifiers.PerTierFlatDamageReductionLoss == null)
            {
                ProtectionModifiers.PerTierFlatDamageReductionLoss = defMods?.PerTierFlatDamageReductionLoss;
            }
            if (ProtectionModifiers != null && ProtectionModifiers.PerTierRelativeProtectionLoss == null)
            {
                ProtectionModifiers.PerTierRelativeProtectionLoss = defMods?.PerTierRelativeProtectionLoss;
            }
        }
Exemple #6
0
        private float handleDamaged(IPlayer player, float damage, DamageSource dmgSource)
        {
            EnumDamageType type = dmgSource.Type;
            double         angleProtectionRange = 120 / 2 * GameMath.DEG2RAD;

            // Reduce damage if player holds a shield
            ItemSlot[] shieldSlots = new ItemSlot[] { player.Entity.LeftHandItemSlot, player.Entity.RightHandItemSlot };
            foreach (var shieldSlot in shieldSlots)
            {
                var attr = shieldSlot.Itemstack?.ItemAttributes?["shield"];
                if (attr == null || !attr.Exists)
                {
                    continue;
                }

                string usetype = player.Entity.Controls.Sneak ? "active" : "passive";

                float dmgabsorb = attr["damageAbsorption"][usetype].AsFloat(0);
                float chance    = attr["protectionChance"][usetype].AsFloat(0);
                (player as IServerPlayer)?.SendMessage(GlobalConstants.DamageLogChatGroup, Lang.Get("{0:0.#} of {1:0.#} damage blocked by shield", Math.Min(dmgabsorb, damage), damage), EnumChatType.Notification);

                double dx;
                double dz;
                if (dmgSource.HitPosition != null)
                {
                    dx = dmgSource.HitPosition.X;
                    dz = dmgSource.HitPosition.Z;
                }
                else if (dmgSource.SourceEntity != null)
                {
                    dx = dmgSource.SourceEntity.Pos.X - player.Entity.Pos.X;
                    dz = dmgSource.SourceEntity.Pos.Z - player.Entity.Pos.Z;
                }
                else if (dmgSource.SourcePos != null)
                {
                    dx = dmgSource.SourcePos.X - player.Entity.Pos.X;
                    dz = dmgSource.SourcePos.Z - player.Entity.Pos.Z;
                }
                else
                {
                    break;
                }

                double attackYaw = Math.Atan2((double)dx, (double)dz);
                double playerYaw = player.Entity.Pos.Yaw + GameMath.PIHALF;

                bool inProtectionRange = Math.Abs(GameMath.AngleRadDistance((float)playerYaw, (float)attackYaw)) < angleProtectionRange;

                if (inProtectionRange && api.World.Rand.NextDouble() < chance)
                {
                    damage = Math.Max(0, damage - dmgabsorb);

                    var loc = shieldSlot.Itemstack.ItemAttributes["blockSound"].AsString("held/shieldblock");
                    api.World.PlaySoundAt(AssetLocation.Create(loc, shieldSlot.Itemstack.Collectible.Code.Domain).WithPathPrefixOnce("sounds/").WithPathAppendixOnce(".ogg"), player, null);

                    if (api.Side == EnumAppSide.Server)
                    {
                        shieldSlot.Itemstack.Collectible.DamageItem(api.World, dmgSource.SourceEntity, shieldSlot, 1);
                        shieldSlot.MarkDirty();
                    }
                }
            }

            if (damage <= 0)
            {
                return(0);
            }
            // The code below only the server needs to execute
            if (api.Side == EnumAppSide.Client)
            {
                return(damage);
            }

            // Does not protect against non-attack damages

            if (type != EnumDamageType.BluntAttack && type != EnumDamageType.PiercingAttack && type != EnumDamageType.SlashingAttack)
            {
                return(damage);
            }
            if (dmgSource.Source == EnumDamageSource.Internal || dmgSource.Source == EnumDamageSource.Suicide)
            {
                return(damage);
            }

            ItemSlot   armorSlot;
            IInventory inv = player.InventoryManager.GetOwnInventory(GlobalConstants.characterInvClassName);
            double     rnd = api.World.Rand.NextDouble();


            int attackTarget;

            if ((rnd -= 0.2) < 0)
            {
                // Head
                armorSlot    = inv[12];
                attackTarget = 0;
            }
            else if ((rnd -= 0.5) < 0)
            {
                // Body
                armorSlot    = inv[13];
                attackTarget = 1;
            }
            else
            {
                // Legs
                armorSlot    = inv[14];
                attackTarget = 2;
            }

            // Apply full damage if no armor is in this slot
            if (armorSlot.Empty || !(armorSlot.Itemstack.Item is ItemWearable))
            {
                EnumCharacterDressType[] dressTargets = clothingDamageTargetsByAttackTacket[attackTarget];
                EnumCharacterDressType   target       = dressTargets[api.World.Rand.Next(dressTargets.Length)];

                ItemSlot targetslot = player.Entity.GearInventory[(int)target];
                if (!targetslot.Empty)
                {
                    // Wolf: 10 hp damage = 10% condition loss
                    // Ram: 10 hp damage = 2.5% condition loss
                    // Bronze locust: 10 hp damage = 5% condition loss
                    float mul = 0.25f;
                    if (type == EnumDamageType.SlashingAttack)
                    {
                        mul = 1f;
                    }
                    if (type == EnumDamageType.PiercingAttack)
                    {
                        mul = 0.5f;
                    }

                    float diff = -damage / 100 * mul;

                    if (Math.Abs(diff) > 0.05)
                    {
                        api.World.PlaySoundAt(ripSound, player.Entity);
                    }

                    (targetslot.Itemstack.Collectible as ItemWearable)?.ChangeCondition(targetslot, diff);
                }

                return(damage);
            }

            ProtectionModifiers protMods = (armorSlot.Itemstack.Item as ItemWearable).ProtectionModifiers;

            int   weaponTier  = dmgSource.DamageTier;
            float flatDmgProt = protMods.FlatDamageReduction;
            float percentProt = protMods.RelativeProtection;

            for (int tier = 1; tier <= weaponTier; tier++)
            {
                bool aboveTier = tier > protMods.ProtectionTier;

                float flatLoss = aboveTier ? protMods.PerTierFlatDamageReductionLoss[1] : protMods.PerTierFlatDamageReductionLoss[0];
                float percLoss = aboveTier ? protMods.PerTierRelativeProtectionLoss[1] : protMods.PerTierRelativeProtectionLoss[0];

                if (aboveTier && protMods.HighDamageTierResistant)
                {
                    flatLoss /= 2;
                    percLoss /= 2;
                }

                flatDmgProt -= flatLoss;
                percentProt *= 1 - percLoss;
            }

            // Durability loss is the one before the damage reductions
            float durabilityLoss    = 0.5f + damage * Math.Max(0.5f, (weaponTier - protMods.ProtectionTier) * 3);
            int   durabilityLossInt = GameMath.RoundRandom(api.World.Rand, durabilityLoss);

            // Now reduce the damage
            damage  = Math.Max(0, damage - flatDmgProt);
            damage *= 1 - Math.Max(0, percentProt);

            armorSlot.Itemstack.Collectible.DamageItem(api.World, player.Entity, armorSlot, durabilityLossInt);

            if (armorSlot.Empty)
            {
                api.World.PlaySoundAt(new AssetLocation("sounds/effect/toolbreak"), player);
            }

            return(damage);
        }
Exemple #7
0
        private float handleDamaged(IPlayer player, float damage, DamageSource dmgSource)
        {
            // Does not protect against non-attack damages
            EnumDamageType type = dmgSource.Type;

            if (type != EnumDamageType.BluntAttack && type != EnumDamageType.PiercingAttack && type != EnumDamageType.SlashingAttack)
            {
                return(damage);
            }
            if (dmgSource.Source == EnumDamageSource.Internal || dmgSource.Source == EnumDamageSource.Suicide)
            {
                return(damage);
            }

            ItemSlot   armorSlot;
            IInventory inv = player.InventoryManager.GetOwnInventory(GlobalConstants.characterInvClassName);
            double     rnd = api.World.Rand.NextDouble();


            int attackTarget;

            if ((rnd -= 0.2) < 0)
            {
                // Head
                armorSlot    = inv[12];
                attackTarget = 0;
            }
            else if ((rnd -= 0.5) < 0)
            {
                // Body
                armorSlot    = inv[13];
                attackTarget = 1;
            }
            else
            {
                // Legs
                armorSlot    = inv[14];
                attackTarget = 2;
            }

            // Apply full damage if no armor is in this slot
            if (armorSlot.Empty || !(armorSlot.Itemstack.Item is ItemWearable))
            {
                EnumCharacterDressType[] dressTargets = clothingDamageTargetsByAttackTacket[attackTarget];
                EnumCharacterDressType   target       = dressTargets[api.World.Rand.Next(dressTargets.Length)];

                ItemSlot targetslot = player.Entity.GearInventory[(int)target];
                if (!targetslot.Empty)
                {
                    // Wolf: 10 hp damage = 10% condition loss
                    // Ram: 10 hp damage = 2.5% condition loss
                    // Bronze locust: 10 hp damage = 5% condition loss
                    float mul = 0.25f;
                    if (type == EnumDamageType.SlashingAttack)
                    {
                        mul = 1f;
                    }
                    if (type == EnumDamageType.PiercingAttack)
                    {
                        mul = 0.5f;
                    }

                    float diff = -damage / 100 * mul;

                    if (Math.Abs(diff) > 0.05)
                    {
                        api.World.PlaySoundAt(ripSound, player.Entity);
                    }

                    (targetslot.Itemstack.Collectible as ItemWearable)?.ChangeCondition(targetslot, diff);
                }

                return(damage);
            }

            ProtectionModifiers protMods = (armorSlot.Itemstack.Item as ItemWearable).ProtectionModifiers;

            int   weaponTier  = dmgSource.DamageTier;
            float flatDmgProt = protMods.FlatDamageReduction;
            float percentProt = protMods.RelativeProtection;

            for (int tier = 1; tier <= weaponTier; tier++)
            {
                bool aboveTier = tier > protMods.ProtectionTier;

                float flatLoss = aboveTier ? protMods.PerTierFlatDamageReductionLoss[1] : protMods.PerTierFlatDamageReductionLoss[0];
                float percLoss = aboveTier ? protMods.PerTierRelativeProtectionLoss[1] : protMods.PerTierRelativeProtectionLoss[0];

                if (aboveTier && protMods.HighDamageTierResistant)
                {
                    flatLoss /= 2;
                    percLoss /= 2;
                }

                flatDmgProt -= flatLoss;
                percentProt *= 1 - percLoss;
            }

            // Durability loss is the one before the damage reductions
            float durabilityLoss    = 0.5f + damage * Math.Max(0.5f, (weaponTier - protMods.ProtectionTier) * 3);
            int   durabilityLossInt = GameMath.RoundRandom(api.World.Rand, durabilityLoss);

            // Now reduce the damage
            damage  = Math.Max(0, damage - flatDmgProt);
            damage *= 1 - Math.Max(0, percentProt);

            armorSlot.Itemstack.Collectible.DamageItem(api.World, player.Entity, armorSlot, durabilityLossInt);

            if (armorSlot.Empty)
            {
                api.World.PlaySoundAt(new AssetLocation("sounds/effect/toolbreak"), player);
            }

            return(damage);
        }
        private void SetupDialog()
        {
            // title bar
            ElementBounds bgBounds     = ElementStdBounds.DialogBackground();
            ElementBounds dialogBounds = ElementStdBounds.AutosizedMainDialog.WithChild(bgBounds);

            SingleComposer = capi.Gui.CreateCompo("tailoring", dialogBounds)
                             .AddShadedDialogBG(bgBounds)
                             .AddDialogTitleBar("Tailoring", () => TryClose())
                             .BeginChildElements(bgBounds);
            ElementBounds titleBarBounds = ElementStdBounds.TitleBar();

            bgBounds.WithChild(titleBarBounds);

            // search text box
            ElementBounds searchBounds = ElementBounds.FixedSize(200, 30).FixedUnder(titleBarBounds);

            bgBounds.WithChild(searchBounds);
            SingleComposer.AddTextInput(searchBounds, (string newText) => {
                filterSearch = newText;
                FilterItems();
            }, CairoFont.WhiteSmallishText(), "search");
            SingleComposer.GetTextInput("search").SetPlaceHolderText("Search...");
            // SingleComposer.FocusElement(SingleComposer.GetTextInput("search").TabIndex);

            // prep for category dropdown
            string[]      characterDressTypeNames         = EnumCharacterDressType.GetNames(typeof(EnumCharacterDressType));
            List <string> filteredCharacterDressTypeNames = new List <string>();

            foreach (var characterDressTypeName in characterDressTypeNames)
            {
                if (categoryCount.ContainsKey(characterDressTypeName.ToLowerInvariant()))
                {
                    filteredCharacterDressTypeNames.Add(characterDressTypeName);
                }
            }
            string[] values = new string[filteredCharacterDressTypeNames.Count + 1];
            values[0] = "";
            filteredCharacterDressTypeNames.CopyTo(0, values, 1, filteredCharacterDressTypeNames.Count);
            string[] names = new string[filteredCharacterDressTypeNames.Count + 1];
            names[0] = "(Show all)";
            filteredCharacterDressTypeNames.CopyTo(0, names, 1, filteredCharacterDressTypeNames.Count);

            // category dropdown
            ElementBounds categoryDropdownBounds = ElementBounds.FixedSize(150, 30).FixedUnder(titleBarBounds).FixedRightOf(searchBounds, PADDING);

            bgBounds.WithChild(categoryDropdownBounds);
            SingleComposer.AddDropDown(values, names, 0, (value, selected) => {
                filterCategory = value;
                FilterItems();
            }, categoryDropdownBounds, "category");

            // stacklist
            ElementBounds stacklistBounds = ElementBounds.FixedSize(400, STACKLIST_HEIGHT).FixedUnder(searchBounds, PADDING);

            bgBounds.WithChild(stacklistBounds);
            ElementBounds clipBounds      = stacklistBounds.ForkBoundingParent();
            ElementBounds insetBounds     = stacklistBounds.FlatCopy().FixedGrow(6).WithFixedOffset(-3, -3);
            ElementBounds scrollbarBounds = insetBounds.CopyOffsetedSibling(3 + stacklistBounds.fixedWidth + 7).WithFixedWidth(20);

            SingleComposer
            .BeginClip(clipBounds)
            .AddInset(insetBounds, 3)
            .AddInteractiveElement(new GuiElementHandbookListWithTooltips(capi, stacklistBounds, (int index) => {
                OnSelectProduct((shownStacklistItems[index] as GuiHandbookItemStackPage).Stack);
            }, shownStacklistItems), "stacklist")
            .EndClip()
            .AddVerticalScrollbar((float value) => {
                GuiElementHandbookList stacklist = SingleComposer.GetHandbookStackList("stacklist");
                stacklist.insideBounds.fixedY    = 3 - value;
                stacklist.insideBounds.CalcWorldBounds();
            }, scrollbarBounds, "scrollbar")
            ;
            UpdateStacklistScrollbar();

            // costLabel
            ElementBounds costLabelBounds = ElementBounds.FixedSize(300, 80).FixedUnder(clipBounds, PADDING);

            bgBounds.WithChild(costLabelBounds);
            SingleComposer.AddDynamicText("", CairoFont.WhiteSmallText(), EnumTextOrientation.Left, costLabelBounds, "costLabel");

            // craftButton
            ElementBounds craftButtonBounds = ElementBounds
                                              .FixedSize(0, 0)
                                              .FixedUnder(clipBounds, PADDING)
                                              .WithAlignment(EnumDialogArea.RightFixed)
                                              .WithFixedPadding(20, 4)
                                              .WithFixedAlignmentOffset(-11, 1)
            ;

            bgBounds.WithChild(craftButtonBounds);
            SingleComposer.AddSmallButton("Craft", () => {
                OnCraftButtonClicked();
                return(true);
            }, craftButtonBounds, EnumButtonStyle.Normal, EnumTextOrientation.Center, "craftButton");
            var craftButton = SingleComposer.GetButton("craftButton");

            craftButton.Enabled = false;

            SingleComposer.EndChildElements(); // bgBounds
            SingleComposer.Compose();
        }
Exemple #9
0
 public ItemSlotCharacter(EnumCharacterDressType type, InventoryBase inventory) : base(inventory)
 {
     this.type = type;
 }