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)); }