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); }
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; } }
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); } }
private void removeFollower(EntityImplementation en) { if (followers.Contains(en)) followers.Remove(en); }
private bool addFollower(EntityImplementation follower) { if (follower.isFollowedByEntities) return false; if (!followers.Contains(follower)) followers.Add(follower); return true; }
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); }
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); }