Complete Refactor of status effect system (WIP)

This commit is contained in:
Pedro Gomes 2025-10-01 18:17:53 +01:00
parent b29daefeef
commit 50cb258353
56 changed files with 1133 additions and 1108 deletions

View File

@ -29,7 +29,8 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 2853615639420944899}
- {fileID: 4067085759663909629}
- {fileID: 3145042774550608289}
- {fileID: 1232807570145535296}
- {fileID: 6120897361266337676}
- {fileID: 1697226282428441736}
@ -89,7 +90,7 @@ GameObject:
m_Component:
- component: {fileID: 1232807570145535296}
m_Layer: 0
m_Name: Defensive
m_Name: Defensive-Only
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@ -111,8 +112,6 @@ Transform:
- {fileID: 6328867119063477148}
- {fileID: 5990858872549904705}
- {fileID: 6088225706018485977}
- {fileID: 5849716072256962441}
- {fileID: 1984011823945327289}
- {fileID: 8352337540601452143}
m_Father: {fileID: 1695802727639733595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -234,7 +233,7 @@ Transform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2853615639420944899}
m_Father: {fileID: 1695802727639733595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &7287908039399585062
MonoBehaviour:
@ -248,7 +247,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 64dc3a191522d6a419b6c81e6124b294, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::OnProcInterceptor
--- !u!1 &6223985906228516018
--- !u!1 &5799065354088029240
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -256,164 +255,42 @@ GameObject:
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 670601208020570842}
- component: {fileID: 7962962154595671713}
- component: {fileID: 4067085759663909629}
- component: {fileID: 4924380159794770017}
m_Layer: 0
m_Name: Stat Amplification Calculator
m_Name: BasicStatModifierCalculator
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &670601208020570842
--- !u!4 &4067085759663909629
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6223985906228516018}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2853615639420944899}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &7962962154595671713
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6223985906228516018}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7c7b2480158261a438df4665d65f6dad, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::DamageStatInfluenceCalculator
--- !u!1 &6616939419038775985
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5849716072256962441}
- component: {fileID: 7027586121535414508}
m_Layer: 0
m_Name: Stat Mitigation Calculator
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &5849716072256962441
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6616939419038775985}
serializedVersion: 2
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1232807570145535296}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &7027586121535414508
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6616939419038775985}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1c1e936b3b0b3bb4ebb8f7712f4a9519, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::MitigationStatInfluenceCalculator
--- !u!1 &6704403151289934996
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2853615639420944899}
m_Layer: 0
m_Name: Offensive
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2853615639420944899
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6704403151289934996}
m_GameObject: {fileID: 5799065354088029240}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 670601208020570842}
- {fileID: 3145042774550608289}
- {fileID: 2860111524623448099}
m_Children: []
m_Father: {fileID: 1695802727639733595}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &7059394560846269332
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1984011823945327289}
- component: {fileID: 3923038257450023262}
m_Layer: 0
m_Name: Temp Incoming Mod Interceptor
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1984011823945327289
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7059394560846269332}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1232807570145535296}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &3923038257450023262
--- !u!114 &4924380159794770017
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7059394560846269332}
m_GameObject: {fileID: 5799065354088029240}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ea668dfbd9dd0b94a8ff9d3f2062c14e, type: 3}
m_Script: {fileID: 11500000, guid: ef8391abf380f634f970af8c9eac8275, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TemporaryIncomeModifierInterceptor
m_EditorClassIdentifier: Assembly-CSharp::BasicStatModifierCalculator
--- !u!1 &8090521145083935055
GameObject:
m_ObjectHideFlags: 0
@ -547,47 +424,3 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 6de99a6f4bb244b4f98a4f762ad5c485, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::AbsorbInterceptor
--- !u!1 &8365795067992873118
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2860111524623448099}
- component: {fileID: 7846247177940105072}
m_Layer: 0
m_Name: Temp Outgoing Mod Interceptor
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2860111524623448099
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8365795067992873118}
serializedVersion: 2
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2853615639420944899}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &7846247177940105072
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8365795067992873118}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bc32ad4c0ff248e4aa48487bcab21545, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TemporaryOutgoingModifierInterceptor

View File

@ -78,7 +78,7 @@ Material:
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Rotation: 6.450734
- _Rotation: 9.499645
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1

View File

@ -137,13 +137,9 @@ GameObject:
- component: {fileID: 457396336866213367}
- component: {fileID: 2365405228662859796}
- component: {fileID: 8315856034822994340}
- component: {fileID: 5749389582425256192}
- component: {fileID: 2278116590711127937}
- component: {fileID: 2278116590711127938}
- component: {fileID: 2278116590711127939}
- component: {fileID: 2278116590711127940}
- component: {fileID: 8705931423815090115}
- component: {fileID: 1091324876633067210}
- component: {fileID: 1534920836715691811}
- component: {fileID: 1776927755208037906}
m_Layer: 0
m_Name: BossEnemyPrefabTemplate
m_TagString: Untagged
@ -482,151 +478,6 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &5749389582425256192
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2278116590711127943}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ca852ea491ac9f340b2f34820a262d84, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
startingIncomeModifierPercent: 0
currentIncomeModifierPercent: 0
--- !u!114 &2278116590711127937
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2278116590711127943}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9d56bc7037aecb344b6d896e7094980f, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 3750971928869404956}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &2278116590711127938
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2278116590711127943}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e47a07abc64d3824fb77261edb5f72e3, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 3432148482415062287}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &2278116590711127939
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2278116590711127943}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 70248ebe0c4107246bddef82854d8bde, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 6708470592804965367}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &2278116590711127940
MonoBehaviour:
m_ObjectHideFlags: 0
@ -639,10 +490,26 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 88a4c67f5abc6544e83efa5dedd057c1, type: 3}
m_Name:
m_EditorClassIdentifier:
burningText: {fileID: 3750971928869404956}
poisonedText: {fileID: 6708470592804965367}
bleedingText: {fileID: 3432148482415062287}
burnVFX: {fileID: 4453006715656267409}
poisonVFX: {fileID: 2334928818334601824}
bleedVFX: {fileID: 3335641161984661472}
--- !u!114 &8705931423815090115
--- !u!114 &1534920836715691811
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2278116590711127943}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 118e9e465521b054092a49272a44da7f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TickingEffectHandler
taggable: {fileID: 0}
--- !u!114 &1776927755208037906
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -653,9 +520,9 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 560c708d650e7564ba17251a581b01f2, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
m_EditorClassIdentifier: Assembly-CSharp::MovementSpeedModifierEffectInstance
canStack: 0
canRefresh: 0
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
@ -666,31 +533,6 @@ MonoBehaviour:
m_PersistentCalls:
m_Calls: []
currentSpeedModifierPercent: 0
--- !u!114 &1091324876633067210
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2278116590711127943}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 09c47ef573bbd814e980780d8ab97f9f, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
startingOutputModifierPercent: 0
currentOutputModifierPercent: 0
--- !u!1 &3340202659944668276
GameObject:
m_ObjectHideFlags: 0

View File

@ -215,13 +215,9 @@ GameObject:
- component: {fileID: 1708233211970282802}
- component: {fileID: 1708233211970282800}
- component: {fileID: 195415824371084160}
- component: {fileID: 4763071500030815453}
- component: {fileID: 8556229780080522573}
- component: {fileID: 5769288145149369695}
- component: {fileID: 3424055164062087377}
- component: {fileID: 7755534186111333956}
- component: {fileID: 6107682786806096939}
- component: {fileID: 7496550751805377274}
- component: {fileID: 7976093900099383634}
- component: {fileID: 5488217473701670712}
m_Layer: 0
m_Name: BasicEnemyPrefabTemplate
m_TagString: Untagged
@ -572,151 +568,6 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &4763071500030815453
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1040714684719195968}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ca852ea491ac9f340b2f34820a262d84, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
startingIncomeModifierPercent: 0
currentIncomeModifierPercent: 0
--- !u!114 &8556229780080522573
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1040714684719195968}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9d56bc7037aecb344b6d896e7094980f, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 5407316254601908038}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &5769288145149369695
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1040714684719195968}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 70248ebe0c4107246bddef82854d8bde, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 1098384084433226102}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &3424055164062087377
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1040714684719195968}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e47a07abc64d3824fb77261edb5f72e3, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 4934109709913625507}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &7755534186111333956
MonoBehaviour:
m_ObjectHideFlags: 0
@ -729,10 +580,26 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 88a4c67f5abc6544e83efa5dedd057c1, type: 3}
m_Name:
m_EditorClassIdentifier:
burningText: {fileID: 5407316254601908038}
poisonedText: {fileID: 1098384084433226102}
bleedingText: {fileID: 4934109709913625507}
burnVFX: {fileID: 4411435976634846358}
poisonVFX: {fileID: 6045638370208658194}
bleedVFX: {fileID: 6559508008017082157}
--- !u!114 &6107682786806096939
--- !u!114 &7976093900099383634
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1040714684719195968}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 118e9e465521b054092a49272a44da7f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TickingEffectHandler
taggable: {fileID: 0}
--- !u!114 &5488217473701670712
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@ -743,9 +610,9 @@ MonoBehaviour:
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 560c708d650e7564ba17251a581b01f2, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
m_EditorClassIdentifier: Assembly-CSharp::MovementSpeedModifierEffectInstance
canStack: 0
canRefresh: 0
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
@ -756,31 +623,6 @@ MonoBehaviour:
m_PersistentCalls:
m_Calls: []
currentSpeedModifierPercent: 0
--- !u!114 &7496550751805377274
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1040714684719195968}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 09c47ef573bbd814e980780d8ab97f9f, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
startingOutputModifierPercent: 0
currentOutputModifierPercent: 0
--- !u!1 &2748734579092027444
GameObject:
m_ObjectHideFlags: 0

View File

@ -348,16 +348,12 @@ GameObject:
- component: {fileID: 1869432520870514277}
- component: {fileID: 4217372937522934288}
- component: {fileID: 3247240039285484624}
- component: {fileID: 2967180887760878724}
- component: {fileID: 1152968068986345070}
- component: {fileID: 7259061766111582522}
- component: {fileID: 5441477912912419125}
- component: {fileID: 8889563140594313924}
- component: {fileID: 1680342496745710291}
- component: {fileID: 6949988666450315186}
- component: {fileID: 7471597901585849079}
- component: {fileID: 5443964135166462109}
- component: {fileID: 7653406841585074505}
- component: {fileID: 6462082073756049429}
- component: {fileID: 3354979778521287855}
m_Layer: 0
m_Name: PlayerPrefab
m_TagString: Untagged
@ -835,176 +831,6 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &2967180887760878724
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ca852ea491ac9f340b2f34820a262d84, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
startingIncomeModifierPercent: 0
currentIncomeModifierPercent: 0
--- !u!114 &1152968068986345070
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 09c47ef573bbd814e980780d8ab97f9f, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
startingOutputModifierPercent: 0
currentOutputModifierPercent: 0
--- !u!114 &7259061766111582522
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9d56bc7037aecb344b6d896e7094980f, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 4176597637354617671}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &5441477912912419125
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 70248ebe0c4107246bddef82854d8bde, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 7030616627635128197}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &8889563140594313924
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e47a07abc64d3824fb77261edb5f72e3, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 4604677370021419963}
m_TargetAssemblyTypeName: UnityEngine.ParticleSystem, UnityEngine
m_MethodName: Play
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
mitigationType: 0
currentDamagePerTick: 0
OnEffectTick:
m_PersistentCalls:
m_Calls: []
--- !u!114 &1680342496745710291
MonoBehaviour:
m_ObjectHideFlags: 0
@ -1017,33 +843,12 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 88a4c67f5abc6544e83efa5dedd057c1, type: 3}
m_Name:
m_EditorClassIdentifier:
burningText: {fileID: 4176597637354617671}
poisonedText: {fileID: 7030616627635128197}
bleedingText: {fileID: 4604677370021419963}
burnVFX: {fileID: 653320600731715169}
poisonVFX: {fileID: 6351619896009355393}
bleedVFX: {fileID: 4390455603706248860}
--- !u!114 &6949988666450315186
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 560c708d650e7564ba17251a581b01f2, type: 3}
m_Name:
m_EditorClassIdentifier:
canStack: 1
canRefresh: 1
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
currentSpeedModifierPercent: 0
--- !u!114 &7471597901585849079
MonoBehaviour:
m_ObjectHideFlags: 0
@ -1107,6 +912,43 @@ MonoBehaviour:
m_DefaultActionMap: Player
m_SplitScreenIndex: -1
m_Camera: {fileID: 0}
--- !u!114 &6462082073756049429
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 118e9e465521b054092a49272a44da7f, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::TickingEffectHandler
taggable: {fileID: 0}
--- !u!114 &3354979778521287855
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 480331571121010796}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 560c708d650e7564ba17251a581b01f2, type: 3}
m_Name:
m_EditorClassIdentifier: Assembly-CSharp::MovementSpeedModifierEffectInstance
canStack: 0
canRefresh: 0
taggable: {fileID: 0}
endEffectTime: 0
activeStacks: []
OnEffectStackAddedEvent:
m_PersistentCalls:
m_Calls: []
OnEffectEnded:
m_PersistentCalls:
m_Calls: []
currentSpeedModifierPercent: 0
--- !u!1 &647488901503982106
GameObject:
m_ObjectHideFlags: 0

View File

@ -19,9 +19,10 @@ MonoBehaviour:
- statTag: {fileID: 11400000, guid: 918ee6f8846e6a9449166ac16b6330ae, type: 2}
percentInfluence: 0.175
duration: 3
canApplyMultipleInstances: 0
stackingRule: 0
applyToTargetsHit: 1
applyToSelf: 0
chanceToApply: 100
defaultNumberOfStacks: 1
baseDamagePerTick: 0.5
tickRate: 0.5
damageType: 0
damageType: 2

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b9a7503ec26ac96418b9ee4e79376931
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: af01294d38acd8c4ba867154b71b9ec6, type: 3}
m_Name: BasicBurn
m_EditorClassIdentifier: Assembly-CSharp::DamageOverTimeEffect
tags: []
influencingStats: []
duration: 3
stackingRule: 0
applyToTargetsHit: 1
applyToSelf: 0
chanceToApply: 100
defaultNumberOfStacks: 1
baseDamagePerTick: 1
damageType: 2

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 92f75479a1cd70c4188ef4a57ce4d201
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -4,6 +4,16 @@ public enum DamageType
{
Attack,
Spell,
Fire, //holy
Cold, //water,
Lightning,
Physical,
Mystic,
Poison,
Shadow
}
[System.Serializable]

View File

@ -99,26 +99,4 @@ public class AbsorbEffectInstance : StatusEffectInstance
base.EffectStateEnded();
}
/*
private CharacterStat GetCorrectStat(CharacterStats stats) //TODO: make it use multiple stats correctly
{
for (int i = 0; i < influencingStats.Count; i++)
{
if (stats.statsDictionary.ContainsKey(influencingStats[i].name.ToLower()))
{
Debug.Log($"Influencing effect using: {influencingStats[i].name.ToLower()}");
return stats.statsDictionary[influencingStats[i].name.ToLower()];
}
}
return null;
}
private void GetFinalValue(CharacterStat stat)
{
if (stat == null)
finalValue = baseValue;
else
finalValue = baseValue + stat.Value * percentStatInfluence;
}*/
}

View File

@ -36,14 +36,14 @@ public abstract class BaseDamageOverTimeEffectInstance : StatusEffectInstance
protected override IEnumerator EffectStateCoroutine()
{
nextTickTime = Time.time + ((DamageOverTimeEffect)activeStacks[0]).tickRate;
//nextTickTime = Time.time + ((DamageOverTimeEffect)activeStacks[0]).tickRate;
while (Time.time < endEffectTime)
{
if (Time.time >= nextTickTime)
{
ApplyDamage();
nextTickTime = Time.time + ((DamageOverTimeEffect)activeStacks[0]).tickRate;
//nextTickTime = Time.time + ((DamageOverTimeEffect)activeStacks[0]).tickRate;
}
yield return null;
}
@ -56,7 +56,7 @@ public abstract class BaseDamageOverTimeEffectInstance : StatusEffectInstance
Health targetHealth = GetComponent<Health>();
if (targetHealth != null)
{
targetHealth.ChangeValue(-currentDamagePerTick, (int)mitigationType, false);
//targetHealth.ChangeValue(-currentDamagePerTick, (int)mitigationType, false);
}
OnEffectTick.Invoke();
}

View File

@ -10,9 +10,9 @@ public class DamageIncomeModifierEffect : StatusEffect
{
public float damageIncomeModifierPercentage;
public bool avoidAllies = false;
public bool avoidEnemies = false;
DamageIncomeModifierEffectInstance targetDamageIncomeModifierEffect;
StatusEffectHandler effectHandler;
public override void ApplyEffect(Taggable user, List<Taggable> targets, BaseAbility source)
{
@ -22,41 +22,26 @@ public class DamageIncomeModifierEffect : StatusEffect
{
foreach (Taggable target in targets)
{
if(avoidAllies)
if (avoidEnemies)
{
if (user.AlliedTagsContains(target.targetTag)) continue;
if (!user.AlliedTagsContains(target.targetTag)) continue;
}
targetDamageIncomeModifierEffect = target.GetComponent<DamageIncomeModifierEffectInstance>();
targetDamageIncomeModifierEffect.ApplyEffect(this, CalculateFinalAmount(user), source);
effectHandler = target.GetComponent<StatusEffectHandler>();
effectHandler.ApplyEffect(this, user, target, source, defaultNumberOfStacks);
}
}
if(applyToSelf)
if (applyToSelf)
{
targetDamageIncomeModifierEffect = user.GetComponent<DamageIncomeModifierEffectInstance>();
targetDamageIncomeModifierEffect.ApplyEffect(this, CalculateFinalAmount(user), source);
effectHandler = user.GetComponent<StatusEffectHandler>();
effectHandler.ApplyEffect(this, user, user, source, defaultNumberOfStacks);
}
}
private float CalculateFinalAmount(Taggable user)
public override RuntimeEffectInstance CreateEffectInstance()
{
float finalAmount = damageIncomeModifierPercentage;
CharacterStats stats = user.GetComponent<CharacterStats>();
foreach (var statInfluence in influencingStats)
{
if (stats.primaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat stat))
{
//Debug.Log("#DIMod: " + this.name + " = " + damageIncomeModifierPercentage + " += " + stat.Value + " * " + statInfluence.percentInfluence);
finalAmount += stat.Value * statInfluence.percentInfluence;
}
else if (stats.secondaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat secondaryStat))
{
//Debug.Log("#DIMod: " + this.name + " = " + damageIncomeModifierPercentage + " += " + stat.Value + " * " + statInfluence.percentInfluence);
finalAmount += secondaryStat.Value * statInfluence.percentInfluence;
}
}
Debug.Log("#DIMod: " + this.name + " finalAmount = " + finalAmount);
return finalAmount;
DamageIncomeModifierRuntimeEffectInstance instance = CObjectPool<DamageIncomeModifierRuntimeEffectInstance>.Get();
instance.damageIncomeModifierPercentage = damageIncomeModifierPercentage;
return instance;
}
}

View File

@ -39,7 +39,7 @@ public class DamageIncomeModifierEffectInstance : StatusEffectInstance
startingIncomeModifierPercent = value;
currentIncomeModifierPercent = value;
}
else if (canStack && (!activeStacks.Contains(addedEffect) || addedEffect.canApplyMultipleInstances))
/*else if (canStack && (!activeStacks.Contains(addedEffect) || addedEffect.canStack))
{
currentIncomeModifierPercent += value;
}
@ -47,7 +47,7 @@ public class DamageIncomeModifierEffectInstance : StatusEffectInstance
{
OnEffectStackAdded();
return;
}
}*/
base.AddStack(addedEffect, value);
}

View File

@ -12,7 +12,7 @@ public class DamageOutputModifierEffect : StatusEffect
public bool avoidEnemies = false;
DamageOutputModifierEffectInstance targetDamageOutputModifierEffect;
StatusEffectHandler effectHandler;
public override void ApplyEffect(Taggable user, List<Taggable> targets, BaseAbility source)
{
@ -26,35 +26,22 @@ public class DamageOutputModifierEffect : StatusEffect
{
if (!user.AlliedTagsContains(target.targetTag)) continue;
}
targetDamageOutputModifierEffect = target.GetComponent<DamageOutputModifierEffectInstance>();
targetDamageOutputModifierEffect.ApplyEffect(this, CalculateFinalAmount(user), source);
effectHandler = target.GetComponent<StatusEffectHandler>();
effectHandler.ApplyEffect(this, user, target, source, defaultNumberOfStacks);
}
}
if(applyToSelf)
{
targetDamageOutputModifierEffect = user.GetComponent<DamageOutputModifierEffectInstance>();
targetDamageOutputModifierEffect.ApplyEffect(this, CalculateFinalAmount(user), source);
effectHandler = user.GetComponent<StatusEffectHandler>();
effectHandler.ApplyEffect(this, user, user, source, defaultNumberOfStacks);
}
}
private float CalculateFinalAmount(Taggable user)
public override RuntimeEffectInstance CreateEffectInstance()
{
float finalAmount = damageOutputModifierPercentage;
CharacterStats stats = user.GetComponent<CharacterStats>();
foreach (var statInfluence in influencingStats)
{
if (stats.primaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat stat))
{
finalAmount += stat.Value * statInfluence.percentInfluence;
}
else if (stats.secondaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat secondaryStat))
{
finalAmount += secondaryStat.Value * statInfluence.percentInfluence;
}
}
return finalAmount;
DamageOutputModifierRuntimeEffectInstance instance = CObjectPool<DamageOutputModifierRuntimeEffectInstance>.Get();
instance.damageOutputModifierPercentage = damageOutputModifierPercentage;
return instance;
}
}

View File

@ -40,7 +40,7 @@ public class DamageOutputModifierEffectInstance : StatusEffectInstance
startingOutputModifierPercent = value;
currentOutputModifierPercent = value;
}
else if (canStack && (!activeStacks.Contains(addedEffect) || addedEffect.canApplyMultipleInstances))
/*else if (canStack && (!activeStacks.Contains(addedEffect) || addedEffect.canStack))
{
currentOutputModifierPercent += value;
}
@ -48,7 +48,7 @@ public class DamageOutputModifierEffectInstance : StatusEffectInstance
{
OnEffectStackAdded();
return;
}
}*/
base.AddStack(addedEffect, value);
}

View File

@ -8,78 +8,38 @@ public class DamageOverTimeEffect : StatusEffect
{
[Space]
public float baseDamagePerTick;
public float tickRate = 1f;
public DamageOverTimeType damageType;
public DamageType damageType;
TickingEffectHandler effectHandler;
private float finalTickValue;
private CharacterStats stats;
private DamageOutputModifierEffectInstance damageOutputModifier;
public override void ApplyEffect(Taggable user, List<Taggable> targets, BaseAbility source)
{
base.ApplyEffect(user, targets, source);
finalTickValue = CalculateFinalDamage(user);
if (applyToTargetsHit)
{
foreach (Taggable target in targets)
{
BaseDamageOverTimeEffectInstance dotInstance = GetOrAddCorrectInstance(target);
dotInstance.ApplyEffect(this, finalTickValue, source);
effectHandler = target.GetComponent<TickingEffectHandler>();
effectHandler.ApplyEffect(this, user, target, source, defaultNumberOfStacks);
}
}
if (applyToSelf)
{
BaseDamageOverTimeEffectInstance dotInstance = GetOrAddCorrectInstance(user);
dotInstance.ApplyEffect(this, finalTickValue, source);
effectHandler = user.GetComponent<TickingEffectHandler>();
effectHandler.ApplyEffect(this, user, user, source, defaultNumberOfStacks);
}
}
private BaseDamageOverTimeEffectInstance GetOrAddCorrectInstance(Taggable target)
public override RuntimeEffectInstance CreateEffectInstance()
{
switch (damageType)
{
case DamageOverTimeType.Burn:
return target.GetComponent<BurnEffectInstance>() ?? target.gameObject.AddComponent<BurnEffectInstance>();
case DamageOverTimeType.Poison:
return target.GetComponent<PoisonEffectInstance>() ?? target.gameObject.AddComponent<PoisonEffectInstance>();
case DamageOverTimeType.Bleed:
return target.GetComponent<BleedEffectInstance>() ?? target.gameObject.AddComponent<BleedEffectInstance>();
default:
throw new System.ArgumentException("Unknown damage type");
}
}
private float CalculateFinalDamage(Taggable user)
{
float finalDamage = baseDamagePerTick;
if (user == null) return finalDamage;
stats = user.GetComponent<CharacterStats>();
if (stats == null) return finalDamage;
damageOutputModifier = user.GetComponent<DamageOutputModifierEffectInstance>();
if (damageOutputModifier == null) return finalDamage;
foreach (var statInfluence in influencingStats)
{
if (stats.primaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat stat))
{
finalDamage += stat.Value * statInfluence.percentInfluence;
}
else if (stats.secondaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat secondaryStat))
{
finalDamage += secondaryStat.Value * statInfluence.percentInfluence;
}
}
finalDamage = damageOutputModifier.ModifyDamageOutput(finalDamage);
return finalDamage;
DamageTickingRuntimeEffectInstance instance = CObjectPool<DamageTickingRuntimeEffectInstance>.Get();
instance.baseDamagePerTick = baseDamagePerTick;
instance.damageType = damageType;
return instance;
}
}

View File

@ -2,24 +2,45 @@ using UnityEngine;
public class DamageOverTimeVFXManager : MonoBehaviour
{
public ParticleSystem burningText;
public ParticleSystem poisonedText;
public ParticleSystem bleedingText;
public GameObject burnVFX;
public GameObject poisonVFX;
public GameObject bleedVFX;
EntityEventBroker broker;
TickingEffectHandler effectHandler;
private void Awake()
{
SetupEffectInstance<BurnEffectInstance>(burnVFX);
SetupEffectInstance<PoisonEffectInstance>(poisonVFX);
SetupEffectInstance<BleedEffectInstance>(bleedVFX);
effectHandler = GetComponent<TickingEffectHandler>();
broker = GetComponent<EntityEventBroker>();
broker.OnAilmentApplied.Subscribe(OnAilmentApplied);
}
private void SetupEffectInstance<T>(GameObject vfx) where T : BaseDamageOverTimeEffectInstance
private void Update()
{
T instance = GetComponent<T>();
if (instance != null)
burnVFX.SetActive(effectHandler.IsBurning());
poisonVFX.SetActive(effectHandler.IsPoisoned());
bleedVFX.SetActive(effectHandler.IsBleeding());
}
private void OnAilmentApplied(DamageType type)
{
switch (type)
{
instance.OnEffectStackAddedEvent.AddListener(() => vfx.SetActive(true));
instance.OnEffectEnded.AddListener(() => vfx.SetActive(false));
case DamageType.Fire:
burningText.Play();
break;
case DamageType.Physical:
bleedingText.Play();
break;
case DamageType.Poison:
poisonedText.Play();
break;
}
}
}

View File

@ -40,7 +40,7 @@ public class InstantValueEffect : BaseEffect
//Debug.Log($"Applied instant effect of {GetCorrectValueSign(user, target)} to target {target.name}");
if (applyToClassResourceInstead)
{
if (user.IsMinion()) return;
/*if (user.IsMinion()) return;
if (applyToSelfResourceInsteadOfHit)
{
@ -53,7 +53,7 @@ public class InstantValueEffect : BaseEffect
classResource = target.GetComponent<ClassResource>();
if (classResource != null)
classResource.ChangeValue(GetCorrectValueSign(user, target));
}
}*/
}
else
@ -85,43 +85,53 @@ public class InstantValueEffect : BaseEffect
if (user.AlliedTagsContains(target.targetTag))
{
HealArgs args = new HealArgs()
{
source = source,
effect = this,
user = user,
target = target,
currentValue = baseValue,
isCrit = false,
applicationMethod = EffectApplicationMethod.Hit,
totalTargetsHit = totalTargetsHit
};
HealArgs args = CObjectPool<HealArgs>.Get();
args.source = source;
args.effect = this;
args.user = user;
args.target = target;
args.currentValue = baseValue;
args.outgoingAccumulator = 0f;
args.incomingAccumulator= 0f;
args.applicationMethod = EffectApplicationMethod.Hit;
args.isCrit = false;
args.totalTargetsHit = totalTargetsHit;
userBroker.OnOutgoingHeal.Invoke(args);
userBroker.OnOutgoingHealProcessed.Invoke(args);
targetHealth.ApplyHeal(args);
CObjectPool<HealArgs>.Release(args);
}
else
{
DamageArgs args = new DamageArgs()
{
source = source,
effect = this,
user = user,
target = target,
currentValue = -baseValue,
isCrit = false,
targetDead = false,
applicationMethod = EffectApplicationMethod.Hit,
totalTargetsHit = totalTargetsHit
};
DamageArgs args = CObjectPool<DamageArgs>.Get();
args.sourceAbility = source;
args.sourceEffect = this;
args.user = user;
args.target = target;
args.currentValue = -baseValue;
args.outgoingAccumulator = 0f;
args.incomingAccumulator = 0f;
args.damageType = damageType;
args.applicationMethod = EffectApplicationMethod.Hit;
args.isCrit = false;
args.totalTargetsHit = totalTargetsHit;
args.targetDead = false;
userBroker.OnOutgoingDamage.Invoke(args);
userBroker.OnOutgoingDamageProcessed.Invoke(args);
targetHealth.ApplyDamage(args);
CObjectPool<DamageArgs>.Release(args);
}
}
@ -150,20 +160,6 @@ public class InstantValueEffect : BaseEffect
return (-finalValue * EnemyTargetMultiplier);
}
/*
private CharacterStat GetCorrectStat(CharacterStats stats) //TODO: make it use multiple stats correctly
{
for (int i = 0; i < influencingStats.Count; i++)
{
if (stats.statsDictionary.ContainsKey(influencingStats[i].statTag.name.ToLower()))
{
Debug.Log($"Influencing effect using: {influencingStats[i].statTag.name.ToLower()}");
return stats.statsDictionary[influencingStats[i].statTag.name.ToLower()];
}
}
return null;
}
*/
private void GetFinalValue(CharacterStats stats, DamageOutputModifierEffectInstance damageOutputModifier)
{

View File

@ -9,61 +9,32 @@ public class MovementSpeedModifierEffect : StatusEffect
{
public float speedModifierPercentage;
MovementSpeedModifierEffectInstance targetMovementSpeedModifierEffect;
StatusEffectHandler effectHandler;
public override void ApplyEffect(Taggable user, List<Taggable> targets, BaseAbility source)
{
base.ApplyEffect(user, targets, source);
if (applyToTargetsHit)
{
foreach (Taggable target in targets)
{
//if (IsAlliedTarget(user, target))
//{
targetMovementSpeedModifierEffect = target.GetComponent<MovementSpeedModifierEffectInstance>();
targetMovementSpeedModifierEffect.ApplyEffect(this, GetCorrectValueSign(user, target), source);
//}
effectHandler = target.GetComponent<StatusEffectHandler>();
effectHandler.ApplyEffect(this, user, target, source, defaultNumberOfStacks);
}
}
if (applyToSelf)
{
targetMovementSpeedModifierEffect = user.GetComponent<MovementSpeedModifierEffectInstance>();
targetMovementSpeedModifierEffect.ApplyEffect(this, GetCorrectValueSign(user, user), source);
effectHandler = user.GetComponent<StatusEffectHandler>();
effectHandler.ApplyEffect(this, user, user, source, defaultNumberOfStacks);
}
}
private bool IsAlliedTarget(Taggable user, Taggable target)
public override RuntimeEffectInstance CreateEffectInstance()
{
return user.AlliedTagsContains(target.targetTag);
MovementSpeedModifierRuntimeEffectInstance instance = CObjectPool<MovementSpeedModifierRuntimeEffectInstance>.Get();
instance.speedModifierPercentage = speedModifierPercentage;
return instance;
}
private float CalculateFinalAmount(Taggable user)
{
float finalAmount = speedModifierPercentage;
CharacterStats stats = user.GetComponent<CharacterStats>();
foreach (var statInfluence in influencingStats)
{
if (stats.primaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat stat))
{
finalAmount += stat.Value * statInfluence.percentInfluence;
}
else if (stats.secondaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat secondaryStat))
{
finalAmount += secondaryStat.Value * statInfluence.percentInfluence;
}
}
return finalAmount;
}
private float GetCorrectValueSign(Taggable user, Taggable target)
{
if (user == null) return 0;
if (target == null) return 0;
//return user.targetTag.AlliedTags.Contains(target.targetTag) ? (finalValue * AlliedTargetMultiplier) : (-finalValue * EnemyTargetMultiplier);
return user.AlliedTagsContains(target.targetTag) ? CalculateFinalAmount(user) : -CalculateFinalAmount(user);
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 25dff400e76a1ee498ffcfa481544c41
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,35 @@
using UnityEngine;
public class DamageIncomeModifierRuntimeEffectInstance : RuntimeEffectInstance
{
public float damageIncomeModifierPercentage;
public override void OnEffectFirstApplied(int numberOfStacksApplied)
{
base.OnEffectFirstApplied(numberOfStacksApplied);
//apply damage amp buff
user.Broker.OnIncomingDamage.Subscribe(ModifyIncomingDamage, GameConstants.BrokerEventPriority.TemporaryMitigationMods);
}
public override void OnEffectRemoved()
{
base.OnEffectRemoved();
//remove damage amp buff
user.Broker.OnIncomingDamage.Unsubscribe(ModifyIncomingDamage);
}
private void ModifyIncomingDamage(DamageArgs args)
{
args.currentValue = args.currentValue * (1 + damageIncomeModifierPercentage);
}
public new void Reset()
{
base.Reset();
damageIncomeModifierPercentage = 0f;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 859fdd6adc6478f4b9496a8915cccd20

View File

@ -0,0 +1,35 @@
using UnityEngine;
public class DamageOutputModifierRuntimeEffectInstance : RuntimeEffectInstance
{
public float damageOutputModifierPercentage;
public override void OnEffectFirstApplied(int numberOfStacksApplied)
{
base.OnEffectFirstApplied(numberOfStacksApplied);
//apply damage amp buff
user.Broker.OnOutgoingDamage.Subscribe(ModifyOutgoingDamage, GameConstants.BrokerEventPriority.TemporaryAmplificationMods);
}
public override void OnEffectRemoved()
{
base.OnEffectRemoved();
//remove damage amp buff
user.Broker.OnOutgoingDamage.Unsubscribe(ModifyOutgoingDamage);
}
private void ModifyOutgoingDamage(DamageArgs args)
{
args.currentValue = args.currentValue * (1 + damageOutputModifierPercentage);
}
public new void Reset()
{
base.Reset();
damageOutputModifierPercentage = 0f;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d01aa1e7b0bf83d4eac75b5e35faa0df

View File

@ -0,0 +1,52 @@
using UnityEngine;
public class DamageTickingRuntimeEffectInstance : TickingRuntimeEffectInstance
{
public float baseDamagePerTick;
public DamageType damageType;
Health targetHealth;
public override void OnEffectFirstApplied(int numberOfStacksApplied)
{
base.OnEffectFirstApplied(numberOfStacksApplied);
targetBroker.OnAilmentApplied.Invoke(damageType);
targetHealth = target.GetComponent<Health>();
}
protected override void PerformTick()
{
if (user == null) return;
if (target == null) return;
DamageArgs args = CObjectPool<DamageArgs>.Get();
args.sourceAbility = sourceAbility;
args.sourceEffect = sourceEffect;
args.user = user;
args.target = target;
args.currentValue = -baseDamagePerTick * numberOfStacks;
args.isCrit = false;
args.targetDead = false;
args.applicationMethod = EffectApplicationMethod.Tick;
args.damageType = damageType;
args.totalTargetsHit = 1;
user.Broker.OnOutgoingDamage.Invoke(args);
user.Broker.OnOutgoingDamageProcessed.Invoke(args);
targetHealth.ApplyDamage(args);
CObjectPool<DamageArgs>.Release(args);
}
public new void Reset()
{
base.Reset();
baseDamagePerTick = 0f;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3c92303cfacaa8f4eb70ac116be8e3b3

View File

@ -0,0 +1,34 @@
using Kryz.CharacterStats;
using Kryz.CharacterStats.Examples;
using UnityEngine;
public class MovementSpeedModifierRuntimeEffectInstance : RuntimeEffectInstance
{
public float speedModifierPercentage;
public CharacterStats targetStats;
public override void OnEffectFirstApplied(int numberOfStacksApplied)
{
base.OnEffectFirstApplied(numberOfStacksApplied);
targetStats = target.GetComponent<CharacterStats>();
//TODO: Update this to use a new movementspeedhandler
targetStats.GetStat("movementspeed").AddModifier(new StatModifier(speedModifierPercentage, StatModType.PercentAdd, sourceEffect));
}
public override void OnEffectRemoved()
{
base.OnEffectRemoved();
targetStats.GetStat("movementspeed").RemoveAllModifiersFromSource(sourceEffect);
}
public new void Reset()
{
base.Reset();
speedModifierPercentage = 0f;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 74f23a8dcdbafb949a230ee8d8cf9aed

View File

@ -0,0 +1,42 @@
using UnityEngine;
public class RuntimeEffectInstance : IResettable
{
public Taggable user;
public Taggable target;
public EntityEventBroker sourceBroker;
public EntityEventBroker targetBroker;
public StatusEffect sourceEffect;
public BaseAbility sourceAbility;
public float duration;
public int numberOfStacks;
public float endEffectTime;
public virtual void OnEffectFirstApplied(int numberOfStacksApplied)
{
//do stuff on apply X amount of stacks
}
public virtual void OnEffectRefreshed(int numberOfStacksApplied)
{
//do stuff when refreshed/re-applied
}
public virtual void OnEffectRemoved()
{
//do stuff when expired/removed
}
public void Reset()
{
user = null;
target = null;
sourceBroker = null;
targetBroker = null;
sourceEffect = null;
sourceAbility = null;
duration = 0f;
endEffectTime = 0f;
numberOfStacks = 0;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b73df61540ec5994a874dd8d9d09de5e

View File

@ -0,0 +1,39 @@
using System.Collections.Generic;
using UnityEngine;
public class StandardEffectHandler : StatusEffectHandler
{
// Separate list for ONLY ticking effects
protected List<TickingRuntimeEffectInstance> tickingEffects = new List<TickingRuntimeEffectInstance>();
protected override void UpdateEffects(float deltaTime)
{
// Only iterate effects that can tick
for (int i = 0; i < tickingEffects.Count; i++)
{
tickingEffects[i].Tick(deltaTime);
}
}
protected override void UpdateCollections(StatusEffect effect, RuntimeEffectInstance runtimeEffect)
{
base.UpdateCollections(effect, runtimeEffect);
// Track ticking effects separately
if (runtimeEffect is TickingRuntimeEffectInstance tickingEffect)
{
tickingEffects.Add(tickingEffect);
}
}
protected override void RemoveFromCollections(RuntimeEffectInstance runtimeEffect)
{
base.RemoveFromCollections(runtimeEffect);
// Remove from ticking list
if (runtimeEffect is TickingRuntimeEffectInstance tickingEffect)
{
tickingEffects.Remove(tickingEffect);
}
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ef20b577e8c65cf47a2a5a0881b5f64a

View File

@ -0,0 +1,190 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
public class StatusEffectHandler : MonoBehaviour
{
[Header("Set by code:")]
public Taggable taggable;
//list of ALL active effects regardless of type
public List<RuntimeEffectInstance> activeEffects = new List<RuntimeEffectInstance>();
//explanation: slow => list of slows from each source
public Dictionary<StatusEffect, List<RuntimeEffectInstance>> activeEffectsByType = new Dictionary<StatusEffect, List<RuntimeEffectInstance>>();
//explanation: entityA => list of every effect type applied by entityA
//public Dictionary<Taggable, List<RuntimeEffectInstance>> activeEffectsBySource = new Dictionary<Taggable, List<RuntimeEffectInstance>>();
// Temporary list to avoid modifying collection during iteration
protected List<RuntimeEffectInstance> effectsToRemove = new List<RuntimeEffectInstance>();
protected virtual void Awake()
{
taggable = GetComponentInParent<Taggable>();
}
public virtual void ApplyEffect(StatusEffect effect, Taggable user, Taggable target, BaseAbility sourceAbility, int numberOfStacks)
{
if (numberOfStacks <= 0)
{
Debug.LogWarning($"Attempted to apply {effect.name} with {numberOfStacks} stacks");
return;
}
if (TryGetExistingEffect(effect, user, out RuntimeEffectInstance existingEffect))
{
RefreshEffect(existingEffect, numberOfStacks);
}
else
{
ApplyNewEffect(effect, user, target, sourceAbility, numberOfStacks);
}
}
protected bool TryGetExistingEffect(StatusEffect effect, Taggable user, out RuntimeEffectInstance existingEffect)
{
if (activeEffectsByType.TryGetValue(effect, out var effectList))
{
existingEffect = effectList.FirstOrDefault(e => e.user == user);
return existingEffect != null;
}
existingEffect = null;
return false;
}
protected virtual void ApplyNewEffect(StatusEffect effect, Taggable user, Taggable target, BaseAbility sourceAbility, int numberOfStacks)
{
RuntimeEffectInstance runtimeEffect = CreateRuntimeEffect(effect, user, target, sourceAbility);
// Initialize stacks based on stacking rule
switch (effect.stackingRule)
{
case StackingRule.StackUnlimited:
runtimeEffect.numberOfStacks = numberOfStacks;
break;
case StackingRule.Refresh_And_ReplaceIfHigher:
runtimeEffect.numberOfStacks = 1;
break;
}
UpdateCollections(effect, runtimeEffect);
runtimeEffect.OnEffectFirstApplied(numberOfStacks);
}
protected virtual void RefreshEffect(RuntimeEffectInstance runtimeEffect, int numberOfStacks)
{
switch (runtimeEffect.sourceEffect.stackingRule)
{
case StackingRule.StackUnlimited:
runtimeEffect.numberOfStacks += numberOfStacks;
runtimeEffect.endEffectTime = Time.time + runtimeEffect.duration;
runtimeEffect.OnEffectRefreshed(numberOfStacks);
break;
case StackingRule.Refresh_And_ReplaceIfHigher:
// Keep stacks at 1, just refresh duration
runtimeEffect.endEffectTime = Time.time + runtimeEffect.duration;
runtimeEffect.OnEffectRefreshed(0); // 0 stacks added, just refreshed
break;
}
}
protected virtual RuntimeEffectInstance CreateRuntimeEffect(StatusEffect effect, Taggable user, Taggable target, BaseAbility sourceAbility)
{
RuntimeEffectInstance runtimeEffect = effect.CreateEffectInstance();
runtimeEffect.user = user;
runtimeEffect.target = target;
runtimeEffect.sourceBroker = user.Broker;
runtimeEffect.targetBroker = target.Broker;
runtimeEffect.sourceEffect = effect;
runtimeEffect.sourceAbility = sourceAbility;
runtimeEffect.duration = effect.duration;
runtimeEffect.endEffectTime = Time.time + effect.duration;
return runtimeEffect;
}
protected virtual void UpdateCollections(StatusEffect effect, RuntimeEffectInstance runtimeEffect)
{
// Add to type-specific dictionary
if (!activeEffectsByType.ContainsKey(effect))
{
activeEffectsByType[effect] = new List<RuntimeEffectInstance>();
}
activeEffectsByType[effect].Add(runtimeEffect);
// Add to global list
activeEffects.Add(runtimeEffect);
}
protected virtual void Update()
{
UpdateEffects(Time.deltaTime);
CheckExpiredEffects();
}
// Hook for child classes to add custom update logic
protected virtual void UpdateEffects(float deltaTime)
{
// Base class does nothing - child classes can override for ticking
}
protected virtual void CheckExpiredEffects()
{
effectsToRemove.Clear();
float currentTime = Time.time;
// Collect expired effects
for (int i = 0; i < activeEffects.Count; i++)
{
if (currentTime >= activeEffects[i].endEffectTime)
{
effectsToRemove.Add(activeEffects[i]);
}
}
// Remove all expired effects
for (int i = 0; i < effectsToRemove.Count; i++)
{
RemoveEffect(effectsToRemove[i]);
}
}
public void RemoveEffect(RuntimeEffectInstance runtimeEffect)
{
runtimeEffect.OnEffectRemoved();
RemoveFromCollections(runtimeEffect);
CObjectPool<RuntimeEffectInstance>.Release(runtimeEffect);
}
protected virtual void RemoveFromCollections(RuntimeEffectInstance runtimeEffect)
{
// Remove from global list
activeEffects.Remove(runtimeEffect);
// Remove from type-specific dictionary
if (activeEffectsByType.TryGetValue(runtimeEffect.sourceEffect, out var effectList))
{
effectList.Remove(runtimeEffect);
// Clean up empty lists to avoid memory bloat
if (effectList.Count == 0)
{
activeEffectsByType.Remove(runtimeEffect.sourceEffect);
}
}
}
public bool HasEffect(StatusEffect effect)
{
return activeEffectsByType.ContainsKey(effect) && activeEffectsByType[effect].Count > 0;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 94288209861e9cf48be8fc8a72c04392

View File

@ -0,0 +1,134 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class TickingEffectHandler : StatusEffectHandler
{
// Separate list for ONLY ticking effects
protected List<TickingRuntimeEffectInstance> tickingEffects = new List<TickingRuntimeEffectInstance>();
protected override void UpdateEffects(float deltaTime)
{
// Only iterate effects that can tick
for (int i = 0; i < tickingEffects.Count; i++)
{
tickingEffects[i].Tick(deltaTime);
}
}
protected override void UpdateCollections(StatusEffect effect, RuntimeEffectInstance runtimeEffect)
{
base.UpdateCollections(effect, runtimeEffect);
// Track ticking effects separately
if (runtimeEffect is TickingRuntimeEffectInstance tickingEffect)
{
tickingEffects.Add(tickingEffect);
}
}
protected override void RemoveFromCollections(RuntimeEffectInstance runtimeEffect)
{
base.RemoveFromCollections(runtimeEffect);
// Remove from ticking list
if (runtimeEffect is TickingRuntimeEffectInstance tickingEffect)
{
tickingEffects.Remove(tickingEffect);
}
}
#region Effect Query Utilities
/// <summary>
/// Get all effects of a specific type, optionally from a specific source
/// </summary>
public List<RuntimeEffectInstance> GetEffects(StatusEffect effectType, Taggable source = null)
{
if (!activeEffectsByType.TryGetValue(effectType, out var effects))
return new List<RuntimeEffectInstance>();
if (source == null)
return new List<RuntimeEffectInstance>(effects);
return effects.Where(e => e.user == source).ToList();
}
/// <summary>
/// Get total stack count for a specific effect type
/// </summary>
public int GetStackCount(StatusEffect effectType, Taggable source = null)
{
var effects = GetEffects(effectType, source);
return effects.Sum(e => e.numberOfStacks);
}
/// <summary>
/// Get the strongest effect of a type (highest stack count)
/// </summary>
public RuntimeEffectInstance GetStrongestEffect(StatusEffect effectType)
{
if (!activeEffectsByType.TryGetValue(effectType, out var effects) || effects.Count == 0)
return null;
return effects.OrderByDescending(e => e.numberOfStacks).First();
}
/// <summary>
/// Get all damage ticking effects of a specific damage type
/// </summary>
public List<DamageTickingRuntimeEffectInstance> GetDamageEffects(DamageType damageType)
{
return tickingEffects
.OfType<DamageTickingRuntimeEffectInstance>()
.Where(effect => effect.sourceEffect is DamageOverTimeEffect source &&
source.damageType == damageType)
.ToList();
}
/// <summary>
/// Get total damage per second from all DOTs of a specific type
/// </summary>
public float GetTotalDPS(DamageType damageType)
{
return GetDamageEffects(damageType)
.Sum(effect => (effect.sourceEffect as DamageOverTimeEffect).baseDamagePerTick /
GameConstants.GameBalancing.EffectsTickingRate);
}
/// <summary>
/// Generic method to check for any effect matching a condition
/// </summary>
public bool HasEffectWhere<T>(System.Func<T, bool> predicate) where T : RuntimeEffectInstance
{
return activeEffects.OfType<T>().Any(predicate);
}
/// <summary>
/// Get remaining time for the longest duration effect of a type
/// </summary>
public float GetRemainingTime(StatusEffect effectType)
{
if (!activeEffectsByType.TryGetValue(effectType, out var effects) || effects.Count == 0)
return 0f;
var longestEffect = effects.OrderByDescending(e => e.endEffectTime).First();
return Mathf.Max(0f, longestEffect.endEffectTime - Time.time);
}
#endregion
#region Simplified Status Checks
// Your existing methods can now be simplified:
public bool IsBurning() => GetDamageEffects(DamageType.Fire).Count > 0;
public bool IsPoisoned() => GetDamageEffects(DamageType.Poison).Count > 0;
public bool IsBleeding() => GetDamageEffects(DamageType.Physical).Count > 0;
// Additional useful checks:
public int GetBurnStacks() => GetDamageEffects(DamageType.Fire).Sum(e => e.numberOfStacks);
public float GetBurnDPS() => GetTotalDPS(DamageType.Fire);
public float GetBurnTimeRemaining() => GetDamageEffects(DamageType.Fire).Max(e => e?.endEffectTime - Time.time ?? 0f);
#endregion
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 118e9e465521b054092a49272a44da7f

View File

@ -0,0 +1,42 @@
using UnityEngine;
public class TickingRuntimeEffectInstance : RuntimeEffectInstance
{
public float timeSinceLastTick = 0f;
public virtual void Tick(float deltaTime)
{
timeSinceLastTick += deltaTime;
if (timeSinceLastTick >= GameConstants.GameBalancing.EffectsTickingRate)
{
PerformTick();
timeSinceLastTick = 0f; // Reset timer after ticking
}
}
protected virtual void PerformTick()
{
// Override in specific effect types (DOT, HealOT, etc.)
// Example: Apply damage based on numberOfStacks
}
public override void OnEffectFirstApplied(int numberOfStacksApplied)
{
base.OnEffectFirstApplied(numberOfStacksApplied);
timeSinceLastTick = 0f;
}
public override void OnEffectRefreshed(int numberOfStacksAdded)
{
base.OnEffectRefreshed(numberOfStacksAdded);
// Optionally reset tick timer on refresh
// timeSinceLastTick = 0f;
}
public new void Reset()
{
base.Reset();
timeSinceLastTick = 0f;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: dd780057d9c90df4283c1bf95b94fd48

View File

@ -6,14 +6,26 @@ using UnityEngine;
public class StatusEffect : BaseEffect
{
public float duration;
public bool canApplyMultipleInstances;
public StackingRule stackingRule;
public bool applyToTargetsHit;
[Header("Should be toggled only when you want to apply the effect ONLY to yourself")]
public bool applyToSelf;
public float chanceToApply = 100f;
public int defaultNumberOfStacks = 1; //TODO: add chance to apply and increase number based on chance rolls
public override void ApplyEffect(Taggable user, List<Taggable> targets, BaseAbility source)
{
base.ApplyEffect(user, targets, source);
}
public virtual RuntimeEffectInstance CreateEffectInstance()
{
return CObjectPool<RuntimeEffectInstance>.Get();
}
}
public enum StackingRule
{
StackUnlimited,
Refresh_And_ReplaceIfHigher,
}

View File

@ -110,7 +110,7 @@ public partial class AbilityEffectEditorWindow
private void ApplyEffectTypeSpecificData(BaseEffect effect)
{
if (effect is InstantValueEffect instantEffect)
/*if (effect is InstantValueEffect instantEffect)
{
instantEffect.baseValue = effectData.GetOrCreateTypeSpecific<float>("baseValue");
instantEffect.damageType = effectData.GetOrCreateTypeSpecific<DamageType>("damageType");
@ -131,7 +131,7 @@ public partial class AbilityEffectEditorWindow
List<StatInfluence> influences = effectData.GetOrCreateTypeSpecific<List<StatInfluence>>("statInfluences");
statusEffect.influencingStats = new List<StatInfluence>(influences);
}
}*/
}
private BaseEffect[] GetAllEffects()

View File

@ -21,12 +21,12 @@ public class AbsorbInterceptor : BrokerInterceptor
if (finalValue >= 0) return;
AbsorbArgs absorbArgs = new AbsorbArgs()
{
user = user,
absorbedDamage = false,
absorbDepleted = false
};
AbsorbArgs absorbArgs = CObjectPool<AbsorbArgs>.Get();
absorbArgs.user = user;
absorbArgs.absorbedDamage = false;
absorbArgs.absorbDepleted = false;
if (absorbEffect.IsActive)
{
@ -39,10 +39,12 @@ public class AbsorbInterceptor : BrokerInterceptor
absorbArgs.absorbedDamage = true;
absorbArgs.absorbDepleted = absorbEffect.currentAmount <= 0;
args.currentValue = finalValue;
}
broker.OnAbsorb.Invoke(absorbArgs);
CObjectPool<AbsorbArgs>.Release(absorbArgs);
}
}

View File

@ -22,19 +22,21 @@ public class BasicStatAmplificationCalculator : BrokerInterceptor
Debug.LogError("character stat influence calculator: stats null");
return;
}
foreach (var statInfluence in args.effect.influencingStats)
for (int i = 0; i < args.sourceEffect.influencingStats.Count; i++)
{
if (stats.primaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat stat))
if(stats.primaryStatsDictionary.TryGetValue(args.sourceEffect.influencingStats[i].statTag.name.ToLower(), out CharacterStat stat))
{
finalValue += stat.Value * statInfluence.percentInfluence;
finalValue += stat.Value * args.sourceEffect.influencingStats[i].percentInfluence;
}
else if (stats.secondaryStatsDictionary.TryGetValue(statInfluence.statTag.name.ToLower(), out CharacterStat secondaryStat))
else if (stats.secondaryStatsDictionary.TryGetValue(args.sourceEffect.influencingStats[i].statTag.name.ToLower(), out CharacterStat secondaryStat))
{
finalValue += secondaryStat.Value * statInfluence.percentInfluence;
finalValue += secondaryStat.Value * args.sourceEffect.influencingStats[i].percentInfluence;
}
if (statInfluence.statTag.name.ToLower().Contains("attack")) args.damageType = DamageType.Attack;
else if (statInfluence.statTag.name.ToLower().Contains("spell")) args.damageType = DamageType.Spell;
if (args.sourceEffect.influencingStats[i].statTag.name.ToLower().Contains("attack")) args.damageType = DamageType.Attack;
else if (args.sourceEffect.influencingStats[i].statTag.name.ToLower().Contains("spell")) args.damageType = DamageType.Spell;
}
if (IsCrit(stats))
{
finalValue *= (1 + stats.GetStat("critdamage").Value / 100f);

View File

@ -0,0 +1,108 @@
using Kryz.CharacterStats;
using Kryz.CharacterStats.Examples;
using UnityEngine;
public class BasicStatModifierCalculator : BrokerInterceptor
{
float percentStatMitigation;
float reducedDamage;
protected override void Awake()
{
base.Awake();
broker.OnOutgoingDamage.Subscribe(CalculateDamageModsBasedOnStats, GameConstants.BrokerEventPriority.BasicStatAmplification);
broker.OnIncomingDamage.Subscribe(HandleStatMitigation, GameConstants.BrokerEventPriority.BasicStatMitigation);
}
private void CalculateDamageModsBasedOnStats(DamageArgs args)
{
float finalValue = args.currentValue;
if (stats == null)
{
Debug.LogError("character stat influence calculator: stats null");
return;
}
for (int i = 0; i < args.sourceEffect.influencingStats.Count; i++)
{
if (stats.primaryStatsDictionary.TryGetValue(args.sourceEffect.influencingStats[i].statTag.name.ToLower(), out CharacterStat stat))
{
finalValue += stat.Value * args.sourceEffect.influencingStats[i].percentInfluence;
}
else if (stats.secondaryStatsDictionary.TryGetValue(args.sourceEffect.influencingStats[i].statTag.name.ToLower(), out CharacterStat secondaryStat))
{
finalValue += secondaryStat.Value * args.sourceEffect.influencingStats[i].percentInfluence;
}
}
if (IsCrit(stats))
{
finalValue *= (1 + stats.GetStat("critdamage").Value / 100f);
args.isCrit = true;
}
else
args.isCrit = false;
args.currentValue = finalValue;
}
private void HandleStatMitigation(DamageArgs args)
{
if (args.currentValue >= 0) return;
float finalValue = args.currentValue;
switch (GetCorrectMitigationType(args))
{
case DamageType.Attack:
default:
{
percentStatMitigation = Mathf.Clamp((stats.GetStat("armor").Value * GameConstants.CharacterStatsBalancing.PercentArmorIntoDamageReduction), 0, GameConstants.CharacterStatsBalancing.MaximumPercentDamageReductionFromArmor);
}
break;
case DamageType.Spell:
{
percentStatMitigation = Mathf.Clamp((stats.GetStat("magicresistance").Value * GameConstants.CharacterStatsBalancing.PercentMagicResistanceIntoDamageReduction), 0, GameConstants.CharacterStatsBalancing.MaximumPercentDamageReductionFromMagicResistance);
}
break;
}
reducedDamage = args.currentValue * percentStatMitigation;
finalValue += Mathf.Abs(reducedDamage);
//Debug.Log(gameObject.name + " receiving dmg = " + incomingValue + $" after mitigations from {(dmgType == DamageType.Attack ? nameof(character.Armor) : nameof(character.MagicResistance))}");
if (finalValue > 0) //avoid damage ultra mitigated turning into healing
finalValue = 0;
args.currentValue = finalValue;
}
private DamageType GetCorrectMitigationType(DamageArgs args)
{
switch (args.damageType)
{
default:
case DamageType.Physical:
case DamageType.Attack:
return DamageType.Attack;
case DamageType.Spell:
case DamageType.Fire:
case DamageType.Cold:
case DamageType.Lightning:
case DamageType.Mystic:
case DamageType.Poison:
case DamageType.Shadow:
return DamageType.Spell;
}
}
private bool IsCrit(CharacterStats stats)
{
return MathHelpers.RollChancePercent(stats.GetStat("critchance").Value);
//return Random.Range(0, 100) < stats.CritChance.Value;
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ef8391abf380f634f970af8c9eac8275

View File

@ -18,12 +18,13 @@ public class BlockInterceptor : BrokerInterceptor
protected void HandleBlockMitigation(DamageArgs args)
{
if (args.currentValue >= 0) return;
if (args.applicationMethod == EffectApplicationMethod.Tick) return;
BlockArgs blockArgs = new BlockArgs()
{
user = user,
blockedSuccessfully = false
};
BlockArgs blockArgs = CObjectPool<BlockArgs>.Get();
blockArgs.user = user;
blockArgs.blockedSuccessfully = false;
if(HasBlocked())
{
@ -45,6 +46,8 @@ public class BlockInterceptor : BrokerInterceptor
}
broker.OnBlock.Invoke(blockArgs);
CObjectPool<BlockArgs>.Release(blockArgs);
}

View File

@ -18,6 +18,6 @@ public class DebugBroker : MonoBehaviour
private void DebugDamageArgs(string prefix, DamageArgs args)
{
Debug.Log($"Broker Debugger || {prefix} ||: {args.user}'s {args.effect.name} dealing damage to: {args.target} => {args.currentValue}, isCrit? {args.isCrit}, dmgType={args.damageType}, targets hit total ={args.totalTargetsHit}");
Debug.Log($"Broker Debugger || {prefix} ||: {args.user}'s {args.sourceEffect.name} dealing damage to: {args.target} => {args.currentValue}, isCrit? {args.isCrit}, dmgType={args.damageType}, targets hit total ={args.totalTargetsHit}");
}
}

View File

@ -12,11 +12,14 @@ public class DodgeInterceptor : BrokerInterceptor
private void HandleDodge(DamageArgs args)
{
DodgeArgs dodgeArgs = new DodgeArgs()
{
user = user,
dodgedSuccessfully = false
};
if (args.currentValue >= 0) return;
if (args.applicationMethod == EffectApplicationMethod.Tick) return;
DodgeArgs dodgeArgs = CObjectPool<DodgeArgs>.Get();
dodgeArgs.user = user;
dodgeArgs.dodgedSuccessfully = false;
if (HasDodged())
{
@ -29,6 +32,8 @@ public class DodgeInterceptor : BrokerInterceptor
}
broker.OnDodge.Invoke(dodgeArgs);
CObjectPool<DodgeArgs>.Release(dodgeArgs);
}
protected bool HasDodged()

View File

@ -16,11 +16,11 @@ public class InvulnerabilityInterceptor : BrokerInterceptor
private void HandleInvulnerability(DamageArgs args)
{
InvulnerabilityArgs invulnerabilityArgs = new InvulnerabilityArgs()
{
user = user,
isImmune = false
};
InvulnerabilityArgs invulnerabilityArgs = CObjectPool<InvulnerabilityArgs>.Get();
invulnerabilityArgs.user = user;
invulnerabilityArgs.isImmune = false;
if(health.Invulnerable)
{
@ -29,5 +29,7 @@ public class InvulnerabilityInterceptor : BrokerInterceptor
}
broker.OnInvulnerable.Invoke(invulnerabilityArgs);
CObjectPool<InvulnerabilityArgs>.Release(invulnerabilityArgs);
}
}

View File

@ -0,0 +1,23 @@
using UnityEngine;
public class PassiveEffectsApplicator : BrokerInterceptor
{
protected override void Awake()
{
base.Awake();
broker.OnOutgoingDamage.Subscribe(HandlePassiveAccumulatedAmplification, GameConstants.BrokerEventPriority.PassiveAmplificationApplicator);
broker.OnIncomingDamage.Subscribe(HandlePassiveAccumulatedMitigation, GameConstants.BrokerEventPriority.PassiveMitigationApplicator);
}
private void HandlePassiveAccumulatedAmplification(DamageArgs args)
{
args.currentValue = args.currentValue * (1 + args.outgoingAccumulator);
}
private void HandlePassiveAccumulatedMitigation(DamageArgs args)
{
args.currentValue = args.currentValue * (1 + args.incomingAccumulator);
}
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f80693a3e5c20f74c815878825fcb8c8

View File

@ -26,6 +26,7 @@ public class EntityEventBroker : MonoBehaviour
public OrderedEvent<DodgeArgs> OnDodge = new OrderedEvent<DodgeArgs>();
public OrderedEvent<BlockArgs> OnBlock = new OrderedEvent<BlockArgs>();
public OrderedEvent<AbsorbArgs> OnAbsorb = new OrderedEvent<AbsorbArgs>();
public OrderedEvent<DamageType> OnAilmentApplied = new OrderedEvent<DamageType>();
}

View File

@ -5,11 +5,13 @@ using UnityEngine.Events;
public class DamageArgs : IResettable
{
public BaseAbility source;
public BaseEffect effect;
public BaseAbility sourceAbility;
public BaseEffect sourceEffect;
public Taggable user;
public Taggable target;
public float currentValue;
public float outgoingAccumulator;
public float incomingAccumulator;
public DamageType damageType;
public EffectApplicationMethod applicationMethod;
public bool isCrit;
@ -18,16 +20,18 @@ public class DamageArgs : IResettable
public void Reset()
{
source = null;
effect = null;
sourceAbility = null;
sourceEffect = null;
user = null;
target = null;
currentValue = 0f;
isCrit = false;
targetDead = false;
applicationMethod = default;
totalTargetsHit = 0;
outgoingAccumulator = 0f;
incomingAccumulator = 0f;
damageType = default;
applicationMethod = default;
isCrit = false;
totalTargetsHit = 0;
targetDead = false;
}
}
@ -38,6 +42,8 @@ public class HealArgs : IResettable
public Taggable user;
public Taggable target;
public float currentValue;
public float outgoingAccumulator;
public float incomingAccumulator;
public EffectApplicationMethod applicationMethod;
public bool isCrit;
public int totalTargetsHit;
@ -49,8 +55,10 @@ public class HealArgs : IResettable
user = null;
target = null;
currentValue = 0f;
isCrit = false;
outgoingAccumulator = 0f;
incomingAccumulator = 0f;
applicationMethod = default;
isCrit = false;
totalTargetsHit = 0;
}
}

View File

@ -84,19 +84,21 @@ public static class GameConstants
[System.Serializable]
public static class BrokerEventPriority
{
public const int BasicStatAmplification = 0;
public const int PassiveAmplificationEffects = 5;
public const int TemporaryAmplificationMods = 10;
public const int BasicStatAmplification = 100;
public const int PassiveAmplificationEffects = 200;
public const int PassiveAmplificationApplicator = 250;
public const int TemporaryAmplificationMods = 300;
public const int Invulnerability = 0;
public const int Dodge = 2;
public const int Block = 3;
public const int BasicStatMitigation = 5;
public const int PassiveMitigationEffects = 7;
public const int TemporaryMitigationMods = 10;
public const int Absorb = 15;
public const int Procs = 30;
public const int Invulnerability = 25;
public const int Dodge = 50;
public const int Block = 75;
public const int BasicStatMitigation = 100;
public const int PassiveMitigationEffects = 200;
public const int PassiveMitigationApplicator = 250;
public const int TemporaryMitigationMods = 300;
public const int Absorb = 400;
public const int Procs = 800;
}
public static class Input
@ -265,6 +267,7 @@ public static class GameConstants
}
public static class GameBalancing
{
public const float EffectsTickingRate = 0.5f;
public const int TotalPagesPerAbilityTome = 1;
public const int AbilityTomeDropChance = 5;

View File

@ -10,7 +10,6 @@ public class Health : Resource
protected EntityEventBroker broker;
protected AbsorbEffectInstance absorbEffectInstance;
protected DamageIncomeModifierEffectInstance damageIncomeModifierEffectInstance;
public UnityEvent<float> onMaxHealthChanged = new UnityEvent<float>();
public UnityEvent onDeath = new UnityEvent();
@ -41,7 +40,6 @@ public class Health : Resource
broker = GetComponent<EntityEventBroker>();
character = GetComponent<CharacterStats>();
absorbEffectInstance = GetComponent<AbsorbEffectInstance>();
damageIncomeModifierEffectInstance = GetComponent<DamageIncomeModifierEffectInstance>();
@ -71,24 +69,6 @@ public class Health : Resource
}
protected void HandleDamageIncomeModifierEffects()
{
if (incomingValue < 0)
{
if (damageIncomeModifierEffectInstance.IsActive)
{
//Debug.Log("Incoming damage b4 mitigation: " + incomingValue);
incomingValue = damageIncomeModifierEffectInstance.ModifyDamageIncome(incomingValue);
if (incomingValue > 0) //avoid damage ultra mitigated turning into healing
incomingValue = 0;
}
//Debug.Log("Incoming damage after mitigation: " + incomingValue);
}
}
public void ApplyDamage(DamageArgs args)
{
if (isDead) return;
@ -142,9 +122,6 @@ public class Health : Resource
if (invulnerable && incomingValue < 0) return;
HandleDamageIncomeModifierEffects();
currentValue += incomingValue;
currentValue = Mathf.Clamp(currentValue, 0, maxValue);
@ -179,71 +156,6 @@ public class Health : Resource
onResourceChanged.Invoke(currentValue);
}
public void ChangeValue(float value, int dmgType, bool isCrit)
{
//Debug.Log("Value to change: " + value);
if (isDead) return;
incomingValue = value;
//Debug.Log(gameObject.name + " receiving dmg = " + incomingValue + " before mitigations " + (DamageType)dmgType);
if (invulnerable && incomingValue < 0)
{
return;
}
if (incomingValue < 0)
{
HandleNegativeValue(dmgType, isCrit);
}
else
{
HandlePositiveValue();
}
}
protected void HandleNegativeValue(int dmgType, bool isCrit)
{
if (incomingValue >= 0) return;
HandleDamageIncomeModifierEffects();
currentValue += incomingValue;
currentValue = Mathf.Clamp(currentValue, 0, maxValue);
if (currentValue == 0)
{
//dead;
onDeath.Invoke();
}
//Debug.Log("CurrentHealth: " + currentValue);
onResourceChanged.Invoke(currentValue);
}
protected void HandlePositiveValue()
{
currentValue += incomingValue;
currentValue = Mathf.Clamp(currentValue, 0, maxValue);
if (currentValue == 0)
{
//dead;
onDeath.Invoke();
}
//Debug.Log("CurrentHealth: " + currentValue);
onResourceChanged.Invoke(currentValue);
}
public override float GetMaxValue()
{
return base.GetMaxValue();

View File

@ -7,6 +7,9 @@ public class Taggable : MonoBehaviour
{
public List<TargetTag> targetTag = new List<TargetTag>();
private EntityEventBroker _cachedBroker;
public EntityEventBroker Broker => _cachedBroker ??= GetComponent<EntityEventBroker>();
public bool IsValidTarget(List<TargetTag> tags)
{
for (int i = 0; i < targetTag.Count; i++)