protected override void copyExtendedProperties(ItemModel sourceItemModel) { EquipmentItemModel equipmentItemModel = sourceItemModel as EquipmentItemModel; if (equipmentItemModel == null) { throw new InvalidCastException("Invalid type."); } EquipmentType = equipmentItemModel.EquipmentType; MaxHealthBoost = equipmentItemModel.MaxHealthBoost; HealthRegenBoost = equipmentItemModel.HealthRegenBoost; MaxManaBoost = equipmentItemModel.MaxManaBoost; ArmorBoost = equipmentItemModel.ArmorBoost; SpellResistBoost = equipmentItemModel.SpellResistBoost; MeleeDamageBoost = equipmentItemModel.MeleeDamageBoost; MeleeCritBoost = equipmentItemModel.MeleeCritBoost; SpellDamageBoost = equipmentItemModel.SpellDamageBoost; SpellCritBoost = equipmentItemModel.SpellCritBoost; if (equipmentItemModel.AbilityItemModels == null) { AbilityItemModels = null; } else { AbilityItemModels = new AbilityItemModel[equipmentItemModel.AbilityItemModels.Length]; for (int i = 0; i < AbilityItemModels.Length; i++) { AbilityItemModels[i] = new AbilityItemModel(); AbilityItemModels[i].CopyFrom(equipmentItemModel.AbilityItemModels[i], true); } } }
protected override void determineAbilityAndTargets(AbilityItemModel[] availableAbilityItemModels, ref AbilityItemModel chosenAbilityItemModel, ref int chosenAbilityIndex, ref List <CombatantModel> chosenTargets) { chosenAbilityItemModel = null; for (int i = 0; i < availableAbilityItemModels.Length; i++) { if (availableAbilityItemModels[i] == null) { continue; } if (availableAbilityItemModels[i].AbilityTargetType == AbilityTargetType.EnemySingle) { chosenAbilityItemModel = availableAbilityItemModels[i]; chosenAbilityIndex = i; } } if (chosenAbilityItemModel != null) { for (int i = 0; i < enemies.Count; i++) { if (enemies[i].IsAlive()) { chosenTargets.Add(enemies[0]); return; } } } }
private AbilityItemModel[] getRandomNPCAbilities(int numAbilities, int level) { List <AbilityItemModel> randomAbilitiesList = new List <AbilityItemModel>(); List <ItemModel> allAbilities = catalogModel.GetAllItemsOfType <AbilityItemModel>(); for (int i = 0; i < numAbilities; i++) { AbilityItemModel randomAbility = allAbilities[RandomGen.GetIntRange(0, allAbilities.Count - 1)] as AbilityItemModel; if (!randomAbilitiesList.Contains(randomAbility)) { randomAbilitiesList.Add(randomAbility); } } AbilityItemModel[] randomAbilitiesArray = new AbilityItemModel[randomAbilitiesList.Count]; for (int j = 0; j < randomAbilitiesArray.Length; j++) { AbilityItemModel clone = new AbilityItemModel(); clone.CopyFrom(randomAbilitiesList[j], false); clone.Level_ZeroBased = level; randomAbilitiesArray[j] = clone; } return(randomAbilitiesArray); }
/// <summary> /// Merges equippedAbilities with any abilities provided by specified equipment. /// </summary> /// <param name="equippedAbilities">Abilities the CombatantModel has equipped</param> /// <param name="equipmentItemModels">Any equipment the CombatantModel is wearing</param> /// <returns></returns> private static AbilityItemModel[] mergeAbilities(AbilityItemModel[] equippedAbilities, EquipmentItemModel[] equipmentItemModels) { int equippedAbilitiesCount = equippedAbilities == null ? 0 : equippedAbilities.Length; int equipmentAbilitiesCount = 0; for (int i = 0; i < equipmentItemModels.Length; i++) { if (equipmentItemModels[i].AbilityItemModels != null) { equipmentAbilitiesCount += equipmentItemModels[i].AbilityItemModels.Length; } } AbilityItemModel[] mergedAbilities = new AbilityItemModel[equippedAbilitiesCount + equipmentAbilitiesCount]; int mergeIndex = 0; for (mergeIndex = 0; mergeIndex < equippedAbilitiesCount; mergeIndex++) { mergedAbilities[mergeIndex] = equippedAbilities[mergeIndex]; } mergeIndex++; for (int e = 0; e < equipmentItemModels.Length; e++) { if (equipmentItemModels[e].AbilityItemModels != null) { for (int ea = 0; ea < equipmentItemModels[e].AbilityItemModels.Length; ea++) { mergedAbilities[mergeIndex++] = equipmentItemModels[e].AbilityItemModels[ea]; } } } return(mergedAbilities); }
public int GetStatModifiedAbilityTotalCastTurns(int abilityIndex) { AbilityItemModel abilityItemModel = AbilityItemModels[abilityIndex]; float deltaRatio = 1f + (float)StatModifiersDeltas.AbilityCastTurnsPercentModifierDelta * .01f; int modifiedCastTurns = (int)(((float)abilityItemModel.CastTurns) * deltaRatio); return(modifiedCastTurns < 1 ? 1 : modifiedCastTurns); }
private static AbilityItemModel parseAbilityItemModel(string customData, IJsonParser jsonParser) { AbilityItemModel abilityItemModel = new AbilityItemModel(); AbilityItemModelRaw abilityItemModelRaw = jsonParser.DeserializeObject <AbilityItemModelRaw>(customData); abilityItemModelRaw.ApplyToAbilityItemModel(abilityItemModel, jsonParser); return(abilityItemModel); }
public override void QueueAbility(AbilityItemModel abilityItemModel, int[] combatantIDs) { if (castingAbilityItemModel != null || nextAbilityItemModel != null) { // Ignore if ability is already queued Logging.Log.Info("An ability is already queued for player with combatant ID: " + ownerCombatantModel.ID + ", ignoring."); return; } nextAbilityItemModel = abilityItemModel; int abilityIndex = ownerCombatantModel.GetAbilityIndex(abilityItemModel.ID); nextTargetCombatants.Clear(); for (int i = 0; i < combatantIDs.Length; i++) { CombatantModel targetCombatantModel = null; if (combatantIDsToModels.TryGetValue(combatantIDs[i], out targetCombatantModel)) { // Ignore if ability is still cooling down if (ownerCombatantModel.GetStatModifiedAbilityCoolDownTurnsRemaining(abilityIndex) > 0) { Logging.Log.Info("Ability with ID: " + abilityItemModel.ID + " is cooling down, ignoring."); continue; } // Ignore if combatant is already dead if (!targetCombatantModel.IsAlive()) { Logging.Log.Info("Specified target with combatant ID: " + targetCombatantModel.ID + " is dead, ignoring"); continue; } bool isAbilityFriendly = abilityItemModel.IsFriendly(); // Ignore if attempting to cast friendly ability on enemy if (isAbilityFriendly && !allies.Contains(targetCombatantModel)) { Logging.Log.Info("Can't apply friendly ability with ID " + abilityItemModel.ID + " to an enemy, ignoring."); continue; } // Ignore if attempting to cast offensive ability on ally if (!isAbilityFriendly && !enemies.Contains(targetCombatantModel)) { Logging.Log.Info("Can't apply offensive ability with ID " + abilityItemModel.ID + " to an ally, ignoring."); continue; } nextTargetCombatants.Add(targetCombatantModel); } else { // Ignore if invalid combatant ID specified. Logging.Log.Info("Invalid combatant ID specified: " + combatantIDs[i] + ", ignoring."); continue; } } }
public void ApplyToDurationData(AbilityDurationData abilityDurationData, AbilityItemModel parentAbility) { abilityDurationData.OriginAbilityID = parentAbility.ID; abilityDurationData.PerTickAmount = int.Parse(PerTickAmount); abilityDurationData.TurnsPerTick = int.Parse(TurnsPerTick); abilityDurationData.MaxTicks = int.Parse(MaxTicks); abilityDurationData.AbilityEffectType = parentAbility.AbilityEffectType; abilityDurationData.AbilityTargetType = parentAbility.AbilityTargetType; }
private void onPlayerCombatAction(OperationRequest operationRequest, IClientConnection clientConnection, SendParameters sendParameters) { PlayerCombatActionRequest playerCombatActionRequest = PlayerCombatActionRequest.FromOperationRequest(operationRequest); ServerPlayerModel serverPlayerModel = clientConnectionToServerPlayerModel[clientConnection]; AbilityItemModel abilityItemModel = serverPlayerModel.CombatantModel.GetAbilityByID(playerCombatActionRequest.AbilityID); clientConnectionToServerPlayerModel[clientConnection].PlayerCombatBehaviour.QueueAbility( abilityItemModel, playerCombatActionRequest.TargetCombatantIDs); }
public int GetStatModifiedAbilityCoolDownTurnsRemaining(int abilityIndex) { AbilityItemModel abilityItemModel = AbilityItemModels[abilityIndex]; float deltaRatio = 1f + (float)StatModifiersDeltas.AbilityCoolDownTurnsPercentModifier * 0.01f; int totalCoolDownTurns = (int)(((float)abilityItemModel.CoolDownTurns) * deltaRatio); int turnsRemaining = totalCoolDownTurns - abilityItemModel.CoolDownTurnsElapsed; return(turnsRemaining < 0 ? 0 : turnsRemaining); }
public void Clear() { allies.Clear(); enemies.Clear(); combatantIDsToModels.Clear(); if (castingAbilityItemModel != null) { castingAbilityItemModel.NumCastTurnsElapsed = 0; if (castingAbilityItemModel.AbilityDurationData != null) { castingAbilityItemModel.AbilityDurationData.NumTurnsElapsed = 0; } castingAbilityItemModel = null; } targetCombatantModels.Clear(); ownerCombatantModel = null; }
public void ApplyToAbilityItemModel(AbilityItemModel abilityItemModel, IJsonParser jsonParser) { abilityItemModel.AbilityEffectType = (AbilityEffectType)int.Parse(AbilityEffectType); abilityItemModel.AbilityTargetType = (AbilityTargetType)int.Parse(AbilityTargetType); abilityItemModel.AbilityDurationType = (AbilityDurationType)int.Parse(AbilityDurationType); abilityItemModel.CastTurns = int.Parse(CastTurns); abilityItemModel.CoolDownTurns = int.Parse(CoolDownTurns); abilityItemModel.ImmediateAmout = int.Parse(ImmediateAmout); abilityItemModel.IsSpellBased = int.Parse(IsSpellBased) == 1; AbilityDurationDataRaw abilityDurationDataRaw = string.IsNullOrEmpty(AbilityDurationData) ? null : jsonParser.DeserializeObject <AbilityDurationDataRaw>(AbilityDurationData); if (abilityDurationDataRaw != null) { abilityItemModel.AbilityDurationData = new AbilityDurationData(); abilityDurationDataRaw.ApplyToDurationData(abilityItemModel.AbilityDurationData, abilityItemModel); } }
protected override void determineAbilityAndTargets(AbilityItemModel[] availableAbilityItemModels, ref AbilityItemModel chosenAbilityItemModel, ref int chosenAbilityIndex, ref List <CombatantModel> chosenTargets) { if (nextAbilityItemModel == null) { return; } chosenAbilityItemModel = nextAbilityItemModel; nextAbilityItemModel = null; bool isAbilityValid = false; for (int a = 0; a < availableAbilityItemModels.Length; a++) { if (availableAbilityItemModels[a] == null) { continue; } if (chosenAbilityItemModel.ID == availableAbilityItemModels[a].ID) { isAbilityValid = true; chosenAbilityIndex = a; break; } } if (!isAbilityValid) { Logging.Log.Info("Player specified invalid ID. CombatantID: " + ownerCombatantModel.ID + ", AbilityID: " + chosenAbilityItemModel.ID); chosenAbilityItemModel = null; return; } for (int i = 0; i < nextTargetCombatants.Count; i++) { chosenTargets.Add(nextTargetCombatants[i]); } nextTargetCombatants.Clear(); }
public void FromObjectArray(object[] properties) { int i = 0; ID = (int)properties[i++]; Level = (int)properties[i++]; CurrentHealth = (int)properties[i++]; MaxHealth = (int)properties[i++]; HealthRegenPerTurn = (int)properties[i++]; CurrentMana = (int)properties[i++]; MaxMana = (int)properties[i++]; ManaRegenPerTurn = (int)properties[i++]; Armor = (int)properties[i++]; SpellResist = (int)properties[i++]; MeleeDamage = (int)properties[i++]; MeleeCritChanceNormalized = (float)properties[i++]; SpellDamage = (int)properties[i++]; SpellCritChanceNormalized = (float)properties[i++]; TeamID = (int)properties[i++]; object[] statModifierAbDurs = properties[i++] as object[]; StatModifierAbilityDurations.FromObjectArray(statModifierAbDurs); object[] regenOverTimeAbDurs = properties[i++] as object[]; RegenOverTimeAbilityDurations.FromObjectArray(regenOverTimeAbDurs); object[] damageOverTimeAbDurs = properties[i++] as object[]; DamageOverTimeAbilityDurations.FromObjectArray(damageOverTimeAbDurs); object[] serializedAbilities = properties[i++] as object[]; AbilityItemModel[] parsedAbilities = new AbilityItemModel[serializedAbilities.Length]; for (int j = 0; j < parsedAbilities.Length; j++) { parsedAbilities[j] = new AbilityItemModel(); parsedAbilities[j].FromObjectArray(serializedAbilities[j] as object[]); } AbilityItemModels = parsedAbilities; }
protected override void getPlayerModelByID(PlayerAuthenticationModel playerAuthModel, PlayerCombatBehaviourBase playerCombatBehaviourBase, Action <ServerPlayerModel> onSuccessHandler, Action onFailureHandler) { if (playerAuthModel.UserID == "testFail") { onFailureHandler(); return; } ServerPlayerModel playerModel = new ServerPlayerModel(playerCombatBehaviourBase); playerModel.PlayerID = playerAuthModel.UserID; playerModel.Name = playerAuthModel.UserName; AbilityItemModel[] mockAbilities = new AbilityItemModel[] { MockCatalogService.FIREBALL_ABILITY }; playerModel.CombatantModel = new CombatantModel(1, 100, 1, 100, 1, 1, 1, 10, 0f, 10, 0f, PlayerModel.DEFAULT_TEAM_ID, mockAbilities); Task.Delay(100).ContinueWith(t => { onSuccessHandler(playerModel); }); }
private void parseEquipmentAndCombatantModel(ServerPlayerModel serverPlayerModel) { if (catalogModel == null) { catalogModel = DIContainer.GetInstanceByContextID <CatalogModel>(InstanceServerApplication.CONTEXT_ID); } // Parse equipment parseItemModel <EquipmentItemModel>(ref serverPlayerModel.EquippedWeaponItemModel, ref serverPlayerModel.EquippedWeapon); parseItemModel <EquipmentItemModel>(ref serverPlayerModel.EquippedOffHandItemModel, ref serverPlayerModel.EquippedOffHand); parseItemModel <EquipmentItemModel>(ref serverPlayerModel.EquippedArmorItemModel, ref serverPlayerModel.EquippedArmor); List <EquipmentItemModel> allEquipment = new List <EquipmentItemModel>(); if (serverPlayerModel.EquippedWeaponItemModel != null) { allEquipment.Add(serverPlayerModel.EquippedWeaponItemModel); } if (serverPlayerModel.EquippedOffHandItemModel != null) { allEquipment.Add(serverPlayerModel.EquippedOffHandItemModel); } if (serverPlayerModel.EquippedArmorItemModel != null) { allEquipment.Add(serverPlayerModel.EquippedArmorItemModel); } // Player must have at least 1 Ability AbilityItemModel[] equippedAbilityItemModels = new AbilityItemModel[serverPlayerModel.EquippedAbilities.Length]; for (int i = 0; i < equippedAbilityItemModels.Length; i++) { parseItemModel <AbilityItemModel>(ref equippedAbilityItemModels[i], ref serverPlayerModel.EquippedAbilities[i]); } serverPlayerModel.CombatantModel = BuildCombatantSCMD.Execute(serverPlayerModel.Level_ZeroBased, PlayerModel.DEFAULT_TEAM_ID, equippedAbilityItemModels, RarityType.Common, allEquipment.Count == 0 ? null : allEquipment.ToArray()); }
private void processCombatantBehaviour(CombatantModel combatantModel) { // Advance all ability cooldowns for (int i = 0; i < combatantModel.AbilityItemModels.Length; i++) { combatantModel.AbilityItemModels[i].CoolDownTurnsElapsed++; } AbilityItemModel combatAbility = null; targets.Clear(); CombatActionModel combatActionModel = combatantModelToBehaviour[combatantModel].GetCombatAction(out combatAbility, ref targets); // If waiting, return if (combatActionModel.CombatActionType == CombatActionType.Wait) { return; } // if starting or canceling cast, append CombatActionModel and return if (combatActionModel.CombatActionType == CombatActionType.StartCastingAbility || combatActionModel.CombatActionType == CombatActionType.CancelCastingAbility) { combatActionsCollection[combatantModel.ID].Add(combatActionModel); return; } if (combatActionModel.CombatActionType != CombatActionType.ApplyAbility) { throw new Exception("Unexpected CombatActionType: " + combatActionModel.CombatActionType.ToString()); } // Append cast completion CombatActionModel combatActionsCollection[combatantModel.ID].Add(combatActionModel); // Restart ability cooldown combatAbility.CoolDownTurnsElapsed = 0; // Apply ability to targets and keep track of CombatActionModels bool isAbilityFriendly = combatAbility.IsFriendly(); for (int t = 0; t < targets.Count; t++) { CombatActionModel combatActionOnTarget; if (combatAbility.AbilityDurationType == AbilityDurationType.Immediate) // Handle ability with IMMEDIATE effect. { bool isCrit; int immediateAmountWithStatMods = getAbilityAmountWithStatMods(combatantModel, combatAbility.ImmediateAmout, combatAbility.IsSpellBased, out isCrit); if (isAbilityFriendly) { combatActionOnTarget = applyRegenAbilityEffectToCombatant(combatAbility.AbilityEffectType, combatAbility.ID, combatantModel.ID, immediateAmountWithStatMods, targets[t], 0, isCrit); } else { combatActionOnTarget = applyDamageAbilityEffectToCombatant(combatAbility.AbilityEffectType, combatAbility.ID, combatantModel.ID, immediateAmountWithStatMods, targets[t], 0, isCrit); } } else // Handle ability with DURATION effect { AbilityDurationData abilityDurationDataClone = combatAbility.AbilityDurationData.Clone(true); if (combatAbility.IsStatModifier()) { // Stat modifiers don't consider other stat modifiers. Ex: (if target has spell effect/damage debuff from // another modifier, we dont want another spell dmg debuff to cause exponential damage). targets[t].StatModifiersDeltas.AddModifier(abilityDurationDataClone.PerTickAmount, abilityDurationDataClone.AbilityEffectType); targets[t].StatModifierAbilityDurations.Add(abilityDurationDataClone); CombatActionType combatActionType = isAbilityFriendly ? CombatActionType.StatIncreasedByDurationAbility : CombatActionType.StatDecreasedByDurationAbility; combatActionOnTarget = new CombatActionModel( combatantModel.ID, combatActionType, combatAbility.ID, targets[t].ID, abilityDurationDataClone.PerTickAmount, abilityDurationDataClone.NumTurnsRemaining, false); } else { // Update clone's per tick value to consider the caster's spell/melee buffs/debuffs bool isCrit; int perTickAmountWithStatMods = getAbilityAmountWithStatMods( combatantModel, abilityDurationDataClone.PerTickAmount, combatAbility.IsSpellBased, out isCrit); abilityDurationDataClone.PerTickAmount = perTickAmountWithStatMods; abilityDurationDataClone.IsCrit = isCrit; AbilityDurationDataCollection abilityDurationCollection = isAbilityFriendly ? targets[t].RegenOverTimeAbilityDurations : targets[t].DamageOverTimeAbilityDurations; abilityDurationCollection.Add(abilityDurationDataClone); combatActionOnTarget = new CombatActionModel( combatantModel.ID, CombatActionType.AffectedByDurationAbility, combatAbility.ID, targets[t].ID, 0, abilityDurationDataClone.NumTurnsRemaining, isCrit); } } combatActionsCollection[targets[t].ID].Add(combatActionOnTarget); // If target has died then append death CombatActionModel if (!targets[t].IsAlive()) { combatActionsCollection[targets[t].ID].Add( new CombatActionModel(combatantModel.ID, CombatActionType.Death, combatAbility.ID, targets[t].ID, 0, 0, false)); } } }
public override void QueueAbility(AbilityItemModel abilityItemModel, int[] combatantIDs) { throw new NotImplementedException(); }
public CombatActionModel GetCombatAction(out AbilityItemModel abilityItemModel, ref List <CombatantModel> targets) { if (!ownerCombatantModel.IsAlive()) { throw new Exception("Dead CombatantModel can't perform actions."); } // If already casting. if (castingAbilityItemModel != null) { castingAbilityItemModel.NumCastTurnsElapsed++; abilityItemModel = castingAbilityItemModel; bool allTargetsDead = true; for (int a = 0; a < targetCombatantModels.Count; a++) { if (targetCombatantModels[a].IsAlive()) { allTargetsDead = false; break; } } // If all targets died during cast, then cancel cast if (allTargetsDead) { castingAbilityItemModel.NumCastTurnsElapsed = 0; castingAbilityItemModel = null; return(new CombatActionModel( ownerCombatantModel.ID, CombatActionType.CancelCastingAbility, abilityItemModel.ID, -1, 0, 0, false)); } // Determine number of total cast turns considering cast time stat modifiers int modifiedTotalCastTurns = ownerCombatantModel.GetStatModifiedAbilityTotalCastTurns(castingAbilityIndex); // Handle cast completion (>= insteand of == as expired cast time debuffs can cause user to cast beyond the unmodified amount) if (castingAbilityItemModel.NumCastTurnsElapsed >= modifiedTotalCastTurns) { // Reset ability cast turns and clear reference castingAbilityItemModel.NumCastTurnsElapsed = 0; castingAbilityItemModel = null; // Output alive targets only. for (int t = 0; t < targetCombatantModels.Count; t++) { if (targetCombatantModels[t].IsAlive()) { targets.Add(targetCombatantModels[t]); } } int abilityDurationTurnsRemaining = abilityItemModel.AbilityDurationType == AbilityDurationType.Immediate ? 0 : abilityItemModel.AbilityDurationData.NumTurnsRemaining; // -1 target id signifies multiple targets. return(new CombatActionModel( ownerCombatantModel.ID, CombatActionType.ApplyAbility, abilityItemModel.ID, targets.Count == 1 ? targets[0].ID : -1, 0, abilityDurationTurnsRemaining, false)); } // Still casting, so perform wait. return(new CombatActionModel(ownerCombatantModel.ID, CombatActionType.Wait, -1, -1, 0, 0, false)); } // Determine which abilities are available (not on cooldown) bool abilityAvailable = false; for (int i = 0; i < ownerCombatantModel.AbilityItemModels.Length; i++) { if (ownerCombatantModel.GetStatModifiedAbilityCoolDownTurnsRemaining(i) > 0) { availableAbilities[i] = null; } else { abilityAvailable = true; availableAbilities[i] = ownerCombatantModel.AbilityItemModels[i]; } } // If all abilities on cooldown, return wait. if (!abilityAvailable) { abilityItemModel = null; return(new CombatActionModel(ownerCombatantModel.ID, CombatActionType.Wait, -1, -1, 0, 0, false)); } targetCombatantModels.Clear(); castingAbilityIndex = -1; determineAbilityAndTargets(availableAbilities, ref castingAbilityItemModel, ref castingAbilityIndex, ref targetCombatantModels); abilityItemModel = castingAbilityItemModel; // If we were unable to determine an AbilityItemModel or find valid targets this turn, perform wait. if (castingAbilityItemModel == null || targetCombatantModels.Count == 0) { return(new CombatActionModel(ownerCombatantModel.ID, CombatActionType.Wait, -1, -1, 0, 0, false)); } // Start casting return(new CombatActionModel(ownerCombatantModel.ID, CombatActionType.StartCastingAbility, abilityItemModel.ID, targetCombatantModels.Count == 1 ? targetCombatantModels[0].ID : -1, 0, abilityItemModel.CastTurns, false)); }
protected abstract void determineAbilityAndTargets(AbilityItemModel[] availableAbilityItemModels, ref AbilityItemModel chosenAbilityItemModel, ref int chosenAbilityIndex, ref List <CombatantModel> chosenTargets);
public abstract void QueueAbility(AbilityItemModel abilityItemModel, int[] combatantIDs);