public bool TryGetMapping(NpcInst npc, out CharacterMapping mapping) { lock (_Lock) { mapping = _ActiveMappings.Values.FirstOrDefault(map => map.CharacterNpc.ID == npc.ID); return(mapping != null); } }
public CharacterMapping SpawnAndMapCharacter(Character character) { if (character == null) { throw new ArgumentNullException(nameof(character)); } if (character.IsMapped) { throw new InvalidOperationException($"The character '{character.Name}' ({character.CharacterId}) is already mapped and can not be mapped again!"); } if (!character.IsValid) { throw new InvalidOperationException($"The given character object is invalid and should not be referenced or used anymore."); } NpcInst npc; if (character is HumanCharacter humanCharacter) { npc = new NpcInst(character.Template) { UseCustoms = true, CustomBodyTex = humanCharacter.HumanVisuals.BodyTex, CustomHeadMesh = humanCharacter.HumanVisuals.HeadMesh, CustomHeadTex = humanCharacter.HumanVisuals.HeadTex, CustomVoice = humanCharacter.HumanVisuals.Voice, CustomFatness = humanCharacter.HumanVisuals.Fatness, CustomScale = new Vec3f(humanCharacter.HumanVisuals.BodyWidth, 1.0f, humanCharacter.HumanVisuals.BodyWidth), CustomName = character.Name, DropUnconsciousOnDeath = true, UnconsciousDuration = 15 * TimeSpan.TicksPerSecond, }; } else { npc = new NpcInst(character.Template) { CustomName = character.Name, }; } npc.Spawn(character.World, character.LastKnownPosition, character.Rotation); character.IsMapped = true; var mapping = new CharacterMapping(character, npc); lock (_Lock) { _ActiveMappings.Add(character.CharacterId, mapping); } return(mapping); }
public void RemoveMapping(Character character) { if (character == null) { throw new ArgumentNullException(nameof(character)); } if (!character.IsValid) { throw new InvalidOperationException($"The given character object is invalid and should not be referenced or used anymore."); } if (!character.IsMapped) { throw new InvalidOperationException($"The character '{character.Name}' ({character.CharacterId}) is not mapped! There is nothing to remove!"); } NpcInst npc = null; lock (_Lock) { if (_ActiveMappings.TryGetValue(character.CharacterId, out CharacterMapping mapping)) { character.LastKnownPosition = mapping.CharacterNpc.GetPosition(); character.Rotation = mapping.CharacterNpc.GetAngles(); character.World = mapping.CharacterNpc.World; character.Template = mapping.CharacterNpc.Template; //Despawn the character npc and remove the mapping. npc = mapping.CharacterNpc; _ActiveMappings.Remove(character.CharacterId); character.IsMapped = false; //Check if we can completely unload the character. bool ownerIsActive = _CharactersByOwner.Values.Any(list => list.Contains(character)); if (!ownerIsActive) { _LoadedCharacters.Remove(character.CharacterId); _LoadedCharactersByName.Remove(character.Name.ToUpperInvariant()); character.IsValid = false; } } } npc?.Despawn(); }
public CharacterMapping(Character character, NpcInst characterNpc) { Character = character ?? throw new ArgumentNullException(nameof(character)); CharacterNpc = characterNpc ?? throw new ArgumentNullException(nameof(characterNpc)); }
/// <summary> /// Sets the <see cref="NpcInst"/> that this client is controlling. /// </summary> /// <param name="npc">The <see cref="NpcInst"/> that should be controlled by the current <see cref="Client"/>.</param> public void SetControl(NpcInst npc) { BaseClient.SetControl(npc?.BaseInst); }
public bool TryGetControlledNpc(out NpcInst npc) { npc = ControlledNpc; return(npc != null); }
public void ReadRequest(RequestMessageIDs id, PacketReader stream, NpcInst npc) { switch (id) { case RequestMessageIDs.JumpFwd: OnJump?.Invoke(npc, JumpMoves.Fwd); break; case RequestMessageIDs.JumpRun: OnJump?.Invoke(npc, JumpMoves.Run); break; case RequestMessageIDs.JumpUp: OnJump?.Invoke(npc, JumpMoves.Up); break; case RequestMessageIDs.ClimbHigh: OnClimb?.Invoke(npc, ClimbMoves.High, new NPC.ClimbingLedge(stream)); break; case RequestMessageIDs.ClimbMid: OnClimb?.Invoke(npc, ClimbMoves.Mid, new NPC.ClimbingLedge(stream)); break; case RequestMessageIDs.ClimbLow: OnClimb?.Invoke(npc, ClimbMoves.Low, new NPC.ClimbingLedge(stream)); break; case RequestMessageIDs.DrawFists: OnDrawFists?.Invoke(npc); break; case RequestMessageIDs.DrawWeapon: OnDrawWeapon?.Invoke(npc, npc.Inventory.GetItem(stream.ReadByte())); break; case RequestMessageIDs.AttackForward: OnFightMove?.Invoke(npc, FightMoves.Fwd); break; case RequestMessageIDs.AttackLeft: OnFightMove?.Invoke(npc, FightMoves.Left); break; case RequestMessageIDs.AttackRight: OnFightMove?.Invoke(npc, FightMoves.Right); break; case RequestMessageIDs.AttackRun: OnFightMove?.Invoke(npc, FightMoves.Run); break; case RequestMessageIDs.Parry: OnFightMove?.Invoke(npc, FightMoves.Parry); break; case RequestMessageIDs.Dodge: OnFightMove?.Invoke(npc, FightMoves.Dodge); break; case RequestMessageIDs.DropItem: OnDropItem?.Invoke(npc, npc.Inventory.GetItem(stream.ReadByte()), stream.ReadUShort()); break; case RequestMessageIDs.TakeItem: if (npc.World.TryGetVob(stream.ReadUShort(), out ItemInst item)) { OnTakeItem?.Invoke(npc, item); } break; case RequestMessageIDs.EquipItem: OnEquipItem?.Invoke(npc, npc.Inventory.GetItem(stream.ReadByte())); break; case RequestMessageIDs.UnequipItem: OnUnequipItem?.Invoke(npc, npc.Inventory.GetItem(stream.ReadByte())); break; case RequestMessageIDs.UseItem: OnUseItem?.Invoke(npc, npc.Inventory.GetItem(stream.ReadByte())); break; case RequestMessageIDs.Aim: OnAim?.Invoke(npc); break; case RequestMessageIDs.Unaim: OnUnaim?.Invoke(npc); break; case RequestMessageIDs.Shoot: OnShoot?.Invoke(npc, stream.ReadVec3f(), stream.ReadVec3f()); break; case RequestMessageIDs.Voice: OnVoice?.Invoke(npc, (VoiceCmd)stream.ReadByte()); break; case RequestMessageIDs.HelpUp: if (npc.World.TryGetVob(stream.ReadUShort(), out NpcInst target)) { OnHelpUp?.Invoke(npc, target); } break; default: GUC.Log.Logger.Log("Received Script RequestMessage with invalid ID: " + id.ToString()); break; } }