Author Topic: [Solved] hero:start_attack() not working (when called from an item script)  (Read 292 times)

alexgleason

  • Jr. Member
  • **
  • Posts: 85
  • Vegan on a Desert Island
    • View Profile
    • Vegan on a Desert Island
Hi, I was hoping to create an item that triggers the hero's normal attack on_using(). It's simple:

Code: Lua
  1. local item = ...
  2. local game = item:get_game()
  3.  
  4. function item:on_created()
  5.   self:set_savegame_variable("stick")
  6.   self:set_assignable(true)
  7. end
  8.  
  9. function item:on_using()
  10.   print("beep")
  11.   game:get_hero():start_attack() -- Normal sword attack
  12. end

When I equip the item and press the button, the console outputs "beep", and then the player becomes frozen. The sword is not swung. From the console, I can unfreeze the player with: sol.main.game:get_hero():unfreeze().

Any clue why start_attack() isn't working here? I can call sol.main.game:get_hero():start_attack() from the console at any time and it works, but the same thing doesn't work inside this item script. Thanks!
« Last Edit: October 11, 2018, 10:33:46 pm by alexgleason »
RIP Aaron Swartz

Christopho

  • Administrator
  • Hero Member
  • *****
  • Posts: 1146
    • View Profile
Re: hero:start_attack() not working (when called from an item script)
« Reply #1 on: October 11, 2018, 09:04:03 pm »
I guess it is because the attack is not allowed during the item state. Try to call item:set_finished() just before hero:start_attack().

alexgleason

  • Jr. Member
  • **
  • Posts: 85
  • Vegan on a Desert Island
    • View Profile
    • Vegan on a Desert Island
Re: hero:start_attack() not working (when called from an item script)
« Reply #2 on: October 11, 2018, 10:28:11 pm »
I guess it is because the attack is not allowed during the item state. Try to call item:set_finished() just before hero:start_attack().

Ohh, that makes sense! Calling item:set_finished() lets the function continue executing, but strangely the sword is still never swung. This is my code now.

Code: Lua
  1. local item = ...
  2. local game = item:get_game()
  3.  
  4. function item:on_created()
  5.   self:set_savegame_variable("stick")
  6.   self:set_assignable(true)
  7. end
  8.  
  9. function item:on_using()
  10.   print("beep")
  11.   item:set_finished()
  12.   print("boop")
  13.   game:get_hero():start_attack()
  14.   print("blip")
  15. end

Pressing the item button does indeed print:

Code: [Select]
beep
boop
blip

But the sword still doesn't swing. The player doesn't freeze, either. Nothing happens except printing to the console. ???
RIP Aaron Swartz

alexgleason

  • Jr. Member
  • **
  • Posts: 85
  • Vegan on a Desert Island
    • View Profile
    • Vegan on a Desert Island
Re: hero:start_attack() not working (when called from an item script)
« Reply #3 on: October 11, 2018, 10:33:07 pm »
Wait, I got it! Just had to add hero:unfreeze(). This code works:

Code: Lua
  1. -- ♡ Copying is an act of love. Please copy and share.
  2.  
  3. -- Script that lets you use the sword as a normal item.
  4. -- Note that the sword button cannot be held with this method (for charging or tapping)
  5.  
  6. local item = ...
  7. local game = item:get_game()
  8.  
  9. function item:on_created()
  10.   self:set_savegame_variable("stick")
  11.   self:set_assignable(true)
  12. end
  13.  
  14. function item:on_using()
  15.   local hero = game:get_hero()
  16.   hero:unfreeze()
  17.   hero:start_attack()
  18.   item:set_finished()
  19. end

Thanks Christopho!

EDIT 1:

Note that this approach has some downsides:

1. The item button cannot be held to hold the sword for longer. You'll need to script that if you want it. I did achieve that here with a different type of item.
2. It doesn't seem you can tap the item button to swing the sword very fast. The animation must totally complete before you can press the item button again.

EDIT 2:

Using the held item command approach improves the situation:

Code: Lua
  1. -- ♡ Copying is an act of love. Please copy and share.
  2.  
  3. -- Script that lets you use the sword as a normal item.
  4. -- Note that the sword button cannot be held with this method (for charging or tapping)
  5.  
  6. local item = ...
  7. local game = item:get_game()
  8.  
  9. function item:on_created()
  10.   self:set_savegame_variable("stick")
  11.   self:set_assignable(true)
  12. end
  13.  
  14. function item:on_command_pressed(command)
  15.   local hero = game:get_hero()
  16.   hero:start_attack()
  17.   item:set_finished()
  18. end

This enables me to tap the sword button very quickly and I don't have to unfreeze the hero first. It still does not let me press and hold the sword button, which doesn't seem possible with the current API. Fortunately this is a feature I'm not using in my game and have disabled anyway.
« Last Edit: October 11, 2018, 11:05:57 pm by alexgleason »
RIP Aaron Swartz

Max

  • Full Member
  • ***
  • Posts: 174
    • View Profile
I've actually been planning on trying to figure out how to force the sword to complete its animation before the next attack, so your downside is my upside, haha. I think it can make an attack feel much weightier, and forces strategy if you lock the player into the animation.

alexgleason

  • Jr. Member
  • **
  • Posts: 85
  • Vegan on a Desert Island
    • View Profile
    • Vegan on a Desert Island
so your downside is my upside, haha.

Aaaannndd this is how a bug becomes a feature. ;D
RIP Aaron Swartz