feat: Adds monster ability groups with weights (#1267)

This commit is contained in:
Kamron Batman 2022-11-22 20:13:40 -08:00 committed by GitHub
parent 8b5bd9ec13
commit 02cee4815e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 170 additions and 3 deletions

View file

@ -0,0 +1,155 @@
using System;
using Server.Random;
using WeightedMonsterAbility = Server.Random.WeightedValue<Server.Mobiles.MonsterAbility>;
namespace Server.Mobiles;
public class MonsterAbilityGroup : MonsterAbility
{
private WeightedMonsterAbility[] _weightedAbilities;
private WeightedMonsterAbility[] _availableToTrigger;
private int _availableToTriggerCount;
private MonsterAbilityTrigger _triggers;
public MonsterAbilityGroup(params WeightedMonsterAbility[] weightedAbilities)
{
_weightedAbilities = weightedAbilities;
_availableToTrigger = new WeightedMonsterAbility[weightedAbilities.Length];
for (var i = 0; i < _weightedAbilities.Length; i++)
{
var weightedAbility = _weightedAbilities[i];
_triggers |= weightedAbility.Value.AbilityTrigger;
}
}
public override MonsterAbilityTrigger AbilityTrigger => _triggers;
public bool HasAbility(MonsterAbility ability)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
if (_weightedAbilities[i].Value == ability)
{
return true;
}
}
return false;
}
// Note: Does not get an ability randomly by weight
// This is used for passives or lookups
public MonsterAbility GetAbilityWithType(MonsterAbilityType type)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
var ability = _weightedAbilities[i].Value;
if (ability.AbilityType == type)
{
return ability;
}
}
return null;
}
public override bool CanTrigger(BaseCreature source, MonsterAbilityTrigger trigger)
{
if (!base.CanTrigger(source, trigger))
{
return false;
}
_availableToTriggerCount = 0;
for (var i = 0; i < _weightedAbilities.Length; i++)
{
var weightedAbility = _weightedAbilities[i];
if (weightedAbility.Value.WillTrigger(trigger) && weightedAbility.Value.CanTrigger(source, trigger))
{
_availableToTrigger[_availableToTriggerCount++] = weightedAbility;
}
}
return _availableToTriggerCount > 0;
}
// Note: Trigger will choose an ability at random by weight
public override void Trigger(MonsterAbilityTrigger trigger, BaseCreature source, Mobile target)
{
if (_availableToTriggerCount <= 0)
{
return;
}
var slice = new ReadOnlySpan<WeightedValue<MonsterAbility>>(_availableToTrigger, 0, _availableToTriggerCount);
var chosenAbility = slice.RandomWeightedElement().Value;
// Just in case?
if (chosenAbility == null)
{
return;
}
base.Trigger(trigger, source, target);
chosenAbility.Trigger(trigger, source, target);
_availableToTriggerCount = 0; // Just in case trigger is called without CanTrigger
}
public override void AlterMeleeDamageFrom(BaseCreature source, Mobile target, ref int damage)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.AlterMeleeDamageFrom(source, target, ref damage);
}
}
public override void AlterMeleeDamageTo(BaseCreature source, Mobile target, ref int damage)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.AlterMeleeDamageTo(source, target, ref damage);
}
}
public override void AlterSpellDamageScalarFrom(BaseCreature source, Mobile target, ref double scalar)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.AlterSpellDamageScalarFrom(source, target, ref scalar);
}
}
public override void AlterSpellDamageScalarTo(BaseCreature source, Mobile target, ref double scalar)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.AlterSpellDamageScalarTo(source, target, ref scalar);
}
}
public override void AlterSpellDamageFrom(BaseCreature source, Mobile target, ref int damage)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.AlterSpellDamageFrom(source, target, ref damage);
}
}
public override void AlterSpellDamageTo(BaseCreature source, Mobile target, ref int damage)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.AlterSpellDamageTo(source, target, ref damage);
}
}
public override void Move(BaseCreature creature, Direction d)
{
for (var i = 0; i < _weightedAbilities.Length; i++)
{
_weightedAbilities[i].Value.Move(creature, d);
}
}
}

View file

@ -1130,7 +1130,15 @@ namespace Server.Mobiles
for (var i = 0; i < abilities.Length; i++)
{
var ability = abilities[i];
if (ability.AbilityType == type)
if (ability is MonsterAbilityGroup group)
{
ability = group.GetAbilityWithType(type);
if (ability != null)
{
return ability;
}
}
else if (ability.AbilityType == type)
{
return ability;
}
@ -1141,6 +1149,11 @@ namespace Server.Mobiles
public virtual bool HasAbility(MonsterAbility ability)
{
if (ability == null)
{
return false;
}
var abilities = GetMonsterAbilities();
if (abilities == null)
@ -1150,7 +1163,7 @@ namespace Server.Mobiles
for (var i = 0; i < abilities.Length; i++)
{
if (abilities[i] == ability)
if (abilities[i] == ability || (ability as MonsterAbilityGroup)?.HasAbility(ability) == true)
{
return true;
}
@ -4290,7 +4303,6 @@ namespace Server.Mobiles
public virtual void OnActionCombat()
{
TriggerAbility(MonsterAbilityTrigger.CombatAction, null);
}
public virtual void OnActionGuard()