AI can 'die' now; blackboard work
This commit is contained in:
@@ -29,7 +29,7 @@ const guard_distance = 2.0
|
||||
const engage_distance = 10.0
|
||||
const flee_distance = 5.0
|
||||
|
||||
var blackboard = {
|
||||
var init_blackboard = {
|
||||
"stamina": 100.0,
|
||||
"health": 100.0,
|
||||
"melee_weapon_equipped": false,
|
||||
@@ -62,7 +62,7 @@ func combat_event(ev, data):
|
||||
var dst = where.distance_squared_to(curpos)
|
||||
if dst < guard_distance * guard_distance:
|
||||
if who == player:
|
||||
blackboard.guard = true
|
||||
blackboard_set("guard", true)
|
||||
"damage":
|
||||
var who = data[0]
|
||||
var weapon = data[1]
|
||||
@@ -72,13 +72,15 @@ func combat_event(ev, data):
|
||||
var dst = where.distance_squared_to(curpos)
|
||||
if dst < attack_distance * attack_distance:
|
||||
if who == player:
|
||||
blackboard.melee_damage = true
|
||||
blackboard_set("melee_damage", true)
|
||||
|
||||
var initialized = false
|
||||
func init():
|
||||
func init(tick):
|
||||
assert(!initialized)
|
||||
name = "bandit_ai"
|
||||
root = get_character()
|
||||
for e in init_blackboard.keys():
|
||||
blackboard_set(e, init_blackboard[e])
|
||||
assert(root.has_meta("skeleton"))
|
||||
rnd = RandomNumberGenerator.new()
|
||||
rnd.randomize()
|
||||
@@ -377,6 +379,39 @@ class rest extends base_bhv:
|
||||
assert(root)
|
||||
active = false
|
||||
finished = false
|
||||
class unconcious extends base_bhv:
|
||||
var root
|
||||
var anim1
|
||||
var anim2
|
||||
var state = 0
|
||||
func start(root: Node, anim1: String, anim2: String):
|
||||
self.root = root
|
||||
self.anim1 = anim1
|
||||
self.anim2 = anim2
|
||||
active = true
|
||||
state = 0
|
||||
|
||||
func run(delta: float, bb: Dictionary):
|
||||
assert(active)
|
||||
assert(root)
|
||||
assert(anim1)
|
||||
assert(anim2)
|
||||
match state:
|
||||
0:
|
||||
characters.animation_node_travel(root, anim1)
|
||||
state = 1
|
||||
# if finished:
|
||||
# return
|
||||
# if bb.stamina < 100.0:
|
||||
# print("rest: stamina: ", bb.stamina)
|
||||
# bb.stamina += 15500.0 * delta
|
||||
# else:
|
||||
# finished = true
|
||||
func stop():
|
||||
assert(active)
|
||||
assert(root)
|
||||
active = false
|
||||
finished = false
|
||||
|
||||
#var walk_to: walkto
|
||||
#var flee_to: walkto
|
||||
@@ -392,76 +427,78 @@ var conf_behaviors: = {
|
||||
"melee_attack": attack,
|
||||
"guard": guard,
|
||||
"rest": rest,
|
||||
"get_melee_damage": get_damage
|
||||
"get_melee_damage": get_damage,
|
||||
"unconcious": unconcious
|
||||
}
|
||||
|
||||
var pdst = INF
|
||||
static func calc_utility(utility: String, bb: Dictionary):
|
||||
func calc_utility(utility: String):
|
||||
match utility:
|
||||
"take_melee_weapon":
|
||||
if bb.health <= 0.0:
|
||||
if blackboard_get("health") <= 0.0:
|
||||
return 0.0
|
||||
if bb.melee_weapon_equipped:
|
||||
if blackboard_get("melee_weapon_equipped"):
|
||||
return 0.0
|
||||
else:
|
||||
if bb.enemy_distance < engage_distance * engage_distance:
|
||||
if blackboard_get("enemy_distance") < engage_distance * engage_distance:
|
||||
return 110.0
|
||||
"approach":
|
||||
if bb.health <= 0.0:
|
||||
if blackboard_get("health") <= 0.0:
|
||||
return 0.0
|
||||
if bb.enemy_distance < 1.6 * 1.6:
|
||||
if blackboard_get("enemy_distance") < 1.6 * 1.6:
|
||||
return 0.0
|
||||
if bb.stamina > 50.0 && bb.enemy_distance < engage_distance * engage_distance:
|
||||
return 10.0 + (bb.enemy_distance - 10.0) / 6.0
|
||||
if blackboard_get("stamina") > 50.0 && blackboard_get("enemy_distance") < engage_distance * engage_distance:
|
||||
return 10.0 + (blackboard_get("enemy_distance") - 10.0) / 6.0
|
||||
"melee_attack":
|
||||
if bb.health <= 0.0:
|
||||
if blackboard_get("health") <= 0.0:
|
||||
return 0.0
|
||||
if bb.melee_weapon_equipped:
|
||||
if bb.attack_cooldown <= 0.0:
|
||||
if blackboard_get("melee_weapon_equipped"):
|
||||
if blackboard_get("attack_cooldown") <= 0.0:
|
||||
var d = attack_distance * attack_distance
|
||||
if bb.stamina > 20.0 && bb.enemy_distance <= d:
|
||||
if blackboard_get("stamina") > 20.0 && blackboard_get("enemy_distance") <= d:
|
||||
return 50.0
|
||||
"flee":
|
||||
if bb.health <= 0.0:
|
||||
if blackboard_get("health") <= 0.0:
|
||||
return 0.0
|
||||
if bb.flee_cooldown > 0.0:
|
||||
if blackboard_get("flee_cooldown") > 0.0:
|
||||
return 0.0
|
||||
if bb.stamina <= 50.0 && bb.stamina > 10.0 && bb.enemy_distance < flee_distance * flee_distance:
|
||||
return 100.0 + clamp((100.0 - bb.stamina), 0, 90.0) * 2.0
|
||||
if bb.stamina <= 10.0 && bb.enemy_distance <= flee_distance * flee_distance * 0.5:
|
||||
if blackboard_get("stamina") <= 50.0 && blackboard_get("stamina") > 10.0 && blackboard_get("enemy_distance") < flee_distance * flee_distance:
|
||||
return 100.0 + clamp((100.0 - blackboard_get("stamina")), 0, 90.0) * 2.0
|
||||
if blackboard_get("stamina") <= 10.0 && blackboard_get("enemy_distance") <= flee_distance * flee_distance * 0.5:
|
||||
return 250.0
|
||||
if bb.stamina <= 50.0 && bb.enemy_distance < engage_distance * engage_distance:
|
||||
if bb.randf < 0.3:
|
||||
if blackboard_get("stamina") <= 50.0 && blackboard_get("enemy_distance") < engage_distance * engage_distance:
|
||||
if blackboard_get("randf") < 0.3:
|
||||
return 100.0
|
||||
if bb.enemy_distance < 1.4 * 1.4:
|
||||
if blackboard_get("enemy_distance") < 1.4 * 1.4:
|
||||
return 150.0
|
||||
if bb.health < 50 && bb.health > 15:
|
||||
if blackboard_get("health") < 50 && blackboard_get("health") > 15:
|
||||
return 160
|
||||
"guard":
|
||||
if bb.health <= 0.0:
|
||||
if blackboard_get("health") <= 0.0:
|
||||
return 0.0
|
||||
if bb.guard_cooldown > 0.0:
|
||||
if blackboard_get("guard_cooldown") > 0.0:
|
||||
return 0.0
|
||||
elif bb.guard:
|
||||
bb.guard = false
|
||||
elif blackboard_get("guard"):
|
||||
blackboard_set("guard", false)
|
||||
return 300.0
|
||||
# elif bb.enemy_distance < guard_distance * guard_distance * 0.3 && bb.stamina > 10.0:
|
||||
# elif blackboard_get("enemy_distance") < guard_distance * guard_distance * 0.3 && blackboard_get("stamina") > 10.0:
|
||||
# return 80
|
||||
# elif bb.enemy_distance < attack_distance * attack_distance * 0.3:
|
||||
# elif blackboard_get("enemy_distance") < attack_distance * attack_distance * 0.3:
|
||||
# return 10.0
|
||||
"rest":
|
||||
if bb.stamina >= 100.0:
|
||||
return 0.0
|
||||
if bb.stamina <= 10.0 && bb.enemy_distance >= flee_distance * flee_distance:
|
||||
return 100.0 + bb.enemy_distance / 10.0
|
||||
if bb.health < 10:
|
||||
"unconcious":
|
||||
if blackboard_get("health") < 10:
|
||||
return 2000
|
||||
"get_melee_damage":
|
||||
if bb.health <= 0.0:
|
||||
"rest":
|
||||
if blackboard_get("stamina") >= 100.0:
|
||||
return 0.0
|
||||
if bb.melee_damage:
|
||||
bb.melee_damage = false
|
||||
print("DAMAGE2 ", bb.health)
|
||||
if blackboard_get("stamina") <= 10.0 && blackboard_get("enemy_distance") >= flee_distance * flee_distance:
|
||||
return 100.0 + blackboard_get("enemy_distance") / 10.0
|
||||
"get_melee_damage":
|
||||
if blackboard_get("health") <= 0.0:
|
||||
return 0.0
|
||||
if blackboard_get("melee_damage"):
|
||||
blackboard_set("melee_damage", false)
|
||||
print("DAMAGE2 ", blackboard_get("health"))
|
||||
return 1000
|
||||
_:
|
||||
assert(false)
|
||||
@@ -473,7 +510,7 @@ func select_behavior():
|
||||
best_behavior = "rest"
|
||||
best_utility = 0.0
|
||||
for e in conf_behaviors.keys():
|
||||
var utility = calc_utility(e, blackboard)
|
||||
var utility = calc_utility(e)
|
||||
if e == last_behavior:
|
||||
utility *= 2.0
|
||||
if best_utility < utility:
|
||||
@@ -486,7 +523,7 @@ var last_bhv
|
||||
var last_running = []
|
||||
var current_running = []
|
||||
var run_behaviors = {}
|
||||
func update_physics(delta):
|
||||
func update_physics(tick, delta):
|
||||
assert(initialized)
|
||||
assert(root)
|
||||
var cam = root.get_viewport().get_camera()
|
||||
@@ -498,10 +535,10 @@ func update_physics(delta):
|
||||
var o = root.global_transform.origin
|
||||
var p = cam.get_meta("player").global_transform
|
||||
pdst = o.distance_squared_to(p.origin)
|
||||
blackboard.enemy_distance = pdst
|
||||
blackboard.randf = rnd.randf()
|
||||
blackboard.enemy_pos = p.origin
|
||||
blackboard.space = space
|
||||
blackboard_set("enemy_distance", pdst)
|
||||
blackboard_set("randf", rnd.randf())
|
||||
blackboard_set("enemy_pos", p.origin)
|
||||
blackboard_set("space", space)
|
||||
# var adest = o + (p.origin - o).normalized() * min(2.0, sqrt(pdst))
|
||||
var adest = p.origin
|
||||
var away = (o - p.origin).normalized()
|
||||
@@ -511,7 +548,7 @@ func update_physics(delta):
|
||||
var enemy_dir: Vector3 = Transform(p.basis, Vector3()).xform(Vector3(0, 0, -1))
|
||||
var root_dir: Vector3 = Transform(root.global_transform.basis, Vector3()).xform(Vector3(0, 0, -1))
|
||||
var dot = root_dir.dot(enemy_dir)
|
||||
blackboard.dot = dot
|
||||
blackboard_set("dot", dot)
|
||||
|
||||
var prev_state = state
|
||||
match state:
|
||||
@@ -544,6 +581,8 @@ func update_physics(delta):
|
||||
run_behaviors[bhv].start(root, "guard-melee1", "guard-front-melee1")
|
||||
"get_melee_damage":
|
||||
run_behaviors[bhv].start(root, "guard-melee1", "guard-front-melee1", 10.0)
|
||||
"unconcious":
|
||||
run_behaviors[bhv].start(root, "fall-front", "fall-back")
|
||||
_:
|
||||
assert(false)
|
||||
# print("adding behavior: ", bhv)
|
||||
@@ -552,10 +591,10 @@ func update_physics(delta):
|
||||
if !e in last_running:
|
||||
if !e.active:
|
||||
e.activate()
|
||||
e.run(delta, blackboard)
|
||||
e.run(delta, blackboard_get_dict())
|
||||
#FIXME: mess :(
|
||||
if e == run_behaviors["flee"]:
|
||||
blackboard.flee_cooldown = 2.0 + rnd.randf() * 3.0
|
||||
blackboard_set("flee_cooldown", 2.0 + rnd.randf() * 3.0)
|
||||
if e.finished && e.active:
|
||||
# print("in current run but finished")
|
||||
e.stop()
|
||||
@@ -570,18 +609,18 @@ func update_physics(delta):
|
||||
state = 3
|
||||
3:
|
||||
state = 0
|
||||
if blackboard.stamina < 100.0:
|
||||
blackboard.stamina += delta
|
||||
if blackboard.attack_cooldown > 0.0:
|
||||
blackboard.attack_cooldown -= delta
|
||||
if blackboard.guard_cooldown > 0.0:
|
||||
blackboard.guard_cooldown -= delta
|
||||
if blackboard.flee_cooldown > 0.0:
|
||||
blackboard.flee_cooldown -= delta
|
||||
blackboard.stamina = clamp(blackboard.stamina, 0, 100.0)
|
||||
blackboard.health = clamp(blackboard.health, 0, 100.0)
|
||||
if blackboard_get("stamina") < 100.0:
|
||||
blackboard_set("stamina", blackboard_get("stamina") + delta)
|
||||
if blackboard_get("attack_cooldown") > 0.0:
|
||||
blackboard_set("attack_cooldown", blackboard_get("attack_cooldown") - delta)
|
||||
if blackboard_get("guard_cooldown") > 0.0:
|
||||
blackboard_set("guard_cooldown", blackboard_get("guard_cooldown") - delta)
|
||||
if blackboard_get("flee_cooldown") > 0.0:
|
||||
blackboard_set("flee_cooldown", blackboard_get("flee_cooldown") - delta)
|
||||
blackboard_set("stamina", clamp(blackboard_get("stamina"), 0, 100.0))
|
||||
blackboard_set("health", clamp(blackboard_get("health"), 0, 100.0))
|
||||
return ERR_BUSY
|
||||
func update(delta):
|
||||
func update(tick, delta):
|
||||
return ERR_BUSY
|
||||
|
||||
##
|
||||
|
||||
Reference in New Issue
Block a user