public override void RunAction() { MechanicsContext.Data data = ElementsContext.GetData <MechanicsContext.Data>(); MechanicsContext mechanicsContext = (data != null) ? data.Context : null; if (mechanicsContext == null) { Main.Logger?.Error("Unable to drop weapons: no context found"); return; } UnitEntityData unit = mechanicsContext.MaybeCaster; if (unit == null) { Main.Logger?.Error("Unable to drop weapons: caster is null"); } if (unit.Descriptor.IsPet || unit.Body.IsPolymorphed) { return; } var currentWeaponSet = unit.Body.CurrentHandsEquipmentSet; if (currentWeaponSet.PrimaryHand.CanDrop() || currentWeaponSet.SecondaryHand.CanDrop()) { unit.Commands.InterruptAll(); unit.Descriptor.Body.DropCurrentWeaponSet(); } }
private LevelUpController AddLevel(UnitDescriptor unit, Dictionary <SelectionEntry, HashSet <int> > selectionsHistory, HashSet <int> spellHistory) { LevelUpController levelUpController = LevelUpController.Start(unit, true, null, null, LevelUpState.CharBuildMode.LevelUp); if (levelUpController.State.CanSelectRace) { BlueprintRace race = unit.Progression.Race; DefaultBuildData data = ElementsContext.GetData <DefaultBuildData>(); if (data != null) { race = data.Race; } if (race != null) { levelUpController.SelectRace(race); } } if (levelUpController.State.CanSelectRaceStat) { levelUpController.SelectRaceStat(instance.RaceStat); } this.ApplyStatsDistributionPreset(levelUpController); if (unit.Progression.GetClassLevel(instance.CharacterClass) <= 0) { foreach (BlueprintArchetype archetype in instance.Archetypes) { levelUpController.AddArchetype(instance.CharacterClass, archetype); } } levelUpController.SelectClass(instance.CharacterClass, false); levelUpController.ApplyClassMechanics(); this.PerformSelections(levelUpController, selectionsHistory, new LevelUpActionPriority?(LevelUpActionPriority.ReplaceSpellbook)); levelUpController.ApplySpellbook(); while (levelUpController.State.AttributePoints > 0 && instance.LevelsStat.IsAttribute()) { levelUpController.SpendAttributePoint(instance.LevelsStat); } this.PerformSelections(levelUpController, selectionsHistory, new LevelUpActionPriority?(LevelUpActionPriority.ApplySkillPoints)); levelUpController.ApplySkillPoints(); while (levelUpController.State.SkillPointsRemaining > 0) { int skillPointsRemaining = levelUpController.State.SkillPointsRemaining; foreach (StatType skill in instance.Skills) { if (levelUpController.State.SkillPointsRemaining <= 0) { break; } levelUpController.SpendSkillPoint(skill); } if (skillPointsRemaining == levelUpController.State.SkillPointsRemaining) { break; } } this.PerformSelections(levelUpController, selectionsHistory, null); this.PerformSpellSelections(levelUpController, spellHistory); return(levelUpController); }
private int DealHitPointsDamage(ContextActionDealDamage2.DamageInfo info) { if (this.Context.MaybeCaster == null) { UberDebug.LogError(this, (object)"Caster is missing", (object[])Array.Empty <object>()); return(0); } BaseDamage damage1 = this.DamageType.GetDamageDescriptor(info.Dices, info.Bonus).CreateDamage(); damage1.EmpowerBonus = !info.Empower ? damage1.EmpowerBonus : 1.5f; damage1.Maximized = info.Maximize || damage1.Maximized; BaseDamage baseDamage = damage1; DamageCriticalModifierType?criticalModifier = info.CriticalModifier; int?critModifier = criticalModifier.HasValue ? new int?(criticalModifier.GetValueOrDefault().IntValue()) : new int?(); baseDamage.CriticalModifier = critModifier; damage1.Half = this.Half; damage1.AlreadyHalved = info.PreRolledValue.HasValue && this.Half && this.AlreadyHalved; damage1.PreRolledValue = info.PreRolledValue; if (this.IsAoE && !info.PreRolledValue.HasValue) { int?nullable2 = this.Context.AoEDamage.Get <ContextActionDealDamage, int?>(this, new int?()); if (nullable2.HasValue) { damage1.PreRolledValue = nullable2; } } ContextAttackData data = ElementsContext.GetData <ContextAttackData>(); DamageBundle damage2 = (DamageBundle)damage1; damage2.Weapon = data?.AttackRoll?.Weapon; RuleDealDamage rule = new RuleDealDamage(this.Context.MaybeCaster, this.Target.Unit, damage2) { Projectile = data?.Projectile, AttackRoll = data?.AttackRoll, HalfBecauseSavingThrow = info.HalfBecauseSavingThrow, MinHPAfterDamage = !this.UseMinHPAfterDamage ? new int?() : new int?(this.MinHPAfterDamage), SourceAbility = this.Context.SourceAbility, SourceArea = this.Context.AssociatedBlueprint as BlueprintAbilityAreaEffect }; if (this.IsShadowEvocation) { RuleSavingThrow ruleSavingThrow = this.Context.TriggerRule(new RuleSavingThrow(this.Target.Unit, SavingThrowType.Will, this.Context.Params.DC)); rule.ReducedBecauseOfShadowEvocation = ruleSavingThrow.IsPassed; } if (this.IsShadowEvocationGreater) { RuleSavingThrow ruleSavingThrow = this.Context.TriggerRule(new RuleSavingThrow(this.Target.Unit, SavingThrowType.Will, this.Context.Params.DC)); rule.ReducedBecauseOfShadowEvocationGreater = ruleSavingThrow.IsPassed; } this.Context.TriggerRule <RuleDealDamage>(rule); if (this.IsAoE && !this.Context.AoEDamage.Get <ContextActionDealDamage, int?>(this, new int?()).HasValue) { this.Context.AoEDamage[this] = new int?(rule.Calculate.CalculatedDamage.FirstItem <DamageValue>().RolledValue); } return(rule.Damage); }
public override void OnEventDidTrigger(RuleAttackWithWeapon evt) { MechanicsContext context = ElementsContext.GetData <MechanicsContext.Data>()?.Context; if (evt.IsAttackOfOpportunity && (evt.Weapon.Blueprint.Category == WeaponCategory.Dagger || evt.Weapon.Blueprint.Category == WeaponCategory.Starknife) && evt.Target.Descriptor.HasFact(enemy_flag) && evt.AttackRoll.IsHit) { evt.Target.Descriptor.AddBuff(debuff, context, new TimeSpan?(4.Seconds())); } }
public override void RunAction() { MechanicsContext context = ElementsContext.GetData <MechanicsContext.Data>()?.Context; EnchantPoolDataDescription description = new EnchantPoolDataDescription(); if (context == null) { UberDebug.LogError((UnityEngine.Object) this, (object)"Unable to apply buff: no context found", (object[])Array.Empty <object>()); } else { Rounds rounds = this.DurationValue.Calculate(context); UnitEntityData maybeCaster = context.MaybeCaster; if (maybeCaster == null) { UberDebug.LogError((UnityEngine.Object) this, (object)"Can't apply buff: target is null", (object[])Array.Empty <object>()); } else { maybeCaster.Ensure <UnitPartEnchantPoolData>().ClearEnchantPool(this.EnchantPool); ItemEntity itemEntity = maybeCaster.Body.PrimaryHand.HasWeapon ? (ItemEntity)maybeCaster.Body.PrimaryHand.MaybeWeapon : (ItemEntity)maybeCaster.Body.EmptyHandWeapon; if (itemEntity == null) { return; } int num1 = 0; int groupSize = maybeCaster.Descriptor.Progression.Features.GetRank(Feature); description.EnchantedItem = itemEntity; description.EnchantPool = this.EnchantPool; if (itemEntity.Enchantments.Any <ItemEnchantment>()) { foreach (WeaponEnhancementBonus enhancementBonus in itemEntity.Enchantments.SelectMany <ItemEnchantment, WeaponEnhancementBonus>((Func <ItemEnchantment, IEnumerable <WeaponEnhancementBonus> >)(e => e.SelectComponents <WeaponEnhancementBonus>()))) { num1 += enhancementBonus.EnhancementBonus; } } foreach (AddBondProperty selectFactComponent in maybeCaster.Buffs.SelectFactComponents <AddBondProperty>()) { if (selectFactComponent.EnchantPool == this.EnchantPool && !itemEntity.HasEnchantment(selectFactComponent.Enchant)) { groupSize -= selectFactComponent.Enchant.EnchantmentCost; description.Enchantments.Add(itemEntity.AddEnchantment(selectFactComponent.Enchant, context, new Rounds?(rounds))); } } int num2 = Math.Min(Math.Max(0, 5 - num1), groupSize); if (num2 > 0) { description.Enchantments.Add(itemEntity.AddEnchantment(this.DefaultEnchantments[num2 - 1], context, new Rounds?(rounds))); } maybeCaster.Ensure <UnitPartEnchantPoolData>().RecordEnchantPool(description); } } }
public override void OnEventDidTrigger(RuleAttackWithWeapon evt) { MechanicsContext context = ElementsContext.GetData <MechanicsContext.Data>()?.Context; if (this.Owner.Body.PrimaryHand.MaybeWeapon != null && (this.Owner.Body.PrimaryHand.MaybeWeapon.Blueprint.Category == WeaponCategory.Dagger || this.Owner.Body.PrimaryHand.MaybeWeapon.Blueprint.Category == WeaponCategory.Starknife) && this.Owner.Unit.CombatState.IsEngage(evt.Initiator)) { if (this.Owner.Resources.GetResourceAmount(Swashbuckler.panache_resource) > 0 && evt.Target.CombatState.AttackOfOpportunityCount > 0) { this.Owner.Resources.Spend(Swashbuckler.panache_resource, 1); evt.Initiator.Descriptor.AddBuff(enemy_flag, context, new TimeSpan?(1.Seconds())); Game.Instance.CombatEngagementController.ForceAttackOfOpportunity(this.Owner.Unit, evt.Initiator); } } }
static public bool Prefix(ContextActionKnockdownTarget __instance) { var context = ElementsContext.GetData <MechanicsContext.Data>()?.Context; if (context == null) { return(true); } if (context?.AssociatedBlueprint is BlueprintBuff) { return(true); } var unit = ElementsContext.GetData <MechanicsContext.Data>()?.CurrentTarget?.Unit; if (unit == null) { return(true); } context = ShadowSpells.extractMainContext(context, context?.MaybeCaster); if (context == null) { return(true); } if (!unit.Ensure <UnitPartDisbelief>().attemptedDisbelief(context)) { if (unit.Descriptor.State.HasCondition(UnitCondition.TrueSeeing)) { unit.Ensure <UnitPartDisbelief>().register(context, true); } else { unit.Ensure <UnitPartDisbelief>().register(context, ShadowSpells.makeDisbeliefSave(context, unit)); } } if (unit.Ensure <UnitPartDisbelief>().disbelieved(context)) { int illusion_reality = ShadowSpells.getSpellReality(context); int result = RulebookEvent.Dice.D(new DiceFormula(1, DiceType.D100)); if (illusion_reality > 0 && result > illusion_reality) { Common.AddBattleLogMessage(unit.CharacterName + " avoids " + context.SourceAbility.Name + $" effect due to disbelief (rolled {result} vs {illusion_reality}%)"); return(false); } } return(true); }
public override void OnTurnOff() { Main.logger.Log("AddSacredWordBonus OnTurnOff"); MechanicsContext context = ElementsContext.GetData <MechanicsContext.Data>()?.Context; EnchantPoolDataDescription description = new EnchantPoolDataDescription(); if (context == null) { UberDebug.LogError((UnityEngine.Object) this, (object)"Unable to apply buff: no context found", (object[])Array.Empty <object>()); } else { UnitEntityData maybeCaster = context.MaybeCaster; maybeCaster.Remove <UnitPartEnchantPoolData>(); } }
internal static void TestDefaultLevelPlan3() { var defaultClass = ResourcesLibrary.TryGetBlueprint <BlueprintCharacterClass>("0937bec61c0dabc468428f496580c721"); //Alchemist var defaultBuild = defaultClass.DefaultBuild; //Note: DefaultPlayerCharacter is StartGame_Player_Unit 4391e8b9afbb0cf43aeba700c089f56d //CustomCompanion is CustomCompanion baaff53a675a84f4983f1e2113b24552 UnitEntityData unitData = Main.settings.DefaultPointBuy25 ? Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.DefaultPlayerCharacter) : Game.Instance.CreateUnitVacuum(BlueprintRoot.Instance.CustomCompanion); var unit = unitData.Descriptor; var race = ResourcesLibrary.TryGetBlueprint <BlueprintRace>("0a5d473ead98b0646b94495af250fdc4"); //Human race = ResourcesLibrary.TryGetBlueprint <BlueprintRace>("5c4e42124dc2b4647af6e36cf2590500"); //Tiefling unit.Progression.SetRace(race); //DefaultBuildData sets a global variable DefaultBuildData that is used by AddClassLevels to determine the race to use //If race is not set, it defaults to unit.Progression.Race; using (new DefaultBuildData(race)) { DefaultBuildData data = ElementsContext.GetData <DefaultBuildData>(); Main.Log($"Default Build Data {data.Race.name}"); unit.Ensure <LevelUpPlanUnitHolder>(); unit.Progression.DropLevelPlans(); unit.AddFact(defaultBuild, null, null); var levelPlanHolder = new LevelPlanHolder(); for (int i = 0; i < 20; i++) { var plan = unit.Progression.GetLevelPlan(i + 1); levelPlanHolder.LevelPlanData[i] = plan; } var levelPlan = unit.Progression.GetLevelPlan(1); var stats = levelPlan.Actions.Select(action => { if (action is AddStatPoint add) { return(1); } if (action is RemoveStatPoint) { return(-1); } return(0); }).Sum(); Main.Log($"Added {stats} points"); LevelPlanManager.CurrentLevelPlan = levelPlanHolder; } }
public override void RunAction() { MechanicsContext context = ElementsContext.GetData <MechanicsContext.Data>()?.Context; if (context == null) { UberDebug.LogError((UnityEngine.Object) this, (object)"Unable to apply buff: no context found", (object[])Array.Empty <object>()); } else { UnitEntityData caster = context.MaybeCaster; UnitEntityData target = this.Target.Unit; if (caster != null && target != null) { caster.Descriptor.Ensure <UnitPartStudiedTarget>().SetTarget(target.Descriptor); } } }
private void LevelUp(UnitDescriptor unit, int levels, bool fromFact) { using (new IgnorePrerequisites()) { ClassLevelLimit component = unit.Blueprint.GetComponent <ClassLevelLimit>(); int classLevelLimit = component == null ? int.MaxValue : component.LevelLimit; if (ElementsContext.GetData <DefaultBuildData>() != null) { classLevelLimit = 0; } Dictionary <SelectionEntry, HashSet <int> > selectionsHistory = new Dictionary <SelectionEntry, HashSet <int> >(); HashSet <int> spellHistory = (instance.SelectSpells.Length <= 0) ? null : new HashSet <int>(); for (int i = 0; i < levels; i++) { if (unit.Progression.CharacterLevel < classLevelLimit) { Main.Log($"A: Adding level {i} unitlevel {unit.Progression.CharacterLevel}"); this.AddLevel(unit, selectionsHistory, spellHistory); } else { Main.Log($"B: Adding level {i} unitlevel {unit.Progression.CharacterLevel}"); LevelUpPlanUnitHolder levelUpPlanUnitHolder = unit.Get <LevelUpPlanUnitHolder>(); if (levelUpPlanUnitHolder != null) { UnitDescriptor unitDescriptor = levelUpPlanUnitHolder.RequestPlan(); LevelUpController levelUpController = this.AddLevel(unitDescriptor, selectionsHistory, spellHistory); unit.Progression.AddLevelPlan(levelUpController.GetPlan()); } } } this.PrepareSpellbook(unit); unit.Progression.ReapplyFeaturesOnLevelUp(); UnitEntityView view = unit.Unit.View; if (view != null) { view.UpdateClassEquipment(); } RestController.ApplyRest(unit); } }
public override void RunAction() { MechanicsContext.Data data = ElementsContext.GetData <MechanicsContext.Data>(); MechanicsContext mechanicsContext = (data != null) ? data.Context : null; if (mechanicsContext == null) { Main.logger.Log("Unable to toggle weapon: no context found"); return; } UnitEntityData unitEntityData = mechanicsContext.MaybeCaster; if (unitEntityData == null) { Main.logger.Log("Can't toggle weapon: target is null"); return; } ItemEntityWeapon weapon = main_hand ? unitEntityData.Body.PrimaryHand.MaybeWeapon : unitEntityData.Body.SecondaryHand.MaybeWeapon; toggleThrown(weapon, unitEntityData); }
public override void RunAction() { //Main.DebugLog($"[ActionDealDamage2] Target:{Target?.Unit?.CharacterName} AC:{Target?.Unit?.Stats?.AC?.ModifiedValue} Flat-AC:{Target?.Unit?.Stats?.AC?.FlatFooted} Touch-AC:{Target?.Unit?.Stats?.AC?.Touch} Caster:{Context?.MaybeCaster?.CharacterName}"); //Main.DebugLog("Context[0] " + this.Context[AbilityRankType.Default].ToString()); //AbilityRankType.DamageDice [1] //AbilitySharedValue.Damage [0] //AbilitySharedValue.Duration [2] only composite //for (int i = 0; i < 7; i++) //{ // Main.DebugLog("AbilitySharedValue:" + Context[(AbilitySharedValue)i].ToString()); //} //for (int i = 0; i < 7; i++) //{ // Main.DebugLog("AbilityRankType:" + Context[(AbilityRankType)i].ToString()); //} if (this.Target.Unit == null) { UberDebug.LogError(this, "Invalid target for effect '{0}'", this.GetType().Name); } else if (this.Context.MaybeCaster == null) { UberDebug.LogError(this, "Invalid caster for effect '{0}'", this.GetType().Name); } else { bool saveSuccess = this.Context.SavingThrow != null && (this.Context.SavingThrow.IsPassed || this.Context.SavingThrow.ImprovedEvasion) && this.HalfIfSaved; if (saveSuccess && this.Context.SavingThrow.Evasion && this.Context.SavingThrow.IsPassed) { EventBus.RaiseEvent <IUnitEvasionHandler>(h => h.HandleEffectEvaded(this.Target.Unit, this.Context)); } else { RuleAttackRoll attackRoll; if (WeaponOverride != null) { attackRoll = new RuleAttackRoll(Context.MaybeCaster, this.Target.Unit, WeaponOverride, 0); if (this.Context[AbilitySharedValue.Heal] == 0) // if this is the first attack this context { this.Context.TriggerRule(attackRoll); this.Context[AbilitySharedValue.Heal] = attackRoll.Roll; // save this for other targets } else { //attackRoll.ImmuneToCriticalHit = true; // only the first target may get a crit attackRoll.SuspendCombatLog = true; // don't print, since the roll would be different this.Context.TriggerRule(attackRoll); } int d20 = this.Context[AbilitySharedValue.Heal]; // result of attack roll Main.DebugLog($"Attack:{d20} total:{d20 + attackRoll.AttackBonus} AC:{attackRoll.TargetAC} result:{attackRoll.Result.ToString()}"); if (attackRoll.Result == AttackResult.MirrorImage) { // battlelog notification that Mirror Image was hit? attackRoll.ConsumeMirrorImageIfNecessary(); return; } if (!this.IsSuccessRoll(d20, attackRoll.AttackBonus, attackRoll.TargetAC)) { return; } if (attackRoll.Result == AttackResult.Concealment) { // battlelog notification that concealment prevented hit Kingmaker.Game.Instance.UI.BattleLogManager.LogView.AddLogEntry(attackRoll.AttackLogEntry); return; } } else { attackRoll = ElementsContext.GetData <ContextAttackData>()?.AttackRoll; } ContextActionDealDamage2.DamageInfo info = new ContextActionDealDamage2.DamageInfo() { Dices = new DiceFormula(this.Value.DiceCountValue.Calculate(this.Context), this.Value.DiceType), Bonus = this.Value.BonusValue.Calculate(this.Context), PreRolledValue = !this.ReadPreRolledFromSharedValue ? new int?() : new int?(this.Context[this.PreRolledSharedValue]), HalfBecauseSavingThrow = saveSuccess, Empower = this.Context.HasMetamagic(Metamagic.Empower), Maximize = this.Context.HasMetamagic(Metamagic.Maximize), CriticalModifier = this.IgnoreCritical || attackRoll == null || !attackRoll.IsCriticalConfirmed ? new DamageCriticalModifierType?() : new DamageCriticalModifierType?(this.AbilityContext == null ? attackRoll.Weapon.Blueprint.CriticalModifier : DamageCriticalModifierType.X2) }; int num; switch (this.M_Type) { case ContextActionDealDamage2.Type.Damage: num = this.DealHitPointsDamage(info); break; case ContextActionDealDamage2.Type.AbilityDamage: num = this.DealAbilityScoreDamage(info); break; case ContextActionDealDamage2.Type.EnergyDrain: num = this.DrainEnergy(info); break; default: throw new ArgumentOutOfRangeException(); } if (this.WriteResultToSharedValue) { this.Context[this.ResultSharedValue] = num; } if (!this.WriteCriticalToSharedValue || attackRoll == null || !attackRoll.IsCriticalConfirmed) { return; } this.Context[this.CriticalSharedValue] = 1; } } }
static bool Prefix(Demoralize __instance) { var tr = Harmony12.Traverse.Create(__instance); var target = tr.Property("Target").GetValue <TargetWrapper>(); MechanicsContext.Data data = ElementsContext.GetData <MechanicsContext.Data>(); MechanicsContext mechanicsContext = (data != null) ? data.Context : null; UnitEntityData unitEntityData = (mechanicsContext != null) ? mechanicsContext.MaybeCaster : null; if (unitEntityData == null || !target.IsUnit) { UberDebug.LogError(__instance, "Unable to apply buff: no context found", Array.Empty <object>()); return(false); } int num = 10 + target.Unit.Descriptor.Progression.CharacterLevel + target.Unit.Stats.Wisdom.Bonus; ModifiableValue.Modifier modifier = null; try { if (__instance.DazzlingDisplay && unitEntityData.Descriptor.State.Features.SwordlordWeaponProwess) { int num2 = 0; foreach (var feature in unitEntityData.Descriptor.Progression.Features) { var param = feature.Param; bool flag; if (param == null) { flag = false; } else { WeaponCategory?weaponCategory = param.WeaponCategory; WeaponCategory weaponCategory2 = WeaponCategory.DuelingSword; flag = (weaponCategory.GetValueOrDefault() == weaponCategory2 & weaponCategory != null); } if (flag) { num2++; } } modifier = unitEntityData.Stats.CheckIntimidate.AddModifier(num2, null, ModifierDescriptor.None); } var ruleSkillCheck = new RuleSkillCheck(unitEntityData, StatType.CheckIntimidate, num); var demoralize_bonus_part = mechanicsContext.MaybeCaster.Get <UnitPartDemoralizeBonus>(); if (demoralize_bonus_part != null) { ruleSkillCheck.Bonus.AddModifier(demoralize_bonus_part.getBonus(), null, ModifierDescriptor.UntypedStackable); } ruleSkillCheck = mechanicsContext.TriggerRule <RuleSkillCheck>(ruleSkillCheck); if (ruleSkillCheck.IsPassed) { int num3 = 1 + (ruleSkillCheck.RollResult - num) / 5 + (unitEntityData.Descriptor.State.Features.FrighteningThug ? 1 : 0); if (unitEntityData.Descriptor.State.Features.FrighteningThug && num3 >= 4) { target.Unit.Descriptor.AddBuff(__instance.GreaterBuff, mechanicsContext, new TimeSpan?(1.Rounds().Seconds)); } Buff buff = target.Unit.Descriptor.AddBuff(__instance.Buff, mechanicsContext, new TimeSpan?(num3.Rounds().Seconds)); if (unitEntityData.Descriptor.HasFact(__instance.ShatterConfidenceFeature) && buff != null) { Buff fact = target.Unit.Descriptor.AddBuff(__instance.ShatterConfidenceBuff, mechanicsContext, new TimeSpan?(num3.Rounds().Seconds)); buff.StoreFact(fact); } unitEntityData.Get <UnitPartActionOnDemoralize>()?.runActions(mechanicsContext, target.Unit, num, ruleSkillCheck.RollResult); var scoped_actions = (mechanicsContext?.SourceAbility?.GetComponents <ScopedDemoralizeActions>()).EmptyIfNull(); foreach (var s in scoped_actions) { s.actions.Run(); } } } finally { if (modifier != null) { modifier.Remove(); } } return(false); }