@Grimshaw Thanks! Glad to hear it.
Progress update.Okay, so arrows are not hard coded anymore!
I've added some of Lua/C++ binding functions to be able to script arrows. Here's how item system works now.
Each item has its "use" function which gets called every time player or entity uses an item. In case of bow, "use" function sets player in AttackState and sets current attack to "bow_attack".
Each attack has its enter, execute and exit functions. Enter function is called when the attack starts, execute function gets called every frame during the attack and exit function is called when the attack stops.
In case of bow_attack, its "execute" function looks like this:
execute = function(vars, owner)
if(getCurrentAnimationFrame(owner) == 1 and not vars.createdArrow) then
arrow = createEntity("arrow", getPosition(owner))
setChildEntity(owner, arrow)
setDirection(arrow, getDirection(owner))
setScriptState(arrow, "IdleState")
vars.createdArrow = true
end
end
Arrow is not created when bow animation starts. Animation has a little delay.
vars is a table which gets created when attack starts. It can be used to store variables in different parts of attack scripting code. When this function is called the first time, vars.createdArrow is nil, but when vars.createdArrow = true line is called, variable "createadArrow" is created in vars table which I can later use to not create arrows twice (player animation can be on second frame of animation for some time).
Arrow scripting code is a bit trickier. Here's how its ScriptStateMachineComponent looks:
ScriptStateMachineComponent = {
states = {
IdleState = {
enter = function(self, entity)
direction = getDirection(entity)
moveSpeedX = getMoveSpeedX(entity)
moveSpeedY = getMoveSpeedY(entity)
setAnimation(entity, "idle." .. direction)
setDamageDirection(entity, direction)
if(direction == "Up") then
setVelocity(entity, 0.0, -moveSpeedY)
setDamageRect(entity, 0.0, 0.0, 9.0, 4.0)
elseif(direction == "Down") then
setVelocity(entity, 0.0, moveSpeedY)
setDamageRect(entity, 0.0, 8.0, 9.0, 4.0)
elseif(direction == "Left") then
setVelocity(entity, -moveSpeedX, 0.0)
setDamageRect(entity, 0.0, 0.0, 4.0, 9.0)
elseif(direction == "Right") then
setVelocity(entity, moveSpeedX, 0.0)
setDamageRect(entity, 0.0, 10.0, 4.0, 9.0)
end
playSound("res/sounds/arrow_shoot.wav")
end,
execute = function(self, entity)
end,
exit = function(self, entity)
end
},
StuckState = {
enter = function(self, entity)
setAnimation(entity, "stuck." .. getDirection(entity))
startTimer(entity, "killTimer")
setVelocity(entity, 0.0, 0.0)
disableComponent(entity, "CollisionComponent")
disableComponent(entity, "DamageComponent")
end,
execute = function(self, entity)
if(timerFinished(entity, "killTimer")) then
killEntity(entity)
stopTimer(entity, "killTimer")
end
end,
exit = function(self, entity)
end
},
}
},
It's mostly self explanatory. There's some other code for arrow collision and damaging, but I won't post it as its pretty obvious.