public bool CombatGetHitChance(EntityImplementation defender, out double chance)
        {
            chance = 0.0;

            if (!combatIsInDistanceToAttack(defender))
                return false;

            // TODO: Use attack/defense descriptors in final implementation
            // TODO: Implement new rules for hitting

            int levelDiff =
                skills.GetSkill(EntitySkillType.AttackUnarmed).CurrentLevel
                    - combatGetPenalizedDesenseSkillLevel(defender);

            // 50% at equal levels
            double skillSuccessRate = 0.0;
            if (levelDiff < 0)
                skillSuccessRate = (10.0 + levelDiff) * 0.05; // Linear
            else
                skillSuccessRate = (20.0 + levelDiff) * 0.025; // Linear

               chance = skillSuccessRate;

            if (chance < 0.001)
                chance = 0.001; // Always a chance for lucky success 1/1000
            if (chance > 0.995)
                chance = 0.995; // Always a chance for failure 5/1000

            return true;
        }
        /// <summary>
        /// Invoked on defender
        /// </summary>
        /// <param name="attacker">
        /// A <see cref="EntityImplementation"/>
        /// </param>
        public void CombatEvadeAttacker(EntityImplementation attacker)
        {
            // Send attacker animation frame
            attacker.SendAnimationCommand(combatGetAnimationForAttack());

            // TODO: Use attack/defense descriptors in final implementation

            // Award defense experience
            DefendActionDescriptor defDescriptor = new DefendActionDescriptor(2000, 1000); //TODO: Time values are meaningless for now
            defDescriptor.AddExperienceDescriptor(
                new ExperienceDescriptor(
                    EntitySkillType.DefenseDodge,
                    attacker.skills.GetSkill(EntitySkillType.AttackUnarmed).CurrentLevel,
                    10));

            SkillsAwardExperience(defDescriptor);
        }
示例#3
0
        public void FollowingStopFollowing()
        {
            if (isFollowingEntity)
            {
                entityToFollow.removeFollower(this);

                TimeBasedActionCancelExecuted();

                RawTextOutgoingMessage msgRawTextOut =
                                     (RawTextOutgoingMessage)OutgoingMessagesFactory.Create(OutgoingMessageType.RAW_TEXT);
                msgRawTextOut.Channel = PredefinedChannel.CHAT_LOCAL;
                msgRawTextOut.Color = PredefinedColor.Blue1;
                msgRawTextOut.Text = "You stopped following " + entityToFollow.Name;
                PutMessageIntoMyQueue(msgRawTextOut);

                entityToFollow = null;
            }
        }
示例#4
0
        public void FollowingFollow(EntityImplementation enImpl)
        {
            RawTextOutgoingMessage msgRawTextOutMe =
                (RawTextOutgoingMessage)OutgoingMessagesFactory.Create(OutgoingMessageType.RAW_TEXT);
            msgRawTextOutMe.Channel = PredefinedChannel.CHAT_LOCAL;
            msgRawTextOutMe.Color = PredefinedColor.Blue1;

            // Is it different than 'me'
            if (enImpl == this)
            {
                msgRawTextOutMe.Text = "There is no point following yourself...";
                PutMessageIntoMyQueue(msgRawTextOutMe);
                return;
            }

            // Is is close enough
            double distance = Double.MaxValue;
            DistanceCalculationResult result = getDistanceToEntity(enImpl, out distance);
            if (result != DistanceCalculationResult.CALC_OK)
            {
                msgRawTextOutMe.Text = "The one you seek is not here...";
                PutMessageIntoMyQueue(msgRawTextOutMe);
                return;
            }

            if (distance > 3.0)
            {
                msgRawTextOutMe.Text = "You need to stand closer...";
                PutMessageIntoMyQueue(msgRawTextOutMe);
                return;
            }

            if (isFollowedByEntities)
            {
                msgRawTextOutMe.Text = "If you want to follow, you can't be followed...";
                PutMessageIntoMyQueue(msgRawTextOutMe);
                return;
            }

            if (enImpl.isFollowingEntity)
            {
                msgRawTextOutMe.Text = enImpl.Name + " can't follow anybody if you want to follow him/her...";
                PutMessageIntoMyQueue(msgRawTextOutMe);
                return;
            }

            FollowingStopFollowing();

            TimeBasedActionCancelExecuted();

            if (enImpl.addFollower(this))
            {
                this.entityToFollow = enImpl;
                TimeBasedActionCancelExecuted();
                msgRawTextOutMe.Text = "You start following " + enImpl.Name;
                PutMessageIntoMyQueue(msgRawTextOutMe);

                RawTextOutgoingMessage msgRawTextOutOther =
                    (RawTextOutgoingMessage)OutgoingMessagesFactory.Create(OutgoingMessageType.RAW_TEXT);
                msgRawTextOutOther.Channel = PredefinedChannel.CHAT_LOCAL;
                msgRawTextOutOther.Color = PredefinedColor.Blue1;
                msgRawTextOutOther.Text = Name + " follows you...";
                enImpl.PutMessageIntoMyQueue(msgRawTextOutOther);
            }
            else
            {
                msgRawTextOutMe.Color = PredefinedColor.Red2;
                msgRawTextOutMe.Text = "You can't follow " + enImpl.Name;
                PutMessageIntoMyQueue(msgRawTextOutMe);
            }
        }
示例#5
0
 private void removeFollower(EntityImplementation en)
 {
     if (followers.Contains(en))
         followers.Remove(en);
 }
示例#6
0
        private bool addFollower(EntityImplementation follower)
        {
            if (follower.isFollowedByEntities)
                return false;

            if (!followers.Contains(follower))
                followers.Add(follower);

            return true;
        }
示例#7
0
        private void removeEntityImplementationFromWorld(EntityImplementation enImpl)
        {
            // Basic implementation check
            if (!(enImpl is PlayerCharacter) && !(enImpl is ServerCharacter))
                throw new ArgumentException("Unknown type of EntityImplementation: " + enImpl.GetType().ToString());

            // Type specific remove operations
            if (enImpl is PlayerCharacter)
            {
                // Total active players
                activePlayerCharacters.Remove(enImpl as PlayerCharacter);

                // By Name dictionary
                if (loggedInPlayersByName.ContainsKey(enImpl.Name.ToLower()))
                    loggedInPlayersByName.Remove(enImpl.Name.ToLower());
            }

            if (enImpl is ServerCharacter)
            {
                // Total server characters
                activeServerCharacters.Remove(enImpl as ServerCharacter);
            }

            // By EntityID dictionary
            if (worldEntitiesByEntityID.ContainsKey(enImpl.EntityID))
                worldEntitiesByEntityID.Remove(enImpl.EntityID);

            // Cancel time based actions
            enImpl.TimeBasedActionCancelExecuted();

            // Remove from current map
            enImpl.LocationLeaveMapAtExitWorld();

            // Stop following
            enImpl.FollowingStopFollowing();

            enImpl.TimeBasedActionConnectToManager(null);
            enImpl.LocationSetMapManager(null);
        }
示例#8
0
        private void addEntityImplementationToWorld(EntityImplementation enImpl)
        {
            // Basic implementation check
            if (!(enImpl is PlayerCharacter) && !(enImpl is ServerCharacter))
                throw new ArgumentException("Unknown type of EntityImplementation: " + enImpl.GetType().ToString());

            // Type specific test operations
            if (enImpl is PlayerCharacter)
            {
                if (loggedInPlayersByName.ContainsKey(enImpl.Name.ToLower()))
                    // This should not happen. It should be checked before making login successful
                    throw new InvalidOperationException("Player is already in 'by name' dictionary!");
            }

            if (enImpl is ServerCharacter)
            {
                if (activeServerCharacters.Contains(enImpl as ServerCharacter))
                    // This should not happen unless bug in script logic.
                    throw new InvalidOperationException("Server character " + enImpl.Name + " already on the list of active characters!");
            }

            // Searching for the next free entityID
            for (UInt16 i = 1; i < UInt16.MaxValue; i++)
                if (!worldEntitiesByEntityID.ContainsKey(i))
                {
                    enImpl.EntityID = i;
                    worldEntitiesByEntityID[i] = enImpl;
                    break;
                }

            if (enImpl.EntityID == 0)
                throw new InvalidOperationException("Could not allocate entityID to entity.");

            // Connect entity to time based actions manager
            enImpl.TimeBasedActionConnectToManager(timeBasedActionsManager);

            // Connecct entity to map manager
            enImpl.LocationSetMapManager(mapManager);

            // Type specific final operations
            if (enImpl is PlayerCharacter)
            {
                loggedInPlayersByName[enImpl.Name.ToLower()] = (enImpl as PlayerCharacter);
            }

            if (enImpl is ServerCharacter)
            {
                activeServerCharacters.Add(enImpl as ServerCharacter);
            }
        }
        private bool combatIsInDistanceToAttack(EntityImplementation defender)
        {
            double distance = Double.MaxValue;
            DistanceCalculationResult result = getDistanceToEntity(defender, out distance);

            if (result != DistanceCalculationResult.CALC_OK)
                return false;

            // TODO: allowed distance is based on weapon type
            if (distance > 3.0)
                return false;

            return true;
        }
        private ushort combatGetPenalizedDesenseSkillLevel(EntityImplementation defender)
        {
            ushort defenseSkillLevel =
                defender.skills.GetSkill(EntitySkillType.DefenseDodge).CurrentLevel;

            // Change defense level based on attackers count
            double penalty = 1.0 / (double)defender.CombatGetNumberOfAttackers();
            penalty += 0.4;
            if (penalty > 1.0) penalty = 1.0;
            if (penalty < 0.5) penalty = 0.5; // No less than 50%
            defenseSkillLevel = (ushort)(defenseSkillLevel * penalty);

            return defenseSkillLevel;
        }
        public void CombatInitiateAttack(EntityImplementation defender)
        {
            // Check if not me
            if (this == defender)
                return;

            // Check if not NPC
            if ((defender is ServerCharacter) &&
                ((defender as ServerCharacter).EntityImplementationKind == PredefinedEntityImplementationKind.ENTITY_NPC))
                return;

            // Check if entity is alive
            if (!defender.EnergiesIsAlive)
            {
                SendLocalChatMessage("It's already dead...", PredefinedColor.Red2);
                return;
            }

            // Check distance
            if (!combatIsInDistanceToAttack(defender))
            {
                SendLocalChatMessage("You need to get closer to attack...",
                                     PredefinedColor.Red2);
                return;
            }

            // Checks ok. Start attack for attacker.
            AttackTimeBasedAction attackDefender =
                new AttackTimeBasedAction(this, defender);
            attackDefender.Activate();

            // Start attack for defender only if it is not attacking already
            if (!defender.CombatIsAttacking)
            {
                AttackTimeBasedAction attackAttacker =
                    new AttackTimeBasedAction(defender, this);
                attackAttacker.Activate();
            }
        }
        /// <summary>
        /// Invoked on attacker
        /// </summary>
        /// <param name="defender">
        /// A <see cref="EntityImplementation"/>
        /// </param>
        public void CombatHitDefender(EntityImplementation defender)
        {
            // Send attacker animation frame
            SendAnimationCommand(combatGetAnimationForAttack());

            // If defender is not attacking, send 'pain' command
            if (!defender.CombatIsAttacking)
                defender.SendAnimationCommand(PredefinedActorCommand.pain1);

            // TODO: Use attack/defense descriptors in final implementation

            // Calculate damage
            int topDamageValue = 5 + skills.GetSkill(EntitySkillType.AttackUnarmed).CurrentLevel;
            defender.EnergiesUpdateHealth((short)(WorldRNG.Next(0,topDamageValue) * -1));

            // Award attack experience
            AttackActionDescriptor atckDescriptor = new AttackActionDescriptor(2000, 1000); //TODO: Time values are meaningless for now
            atckDescriptor.AddExperienceDescriptor(
                new ExperienceDescriptor(EntitySkillType.AttackUnarmed,
                    combatGetPenalizedDesenseSkillLevel(defender), 10));

            SkillsAwardExperience(atckDescriptor);
        }