Tracking variable changes between multiple objects

I have an small issue. I have two objects, that modify third object.
Both objects run on timers. First last for 5 seconds and second for 10 seconds.
They both affect third object at the same time.
What they do is modify third object property (they decrees it’s value).

Value is 100.

First object decrees it by 20 and second by 10.

So for 5s it should be 100 - 20 - 10 = 70.

After 5s it should 100 - 10 = 90.

and Then after 10 second it reset back to 100.

What problem I have encountered is making both objects aware of the value change. They pick the value once, and do not know if it changed, so when the first object expire the value remain at 70.

My first thought about fixing it was creating custom ticker event, so it would constantly check for value change. You might imagine it didn’t work, as it caused damage over time effect, where the value was progressively decreased with each tick.

I tried to make it in blueprint, but it’s clear to me right now that I need to create some kind of tracking mechanism or variable accessors that will check for the variable changes and will constantly pass it the the blueprint, without actually modifying original variable value.

Not asking for ready-to-go solution, but some pointing where to start about it will be appreciated!

Ok. There is another answer. I must say I just completely over-thinked the issue.

The only think that should have been done is to add at end the value I subtracted at start.

So 100 - 20 = 80.

Delay 5s

80 + 20 = 100.

And it pretty much work as expected.

Now I feel like idiot :smiley:

Can you please post your C++ or blueprint graph so we can see exactly how you are decrementing the values?

I think I understand, but seeing exactly what you’re doing would really help :slight_smile:

Rama

This Is value I try to modify:

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=CharacterAttributes)
float Health;

This is how I made my Ticker:

void URPGEffectBase::SelfRemove()
{
	ARPGCharacter* GC = Cast(AffectedTarget);
	if(GC)
	{
		UWorld* world = GetCurrentWorld(GC);
		if(world)
		{
			FTimerDynamicDelegate eventTick;
			eventTick.BindDynamic(this, &URPGEffectBase::SetEffectTick);
			world->GetTimerManager().SetTimer(eventTick, 0.9, true);
//this set timer after which object will be removed from character
			FTimerDynamicDelegate tdd;
			tdd.BindDynamic(this, &URPGEffectBase::RemoveFromArray);
			world->GetTimerManager().SetTimer(tdd, Duration, false);
		}
	}
}

void URPGEffectBase::SetEffectTick()
{
	OnEffectTick();
}

It’s probably awful but it’s doing what it is supposed to do :D.

This is the graph to object that should reduce health by 20. It’s one of few iterations.

I know I need to make some way, for both objects, to be aware of changes the other object made to variable, I just honestly have no idea where to start with it.

Health value should be persistent between objects, so if one object make change it is automatically propagated to all other objects in interest and they accordingly adjust to it.

Now objects receive Health value only on event where they are initialized and added to array, and are unware on the any changes that other object might make tot it.

I dont understand how your two tickers would NOT be dealing with the same accurate health value

You’re getting a reference to an actor, a pointer to a uobject casted to an actor with a health value,

so the health value should always be correct!

How is that you are saying the tickers are only getting the health value initially and then not getting updated?

are they storing the health value somewhere?

Rama

I think you didn’t understand what I’m trying to do. (;

If I connect my ticker to Cast node and level everything as it is, I will get damage over time effect, because it will update and modify Health on each tick.

If I disconnect Cast node from everything and plug OnEffectAppiled to Set I will get 0.

What I want to do is this: There X amount of objects. In that case Object5s, Object10s, and Target.

Object5s reduce health by 20 for 5s.

Object10s reduce health by 10 for 10s.

Target have 100 health.

Now both objects are applied on the same time to target. So initial reduction is this:

100 - 20 - 10 = 70

And It should last for 5s. After 5 seconds:

100-10 = 90

And it should last for another 5 seconds after which target health will be restored to 100.

Now I don’t know how to make both objects, aware of the health changes, without making them updating them each second.

Probably the best option would be to store updated health value somewhere in memory and and then make it push changes out to al objects, so the objects in interest wouldn’t need to check for changes. Changes would be pushed to them. Objects should just update accordingly.

IDK how to do it without affecting output of rest of the graph. Which should only set variable once, and update it only when other object modify it, not change i on it’s own, every second or so.

Well I am glad you found a solution! I must confess I really cant understand the roadblock you are hitting, because I do pretty much everything in the C++ and there, I never have to worry about keeping a character’s property updated for everyone using it, because I am always using a pointer to the character and updating its values directly.

Hopefully those who understand blueprints better can help you with what is different between what I just said about the c++ vs blueprints.

Good luck!

Rama

A Purely C++ Solution

Have you tried a purely C++ solution to this issue, at least to get a comparison on what you are experiencing?

I often gain whole new levels of insight into an issue when I approach it from a very different direction.

I’d be very curious to know of your purely-C++ results!

I might try it. but the whole point of my work right now is to abstract all the C++ stuff. I want to build base blocks in C++, so other people will be able to construct new gameplay elements just by connecting blueprint nodes. In that case new elements for abilities used by player.

My current solution is pretty bad, because the blueprint graph is complete mess (to many wires), but I’m now on good way, to refine it into something more useful :smiley:

" but I’m now on good way, to refine it into something more useful :D"

Woohoo!

Wishing you luck with this!

Yes I can appreciate wanting to make an easily extensible system, but I still think a purely c++ solution would help you understand BOTH c++ and blueprints in relation to UE4 better, so that you can use blueprints even more effectively.

I am not pretending I know the answer here, I would tell you if I did, but I bet you will figure it out if you dive deeper into the c++

The more deeply you understand the whole of the c++, the more effectively you can make easy-to-use blueprint system for others :slight_smile:

Ok. I managed to find solution with bit help of Stackoverflow :D. It’s utterly patch work, but it seems it does it’s job for now.

Here is what I have done:
URPGEffect, I added new Event:

UFUNCTION(BlueprintNativeEvent, Category=AbilityEffects)
void OnValueChanged();

Then In ARPGCharacter I added new setter:

UFUNCTION(BlueprintCallable, Category=CharacterAttributes)
void SetHealthValue(float newHealth, URPGEffectBase* effect);

void ARPGCharacter::SetHealthValue(float newHealth, URPGEffectBase* effect)
{
	Health = newHealth;
	if(effect)
	{
		bool eff = EffectManager->EffectsList.Contains(effect);
		if(eff)
		{
			effect->OnValueChanged();
		}
	}
}

Then in Blueprint I just add my new event at begining and my new Setter at end (or in any place I want value to be changed and notification send).

It seems to work, but personally I’m not happy with this solution.