Need help making a Redead AI that acts similar to Ocarina of time

Started by Akamatsu, September 09, 2018, 05:05:48 PM

Previous topic - Next topic
Hey Guys!,

I'm working on a new zelda game that is a prequel to majora's mask!
but I've run into some issues most of them I was able to figure out but there is one that is really annoying me currently I'm working on the stone tower area trying to finish up the story and plot in this area first I managed to make just about any enemy I wanted work but the redead!
The issue I'm having is more of a lack of experience with the engine, I suppose I'm trying to make the redeads act like they would in the game I don't want them to bite link however, I just need help making them scream and paralyze link, I have no idea how to go about this so I figured I would ask around the forums hopefully somebody can explain what I should put in the code thanks!

Hey Akamatsu. One thing that will help is putting some periods in your sentences what you ask questions, I was a bit confused trying to read that. But the take away is you're trying to recreate some of the freezing behavior of the redeads in Ocarina?

There's a couple things you'll probably need. The way I would do it requires a basic understanding of timers and some basic enemy programming.

For the freezing part specifically, I think you want the redeads to freeze link when he's close enough? You'll have to have your enemy script check the distance to the hero every several milliseconds, you can find a lot of enemy scripts that do that.

Once the player is close enough, you'll probably want to use hero:freeze() to stop the player moving. Then you'll set a timer and after  3-4 seconds, call hero:unfreeze().

If you have other questions, feel free to ask, I'm not sure if you've seen the documentation for Solarus, but look through there for timers and such.
http://www.solarus-games.org/doc/latest/lua_api_timer.html


Yeah,

sorry about the no periods I was extremely tired when I wrote this.
I basically, figured it out for the most part I was having trouble with the timer system, but I know how to make it work now.


Thanks!,

Congrats! Enemy AI can be a really fun (occasionally headache inducing) project. Have fun with your project!

Thanks dude,

I've been spending the past 5 days mostly making all the sprites and working on the first dungeon.
right now I'm working on an Iron Knuckle enemy seem to be having issues getting him to play his sleeping animation while not active.

This command doesn't seem to do anything for some reason am I doing something wrong?

sprite:set_animation("sleeping")

Thanks in advance!

I can also never get this command to work

enemy:is_pushed_back_when_hurt(false)

its supposed to make it so they can't get knocked back but it never does anything for me really annoying cause it makes my mini bosses and bosses feel weak.

It could be a few things- post your whole code and use the code=Lua tag in square brackets to format it.

A couple things that come to mind for the sleeping animation thing are that your variable "Sprite" doesn't contain the data of this enemy's sprite, or perhaps there is another function that's almost immediately changing his animation back from sleeping to walking or something.

Okay so I managed to figure it out for some reason you can't use

enemy:set_pushed_back_when_hurt(false)

it has to be

self:set_pushed_back_when_hurt(false)

there is one more issue I'm having with my mini boss I'm trying to make him spawn bats every 3 seconds but its not working mind taking a look at the code?

here is the first bit

function enemy:on_created()
  self:set_pushed_back_when_hurt(false)
  self:set_hurt_style("boss")
  sprite = enemy:create_sprite("enemies/Ghomess")
  enemy:set_life(100)
  enemy:set_damage(9)
  enemy:check_hero()

end

I used   enemy:check_hero() to make it run the next part

function enemy:check_hero()
enemy:create_enemy{
name = "BadBat",
     breed = "BadBat",
}

sol.timer.start(self, 3000, function() enemy:check_hero() end)
end

it seems to be an issue with the timer it doesn't work for some reason not sure why do you notice anything wrong?


Using the tag code = lua inside square brackets is super helpful is people are looking over your code, so you might do that next time. Have you used BBC formatting like that before? You can just copy and paste the whole enemy script so someone helping you can see how things are related.

One thing it looks like in your create-a-bat code is that enemy:create_enemy() needs x and y coordinates specified, or else you're creating it up at 0,0: the top left corner of the map. Perhaps they're being created but you can't see them up there for some reason?

Also, when are you calling your timer? You should probably call the timer in the enemy:on_restarted() event, or enemy:on_created()
It doesn't look like you're ever calling the timer?

"Using the tag code = lua inside square brackets is super helpful is people are looking over your code, so you might do that next time. Have you used BBC formatting like that before? You can just copy and paste the whole enemy script so someone helping you can see how things are related.

One thing it looks like in your create-a-bat code is that enemy:create_enemy() needs x and y coordinates specified, or else you're creating it up at 0,0: the top left corner of the map. Perhaps they're being created but you can't see them up there for some reason?

Also, when are you calling your timer? You should probably call the timer in the enemy:on_restarted() event, or enemy:on_created()
It doesn't look like you're ever calling the timer?"

Actually I have it set to create the bat's on self and sorry I had no idea you could use brackets  ??? what I was doing in my code doesn't work it seems what I tried to do was when the enemy was created make it run a check_hero command then under the function check hero make it spawn the bat and set a timer to check the hero again seems that doesn't work though.

I just tested out trying to set the timer under enemy:on_restarted() and it worked!
Thanks for the help!

Sorry, for my ignorance.

Tip: you can also quote with the quote button.

But the annoying thing is that with more than 1000 posts I'm still a Hero Member and not a Ninja Member or a Cat-lover Member.  :'(

PS: don't be sorry for your ignorance. Be proud of your knowledge, because we are all ignorant (except my cats).
"If you make people think they're thinking, they'll love you. But if you really make them think, they'll hate you."

Ignorance when you start learning is inevitable.
If you imagine I'm using [square brakets] instead of <> signs:
<Quote> quoted text goes here </quote>
<Code=Lua> your code goes here </code>
(And I'm just talking about on this website, not in your files, in case that wasn't clear).
Also giving your whole code is often helpful in case your problem isn't where you think it is, which is  more common when you're starting out.

Enemy:on_restarted is often a good place to set timers, because all timers with the context "enemy" are destroyed when the enemy restarts. So if you want a timer to restart when you restart the enemy (when it gets hit, when it is created, etc) create the timer there.

Keep in mind though, this might mean he'll create bats every time you hit him. If you don't want that, you'll want the context of the timer to be outside the enemy- set to the map for instance. I have the Solarus API open 24/7 on like two devices at least because I check it so much when I'm working, lol. Definitely reference it frequently while learning and trying new things.


I'm still wondering why enemy:set_pushed_when_hurt(false) didn't work though. Do you have your line declaring what the enemy variable refers to? Usually enemy=...(the dots mean, this instance of the code)

Yeah,

I'm not sure either I did have local enemy = ... I honestly have no idea why but when I changed it to self instead of enemy it worked I can send you the whole code if you want to take a look maybe I did something wrong?

Honestly I'm much better at making sprites then coding so far so I really need to work on that is their a way for me to get in touch with you guys like steam or discord maybe?

I don't want to bother you with to many questions but you guys seem nice and I could use your advice on how things look and act if that's fine with you of course.

Quote from: maxAlso giving your whole code is often helpful in case your problem isn't where you think it is
Quote from: maxYou can just copy and paste the whole enemy script so someone helping you can see how things are related.

I've low key been trying to say that the whole code in this case is probably more useful for people trying to help you. If you're an experienced coder and you've been testing things and you know where the issue is, maybe you don't need to send the whole thing but if you haven't coded many enemies and you're aware there's a problem somewhere, it isn't too hard for us to take a look over the whole thing.

As far as I know, there isn't a discord or anything for chatting, but I think posting your code on the forum is a pretty good way to get help fairly quickly. I check the forum at least five or six times a day unless I'm on vacation, and we're pretty nice around here. While we aren't going to code your whole game for you, if you've tried a bit yourself, most everyone is more than happy to point you in the right direction. For example, "Can someone show me how to make a custom sword that shoots lasers" might not get many replies, but being like "I tried this code to make a custom sword that shoots lasers, can someone help show me where I've gone wrong" is more likely to get assistance.

One way to get much better at coding is just to keep trying. Figure out what steps are necessary to what you're trying to do, and then think about how a computer might be able to do those steps. Keep breaking it down into more steps, keep looking over the API for methods that do what you want, use the search function there, and when you've tried a couple things and things aren't working, ask. Make sure to watch Christopho's tutorials on youtube, and look at the Solarus team's code on GitHub. If there are things there you don't understand, feel free to ask.

With all that said, I just started taking a coding course at a school in my city. In two weeks, I've learned almost as much as I could teach myself over six months trying things myself. It's worth it to buy or borrow a book about coding. Even if the language the book is about isn't Lua, many concepts will be transferable.


Here is the code.





local enemy = ...
local game = enemy:get_game()
local map = enemy:get_map()
local hero = map:get_hero()
local sprite
local movement
local sprite = enemy:create_sprite("enemies/" .. enemy:get_breed())

-- Event called when the enemy is initialized.
function enemy:on_created()
if game:get_value("Sleeping") == nil
then game:set_value("Sleeping",1)
end

  enemy:set_life(25)
  enemy:set_damage(12)
enemy:get_damage()
self:set_pushed_back_when_hurt(false)
end

function enemy:get_damage()
enemy:set_hurt_style("monster")
self:set_animation("sleeping")
end


function enemy:on_hurt()
if game:get_value("Sleeping") == 1
then game:set_value("Sleeping",2)
end
sol.audio.play_sound("IronKnuckle/Iron_KnuckleHit")
sol.audio.play_music("MiniBossTheme")
end

function enemy:on_dead()
enemy:create_enemy{
name = "UnarmoredIronKnuckle",
      breed = "IronKnuckle Early Unarmored",
}
sol.audio.play_sound("IronKnuckle/Iron_KnuckleLoseArmor")
end

function enemy:on_restarted()
if game:get_value("Sleeping") == 2
then movement = sol.movement.create("target")
end
if game:get_value("Sleeping") == 2
then movement:set_target(hero)
end
if game:get_value("Sleeping") == 2
then movement:set_speed(15)
end
if game:get_value("Sleeping") == 2
then movement:start(enemy)
end
if game:get_value("Sleeping") == 2
then sprite:set_animation("walking")
end
end