Efficient way to create different type of NPC enemies

Hey, so basically I’m making an attacking NPC system, which contains different classes (As in weapons like swords, guns, etc…) and it is handled within a single master script. There are some similarities between them such as the movements or the states but there are also many discrepancies.

I’m trying to figure out a way to handle these differences without if statements, for example, a class will go search for weapons instead of attacking bare-handed, or that if you attack a shield enemy, you must strike it from the back.

Now you can technically make this work by using if statements

function enemyClass:moveToAtk()
   if self.Class == "class here" then
      -- do actions
      return
   end
   -- continue with the normal movement if reqs aren't met
end

I’m trying to evade this as it heavily deter readability. Furthermore, there will be different type of response each enemies will give out depending on which attack hit them, for instance, if a player throws a projectile and it hit a shield enemy, they wont get damaged, this can also be achieved by using if statements - which I’m trying to avoid.
Any help is appreciated!

Somewhat relevant.

I’ve encountered another issue regarding the NPC’s classes, for example if I am to attack a standard enemy, it hit them normally, but if I attack a shielded enemy however, it would be blocked. This i
s just a fraction of what I am trying to accomplish so wrapping it in if statements will be very messy

Basically, there are different behaviours for each NPCs when it is attacked, and I want to avoid if statements for this

Any help is appreciated