Compare commits

...

1 Commits

Author SHA1 Message Date
ddd7caad77 possible solution for ability system 2024-08-21 21:48:06 +01:00
78 changed files with 2002 additions and 368 deletions

View File

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

View File

@ -0,0 +1,37 @@
%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: 4aedcd11782e6544e8786936943468a6, type: 3}
m_Name: IceShard_Template
m_EditorClassIdentifier:
abilityName: Ice Shard
description: Hurl an ice shard towards the targeted direction
icon: {fileID: 21300000, guid: 50a820d3228a2bf4da98a6e769e90f12, type: 3}
targettingTags:
- {fileID: 11400000, guid: 3ac5bfbf7e1fbdd4baec1c17bd3d874c, type: 2}
- {fileID: 11400000, guid: 201eca8f8c72ba74dbb0854cad29be4f, type: 2}
tags:
- {fileID: 11400000, guid: 4e6f036fb4aad9b428694360fcc62f88, type: 2}
- {fileID: 11400000, guid: 918ee6f8846e6a9449166ac16b6330ae, type: 2}
abilityEffects:
- {fileID: 11400000, guid: d441f01dcc2dc5943a605b0bbffa1a03, type: 2}
castTime: 0.5
manaCost: 6
healthCost: 0
classResourceCost: 0
cooldown: 0
castableWhileMoving: 0
animationType: 1
projectilePrefab: {fileID: 4298339421658607672, guid: e2e28eac2a915464284517bc9f1425b0, type: 3}
projectileSpeed: 10
lifeSpan: 1.5
canPierce: 0
canHitSelf: 0

View File

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

View File

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

View File

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

View File

@ -0,0 +1,19 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New Anti-Projectile Ability", menuName = "RiftMayhem/Abilities/Anti-Projectile Ability")]
public class AntiProjectileAbilityTemplate : BaseAbility
{
public GameObject antiProjectilePrefab;
public float duration;
public bool followUser;
public override IAbilityProperties CreateProperties()
{
return new AntiProjectileAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dcd80a6f46ee35e4ca73befb46c40e7d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New AoE Ability", menuName = "RiftMayhem/Abilities/AoE Ability")]
public class AreaOfEffectAbilityTemplate : BaseAbility
{
public GameObject aoePrefab;
public float radius;
public float lifeSpan;
public float telegraphDelay;
public bool spawnUnderUser;
public override IAbilityProperties CreateProperties()
{
return new AreaOfEffectAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4fd10732ea3f0264a82b38345f89bdc4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,19 @@
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New AoE Over Time Ability", menuName = "RiftMayhem/Abilities/AoE Over Time Ability")]
public class AreaOfEffectOverTimeAbilityTemplate : AreaOfEffectAbilityTemplate
{
[Header("Over Time Settings")]
public float duration;
public bool followUser;
public bool followTarget;
public bool damageFollowingTarget;
public override IAbilityProperties CreateProperties()
{
return new AreaOfEffectOverTimeAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09d6928bbd92a3c4890a0be6e545de0e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public abstract class BaseAbility : ScriptableObject
{
public string abilityName;
public string description;
public Sprite icon;
public List<TargetTag> targettingTags = new List<TargetTag>();
public List<GameTag> tags = new List<GameTag>();
public List<BaseEffect> abilityEffects = new List<BaseEffect>();
public float castTime;
public float manaCost;
public float healthCost = 0;
public float classResourceCost = 0;
public float cooldown;
public bool castableWhileMoving;
public AbilityAnimationType animationType;
public abstract IAbilityProperties CreateProperties();
private void OnValidate()
{
InitializeUniqueTags();
}
private void OnEnable()
{
InitializeUniqueTags();
}
public void InitializeUniqueTags()
{
tags.Clear();
// Iterate through each effect and add unique GameTags to uniqueTags list
foreach (var effect in abilityEffects)
{
if (effect != null)
{
foreach (var tag in effect.tags)
{
if (!tags.Contains(tag))
{
tags.Add(tag);
}
}
foreach (var influencingStat in effect.influencingStats)
{
if (!tags.Contains(influencingStat.statTag))
{
tags.Add(influencingStat.statTag);
}
}
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec6e4aa3effacb4468d53cb718f1c98a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New Channeled Ability", menuName = "RiftMayhem/Abilities/Channeled Ability")]
public class ChanneledAbilityTemplate : BaseAbility
{
public GameObject prefab;
public float duration;
public float radius;
public bool canHitSelf;
public bool followUser;
public override IAbilityProperties CreateProperties()
{
return new ChanneledAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 95e386d09f94bf444aacbb26ed5182db
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New Potion Ability", menuName = "RiftMayhem/Abilities/Potion Ability")]
public class PotionAbilityTemplate : BaseAbility
{
public float healingPercent;
public override IAbilityProperties CreateProperties()
{
return new PotionAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 171d73bfd42fe054ca28b6a8f4ef9358
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New Projectile Ability", menuName = "RiftMayhem/Abilities/Projectile Ability")]
public class ProjectileAbilityTemplate : BaseAbility
{
public GameObject projectilePrefab;
public float projectileSpeed;
public float lifeSpan;
public bool canPierce;
public bool canHitSelf;
public override IAbilityProperties CreateProperties()
{
return new ProjectileAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4aedcd11782e6544e8786936943468a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,23 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New Slash Ability", menuName = "RiftMayhem/Abilities/Slash Ability")]
public class SlashAbilityTemplate : BaseAbility
{
public GameObject slashPrefab;
public float range;
public bool regenHealthOnHit;
public bool regenManaOnHit;
public float healthOnHit;
public float manaOnHit;
public override IAbilityProperties CreateProperties()
{
return new SlashAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07d783530f392274182059bc1f32be1e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
[CreateAssetMenu(fileName = "New Summon Ability", menuName = "RiftMayhem/Abilities/Summon Ability")]
public class SummonAbilityTemplate : BaseAbility
{
public GameObject minionPrefab;
public override IAbilityProperties CreateProperties()
{
return new SummonAbilityProperties();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0a746ba64a0d9204c89fbf784ab69339
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,82 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AbilityInstance
{
public string id;
public BaseAbility template;
public float currentCooldown;
public float currentManaCost;
public float currentHealthCost;
public float currentClassResourceCost;
public List<BaseEffect> currentEffects;
public List<IAbilityModifier> currentModifiers;
public IAbilityProperties properties;
public AbilityInstance(BaseAbility template)
{
this.id = System.Guid.NewGuid().ToString();
this.template = template;
this.currentCooldown = template.cooldown;
this.currentManaCost = template.manaCost;
this.currentHealthCost = template.healthCost;
this.currentClassResourceCost = template.classResourceCost;
this.currentEffects = new List<BaseEffect>(template.abilityEffects);
this.currentModifiers = new List<IAbilityModifier>();
this.properties = template.CreateProperties();
this.properties.Initialize(template);
}
public void AddModifier(IAbilityModifier abilityModifier)
{
currentModifiers.Add(abilityModifier);
}
public void RemoveModifier(IAbilityModifier abilityModifier)
{
currentModifiers.Remove(abilityModifier);
}
public void Execute(PhotonView user, Taggable userTag, Vector3 targetPosition, Taggable targetTag)
{
AbilityExecutionContext context = new AbilityExecutionContext
{
User = user,
UserTag = userTag,
TargetPosition = targetPosition,
TargetTag = targetTag,
Cooldown = currentCooldown,
ManaCost = currentManaCost,
HealthCost = currentHealthCost,
ClassResourceCost = currentClassResourceCost,
Effects = currentEffects,
Modifiers = currentModifiers
};
SpendResourcesNecessary(user);
properties.ModifiedExecution(context);
/*foreach (var effect in context.Effects)
{
effect.ApplyEffect(context.UserTag, new List<Taggable> { context.TargetTag });
}
currentCooldown = context.Cooldown;
currentManaCost = context.ManaCost;
currentHealthCost = context.HealthCost;
currentClassResourceCost = context.ClassResourceCost;*/
}
public void SpendResourcesNecessary(PhotonView user)
{
user.GetComponent<Mana>().ChangeValue(-currentManaCost);
user.GetComponent<Health>().ChangeValue(-currentHealthCost);
user.GetComponent<ClassResource>()?.ChangeValue(-currentClassResourceCost);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4bf69549f85408344a7d334b55755d93
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,37 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AntiProjectileAbilityProperties : IAbilityProperties
{
public float duration;
public bool followUser;
private GameObject antiProjectilePrefab;
public void Initialize(BaseAbility template)
{
if (template is AntiProjectileAbilityTemplate antiProjectileTemplate)
{
duration = antiProjectileTemplate.duration;
followUser = antiProjectileTemplate.followUser;
antiProjectilePrefab = antiProjectileTemplate.antiProjectilePrefab;
}
}
public void ModifiedExecution(AbilityExecutionContext context)
{
GameObject antiProjectileGO = PhotonNetwork.Instantiate("Abilities/" + antiProjectilePrefab.name, context.User.transform.position, context.User.transform.rotation);
NetworkedAntiProjectile networkedAntiProjectile = antiProjectileGO.GetComponent<NetworkedAntiProjectile>();
if (networkedAntiProjectile != null)
{
networkedAntiProjectile.Initialize(context, this);
}
}
public float GetLifeSpan() => duration;
public bool GetCanHitSelf() => false;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1b55bef88a4c5fd44a22739a6ec6ebeb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,49 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AreaOfEffectAbilityProperties : IAbilityProperties
{
public float radius;
public float lifeSpan;
public float telegraphDelay;
public bool canHitSelf;
public bool spawnUnderUser;
private GameObject aoePrefab;
public bool GetCanHitSelf()
{
return canHitSelf;
}
public float GetLifeSpan()
{
return lifeSpan;
}
public virtual void Initialize(BaseAbility template)
{
if (template is AreaOfEffectAbilityTemplate aoeTemplate)
{
radius = aoeTemplate.radius;
lifeSpan = aoeTemplate.lifeSpan;
spawnUnderUser = aoeTemplate.spawnUnderUser;
aoePrefab = aoeTemplate.aoePrefab;
telegraphDelay = aoeTemplate.telegraphDelay;
}
}
public virtual void ModifiedExecution(AbilityExecutionContext context)
{
GameObject aoeGO = PhotonNetwork.Instantiate("Abilities/" + aoePrefab.name, context.TargetPosition, Quaternion.identity);
NetworkedAreaOfEffect networkedAOE = aoeGO.GetComponent<NetworkedAreaOfEffect>();
if (networkedAOE != null)
{
networkedAOE.Initialize(context, this);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d98ad1e252315646adbbd532c2ec6ef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,39 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AreaOfEffectOverTimeAbilityProperties : AreaOfEffectAbilityProperties
{
public float duration;
public bool followUser;
public bool followTarget;
public bool damageFollowingTarget;
private GameObject prefab;
public override void Initialize(BaseAbility template)
{
base.Initialize(template);
if (template is AreaOfEffectOverTimeAbilityTemplate aoeotTemplate)
{
duration = aoeotTemplate.duration;
followUser = aoeotTemplate.followUser;
followTarget = aoeotTemplate.followTarget;
damageFollowingTarget = aoeotTemplate.damageFollowingTarget;
prefab = aoeotTemplate.aoePrefab;
}
}
public override void ModifiedExecution(AbilityExecutionContext context)
{
GameObject aoeGO = PhotonNetwork.Instantiate("Abilities/" + prefab.name, context.TargetPosition, Quaternion.identity);
NetworkedAreaOfEffectOverTime networkedAOEOT = aoeGO.GetComponent<NetworkedAreaOfEffectOverTime>();
if (networkedAOEOT != null)
{
networkedAOEOT.Initialize(context, this);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4ebea300a1db6cf4aa2fb9eba0283b0d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,14 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public interface IAbilityProperties
{
void Initialize(BaseAbility template);
void ModifiedExecution(AbilityExecutionContext context);
float GetLifeSpan();
bool GetCanHitSelf();
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8e523d871d41ec84e8429ff314daf3fe
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,41 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class ChanneledAbilityProperties : IAbilityProperties
{
public float duration;
public float radius;
public bool canHitSelf;
public bool followUser;
private GameObject prefab;
public void Initialize(BaseAbility template)
{
if (template is ChanneledAbilityTemplate channeledTemplate)
{
duration = channeledTemplate.duration;
radius = channeledTemplate.radius;
canHitSelf = channeledTemplate.canHitSelf;
followUser = channeledTemplate.followUser;
prefab = channeledTemplate.prefab;
}
}
public void ModifiedExecution(AbilityExecutionContext context)
{
GameObject channeledGO = PhotonNetwork.Instantiate("Abilities/" + prefab.name, context.User.transform.position, context.User.transform.rotation);
NetworkedChanneling networkedChanneling = channeledGO.GetComponent<NetworkedChanneling>();
if (networkedChanneling != null)
{
networkedChanneling.Initialize(context, this);
}
}
public float GetLifeSpan() => duration;
public bool GetCanHitSelf() => canHitSelf;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39d9378d941174144b4d691088981463
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,32 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class PotionAbilityProperties : IAbilityProperties
{
public float healingPercent;
public void Initialize(BaseAbility template)
{
if (template is PotionAbilityTemplate potionTemplate)
{
healingPercent = potionTemplate.healingPercent;
}
}
public void ModifiedExecution(AbilityExecutionContext context)
{
Health userHealth = context.User.GetComponent<Health>();
if (userHealth != null)
{
float healAmount = userHealth.GetMaxValue() * healingPercent;
userHealth.ChangeValue(healAmount);
}
}
public float GetLifeSpan() => 0f; // Potions typically have instant effect
public bool GetCanHitSelf() => true;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2332831b88d738446aa91cf6c007add3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,48 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class ProjectileAbilityProperties : IAbilityProperties
{
public float projectileSpeed;
public float lifeSpan;
public bool canPierce;
public bool canHitSelf;
private GameObject projectilePrefab;
public bool GetCanHitSelf()
{
return canHitSelf;
}
public float GetLifeSpan()
{
return lifeSpan;
}
public void Initialize(BaseAbility template)
{
if (template is ProjectileAbilityTemplate projectileTemplate)
{
projectileSpeed = projectileTemplate.projectileSpeed;
lifeSpan = projectileTemplate.lifeSpan;
canPierce = projectileTemplate.canPierce;
canHitSelf = projectileTemplate.canHitSelf;
projectilePrefab = projectileTemplate.projectilePrefab;
}
}
public void ModifiedExecution(AbilityExecutionContext context)
{
GameObject projectileGO = PhotonNetwork.Instantiate("Abilities/" + projectilePrefab.name, context.User.GetComponentInChildren<ProjectileSpawnLocationController>().transform.position, context.User.GetComponentInChildren<ProjectileSpawnLocationController>().transform.rotation);
NetworkedProjectile networkedProjectile = projectileGO.GetComponent<NetworkedProjectile>();
if (networkedProjectile != null)
{
networkedProjectile.Initialize(context, this);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8134918c95b031b49b243d8588a9a667
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class SlashAbilityProperties : IAbilityProperties
{
public float range;
public bool regenHealthOnHit;
public bool regenManaOnHit;
public float healthOnHit;
public float manaOnHit;
private GameObject slashPrefab;
public void Initialize(BaseAbility template)
{
if (template is SlashAbilityTemplate slashTemplate)
{
range = slashTemplate.range;
regenHealthOnHit = slashTemplate.regenHealthOnHit;
regenManaOnHit = slashTemplate.regenManaOnHit;
healthOnHit = slashTemplate.healthOnHit;
manaOnHit = slashTemplate.manaOnHit;
slashPrefab = slashTemplate.slashPrefab;
}
}
public void ModifiedExecution(AbilityExecutionContext context)
{
GameObject slashGO = PhotonNetwork.Instantiate("Abilities/" + slashPrefab.name, context.User.transform.position, context.User.transform.rotation);
NetworkedSlash networkedSlash = slashGO.GetComponent<NetworkedSlash>();
if (networkedSlash != null)
{
networkedSlash.Initialize(context, this);
}
}
public float GetLifeSpan() => 0.5f; // Adjust this value as needed
public bool GetCanHitSelf() => false;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 064c44c8976c7b94b8663224456b2300
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class SummonAbilityProperties : IAbilityProperties
{
private GameObject minionPrefab;
public void Initialize(BaseAbility template)
{
if (template is SummonAbilityTemplate summonTemplate)
{
minionPrefab = summonTemplate.minionPrefab;
}
}
public void ModifiedExecution(AbilityExecutionContext context)
{
GameObject minionGO = PhotonNetwork.Instantiate("Abilities/" + minionPrefab.name, context.User.transform.position, context.User.transform.rotation);
NetworkedSummonedMinion networkedMinion = minionGO.GetComponent<NetworkedSummonedMinion>();
if (networkedMinion != null)
{
networkedMinion.Initialize(context, this);
}
}
public float GetLifeSpan() => 0f; // Summons typically don't have a lifespan
public bool GetCanHitSelf() => false;
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 541d4fe7cefd00548bd59a7f5109c387
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,24 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AbilityExecutionContext
{
public PhotonView User { get; set; }
public Taggable UserTag { get; set; }
public Vector3 TargetPosition { get; set; }
public Taggable TargetTag { get; set; }
public float Cooldown { get; set; }
public float ManaCost { get; set; }
public float HealthCost { get; set; }
public float ClassResourceCost { get; set; }
public List<BaseEffect> Effects { get; set; }
public List<IAbilityModifier> Modifiers { get; set; }
public BaseAbility AbilityTemplate { get; set; }
public AbilityInstance AbilityInstance { get; set; }
// Add any other relevant execution data
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 504972c68665c9048b13ace4c82b2bcd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public interface IAbilityModifier
{
void ApplyModifier(AbilityInstance instance);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7acc8438eba362f44900e746928e422b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

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

View File

@ -0,0 +1,102 @@
using UnityEngine;
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Events;
namespace Template_RuntimeInstance
{
public abstract class NetworkedAbilityBase : MonoBehaviourPunCallbacks
{
[Header("Visuals")]
[SerializeField] private GameObject hitParticlesPrefab;
[SerializeField] private GameObject visuals;
[Header("Common Settings")]
public PhotonView photonView;
public PhotonView owner;
public Taggable ownerTag;
public BaseAbility abilityTemplate;
public AbilityInstance abilityInstance;
public float lifeSpan;
public bool canHitSelf;
public AbilityExecutionContext context;
protected bool waitingForDestroy = false;
protected List<Taggable> targets = new List<Taggable>();
public UnityEvent<PhotonView, Taggable, List<Taggable>> onHitHappened = new UnityEvent<PhotonView, Taggable, List<Taggable>>();
protected virtual void Awake()
{
photonView = GetComponent<PhotonView>();
}
public virtual void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
this.context = context;
owner = context.User;
ownerTag = context.UserTag;
abilityTemplate = context.AbilityTemplate;
lifeSpan = properties.GetLifeSpan();
canHitSelf = properties.GetCanHitSelf();
for (int i = 0; i < context.Modifiers.Count; i++)
{
context.Modifiers[i].ApplyModifier(context.AbilityInstance);
}
if (photonView.IsMine)
{
photonView.RPC(nameof(RPC_RemoteInit), RpcTarget.Others, AbilityIndexer.Instance.Abilities.IndexOf(abilityTemplate));
StartCoroutine(SelfDestruct());
}
}
[PunRPC]
protected virtual void RPC_RemoteInit(int abilityIndex)
{
abilityTemplate = AbilityIndexer.Instance.Abilities[abilityIndex];
}
[PunRPC]
private void RPC_DisableVisuals()
{
visuals.SetActive(false);
}
protected virtual void ApplyEffects(List<Taggable> targets)
{
if (!photonView.IsMine) return;
foreach (BaseEffect effect in context.Effects)
{
effect.ApplyEffect(ownerTag, targets);
}
}
protected virtual IEnumerator SelfDestruct()
{
yield return new WaitForSeconds(lifeSpan);
waitingForDestroy = true;
StartCoroutine(DelayedDestroy());
}
protected virtual IEnumerator DelayedDestroy()
{
photonView.RPC(nameof(RPC_DisableVisuals), RpcTarget.All);
yield return new WaitForSeconds(1.5f);
PhotonNetwork.Destroy(photonView);
}
protected virtual bool IsValidTarget(Taggable target)
{
return target != null &&
(canHitSelf || target != ownerTag) &&
target.IsValidTarget(abilityTemplate.targettingTags);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 50bdce70855772146bb66c989741fe12
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,63 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Template_RuntimeInstance
{
public class NetworkedAntiProjectile : NetworkedAbilityBase
{
public bool followUser;
public GameObject visuals;
public UnityEvent onProjectileBlocked = new UnityEvent();
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
if (properties is AntiProjectileAbilityProperties antiProjectileProps)
{
followUser = antiProjectileProps.followUser;
}
if (photonView.IsMine && followUser)
{
StartCoroutine(FollowUser());
}
}
private IEnumerator FollowUser()
{
while (!waitingForDestroy)
{
transform.position = owner.transform.position;
yield return null;
}
}
public void SendBlockNotice()
{
if (waitingForDestroy) return;
photonView.RPC(nameof(RPC_SendBlockNotice), RpcTarget.All);
}
[PunRPC]
private void RPC_SendBlockNotice()
{
waitingForDestroy = true;
onProjectileBlocked.Invoke();
if (!photonView.IsMine)
{
visuals.SetActive(false);
return;
}
StartCoroutine(DelayedDestroy());
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5b30ab95901978444a92c50fbb1b9c7c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,90 @@
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace Template_RuntimeInstance
{
public class NetworkedAreaOfEffect : NetworkedAbilityBase
{
public float radius;
public float telegraphDelay;
[SerializeField] protected GameObject telegraph;
[SerializeField] protected GameObject effectVisual;
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
if (properties is AreaOfEffectAbilityProperties aoeProps)
{
radius = aoeProps.radius;
telegraphDelay = aoeProps.telegraphDelay;
}
if (photonView.IsMine)
{
StartCoroutine(ApplyTelegraphDelay());
}
}
protected virtual IEnumerator ApplyTelegraphDelay()
{
ShowTelegraph();
yield return new WaitForSeconds(telegraphDelay);
ApplyArea();
}
protected virtual void ApplyArea()
{
ShowEffectVisual();
CheckSurroundings();
}
protected virtual void CheckSurroundings()
{
Collider[] hits = Physics.OverlapSphere(transform.position, radius, LayerMask.GetMask("Targetable"));
targets.Clear();
foreach (Collider collider in hits)
{
Taggable target = collider.GetComponentInParent<Taggable>();
if (IsValidTarget(target))
{
targets.Add(target);
}
}
photonView.RPC(nameof(RPC_CheckSurroundings), RpcTarget.Others);
if (photonView.IsMine)
{
ApplyEffects(targets);
onHitHappened.Invoke(owner, ownerTag, targets);
}
}
[PunRPC]
protected virtual void RPC_CheckSurroundings()
{
// This method is called on other clients to sync the visual effects
ShowEffectVisual();
}
protected virtual void ShowTelegraph()
{
telegraph.SetActive(true);
effectVisual.SetActive(false);
}
protected virtual void ShowEffectVisual()
{
telegraph.SetActive(false);
effectVisual.SetActive(true);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b773c4ada4c470343a007e8dce390ce0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,73 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class NetworkedAreaOfEffectOverTime : NetworkedAreaOfEffect
{
public float duration;
public bool followUser;
public bool followTarget;
public bool damageFollowingTarget;
protected float endTime;
protected Taggable followingTargetTaggable;
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
if (properties is AreaOfEffectOverTimeAbilityProperties aoeotProps)
{
duration = aoeotProps.duration;
followUser = aoeotProps.followUser;
followTarget = aoeotProps.followTarget;
damageFollowingTarget = aoeotProps.damageFollowingTarget;
}
if (photonView.IsMine)
{
if (followUser)
StartCoroutine(FollowTransform(owner.transform));
else if (followTarget && context.TargetTag != null)
{
followingTargetTaggable = context.TargetTag;
StartCoroutine(FollowTransform(followingTargetTaggable.transform));
}
}
}
protected override void ApplyArea()
{
base.ApplyArea();
StartCoroutine(ApplyAreaOverTime());
}
protected virtual IEnumerator ApplyAreaOverTime()
{
endTime = Time.time + duration;
while (Time.time < endTime)
{
yield return new WaitForSeconds(0.5f);
CheckSurroundings();
}
}
protected virtual IEnumerator FollowTransform(Transform target)
{
while (Time.time < endTime)
{
if (transform == null || target == null) break;
transform.position = target.position;
yield return new WaitForEndOfFrame();
}
}
protected override bool IsValidTarget(Taggable target)
{
return base.IsValidTarget(target) &&
(!followTarget || damageFollowingTarget || target != followingTargetTaggable);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5bcdcd847e0509447a00245e99d943aa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,79 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class NetworkedChanneling : NetworkedAbilityBase
{
public float radius;
public bool followUser;
private Coroutine channelingCoroutine;
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
if (properties is ChanneledAbilityProperties channeledProps)
{
radius = channeledProps.radius;
followUser = channeledProps.followUser;
}
if (photonView.IsMine)
{
channelingCoroutine = StartCoroutine(ExecuteChanneling());
if (followUser)
StartCoroutine(FollowUser());
}
}
private IEnumerator ExecuteChanneling()
{
float endTime = Time.time + lifeSpan;
while (Time.time < endTime)
{
yield return new WaitForSeconds(0.5f);
CheckSurroundings();
}
}
private IEnumerator FollowUser()
{
while (channelingCoroutine != null)
{
transform.position = owner.transform.position;
yield return null;
}
}
private void CheckSurroundings()
{
Collider[] hits = Physics.OverlapSphere(transform.position, radius, LayerMask.GetMask("Targetable"));
targets.Clear();
foreach (Collider collider in hits)
{
Taggable target = collider.GetComponentInParent<Taggable>();
if (IsValidTarget(target))
{
targets.Add(target);
}
}
ApplyEffects(targets);
onHitHappened.Invoke(owner, ownerTag, targets);
}
protected override IEnumerator DelayedDestroy()
{
if (channelingCoroutine != null)
{
StopCoroutine(channelingCoroutine);
channelingCoroutine = null;
}
return base.DelayedDestroy();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 89f072756f5993f4d88a1556a93f3614
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,52 @@
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class NetworkedProjectile : NetworkedAbilityBase
{
public float speed;
public bool canPierce;
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
if (properties is ProjectileAbilityProperties projectileProps)
{
speed = projectileProps.projectileSpeed;
canPierce = projectileProps.canPierce;
}
}
private void Update()
{
if (!photonView.IsMine || waitingForDestroy) return;
transform.position += transform.forward * speed * Time.deltaTime;
}
private void OnTriggerEnter(Collider other)
{
if (waitingForDestroy) return;
Taggable target = other.GetComponentInParent<Taggable>();
if (!IsValidTarget(target)) return;
targets.Clear();
targets.Add(target);
onHitHappened.Invoke(owner, ownerTag, targets);
if (!photonView.IsMine) return;
ApplyEffects(targets);
if (!canPierce)
{
waitingForDestroy = true;
StartCoroutine(DelayedDestroy());
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6e997bda1384dc746886206fbd69e410
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,82 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class NetworkedSlash : NetworkedAbilityBase
{
public float range;
public bool regenHealthOnHit;
public bool regenManaOnHit;
public float healthOnHit;
public float manaOnHit;
[SerializeField] protected GameObject hitBox;
protected Health ownerHealth;
protected Mana ownerMana;
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
if (properties is SlashAbilityProperties slashProps)
{
range = slashProps.range;
regenHealthOnHit = slashProps.regenHealthOnHit;
regenManaOnHit = slashProps.regenManaOnHit;
healthOnHit = slashProps.healthOnHit;
manaOnHit = slashProps.manaOnHit;
}
ownerHealth = owner.GetComponent<Health>();
ownerMana = owner.GetComponent<Mana>();
if (photonView.IsMine)
{
SetupHitBox();
CheckSurroundings();
}
}
private void SetupHitBox()
{
Vector3 newScale = hitBox.transform.localScale;
newScale.z = range;
hitBox.transform.localScale = newScale;
Vector3 newPosition = hitBox.transform.localPosition;
newPosition.z = range / 2;
hitBox.transform.localPosition = newPosition;
}
protected virtual void CheckSurroundings()
{
Collider[] hits = Physics.OverlapBox(hitBox.transform.position, hitBox.transform.localScale / 2, transform.rotation, LayerMask.GetMask("Targetable"));
targets.Clear();
foreach (Collider collider in hits)
{
Taggable target = collider.GetComponentInParent<Taggable>();
if (IsValidTarget(target))
{
targets.Add(target);
}
}
ApplyEffects(targets);
ApplyRegeneration(targets.Count);
onHitHappened.Invoke(owner, ownerTag, targets);
StartCoroutine(DelayedDestroy());
}
protected virtual void ApplyRegeneration(int hitCount)
{
if (regenHealthOnHit)
ownerHealth.ChangeValue(healthOnHit * hitCount);
if (regenManaOnHit)
ownerMana.ChangeValue(manaOnHit * hitCount);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 31d18d3d362ad814eb76d79edb779a50
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,46 @@
using Kryz.CharacterStats;
using Kryz.CharacterStats.Examples;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class NetworkedSummonedMinion : NetworkedAbilityBase
{
private CharacterStats minionStats;
public override void Initialize(AbilityExecutionContext context, IAbilityProperties properties)
{
base.Initialize(context, properties);
minionStats = GetComponent<CharacterStats>();
if (minionStats != null && photonView.IsMine)
{
InitializeStatsBasedOnOwner(context.User.GetComponent<CharacterStats>());
}
}
private void InitializeStatsBasedOnOwner(CharacterStats ownerStats)
{
// Scale minion stats based on owner's stats
minionStats.Strength.AddModifier(new StatModifier(ownerStats.Strength.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.Agility.AddModifier(new StatModifier(ownerStats.Agility.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.Intelligence.AddModifier(new StatModifier(ownerStats.Intelligence.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.Spirit.AddModifier(new StatModifier(ownerStats.Spirit.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.Vitality.AddModifier(new StatModifier(ownerStats.Vitality.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.AttackDamage.AddModifier(new StatModifier(ownerStats.AttackDamage.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.SpellDamage.AddModifier(new StatModifier(ownerStats.SpellDamage.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.CritChance.AddModifier(new StatModifier(ownerStats.CritChance.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.CritDamage.AddModifier(new StatModifier(ownerStats.CritDamage.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.MaxHealth.AddModifier(new StatModifier(ownerStats.MaxHealth.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.Armor.AddModifier(new StatModifier(ownerStats.Armor.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.MagicResistance.AddModifier(new StatModifier(ownerStats.MagicResistance.Value * GameConstants.CharacterStatsBalancing.PercentageStatScaleForMinions, StatModType.Flat, ownerStats));
minionStats.onUpdateStatValues.Invoke();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b8be85325eb19ec4aae2ce7a7f0b5a41
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,62 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AbilityIndexer : MonoBehaviour
{
#region Singleton
private static AbilityIndexer _instance;
// Public reference to the singleton instance
public static AbilityIndexer Instance
{
get
{
// If the instance doesn't exist, try to find it in the scene
if (_instance == null)
{
_instance = FindObjectOfType<AbilityIndexer>();
// If it's still null, create a new GameObject and add the component
if (_instance == null)
{
GameObject singletonObject = new GameObject(typeof(AbilityIndexer).Name);
_instance = singletonObject.AddComponent<AbilityIndexer>();
}
}
return _instance;
}
}
#endregion
public List<BaseAbility> Abilities = new List<BaseAbility>();
protected void Awake()
{
// Ensure there's only one instance
if (_instance != null && _instance != this)
{
Destroy(gameObject);
return;
}
// If this is the first instance, set it as the singleton
_instance = this;
DontDestroyOnLoad(gameObject);
}
private void OnValidate()
{
if (Abilities == null) return;
foreach (BaseAbility baseAbility in Resources.FindObjectsOfTypeAll<BaseAbility>())
{
if (Abilities.Contains(baseAbility)) continue;
Abilities.Add(baseAbility);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a115334de21b946428e94622ccf94960
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,149 @@
using Kryz.CharacterStats.Examples;
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AbilityKeyBinder : MonoBehaviour
{
[Header("Listeners:")]
[SerializeField] private GameEventListener onLocalPlayerFainted;
[SerializeField] private GameEventListener onLocalPlayerPermaDeath;
[SerializeField] private GameEventListener onLocalPlayerRevived;
[Space]
[SerializeField] private BaseAbility ability;
[SerializeField] private GameKey key;
[SerializeField] private CastingStateController castingStateController;
[SerializeField] private GameEvent_AbilityKeyBinder onAbilityKeyBinderSpawned;
private PhotonView user;
private Taggable userTag;
private Mana mana;
public BaseAbility Ability => ability;
public GameKey GameKey => key;
Coroutine currentChanneling;
NetworkedChanneling networkedChanneling;
AbilityBindInstance abilityBindInstance;
AbilityCooldownTracker cooldownTracker;
bool isDead = false;
private void Awake()
{
user = GetComponentInParent<PhotonView>();
userTag = GetComponentInParent<Taggable>();
mana = GetComponentInParent<Mana>();
cooldownTracker = user.GetComponentInChildren<AbilityCooldownTracker>();
}
private void Start()
{
if (!user.IsMine)
{
enabled = false;
return;
}
onLocalPlayerFainted.Response.AddListener(() =>
{
isDead = true;
});
onLocalPlayerPermaDeath.Response.AddListener(() =>
{
isDead = true;
});
onLocalPlayerRevived.Response.AddListener(() =>
{
isDead = false;
});
onAbilityKeyBinderSpawned.Raise(this);
}
// Update is called once per frame
void Update()
{
if (isDead) return;
if (Input.GetKeyDown(key.keyCode))
{
if (abilityBindInstance != null)
abilityBindInstance.pressed.SetActive(true);
if (IsAbilityOffCooldown() && mana.EnoughMana(ability.manaCost))
{
if (ability is ChanneledAbility)
{
castingStateController.RequestAbilityChannel(ability, () =>
{
networkedChanneling = ((ChanneledAbility)ability).ExecuteChannel(user, userTag, ref currentChanneling);
if (ability.cooldown > 0)
{
cooldownTracker.StartAbilityCooldown(ability);
abilityBindInstance.StartCooldownTrackerUI();
}
});
}
else
{
castingStateController.RequestAbilityCast(ability, () =>
{
ability.Execute(user, userTag);
if (ability.cooldown > 0)
{
cooldownTracker.StartAbilityCooldown(ability);
abilityBindInstance.StartCooldownTrackerUI();
}
});
}
}
}
if (Input.GetKeyUp(key.keyCode))
{
if (abilityBindInstance != null)
abilityBindInstance.pressed.SetActive(false);
if (currentChanneling != null)
{
if (networkedChanneling != null)
{
networkedChanneling.StopCoroutine(currentChanneling);
}
else
{
StopCoroutine(currentChanneling);
}
castingStateController.ResetChannelingCast();
CastBarHandler.Instance.CancelChannelingOnButtonReleased();
}
if (networkedChanneling != null)
{
networkedChanneling.channeling = false;
networkedChanneling.DisableVisuals();
}
}
}
public void SetupAbilityBindInstance(AbilityBindInstance abilityBindInstance)
{
this.abilityBindInstance = abilityBindInstance;
mana.onResourceChanged.AddListener(OnManaChanged);
}
public void OnManaChanged(float currentMana)
{
abilityBindInstance.noMana.SetActive(!mana.EnoughMana(ability.manaCost));
}
public bool IsAbilityOffCooldown()
{
return ability.cooldown <= 0 || !cooldownTracker.OnCooldown(ability);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2a0a457ad3799e24ba58619e9cdff270
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,36 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Template_RuntimeInstance
{
public class AbilityManager : MonoBehaviour
{
private Dictionary<string, AbilityInstance> abilityInstances = new Dictionary<string, AbilityInstance>();
public AbilityInstance CreateAbilityInstance(BaseAbility abilityTemplate)
{
AbilityInstance instance = new AbilityInstance(abilityTemplate);
abilityInstances[instance.id] = instance;
return instance;
}
public AbilityInstance GetAbilityInstance(string id)
{
if (abilityInstances.TryGetValue(id, out AbilityInstance instance))
{
return instance;
}
return null;
}
public void RemoveAbilityInstance(string id)
{
if (abilityInstances.ContainsKey(id))
{
abilityInstances.Remove(id);
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bebd20e6ca211ad4da2daaa3fea134e7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long