diff options
author | Erik Schilling <ablu.erikschilling@googlemail.com> | 2013-05-05 10:35:36 +0200 |
---|---|---|
committer | Erik Schilling <ablu.erikschilling@googlemail.com> | 2013-05-12 09:58:12 +0200 |
commit | 323b14db576e9fec6f714f907aec07264a47d57a (patch) | |
tree | 72b9bffe52b7ae5b249bc348730fa81740bd8bc4 /example/scripts/monster/basic_ai.lua | |
parent | d64e1c6d41362c5305a1b5f06fc34d9794f82a88 (diff) | |
download | manaserv-323b14db576e9fec6f714f907aec07264a47d57a.tar.gz manaserv-323b14db576e9fec6f714f907aec07264a47d57a.tar.xz manaserv-323b14db576e9fec6f714f907aec07264a47d57a.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/monster/basic_ai.lua')
-rw-r--r-- | example/scripts/monster/basic_ai.lua | 141 |
1 files changed, 113 insertions, 28 deletions
diff --git a/example/scripts/monster/basic_ai.lua b/example/scripts/monster/basic_ai.lua index 9c35f42..40fa851 100644 --- a/example/scripts/monster/basic_ai.lua +++ b/example/scripts/monster/basic_ai.lua @@ -7,6 +7,8 @@ local STROLL_TIMEOUT = 20 local STROLL_TIMEOUT_RANDOMNESS = 10 +local TARGET_SEARCH_DELAY = 10 + -- Wrapping the monster update callback in order to do the stroll ai here local old_on_update = MonsterClass.on_update local update_functions = {} @@ -14,18 +16,38 @@ function MonsterClass:on_update(callback) update_functions[self] = callback end -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,55 +57,98 @@ 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 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 + + -- Call other update functions local monsterclass = get_monster_class(mob:monster_id()) local update_function = update_functions[monsterclass] if update_function then @@ -91,7 +156,27 @@ local function stroll_update(mob, tick) 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_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 + +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 + old_on_update(monsterclass, update) end |