190 lines
5.7 KiB
GDScript
190 lines
5.7 KiB
GDScript
extends Node
|
|
class_name BallGameAI3D
|
|
signal started_game
|
|
signal stopped_game
|
|
signal update_score
|
|
|
|
var _cheers = {}
|
|
var _game_area: AABB
|
|
var _teams = {}
|
|
var _main
|
|
var _state = STATE_INIT
|
|
var _ball_instance
|
|
var _cheer_locations = {}
|
|
var _team_start = {}
|
|
var _ball_carrier = null
|
|
var _ball_team = -1
|
|
var ch2team: Dictionary = {}
|
|
var gate2team = {}
|
|
var _gates = {}
|
|
var _scores = {}
|
|
var _speeds = {}
|
|
var training_time = 0.0
|
|
const max_training_time: float = 180.0
|
|
const max_score: int = 6
|
|
|
|
enum {STATE_INIT, STATE_START, STATE_RUNNING, STATE_GOAL, STATE_FINISH}
|
|
func _ready():
|
|
_game_area = AABB()
|
|
|
|
func set_ball(ball: Node):
|
|
_ball_instance = ball
|
|
|
|
func add_player(team: int, pl: Dictionary):
|
|
if !_teams.has(team):
|
|
_teams[team] = [pl]
|
|
else:
|
|
_teams[team].push_back(pl)
|
|
assert(pl != null)
|
|
ch2team[pl.scene] = team
|
|
func add_cheer(team: int, ch: Dictionary):
|
|
if !_cheers.has(team):
|
|
_cheers[team] = [ch]
|
|
else:
|
|
_cheers[team].push_back(ch)
|
|
assert(ch != null)
|
|
ch2team[ch.scene] = team
|
|
func add_cheer_game_location(team: int, loc: Vector3):
|
|
if !_cheer_locations.has(team):
|
|
_cheer_locations[team] = [loc]
|
|
else:
|
|
_cheer_locations[team].push_back(loc)
|
|
_game_area = _game_area.expand(loc)
|
|
func set_team_start(team: int, v: Vector3):
|
|
_team_start[team] = v
|
|
_game_area = _game_area.expand(v)
|
|
func check_goal(body, gate):
|
|
if _state in [STATE_RUNNING, STATE_GOAL]:
|
|
var team = gate2team[gate]
|
|
if body is RigidBody:
|
|
if body == _ball_instance:
|
|
_scores[team ^ 1] += 1
|
|
emit_signal("update_score", _scores)
|
|
elif body is KinematicBody && _ball_carrier != null:
|
|
if body == _ball_carrier.scene:
|
|
world.increase_xp(_ball_carrier, 150)
|
|
_scores[team] += 1
|
|
emit_signal("update_score", _scores)
|
|
catch_ball_delay += 3.0
|
|
_ball_carrier.scene.drop_object(_ball_instance)
|
|
_ball_instance.apply_impulse(Vector3(), Vector3(randf() - 0.5, randf() - 0.5, randf() - 0.5) * 10000.0)
|
|
_ball_carrier = null
|
|
_ball_team = -1
|
|
if _state == STATE_GOAL:
|
|
_state = STATE_RUNNING
|
|
print("score: ", _scores)
|
|
var max_team_score = -1
|
|
for k in _scores.keys():
|
|
if _scores[k] > max_team_score:
|
|
max_team_score = _scores[k]
|
|
if max_team_score >= max_score:
|
|
_state = STATE_FINISH
|
|
|
|
func set_team_gate(team: int, gate: Area):
|
|
_gates[team] = gate
|
|
gate2team[gate] = team
|
|
gate.connect("body_entered", self, "check_goal", [gate])
|
|
var o : = gate.global_transform.origin
|
|
_game_area = _game_area.expand(o)
|
|
func set_main(n):
|
|
_main = n
|
|
var start_timeout = 10.0
|
|
func start_game():
|
|
var ball = _ball_instance
|
|
ball.add_to_group("ball")
|
|
_state = STATE_START
|
|
for t in _teams.keys():
|
|
for ch in _teams[t]:
|
|
assert(ch != null)
|
|
print(ch)
|
|
assert(ch.scene != null)
|
|
print("start: ", _team_start[t])
|
|
ch.scene.walkto(_team_start[t] + Vector3(randf() * 2.0 - 1.0, 0.0, randf() * 2.0 - 1.0), 1.0 + ch.speed + randf() * ch.speed * 0.5)
|
|
start_timeout = 10.0
|
|
var loc = 0
|
|
for t in _cheers.keys():
|
|
for ch in _cheers[t]:
|
|
assert(ch != null)
|
|
print(ch)
|
|
assert(ch.scene != null)
|
|
ch.scene.walkto(_cheer_locations[t][loc % _cheer_locations[t].size()], 1.0 + ch.speed + randf() * ch.speed * 0.5)
|
|
loc += 1
|
|
for t in _teams.keys():
|
|
_scores[t] = 0
|
|
emit_signal("started_game", _scores)
|
|
func stop_game():
|
|
# for k in get_tree().get_nodes_in_group("ball"):
|
|
# k.queue_free()
|
|
_state = STATE_INIT
|
|
var max_score = -1
|
|
var winner_team = -1
|
|
for k in _scores.keys():
|
|
if _scores[k] > max_score:
|
|
max_score = _scores[k]
|
|
winner_team = k
|
|
if winner_team >= 0:
|
|
for e in _teams[winner_team]:
|
|
world.increase_xp(e, min(e.xp * 2, min(100 * e.level, 1000)))
|
|
for e in _cheers[winner_team]:
|
|
world.increase_xp(e, min(e.xp * 2, min(200 * e.level, 2000)))
|
|
emit_signal("stopped_game", _scores)
|
|
|
|
var ball_delay = 0.0
|
|
var catch_ball_delay = 0.0
|
|
func _physics_process(delta):
|
|
match(_state):
|
|
STATE_START:
|
|
start_timeout -= delta
|
|
# print("timeout")
|
|
if start_timeout <= 0.0:
|
|
for t in _teams.keys():
|
|
for ch in _teams[t]:
|
|
# print("teleport")
|
|
if ch.scene._path.size() > 0:
|
|
ch.scene.global_transform.origin = ch.scene._path[ch.scene._path.size() - 1]
|
|
else:
|
|
ch.scene.global_transform.origin = _team_start[t] + Vector3(randf() * 2.0 - 1.0, 0.0, randf() * 2.0 - 1.0)
|
|
_state = STATE_RUNNING
|
|
STATE_RUNNING:
|
|
# print("running")
|
|
var tgt = _ball_instance.global_transform.origin
|
|
for t in _teams.keys():
|
|
for ch in _teams[t]:
|
|
if ch.scene._path && ch.scene._path.size() > 0:
|
|
var moveto = ch.scene._path[ch.scene._path.size() - 1]
|
|
if tgt.distance_squared_to(moveto) > 0.5:
|
|
# print("walking")
|
|
ch.scene.walkto(tgt, 1.0 + ch.speed + randf() * ch.speed * 0.5)
|
|
else:
|
|
ch.scene.walkto(tgt, 1.0 + ch.speed + randf() * ch.speed * 0.5)
|
|
if ch.scene.global_transform.origin.distance_to(tgt) < 0.6 && _ball_carrier == null && catch_ball_delay <= 0:
|
|
ch.scene.take_object(_ball_instance)
|
|
_state = STATE_GOAL
|
|
_ball_carrier = ch
|
|
_ball_team = t
|
|
ball_delay = 20.0
|
|
for tg in _teams.keys():
|
|
for ch in _teams[tg]:
|
|
if ch != _ball_carrier:
|
|
ch.scene.walkto(_gates[tg].global_transform.origin, 1.0 + ch.speed + randf() * ch.speed * 0.5)
|
|
else:
|
|
ch.scene.walkto(_gates[tg ^ 1].global_transform.origin, 1.0 + ch.speed + randf() * ch.speed * 0.5)
|
|
world.increase_xp(_ball_carrier, 50)
|
|
if catch_ball_delay > 0:
|
|
catch_ball_delay -= delta
|
|
STATE_GOAL:
|
|
ball_delay -= delta
|
|
if ball_delay <= 0 || randf() > 0.995:
|
|
if _ball_carrier:
|
|
_ball_carrier.scene.drop_object(_ball_instance)
|
|
_ball_carrier = null
|
|
_ball_team = -1
|
|
catch_ball_delay = 5.0
|
|
_state = STATE_RUNNING
|
|
STATE_FINISH:
|
|
stop_game()
|
|
_state = STATE_INIT
|
|
training_time += delta
|
|
if training_time >= max_training_time:
|
|
stop_game()
|