summaryrefslogtreecommitdiff
path: root/example/scripts
diff options
context:
space:
mode:
authorErik Schilling <ablu.erikschilling@googlemail.com>2013-05-05 10:35:36 +0200
committerErik Schilling <ablu.erikschilling@googlemail.com>2013-08-26 22:56:47 +0200
commit9314e60fc37d4940d80a4c110ead5c0b8c324947 (patch)
treed0573aacf448d6eafc95080661955c5749be6f78 /example/scripts
parentc3506577da37bb25cbb42bd534e74b05910d1580 (diff)
downloadmanaserv-9314e60fc37d4940d80a4c110ead5c0b8c324947.tar.gz
manaserv-9314e60fc37d4940d80a4c110ead5c0b8c324947.tar.bz2
manaserv-9314e60fc37d4940d80a4c110ead5c0b8c324947.tar.xz
manaserv-9314e60fc37d4940d80a4c110ead5c0b8c324947.zip
Added a first very basic monster ai version
The ai is similar to the old c++ version. Only the target searching is executed every 10 ticks only now to prevent performance issues with too many lua calls.
Diffstat (limited to 'example/scripts')
-rw-r--r--example/scripts/callbacks.lua24
-rw-r--r--example/scripts/main.lua5
-rw-r--r--example/scripts/monster/basic_ai.lua148
-rw-r--r--example/scripts/monster/settings.lua28
4 files changed, 167 insertions, 38 deletions
diff --git a/example/scripts/callbacks.lua b/example/scripts/callbacks.lua
new file mode 100644
index 00000000..af27e1a5
--- /dev/null
+++ b/example/scripts/callbacks.lua
@@ -0,0 +1,24 @@
+--[[
+
+ Allows to assign multiple functions to some callbacks
+
+--]]
+
+local monsterclass_update_old_callback = MonsterClass.on_update
+local monsterclass_update_callbacks = {}
+
+local function on_monsterclass_update(monsterclass, entity, tick)
+ for _, func in ipairs(monsterclass_update_callbacks[monsterclass]) do
+ func(entity, tick)
+ end
+end
+
+function MonsterClass:on_update(func)
+ if not monsterclass_update_callbacks[self] then
+ monsterclass_update_old_callback(self, function(entity, tick)
+ on_monsterclass_update(self, entity, tick)
+ end)
+ monsterclass_update_callbacks[self] = {}
+ end
+ table.insert(monsterclass_update_callbacks[self], func)
+end
diff --git a/example/scripts/main.lua b/example/scripts/main.lua
index 7093f112..cb657510 100644
--- a/example/scripts/main.lua
+++ b/example/scripts/main.lua
@@ -5,6 +5,9 @@
--]]
+-- Global functions:
+require "scripts/callbacks"
+
-- At the moment the event handlers are split up over the following files:
require "scripts/global_events"
require "scripts/abilities"
@@ -12,6 +15,8 @@ require "scripts/crafting"
require "scripts/attributes"
require "scripts/items/candy"
+
+require "scripts/monster/basic_ai"
require "scripts/monster/testmonster"
require "scripts/status/jump"
diff --git a/example/scripts/monster/basic_ai.lua b/example/scripts/monster/basic_ai.lua
index 9c35f42c..385099cc 100644
--- a/example/scripts/monster/basic_ai.lua
+++ b/example/scripts/monster/basic_ai.lua
@@ -7,25 +7,40 @@
local STROLL_TIMEOUT = 20
local STROLL_TIMEOUT_RANDOMNESS = 10
--- Wrapping the monster update callback in order to do the stroll ai here
-local old_on_update = MonsterClass.on_update
-local update_functions = {}
-function MonsterClass:on_update(callback)
- update_functions[self] = callback
-end
+local TARGET_SEARCH_DELAY = 10
-local stroll_timer = {}
+local mob_stati = {}
local angerlist = {}
local mob_config = require "scripts/monster/settings"
-local function find_target(mob, config)
+local function calculate_position_priority(x1, y1, x2, y2, anger, range)
+ if math.floor(x1 / TILESIZE) == math.floor(x2 / TILESIZE) and
+ math.floor(y1 / TILESIZE) == math.floor(y2 / TILESIZE)
+ then
+ -- Both on the same tile
+ return anger * range
+ end
+
+ local path_length = get_path_length(x1, y1, x2, y2, range, "w")
+ return (range - path_length) * anger
+end
+
+local function update_attack_ai(mob, tick)
+ local config = mob_config[mob:name()]
+
local target
local target_priority
local attack_x, attack_y
+ local mob_status = mob_stati[mob]
+ local timer = mob_status.update_target_timer
+ if timer and timer > tick then
+ return false
+ end
+
for _, being in ipairs(get_beings_in_circle(mob, config.trackrange)) do
- if being:type() == OBJECT_CHARACTER
+ if being:type() == TYPE_CHARACTER
and being:action() ~= ACTION_DEAD
then
local anger = angerlist[being] or 0
@@ -35,63 +50,120 @@ local function find_target(mob, config)
local possible_attack_positions = {
{
- x = being:x() - config.attack_distance or TILESIZE,
- y = being:y()
+ x = being:x() - config.attack_distance,
+ y = being:y(),
},
{
-
- x = being:x()
- y = being:y() - config.attack_distance or TILESIZE,
+ x = being:x(),
+ y = being:y() - config.attack_distance,
},
{
-
- x = being:x() + config.attack_distance or TILESIZE,
+ x = being:x() + config.attack_distance,
y = being:y(),
},
{
-
- x = being:x()
- y = being:y() + config.attack_distance or TILESIZE,
+ x = being:x(),
+ y = being:y() + config.attack_distance,
},
}
for _, point in ipairs(possible_attack_positions) do
- local priority = calculate_position_priority(mob:position(), point.x, point.y)
+ local priority = calculate_position_priority(mob:x(),
+ mob:y(),
+ point.x,
+ point.y,
+ anger,
+ config.trackrange)
+
+ if priority > 0 and (not target or priority > target_priority)
+ then
+ target = being
+ target_priority = priority
+ attack_x, attack_y = point.x, point.y
+ end
end
-
-
-
end
end
-end
-local function stroll_update(mob, tick)
- local stroll_tick = stroll_timer[mob]
- local mobconfig = mob_config[mob:name()]
+ mob_status.update_target_timer = tick + TARGET_SEARCH_DELAY
+ if not target then
+ return false
+ end
- local trackrange = mobconfig and mobconfig.trackrange or nil
+ local x, y = mob:position()
+ if x == attack_x and y == attack_y then
+ mob:use_ability(config.ability_id, target)
+ else
+ mob:walk(attack_x, attack_y)
+ end
+ return true
+end
+
+local function update_stroll_timer(mob_status, tick)
+
+ mob_status.stroll_timer = tick + STROLL_TIMEOUT
+ + math.random(STROLL_TIMEOUT_RANDOMNESS)
+end
+local function update_stroll(mob, tick)
+ local mobconfig = mob_config[mob:name()]
+ local mob_status = mob_stati[mob]
local strollrange = mobconfig and mobconfig.strollrange or nil
- if (not stroll_tick or stroll_tick <= tick) and strollrange then
+ if (not mob_status.stroll_timer or mob_status.stroll_timer <= tick) and
+ strollrange
+ then
local x, y = mob:position()
local destination_x = math.random(x - strollrange, x + strollrange)
local destination_y = math.random(y - strollrange, y + strollrange)
if is_walkable(destination_x, destination_y) then
mob:walk(destination_x, destination_y)
end
- stroll_timer[mob] = tick + STROLL_TIMEOUT
- + math.random(STROLL_TIMEOUT_RANDOMNESS)
+ update_stroll_timer(mob_status, tick)
+ end
+end
+
+local function remove_mob(mob)
+ mob_stati[mob] = nil
+end
+
+local function update(mob, tick)
+ local mob_status = mob_stati[mob]
+ if not mob_status then
+ mob_status = {}
+ mob_stati[mob] = mob_status
+ on_remove(mob, remove_mob)
+ end
+
+ local stop_stroll = update_attack_ai(mob, tick)
+ if stop_stroll then
+ update_stroll_timer(mob_status, tick)
+ else
+ update_stroll(mob, tick)
end
+end
- local monsterclass = get_monster_class(mob:monster_id())
- local update_function = update_functions[monsterclass]
- if update_function then
- return update_function(mob, tick)
+local function mob_attack(mob, target, ability_id)
+ local hp = target:base_attribute(ATTR_HP)
+ local config = mob_config[mob:name()]
+ local dealt_damage = math.min(hp, config.damage)
+ if dealt_damage > 0 then
+ local v = hp - dealt_damage
+ target:set_base_attribute(ATTR_HP, hp - dealt_damage)
+ target:add_hit_taken(dealt_damage)
end
end
--- Register all update functions for strolling
-for _, monsterclass in ipairs(get_monster_classes()) do
- old_on_update(monsterclass, stroll_update)
+local function mob_recharged(mob, ability_id)
+ mob_stati[mob].update_target_timer = 0 -- Enforce looking for new target
+end
+
+local mob_attack_ability =
+ get_ability_info("Monster attack_Basic Monster strike")
+mob_attack_ability:on_use(mob_attack)
+mob_attack_ability:on_recharged(mob_recharged)
+
+-- Register all update functions for the ai
+for _, monsterclass in pairs(get_monster_classes()) do
+ monsterclass:on_update(update)
end
diff --git a/example/scripts/monster/settings.lua b/example/scripts/monster/settings.lua
new file mode 100644
index 00000000..b095a2d7
--- /dev/null
+++ b/example/scripts/monster/settings.lua
@@ -0,0 +1,28 @@
+return {
+ ["Maggot"] = {
+ strollrange = TILESIZE,
+ aggressive = false,
+ trackrange = 5 * TILESIZE,
+ attack_distance = TILESIZE,
+ },
+ ["Scorpion"] = {
+ strollrange = 2 * TILESIZE,
+ aggressive = false,
+ trackrange = 5 * TILESIZE,
+ attack_distance = TILESIZE,
+ },
+ ["Red Scorpion"] = {
+ strollrange = TILESIZE,
+ aggressive = true,
+ trackrange = 5 * TILESIZE,
+ attack_distance = TILESIZE,
+ ability_id = 2,
+ damage = 1,
+ },
+ ["Green Slime"] = {
+ strollrange = TILESIZE,
+ aggressive = true,
+ trackrange = 5 * TILESIZE,
+ attack_distance = TILESIZE,
+ },
+}