/// <inheritdoc /> public void CalculatePosition(ILivingEntity entity) { if (!entity.Object.Spawned) { return; } if (entity.Moves.DestinationPosition.IsZero() || entity.Object.MovingFlags.HasFlag(ObjectState.OBJSTA_STAND)) { return; } if (entity.Follow.IsFollowing) { if (entity.Object.Position.IsInCircle(entity.Follow.Target.Object.Position, entity.Follow.FollowDistance)) { entity.Moves.DestinationPosition.Reset(); entity.Object.MovingFlags &= ~ObjectState.OBJSTA_FMOVE; entity.Object.MovingFlags |= ObjectState.OBJSTA_STAND; entity.Behavior?.OnArrived(); } else { entity.Moves.DestinationPosition.Copy(entity.Follow.Target.Object.Position); entity.Object.MovingFlags &= ~ObjectState.OBJSTA_STAND; entity.Object.MovingFlags |= ObjectState.OBJSTA_FMOVE; } } Walk(entity); }
public void Su_Lethal_Test() { using (GameContext context = CreateContext()) { ICharacter character = context.Character; ILivingEntity target = TestFactory.CreateMonster(); IMap map = TestFactory.CreateMap(character, target); context.Process(new Su { CasterType = character.EntityType, CasterId = character.Id, TargetType = target.EntityType, TargetId = target.Id, SkillKey = 254, Damage = 1000, IsTargetAlive = false, HpPercentage = 0 }); Check.That(target.Map).IsNull(); Check.That(map.Entities).Not.Contains(target); Check.That(target.HpPercentage).IsEqualTo(0); context.IsEventEmitted <EntityDamageEvent>(x => x.Caster.Equals(character) && x.Target.Equals(target) && x.Damage == 1000 && x.SkillKey == 254); context.IsEventEmitted <EntityDeathEvent>(x => x.Killer.Equals(character) && x.Entity.Equals(target)); } }
private void UpdatePosition(ILivingEntity entity, float x, float z) { if (entity is IPlayerEntity && entity.Moves.IsMovingWithKeyboard) { float angle = entity.Object.Angle; var movementX = (float)(Math.Sin(angle * (Math.PI / 180)) * Math.Sqrt(x * x + z * z)); var movementZ = (float)(Math.Cos(angle * (Math.PI / 180)) * Math.Sqrt(x * x + z * z)); if (entity.Object.MovingFlags.HasFlag(ObjectState.OBJSTA_FMOVE)) { entity.Object.Position.X += movementX; entity.Object.Position.Z -= movementZ; } else if (entity.Object.MovingFlags.HasFlag(ObjectState.OBJSTA_BMOVE)) { entity.Object.Position.X -= movementX; entity.Object.Position.Z += movementZ; } } else { entity.Object.Position.X += x; entity.Object.Position.Z += z; } }
/// <summary> /// Sends a "name query" reply to the client. /// </summary> /// <param name="client">the client to send to</param> /// <param name="entity">the character information to be sent</param> public static void SendNameQueryReply(IPacketReceiver client, ILivingEntity entity) { using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_NAME_QUERY_RESPONSE)) { entity.EntityId.WritePacked(packet); packet.Write((byte)0); // new in 3.1.0 - this is a type, ranging from 0-3 packet.WriteCString(entity.Name); packet.Write((byte)0); // cross realm bg name? (256 bytes max) packet.Write((byte)entity.Race); packet.Write((byte)entity.Gender); packet.Write((byte)entity.Class); packet.Write((byte)0); // hasDeclinedNames //if (hasDeclinedNames) //{ // for (int i=0;i<4;i++) // { // packet.WriteCString(""); // } //} client.Send(packet, addEnd: false); } }
/// <summary> /// Gets the magic skill factor based on the equiped weapon element type and skill element type. /// </summary> /// <param name="entity">Living entity.</param> /// <param name="skill">Skill.</param> /// <returns>Magic skill factor.</returns> private float GetMagicSkillFactor(ILivingEntity entity, SkillInfo skill) { const float DefaultMagicSkillFactor = 1.0f; if (entity is IPlayerEntity player) { Item weapon = player.Inventory.GetEquipedItem(ItemPartType.RightWeapon) ?? player.Hand; ElementType weaponElementType = weapon.Id != -1 ? weapon.Data.Element : ElementType.None; ElementType skillElementType = skill.Data.Element.GetValueOrDefault(ElementType.None); if (skillElementType == weaponElementType) { return(1.1f); } else if ( skillElementType == ElementType.Fire && weaponElementType == ElementType.Water || skillElementType == ElementType.Water && weaponElementType == ElementType.Electricity || skillElementType == ElementType.Electricity && weaponElementType == ElementType.Earth || skillElementType == ElementType.Wind && weaponElementType == ElementType.Fire ) { return(0.9f); } } return(DefaultMagicSkillFactor); }
/// <summary>Handles an incoming name query.</summary> /// <param name="client">the Session the incoming packet belongs to</param> /// <param name="packet">the full packet</param> public static void NameQueryRequest(IRealmClient client, RealmPacketIn packet) { EntityId id = packet.ReadEntityId(); ILivingEntity entity = (ILivingEntity)client.ActiveCharacter; if ((int)entity.EntityId.Low != (int)id.Low) { entity = World.GetNamedEntity(id.Low) as ILivingEntity; } if (entity != null) { QueryHandler.SendNameQueryReply((IPacketReceiver)client, entity); } else { ServerApp <WCell.RealmServer.RealmServer> .IOQueue.AddMessage((IMessage) new Message((Action)(() => { CharacterRecord characterRecord = CharacterRecord.LoadRecordByEntityId(id.Low); if (characterRecord == null) { QueryHandler.s_log.Warn("{0} queried name of non-existing Character: " + (object)id, (object)client); } else { QueryHandler.SendNameQueryReply((IPacketReceiver)client, (ILivingEntity)characterRecord); } }))); } }
/// <summary> /// Handles an incoming name query. /// </summary> /// <param name="client">the Session the incoming packet belongs to</param> /// <param name="packet">the full packet</param> //[ClientPacketHandler((RealmServerOpCode.CMSG_NAME_QUERY)] public static void NameQueryRequest(IRealmClient client, RealmPacketIn packet) { var id = packet.ReadEntityId(); ILivingEntity entity = client.ActiveCharacter; if (entity.EntityId.Low != id.Low) { entity = World.GetNamedEntity(id.Low) as ILivingEntity; } if (entity != null) { SendNameQueryReply(client, entity); } else { RealmServer.IOQueue.AddMessage(new Message(() => { var record = CharacterRecord.LoadRecordByEntityId(id.Low); if (record == null) { s_log.Warn("{0} queried name of non-existing Character: " + id, client); } else { SendNameQueryReply(client, record); } })); } }
public AIBehaviorTree(AIGetToTargetActions aiToTarget, AIWeaponActions aiWA, ILivingEntity entity, ProjectileDetector projectileDetector) { this.aiToTarget = aiToTarget; this.aiWeapon = aiWA; this.entity = entity; this.projectileDetector = projectileDetector; }
public MeleeAttackEventArgs(ObjectMessageType attackType, ILivingEntity target, float attackSpeed, int unknownParameter) { this.AttackType = attackType; this.Target = target; this.AttackSpeed = attackSpeed; this.UnknownParameter = unknownParameter; }
/// <summary> /// Executes a melee or magic skill and inflicts the damages to the target. /// </summary> /// <param name="caster">Living entity casting a skill.</param> /// <param name="target">Living target entity touched by the skill.</param> /// <param name="skill">Skill to be casted.</param> /// <param name="reduceCasterPoints">Value that indicates if it should reduce caster points or not.</param> private void ExecuteSkill(ILivingEntity caster, ILivingEntity target, SkillInfo skill, bool reduceCasterPoints = true) { ObjectMessageType skillMessageType = ObjectMessageType.OBJMSG_NONE; IAttackArbiter attackArbiter = null; switch (skill.Data.Type) { case SkillType.Magic: attackArbiter = new MagicSkillAttackArbiter(caster, target, skill); skillMessageType = ObjectMessageType.OBJMSG_MAGICSKILL; break; case SkillType.Skill: attackArbiter = new MeleeSkillAttackArbiter(caster, target, skill); skillMessageType = ObjectMessageType.OBJMSG_MELEESKILL; break; } _battleSystem.DamageTarget(caster, target, attackArbiter, skillMessageType); if (skill.LevelData.CooldownTime > 0) { skill.SetCoolTime(skill.LevelData.CooldownTime); } if (reduceCasterPoints) { ReduceCasterPoints(caster, skill); } }
public void CMode_Unwear_Test() { using (GameContext context = CreateContext()) { ICharacter character = context.Character; ILivingEntity entity = TestFactory.CreatePlayer(); IMap map = TestFactory.CreateMap(character, entity); context.Process(new CMode { EntityType = entity.EntityType, EntityId = entity.Id, MorphId = 0, MorphUpgrade = 13, MorphDesign = 11, MorphBonus = 0, Size = 10 }); Check.That(map.Entities).Contains(entity); Check.That(entity.MorphId).IsEqualTo(0); context.IsEventEmitted <SpecialistUnwearEvent>(x => x.Entity.Equals(entity)); } }
/// <inheritdoc /> public AttackResult DamageTarget(ILivingEntity attacker, ILivingEntity defender, IAttackArbiter attackArbiter, ObjectMessageType attackType) { if (!CanAttack(attacker, defender)) { ClearBattleTargets(defender); ClearBattleTargets(attacker); return(null); } if (defender is IPlayerEntity undyingPlayer) { if (undyingPlayer.PlayerData.Mode == ModeType.MATCHLESS_MODE) { _logger.LogDebug($"{attacker.Object.Name} wasn't able to inflict any damages to {defender.Object.Name} because he is in undying mode"); return(null); } } AttackResult attackResult; if (attacker is IPlayerEntity player && player.PlayerData.Mode.HasFlag(ModeType.ONEKILL_MODE)) { attackResult = new AttackResult { Damages = defender.Attributes[DefineAttributes.HP], Flags = AttackFlags.AF_GENERIC }; }
/// <inheritdoc /> public void OnKilled(ILivingEntity killerEntity) { _monster.Timers.DespawnTime = Time.TimeInSeconds() + 5; // TODO: Configure this timer on world configuration // Drop items int itemCount = 0; foreach (DropItemData dropItem in _monster.Data.DropItems) { if (itemCount >= _monster.Data.MaxDropItem) { break; } long dropChance = RandomHelper.LongRandom(0, DropSystem.MaxDropChance); if (dropItem.Probability * _worldConfiguration.Rates.Drop >= dropChance) { var item = new Item(dropItem.ItemId, 1, -1, -1, -1, (byte)RandomHelper.Random(0, dropItem.ItemMaxRefine)); _dropSystem.DropItem(_monster, item, killerEntity); itemCount++; } } // Drop item kinds foreach (DropItemKindData dropItemKind in _monster.Data.DropItemsKind) { var itemsDataByItemKind = _gameResources.Items.Values.Where(x => x.ItemKind3 == dropItemKind.ItemKind && x.Rare >= dropItemKind.UniqueMin && x.Rare <= dropItemKind.UniqueMax); if (!itemsDataByItemKind.Any()) { continue; } var itemData = itemsDataByItemKind.ElementAt(RandomHelper.Random(0, itemsDataByItemKind.Count() - 1)); int itemRefine = RandomHelper.Random(0, 10); for (int i = itemRefine; i >= 0; i--) { long itemDropProbability = (long)(_gameResources.ExpTables.GetDropLuck(itemData.Level > 120 ? 119 : itemData.Level, itemRefine) * (_monster.Data.CorrectionValue / 100f)); long dropChance = RandomHelper.LongRandom(0, DropSystem.MaxDropChance); if (dropChance < itemDropProbability * _worldConfiguration.Rates.Drop) { var item = new Item(itemData.Id, 1, -1, -1, -1, (byte)itemRefine); _dropSystem.DropItem(_monster, item, killerEntity); break; } } } // Drop gold int goldDropped = RandomHelper.Random(_monster.Data.DropGoldMin, _monster.Data.DropGoldMax); _dropSystem.DropGold(_monster, goldDropped, killerEntity); }
public EntityDamageEvent(IClient client, ILivingEntity caster, ILivingEntity target, int skillKey, int damage) { Client = client; Caster = caster; Target = target; SkillKey = skillKey; Damage = damage; }
public override void Attack(ILivingEntity target) { if (target == null) { return; } target.Damage(DamageCause.EntityAttack, AttackStrength, this); }
/// <inheritdoc /> public int CreateProjectile(ProjectileInfo projectile) { ILivingEntity livingEntity = projectile.Owner; int projectileId = livingEntity.Battle.LastProjectileId++; livingEntity.Battle.Projectiles.Add(projectileId, projectile); return(projectileId); }
private void OnTriggerEnter2D(Collider2D collision) { ILivingEntity other = collision.GetComponent <ILivingEntity>(); if (other != null) { other.TakeDamage(other.health); } }
/// <inheritdoc /> public void Follow(ILivingEntity livingEntity, IWorldEntity targetEntity, float distance = 1f) { livingEntity.Follow.Target = targetEntity; livingEntity.Moves.DestinationPosition.Copy(targetEntity.Object.Position); livingEntity.Object.MovingFlags &= ~ObjectState.OBJSTA_STAND; livingEntity.Object.MovingFlags |= ObjectState.OBJSTA_FMOVE; _moverPacketFactory.SendFollowTarget(livingEntity, targetEntity, distance); }
/// <inheritdoc /> public void SendDie(IPlayerEntity player, ILivingEntity deadEntity, ILivingEntity killerEntity, ObjectMessageType motion) { using var packet = new FFPacket(); packet.StartNewMergedPacket(deadEntity.Id, SnapshotType.MOVERDEATH); packet.Write((int)motion); packet.Write(killerEntity.Id); SendToVisible(packet, player, sendToPlayer: true); }
/// <inheritdoc /> public void Follow(ILivingEntity livingEntity, uint targetId, float distance = 1f) { var entityToFollow = livingEntity.FindEntity <IWorldEntity>(targetId); if (entityToFollow == null) { throw new ArgumentNullException(nameof(entityToFollow), $"Cannot find entity with object id: {targetId} around {livingEntity.Object.Name}"); } Follow(livingEntity, entityToFollow, distance); }
/// <inheritdoc /> public void OnTargetKilled(ILivingEntity killedEntity) { if (killedEntity is IMonsterEntity deadMonster) { // Give experience _experienceSystem.GiveExeperience(_player, deadMonster.Data.Experience * _worldConfiguration.Rates.Experience); // Quest check _questSystem.UpdateQuestDiary(_player, QuestActionType.KillMonster, deadMonster.Data.Id, 1); } }
public void Attack(ILivingEntity entity) { ISkill skill = Skills.FirstOrDefault(); if (skill == null) { Logger.Warn("Can't found first skill"); return; } Attack(skill, entity); }
/// <inheritdoc /> public void SendMeleeAttack(ILivingEntity attacker, ObjectMessageType motion, uint targetId, int unknwonParam, AttackFlags attackFlags) { using var packet = new FFPacket(); packet.StartNewMergedPacket(attacker.Id, SnapshotType.MELEE_ATTACK); packet.Write((int)motion); packet.Write(targetId); packet.Write(unknwonParam); packet.Write((int)attackFlags); SendToVisible(packet, attacker); }
public int DealDamageTo(ILivingEntity enemy) { if (!CanDealDamageTo(enemy)) { return(0); } int damageDone = stats.GetRandomDamage() - enemy.Stats.Defence; damageDone = (damageDone < 0) ? 0 : damageDone; enemy.Stats.UpdateHealth(-damageDone); return(damageDone); }
private float GetEntitySpeed(ILivingEntity entity) { float entitySpeed = entity.Moves.Speed * entity.Moves.SpeedFactor; // TODO: Add speed bonuses if (entity.Type == WorldEntityType.Monster) { entitySpeed /= 2f; } entitySpeed *= _updateRate; return(entitySpeed); }
/// <inheritdoc /> public void SendUseSkill(ILivingEntity player, IWorldEntity target, SkillInfo skill, int castingTime, SkillUseType skillUseType) { using var packet = new FFPacket(); packet.StartNewMergedPacket(player.Id, SnapshotType.USESKILL); packet.Write(skill.SkillId); packet.Write(skill.Level); packet.Write(target.Id); packet.Write((int)skillUseType); packet.Write(castingTime); SendToVisible(packet, player, sendToPlayer: true); }
/// <summary> /// Gets the hit rating of an entity. /// </summary> /// <param name="entity">Entity</param> /// <returns></returns> private int GetHitRating(ILivingEntity entity) { if (entity is IPlayerEntity player) { return(player.Attributes[DefineAttributes.DEX]); // TODO: add dex bonus } else if (entity is IMonsterEntity monster) { return(monster.Data.HitRating); } return(0); }
/// <summary> /// Gets the hit rating of an entity. /// </summary> /// <param name="entity">Entity</param> /// <returns></returns> private int GetHitRating(ILivingEntity entity) { if (entity is IPlayerEntity player) { return(player.Statistics.Dexterity); // TODO: add dex bonus } else if (entity is IMonsterEntity monster) { return(monster.Data.HitRating); } return(0); }
/// <summary> /// Gets the escape rating of an entity. /// </summary> /// <param name="entity"></param> /// <returns></returns> public int GetEspaceRating(ILivingEntity entity) { if (entity is IPlayerEntity player) { return((int)(player.Statistics.Dexterity * 0.5f)); // TODO: add dex bonus and DST_PARRY } else if (entity is IMonsterEntity monster) { return(monster.Data.EscapeRating); } return(0); }
/// <inheritdoc /> public void SendRangeAttack(ILivingEntity attacker, ObjectMessageType motion, uint targetId, int power, int projectileId) { using var packet = new FFPacket(); packet.StartNewMergedPacket(attacker.Id, SnapshotType.RANGE_ATTACK); packet.Write((int)motion); packet.Write(targetId); packet.Write(power); packet.Write(0); // unused parameter, always 0 packet.Write(projectileId); SendToVisible(packet, attacker); }
public override void Attack(ILivingEntity target) { if (target == null) return; short weaponDmg = Inventory.ActiveItem.GetDamage(); //Start Event EntityAttackEventArgs e = new EntityAttackEventArgs(this, weaponDmg, target); Server.PluginManager.CallEvent(Event.EntityAttack, e); if(e.EventCanceled) return; target = (LivingEntity)e.EntityToAttack; weaponDmg = e.Damage; //End Event Exhaustion += 300; target.Damage(DamageCause.EntityAttack, weaponDmg, this); }
public abstract void Attack(ILivingEntity target);
/// <summary> /// Determines whether this instance can see the specified entity. /// </summary> /// <returns> /// <c>true</c> if this instance can see the specified entity; otherwise, <c>false</c>. /// </returns> /// <param name='entity'> /// The entity to check for line of sight to. /// </param> public bool CanSee(ILivingEntity entity) { return this.World.RayTraceBlocks(new AbsWorldCoords(this.Position.X, this.Position.Y + this.EyeHeight, this.Position.Z), new AbsWorldCoords(entity.Position.X, entity.Position.Y + entity.EyeHeight, entity.Position.Z)) == null; }
public override void Attack(ILivingEntity target) { if (target == null) return; target.Damage(DamageCause.EntityAttack, AttackStrength, this); }
/// <summary> /// Sends a "name query" reply to the client. /// </summary> /// <param name="client">the client to send to</param> /// <param name="entity">the character information to be sent</param> public static void SendNameQueryReply(IPacketReceiver client, ILivingEntity entity) { using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_NAME_QUERY_RESPONSE)) { entity.EntityId.WritePacked(packet); packet.Write((byte)0); // new in 3.1.0 - this is a type, ranging from 0-3 packet.WriteCString(entity.Name); packet.Write((byte)0); // cross realm bg name? (256 bytes max) packet.Write((byte)entity.Race); packet.Write((byte)entity.Gender); packet.Write((byte)entity.Class); packet.Write((byte)0); // hasDeclinedNames //if (hasDeclinedNames) //{ // for (int i=0;i<4;i++) // { // packet.WriteCString(""); // } //} client.Send(packet); } }