public void TestInit() { world = new World(null, 0, new History()); combatant = new CombatantModel(0, "Combatant", "bar", new Vector3D(), Quaternion.Identity, 10, 10, EnumMobileState.Running, 2, 20, 20, 20, 20, 20); entity = new EntityModel(1, "Entity", "bar", new Vector3D(10, 10, 10), Quaternion.Identity, 10, 10, EnumMobileState.Standing, 2); }
public Party(string name, CombatantModel leader) { Contract.Requires<ArgumentNullException>(leader != null); Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(name)); Name = name; Leader = leader; }
public static void DoKick(CombatantModel source, EntityModel target) { //source.Kick(target); }
public static double GetCompetancy(CombatantModel combatant, Schema.EnumSkillRow skill) { Schema.MobileHasSkillRow mhs = Global.Schema.MobileHasSkill.FindByTemplateObjectIDEnumSkillID( // TODO: do we even want templates? //TemplateObjectId, combatant.Id, skill.EnumSkillID); if (mhs != null) return mhs.Rating; return 0; }
public static EntityModel DamagedBy(this EntityModel target, CombatantModel source, Schema.EnumSkillRow skill) { // TODO: use actual damage and hitroll float damage = skill.EnergyCost * 2; int hitroll = 80; // hit armor, or bypass armor // TODO: use armor rating if (Global.Rand.Next(hitroll) < 50) damage -= 8; // opponent.ArmorRating if (damage < 0) damage = 0; var opponent = target as CombatantModel; if (opponent != null) damage *= source.Strength / opponent.Constitution; target = target.WithHealthChange(-damage); if (target.MobileState != EnumMobileState.Dead && target.MobileState != EnumMobileState.Incapacitated && target.MobileState != EnumMobileState.Fighting) { target = target.WithState(EnumMobileState.Fighting); if (opponent != null && opponent.Target == null) target = opponent.WithTarget(source); } return target; }
public static EntityModel MagicallyDamagedBy(this EntityModel target, CombatantModel source, Schema.EnumSkillRow skill) { float damage = skill.EnergyCost * 2; damage += Math.Max(skill.AirAffinity * source.Affinity.Air / target.Affinity.Air, 0); damage += Math.Max(skill.EarthAffinity * source.Affinity.Earth / target.Affinity.Earth, 0); damage += Math.Max(skill.FireAffinity * source.Affinity.Fire / target.Affinity.Fire, 0); damage += Math.Max(skill.LifeAffinity * source.Affinity.Life / target.Affinity.Life, 0); damage += Math.Max(skill.WaterAffinity * source.Affinity.Water / target.Affinity.Water, 0); var opponent = target as CombatantModel; if (opponent != null) damage *= source.Cognition / opponent.Willpower; return target.WithHealthChange(-damage); }
public static bool Avoids(this EntityModel target, CombatantModel source, Schema.EnumSkillRow skill) { var opponent = target as CombatantModel; if (opponent == null || opponent != source) return false; else if ((EnumActivationType)skill.EnumActivationTypeID == EnumActivationType.Skill) // physical attack: ratio of Dexterity // 20% chance for equal dexterity player to avoid return (source.Dexterity == 0 || Global.Rand.Next(100) <= opponent.Dexterity / source.Dexterity * 20); else // magical attack: Dexterity return (Global.Rand.Next(100) <= opponent.Dexterity); }
public static void UseSkillNow(this World world, CombatantModel source, Schema.EnumSkillRow skill, EntityModel target) { if (source.MobileState == EnumMobileState.Dead || source.MobileState == EnumMobileState.Incapacitated) { world.LogMessage(source, "Unable to use " + skill.EnumSkillName + " while " + source.MobileState); return; } /* TODO: skill specific states if ( skill.EnumMobileState > caster.MobileState ) { caster.SendLog( "Not while " + caster.MobileState.Name ); } */ if ((source.Position - target.Position).Length > skill.Range) { world.LogMessage(source, target.Name + " is out of range"); return; } if (skill.EnergyCost > source.Energy) { world.LogMessage(source, "Not enough energy to use " + skill.EnumSkillName + ", requires " + skill.EnergyCost); return; } // deduct energy regardless // TODO: can remove the explicit cast here by using generics source = (CombatantModel)source.WithEnergyChange(-skill.EnergyCost); bool succeeds = source.Succeeds(skill); bool hits = source.Hits(target, skill); bool avoids = target.Avoids(source, skill); // successful casting affects affinity with the elements if (succeeds && hits && !avoids) { // TODO: can remove the explicit cast here by using generics source = (CombatantModel)source.WithAffinityChange( skill.AirAffinity / 1000f, skill.EarthAffinity / 1000f, skill.FireAffinity / 1000f, skill.LifeAffinity / 1000f, skill.WaterAffinity / 1000f); // TODO: just get the damage number instead?? switch ((EnumActivationType)skill.EnumActivationTypeID) { case EnumActivationType.AttackSpell: target = target.MagicallyDamagedBy(source, skill); break; case EnumActivationType.Enchantment: target = target.EnchantedBy(source, skill); break; case EnumActivationType.Glamour: source.Activates(skill, target); break; case EnumActivationType.HealingSpell: target = target.HealedBy(source, skill); break; case EnumActivationType.Skill: target = target.DamagedBy(source, skill); target = target.AffectedBy(source, skill); source.Activates(skill, target); break; case EnumActivationType.Sorcery: break; default: world.LogMessage(source, "That skill does not work yet, contact admin."); Log.Error("Unhandled activation type " + (EnumActivationType)skill.EnumActivationTypeID + " for skill " + skill.EnumSkillName); break; } } source = source.FinishSkill(); string description = avoids ? "Avoided" : !hits ? "Missed" : !succeeds ? "Failed" : "Success"; world.Apply(new SkillEvent(source, (EnumSkill)skill.EnumSkillID, target, succeeds, hits, avoids, description)); }
public void Add(CombatantModel member) { _members.Add(member.Id, member); }
void ProcessMessage(ClientConnection client, PossessMobile message) { var avatar = World.History.Head.Entities.ValueOrDefault(message.InstanceId); if (avatar != null) { // reconnected, replace existing connection with the new ClientConnection possessedBy; if (World.Possession.TryGetValue(avatar.Id, out possessedBy)) { if (possessedBy == client) { client.LogMessage("You already possess " + avatar); return; } else { _log.Info("Mobile " + avatar + " has been taken over by " + client); possessedBy.LogMessage("You lost control of " + avatar); possessedBy.Avatar = null; } } if (client.Avatar != null && client.Avatar.Id != avatar.Id) { // TODO: omg releasing this sends a combatant which crashes // release control of previous avatar //World.Possession.Remove(client.Avatar.Id); } World.Possession[avatar.Id] = client; client.Avatar = avatar; client.LogMessage("You are now controlling " + avatar); } else { // try to load the character avatar = World.LoadMobile(message.InstanceId); if (avatar == null) { _log.Warn("Character " + message.InstanceId + " not found."); //TODO: rely on world loading //client.Close(); //return; avatar = new CombatantModel( Global.Rand.Next(), client.AuthenticatedUsername, "RTSRobot", new Vector3D(), Quaternion.Identity, 100, 100, Common.EnumMobileState.Standing, 1.7f, 20, 20, 20, 20, 20); } World.Possession[avatar.Id] = client; client.Avatar = avatar; // try to add the character to the world World.Apply(new EntityUpdateEvent(avatar, "Loaded for possession")); } World.SendInitialWorldView(client); }
public CombatantModel WithTarget(CombatantModel target) { var r = (CombatantModel)MemberwiseClone(); r.Target = target; return r; }