diff options
Diffstat (limited to 'godot/scripts')
| -rw-r--r-- | godot/scripts/CharacterAIManager.gd | 18 | ||||
| -rw-r--r-- | godot/scripts/GameBase.gd | 3 | ||||
| -rw-r--r-- | godot/scripts/Server.gd | 26 | ||||
| -rw-r--r-- | godot/scripts/World.gd | 7 | ||||
| -rw-r--r-- | godot/scripts/ballistics/Cannonball.gd | 11 | ||||
| -rw-r--r-- | godot/scripts/characters/Idle.gd | 2 | ||||
| -rw-r--r-- | godot/scripts/characters/ManCannon.gd | 107 | ||||
| -rw-r--r-- | godot/scripts/characters/NetworkedCharacter.gd | 14 | ||||
| -rw-r--r-- | godot/scripts/characters/player_controller_new.gd | 164 | ||||
| -rw-r--r-- | godot/scripts/fsm/State.gd | 22 | ||||
| -rw-r--r-- | godot/scripts/fsm/StateMachine.gd | 35 | ||||
| -rw-r--r-- | godot/scripts/machines/Cannon.gd | 27 | ||||
| -rw-r--r-- | godot/scripts/vehicles/Gunboat.gd | 10 |
13 files changed, 376 insertions, 70 deletions
diff --git a/godot/scripts/CharacterAIManager.gd b/godot/scripts/CharacterAIManager.gd index fb86a48..61d38ae 100644 --- a/godot/scripts/CharacterAIManager.gd +++ b/godot/scripts/CharacterAIManager.gd @@ -4,7 +4,7 @@ var calcs_per_tick: int = 15 var request_queue: Array = [] #array of dictionaries var cur_req: Dictionary var cur_req_args: Dictionary -var WORLD_MAP_RID +var WORLD_MAP_RID: RID enum Task {PATHFIND, FINDITEM} @@ -13,6 +13,9 @@ enum Task {PATHFIND, FINDITEM} func _ready(): pass # Replace with function body. +func set_rid(id: RID) -> void: + WORLD_MAP_RID = id + func _physics_process(_delta): for i in calcs_per_tick: if len(request_queue) == 0: @@ -22,7 +25,20 @@ func _physics_process(_delta): if cur_req["type"] == Task.PATHFIND: var dest_vec: Vector3 = cur_req_args["dest"] if cur_req_args["obj"] == null else cur_req_args["obj"].global_transform.origin var path: PoolVector3Array = NavigationServer.map_get_path(WORLD_MAP_RID, cur_req["char"].global_transform.origin, dest_vec, cur_req_args["optimize"]) + cur_req["char"].ai_set_path_array(path) + elif cur_req["type"] == Task.FINDITEM: + var bodies = cur_req["char"].get_node("AISearchArea").get_overlapping_bodies() + for body in bodies: + if body.name.begins_with(cur_req_args["objtype"]): + var path: PoolVector3Array = NavigationServer.map_get_path(WORLD_MAP_RID, cur_req["char"].global_transform.origin, body.global_transform.origin, cur_req_args["optimize"]) + cur_req["char"].ai_set_path_target(body.global_transform.origin) + #cur_req["char"].ai_set_path_array(path) + cur_req["char"].ai_set_look_status(body, "TRACK") + return #will request a path from character to dest_g, or to the global origin of obj if passed func request_find_path(character: NetChar, dest_g: Vector3, precise: bool, obj: Spatial = null) -> void: request_queue.append({"char" : character, "type" : Task.PATHFIND, "args" : {"dest" : dest_g, "obj" : obj, "optimize" : !precise}}) + +func request_find_object(character: NetChar, object: String, radius: float, precise: bool): + request_queue.append({"char" : character, "type" : Task.FINDITEM, "args" : {"objtype" : object, "radius" : radius, "optimize" : !precise}}) diff --git a/godot/scripts/GameBase.gd b/godot/scripts/GameBase.gd index 9f24d7b..abc269f 100644 --- a/godot/scripts/GameBase.gd +++ b/godot/scripts/GameBase.gd @@ -9,6 +9,7 @@ var player_name : String var player_team : String var player_char = null onready var cam = $PLAYERCAM +onready var hud = $HUD var players_info = {} #dictionary of id : name, team, ping, etc. @@ -77,7 +78,7 @@ remotesync func game_hitsound(): remotesync func game_killsound(): $HUD.ui_play_killsound() -func select_character(dest): +func request_select_character(dest): if player_char == null: rpc_id(1, "_call_on_server", "_client_request_change_character", {"id" : client_id, "current_char_name" : "NULL", "char_name" : dest}) else: diff --git a/godot/scripts/Server.gd b/godot/scripts/Server.gd index b4b0a28..e360703 100644 --- a/godot/scripts/Server.gd +++ b/godot/scripts/Server.gd @@ -30,7 +30,15 @@ func start_server(_server_name: String, _motd: String, max_players: int, map_pat server_name = _server_name motd = _motd player_limit = max_players - + + server_enet = NetworkedMultiplayerENet.new() + var srv_stat = server_enet.create_server(port, max_players) + if srv_stat != OK: + print_line("Error creating server. Code: "+str(srv_stat)) + stop_server() + return + tree.set_network_peer(server_enet) + world = load(map_path) if world: world = world.instance() @@ -43,14 +51,6 @@ func start_server(_server_name: String, _motd: String, max_players: int, map_pat world.client_id = 1 - server_enet = NetworkedMultiplayerENet.new() - var srv_stat = server_enet.create_server(port, max_players) - if srv_stat != OK: - print_line("Error creating server. Code: "+str(srv_stat)) - stop_server() - return - tree.set_network_peer(server_enet) - print_line("Server started successfully.") func stop_server(): @@ -125,3 +125,11 @@ func _send_chat(arguments): arguments["name"]=connected_players[arguments["id"]][0] print_line(arguments["name"]+ ": " + arguments["msg"]) world.rpc("game_chat_msg", arguments["name"]+ ": " + arguments["msg"]) + +func _set_ai_state(args): + var charname: String = args[0] + var state: String = args[1] + print(args) + var man: NetChar = world.get_node("PLAYERS/"+charname) + if man: + man.ai_set_state(state) diff --git a/godot/scripts/World.gd b/godot/scripts/World.gd index 01df1b5..90b3cf7 100644 --- a/godot/scripts/World.gd +++ b/godot/scripts/World.gd @@ -7,7 +7,7 @@ onready var pathfinder = get_node("PLAYERS/Player2") var path = [] var map_rids var client_id -var player_char +var player_char: NetChar var players_info = {} var WORLD_MAP_RID : RID @@ -23,12 +23,13 @@ func _ready(): #merge all nav meshes onto the main map yield(get_tree().create_timer(1.0), "timeout") WORLD_MAP_RID = get_world().get_navigation_map() - find_path() + CharacterAIManager.set_rid(WORLD_MAP_RID) + #find_path() remotesync func update_players_info(info): players_info = info -remote func _call_on_server(function, arguments): +remotesync func _call_on_server(function, arguments): print('Remote server call: ' + function) $Server.call(function, arguments) diff --git a/godot/scripts/ballistics/Cannonball.gd b/godot/scripts/ballistics/Cannonball.gd index b41f104..5e6b84d 100644 --- a/godot/scripts/ballistics/Cannonball.gd +++ b/godot/scripts/ballistics/Cannonball.gd @@ -3,9 +3,12 @@ extends "res://scripts/ballistics/NetworkedProjectile.gd" export var drag_constant: float = 0.3 var damage_exceptions = [] var oldvel: Vector3 +var oldoldvel: Vector3 +const inventory_name: String = "cannonball" func _physics_process(_delta): if is_network_master(): + oldoldvel = oldvel oldvel = linear_velocity add_force(-1*linear_velocity*drag_constant, Vector3.ZERO) if global_transform.origin.y < -20: @@ -15,10 +18,6 @@ func get_init_info(): return {"linear_velocity" : linear_velocity, "angular_velocity" : angular_velocity, "oldvel" : oldvel, "shooter" : shooter, "shooter_id" : shooter_id} func _on_collision(body): - if is_network_master() and body.has_method("load_cannonball") and !body.loaded: - body.rpc("load_cannonball") - rpc("net_remove") - return - if is_network_master() and oldvel.length() > 20 and !damage_exceptions.has(body) and body.has_method("damage"): - body.rpc("damage", oldvel.length(), "BLUNT", [shooter_id, shooter], "using 'cannon'") + if is_network_master() and oldoldvel.length() > 20 and !damage_exceptions.has(body) and body.has_method("damage"): + body.rpc("damage", oldoldvel.length(), "BLUNT", [shooter_id, shooter], "using 'cannon'") damage_exceptions.append(body) diff --git a/godot/scripts/characters/Idle.gd b/godot/scripts/characters/Idle.gd new file mode 100644 index 0000000..4be00e4 --- /dev/null +++ b/godot/scripts/characters/Idle.gd @@ -0,0 +1,2 @@ +extends State + diff --git a/godot/scripts/characters/ManCannon.gd b/godot/scripts/characters/ManCannon.gd new file mode 100644 index 0000000..b4d111c --- /dev/null +++ b/godot/scripts/characters/ManCannon.gd @@ -0,0 +1,107 @@ +extends State + +enum ManCannonStates { INITIAL, OPERATE_CANNON, MOVE_TO_CANNON, FIND_CANNONBALL } +var ai_substate: int +var path_requested: bool = false +var retry_timer: float = 0.0 +var searching_for: String + +var cannon: NetMachine + +# Corresponds to the `_process()` callback. +func update(delta: float) -> void: + retry_timer -= delta + +# Virtual function. Corresponds to the `_physics_process()` callback. +func physics_update(_delta: float) -> void: + match ai_substate: + ManCannonStates.INITIAL: + _state_initial() + ManCannonStates.MOVE_TO_CANNON: + _state_move_to_cannon() + ManCannonStates.FIND_CANNONBALL: + _state_find_cannonball() + ManCannonStates.OPERATE_CANNON: + _state_operate_cannon() + +func _state_initial() -> void: + if cannon.loaded: + change_substate(ManCannonStates.MOVE_TO_CANNON) + else: + change_substate(ManCannonStates.FIND_CANNONBALL) + +func _state_move_to_cannon() -> void: + if !path_requested: + #CharacterAIManager.request_find_path(owner, Vector3.ZERO, true, cannon.get_node("AINavPoint")) + owner.ai_set_path_target(cannon.get_node("AINavPoint").global_transform.origin) + owner.ai_set_look_status(cannon.steer_area, "TRACK") + path_requested = true + if (owner.global_transform.origin - cannon.get_node("AINavPoint").global_transform.origin).length_squared() > 4: + owner.ai_set_path_target(cannon.get_node("AINavPoint").global_transform.origin) + if retry_timer <= 0 and owner.use_ray.is_colliding(): + if owner.use_ray.get_collider() == cannon.steer_area: + owner.use_held = false + owner.initiate_use() + if !cannon.loaded: + owner.use_held = true + retry_timer = 3.1 + + if owner.machine == cannon: + owner.ai_set_look_status(null, "NONE") + retry_timer = 1.0 + change_substate(ManCannonStates.OPERATE_CANNON) + +func _state_find_cannonball() -> void: + #CHECK FOR BALL BOX FIRST! /setaistate Player ManCannon + if !path_requested: + CharacterAIManager.request_find_object(owner, "BallBarrel", 50, true) + searching_for = "BallBarrel" + path_requested = true + #if !path_requested: + # CharacterAIManager.request_find_object(owner, "Cannonball", 50, false) + # searching_for = "Cannonball" + # path_requested = true + if owner.use_ray.is_colliding(): + if owner.use_ray.get_collider().name.begins_with("UseArea") and owner.use_ray.get_collider().get_parent().name.begins_with(searching_for): + owner.initiate_use() + + #cannonball found + if owner.inventory["cannonball"] > 0: + change_substate(ManCannonStates.MOVE_TO_CANNON) + +func _state_operate_cannon() -> void: + if owner.machine != cannon: #if control lost + if is_instance_valid(cannon): + change_substate(ManCannonStates.MOVE_TO_CANNON) + else: + state_machine.transition_to("Idle") + return + if retry_timer <= 0.0: + cannon.attack1() + owner.initiate_use() + change_substate(ManCannonStates.FIND_CANNONBALL) + +func change_substate(to: int): + path_requested = false + ai_substate = to + +func enter(msg := {}) -> void: + retry_timer = 0 + ai_substate = ManCannonStates.INITIAL + if "cannon" in msg.keys(): + cannon = msg["cannon"] + else: + if owner.ai_target_machine != null: + cannon = owner.ai_target_machine + return + var bodies = owner.get_node("AISearchArea").get_overlapping_bodies() + for body in bodies: + if body.name.begins_with("Cannon"): + cannon = body + return + #if cannon not found + print("cannon not found") + state_machine.transition_to("Idle") + +func exit() -> void: + pass diff --git a/godot/scripts/characters/NetworkedCharacter.gd b/godot/scripts/characters/NetworkedCharacter.gd index c8e90a4..c14d46f 100644 --- a/godot/scripts/characters/NetworkedCharacter.gd +++ b/godot/scripts/characters/NetworkedCharacter.gd @@ -15,14 +15,21 @@ var world: Spatial = null var carrying: bool = false var carrying_object: NetObject = null +var loading: bool = false +var load_target: RigidBody = null +var load_ammo: String + # Control var controlling_machine: bool = false #whether character is riding/controlling something var machine: RigidBody = null -export var is_player: bool = false #whether character is currently controlled by a player +var is_player: bool = false #whether character is currently controlled by a player var ladder_m: Spatial = null +const inventory_caps: Dictionary = {"cannonball" : 1} +remote var inventory: Dictionary = {"cannonball" : 0} # + func get_init_info() -> Dictionary: - return {"linear_velocity" : linear_velocity, "angular_velocity" : angular_velocity, "controlling_machine" : controlling_machine, "team" : team, "health" : health, "nametag" : $Nametag.text} + return {"linear_velocity" : linear_velocity, "angular_velocity" : angular_velocity, "controlling_machine" : controlling_machine, "team" : team, "health" : health, "inventory": inventory, "nametag" : $Nametag.text} func mp_init(init_info: Dictionary): for variable in init_info.keys(): @@ -60,11 +67,12 @@ func take_control_of_machine(slave_machine: RigidBody): controlling_machine = true func lose_machine(): - if is_network_master(): world.cam.attach(self, "FIRSTPERSON", "./Neck/Head") + if is_network_master() and get_network_master() != 1: world.cam.attach(self, "FIRSTPERSON", "./Neck/Head") controlling_machine = false machine = null remotesync func damage(dmg_amt: int, _type: String, shooter: Array, extra: String): + print(dmg_amt) health -= dmg_amt if health <= 0 and is_network_master(): if shooter[0] != get_network_master() and shooter[0] != 1: world.rpc_id(shooter[0], "game_killsound") diff --git a/godot/scripts/characters/player_controller_new.gd b/godot/scripts/characters/player_controller_new.gd index 6e2a28b..b2af75c 100644 --- a/godot/scripts/characters/player_controller_new.gd +++ b/godot/scripts/characters/player_controller_new.gd @@ -7,6 +7,7 @@ var mouse_axis: Vector2 = Vector2.ZERO onready var head: Spatial = $Neck/Head onready var neck: Spatial = $Neck onready var melee_ray: RayCast = $"%MeleeRay" +onready var use_ray: RayCast = $"%UseRay" onready var gun_ray: RayCast = $Neck/Head/GunRay onready var carry_point: Position3D = $Neck/Head/CarryPoint onready var viewmodel: Spatial = $Neck/Head/VIEWMODEL_ARMS @@ -17,6 +18,7 @@ var direction := Vector3() var move_axis := Vector2() var floorspeed := Vector3() var jumping:bool = false +var use_held:bool = false var can_jump:bool = true onready var nav: NavigationAgent = $NavigationAgent @@ -37,10 +39,17 @@ var c_friction:float = 4.0 var air_control:float = 0.3 #ai -var ai_state: String = "IDLE" +onready var ai_state_machine:StateMachine = get_node("AIStateMachine") +enum AIStates { IDLE, MAN_CANNON } +export(AIStates) var ai_state = AIStates.IDLE + +export var ai_target_machine_path := NodePath() +var ai_target_machine: NetMachine = null var ai_should_pathfind: bool = false var ai_path_target_global: Vector3 = Vector3.ZERO +var ai_path_array: Array = [] +const AI_PATH_PROXIM_DIST_SQ: float = 1.0 var ai_look_target: Vector3 = Vector3.ZERO var ai_should_look: bool = false @@ -63,6 +72,15 @@ func _ready() -> void: $"%MeleeRay".add_exception(self) $"%UseRay".add_exception($AreaDetect) $"%MeleeRay".add_exception($AreaDetect) + + if ai_target_machine_path: + ai_target_machine = get_node(ai_target_machine_path) + if get_tree().get_network_unique_id() != 1: #only server needs ai processing + get_node("AIStateMachine").queue_free() + + #for playerbody in get_tree().get_nodes_in_group("player"): + # if playerbody.team == team and playerbody != self: + # add_collision_exception_with(playerbody) func add_weapon_vm(weapon_vm: Spatial, trfrm: Transform): viewmodel.get_node("Skeleton/GunBone").add_child(weapon_vm) @@ -70,10 +88,12 @@ func add_weapon_vm(weapon_vm: Spatial, trfrm: Transform): # Called every frame. 'delta' is the elapsed time since the previous frame func _process(_delta: float) -> void: - if is_player and !world.is_chatting: + if is_network_master() and !is_player: + pass + elif is_player and !world.is_chatting: + use_held = Input.is_action_pressed("use") if Input.is_action_just_pressed("use"): initiate_use() - if controlling_machine: if Input.is_action_just_pressed("fire"): machine.attack1() @@ -121,26 +141,57 @@ func initiate_use(): carrying_object.rpc("set_nm",1) carrying_object = null return - if $"%UseRay".is_colliding(): - var area_c = $"%UseRay".get_collider() - match area_c.name: - "SteerArea": #must be a networkedmachine - if area_c.get_parent().controllable: world.rpc_id(1, "_call_on_server", "_client_request_control_vehicle", {"id" : world.client_id, "machine_path" : area_c.get_parent().get_path(), "char_name" : name}) - "LadderArea": - mount_ladder(area_c.get_parent()) - "TugArea": - pass - "CarryArea": - if weapon.name == "HANDS" and weapon.can_pickup(): - carrying = true - carrying_object = area_c.get_parent() - carrying_object.rpc("set_nm",get_network_master()) - carry_point.global_transform.origin = carrying_object.global_transform.origin - _: - pass + + #interact with world + if !use_ray.is_colliding(): return + var area_c = use_ray.get_collider() + match area_c.name: + "SteerArea": #must be a networkedmachine + if area_c.get_parent().controllable: world.rpc_id(1, "_call_on_server", "_client_request_control_vehicle", {"id" : world.client_id, "machine_path" : area_c.get_parent().get_path(), "char_name" : name}) + elif !area_c.get_parent().loaded and inventory[area_c.get_parent().ammo_type] > 0: + loading = true + load_target = area_c.get_parent() + load_ammo = area_c.get_parent().ammo_type + "LadderArea": + mount_ladder(area_c.get_parent()) + "TugArea": + pass + "UseArea": #must have method use_generic + area_c.get_parent().use_generic(self) + "PickupArea": #must be a networkedprojectile. must have inventory_name property + var type: String = area_c.get_parent().inventory_name + if inventory[type] < inventory_caps[type]: + area_c.get_parent().rpc("net_remove") + inventory[type] += 1 + rset("inventory", inventory) + "CarryArea": + if weapon.name == "HANDS" and weapon.can_pickup(): + carrying = true + carrying_object = area_c.get_parent() + carrying_object.rpc("set_nm",get_network_master()) + carry_point.global_transform.origin = carrying_object.global_transform.origin + _: + pass + +func load_process(delta) -> void: + if use_ray.is_colliding() and use_ray.get_collider().get_parent() == load_target and use_held: + var progress: float =load_target.increase_load(delta) + if progress < 0: + if get_network_master() != 1: world.hud.hide_progress() + load_target.reset_load() + loading = false + load_target = null + inventory[load_ammo] -= 1 + else: + if get_network_master() != 1: world.hud.set_progress(progress) + else: + if get_network_master() != 1: world.hud.hide_progress() + load_target.reset_load() + loading = false + load_target = null func carry_process() -> void: - if !is_instance_valid(carrying_object): + if !is_instance_valid(carrying_object) or carrying_object.get_network_master() != get_network_master(): carrying_object = null carrying = false return @@ -157,6 +208,8 @@ func carry_process() -> void: # Called every physics tick. 'delta' is constant func _physics_process(delta: float) -> void: if is_network_master(): + if loading: load_process(delta) + move_dir_process() if !is_player: #ai behavior if ai_should_look: ai_look_at() if carrying: @@ -168,6 +221,21 @@ func _physics_process(delta: float) -> void: else: walk(delta) is_on_floor = false #reset whether is on floor in between frames + + +func move_dir_process(): + direction = Vector3() + if is_player: + var aim: Basis = head.get_global_transform().basis + direction += -move_axis.x * aim.z + move_axis.y * aim.x + direction.y = 0 + direction = direction.normalized() + else: + if ai_should_pathfind: + if !ai_path_process(): return + direction = ai_path_target_global - global_transform.origin + direction.y = 0 + direction = direction.normalized() # called each physics frame func on_floor_test() -> bool: @@ -198,19 +266,14 @@ func _integrate_forces(state: PhysicsDirectBodyState) -> void: break if i == player_state.get_contact_count() - 1: friction = 1 - nav.set_velocity(velocity) + rpc("set_phys_transform", transform, linear_velocity) if global_transform.origin.y < -30: rpc("damage", 500000, "drown", [1, "Davy Jones"], "") + + nav.set_velocity(velocity) func walk(_delta: float) -> void: - # Input - direction = Vector3() - var aim: Basis = head.get_global_transform().basis - direction += -move_axis.x * aim.z + move_axis.y * aim.x - direction.y = 0 - direction = direction.normalized() - if floor_normal != Vector3.UP: direction = direction.rotated(floor_normal.cross(Vector3.UP).normalized(), Vector3.UP.angle_to(floor_normal)) # Jump @@ -306,13 +369,17 @@ remotesync func play_weapon_sound(filepath) -> void: remotesync func add_rocket_to_scene(pos, dir, id): var rocket = preload("res://scenes/ballistics/Rocket.tscn").instance() world.get_node("BALLISTICS").add_child(rocket, true) - rocket.shooter = name + " (" + world.players_info[get_network_master()][0] + ")" + rocket.shooter = name + if get_network_master() != 1: rocket.shooter+= " (" + world.players_info[get_network_master()][0] + ")" rocket.shooter_id = id rocket.global_transform.origin = pos rocket.global_transform.basis = Basis(-1*dir.z, dir.y, dir.x) rocket.add_collision_exception_with(self) -func set_look_status(target, type="STATIC"): +func ai_set_state(state: String): + ai_state_machine.transition_to(state) + +func ai_set_look_status(target, type:String="STATIC"): if type == "STATIC": ai_look_target = target ai_should_look = true @@ -321,11 +388,9 @@ func set_look_status(target, type="STATIC"): ai_should_look = true ai_should_track = true else: + ai_should_look = false ai_should_track = false -func set_path_target(target): - ai_path_target_global = target - func ai_look_at(): if ai_should_track: if is_instance_valid(ai_track_object): @@ -335,10 +400,33 @@ func ai_look_at(): ai_should_track = false var p_neck: float = Vector3(ai_look_target.x - neck.global_transform.origin.x, 0, ai_look_target.z - neck.global_transform.origin.z).signed_angle_to(-neck.global_transform.basis.z, neck.global_transform.basis.y ) var p_head: float = Vector3(ai_look_target.x - neck.global_transform.origin.x, ai_look_target.y - head.global_transform.origin.y, ai_look_target.z - neck.global_transform.origin.z).signed_angle_to( -head.global_transform.basis.z, head.global_transform.basis.x) - if abs(p_neck) > 0.01: - neck.rotation_degrees.y = lerp(neck.rotation_degrees.y, neck.rotation_degrees.y-p_neck, AI_LOOK_SPEED+abs(p_neck/3.1415)) - if abs(p_head) > 0.01: - head.rotation_degrees.x = lerp(head.rotation_degrees.x, head.rotation_degrees.x-p_head, AI_LOOK_SPEED+abs(p_head/3.1415)) + neck.rotation_degrees.y = lerp(neck.rotation_degrees.y, neck.rotation_degrees.y-p_neck, AI_LOOK_SPEED+abs(p_neck/3.1415)) + head.rotation_degrees.x = lerp(head.rotation_degrees.x, head.rotation_degrees.x-p_head, AI_LOOK_SPEED+abs(p_head/3.1415)) if abs(p_neck) <= 0.01 and abs(p_head) <= 0.01 and !ai_should_track: ai_should_look = false + +func ai_set_path_target(target: Vector3): + ai_should_pathfind = true + nav.set_target_location(target) + #CharacterAIManager.request_find_path(self, target, true) + +func ai_set_path_array(arr: PoolVector3Array): + world.draw_path(arr) + ai_should_pathfind = true + ai_path_array = arr + ai_path_target_global = ai_path_array[0] + +func ai_path_process() -> bool: +# if (global_transform.origin - ai_path_array[0]).length_squared() < AI_PATH_PROXIM_DIST_SQ: +# ai_path_array.remove(0) +# if len(ai_path_array) == 0: #destination reached +# ai_should_pathfind = false +# return false +# else: ai_path_target_global = ai_path_array[0] +# return true + if nav.is_navigation_finished(): + ai_should_pathfind = false + return false + ai_path_target_global = nav.get_next_location() + return true diff --git a/godot/scripts/fsm/State.gd b/godot/scripts/fsm/State.gd new file mode 100644 index 0000000..be7ba2d --- /dev/null +++ b/godot/scripts/fsm/State.gd @@ -0,0 +1,22 @@ +class_name State +extends Node + +var state_machine = null + +# Corresponds to the `_process()` callback. +func update(_delta: float) -> void: + pass + +# Virtual function. Corresponds to the `_physics_process()` callback. +func physics_update(_delta: float) -> void: + pass + +# Virtual function. Called by the state machine upon changing the active state. The `msg` parameter +# is a dictionary with arbitrary data the state can use to initialize itself. +func enter(_msg := {}) -> void: + pass + +# Virtual function. Called by the state machine before changing the active state. Use this function +# to clean up the state. +func exit() -> void: + pass diff --git a/godot/scripts/fsm/StateMachine.gd b/godot/scripts/fsm/StateMachine.gd new file mode 100644 index 0000000..834f036 --- /dev/null +++ b/godot/scripts/fsm/StateMachine.gd @@ -0,0 +1,35 @@ +class_name StateMachine +extends Node + +# Emitted when transitioning to a new state. +signal transitioned(state_name) + +# Path to the initial active state. We export it to be able to pick the initial state in the inspector. +export var initial_state := NodePath() + +# The current active state. At the start of the game, we get the `initial_state`. +onready var state: State = get_node(initial_state) + + +func _ready() -> void: + yield(owner, "ready") + # The state machine assigns itself to the State objects' state_machine property. + for child in get_children(): + child.state_machine = self + state.enter() + +func _process(delta: float) -> void: + state.update(delta) + +func _physics_process(delta: float) -> void: + state.physics_update(delta) + +func transition_to(target_state_name: String, msg: Dictionary = {}) -> void: + if not has_node(target_state_name): + print("no state") + return + + state.exit() + state = get_node(target_state_name) + state.enter(msg) + emit_signal("transitioned", state.name) diff --git a/godot/scripts/machines/Cannon.gd b/godot/scripts/machines/Cannon.gd index 6c0b350..b66903a 100644 --- a/godot/scripts/machines/Cannon.gd +++ b/godot/scripts/machines/Cannon.gd @@ -21,6 +21,22 @@ export var max_yaw = 15 onready var muzzle: Spatial = get_node("YawJoint/PitchJoint/Muzzle") onready var status: Label3D = get_node("StatusNotifier") +onready var steer_area: Area = get_node("SteerArea") + +const ammo_type = "cannonball" + +var load_time: float = 3.0 +var load_progress: float = 0.0 + +func increase_load(delta) -> float: + if loaded: return -1.0 + load_progress += delta + if load_progress >= load_time: + rpc("load_cannonball") + return load_progress/load_time + +func reset_load(): + load_progress = 0 remote func update_aim(pitch_z, yaw_y): $YawJoint/PitchJoint.rotation_degrees.z = pitch_z @@ -39,12 +55,13 @@ func mp_init(init_info): func _ready(): if get_parent().name != "MACHINES": #if cannon is aboard ship add_collision_exception_with(get_parent().get_parent()) - mode = RigidBody.MODE_KINEMATIC + mode = RigidBody.MODE_STATIC + print("kinematic") world_ballistics = world.get_node("BALLISTICS") if loaded: controllable = true func on_new_control(): - if is_network_master(): world.cam.attach(self, "STATIC", "./YawJoint/PitchJoint/CameraPoint") + if is_network_master() and get_network_master() != 1: world.cam.attach(self, "STATIC", "./YawJoint/PitchJoint/CameraPoint") func _physics_process(delta): if in_use and is_network_master(): #aim @@ -78,9 +95,11 @@ remotesync func fire(): add_collision_exception_with(cball) cball.global_transform.origin = muzzle.global_transform.origin cball.linear_velocity = muzzle.global_transform.basis.x*ball_speed - cball.shooter = user.name + " (" + world.players_info[user.get_network_master()][0] + ")" + cball.set_network_master(1) + cball.shooter = user.name + if user.get_network_master() != 1: cball.shooter += " (" + world.players_info[user.get_network_master()][0] + ")" cball.shooter_id = user.get_network_master() - if mode == RigidBody.MODE_KINEMATIC: + if mode == RigidBody.MODE_STATIC: get_parent().get_parent().apply_impulse($YawJoint/PitchJoint.global_transform.origin - get_parent().global_transform.origin, -1*cball.mass*ball_speed*muzzle.global_transform.basis.x) else: if is_network_master(): apply_impulse($YawJoint/PitchJoint.global_transform.origin - global_transform.origin, -1*cball.mass*ball_speed*muzzle.global_transform.basis.x) diff --git a/godot/scripts/vehicles/Gunboat.gd b/godot/scripts/vehicles/Gunboat.gd index 03252e6..fe5473a 100644 --- a/godot/scripts/vehicles/Gunboat.gd +++ b/godot/scripts/vehicles/Gunboat.gd @@ -5,7 +5,7 @@ export var team = 0 const accel = 500000 const turn_accel = 50000 -export(float, 0.0, 1.0) var sail_out = 0.0 +remote var sail_out = 0.0 export var sail_speed : float = 0.2 var sail_turn = 0 export var sail_turn_speed = 30 @@ -87,9 +87,9 @@ func _physics_process(delta): sail.set_sheet(sail_out) $Rudder.rotation_degrees.y = rudder_turn #$Mast.rotation_degrees.y = sail_turn - #var push_force = accel*sail_out*world.winddir.dot($Mast.global_transform.basis.x) - #if world.winddir.angle_to($Mast.global_transform.basis.x) < PI/2: - # add_force(global_transform.basis.x*push_force, Vector3.ZERO) + var push_force = accel*sail_out*world.winddir.dot(global_transform.basis.x) + if world.winddir.angle_to(global_transform.basis.x) < PI/2: + add_force(global_transform.basis.x*push_force, Vector3.ZERO) add_torque(Vector3(0,-rudder_turn*rudder_constant*(0.5+linear_velocity.dot(global_transform.basis.x)),0)) add_torque(Vector3(-100000*angular_velocity.x,0,0)) add_torque(Vector3(0,0,-100000*angular_velocity.z)) @@ -110,5 +110,5 @@ func _physics_process(delta): sail_out = clamp(sail_out, 0, 1) rudder_turn = clamp(rudder_turn, -RUDDER_MAX, RUDDER_MAX) sail_turn = clamp(sail_turn, -SAIL_MAX, SAIL_MAX) - + rset("sail_out", sail_out) #add_force(transform.basis.x*accel*Input.get_action_strength("move_forward"), Vector3.ZERO) |
