Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

OscarVezz

29
Posts
4
Followers
A member registered Sep 18, 2022 · View creator page →

Creator of

Recent community posts

Hi! override_position and override_direction are Attack properties.

You can see more info in the Documentation!

Indeed, the 1.3 version is the most recent one. The “override destination” property is a small slip from the next 1.4 update.

In fact, if you have any feature suggestions feel free to tell me and they may be included in the next patch!

(3 edits)

Managing attacks is a bit complex but don’t worry, let’s break it down:

As you inferred, whenever you request an attack, the first position and destination parameters given are the ones that will be used throughout the rest of the attack.

This behavior is intentional by design so your attacks can whiff:

However you still have some quick tools to overwrite this:

When you overwrite position, you are telling the attack to ignore any given positions and to use its own physical Node position instead, and so you can dictate your final result just by modifying its position:

func _process(_delta: float) -> void:
...
	# -> Like this!
	projectile_manager.global_position = end_of_gun.global_position

	if charging and Input.is_action_pressed("mb_left"):
		projectile_manager.request_execution(0, 0, end_of_gun.global_position, get_global_mouse_position())
...

In case you need more control or you don’t want to use the overrides, you will have to modify the behavior of your attacks:

func _ready() -> void:
	# -> Here we set the methods themselves on the attack
	projectile_manager.get_attack(0).set_on_charge_exit(on_charge_exit).set_on_main_enter(on_main_enter)


func on_charge_exit(attack: Attack2D) -> void:
	# -> Here we are setting the final destination *only* when the charge is finished.
	# -> "pi" refers to *PackedInfo*, a helper class that stores all the information about how a projectile is initialized.
	attack.pi.destination = get_global_mouse_position()
	attack.charge_exit()


func on_main_enter(attack: Attack2D) -> void:
	# -> Here we are setting the projectile position, just before spawning.
	attack.pi.position = end_of_gun.global_position
	attack.main_enter()

All of this will be explained in the Documentation, again sorry it is not finished yet but I hope this clarification will help you in your project!

I’m here if you need more help. Regards.

(6 edits)

Modifying your projectiles and attacks behaviors is a bit complex but bear with me.

Let’s say I want to modify a projectile speed, right at the start of instancing it. First, I need to create a function that modifies ANY projectile:

# In this example the parameter “proj” is a representation of the Projectile to modify.
# So in order to modify its speed, I need to change the speed property of “proj”
func custom_start(proj: Projectile2D) -> void:
	proj.speed = 50

Then I would have to attach it to my desired projectile, like this:

# In this example, I’m requesting and modifying the projectile with index “0” of the “Projectile Resources” array
projectile_manager.get_projectile(0).set_on_start(custom_start)

# To be clear, you can reuse the “custom start” function to modify any other projectile, like this:
projectile_manager.get_projectile(1).set_on_start(custom_start)
projectile_manager.get_projectile(2).set_on_start(custom_start)

At the end, you should have a script similar to this:

extends Node2D

@onready var projectile_manager: ProjectileManager2D = $ProjectileManager2D


# In this example the "custom_start" function is set as the "start_method" of the projectile at index “0”.
func _ready() -> void:
	projectile_manager.get_projectile(0).set_on_start(custom_start)

			
func _process(_delta: float):
	if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
		projectile_manager.request_execution(0, 0, position, get_global_mouse_position())


# This function will change the projectile "speed" property at projectile creation.
func custom_start(proj: Projectile2D) -> void:
	proj.speed = 50

You can change all projectile behaviors in this way:

func _ready() -> void:
	projectile_manager.get_projectile(0).set_on_start(custom_start).set_on_move(custom_move).set_on_collision(custom_collision).set_on_expired(custom_expired)

The documentation is not yet up to date, but this page should give you an idea of the form and parameters needed for each behavior method.


Now, attacks work almost the same. Using your question I can modify an attack internal and external variables and methods on its recovery phase like this:

func _ready() -> void:
	projectile_manager.get_attack(0).set_on_recovery_enter(custom_recovery_enter).set_on_recovery_exit(custom_recovery_exit)


func custom_recovery_enter(attack: Attack2D) -> void:
	attack.attack_duration_time += 0.5
	attack.request_projectile()

	attack.projectile.instances += 1

	enter_executions += 1
	on_enter()


func custom_recovery_exit(attack: Attack2D) -> void:
	attack.attack_duration_time += 0.5
	attack.request_projectile()

	attack.projectile.instances += 1

	exit_executions += 1
	on_exit()

However THIS WILL NOT WORK, because unlike projectiles, assigning custom methods to your attacks will overwrite its “normal” methods.

To recover its normal functionality you will have to invoke the “normal functions” inside your custom methods, like this:

func custom_recovery_enter(attack: Attack2D) -> void:
	attack.recovery_enter()

func custom_recovery_exit(attack: Attack2D) -> void:
	attack.recovery_exit()

So you will end up with a script like this:

extends Node2D

@onready var projectile_manager: ProjectileManager2D = $ProjectileManager2D

var enter_executions: int
var exit_executions: int


func _ready() -> void:
	projectile_manager.get_attack(0).set_on_recovery_enter(custom_recovery_enter).set_on_recovery_exit(custom_recovery_exit)


func _process(_delta: float):
	if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
		projectile_manager.request_execution(0, 0, position, get_global_mouse_position())


func custom_recovery_enter(attack: Attack2D) -> void:
	attack.recovery_enter()

	attack.attack_duration_time += 0.5
	attack.request_projectile()

	attack.projectile.instances += 1

	enter_executions += 1
	on_enter()


func custom_recovery_exit(attack: Attack2D) -> void:
	attack.recovery_exit()

	attack.attack_duration_time += 0.5
	attack.request_projectile()

	attack.projectile.instances += 1

	exit_executions += 1
	on_exit()


func on_enter() -> void:
	print("Hi, there are %d enter executions" % enter_executions)


func on_exit() -> void:
	print("Goodbye, there are %d exit executions" % exit_executions)

Remember, in order to see these changes, your attack blueprint “attack recovery time” property should be greater than zero, otherwise the “recovery phase” will just be skipped.

Hope that helps!

Any other questions I am here to help!

Thank you very much for playing, all your feedback is appreciated! <3

A very cool and chill game. It really has good potential to be expanded into a full game!

You have designed a really good game for such a short time window! Just lacks some sound effects to really bring it to life!

This game has a really good potential to become a solid idle game! You really have done an amazing job!

A timeless classic que trasciende idiomas y fronteras xD

A good take on a new form of Snake! Nice work!

An absolutely fun and clean game! It's completely full of charm!

Thanks for playing! I'm glad you like it! XD 

Indeed, the movement is synchronized with the beat of the song.

An actually funny game! As previously stated, having a visual for the egg trajectory would help a lot.

The controls are a little bit weird but I love the concept, nice work!

Thank you!

Incredible potential here! I can definitely see myself playing this for hours if it were a full incremental game.

(1 edit)

Absolutely beautiful with very good feedback! I just wish there were more weapons.

I've always been a fan of incremental games, good job!

Simple and with a lot of charisma, I really liked it! But I would recommend linking the attack to the mouse. 

Thanks! You can skip the intro by pressing Enter in case you want to give it more tries.

Actually there is one! If you press Enter you can skip the intro.

Visually outstanding! Unfortunately there is no feedback on projectile collisions.

I don't know if it's intentional but I absolutely love that there can only be one bullet! It forces you to be aggressive in a game where the normal thing would be to hug a wall and stay as far away from the boss as possible.

It's unfortunate, but it seems to happen only on the first run of the game and performance improves on subsequent runs. Sadly the first impression is the most important.

You are absolutely right! the tutorial definitely needs a revamp and some more love. Thanks for the feedback <3

Jejeje muchas gracias, es cierto que me tome muchas libertades con lo de los sprites jaja.

Siendo honestos, tengo un sesgo muy fuerte en favor de juegos difíciles xD. Mirando en perspectiva, implementar un "modo práctica" sería una buena solución. 

El concepto me encanta! El game feel lo noto muy verde, pero el arte me parece brutal. 

Una pena lo del Reset, aun así me parece que han hecho un juego bastante sólido y muy, muy guapo!