diff options
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/ClientUI.gd | 27 | ||||
| -rw-r--r-- | scripts/CmdPrompt.gd | 26 | ||||
| -rw-r--r-- | scripts/Console.gd | 14 | ||||
| -rw-r--r-- | scripts/GameBase.gd | 77 | ||||
| -rw-r--r-- | scripts/Server.gd | 110 | ||||
| -rw-r--r-- | scripts/ServerUI.gd | 38 | ||||
| -rw-r--r-- | scripts/World.gd | 51 | ||||
| -rw-r--r-- | scripts/ballistics/Cannonball.gd | 24 | ||||
| -rw-r--r-- | scripts/boats/Gunboat.gd | 121 | ||||
| -rw-r--r-- | scripts/characters/player_controller_new.gd | 236 | ||||
| -rw-r--r-- | scripts/machines/Cannon.gd | 92 | ||||
| -rw-r--r-- | scripts/world_tools.gd | 65 |
12 files changed, 881 insertions, 0 deletions
diff --git a/scripts/ClientUI.gd b/scripts/ClientUI.gd new file mode 100644 index 0000000..6a3eb41 --- /dev/null +++ b/scripts/ClientUI.gd @@ -0,0 +1,27 @@ +extends Node2D + +var client : NetworkedMultiplayerENet +var world + +func _ready(): + world = preload("res://scenes/GameBase.tscn").instance() + get_tree().connect("network_peer_connected", self, "_player_connected") + get_tree().connect("network_peer_disconnected", self, "_player_disconnected") + get_tree().connect("connected_to_server", self, "_connection_successful") + get_tree().connect("connection_failed", self, "_connected_fail") + get_tree().connect("server_disconnected", world, "_server_disconnected") + +func _connect_btn(): + client = NetworkedMultiplayerENet.new() + client.create_client($IP.text, $Port.value) + + get_tree().set_network_peer(client) + + +func _connection_successful(): + get_tree().get_root().add_child(world) + world.client = client + world.client_id = get_tree().get_network_unique_id() + world.player_name = $Name.text + print("Connected.") + queue_free() diff --git a/scripts/CmdPrompt.gd b/scripts/CmdPrompt.gd new file mode 100644 index 0000000..965631b --- /dev/null +++ b/scripts/CmdPrompt.gd @@ -0,0 +1,26 @@ +extends LineEdit + +export var console_path := @""; onready var console := get_node(console_path) as ScrollContainer +var server_ref = null +var ui_ref = null + +func enter_cmd(new_text: String): + console.add_line(new_text) + text = "" + if new_text.substr(0,1) == "/": #PROCESS COMMAND + var end_ind = new_text.find(" ")-1 + if end_ind < -1: end_ind = -1 + var cmd : String = new_text.substr(1, end_ind) + var args = new_text.substr(end_ind+1, -1).split(" ", false) + + if cmd == "say": + if server_ref != null: + var m_args = {"name" : "SERVER", "msg" : args.join(" ")} + server_ref._send_chat(m_args) + elif cmd == "start": + if server_ref == null: + ui_ref.start_server() + elif cmd == "stop": + if server_ref != null: + ui_ref.stop_server() + diff --git a/scripts/Console.gd b/scripts/Console.gd new file mode 100644 index 0000000..ac73525 --- /dev/null +++ b/scripts/Console.gd @@ -0,0 +1,14 @@ +extends ScrollContainer + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass + +func add_line(text): + var lbl = Label.new() + lbl.autowrap = true + lbl.text = text + text = "" + $ConsoleLines.add_child(lbl) + yield(get_tree().create_timer(0.05), "timeout") + ensure_control_visible(lbl) diff --git a/scripts/GameBase.gd b/scripts/GameBase.gd new file mode 100644 index 0000000..ee26531 --- /dev/null +++ b/scripts/GameBase.gd @@ -0,0 +1,77 @@ +extends Spatial + +var client +var client_id +var player_name : String +var player_team : String +var player_char = null + +var players_info = {} #dictionary of id : name, team, ping, etc. + +var is_chatting = false + +var winddir = Vector3(1,0,0) + +remote func set_up_server_info(info): + $HUD/ServerJoinMenu/MOTD.text = info["MOTD"] + $HUD/ServerJoinMenu/ServerName.text = info["server_name"] + $DEFAULTCAM.transform = info["cam_pos"] + + rpc_id(1, "_call_on_server", "_client_connection_confirmed", {"id" : client_id, "username" : player_name}) + +remote func load_map(geo_info): + for geo in geo_info: + var prop = load(geo["filename"]).instance() + $WORLDGEO.add_child(prop) + prop.transform = geo["transform"] + +remote func load_entities(entity_info): #machines, players, and projectiles + for entity in entity_info: + var parent_section = get_node(entity["type"]) + var ent = load(entity["filename"]).instance() + ent.name = entity["name"] + ent.set_network_master(entity["net_master"]) + parent_section.add_child(ent, true) + ent.transform = entity["transform"] + ent.mp_init(entity["init_info"]) + +remote func update_players_info(info): + $HUD/ServerJoinMenu/Team1Players.text = "" + $HUD/ServerJoinMenu/Team2Players.text = "" + $HUD/ServerJoinMenu/Spectators.text = "" + players_info = info + for player in players_info.keys(): + var p_team = players_info[player][1] + var p_name = players_info[player][0] + if p_team == "RED": + $HUD/ServerJoinMenu/Team1Players.text += p_name + ", " + elif p_team == "BLUE": + $HUD/ServerJoinMenu/Team2Players.text += p_name + ", " + elif p_team == "SPEC": + $HUD/ServerJoinMenu/Spectators.text += p_name + ", " + +remote func game_update_chars(): + $HUD.update_characters() + +remote func game_chat_msg(msg): + $HUD.ui_chat_msg(msg) + +func select_character(dest): + print(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: + rpc_id(1, "_call_on_server", "_client_request_change_character", {"id" : client_id, "current_char_name" : player_char.name, "char_name" : dest}) + +func client_disconnect(): + if player_char != null: + player_char.deselect_character() + client.close_connection() + get_tree().quit() + +func join_team(team): + if player_char != null: + player_char.deselect_character() + $DEFAULTCAM.current = true + player_team = team + rpc_id(1, "_call_on_server", "_client_change_teams", {"id" : client_id, "team" : team}) diff --git a/scripts/Server.gd b/scripts/Server.gd new file mode 100644 index 0000000..bd24911 --- /dev/null +++ b/scripts/Server.gd @@ -0,0 +1,110 @@ +extends Node + +var world +var motd : String +var server_name : String +var player_limit : int +var connected_player_count : int = 0 +var connected_players = {} + +var server_enet : NetworkedMultiplayerENet +var output +var output_func : String + +func print_line(line): + output.call(output_func, line) + +func _ready(): + get_tree().connect("network_peer_connected", self, "_client_connect") + get_tree().connect("network_peer_disconnected", self, "_client_disconnect") + +func start_server(_server_name: String, _motd: String, max_players: int, map_path: String, ip: String, port: int, root, output_obj, output_f): + output = output_obj + output_func = output_f + server_name = _server_name + motd = _motd + player_limit = max_players + + world = load(map_path) + if world: + world = world.instance() + else: + print_line("Error loading map.") + return + + world.add_child(self) + root.add_child(world) + world.client_id = 1 + + server_enet = NetworkedMultiplayerENet.new() + server_enet.create_server(port, max_players) + get_tree().set_network_peer(server_enet) + + print_line("Server started successfully.") + +func stop_server(): + print_line("Shutting down server...") + server_enet.close_connection() + print_line("Shut down successfully.") + world.queue_free() + +func _client_disconnect(id): + print_line("Client (ID: "+str(id)+") has disconnected.") + for character in world.get_node("PLAYERS").get_children(): + if character.get_network_master() == id: + character.rpc("set_owner", 1) + connected_players.erase(id) + connected_player_count -= 1 + world.rpc("update_players_info", connected_players) + +func _client_connect(id): + print_line("Client (ID: "+str(id)+") connecting...") + connected_player_count += 1 + connected_players[id] = ["", "SPEC"] #Placeholder for name + + var server_info = {"player_count" : connected_player_count, "server_name" : server_name, "MOTD" : motd, "cam_pos" : world.get_node("DEFAULTCAM").transform} + world.rpc_id(id, "set_up_server_info", server_info) + + var geo_info = [] + for world_geo in world.get_node("WORLDGEO").get_children(): + geo_info.append( { "filename" : world_geo.filename, "transform" : world_geo.transform }) + world.rpc_id(id, "load_map", geo_info) + + var ent_info = [] + for section in ["PLAYERS","MACHINES","BALLISTICS"]: + for item in world.get_node(section).get_children(): + ent_info.append({"type" : section, "net_master" : item.get_network_master(), "name" : item.name, "filename" : item.filename, "transform" : item.transform, "init_info" : item.get_init_info() }) + world.rpc_id(id, "load_entities", ent_info) + +func _client_connection_confirmed(arguments): + print_line("Client (ID: "+str(arguments["id"])+") connected as " +arguments["username"] +".") + connected_players[arguments["id"]] = [arguments["username"], "SPEC"] + world.rpc("update_players_info", connected_players) + +func _client_change_teams(arguments): + print_line(connected_players[arguments["id"]][0] + " ("+ str(arguments["id"]) +") changed to team " + arguments["team"]) + connected_players[arguments["id"]][1] = arguments["team"] + world.rpc("update_players_info", connected_players) + +func _client_request_change_character(arguments): + var dest = world.get_node("PLAYERS/"+arguments["char_name"]) + if dest.get_network_master() == 1: + print_line(connected_players[arguments["id"]][0] + " selected character " + arguments["char_name"]) + dest.rpc("set_owner", arguments["id"]) + if arguments["current_char_name"] != "NULL": + var old = world.get_node("PLAYERS/"+arguments["current_char_name"]) + old.rpc("set_owner", 1) + +func _character_death(arguments): + print(arguments) + var victim_player = connected_players[arguments["victim_mp_id"]][0] if arguments["victim_mp_id"] != 1 else "" + print_line(arguments["victim"] + " ("+victim_player+") killed by " + arguments["killer"] + " " + arguments["extra"] + ".") + world.rpc("game_chat_msg", arguments["victim"] + " ("+victim_player+") killed by " + arguments["killer"] + " " + arguments["extra"] + ".") + world.get_node("PLAYERS/"+arguments["victim"]).rpc("remove_dead") + world.rpc("game_update_chars") + +func _send_chat(arguments): + if !("name" in arguments): + arguments["name"]=connected_players[arguments["id"]][0] + print_line(arguments["name"]+ ": " + arguments["msg"]) + world.rpc("game_chat_msg", arguments["name"]+ ": " + arguments["msg"]) diff --git a/scripts/ServerUI.gd b/scripts/ServerUI.gd new file mode 100644 index 0000000..1acf9eb --- /dev/null +++ b/scripts/ServerUI.gd @@ -0,0 +1,38 @@ +extends Node2D + + +var server +onready var console = get_node("Console") + +var is_running :bool = false + +func _ready(): + $CmdPrompt.ui_ref = self + +func hide_init_fields(): + for node in get_tree().get_nodes_in_group("init_fields"): + node.visible = false + $StopButton.visible = true + +func show_init_fields(): + for node in get_tree().get_nodes_in_group("init_fields"): + node.visible = true + $StopButton.visible = false + +func start_server(): + console.add_line("Server starting...") + is_running = true + + server = preload("res://scenes/Server.tscn").instance() + $CmdPrompt.server_ref = server + server.start_server($ServerName.text, $MOTD.text, $PlayerCount.value, $MapPath.text, $IP.text, $Port.value, get_tree().get_root(), console, "add_line") + + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + hide_init_fields() + +func stop_server(): + server.stop_server() + is_running = false + $CmdPrompt.server_ref = null + + show_init_fields() diff --git a/scripts/World.gd b/scripts/World.gd new file mode 100644 index 0000000..dd5b177 --- /dev/null +++ b/scripts/World.gd @@ -0,0 +1,51 @@ +extends Spatial + + +var m = SpatialMaterial.new() +var winddir = Vector3(1,0,0) +onready var pathfinder = get_node("PLAYERS/Player2") +var path = [] +var map_rid +var client_id +var player_char +var players_info = {} + +# Called when the node enters the scene tree for the first time. +func _ready(): + map_rid = NavigationServer.get_maps() + print(map_rid) + for rid in map_rid: + NavigationServer.map_set_edge_connection_margin(rid,1) + m.flags_unshaded = true + m.flags_use_point_size = true + m.albedo_color = Color.white + +remotesync func update_players_info(info): + players_info = info + +remote func _call_on_server(function, arguments): + print('Remote server call: ' + function) + $Server.call(function, arguments) + +func find_path(to): + pathfinder.nav.set_target_location(to) + var t_path = pathfinder.nav.get_next_location() + pathfinder.should_move = true + t_path = pathfinder.nav.get_nav_path() + print(to) + print(t_path) + draw_path(t_path) + pass + +func draw_path(path_array): + var im = get_node("Draw") + im.set_material_override(m) + im.clear() + im.begin(Mesh.PRIMITIVE_POINTS, null) + im.add_vertex(path_array[0]) + im.add_vertex(path_array[path_array.size() - 1]) + im.end() + im.begin(Mesh.PRIMITIVE_LINE_STRIP, null) + for x in path_array: + im.add_vertex(x) + im.end() diff --git a/scripts/ballistics/Cannonball.gd b/scripts/ballistics/Cannonball.gd new file mode 100644 index 0000000..e59ca6c --- /dev/null +++ b/scripts/ballistics/Cannonball.gd @@ -0,0 +1,24 @@ +extends RigidBody + +export var drag_constant = 0.3 +var damage_exceptions = [] +var oldvel + +var shooter = "WORLD" + +func _physics_process(_delta): + oldvel = linear_velocity + add_force(-1*linear_velocity*drag_constant, Vector3.ZERO) + +func get_init_info(): + return {"linear_velocity" : linear_velocity, "angular_velocity" : angular_velocity, "oldvel" : oldvel, "shooter" : shooter} + +func mp_init(init_info): + for variable in init_info.keys(): + set(variable, init_info[variable]) + + +func _on_collision(body): + if linear_velocity.length() > 20 and !damage_exceptions.has(body) and body.has_method("damage"): + body.damage(oldvel.length(), "blunt") + damage_exceptions.append(body) diff --git a/scripts/boats/Gunboat.gd b/scripts/boats/Gunboat.gd new file mode 100644 index 0000000..1e8dd49 --- /dev/null +++ b/scripts/boats/Gunboat.gd @@ -0,0 +1,121 @@ +extends RigidBody + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" +var in_use : bool = false +var user = null +var world = null + +export var team = 0 + +const accel = 50000 +const turn_accel = 50000 + +export(float, 0.0, 1.0) var sail_out = 0.0 +export var sail_speed : float = 0.5 +var sail_turn = 0 +export var sail_turn_speed = 30 +const SAIL_MAX = 90 + +var rudder_turn : float = 0.0 +export var rudder_speed = 25 +export var rudder_constant = 1800 +const RUDDER_MAX = 60 + +const health_max = 1000 +var health = health_max +const max_depth = 2 + +#controls +var throttle: float = 0.0 +var rudder: float = 0.0 +var mainsheet: float = 0.0 + +func get_init_info(): + return {"sail_out" : sail_out, "rudder_turn" : rudder_turn, "sail_turn" : sail_turn, "health" : health, "in_use" : in_use} + +func mp_init(init_info): + for variable in init_info.keys(): + set(variable, init_info[variable]) + +# Called when the node enters the scene tree for the first time. +func _ready(): + world = get_tree().get_root().find_node("GAMEWORLD", true, false) + mass = 13500 + weight = mass * 9.8 + +func is_in_use(): + return in_use + +func take_control(controller): + user = controller + in_use = true + return self + +func relinquish_control(): + in_use = false + rudder = 0.0 + throttle = 0.0 + mainsheet = 0.0 + user = null + +func auto_sail(delta): + var in_range = global_transform.basis.x.dot(world.winddir) >= 0 + if in_range: + if Vector2(world.winddir.x, world.winddir.z).angle_to(Vector2($Mast.global_transform.basis.x.x,$Mast.global_transform.basis.x.z)) < 0: + sail_turn -= sail_turn_speed*delta + else: + sail_turn += sail_turn_speed*delta + else: + if abs(Vector2(world.winddir.x, world.winddir.z).angle_to(Vector2(global_transform.basis.z.x,global_transform.basis.z.z))) < PI/2: + sail_turn -= sail_turn_speed*delta + else: + sail_turn += sail_turn_speed*delta + +func attack1(): + pass + +func attack2(): + pass + +func direction_input(fwd,bwd,left,right,_left,_right): + throttle = fwd - bwd + rudder = left - right + mainsheet = _left - _right + +func damage(amount, type, shooter, extra = ""): + health -= amount + print(health) + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _physics_process(delta): + $Mast/Sail.scale.y = 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) + add_torque(Vector3(0,-rudder_turn*rudder_constant*(0.5+linear_velocity.dot(global_transform.basis.x)),0)) + add_torque(Vector3(-1000000*angular_velocity.x,0,0)) + add_torque(Vector3(0,0,-1000000*angular_velocity.z)) + rudder_turn += rudder_speed*delta*(-0.25 if rudder_turn > 0 else 0.25) + for point in $FloatPoints.get_children(): + for area in point.get_overlapping_areas(): + if area.name == "WaterArea": + var depth = area.global_transform.origin.y-point.global_transform.origin.y + var floatiness = 0.275 if health <= 0 else 1 + if floatiness == 0.275: + depth = 0.05 + add_force(Vector3.UP*weight*depth*floatiness, point.global_transform.origin-global_transform.origin) + if in_use: + rudder_turn += rudder_speed*delta*(rudder) + sail_out += sail_speed*delta*(throttle) + sail_turn += sail_turn_speed*delta*(mainsheet) + auto_sail(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) + + #add_force(transform.basis.x*accel*Input.get_action_strength("move_forward"), Vector3.ZERO) diff --git a/scripts/characters/player_controller_new.gd b/scripts/characters/player_controller_new.gd new file mode 100644 index 0000000..37f8562 --- /dev/null +++ b/scripts/characters/player_controller_new.gd @@ -0,0 +1,236 @@ +extends RigidBody + +# Game +export var team = "RED" +export (int) var health = 100 +var weapon = null +var world + +# Camera +export(float) var mouse_sensitivity = 12.0 +export(float) var FOV = 90.0 +var mouse_axis := Vector2() +onready var head: Spatial = $Head +onready var cam: Camera = $Head/Camera + +# Move +var velocity := Vector3() +var direction := Vector3() +var move_axis := Vector2() +var floorspeed := Vector3() +onready var nav = $NavigationAgent + +# Walk +const FLOOR_MAX_ANGLE: float = deg2rad(46.0) +export(float) var jump_height = 400 + +# Control +var controlling_machine = false #whether character is riding/controlling something +var machine = null +export var is_player = false #whether character is currently controlled by a player +var should_move = false + +#physics +var player_state : PhysicsDirectBodyState +var is_on_floor:bool +export(float) var acceleration = 80.0 +export(int) var walk_speed = 6 +export(float) var c_friction = 4.0 +export(float) var _airspeed_cap = 1.0 +export(float) var air_control = 1.0 + +# Called when the node enters the scene tree +func _ready() -> void: + weapon = preload("res://scenes/weapons/w_Rockets.tscn").instance() + add_child(weapon) + world = get_tree().get_root().get_node("GAMEWORLD") + if is_player: + cam.current = true + $Head/Camera/UseRay.add_exception(self) + $Head/Camera/MeleeRay.add_exception(self) + $Head/Camera/LongRay.add_exception(self) + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + cam.fov = FOV + +func get_init_info(): + return {"linear_velocity" : linear_velocity, "angular_velocity" : angular_velocity, "controlling_machine" : controlling_machine, "team" : team, "health" : health, "nametag" : $Nametag.text} + +func mp_init(init_info): + for variable in init_info.keys(): + set(variable, init_info[variable]) + $Nametag.text = init_info["nametag"] + +remote func set_phys_transform(trfrm, lvel): + transform = trfrm + linear_velocity = lvel + +# 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 Input.is_action_just_pressed("use"): + initiate_use() + + if controlling_machine: + if Input.is_action_just_pressed("fire"): + machine.attack1() + if Input.is_action_just_pressed("fire2"): + machine.attack2() + machine.direction_input(Input.get_action_strength("move_forward"),Input.get_action_strength("move_backward"), Input.get_action_strength("move_right"),Input.get_action_strength("move_left"), Input.get_action_strength("alt_right"),Input.get_action_strength("alt_left")) + else: + if Input.is_action_just_pressed("fire"): + weapon.attack1() + move_axis.x = Input.get_action_strength("move_forward") - Input.get_action_strength("move_backward") + move_axis.y = Input.get_action_strength("move_right") - Input.get_action_strength("move_left") + + +func initiate_use(): + if controlling_machine: + machine.relinquish_control() + machine = null + controlling_machine = false + if is_player: + cam.current = true + return + if $Head/Camera/UseRay.is_colliding(): + var type = $Head/Camera/UseRay.get_collider().name + match type: + "SteerArea": + controlling_machine = true + machine = $Head/Camera/UseRay.get_collider().get_parent().take_control(self) + var gt = global_transform.origin + velocity = Vector3.ZERO + global_transform.origin = gt + _: + pass + +remotesync func set_owner(owner_id): + $Nametag.text = "" + set_network_master(owner_id) + if owner_id != 1: + $Nametag.text = world.players_info[owner_id][0] + if get_tree().get_network_unique_id() != 1: + if owner_id == world.client_id: + world.player_char = self + is_player = true + cam.current = true + else: + cam.current = false + is_player = false + world.get_node("HUD").update_characters() + +func deselect_character(): + if is_network_master(): + world.player_char = null + world.get_node("DEFAULTCAM").current = true + rpc("set_owner", 1) + +func regain_control(_gt): + controlling_machine = false + machine = null + +# Called every physics tick. 'delta' is constant +func _physics_process(delta: float) -> void: + walk(delta) + if is_network_master(): + rpc("set_phys_transform", transform, linear_velocity) + +# called by signal when character is collided with +func on_floor_test() -> void: + if $Feet.is_colliding(): + is_on_floor = true + if $Feet.get_collider().has_method("get_linear_velocity"): + floorspeed = $Feet.get_collider().get_linear_velocity() + else: + floorspeed = Vector3.ZERO + return + if player_state: + for i in range(player_state.get_contact_count()): + var contact_angle_from_up : float = Vector3.UP.angle_to(player_state.get_contact_local_normal(i)) + if contact_angle_from_up < FLOOR_MAX_ANGLE: + is_on_floor = true + +#modify simulated physics results +func _integrate_forces(state) -> void: + player_state = state + velocity = state.get_linear_velocity() + if should_move: + nav.set_velocity(velocity) + if nav.is_target_reached(): + should_move = false + +# on input event +func _input(event: InputEvent) -> void: + if is_player: + if event is InputEventMouseMotion: + mouse_axis = event.relative + camera_rotation() + +func walk(_delta:float) -> void: + on_floor_test() + # Input + direction = Vector3() + var aim: Basis = head.get_global_transform().basis + direction += -move_axis.x * aim.z + move_axis.y * aim.x + if !is_player and should_move: + direction = nav.get_next_location() - global_transform.origin + if nav.get_next_location().y - global_transform.origin.y > 0.05 and is_on_floor: + apply_central_impulse(Vector3.UP*jump_height) + direction.y = 0 + direction = direction.normalized() + + # Jump + if is_on_floor and is_player: + if Input.is_action_just_pressed("move_jump"): + apply_central_impulse(Vector3.UP*jump_height) + + #max walk speed + var _speed = walk_speed + var _temp_accel: float = acceleration + var _cspeed = sqrt(pow(velocity.x-floorspeed.x,2)+pow(velocity.z-floorspeed.z,2)) + + if not is_on_floor: + _temp_accel *= air_control + + var projVel = Vector2(velocity.x-floorspeed.x,velocity.z-floorspeed.z).dot(Vector2(direction.x,direction.z)) + + if is_on_floor: + if _speed - _cspeed > 0: + add_central_force (mass*Vector3(direction.x*_temp_accel, 0, direction.z*_temp_accel))#velocity.x += direction.x*_temp_accel + else: + add_central_force(mass*Vector3(direction.x*(_speed-projVel), 0, direction.z*(_speed-projVel))) + elif _airspeed_cap - projVel > 0: + add_central_force (mass*Vector3(direction.x*_temp_accel, 0, direction.z*_temp_accel)) + + is_on_floor = false #reset whether is on floor in between frames + +remotesync func damage(dmg_amt, type, shooter, extra = ""): + health -= dmg_amt + if health <= 0 and is_network_master(): + if get_network_master() == 1: + world._call_on_server("_character_death", {"killer" : shooter, "victim_mp_id" : get_network_master(), "victim" : name, "extra" : extra}) + else: + world.rpc_id(1, "_call_on_server", "_character_death", {"killer" : shooter, "victim_mp_id" : get_network_master(), "victim" : name, "extra" : extra}) + + +remotesync func remove_dead(): + deselect_character() + queue_free() + +func camera_rotation() -> void: + if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED: + return + if mouse_axis.length() > 0: + var horizontal: float = -mouse_axis.x * (mouse_sensitivity / 100) + var vertical: float = -mouse_axis.y * (mouse_sensitivity / 100) + + mouse_axis = Vector2() + + head.rotate_y(deg2rad(horizontal)) + cam.rotate_x(deg2rad(vertical)) + + # Clamp mouse rotation + var temp_rot: Vector3 = cam.rotation_degrees + temp_rot.x = clamp(temp_rot.x, -90, 90) + cam.rotation_degrees = temp_rot + diff --git a/scripts/machines/Cannon.gd b/scripts/machines/Cannon.gd new file mode 100644 index 0000000..d7c9a18 --- /dev/null +++ b/scripts/machines/Cannon.gd @@ -0,0 +1,92 @@ +extends RigidBody +#Basis +var in_use : bool = false +var user = null +var world = null + +var cooldown = 0 +export var fire_rate = 1 #shot/s +export var ball_speed = 500 #m/s + +var pitch :float = 0.0 +var turn :float = 0.0 + +export var turn_speed = 7.5 #deg/s +export var pitch_speed = 10 + +export var max_pitch = 50 +export var min_pitch = -10 +export var min_yaw = -15 +export var max_yaw = 15 + +onready var muzzle = get_node("YawJoint/PitchJoint/Muzzle") + +func get_init_info(): + return {"pitch_rot" : $YawJoint/PitchJoint.rotation_degrees.z, "turn_rot" : $YawJoint.rotation_degrees.y, "in_use" : in_use} + +func mp_init(init_info): + $YawJoint/PitchJoint.rotation_degrees.z = init_info["pitch_rot"] + $YawJoint.rotation_degrees.y = init_info["turn_rot"] + in_use = init_info["in_use"] + +# Called when the node enters the scene tree for the first time. +func _ready(): + if get_parent().name != "MACHINES": + add_collision_exception_with(get_parent()) + mode = RigidBody.MODE_STATIC + world = get_tree().get_root().find_node("BALLISTICS", true, false) + + +func is_in_use(): + return in_use + +func take_control(controller): + $YawJoint/PitchJoint/Camera.current = true + user = controller + in_use = true + return self + +func relinquish_control(): + in_use = false + user = null + +func _physics_process(delta): + if cooldown > 0: + cooldown -= delta + if in_use: + #aim + $YawJoint/PitchJoint.rotation_degrees.z += pitch*pitch_speed*delta + $YawJoint.rotation_degrees.y += turn*turn_speed*delta + if $YawJoint.rotation_degrees.y > max_yaw: + $YawJoint.rotation_degrees.y = max_yaw + elif $YawJoint.rotation_degrees.y < min_yaw: + $YawJoint.rotation_degrees.y = min_yaw + if $YawJoint/PitchJoint.rotation_degrees.z > max_pitch: + $YawJoint/PitchJoint.rotation_degrees.z = max_pitch + elif $YawJoint/PitchJoint.rotation_degrees.z < min_pitch: + $YawJoint/PitchJoint.rotation_degrees.z = min_pitch + +func direction_input(fwd,bwd,left,right,_left,_right): + pitch = fwd - bwd + turn = left - right + +func attack1(): + if cooldown > 0: + return + $YawJoint/PitchJoint/Muzzle/explosion_sound.play() + var expl = preload("res://particles/p_Explosion.tscn").instance() + var cball = preload("res://scenes/ballistics/Cannonball.tscn").instance() + world.add_child(cball) + world.add_child(expl) + expl.init(muzzle.global_transform.origin, Vector3.ZERO) + add_collision_exception_with(cball) + cball.global_transform.origin = muzzle.global_transform.origin + cball.linear_velocity = muzzle.global_transform.basis.x*ball_speed + cooldown = fire_rate + if mode == RigidBody.MODE_STATIC: + 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: + apply_impulse($YawJoint/PitchJoint.global_transform.origin - global_transform.origin, -1*cball.mass*ball_speed*muzzle.global_transform.basis.x) + +func attack2(): + pass diff --git a/scripts/world_tools.gd b/scripts/world_tools.gd new file mode 100644 index 0000000..bb3b336 --- /dev/null +++ b/scripts/world_tools.gd @@ -0,0 +1,65 @@ +tool +extends Node + +export(String) var terrain1path = "" setget t1update +export(String) var terrain2path = "" setget t2update +export(bool) var seam = 0 setget makeseam +export(Vector3) var winddir = Vector3.ZERO + +var terr1 +var terr2 + +func t1update(p): + terrain1path = p + terr1 = get_node(terrain1path) +func t2update(p): + terrain2path = p + terr2 = get_node(terrain2path) + +#makes adjacent terrain (terr2) snap to given terrain (terr1) on their border +func makeseam(_p): +# var t1pos: Vector3 = terr1.transform.origin +# var t2pos: Vector3 = terr2.transform.origin +# var t1data = terr1.get_data() +# var t2data = terr2.get_data() +# var heightmap1: Image = t1data.get_image(t1data.CHANNEL_HEIGHT) +# var heightmap2: Image = t2data.get_image(t2data.CHANNEL_HEIGHT) +# +# if heightmap1.get_height() != heightmap2.get_height(): +# return +# var sidelength = heightmap1.get_height() +# heightmap2.lock() +# heightmap1.lock() + + #if t1pos.distance_squared_to(t2pos) != heightmap1.get_height()*heightmap1.get_height(): + # return + pass +# var side : int = 0 +# var is_x : bool +# if t1pos.x == t2pos.x: +# is_x = false +# if t1pos.z > t2pos.z: +# side = sidelength-1 +# elif t2pos.z == t2pos.z: +# is_x = true +# if t1pos.x > t2pos.x: +# side = sidelength-1 +# else: +# return +# +# var oside = sidelength-1-side +# +# for i in sidelength: +# if is_x: +# heightmap2.set_pixel(side, i, heightmap1.get_pixel(oside, i)) +# else: +# heightmap2.set_pixel(i, side, heightmap1.get_pixel(i, oside)) +# +# heightmap2.unlock() +# heightmap1.unlock() +# +# var modified_region = Rect2(Vector2(), heightmap2.get_size()) +# t2data.notify_region_change(modified_region, t2data.CHANNEL_HEIGHT) +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass |
