#Communicating changing variables to different scripts

1 messages · Page 1 of 1 (latest)

errant lynx
#

So I'm trying to make a damage system for my top down 2d game but in order for the player to take damage it's script needs to know if the enemy is attacking. I have a variable called is_attacking on the enemy script that changes to True when the enemy is attacking the player/running it's attack animation. How do I make it so my player script see when is_attacking changes to True?

manic mesa
#

Typically, you'd want the thing causing damage to be responsible for actually causing the damage.

So you might have a player function ChangeHealth(float), so that if an enemy attacked, or aprojectile hit, or a trap closed successfully, they would call player.ChangeHealth(amount) on the player (or any other target they hit)

Unless there's a reason not to do so, I'd recommend using a system like that.

#

You'd use the same technique to notify the player when a character is starting an attack on them.

errant lynx
#

How do I do this? @manic mesa

zenith shuttle
errant lynx
# zenith shuttle I'd personally have it set up to where it emits a signal that the player is conn...

I tried to do that and it's not really working as expected.(Ill provide a pastebin below) When I run the program it constantly prints enemy is attacking even with all of the filters of conditional statements I have in place.https://pastebin.com/qbCqYdnX

zenith shuttle
#

I don't think there's ever gonna be a time when looking at code on mobile doesn't suck One sec

zenith shuttle
#

So, if any of the conditions are met before attacking, you want it to stop running the function?

#

...So use return after each if/elif condition...?

manic mesa
#

@errant lynx pass in godot does nothing except prevent an error message, because gdscript doesn't use brackets to contain functions. In this case, return is the correct term to use.

You can even replace all the elif with if, because if any of the conditions returns true, the function will exit early regardless.

Other keywords you may find helpful going forward (if you haven't already encountered them) are break and continue. These are used only inside loops though.

errant lynx
#

Ok so that didn't really fix anything or make it worse. What's happening is, I'll run the program, the player will spawn in, when i move around without going into the enemy's area2d i still get the message that the enemy is attacking which probably means that the signals from the enemy script are being sent too often but I have no clue how to fix that. @zenith shuttle @manic mesa

manic mesa
#

I think you should be able to call _on_bb_enemy_attacking() directly, instead of via a signal, since you need to access the player's class anyway to subscribe that function.
That might simplify things a bit.

#

@errant lynx

junior tiger
#

btw if u wanna use signals and areas make sure the area signal checks for body

errant lynx
#

Yup thats what I have

junior tiger
#

and that it excludes itself if it is a body

errant lynx
#

Oh so the area2d thinks the enemy character2d is the player body and thats why it keeps saying attacking?

junior tiger
#

yh

#

happen to me too XD

errant lynx
#

oh shit!

#

lol thats funny

#

lemme try to fix that rq

#

would this be the right way to check if the body is the player body? func _on_detection_area_body_entered(body): # Check if the entered body is a player, initiate chase if body.name == $"../Player": player = body chasing_player = true else: return @junior tiger

junior tiger
#

dont ask me im a noob

#

XD

#

does it work?

errant lynx
#

pfft same lol

#

um....

#

no

#

it doesn't

junior tiger
#

nah was gonna tell u something wrong like u coould check for self but then u detect other enemies

errant lynx
#

ur good, i just checked if the body was equal to the player path

junior tiger
#

this wont wor later if u separate then in individual scenes btw

#

gonna need an singleton autolooader to signal each other

#

i think

errant lynx
#

well i was planning on just writing custom code for the diff enemies in other scenes

#

I got it to work for this scene which is great! Thanks guys! @manic mesa @zenith shuttle @junior tiger

junior tiger
#

✅ Godot Basics for Beginners Playlist: https://www.youtube.com/playlist?list=PL1wWXwjiybX-e07LsEPumTKYqteFkfisl
In this video we're going to learn what are Global Signals and how to use Godot's Singleton's Pattern Autoload feature.

If you have any questions post them in the comments and I'll do my best to answer them.

🎮 Add Kitchen Madness to...

▶ Play video
#

u might need this later to signal between scenes f u wanna do that

errant lynx
#

Ok thanks

manic mesa
# errant lynx would this be the right way to check if the body is the player body? ``` func _o...

Glad you got it to work. If I may, here's how I would handle this:
Make player a singleton. You don't need player themselves as an autoload, but you can have some sort of autoload to hold all your game variables.
If player itself is not already an autoload, player._ready() would then call AutoloadedVars.Player = self

When your player enters an enemies Area, it'll trigger _on_detection_area_body_entered(body)
You can check if it's valid via if body == myAutoloadedVars.Player to set chasing_player.

inside the enemy's _process() function state:

    if (self.global_position.distance_to(AutoloadedVars.player.global_position) < attackRange):
        #
        # maybe insert your position and velocity early exits here
        # also trigger attack animation here
        #
        AutoloadedVars.player.CauseDamage(damageAmount)```

all player's causeDamage() function does here, is reduce the player's health by the given amount. `damageAmount` is an exported float in the enemy script.
That way you can have the damage and attack stuff handled entirely by the enemy, and shouldn't have to worry about detection range or any of that stuff.
errant lynx
#

woah ok, that looks a little complicated for my smooth brain but tsym! I'll probably use that method for different scenes @manic mesa

junior tiger
#

u should probabbly do it everywere yh so u can jsut drop the player and the enemies in scens when u need

#

@manic mesaso u make the player a autoloader so all enemies can talk to it, do u make the enemies autoloaders too or not necessary?? i mean u probabbl need to to spawn then in or something ?

manic mesa
# errant lynx woah ok, that looks a little complicated for my smooth brain but tsym! I'll prob...

The only key differences are:

  • attack is automated and handled entirely by the enemy script: if the player is within attackRange of the enemy, it'll attack them
  • player is referenced in an autoload, so that if body == player is not dependent on names (which may change, or sometimes match each other)

@junior tiger it depends entirely on your implementation, but I see no reason to make enemies autoloaders (or store them in one). Probably better off using a resource to store spawnable enemies.

junior tiger
#

ok thx for the advice just wondering

#

still a noob

manic mesa
#

no worries. I'm far away from being an expert too.
haven't seen anybody judging anyone else on that basis here yet 🙂

#

also, most of the time, I work in c#... so there's a few additional options that I'm used to having available

junior tiger
#

i mean yh but i was helping without knowing much and i must make evident that my solution might not be very usable long run, and that u get that i dont known much at all really just working with what i found

#

cant iimagine working with c sharp

#

gonna stick to gd

#

😄

#

thx for the advice

errant lynx
#

I gotta agree with rakam tho, c# sounds rough @manic mesa

junior tiger
#

@errant lynx thanks, yh thats what u should do if u see something u think u can help with

errant lynx
#

Yup!

manic mesa
#

For example, instead of using an autoload, I'd be declaring a public static Player PlayerInstance as a singleton, within the Player class itself.
and from that point on, any script anywhere can reference the current, active player via Player.PlayerInstance, such as for conditional statements.

errant lynx
manic mesa
#

😄 yeah. I think mainly people just get intimidated by c#, but it's not such a big jump between the two. You still have full access to all the godot functionality - the only change in that regard is that you might write myNode3D.GlobalPosition instead of myNode3D.global_position and the IDE (probably Visual Studio) will complain immediately if you do anything that's technically not allowed (so you don't have to check if a node type has a certain function on it - you won't even be able to write the code to try calling that function)
GDScript is probably more accessible to new programmers, but if you've been doing stuff in python or other languages for a few years, you should pick it up fairly quickly.