source: Studio/Player/player.gd@ 831a978

godot4-dev
Last change on this file since 831a978 was 831a978, checked in by Jonathan Neufeld <support@…>, 3 years ago

Initial commit of Godot4 project Working world and movable player.

  • Property mode set to 100644
File size: 10.8 KB
Line 
1extends CharacterBody3D
2
3# Load Config File
4var player_data = {}
5var player_config = ConfigFile.new()
6var player_filepath = "res://Player/player.ini"
7
8#Camera moving with Mouse
9var mouse_axis := Vector2()
10var camera_change = false
11var mouse_sensitivity = 8.0
12@export var FOV = 80.0
13@export var neck_path = NodePath("Neck")
14@export var head_path = NodePath("Neck/Head")
15@export var camera_path = NodePath("Neck/Head/Camera")
16@onready var neck: SpringArm3D = get_node(neck_path)
17@onready var head: Node3D = get_node(head_path)
18@onready var camera: Camera3D = get_node(camera_path)
19
20# Walk and Sprint
21const FLOOR_MAX_ANGLE: float = deg2rad(46.0)
22@export var walk_speed = 5
23@export var sprint_speed = 9
24@export var acceleration = 8
25@export var deacceleration = 10
26@export var jump_height = 4.5
27var speed = 5.0
28var sprint_enabled := true
29var hold_walk := false
30var stamina_delay = 0
31
32# Player defaults if not found in INI file
33var player = "player"
34var exhausted_delay = 60
35var sprint_energy_consumption = 0.5
36var stamina_regen_speed = 0.5
37var mana_needed_to_heal = 30
38var mana_heal_ammount = 10
39var mana_regen_speed = 0.1
40var fall_threshold_damage = 9 # distance down a player has to fall before taking damage
41
42# Move
43var falling := Vector3()
44
45# Grounded
46enum GROUNDED_STATE {
47 GROUNDED,
48 MIDAIR,
49 TOUCHDOWN
50}
51var player_state = GROUNDED_STATE.GROUNDED
52
53# Damage
54var max_fall := Vector3() # Total disatance fallen down
55
56
57# Get the gravity from the project settings to be synced with RigidDynamicBody nodes.
58var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
59
60func _ready() -> void:
61 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
62 if player_config.load(player_filepath) == OK:
63 mana_needed_to_heal = player_config.get_value(player, "mana_needed_to_heal")
64 mana_heal_ammount = player_config.get_value(player, "mana_heal_ammount")
65 mana_regen_speed = player_config.get_value(player, "mana_regen_speed")
66 fall_threshold_damage = player_config.get_value(player, "fall_threshold_damage")
67 gravity = player_config.get_value(player, "gravity")
68 walk_speed = player_config.get_value(player, "walk_speed")
69 exhausted_delay = player_config.get_value(player, "exhausted_delay")
70 stamina_regen_speed = player_config.get_value(player, "stamina_regen_speed")
71 sprint_speed = player_config.get_value(player, "sprint_speed")
72 sprint_energy_consumption = player_config.get_value(player, "sprint_energy_consumption")
73 jump_height = player_config.get_value(player, "jump_height")
74 Universal.player = player_config.get_value(player, "playername")
75 Universal.health = player_config.get_value(player, "health")
76 Universal.stamina = player_config.get_value(player, "stamina")
77 Universal.mana = player_config.get_value(player, "mana")
78 Universal.lifeforce = player_config.get_value(player, "lifeforce")
79 Universal.xp = player_config.get_value(player, "xp")
80 Universal.dead = player_config.get_value(player, "dead")
81 else:
82 print("Player Config File Not Found - Using defaults")
83 stat_change() # Used to update display for stats
84
85func _physics_process(delta):
86
87 #Checks to see if player is dead
88 if Universal.dead == true:
89 dead()
90 Universal.dead = null
91
92 # Reset player stats if respauned
93 if Universal.respaun == true:
94 Universal.respaun = false
95 stamina_delay = 0
96 visible = true
97 get_node("PlayerInterface").visible = true
98 _ready()
99 velocity.x = 0
100 velocity.z = 0
101 hold_walk = false
102 position.x = 0
103 position.y = 0.7
104 position.z = 0
105 stat_change() # Used to update display for stats
106 player_state = GROUNDED_STATE.GROUNDED
107 max_fall.y = 0
108
109
110 # Pause menu
111 if Input.is_action_just_pressed("ui_cancel") && Universal.dead == false:
112 velocity.x = 0
113 velocity.z = 0
114 hold_walk = false
115 if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
116 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
117 $Pause.visible = !$Pause.visible
118 if Universal.ui_lock == false:
119 Universal.ui_lock = true
120 else:
121 Universal.ui_lock = false
122 else:
123 Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
124 $Pause.visible = !$Pause.visible
125 Universal.ui_lock = false
126
127 # Add the gravity.
128 if not is_on_floor():
129 velocity.y -= gravity * delta
130
131 # Get the input direction and handle the movement/deceleration.
132 # As good practice, you should replace UI actions with custom gameplay actions.
133 var input_dir = Input.get_vector("move_left", "move_right", "move_forward", "move_backward")
134
135 # Overide to force continus walking
136 if Input.is_action_just_pressed("hold_move_forward"):
137 if hold_walk == true:
138 hold_walk = false
139 else:
140 hold_walk = true
141 if Input.is_action_just_pressed("move_forward") || Input.is_action_just_pressed("move_backward"):
142 hold_walk = false
143 if hold_walk == true:
144 input_dir.y = -1
145
146 if Universal.ui_lock == false:
147 # Handle Jump.
148 if Input.is_action_just_pressed("move_jump") and is_on_floor():
149 velocity.y = jump_height
150 #Move Player
151 var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
152 if direction:
153 velocity.x = direction.x * speed
154 velocity.z = direction.z * speed
155 else:
156 velocity.x = move_toward(velocity.x, 0, speed)
157 velocity.z = move_toward(velocity.z, 0, speed)
158
159 sprint(delta)
160 move_and_slide()
161
162 if Input.is_action_just_pressed("camera_perspective"):
163 var player_camera = $Neck/Head/Camera
164 if camera_change == true:
165 player_camera.position.z = 0
166 player_camera.position.x = 0
167 player_camera.position.y = 0
168 camera_change = false
169 else:
170 player_camera.position.z = 1.5
171 player_camera.position.x = 0.25
172 player_camera.position.y = 0.5
173 camera_change = true
174
175# Fall damage calculation
176 match player_state:
177 GROUNDED_STATE.GROUNDED:
178 falling = Vector3.ZERO
179 if not is_on_floor():
180 player_state = GROUNDED_STATE.MIDAIR
181 GROUNDED_STATE.MIDAIR:
182 falling += Vector3.DOWN * gravity * delta
183 if velocity.y <= -fall_threshold_damage:
184 max_fall = velocity
185 if is_on_floor():
186 player_state = GROUNDED_STATE.TOUCHDOWN
187 GROUNDED_STATE.TOUCHDOWN:
188 if falling.length() >= fall_threshold_damage and max_fall.y <= -fall_threshold_damage:
189 Universal.health -= round(-(max_fall.y + fall_threshold_damage))
190 Universal.stamina -= round(-(max_fall.y + fall_threshold_damage))
191 if round(-(max_fall.y + fall_threshold_damage)) > 5:
192 Universal.health -= round(-(max_fall.y + fall_threshold_damage)*9)
193 else:
194 if round(-(max_fall.y + fall_threshold_damage)) > 10:
195 Universal.health -= round(-(max_fall.y + fall_threshold_damage)*15)
196 if Universal.health <= 0:
197 dead()
198 get_node("PlayerInterface/VBoxContainer/BottomRight2/Health").value = Universal.health
199 max_fall = Vector3.ZERO
200 player_state = GROUNDED_STATE.GROUNDED
201
202func dead():
203 velocity.x = 0
204 velocity.z = 0
205 hold_walk = false
206 Universal.ui_lock = true
207 Universal.dead = true
208 Universal.health = 0
209 Universal.lifeforce = 0
210 Universal.mana = 0
211 Universal.stamina = 0
212 sprint_enabled = false
213 stamina_delay = exhausted_delay
214 stamina_regen_speed = 0
215 visible = false
216 get_node("PlayerInterface").visible = false
217 stat_change()
218 Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
219 $Dead.visible = !$Dead.visible
220
221# Called when there is an input event
222func _input(event: InputEvent) -> void:
223 if event is InputEventMouseMotion:
224 mouse_axis = event.relative
225 camera_rotation()
226
227# Heal button
228 if Input.is_action_just_pressed("player_heal") && Universal.mana >= mana_needed_to_heal:
229 if Universal.health != 1000:
230 Universal.mana -= mana_needed_to_heal
231 if 1000 < Universal.health + mana_heal_ammount:
232 Universal.health = 1000
233 elif Universal.health == 0:
234 Universal.health = mana_heal_ammount
235 else:
236 Universal.health += mana_heal_ammount
237 stat_change() # Used to update display for stats
238
239func camera_rotation() -> void:
240 if Input.get_mouse_mode() != Input.MOUSE_MODE_CAPTURED:
241 return
242 if mouse_axis.length() > 0:
243 var horizontal: float = -mouse_axis.x * (mouse_sensitivity / 100)
244 var vertical: float = -mouse_axis.y * (mouse_sensitivity / 100)
245 mouse_axis = Vector2()
246 rotate_y(deg2rad(horizontal))
247 camera.rotate_x(deg2rad(vertical))
248
249 # Clamp mouse rotation
250 var temp_rot = camera.rotation.x
251 if camera_change == false:
252 temp_rot = clamp(temp_rot, -1.5, 2)
253 else:
254 temp_rot = clamp(temp_rot, -0.5, 2)
255 camera.rotation.x = temp_rot
256
257func can_sprint() -> bool:
258 return (sprint_enabled and is_on_floor() and Input.is_action_pressed("move_sprint"))
259
260
261func sprint(delta: float) -> void:
262 if can_sprint():
263 if Universal.stamina >= 0 && stamina_delay <= 1:
264 speed = sprint_speed
265 camera.set_fov(lerp(camera.fov, FOV * 1.25, delta * 8))
266 Universal.stamina -= sprint_energy_consumption
267 if Universal.stamina <= 0:
268 stamina_delay = exhausted_delay
269 sprint_enabled = false
270 camera.fov = FOV
271 speed = walk_speed
272 return
273 stat_change() # Used to update display for stats
274 else:
275 speed = walk_speed
276 camera.set_fov(lerp(camera.fov, FOV, delta * 8))
277 if stamina_delay >= 0:
278 stamina_delay -= 0.1
279 sprint_enabled = true
280 elif Universal.stamina <= 1000:
281 if velocity.x == 0:
282 Universal.stamina += stamina_regen_speed * 2
283 else:
284 Universal.stamina += stamina_regen_speed
285 stat_change() # Used to update display for stats a
286 elif Universal.stamina >= 1000 && Universal.mana < 1000:
287 if velocity.x == 0:
288 Universal.mana += mana_regen_speed * 2
289 else:
290 Universal.mana += mana_regen_speed
291 stat_change() # Used to update display for stats a
292
293
294func stat_change():
295 # Change the stats & displaybox size and refreshes so everythine stays at the bottom of the screen
296 var sbox_size = 0
297 var hbox_size = 0
298 var mbox_size = 0
299 var lbox_size = 0
300 var default_size = -130
301
302 if Universal.stamina >= Universal.stamina_max:
303 sbox_size = 30
304 get_node("PlayerInterface/VBoxContainer/BottomRight1").visible = false
305 else:
306 sbox_size = 0
307 get_node("PlayerInterface/VBoxContainer/BottomRight1").visible = true
308 if Universal.health == Universal.health_max:
309 hbox_size = 30
310 get_node("PlayerInterface/VBoxContainer/BottomRight2").visible = false
311 else:
312 hbox_size = 0
313 get_node("PlayerInterface/VBoxContainer/BottomRight2").visible = true
314 if Universal.mana >= Universal.mana_max -1:
315 mbox_size = 30
316 get_node("PlayerInterface/VBoxContainer/BottomRight3").visible = false
317 else:
318 mbox_size = 3
319 get_node("PlayerInterface/VBoxContainer/BottomRight3").visible = true
320 if Universal.lifeforce == Universal.lifeforce_max:
321 lbox_size = 30
322 get_node("PlayerInterface/VBoxContainer/BottomRight4").visible = false
323 else:
324 lbox_size = 0
325 get_node("PlayerInterface/VBoxContainer/BottomRight4").visible = true
326
327 get_node("PlayerInterface/VBoxContainer").offset_top = default_size + sbox_size + hbox_size + mbox_size + lbox_size
328
329 get_node("PlayerInterface/VBoxContainer/BottomRight1/Energy").value = Universal.stamina
330 get_node("PlayerInterface/VBoxContainer/BottomRight4/Food").value = Universal.lifeforce
331 get_node("PlayerInterface/VBoxContainer/BottomRight3/Mana").value = Universal.mana
332 get_node("PlayerInterface/VBoxContainer/BottomRight2/Health").value = Universal.health
333
Note: See TracBrowser for help on using the repository browser.