Пример #1
0
 public override void ClientResetItemInHand(IComponentSkeleton skeletonRenderer)
 {
     skeletonRenderer.SetAttachmentSprite(this.SlotNameItemInHand,
                                          attachmentName: "WeaponMelee",
                                          textureResource: null);
     skeletonRenderer.SetAttachmentSprite(this.SlotNameItemInHand,
                                          attachmentName: "WeaponRifle",
                                          textureResource: null);
     skeletonRenderer.SetAttachment(this.SlotNameItemInHand, attachmentName: null);
 }
        public static void SetAttachments(
            IComponentSkeleton skeletonRenderer,
            IReadOnlyList <SkeletonSlotAttachment> slotAttachments)
        {
            foreach (var skeleton in skeletonRenderer.AllSkeletons)
            {
                var skeletonName = skeleton.SkeletonName;
                foreach (var slotAttachment in slotAttachments)
                {
                    if (slotAttachment.SkeletonName is not null &&
                        !slotAttachment.SkeletonName.Equals(skeletonName, StringComparison.Ordinal))
                    {
                        // this attachment for different skeleton
                        continue;
                    }

                    if (slotAttachment.AttachmentName.StartsWith("Head", StringComparison.Ordinal))
                    {
                        // Head attachments are processed by ClientCharacterHeadSpriteComposer
                        // when generating the head sprite. They're not assigned directly to skeleton.
                        continue;
                    }

                    skeletonRenderer.SetAttachmentSprite(
                        skeleton,
                        // auto find slot
                        slotName: null,
                        attachmentName: slotAttachment.AttachmentName,
                        textureResource: slotAttachment.TextureResource);
                }
            }
        }
Пример #3
0
 public virtual void ClientSetupItemInHand(
     IComponentSkeleton skeletonRenderer,
     string attachmentName,
     TextureResource textureResource)
 {
     skeletonRenderer.SetAttachmentSprite(this.SlotNameItemInHand, attachmentName, textureResource);
     skeletonRenderer.SetAttachment(this.SlotNameItemInHand, attachmentName);
 }
Пример #4
0
        public override void ClientSetupItemInHand(
            IComponentSkeleton skeletonRenderer,
            string attachmentName,
            TextureResource textureResource)
        {
            skeletonRenderer.SetAttachmentSprite(this.SlotNameItemInHand, attachmentName, textureResource);
            skeletonRenderer.SetAttachment(this.SlotNameItemInHand, attachmentName);

            // set left hand to use special sprite (representing holding of the item in hand)
            skeletonRenderer.SetAttachment("HandLeft", "HandLeft2");
            skeletonRenderer.SetAttachment("HandLeftEquipment", "HandLeft2Equipment");
        }
        public static void Setup(
            IComponentSkeleton skeletonRenderer,
            string attachmentName,
            TextureResource textureResource)
        {
            skeletonRenderer.SetAttachmentSprite(SlotNameWeapon, attachmentName, textureResource);
            skeletonRenderer.SetAttachment(SlotNameWeapon, attachmentName);

            // set left hand to use special sprite (representing holding of the item in hand)
            skeletonRenderer.SetAttachment(SlotNameHandLeft, "HandLeft2");
            skeletonRenderer.SetAttachment(SlotNameHandLeft + "Equipment", "HandLeft2Equipment");
        }
        public static void SetupSkeletonEquipmentForCharacter(
            ICharacter character,
            IItemsContainer containerEquipment,
            IComponentSkeleton skeletonRenderer,
            ProtoCharacterSkeleton skeleton,
            List <IClientComponent> skeletonComponents,
            bool isPreview = false)
        {
            if (!(skeleton is SkeletonHumanMale) &&
                !(skeleton is SkeletonHumanFemale))
            {
                // not a human
                // setup only implants
                using var equipmentImplants = Api.Shared.WrapInTempList(
                          containerEquipment.GetItemsOfProto <IProtoItemEquipmentImplant>());
                foreach (var item in equipmentImplants.AsList())
                {
                    var proto = (IProtoItemEquipmentImplant)item.ProtoGameObject;
                    proto.ClientSetupSkeleton(item,
                                              character,
                                              skeletonRenderer,
                                              skeletonComponents,
                                              isPreview);
                }

                return;
            }

            bool isMale, isHeadEquipmentHiddenForSelfAndPartyMembers;
            CharacterHumanFaceStyle faceStyle;

            if (character.ProtoCharacter is PlayerCharacter)
            {
                var publicState = PlayerCharacter.GetPublicState(character);
                faceStyle = publicState.FaceStyle;
                isMale    = publicState.IsMale;
                isHeadEquipmentHiddenForSelfAndPartyMembers = publicState.IsHeadEquipmentHiddenForSelfAndPartyMembers;

                if (isMale && !(skeleton is SkeletonHumanMale) ||
                    !isMale && !(skeleton is SkeletonHumanFemale))
                {
                    throw new Exception(
                              $"Skeleton don\'t match the gender of the player\'s character: isMale={isMale}, {skeleton}");
                }
            }
            else
            {
                // for NPC it will generate a random face
                isMale    = true;
                faceStyle = SharedCharacterFaceStylesProvider.GetForGender(isMale).GenerateRandomFace();
                isHeadEquipmentHiddenForSelfAndPartyMembers = false;
            }

            skeletonRenderer.ResetAttachments();
            skeleton.ClientResetItemInHand(skeletonRenderer);

            var skinToneId = faceStyle.SkinToneId;

            if (string.IsNullOrEmpty(skinToneId))
            {
                skeletonRenderer.DefaultTextureRemapper = null;
            }
            else
            {
                // use colorizer for the original sprites (to apply the skin tone)
                skeletonRenderer.DefaultTextureRemapper
                    = textureResource =>
                    {
                    var filePath = textureResource.LocalPath;
                    if (filePath.IndexOf("/Weapon", StringComparison.Ordinal) >= 0 ||
                        filePath.IndexOf("/Head", StringComparison.Ordinal) >= 0)
                    {
                        // no need to remap the original head and weapon sprites
                        // (they're never used as is)
                        return(textureResource);
                    }

                    return(ClientCharacterSkinTexturesCache.Get(textureResource,
                                                                skinToneId));
                    };
            }

            // setup equipment items
            using var equipmentItems = Api.Shared.WrapInTempList(
                      containerEquipment.GetItemsOfProto <IProtoItemEquipment>());
            if (!IsAllowNakedHumans)
            {
                if (!equipmentItems.AsList().Any(i => i.ProtoGameObject is IProtoItemEquipmentArmor))
                {
                    // no armor equipped - apply generic one
                    var pants = GenericPantsAttachments.Value;
                    ClientSkeletonAttachmentsLoader.SetAttachments(
                        skeletonRenderer,
                        isMale
                            ? pants.SlotAttachmentsMale
                            : pants.SlotAttachmentsFemale);

                    // select a random generic T-shirt based on character ID
                    var allShirts          = GenericShirtAttachments.Value;
                    var selectedShirtIndex = character.Id % allShirts.Length;
                    var shirt = allShirts[(int)selectedShirtIndex];
                    ClientSkeletonAttachmentsLoader.SetAttachments(
                        skeletonRenderer,
                        isMale
                            ? shirt.SlotAttachmentsMale
                            : shirt.SlotAttachmentsFemale);
                }
            }

            IItem headEquipmentForFaceSprite = null;

            foreach (var item in equipmentItems.AsList())
            {
                var proto = (IProtoItemEquipment)item.ProtoGameObject;
                proto.ClientSetupSkeleton(item,
                                          character,
                                          skeletonRenderer,
                                          skeletonComponents,
                                          isPreview);

                if (item.ProtoItem is IProtoItemEquipmentHead &&
                    headEquipmentForFaceSprite is null)
                {
                    headEquipmentForFaceSprite = item;
                }
            }

            if (isHeadEquipmentHiddenForSelfAndPartyMembers &&
                (character.IsCurrentClientCharacter ||
                 PartySystem.ClientIsPartyMember(character.Name) ||
                 PveSystem.ClientIsPve(false)))
            {
                headEquipmentForFaceSprite = null;
            }

            // generate head sprites for human players
            const string slotName       = "Head",
                         attachmentName = "Head";

            headGenerationId++;

            var spriteQualityOffset = skeletonRenderer.SpriteQualityOffset;

            skeletonRenderer.SetAttachmentSprite(
                skeleton.SkeletonResourceFront,
                slotName,
                attachmentName,
                new ProceduralTexture(
                    $"Head Front CharacterID={character.Id} gen={headGenerationId}",
                    proceduralTextureRequest =>
                    ClientCharacterHeadSpriteComposer.GenerateHeadSprite(
                        new CharacterHeadSpriteData(faceStyle,
                                                    headEquipmentForFaceSprite,
                                                    skeleton.SkeletonResourceFront),
                        proceduralTextureRequest,
                        isMale,
                        headSpriteType: ClientCharacterHeadSpriteComposer.HeadSpriteType.Front,
                        spriteQualityOffset: spriteQualityOffset),
                    isTransparent: true,
                    isUseCache: false));

            skeletonRenderer.SetAttachmentSprite(
                skeleton.SkeletonResourceBack,
                slotName,
                attachmentName,
                new ProceduralTexture(
                    $"Head Back CharacterID={character.Id} gen={headGenerationId}",
                    proceduralTextureRequest =>
                    ClientCharacterHeadSpriteComposer.GenerateHeadSprite(
                        new CharacterHeadSpriteData(faceStyle,
                                                    headEquipmentForFaceSprite,
                                                    skeleton.SkeletonResourceBack),
                        proceduralTextureRequest,
                        isMale,
                        headSpriteType: ClientCharacterHeadSpriteComposer.HeadSpriteType.Back,
                        spriteQualityOffset: spriteQualityOffset),
                    isTransparent: true,
                    isUseCache: false));

            skeletonRenderer.SetAttachmentSprite(
                skeleton.SkeletonResourceBack,
                slotName + "Back",
                attachmentName,
                new ProceduralTexture(
                    $"Head Back2 CharacterID={character.Id} gen={headGenerationId}",
                    proceduralTextureRequest =>
                    ClientCharacterHeadSpriteComposer.GenerateHeadSprite(
                        new CharacterHeadSpriteData(faceStyle,
                                                    headEquipmentForFaceSprite,
                                                    skeleton.SkeletonResourceBack),
                        proceduralTextureRequest,
                        isMale,
                        headSpriteType: ClientCharacterHeadSpriteComposer.HeadSpriteType.BackOverlay,
                        spriteQualityOffset: spriteQualityOffset),
                    isTransparent: true,
                    isUseCache: false));
        }
        public static void SetupSkeletonEquipmentForCharacter(
            ICharacter character,
            IItemsContainer containerEquipment,
            IComponentSkeleton skeletonRenderer,
            ProtoCharacterSkeleton skeleton,
            List <IClientComponent> skeletonComponents)
        {
            if (!(skeleton is SkeletonHumanMale) &&
                !(skeleton is SkeletonHumanFemale))
            {
                // not a human
                return;
            }

            skeletonRenderer.ResetAttachments();

            bool isMale;
            CharacterHumanFaceStyle faceStyle;

            if (character.ProtoCharacter is PlayerCharacter)
            {
                var pubicState = PlayerCharacter.GetPublicState(character);
                faceStyle = pubicState.FaceStyle;
                isMale    = pubicState.IsMale;

                if (isMale && !(skeleton is SkeletonHumanMale) ||
                    !isMale && !(skeleton is SkeletonHumanFemale))
                {
                    throw new Exception(
                              $"Skeleton don\'t match the gender of the player\'s character: isMale={isMale}, {skeleton}");
                }
            }
            else
            {
                // for NPC it will generate a random face
                isMale    = true;
                faceStyle = SharedCharacterFaceStylesProvider.GetForGender(isMale).GenerateRandomFace();
            }

            // setup equipment items
            var equipmentItems = containerEquipment.GetItemsOfProto <IProtoItemEquipment>().ToList();

            if (!IsAllowNakedHumans)
            {
                if (!equipmentItems.Any(i => i.ProtoGameObject is IProtoItemEquipmentLegs))
                {
                    // no lower cloth - apply generic one
                    ClientSkeletonAttachmentsLoader.SetAttachments(
                        skeletonRenderer,
                        isMale
                            ? GenericPantsAttachments.Value.SlotAttachmentsMale
                            : GenericPantsAttachments.Value.SlotAttachmentsFemale);
                }

                if (!equipmentItems.Any(i => i.ProtoGameObject is IProtoItemEquipmentChest))
                {
                    // no upper cloth - apply generic one (based on character Id)
                    var allShirts          = GenericShirtAttachments.Value;
                    var selectedShirtIndex = character.Id % allShirts.Length;
                    var shirt = allShirts[(int)selectedShirtIndex];
                    ClientSkeletonAttachmentsLoader.SetAttachments(
                        skeletonRenderer,
                        isMale
                            ? shirt.SlotAttachmentsMale
                            : shirt.SlotAttachmentsFemale);
                }
            }

            IItem headEquipment = null;

            foreach (var item in equipmentItems)
            {
                var proto = (IProtoItemEquipment)item.ProtoGameObject;
                proto.ClientSetupSkeleton(item, character, skeletonRenderer, skeletonComponents);

                if (item.ProtoItem is IProtoItemEquipmentHead &&
                    headEquipment == null)
                {
                    headEquipment = item;
                }
            }

            // generate head sprites for human players
            const string slotName = "Head", attachmentName = "Head";

            skeletonRenderer.SetAttachmentSprite(
                skeleton.SkeletonResourceFront,
                slotName,
                attachmentName,
                new ProceduralTexture(
                    "Head Front CharacterID=" + character.Id,
                    proceduralTextureRequest =>
                    ClientCharacterHeadSpriteComposer.GenerateHeadSprite(
                        new CharacterHeadSpriteData(faceStyle, headEquipment, skeleton.SkeletonResourceFront),
                        proceduralTextureRequest,
                        isMale,
                        isFrontFace: true,
                        spriteQualityOffset: skeletonRenderer.SpriteQualityOffset),
                    isTransparent: true,
                    isUseCache: false));

            skeletonRenderer.SetAttachmentSprite(
                skeleton.SkeletonResourceBack,
                slotName,
                attachmentName,
                new ProceduralTexture(
                    "Head Back CharacterID=" + character.Id,
                    proceduralTextureRequest =>
                    ClientCharacterHeadSpriteComposer.GenerateHeadSprite(
                        new CharacterHeadSpriteData(faceStyle, headEquipment, skeleton.SkeletonResourceBack),
                        proceduralTextureRequest,
                        isMale,
                        isFrontFace: false,
                        spriteQualityOffset: skeletonRenderer.SpriteQualityOffset),
                    isTransparent: true,
                    isUseCache: false));

            ClientResetWeaponAttachments(skeletonRenderer);
        }
 public static void Reset(IComponentSkeleton skeletonRenderer)
 {
     skeletonRenderer.SetAttachmentSprite(SlotNameWeapon, attachmentName: "WeaponMelee", textureResource: null);
     skeletonRenderer.SetAttachmentSprite(SlotNameWeapon, attachmentName: "WeaponRifle", textureResource: null);
     skeletonRenderer.SetAttachment(SlotNameWeapon, attachmentName: null);
 }