After implementing this in my project my weapons now do not do damage to enemies.
The only damage I am getting/inflicting to the enemy is the base damage from the progression scriptable object.
Idk what is happening. I can pick up the weapon, open inventory and see the weapon, I can equip and un equip it in the weapon slot but when I attack the enemy or the enemy attacks me weapon damage value is not being applied. where do I look for this to work?
Thank you.
Are there any error messages in the console?
When you equip a physical weapon (like a sword, for instance) is the weapon being spawned?
Paste in your Fighter.cs script and we’ll have a look.
-No error message on console.
-yes the weapon pickup on the world is being spawned with pick up spawner, I can pick it up, in the inventory I can equip it and unequip it in the weapon slot. but when I attack the nemey or the enemy attacks me. weapon damage is not added, instead damage is only coming from the base level progression damage stat.
using UnityEngine;
using RPG.Movement;
using RPG.Core;
using GameDevTV.Saving;
using RPG.Attributes;
using RPG.Stats;
using GameDevTV.Utils;
using GameDevTV.Inventories;
namespace RPG.Combat
{
public class Fighter : MonoBehaviour, IAction, ISaveable
{
[SerializeField] private float _timeBetweenAttacks = 1f;
[SerializeField] private Transform _rightHandTransform = null;
[SerializeField] private Transform _leftHandTransform = null;
[SerializeField] private WeaponConfig _defaultWeapon = null;
private WeaponConfig _currentWeaponConfig;
private Equipment _equipment;
private Health _target;
private float _timesSincelastAttack = Mathf.Infinity;
private LazyValue<Weapon> _currentWeapon;
private void Awake()
{
_currentWeaponConfig = _defaultWeapon;
_currentWeapon = new LazyValue<Weapon>(SetUpDefaultWeapon);
_equipment = GetComponent<Equipment>();
if (_equipment)
{
_equipment.equipmentUpdated += UpdateWeapon;
}
}
private Weapon SetUpDefaultWeapon()
{
return AttachWeapon(_defaultWeapon);
}
private void Start()
{
_currentWeapon.ForceInit();
}
private void Update()
{
_timesSincelastAttack += Time.deltaTime;
if (_target == null) return;
if (_target.IsDead())
{
Cancel();
return;
}
if (!GetIsInRange(_target.transform))
{
GetComponent<Mover>().MoveTo(_target.transform.position, 1f);
}
else
{
GetComponent<Mover>().Cancel();
AttackBehaviour();
}
}
public Health GetTarget()
{
return _target;
}
public void Attack(GameObject combatTarget)
{
GetComponent<ActionScheduler>().StartAction(this);
_target = combatTarget.GetComponent<Health>();
}
public void Cancel()
{
GetComponent<Mover>().Cancel();
StopAttack();
_target = null;
}
public void EquipWeapon(WeaponConfig weapon)
{
_currentWeaponConfig = weapon;
_currentWeapon.value = AttachWeapon(weapon);
}
private void UpdateWeapon()
{
var weapon = _equipment.GetItemInSlot(EquipLocation.Weapon) as WeaponConfig;
if (weapon == null)
{
EquipWeapon(_defaultWeapon);
}
else
{
EquipWeapon(weapon);
}
}
private Weapon AttachWeapon(WeaponConfig weapon)
{
Animator animator = GetComponent<Animator>();
return weapon.Spawn(_rightHandTransform, _leftHandTransform, animator);
}
public bool CanAttack(GameObject combatTarget)
{
if (combatTarget == null) return false;
if (!GetComponent<Mover>().CanMoveTo(combatTarget.transform.position)
&& !GetIsInRange(combatTarget.transform))
{ return false; }
Health targetToTest = combatTarget.GetComponent<Health>();
return targetToTest != null && !targetToTest.IsDead();
}
private void AttackBehaviour()
{
transform.LookAt(_target.transform);
if (_timesSincelastAttack > _timeBetweenAttacks)
{
// trigger the Hit() Event
TriggerAttack();
_timesSincelastAttack = 0f;
}
}
private void Shoot()
{
Hit();
}
// Animation Event
private void Hit()
{
if (_target == null) return;
// Get the base stat damage
float damage = GetComponent<BaseStats>().GetStat(Stat.Damage);
if (_currentWeapon.value != null)
{
_currentWeapon.value.OnHit();
}
if (_currentWeaponConfig.HasProjectile())
{
_currentWeaponConfig.LaunchProjectile(_rightHandTransform, _leftHandTransform, _target, gameObject, damage);
}
else
{
_target.TakeDamage(gameObject, damage);
}
}
private void TriggerAttack()
{
GetComponent<Animator>().ResetTrigger("stopAttack");
GetComponent<Animator>().SetTrigger("attack");
}
private void StopAttack()
{
GetComponent<Animator>().ResetTrigger("attack");
GetComponent<Animator>().SetTrigger("stopAttack");
}
private bool GetIsInRange(Transform targetTransform)
{
return Vector3.Distance(transform.position, targetTransform.position) < _currentWeaponConfig.GetWeaponRange();
}
public object CaptureState()
{
return _currentWeaponConfig.name;
}
public void RestoreState(object state)
{
string weaponName = (string)state;
WeaponConfig weapon = Resources.Load<WeaponConfig>(weaponName);
EquipWeapon(weapon);
}
}
}
Actually, looking at the lecture list, you might find the answers you’re looking for in the next lecture. Have a go and let me know if that answered your question.
Hello, I checked the next lesson and it didn’t change anything for me.
since I am already using those things before I noticed that the weapon has no damage anymore.
Here are my scripts. I might have missed some things.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameDevTV.Inventories;
using RPG.Stats;
namespace RPG.Inventories
{
[CreateAssetMenu(menuName = ("RPG/Inventory/Equipable Item"))]
public class StatsEquipableItem : EquipableItem, IModifierProvider
{
[SerializeField]
Modifier[] additiveModifiers;
[SerializeField]
Modifier[] percentageModifiers;
[System.Serializable]
struct Modifier
{
public Stat stat;
public float value;
}
public IEnumerable<float> GetAdditiveModifiers(Stat stat)
{
foreach (var modifier in additiveModifiers)
{
if (modifier.stat == stat)
{
yield return modifier.value;
}
}
}
public IEnumerable<float> GetPercentageModifiers(Stat stat)
{
foreach (var modifier in percentageModifiers)
{
if (modifier.stat == stat)
{
yield return modifier.value;
}
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RPG.Stats;
using GameDevTV.Inventories;
namespace RPG.Inventories
{
public class StatsEquipment : Equipment, IModifierProvider
{
IEnumerable<float> IModifierProvider.GetAdditiveModifiers(Stat stat)
{
foreach (var slot in GetAllPopulatedSlots())
{
var item = GetItemInSlot(slot) as IModifierProvider;
if (item == null) continue;
foreach (float modifier in item.GetAdditiveModifiers(stat))
{
yield return modifier;
}
}
}
IEnumerable<float> IModifierProvider.GetPercentageModifiers(Stat stat)
{
foreach (var slot in GetAllPopulatedSlots())
{
var item = GetItemInSlot(slot) as IModifierProvider;
if (item == null) continue;
foreach (float modifier in item.GetPercentageModifiers(stat))
{
yield return modifier;
}
}
}
}
}
using GameDevTV.Inventories;
using RPG.Attributes;
using RPG.Stats;
using System.Collections.Generic;
using UnityEngine;
namespace RPG.Combat
{
[CreateAssetMenu(fileName = "Weapon", menuName = "Weapon/Create New Weapon", order = 0)]
public class WeaponConfig : EquipableItem, IModifierProvider
{
[SerializeField] private AnimatorOverrideController _animatorOverride = null;
[SerializeField] private Weapon _equippedPrefab = null;
[SerializeField] private Projectile _projectile = null;
[SerializeField] private float _weaponRange = 2f;
[SerializeField] private float _weaponDamage = 4f;
[SerializeField] private float _percentageBonus = 0f;
[SerializeField] private bool _isRightHanded = true;
const string _weaponName = "weapon";
public Weapon Spawn(Transform rightHand, Transform leftHand, Animator animator)
{
DestroyOldWeapon(rightHand, leftHand);
Weapon weapon = null;
if (_equippedPrefab != null)
{
Transform handTransform = GetTransform(rightHand, leftHand);
weapon = Instantiate(_equippedPrefab, handTransform);
weapon.gameObject.name = _weaponName;
}
if (_animatorOverride != null)
{
animator.runtimeAnimatorController = _animatorOverride;
}
else
{
var overrideController = animator.runtimeAnimatorController as AnimatorOverrideController;
if (overrideController != null)
{
animator.runtimeAnimatorController = overrideController.runtimeAnimatorController;
}
}
return weapon;
}
private void DestroyOldWeapon(Transform rightHand, Transform leftHand)
{
Transform oldWeapon = rightHand.Find(_weaponName);
if (oldWeapon == null)
{
oldWeapon = leftHand.Find(_weaponName);
}
if (oldWeapon == null) return;
oldWeapon.name = "DESTROYING";
Destroy(oldWeapon.gameObject);
}
private Transform GetTransform(Transform rightHand, Transform leftHand)
{
Transform handTransform;
if (_isRightHanded)
{
handTransform = rightHand;
}
else
{
handTransform = leftHand;
}
return handTransform;
}
public bool HasProjectile()
{
return _projectile != null;
}
public void LaunchProjectile(Transform rightHand, Transform leftHand, Health target, GameObject instigator, float calculatedDamage)
{
Projectile projectileInstance = Instantiate(_projectile, GetTransform(rightHand, leftHand).position, Quaternion.identity);
projectileInstance.SetTarget(target, instigator, calculatedDamage);
}
public float GetWeaponRange()
{
return _weaponRange;
}
public float GetPercentageBonus()
{
return _percentageBonus;
}
public float GetDamage()
{
return _weaponDamage;
}
public IEnumerable<float> GetAdditiveModifiers(Stat stat)
{
if (stat == Stat.Damage)
{
yield return _weaponDamage;
}
}
public IEnumerable<float> GetPercentageModifiers(Stat stat)
{
if (stat == Stat.Damage)
{
yield return _percentageBonus;
}
}
}
}
Does your player’s BaseStats have the ShouldUseModifiers checked?
Oh great, that’s it. It fixed my weapon. It does damage now.
I missed that process. Thank you.
how about the default unarmed weapon? seems like it is missing or not on when the game starts.
The unarmed weapon/default weapon only exists on the Fighter. You should factor your damage in the progression to account for unarmed damage.
but why is it not added to the damage like the weapon.
when I do unequip the sword it does not add unarmed damage to the progression damage. its like it is not equipped to replace the sword when I unequip.
See message above. The damage in the progression needs to account for the default weapon/unarmed.
Here’s the problem… if you push the Unarmed into the StatsEquipment, where its damage modifier can be picked up, then you would be able to unequip the Unarmed and put it in your inventory. This can get quite amusing, as it would be possible to fill your inventory with Unarmed as the system keeps creating new ones to put in the Equipment whenever you drag the existing one away.
This also means that enemy damage needs to be factored into their progressions as well.
There is an alternate scheme… which would involve removing the IModifierProvider from the WeaponConfig, and in Fighter, adding the currentWeaponConfig.GetDamage() to the retrieved state from BaseStats.
will it be better to just remove the default weapon implementation for unarmed and just stick to the progression base damage?
since unarmed is of no use at this moment if it is not being equipped as a default weapon like it is suppose to do.
maybe Ill just put a starter weapon on the player inventory to use on start.
You should have a default weapon that is loaded if there is no weapon in the Equipment. It won’t show up in equipment, but it’s still used for weapon sounds (or a physical weapon if you aren’t using Unarmed)
but this is what I am getting when equipping and unequipping, no unarmed being equipped to replace the sword. or is it normal like this?
private void UpdateWeapon()
{
var weapon = _equipment.GetItemInSlot(EquipLocation.Weapon) as WeaponConfig;
if (weapon == null)
{
EquipWeapon(_defaultWeapon);
}
else
{
EquipWeapon(weapon);
}
print("WEAPON EQUIPPED = " + weapon);
}
weapon is the local variable you just created, EquipWeapon(_defaultWeapon) won’t change this.
You should have a variable WeaponConfig currentWeapon.
, which is what EquipWeapon() should be changing… that’s the value you want to print.
I see it now, thank you very much for your support.
public void EquipWeapon(WeaponConfig weapon)
{
_currentWeaponConfig = weapon;
_currentWeapon.value = AttachWeapon(weapon);
print("WEAPON = " + weapon);
}
private void UpdateWeapon()
{
var weapon = _equipment.GetItemInSlot(EquipLocation.Weapon) as WeaponConfig;
if (weapon == null)
{
EquipWeapon(_defaultWeapon);
print("WEAPON IS NULL");
}
else
{
EquipWeapon(weapon);
}
}
Save yourself some headaches in future debugging… put the Weapon is null debug BEFORE the EquipWeapon method… in fact, I’d say:
Debug.Log($"No weapon found in Equipment. Equipping default weapon {_defaultWeapon}");
EquipWeapon(_defaultWeapon);
(This saves you a lot of headaches later if something is acting wonky and the last message on your list is Weapon is null, but you forgot the purposes of the debugs… speaking as somebody who writes a LOT of code and forgets the purposes of the debug).
Got it. Thanks.
This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.