Code Attached: This is the WIP for my General ALLY Code. With some coding goals. In the search code I identify an entity by name. However... this part of the code is archaic and "for entities" loops are a lot simpler. The collision technique is with link's sword so there are some built in collision detection with enemies.
local entity = ...
--Entity todo:...
-- PUT BEHAVIOR SCRIPT INTO A SEPARATE FILE...
-- PUT INTERACTION SCRIPT INTO A SEPARATE FILE...
-- update behavior script with variables for targeting #'s (default: 100)
-- local attitude = script with variables for targeting #'s (default: 100)
-- create local strength/health function...
-- create local morale function...
-- create global speed function...
-- game:set_value("p_" .. i .. "_distance_to_hero", entity_slots[i])
--local behavior = require("entities/lib/behavior")
--local interactions = require("entities/lib/interactions")?
-- behavior variables...
local game = entity:get_game()
local map = entity:get_map()
local m = sol.movement.create("target")
local direction = entity:get_direction()
local hero = game:get_map():get_entity("hero")
local hero_x, hero_y, hero_layer = hero:get_position()
local self_x, self_y, self_layer = entity:get_position()
local target_dt = nil
local target_dth = nil
local target_h = nil
local ally_dt = nil
local ally_dth = nil
local ally_h = nil
local rock_dt = nil
local rock_dth = nil
local rock_h = nil
-- BEHAVIOR VARIABLES...
local target_dt_distance = nil
local target_h_distance = nil
local target_dth_distance = nil
local target_a_distance = nil
local ally_dt_distance = nil
local ally_h_distance = nil
local ally_dth_distance = nil
local rock_dt_distance = nil
local rock_h_distance = nil
local rock_dth_distance = nil
local rock_a_distance = nil
-- BEHAVIOR ASSIGNMENTS
-- enemy behaviour sliders
target_dt_distance = 100
target_h_distance = 100
target_dth_distance = 100
target_a_distance = 100
-- ally behaviour sliders
ally_dt_distance = 100
ally_h_distance = 100
ally_dth_distance = 100
-- Projectile behaviour sliders
rock_dt_distance = 100
rock_h_distance = 100
rock_dth_distance = 100
rock_a_distance = 100
-- more on the list to be added later...
local going_enemy = false
local properties = {}
--local shield_sprite = nil
local weapon_sprite = nil
local towards_hero = false
local away_hero = false
local attacked_hero = false
local towards_enemy = false
local near_hero = false
local weapon_attack = nil
local current_xy = {}
local xspeed = 0
local yspeed = 0
local timer, enemy_check, shoot_timer, health_timer
function entity:set_properties(prop)
properties = prop
properties.life = 10
properties.damage = 2
properties.play_hero_seen_sound = false
properties.stopped_speed = 0
properties.normal_speed = 64
properties.faster_speed = 128
properties.weapon = "knife"
-- can be knife, pistol, shotgun, grenade, ect...
properties.regen = 0
end
function entity:on_created()
-- main_sprite =
self:create_sprite("allies/a_butterfly")
self:set_size(16, 16)
self:set_origin(8, 13)
x, y, layer = hero:get_position()
self:set_position(x, y, layer)
self:get_sprite():set_animation("walking")
-- shield_sprite = self:create_sprite(properties.shield_sprite)
end
function entity:on_restarted()
--current_xy.x, current_xy.y = self:get_position()
end
--function entity:on_position_changed(x, y)
-- if weapon ~= nil then
-- local dx = x - current_xy.x
-- local dy = y - current_xy.y
-- local weapon_x, weapon_y = weapon:get_position()
-- weapon:set_position(weapon_x + dx, weapon_y + dy)
-- end
-- current_xy.x, current_xy.y = x, y
--end
-- PUT THIS BEHAVIOR SCRIPT INTO A SEPARATE FILE...
-- PUT INTERACTION SCRIPT INTO A SEPARATE FILE...
function entity:begin()
-- allies:create(game)
-- item:set_savegame_variable("e102")
timer = sol.timer.start(entity, 500, function()
-- Checks for the presence, and location of enemies and allies on the map in relationship to self, ally and hero. The first look...
-- ENEMY sight... turned into save game variables.
-- Naming System... e: enemy, p: projectile,
-- sw: switch, d: door, s: stairs, n: npc, pi: pickable, b: boss
print ("INPUT BEGIN")
print(target_dt)
print(target_dth)
print(ally_dt)
print(ally_dth)
local entity_slots = {}
for i = 1, 25 do
local hero = game:get_map():get_entity("hero")
local hero_x, hero_y, hero_layer = hero:get_position()
local self_x, self_y, self_layer = entity:get_position()
local distance_hero = math.abs((hero_x+hero_y)-(self_x+self_y))
local target = game:get_map():get_entity("e_" .. i .. "")
local ally = game:get_map():get_entity("a_" .. i .. "")
local rock = game:get_map():get_entity("p_" .. i .. "")
-- local door = game:get_map():get_entity("d_" .. i .. "")
-- local switch = game:get_map():get_entity("sw_" .. i .. "")
-- local npc = game:get_map():get_entity("n_" .. i .. "")
-- local pickable = game:get_map():get_entity("pi_" .. i .. "")
-- local stairs = game:get_map():get_entity("s_" .. i .. "")
-- local boss = game:get_map():get_entity("b_" .. i .. "")
-- local destructible = game:get_map():get_entity("de_" .. i .. "")
-- local sort_door = door:get_type()
-- local sort_switch = switch:get_type()
-- local sort_npc = npc:get_type()
-- local sort_pickable = pickable:get_type()
-- local sort_stairs = stairs:get_type()
-- local sort_destructible = destructible:get_type()
if target ~= nil then
entity_slots[i] = target
local breed = target:get_breed()
local t_x, t_y, t_layer = target:get_position()
local distance_target = math.abs((t_x+t_y)-(self_x+self_y))
local distance_to_hero = math.abs((hero_x+hero_y)-(t_x+t_y))
local distance_hero = math.abs((hero_x+hero_y)-(self_x+self_y))
if distance_target <= target_dt_distance then
target_dt = ("e_" .. i .. "")
print(target_dt)
print("enemy_detected")
elseif distance_to_hero <= target_dth_distance then
target_dth = ("e_" .. i .. "")
print(target_dth)
print("enemy_attacking_hero")
elseif distance_hero <= target_h_distance then
target_dh = ("hero")
print(target_dh)
print("enemy regrouping_with_hero")
end
-- print("B_targeting_finished...")
elseif ally ~= nil then
local sort_ally = ally:get_type()
local model = ally:get_model()
local a_x, a_y, a_layer = ally:get_position()
local distance_ally = math.abs((a_x+a_y)-(self_x+self_y))
local distance_to_hero = math.abs((hero_x+hero_y)-(a_x+a_y))
local distance_hero = math.abs((hero_x+hero_y)-(self_x+self_y))
if distance_ally <= ally_dt_distance then
ally_dt = ("a_" .. i .. "")
print(ally_dt)
-- print("B_ally_targeting_dt")
elseif distance_to_hero >= ally_dth_distance then
ally_dth = ("a_" .. i .. "")
print(ally_dth)
-- print("B_ally_targeting_dth")
elseif distance_hero <= ally_h_distance then
ally_dh = ("hero")
print(ally_dh)
print("ally regrouping_with_hero")
end
elseif rock ~= nil then
local sort_rock = rock:get_type()
local p_x, p_y, p_layer = rock:get_position()
local distance_rock = math.abs((p_x+p_y)-(self_x+self_y))
local distance_hero = math.abs((hero_x+hero_y)-(self_x+self_y))
local distance_to_hero = math.abs((hero_x+hero_y)-(p_x+p_y))
if distance_rock <= rock_dt_distance then
rock_dt = ("p_" .. i .. "")
print(rock_dt)
print("B_rock_targeting_dt")
elseif distance_to_hero >= rock_dt_distance then
rock_dth = ("p_" .. i .. "")
print(rock_dth)
print("B_rock_targeting_dth")
elseif distance_hero <= rock_h_distance then
target_dh = ("hero")
print(rock_h_distance)
print("regrouping_with_hero")
end
-- print("B_rock_targeting_finished...")
end
end
local hero = game:get_map():get_entity("hero")
local hero_x, hero_y, hero_layer = hero:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
local distance_hero = math.abs((hero_x+hero_y)-(npc_x+npc_y))
local m = sol.movement.create("target")
local direction = entity:get_direction()
local health = properties.life
if map:has_entities("e_") then
if target_dt ~= nil and target_dth == nil and distance_hero < 200 then
local target_in_range = game:get_map():get_entity(target_dt)
if target_in_range ~= nil then
local tir_x, tir_y, tir_layer = target_in_range:get_position()
print("go_enemy")
entity:go_enemy()
end
elseif target_dt ~= nil and target_dth ~= nil and distance_hero < 200 then
local target_d_to_hero = game:get_map():get_entity(target_dth)
if target_d_to_hero ~= nil then
local tdth_x, tdth_y, tdth_layer = target_d_to_hero:get_position()
print("defend_hero")
entity:defend_hero()
end
elseif target_dt ~= nil and target_dth ~= nil and distance_hero > 100 then
print("group_hero")
entity:go_hero()
elseif map:has_entities("a_") and ally_dt ~= nil and ally_dt ~= "a_1" then
local ally_in_range = game:get_map():get_entity(ally_dt)
if ally_in_range ~= nil then
local air_x, air_y, air_layer = ally_in_range:get_position()
print("go_ally")
entity:go_ally()
end
elseif ally_dt ~= nil and ally_dth ~= nil then
local ally_in_range = game:get_map():get_entity(ally_dt)
if ally_in_range ~= nil then
local air_x, air_y, air_layer = ally_in_range:get_position()
print("go_ally")
entity:go_ally()
end
elseif ally_dth ~= nil and target_dth == nil or ally_dth ~= nil and target_dt == nil then
local ally_d_to_hero = game:get_map():get_entity(ally_dth)
if ally_d_to_hero ~= nil then
local adth_x, adth_y, adth_layer = ally_d_to_hero:get_position()
print("go_hero")
entity:go_hero()
end
elseif rock_dt ~= nil then
local rock_in_range = game:get_map():get_entity(rock_dt)
if rock_in_range ~= nil then
local rir_x, rir_y, rir_layer = rock_in_range:get_position()
print("go_dodge")
entity:dodge()
end
elseif rock_dth ~= nil and target_dth ~= nil then
local rock_d_to_hero = game:get_map():get_entity(rock_dth)
if rock_d_to_hero ~= nil then
local rdth_x, rdth_y, rdth_layer = rock_d_to_hero:get_position()
print("go_block")
entity:block()
end
else
print("else__go_hero")
entity:go_hero()
end
else
print("NO ENEMIES...else__go_hero")
entity:go_ally()
print ("sort_ally")
print (sort_ally)
end
return true
end)
end
function entity:go_hero()
print("following hero...")
local hero_x, hero_y, hero_layer = hero:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
local distance_hero = math.abs((hero_x+hero_y)-(npc_x+npc_y))
if distance_hero > 64 then
m:set_ignore_obstacles(false)
m:set_target(hero_x, hero_y, hero_layer)
m:set_speed(64)
m:start(entity)
entity:get_sprite():set_animation("walking")
else
m:set_ignore_obstacles(false)
m:set_target(hero_x, hero_y, hero_layer)
m:set_speed(0)
m:start(entity)
entity:get_sprite():set_animation("stopped")
end
going_enemy = false
away_hero = false
towards_hero = true
near_hero = false
end
function entity:defend_hero()
if target_dth ~= nil then
local target_in_range = game:get_map():get_entity(target_dth)
local tir_x, tir_y, tir_layer = target_in_range:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
local distance_enemy = math.abs((tir_x+tir_y)-(npc_x+npc_y))
if distance_enemy > 24 then
--FUNCTION: GO_ENEMY
m:set_ignore_obstacles(false)
m:set_target(tir_x, tir_y, tir_layer)
m:set_speed(128)
m:start(entity)
entity:get_sprite():set_animation("walking")
going_enemy = true
away_hero = false
towards_hero = false
near_hero = false
print("Going enemy")
else
--FUNCTION: ATTACK
weapon_attack = map:create_custom_entity{
name = "w_knife",
x = npc_x,
y = npc_y,
layer = npc_layer,
direction = direction,
sprite = "allies/w_knife",
}
self.created = true
weapon_attack:set_position(npc_x, npc_y, npc_layer)
print("attacking enemy")
-- FUNCTION: WEAPON_POWER
weapon_attack:add_collision_test("sprite", function(weapon_attack, other)
if other:get_type() == "enemy" then
other:hurt(8)
weapon_attack:remove()
else
weapon_attack:remove()
end
end)
print("sword swing...")
--FUNCTION: STOPPED
m:set_ignore_obstacles(false)
m:set_target(tir_x, tir_y)
m:set_speed(0)
m:start(entity)
entity:get_sprite():set_animation("stopped")
going_enemy = false
away_hero = false
towards_hero = false
near_enemy = true
end
end
end
function entity:go_enemy()
if target_dt ~= nil and target_dth == nil then
local target_in_range = game:get_map():get_entity(target_dt)
local tir_x, tir_y, tir_layer = target_in_range:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
local distance_enemy = math.abs((tir_x+tir_y)-(npc_x+npc_y))
if distance_enemy > 24 then
--FUNCTION: GO_ENEMY
m:set_ignore_obstacles(false)
m:set_target(tir_x, tir_y, tir_layer)
m:set_speed(128)
m:start(entity)
entity:get_sprite():set_animation("walking")
going_enemy = true
away_hero = false
towards_hero = false
near_hero = false
print("Going enemy")
else
--FUNCTION: ATTACK
weapon_attack = map:create_custom_entity{
name = "w_knife",
x = npc_x,
y = npc_y,
layer = npc_layer,
direction = direction,
sprite = "allies/w_knife",
}
self.created = true
weapon_attack:set_position(npc_x, npc_y, npc_layer)
print("attacking enemy")
-- FUNCTION: WEAPON_POWER
weapon_attack:add_collision_test("sprite", function(weapon_attack, other)
if other:get_type() == "enemy" then
other:hurt(8)
weapon_attack:remove()
else
weapon_attack:remove()
end
end)
print("sword swing...")
--FUNCTION: STOPPED
m:set_ignore_obstacles(false)
m:set_target(tir_x, tir_y)
m:set_speed(0)
m:start(entity)
entity:get_sprite():set_animation("stopped")
going_enemy = false
away_hero = false
towards_hero = false
near_enemy = true
end
end
end
function entity:go_ally()
-- Buggy code... I have to differentiate between the allies... by identifying this ally. by getting their hud slot... it is much easier.
-- local air_x, air_y, air_layer = ally_dt:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
-- local distance_ally = math.abs((air_x+air_y)-(npc_x+npc_y))
-- if map:get_entities_count("a_") > 1 then
-- m:set_ignore_obstacles(false)
-- m:set_target(air_x + 32, air_y + 32, air_layer)
-- m:set_speed(64)
-- m:start(entity)
-- entity:get_sprite():set_animation("walking")
-- going_enemy = false
-- going_ally = true
-- away_hero = false
-- towards_hero = true
-- near_hero = false
-- elseif map:get_entities_count("a_") < 2 then
entity:go_hero()
end
function entity:block()
local rir_x, rir_y, rir_layer = rock_dt:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
local distance_enemy = math.abs((rir_x+rir_y)-(npc_x+npc_y))
m:set_ignore_obstacles(false)
m:set_target(rir_x, rir_y, rir_layer)
m:set_speed(128)
m:start(entity)
entity:get_sprite():set_animation("walking")
going_enemy = false
going_ally = true
away_hero = false
towards_hero = true
near_hero = false
end
function entity:dodge()
local rdth_x, rdth_y, rdth_layer = rock_dth:get_position()
local npc_x, npc_y, npc_layer = entity:get_position()
local distance_enemy = math.abs((rdth_x+rdth_y)-(npc_x+npc_y))
m:set_ignore_obstacles(false)
m:set_target(rdth_x + 128, rdth_y + 128, rdth_layer)
m:set_speed(128)
m:start(entity)
entity:get_sprite():set_animation("walking")
going_enemy = false
going_ally = true
away_hero = false
towards_hero = true
near_hero = false
end
function entity:hurt()
end
function entity:health()
end
function entity:on_created()
self:set_drawn_in_y_order(true)
self:set_can_traverse("hero", false)
self:set_traversable_by("hero", true)
entity:begin()
end
-- Behavior function ends.
-- PUT INTERACTION SCRIPT INTO A SEPARATE FILE...
end
function entity:on_movement_changed(movement)
local direction = movement:get_direction4()
entity:get_sprite():set_direction(direction)
end
The other part is in the game_manager.lua insert in the
function game:on_map_changed(map)
if game:get_value("a1010") and game:get_value("a1011")
then
ally2 = map:create_custom_entity{
name = "a_2",
x = x,
y = x,
layer = layer,
direction = direction,
sprite = "allies/a_pi",
model = "ally_pi"
}
self.created = true
ally2:set_position(x, y, layer)
local ally2 = true
local allynumber = 2
end
Crude but it is a WIP.
Good luck.
PG