A Massive 1.1 Update
❇️New Features❇️
⏩Preset Projectiles & Chained Methods
One of the biggest drawbacks with “All Projectiles” was that any projectile behavior could only be set when requesting its creation. Which resulted in statements like this:
With this new update, you can now directly get Projectile2Ds from your ProjectileCallers and preset its properties and behaviors for later requests.
So now we got from that match statement, to this:
You can also use this projectile_caller.get_projectile(0) method to directly set the properties of your projectiles with set_property(“name”, value). Like in this example, where I get a homing, multi-projectile “buff” after I press the “N” key:
func _process(delta: float) -> void:
super(delta)
if (Input.is_key_pressed(KEY_N)):
projectile_manager.get_projectile(selected_projectile_id).set_property("instances", 2).set_property("proj_spread", Projectile2D.ProjectileSpread.ANGULAR
).set_property("angular_spread", 90.0).set_property("seeking", true).set_property("seeking_mask", 2).set_property("angular_speed", 270.0)
projectile_manager.get_attack(selected_projectile_id).set_property("attack_charge_time", 0.016).set_property("attack_anticipate_time", 0.016
).set_property("attack_duration_time", 0.008).set_property("attack_recovery_time", 0.016)
⏩New Attack2D Class
Attack2D is a helper class made to assist you in the common task of spawning projectiles. Use it to delegate the fire rate of your weapons as well as the delay and offset of your attacks.
It works exactly as a Projectile2D, you define the properties of a new Attack2D with an AttackBlueprint2D Resource and let the AP engine do the rest.
And to manage these new Resources we have a new Node: ProjectileManager2D.
⏩New ProjectileManager2D Node
ProjectileManager2D is an extension of the ProjectileCaller2D Node, and like the latter, you can use it to request the creation of any of its projectiles.
The main difference between these two is that you can use ProjectileManager2Ds in conjunction with AttackBlueprint2Ds to convert a constant Input request into an orderly timed projectile barrage.
func _process(delta: float) -> void:
if (Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT)):
projectile_manager.request_execution(0, 0, position, get_global_mouse_position())
And like Projectile2Ds themselves, you can also modify and preset the properties and behaviors of your attacks.
See more info in the sections below.
⏩Set your own custom Projectile Classes
All projectiles its built entirely on complete customization, yet there was no built-in way to support your own full fledge Projectile2D custom classes.
That is no longer the case; now AP comes with sample templates that extend on the Attack2D and Projectile2D classes.
It also allows you to directly set any custom Attack2D or Projectile2D like this:
func _ready() -> void:
projectile_manager.set_attack(0, MyAttack.new())
projectile_manager.set_projectile(0, MyProjectile.new())
By default it sets its blueprint to the same one its method index is replacing. You can change this in the set method itself.
func _ready() -> void:
# These two statements are the same
projectile_manager.set_projectile(0, MyProjectile.new())
projectile_manager.set_projectile(0, MyProjectile.new(projectile_manager.get_projectile_blueprint(0)))
# Set it to "false" so it does not auto assing
projectile_manager.set_projectile(0, MyProjectile.new(projectile_manager.get_projectile_blueprint(1)), false)
⚠️Breaking Changes⚠️
⏩Projectiles now have Custom User Defined Properties
Previously all Projectiles2Ds had two Variant properties for arbitrary user defined data called “arg1” y “arg2”.
These properties have been removed and changed for set [StringName, Variant] Dictionaries.
Now each Projectiles2D has two dictionaries for custom properties:
- global_properties: This dictionary is shared between all projectiles created by its original blueprint. If you change its values, you will change them in all their projectiles.
- individual_properties: This dictionary is independent in all projectiles created by its original blueprint. Modifying it will only affect the individual instance.
In exchange, you can now define these properties on the ProjectileBlueprint2D Resources themselves.
In the demo examples I use these dictionaries to set the custom Trails and Blast scenes of my projectiles, as well as some other properties
I also use them to set the properties of some of my Attacks too! (mainly sound effects)
⏩Temporarily remove on_expired_projectile property from ProjectileBlueprint2D
This update introduced many behind the scene changes, mainly on the Projectile2D spawning and request system. Unfortunately, these changes caused all Projectile2Ds to lose their native ability to directly request new projectiles.
Of course this change is only temporary and will be resolved in the next update with the new Global Projectile Database system.
❇️More❇️
⏩Projectile2D Changes
Added reset() method. ## Reverts a Projectile2D to its ProjectileBlueprint2D resource property original values.
Added assign(pi: PackedInfo) method. ## Sets and starts all Projectile2D in-game components.
Added copy(base: Projectile2D, _pi: PackedInfo = null) method. ## Copies all property values from the given base parameter. If provided with a PakedInfo argument, it also calls the assign method.
Added clone(_pi: PackedInfo = null) method. ## Return a new instance of the called projectile type, with all its properties copied from the called projectile values. If provided with a PakedInfo argument, it also calls the assign method.
Added set_start_method(method: Callable) method. ## Assigns the custom_start_method parameter if the given method is valid.
Added set_move_method(method: Callable) method. ## Assigns the custom_move_method parameter if the given method is valid.
Added set_collision_method(method: Callable) method. ## Assigns both custom_area_collision_method and custom_body_collision_method parameters to the given method if it is valid.
Added set_area_collision_method(method: Callable) method. ## Assigns the custom_area_collision_method parameter if the given method is valid.
Added set_body_collision_method(method: Callable) method. ## Assigns the custom_body_collision_method parameter if the given method is valid.
Added set_expired_method(method: Callable) method. ## Assigns the custom_expired_method parameter if the given method is valid.
Added set_property(property: StringName, value: Variant) method. ## Assigns the given value to the given property if valid.
⏩ProjectileCaller2D Changes
Added get_projectile(index: int) method. ## Returns the Projectile2D at the given index in the projectiles array property if valid.
Added set_projectile(index: int, projectile: Projectile2D, auto_assign_blueprint: bool = true) method. ## Sets the value of the projectiles property element at the given index to the given projectile argument. If auto_assign_blueprint is true, the projectile_resources blueprint in the same given index will be automatically assigned to the given projectile.
Added get_projectile_blueprint(index: int) method. ## Returns the ProjectileBlueprint2D at the given index in the projectile_resources array property if valid.
⏩ProjectileBlueprint2D Changes
You can now set the area_monitoreable property on Instanced Projectiles.
You can now set collision layers and masks directly on Instanced Projectiles.
❇️Attack2D Quick use Guide❇️
⏩Let’s create an AttackBlueprint2D:
Right click on any Godot FileSystem folder ➡️ Create New ➡️ Resource.
Search for AttackBlueprint2D ➡️ Create ➡️ Name it ➡️ Save.
Assign your new AttackBlueprint2D to any ProjectileManager2D AttackResources array.
⏩AttackBlueprint2D Properties:
attack_anticipate_time: float ## Time between the attack being initiated and it having an effect (in seconds).
attack_charge_time: float ## Time it takes to even start an attack (in seconds)
attack_duration_time: float ## Time between weapon attacks (in seconds)
attack_offset: Vector2 ## Added distance to projectile position on creation
attack_recovery_time: float ## Time between the end of an attack an the start of another action (in seconds)
charge_trigger: Attack2D.WeaponChargeTrigger ## Charge completion condition
- ON_READY = Charge ends once its duration is completed.
- ON_RELEASE = Charge ends once input is released.
charge_type: Attack2D.WeaponChargeType ## Charge accumulation tracked method
- CONTINUOUS = Charge has to accumulate without pause or interruption to count.
- DISCRETE = Charge can accumulate and distribute over separate periods of time.
- MANDATORY = Once the charge starts it cannot be stopped.
global_properties: Dictionary[StringName, Variant] ## This dictionary is shared between all attacks created by this blueprint. If you change its values, you will change them in all their attacks.
individual_properties: Dictionary[StringName, Variant] ## This dictionary is independent in all attacks created by this blueprint. Modifying it will only affect the instance itself.
override_position: bool ## If true the weapon ignores the given spawn positions and uses its own ProjectileManager node global position instead.
⏩Attack Properties
accumulated_charge: float ## Collective time accumulation for discrete charged attacks
attack_anticipate_time: float ## Time between the attack being initiated and it having an effect (in seconds)
attack_charge_time: float ## Time it takes to even start an attack (in seconds)
attack_duration_time: float ## Time between weapon attacks (in seconds)
attack_offset: Vector2 ## Added distance to projectile position on creation
attack_recovery_time: float ## Time between the end of an attack an the start of another action (in seconds)
charge_trigger: Attack2D.WeaponChargeTrigger ## Charge completion condition
charge_type: Attack2D.WeaponChargeType ## Charge accumulation tracked method
current_state_lifetime: float ## Remaining time in current phase
current_state: WeaponState ## Current attack phase
- ATTACK_CHARGE = Attack start validation state.
- ATTACK_ANTICIPATE = Attack precursor state.
- ATTACK_MAIN = Projectile spawning state.
- ATTACK_RECOVERY = Attack cooldown state.
global_properties: Dictionary[StringName, Variant] ## This dictionary is shared between all attacks created by its original blueprint. If you change its values, you will change them in all their attacks.
individual_properties: Dictionary[StringName, Variant] ## This dictionary is independent in all attacks created by its original blueprint. Modifying it will only affect this instance.
is_active: bool ## Variable state for weapon update validation
is_linked: bool ## If true the attack itself is connected with the projectile processor and can request projectiles
is_under_uninterrupted_request: bool ## If true the original caller has requested new projectiles on every frame without a break
on_anticipate_enter: Callable ## Anticipation phase start callback
on_anticipate_exit: Callable ## Anticipation phase end callback
on_anticipate_update: Callable ## Anticipation phase update callback
on_charge_enter: Callable ## Charge phase start callback
on_charge_exit: Callable ## Charge phase end callback
on_charge_update: Callable ## Charge phase update callback
on_completed: Callable ## Custom attack end callback
on_main_enter: Callable ## Main attack start callback
on_main_exit: Callable ## Main attack end callback
on_main_update: Callable ## Main attack update callback
on_recovery_enter: Callable ## Recovery phase start callback
on_recovery_exit: Callable ## Recovery phase end callback
on_recovery_update: Callable ## Recovery phase update callback
on_start: Callable ## Custom attack start callback
override_position: bool ## If true the weapon ignores the given spawn positions and uses its own ProjectileManager node position instead.
pi: PackedInfo ## Projectile spawn parameters. These are its components:
- position: Vector2 ## The position from which the projectiles are being called
- direction: Vector2 ## The direction to when the projectiles are being directed
- destination: Vector2 ## The original destination the projectile was being headed
- target: Node2D ## The target to where the projectiles are being home-in
- move_method: Callable ## Custom projectile move method
- start_method: Callable ## Custom projectile start method
- collision_method: Callable ## Custom projectile collision method
- expired_method: Callable ## Custom projectile expired method
proj_caller: ProjectileManager2D ## Order requestor
projectile: Projectile2D ## Reference to projectile requested
requested_interaction: bool ## If true the original caller has requested the creation of more projectiles on this frame
resource: AttackBlueprint2D ## Fixed attack blueprint
⏩Attack Methods
func _on_anticipate_enter(method: Callable) ## Sets current_state_lifetime to attack_anticipate_time.
func _on_anticipate_exit(method: Callable) ## Changes the current_state to ATTACK_MAIN.
func _on_anticipate_update(method: Callable) ## Updates current_state_lifetime and calls _on_anticipate_exit when it runs out.
func _on_charge_enter(method: Callable) ## Sets current_state_lifetime to attack_charge_time and accounts for any accumulated_charge time.
func _on_charge_exit(method: Callable) ## Sets acummulated_charge to 0, and changes the current_state to ATTACK_ANTICIPATE.
func _on_charge_update(method: Callable) ## Validates the current charge type and triggers. It also updates current_state_lifetime and calls _on_charge_exit when it runs out.
func _on_main_enter(method: Callable) ## Sets current_state_lifetime to attack_duration_time and requests the attack projectile.
func _on_main_exit(method: Callable) ## Changes the current_state to ATTACK_RECOVERY.
func _on_main_update(method: Callable) ## Updates current_state_lifetime and calls _on_main_exit when it runs out.
func _on_recovery_enter(method: Callable) ## Sets current_state_lifetime to attack_recovery_time.
func _on_recovery_exit(method: Callable) ## Disables the attack.
func _on_recovery_update(method: Callable) ## Updates current_state_lifetime and calls _on_recovery_exit when it runs out.
func change_state(state: WeaponState) ## Returns true if successfully changed current_state to the state argument. States with no duration will be skipped.
func disable() ## Calls on_complete Callable and deactivates the attack.
func request_projectile(_projectile: Projectile2D = projectile) ## Request the creation of the given projectile with the current pi (PackedInfo) attributes.
func set_on_anticipate_enter(method: Callable) ## Assigns the on_anticipate_enter Callable to replace _on_anticipate_enter if the given method is valid.
func set_on_anticipate_exit(method: Callable) ## Assigns the on_anticipate_exit Callable to replace _on_anticipate_exit if the given method is valid.
func set_on_anticipate_update(method: Callable) ## Assigns the on_anticipate_update Callable to replace _on_anticipate_update if the given method is valid.
func set_on_charge_enter(method: Callable) ## Assigns the on_charge_enter Callable to replace _on_charge_enter if the given method is valid.
func set_on_charge_exit(method: Callable) ## Assigns the on_charge_exit Callable to replace _on_charge_exit if the given method is valid.
func set_on_charge_update(method: Callable) ## Assigns the on_charge_update Callable to replace _on_charge_update if the given method is valid.
func set_on_completed(method: Callable) ## Assigns the on_completed Callable if the given method is valid.
func set_on_main_enter(method: Callable) ## Assigns the on_main_enter Callable to replace _on_main_enter if the given method is valid.
func set_on_main_exit(method: Callable) ## Assigns the on_main_exit Callable to replace _on_main_exit if the given method is valid.
func set_on_main_update(method: Callable) ## Assigns the on_main_update Callable to replace _on_main_update if the given method is valid.
func set_on_recovery_enter(method: Callable) ## Assigns the on_recovery_enter Callable to replace _on_recovery_enter if the given method is valid.
func set_on_recovery_exit(method: Callable) ## Assigns the on_recovery_exit Callable to replace _on_recovery_exit if the given method is valid.
func set_on_recovery_update(method: Callable) ## Assigns the on_recovery_update Callable to replace _on_recovery_update if the given method is valid.
func set_on_start(method: Callable) ## Assigns the on_start Callable if the given method is valid.
func set_property(property: StringName, value: Variant) ## Assigns the given value to the given property if valid.
func start() ## Activates the attack and initializes the current_state.
Leave a comment
Log in with itch.io to leave a comment.