private Color GetColor() { if (this.currentCharacter.IsCurrentClientCharacter) { return(RayColorCurrentPlayerCharacter); } return(PartySystem.ClientIsPartyMember(this.currentCharacter.Name) || FactionSystem.ClientIsFactionMemberOrAlly(this.currentCharacter) ? RayColorFriendlyPlayerCharacter : RayColorOtherPlayerCharacter); }
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)); }