Merge pull request #834 from eduardosmaniotto/bugfix/duplicate-rows

fix: duplicate rows in deserialized aggregate collections
(cherry picked from commit f95498770ea1af30530a164f868f571ec30052b5)
This commit is contained in:
sven-n
2026-07-21 22:09:15 +02:00
committed by Acentech Dev
parent 0e2c94b84b
commit b854565586
3 changed files with 53 additions and 40 deletions

View File

@@ -62,41 +62,46 @@ public class AddElfSoldierBuffPlugIn : UpdatePlugInBase
return; return;
} }
var buffEffect = context.CreateNew<MagicEffectDefinition>(); var buffEffect = gameConfiguration.MagicEffects.FirstOrDefault(e => e.Number == (short)MagicEffectNumber.ElfSoldierBuff);
gameConfiguration.MagicEffects.Add(buffEffect); if (buffEffect is null)
buffEffect.Number = (short)MagicEffectNumber.ElfSoldierBuff; {
buffEffect.Name = "Elf Soldier Buff"; buffEffect = context.CreateNew<MagicEffectDefinition>();
buffEffect.InformObservers = true; gameConfiguration.MagicEffects.Add(buffEffect);
buffEffect.StopByDeath = true; buffEffect.Number = (short)MagicEffectNumber.ElfSoldierBuff;
buffEffect.Name = "Elf Soldier Buff";
buffEffect.InformObservers = true;
buffEffect.StopByDeath = true;
// Duration: 60 minutes // Duration: 60 minutes
buffEffect.Duration = context.CreateNew<PowerUpDefinitionValue>(); buffEffect.Duration = context.CreateNew<PowerUpDefinitionValue>();
buffEffect.Duration.ConstantValue.Value = 3600; buffEffect.Duration.ConstantValue.Value = 3600;
// Defense boost: 50 + (Level / 5) // Defense boost: 50 + (Level / 5)
var defensePowerUp = context.CreateNew<PowerUpDefinition>(); var defensePowerUp = context.CreateNew<PowerUpDefinition>();
defensePowerUp.TargetAttribute = Stats.DefenseFinal.GetPersistent(gameConfiguration); defensePowerUp.TargetAttribute = Stats.DefenseFinal.GetPersistent(gameConfiguration);
defensePowerUp.Boost = context.CreateNew<PowerUpDefinitionValue>(); defensePowerUp.Boost = context.CreateNew<PowerUpDefinitionValue>();
defensePowerUp.Boost.ConstantValue.Value = 50; defensePowerUp.Boost.ConstantValue.Value = 50;
defensePowerUp.Boost.ConstantValue.AggregateType = AggregateType.AddFinal; defensePowerUp.Boost.ConstantValue.AggregateType = AggregateType.AddFinal;
var defensePerLevel = context.CreateNew<AttributeRelationship>(); var defensePerLevel = context.CreateNew<AttributeRelationship>();
defensePerLevel.InputAttribute = Stats.Level.GetPersistent(gameConfiguration); defensePerLevel.InputAttribute = Stats.Level.GetPersistent(gameConfiguration);
defensePerLevel.InputOperand = 1f / 5; defensePerLevel.InputOperand = 1f / 5;
defensePerLevel.InputOperator = InputOperator.Multiply; defensePerLevel.InputOperator = InputOperator.Multiply;
defensePowerUp.Boost.RelatedValues.Add(defensePerLevel); defensePowerUp.Boost.RelatedValues.Add(defensePerLevel);
buffEffect.PowerUpDefinitions.Add(defensePowerUp); buffEffect.PowerUpDefinitions.Add(defensePowerUp);
// Damage boost: 45 + (Level / 3) // Damage boost: 45 + (Level / 3)
var damagePowerUp = context.CreateNew<PowerUpDefinition>(); var damagePowerUp = context.CreateNew<PowerUpDefinition>();
damagePowerUp.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(gameConfiguration); damagePowerUp.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(gameConfiguration);
damagePowerUp.Boost = context.CreateNew<PowerUpDefinitionValue>(); damagePowerUp.Boost = context.CreateNew<PowerUpDefinitionValue>();
damagePowerUp.Boost.ConstantValue.Value = 45; damagePowerUp.Boost.ConstantValue.Value = 45;
var damagePerLevel = context.CreateNew<AttributeRelationship>(); damagePowerUp.Boost.ConstantValue.AggregateType = AggregateType.AddRaw;
damagePerLevel.InputAttribute = Stats.Level.GetPersistent(gameConfiguration); var damagePerLevel = context.CreateNew<AttributeRelationship>();
damagePerLevel.InputOperand = 1f / 3; damagePerLevel.InputAttribute = Stats.Level.GetPersistent(gameConfiguration);
damagePerLevel.InputOperator = InputOperator.Multiply; damagePerLevel.InputOperand = 1f / 3;
damagePowerUp.Boost.RelatedValues.Add(damagePerLevel); damagePerLevel.InputOperator = InputOperator.Multiply;
buffEffect.PowerUpDefinitions.Add(damagePowerUp); damagePowerUp.Boost.RelatedValues.Add(damagePerLevel);
buffEffect.PowerUpDefinitions.Add(damagePowerUp);
}
var buff = context.CreateNew<Buff>(); var buff = context.CreateNew<Buff>();
buff.MagicEffectDefinition = buffEffect; buff.MagicEffectDefinition = buffEffect;

View File

@@ -151,6 +151,7 @@ internal partial class NpcInitialization : Version095d.NpcInitialization
damagePowerUp.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(this.GameConfiguration); damagePowerUp.TargetAttribute = Stats.GreaterDamageBonus.GetPersistent(this.GameConfiguration);
damagePowerUp.Boost = this.Context.CreateNew<PowerUpDefinitionValue>(); damagePowerUp.Boost = this.Context.CreateNew<PowerUpDefinitionValue>();
damagePowerUp.Boost.ConstantValue.Value = 45; damagePowerUp.Boost.ConstantValue.Value = 45;
damagePowerUp.Boost.ConstantValue.AggregateType = AggregateType.AddRaw;
var damagePerLevel = this.Context.CreateNew<AttributeRelationship>(); var damagePerLevel = this.Context.CreateNew<AttributeRelationship>();
damagePerLevel.InputAttribute = Stats.Level.GetPersistent(this.GameConfiguration); damagePerLevel.InputAttribute = Stats.Level.GetPersistent(this.GameConfiguration);
damagePerLevel.InputOperand = 1f / 3; damagePerLevel.InputOperand = 1f / 3;

View File

@@ -47,11 +47,14 @@ public class ReferenceResolvingConverter<T> : JsonConverter<T>
else if (x.CollectionInterface != null && x.Property.Name.StartsWith("Raw")) else if (x.CollectionInterface != null && x.Property.Name.StartsWith("Raw"))
{ {
propertyType = x.CollectionInterface.GetGenericArguments()[0]; propertyType = x.CollectionInterface.GetGenericArguments()[0];
var collectionExpr = Expression.Convert(Expression.Property(tParam, x.Property), x.CollectionInterface);
var itemExpr = Expression.Convert(objParam, propertyType);
var containsCall = Expression.Call(collectionExpr, x.CollectionInterface.GetMethod("Contains")!, itemExpr);
var addCall = Expression.Call(collectionExpr, x.CollectionInterface.GetMethod("Add")!, itemExpr);
adder = Expression.Lambda<Action<T, object>>( adder = Expression.Lambda<Action<T, object>>(
Expression.Call( Expression.IfThen(Expression.Not(containsCall), addCall),
Expression.Property(tParam, x.Property),
x.CollectionInterface.GetMethod("Add")!,
Expression.Convert(objParam, propertyType)),
tParam, tParam,
objParam) objParam)
.Compile(); .Compile();
@@ -66,11 +69,15 @@ public class ReferenceResolvingConverter<T> : JsonConverter<T>
propertyType = propertyType.GetProperties().First(p => p.PropertyType.BaseType == baseType).PropertyType; propertyType = propertyType.GetProperties().First(p => p.PropertyType.BaseType == baseType).PropertyType;
jsonPropertyName = basePropertyName; jsonPropertyName = basePropertyName;
var baseCollectionInterface = DetermineCollectionInterface(baseCollectionProperty)!;
var collectionExpr = Expression.Convert(Expression.Property(tParam, baseCollectionProperty), baseCollectionInterface);
var itemExpr = Expression.Convert(objParam, propertyType);
var containsCall = Expression.Call(collectionExpr, baseCollectionInterface.GetMethod("Contains")!, itemExpr);
var addCall = Expression.Call(collectionExpr, baseCollectionInterface.GetMethod("Add")!, itemExpr);
adder = Expression.Lambda<Action<T, object>>( adder = Expression.Lambda<Action<T, object>>(
Expression.Call( Expression.IfThen(Expression.Not(containsCall), addCall),
Expression.Property(tParam, baseCollectionProperty),
baseCollectionProperty.PropertyType.GetMethod("Add")!,
Expression.Convert(objParam, propertyType)),
tParam, tParam,
objParam) objParam)
.Compile(); .Compile();