Sweet I see what you mean I'll have to look into setting it up like you suggested so 1 entity can cover a length of corridor instead of using n tiles like I probably would have.
Many thanks for the advice.
Many thanks for the advice.
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
Show posts Menu-- Floor Spikes: damages hero by 1 but can be traversed with magic_cape or if hero is invincible
local floor_spikes = ...
local game = floor_spikes:get_game()
local map = floor_spikes:get_map()
local hero = game:get_hero()
-- setup basic values for floor_spikes
function floor_spikes:on_created()
floor_spikes:set_size(16, 16)
floor_spikes:set_origin(8, 13)
floor_spikes:set_traversable_by("hero", true)
floor_spikes:set_layer_independent_collisions(true)
if floor_spikes:get_sprite() == nil then
floor_spikes:create_sprite("entities/floor_spikes")
end
end
-- function to process results with collision test
local function spikes_collision_test(floor_spikes, entity)
local x, y = hero:get_position()
-- if not the hero ignore collision
if entity:get_type() ~= "hero" then
return false
end
if hero:is_blinking() then
return false
end
-- if magic_cape is active ignore collision
if game:get_item("magic_cape"):is_cape_active() then
return false
end
-- return the collision point to be used by the collision test
return floor_spikes:overlaps(x, y)
end
-- collision test: if triggered hurt hero by 1 and push away
floor_spikes:add_collision_test(spikes_collision_test, function(floor_spikes, entity)
--game:remove_life(1) --instakill!
hero:start_hurt(floor_spikes, 1)
end)
local direction = hero:get_direction()
function r_mag:on_movement_changed(mov_t) -- working
--local direction = hero:get_direction() --<< only works if un-commented despite the var being declared outside with the rest
sprite:set_direction(direction)
if hero_offset_pos == r_mag_pos then
state = "flanking"
else
state = "moving"
end
r_mag:attack_request()
end
-- Created by SL1200 2017
-- Ranged Combat Support Machine: aka R-Mag
-- randomly helps player by selecting either:
-- a single enemy to attack
-- or to attack all enemies
-- R-Mag will have no effect on bosses *todo*
-- poss check name of enemy to skip collecting bosses into table *todo*
--[[
-- TODO:
add target marker ? would like the maker inbetween floor and enemy
see if location updates if enemy not frozen as this will mean
the target marker can follow the enemy ? make enemy panic movement if targted
might include abillity to autoheal hero when health is very low, only if player has any of the following: fairy, red potion, blue potion
--]]
local r_mag = ...
local game = r_mag:get_game()
local map = r_mag:get_map()
local hero = game:get_hero()
local hero_x, hero_y
local offset_x
local offset_y
local hero_x_offset
local hero_y_offset
local hero_offset_pos
local r_mag_x, r_mag_y
local r_mag_pos
local mov_t = sol.movement.create("target")
local sprite
local state
local single_target_cool_down = "ready"
local full_spread_cool_down = "active"
local random_cool_down = "ready"
local entities_length = 0
local entities = {}
local enemies_to_kill
local sgl_tgt_x
local sgl_tgt_y
local start_delay
local s_attack_active
local f_attack_active
-- initialize r_mag
function r_mag:on_created()
r_mag:set_size(16, 16)
r_mag:set_origin(10, 13)
r_mag:set_traversable_by("hero", true)
r_mag:set_layer_independent_collisions()
if r_mag:get_sprite() == nil then
r_mag:create_sprite("entities/r_mag")
end
sprite = r_mag:get_sprite()
--r_mag:get_sprite():set_animation("stopped")
--full_spread_cool_down = "active"
end
-- makes sure full_spread() does not activate as soon R-MAG is activated
if start_delay == nil then
print("start_delay entered full spread on cooldown")
sol.timer.start(60200, function() full_spread_cool_down = "ready" end)
start_delay = false
end
-- movement main: r_mag moves to set positions to flank hero depending on hero direction
sol.timer.start(150, function () -- working
local game = r_mag:get_game()
local map = r_mag:get_map()
local hero = map:get_entity("hero")
local direction = hero:get_direction()
r_mag_x, r_mag_y = r_mag:get_position()
r_mag_pos = r_mag_x, r_mag_y
-- direction_up
if direction == 1 then
offset_x = 16
offset_y = 0
--print("Up")
end
-- direction_right
if direction == 0 then
offset_x = -16
offset_y = -20
--print("Right")
end
-- direction_down
if direction == 3 then
offset_x = 16
offset_y = -20
--print("Down")
end
-- direction_left
if direction == 2 then
offset_x = 16
offset_y = -20
--print("Left")
end
hero_x, hero_y = hero:get_position()
hero_x_offset = hero_x + offset_x
hero_y_offset = hero_y + offset_y
hero_offset_pos = hero_x_offset, hero_y_offset
sprite:set_direction(direction)
mov_t:set_target(hero, offset_x, offset_y)
mov_t:set_speed(100)
mov_t:set_smooth(true)
mov_t:start(r_mag)
return true
end)
-- sets bombos to use random positions
function r_mag:bombos_full_spread() -- working
local map = r_mag:get_map()
local hero = map:get_hero()
local _x, _y, layer = hero:get_position()
local x, y = map:get_camera():get_position()
local random_x = math.random(x, x + 320)
local random_y = math.random(y, y + 240)
map:create_custom_entity{
model = "bombos",
x = random_x,
y = random_y,
layer = 2,
width = 16,
height = 16,
direction = 0,
}
sol.audio.play_sound("8bit_bomb_explosion")
end
-- sets bombos to use targeted location
function r_mag:bombos_single_target() -- working
local map = r_mag:get_map()
local hero = map:get_hero()
map:create_custom_entity{
model = "bombos",
x = sgl_tgt_x,
y = sgl_tgt_y,
layer = 2,
width = 16,
height = 16,
direction = 0,
}
sol.audio.play_sound("8bit_bomb_explosion")
end
-- triggers cooldown of either attack
function r_mag:reset_cool_down() -- working
r_mag:get_sprite():set_animation("walking")
target_collected = false
if single_target_cool_down == "active" then
sol.timer.start(30000, function()
single_target_cool_down = "ready"
print("single target attack available")
end)
elseif full_spread_cool_down == "active" then
sol.timer.start(1200000, function()
full_spread_cool_down = "ready"
print("full spread attack available")
end)
else
end
end
-- collects a single enemy and location for single bombos to target
function r_mag:collect_target() -- working
-- find and place an enemey in table
local x, y = map:get_camera():get_position()
-- collect all entities on screen
for other in r_mag:get_map():get_entities_in_rectangle(x, y, 320, 240) do
-- if they are an enemy put into table entities
if other:get_type() == "enemy" then
table.insert(entities, other)
-- break kills loop so only 1 enemy is placed inside
break
end
end
-- freeze targeted enemy and grab its position
for j, enemies in ipairs(entities) do
enemies:stop_movement()
sgl_tgt_x, sgl_tgt_y = enemies:get_position()
--print(sgl_tgt_x)
--print(sgl_tgt_y)
end
-- place single bombos on targeted enemy
r_mag:bombos_single_target()
-- set delay while animation plays then kill enemy in table
sol.timer.start(200, function()
for i, enemies in ipairs(entities) do
enemies:hurt(10)
r_mag:reset_cool_down()
s_attack_active = false
print("Single target attack complete, on cooldown")
end
end)
end
-- triggers single enemy attack
function r_mag:single_target() -- working
if state == "flanking" and single_target_cool_down == "ready" then
print("choosing random enemy")
single_target_cool_down = "active"
s_attack_active = true
sol.timer.start(1000, function()
r_mag:collect_target()
end)
end
return entities
end
-- triggers all enemies on screen attack
function r_mag:full_spread() -- working
if state == "flanking" and full_spread_cool_down == "ready" then
r_mag:get_sprite():set_animation("attacking")
full_spread_cool_down = "active"
f_attack_active = true
local x, y = map:get_camera():get_position()
local bdi = 200 -- bomb delay interval
local bombos_count = 0
local entities = {}
-- collect all enemies and place reference in table
for other in r_mag:get_map():get_entities_in_rectangle(x, y, 320, 240) do
if other:get_type() == "enemy" then
table.insert(entities, other)
--print(#entities)
end
-- stop enemies in table moving
for i, enemies in ipairs(entities) do
--print("freeze loop")
enemies:stop_movement()
end
end
-- set timer for delay between bombos explosions
sol.timer.start(bdi, function()
r_mag:bombos_full_spread()
bombos_count = bombos_count + 1
return bombos_count < 15
end)
-- set timer delay for animations then kill everything in the table
sol.timer.start(bdi * 15, function()
for i, enemies in ipairs(entities) do
enemies:hurt(10)
r_mag:reset_cool_down()
f_attack_active = false
print("full spread attack complete, on cooldown")
end
end)
end
end
-- chooses which attack to use depending on cooldowns and if already attacking
function r_mag:attack_request() -- working
-- check if there are any enemies to kill on screen
local x, y = map:get_camera():get_position()
for other in r_mag:get_map():get_entities_in_rectangle(x, y, 320, 240) do
if other:get_type() == "enemy" then
enemies_to_kill = true
break
else
enemies_to_kill = false
end
end
-- !!! end script here if there are no enemies to kill !!!
if enemies_to_kill ~= true then return false end
-- if there are enemies then check we can proceed with an attack
if full_spread_cool_down == "ready" and s_attack_active ~= true then
r_mag:get_sprite():set_animation("attacking")
r_mag:full_spread()
enemies_to_kill = false
elseif single_target_cool_down == "ready" and f_attack_active ~= true then
r_mag:get_sprite():set_animation("attacking")
r_mag:single_target()
enemies_to_kill = false
else
-- R-MAG does nothing as either cooldown is active or other attack in progress
enemies_to_kill = false
end
end
-- updates if r_mag is moving or flanking hero and triggers attack request
function r_mag:on_movement_changed(mov_t) -- working
local direction = hero:get_direction()
sprite:set_direction(direction)
if hero_offset_pos == r_mag_pos then
state = "flanking"
else
state = "moving"
end
r_mag:attack_request()
end
-- constructor function
function r_mag:create_r_mag() -- n/a used to create the r_mag
local map = r_mag:get_map()
local hero = map:get_hero()
local _direction = hero:get_direction()
local _x, _y
if direction == 0 then
_x, _y = 12, -4
elseif direction == 1 then
_x, _y = 0, -18
elseif direction == 2 then
_x, _y = -14, -4
elseif direction == 3 then
_x, _y = 0, 10
end
local x, y, layer = hero:get_position()
map:create_custom_entity{
model = "r_mag",
x = x + 16,
y = x + 16,
layer = layer,
width = 16,
height = 16,
direction = _direction,
}
end
return r_mag