private Color GetColor()
        {
            if (this.currentCharacter.IsCurrentClientCharacter)
            {
                return(RayColorCurrentPlayerCharacter);
            }

            return(PartySystem.ClientIsPartyMember(this.currentCharacter.Name) ||
                   FactionSystem.ClientIsFactionMemberOrAlly(this.currentCharacter)
                       ? RayColorFriendlyPlayerCharacter
                       : RayColorOtherPlayerCharacter);
        }
Exemple #2
0
        public override bool SharedCanInteract(ICharacter character, IStaticWorldObject worldObject, bool writeToLog)
        {
            if (!base.SharedCanInteract(character, worldObject, writeToLog))
            {
                return(false);
            }

            var ownerName = GetPublicState(worldObject).OwnerName;

            if (ownerName == character.Name)
            {
                return(true);
            }

            if (PveSystem.SharedIsPve(false))
            {
                if (IsClient && PartySystem.ClientIsPartyMember(ownerName) ||
                    (IsServer &&
                     PartySystem.ServerIsSameParty(Server.Characters.GetPlayerCharacter(ownerName),
                                                   character)))
                {
                    // in PvE party members can pickup items of their party members
                }
                else
                {
                    // other players in PvE cannot pickup player's loot
                    if (writeToLog && IsClient)
                    {
                        PveSystem.ClientShowNotificationActionForbidden();
                    }

                    return(false);
                }
            }

            if (NewbieProtectionSystem.SharedIsNewbie(character))
            {
                // newbie cannot pickup other players' loot
                if (writeToLog)
                {
                    NewbieProtectionSystem.SharedShowNewbieCannotDamageOtherPlayersOrLootBags(character,
                                                                                              isLootBag: true);
                }

                return(false);
            }

            // non-newbie character can pickup players' loot
            // please note this validation has an override for derived ObjectPlayerLootContainerProtected
            return(true);
        }
        private void MouseUpHandler(object sender, MouseEventArgs e)
        {
            var contextMenu = this.ContextMenu;

            if (contextMenu != null &&
                contextMenu.IsOpen)
            {
                // close current context menu
                contextMenu.IsOpen = false;
                this.ContextMenu   = null;
                return;
            }

            if (lastContextMenuCloseFrameTime + 0.2 >= Api.Client.Core.ClientRealTime)
            {
                // just closed a context menu
                return;
            }

            // create new context menu
            contextMenu = new ContextMenu();
            var contextMenuItems = contextMenu.Items;

            var viewModel = (ViewModelPlayerEntry)this.DataContext;

            contextMenuItems.Add(
                new MenuItem()
            {
                Header  = CoreStrings.Chat_MessageMenu_CopyName,
                Command = new ActionCommand(this.ExecuteCommandCopyName)
            });

            if (!PartySystem.ClientIsPartyMember(viewModel.Name))
            {
                contextMenuItems.Add(
                    new MenuItem()
                {
                    Header  = CoreStrings.Chat_MessageMenu_InviteToParty,
                    Command = new ActionCommand(this.ExecuteCommandInviteToParty)
                });
            }

            contextMenuItems.Add(
                new MenuItem()
            {
                Header  = CoreStrings.Chat_MessageMenu_PrivateMessage,
                Command = new ActionCommand(this.ExecuteCommandOpenPrivateChat)
            });

            contextMenuItems.Add(
                new MenuItem()
            {
                Header = viewModel.IsBlocked
                                 ? CoreStrings.Chat_MessageMenu_Unblock
                                 : CoreStrings.Chat_MessageMenu_Block,
                Command = viewModel.CommandToggleBlock,
            });

            this.ContextMenu = contextMenu;

            contextMenu.Placement = PlacementMode.Relative;
            var target = sender as UIElement;

            contextMenu.PlacementTarget = target;
            var position = e.GetPosition(target);

            contextMenu.HorizontalOffset = position.X;
            contextMenu.VerticalOffset   = position.Y;
            contextMenu.IsOpen           = true;
            contextMenu.Closed          += this.ContextMenuClosedHandler;
        }
        public override void LateUpdate(double deltaTime)
        {
            var characterPublicState = this.currentCharacter.GetPublicState <ICharacterPublicState>();

            if (characterPublicState.IsDead ||
                (characterPublicState is PlayerCharacterPublicState playerCharacterPublicState &&
                 !playerCharacterPublicState.IsOnline) ||
                !(characterPublicState.SelectedItemWeaponProto is IProtoItemWeaponRanged protoWeaponRanged))
            {
                this.componentBeam.IsEnabled = false;
                return;
            }

            var rangeMax = this.currentCharacter.IsCurrentClientCharacter
                               ? ItemLaserSight.SharedGetCurrentRangeMax(characterPublicState)
                               : this.itemPublicState.MaxRange;

            if (rangeMax <= 1.5)
            {
                // no weapon selected or a too close-range weapon
                this.componentBeam.IsEnabled = false;
                return;
            }

            var clientState = this.currentCharacter.GetClientState <BaseCharacterClientState>();

            if (clientState.SkeletonRenderer is null ||
                !clientState.SkeletonRenderer.IsReady)
            {
                this.componentBeam.IsEnabled = false;
                return;
            }

            var customTargetPosition = this.currentCharacter.IsCurrentClientCharacter &&
                                       protoWeaponRanged is IProtoItemWeaponGrenadeLauncher
                                           ? (Vector2D?)WeaponGrenadeLauncherHelper.ClientGetCustomTargetPosition()
                                           : default;

            CastLine(this.currentCharacter,
                     customTargetPosition: customTargetPosition,
                     rangeMax: rangeMax,
                     collisionGroup: protoWeaponRanged.CollisionGroup,
                     toPosition: out var toPosition,
                     hitPosition: out var hitPosition);

            var sourcePosition  = this.GetSourcePosition(protoWeaponRanged);
            var beamEndPosition = hitPosition ?? toPosition;

            // fade-out if too close to prevent visual glitches
            var distance    = (beamEndPosition - sourcePosition).Length;
            var beamOpacity = MathHelper.Clamp(distance - 0.5, min: 0, max: 1);

            beamOpacity = beamOpacity * beamOpacity * beamOpacity;

            this.componentBeam.IsEnabled = true;
            var color = this.currentCharacter.IsCurrentClientCharacter
                            ? RayColorCurrentPlayerCharacter
                            : PartySystem.ClientIsPartyMember(this.currentCharacter.Name)
                                ? RayColorPartyMember
                                : RayColorOtherPlayerCharacter;

            this.componentBeam.Refresh(
                sourcePosition: sourcePosition,
                sourcePositionOffset: 0.1,
                targetPosition: beamEndPosition,
                beamWidth: BeamWidth,
                beamColor: color,
                spotColor: color,
                beamOpacity: beamOpacity,
                // determine whether the beam should end with a bright spot (when pointing on something)
                hasTarget: hitPosition.HasValue ||
                protoWeaponRanged is IProtoItemWeaponGrenadeLauncher);
        }
        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));
        }