diff --git a/2d/bullet_shower/bullets.gd b/2d/bullet_shower/bullets.gd index e6a4266a..e9096455 100644 --- a/2d/bullet_shower/bullets.gd +++ b/2d/bullet_shower/bullets.gd @@ -8,28 +8,28 @@ const BULLET_COUNT = 500 const SPEED_MIN = 20 const SPEED_MAX = 80 -const bullet_image = preload("res://bullet.png") +const bullet_image := preload("res://bullet.png") var bullets := [] -var shape +var shape := RID() class Bullet: - var position = Vector2() - var speed = 1.0 + var position := Vector2() + var speed := 1.0 # The body is stored as a RID, which is an "opaque" way to access resources. # With large amounts of objects (thousands or more), it can be significantly # faster to use RIDs compared to a high-level approach. - var body = RID() + var body := RID() -func _ready(): +func _ready() -> void: shape = PhysicsServer2D.circle_shape_create() # Set the collision shape's radius for each bullet in pixels. PhysicsServer2D.shape_set_data(shape, 8) for _i in BULLET_COUNT: - var bullet = Bullet.new() + var bullet := Bullet.new() # Give each bullet its own random speed. bullet.speed = randf_range(SPEED_MIN, SPEED_MAX) bullet.body = PhysicsServer2D.body_create() @@ -45,22 +45,22 @@ func _ready(): randf_range(0, get_viewport_rect().size.x) + get_viewport_rect().size.x, randf_range(0, get_viewport_rect().size.y) ) - var transform2d = Transform2D() + var transform2d := Transform2D() transform2d.origin = bullet.position PhysicsServer2D.body_set_state(bullet.body, PhysicsServer2D.BODY_STATE_TRANSFORM, transform2d) bullets.push_back(bullet) -func _process(_delta): +func _process(_delta: float) -> void: # Order the CanvasItem to update every frame. queue_redraw() -func _physics_process(delta): - var transform2d = Transform2D() - var offset = get_viewport_rect().size.x + 16 - for bullet in bullets: +func _physics_process(delta: float) -> void: + var transform2d := Transform2D() + var offset := get_viewport_rect().size.x + 16 + for bullet: Bullet in bullets: bullet.position.x -= bullet.speed * delta if bullet.position.x < -16: @@ -73,15 +73,15 @@ func _physics_process(delta): # Instead of drawing each bullet individually in a script attached to each bullet, # we are drawing *all* the bullets at once here. -func _draw(): - var offset = -bullet_image.get_size() * 0.5 - for bullet in bullets: +func _draw() -> void: + var offset := -bullet_image.get_size() * 0.5 + for bullet: Bullet in bullets: draw_texture(bullet_image, bullet.position + offset) # Perform cleanup operations (required to exit without error messages in the console). -func _exit_tree(): - for bullet in bullets: +func _exit_tree() -> void: + for bullet: Bullet in bullets: PhysicsServer2D.free_rid(bullet.body) PhysicsServer2D.free_rid(shape) diff --git a/2d/bullet_shower/player.gd b/2d/bullet_shower/player.gd index 32b14c7e..3f07285d 100644 --- a/2d/bullet_shower/player.gd +++ b/2d/bullet_shower/player.gd @@ -4,32 +4,32 @@ extends Node2D # efficient than using instancing and nodes, but requires more programming and # is less visual. Bullets are managed together in the `bullets.gd` script. -# The number of bullets currently touched by the player. -var touching = 0 +## The number of bullets currently touched by the player. +var touching := 0 -@onready var sprite = $AnimatedSprite2D +@onready var sprite: AnimatedSprite2D = $AnimatedSprite2D -func _ready(): +func _ready() -> void: # The player follows the mouse cursor automatically, so there's no point # in displaying the mouse cursor. Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) -func _input(event): +func _input(event: InputEvent) -> void: # Getting the movement of the mouse so the sprite can follow its position. if event is InputEventMouseMotion: position = event.position - Vector2(0, 16) -func _on_body_shape_entered(_body_id, _body, _body_shape, _local_shape): +func _on_body_shape_entered(_body_id: RID, _body: Node2D, _body_shape_index: int, _local_shape_index: int) -> void: # Player got touched by a bullet so sprite changes to sad face. touching += 1 if touching >= 1: sprite.frame = 1 -func _on_body_shape_exited(_body_id, _body, _body_shape, _local_shape): +func _on_body_shape_exited(_body_id: RID, _body: Node2D, _body_shape_index: int, _local_shape_index: int) -> void: touching -= 1 # When non of the bullets are touching the player, # sprite changes to happy face. diff --git a/2d/bullet_shower/project.godot b/2d/bullet_shower/project.godot index 4eb91110..30a0d895 100644 --- a/2d/bullet_shower/project.godot +++ b/2d/bullet_shower/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://shower.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/2d/dynamic_tilemap_layers/level/tile_map.gd b/2d/dynamic_tilemap_layers/level/tile_map.gd index 717a89cb..62d1b16d 100644 --- a/2d/dynamic_tilemap_layers/level/tile_map.gd +++ b/2d/dynamic_tilemap_layers/level/tile_map.gd @@ -1,13 +1,13 @@ extends TileMap - -var secret_layer: int # You can have multiple layers if you make this an array. -var player_in_secret: bool +# You can have multiple layers if you make this an array. +var secret_layer := 0 +var player_in_secret := false var layer_alpha := 1.0 - func _init() -> void: - for i in get_layers_count(): # Find the secret layer by name. + for i in get_layers_count(): + # Find the secret layer by name. if get_layer_name(i) == "Secret": secret_layer = i @@ -19,7 +19,8 @@ func _ready() -> void: func _process(delta: float) -> void: if player_in_secret: if layer_alpha > 0.3: - layer_alpha = move_toward(layer_alpha, 0.3, delta) # Animate the layer transparency. + # Animate the layer transparency. + layer_alpha = move_toward(layer_alpha, 0.3, delta) set_layer_modulate(secret_layer, Color(1, 1, 1, layer_alpha)) else: set_process(false) @@ -32,17 +33,17 @@ func _process(delta: float) -> void: func _use_tile_data_runtime_update(layer: int, _coords: Vector2i) -> bool: - if layer == secret_layer: - return true - return false + return layer == secret_layer func _tile_data_runtime_update(_layer: int, _coords: Vector2i, tile_data: TileData) -> void: - tile_data.set_collision_polygons_count(0, 0) # Remove collision for secret layer. + # Remove collision for secret layer. + tile_data.set_collision_polygons_count(0, 0) func _on_secret_detector_body_entered(body: Node2D) -> void: - if not body is CharacterBody2D: # Detect player only. + if not body is CharacterBody2D: + # Detect the player only. return player_in_secret = true diff --git a/2d/dynamic_tilemap_layers/player/player.gd b/2d/dynamic_tilemap_layers/player/player.gd index 6bdbb58b..3685f1e6 100644 --- a/2d/dynamic_tilemap_layers/player/player.gd +++ b/2d/dynamic_tilemap_layers/player/player.gd @@ -5,11 +5,11 @@ const WALK_MAX_SPEED = 200 const STOP_FORCE = 1300 const JUMP_SPEED = 200 -@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") +@onready var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity") -func _physics_process(delta): +func _physics_process(delta: float) -> void: # Horizontal movement code. First, get the player's input. - var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right")) + var walk := WALK_FORCE * (Input.get_axis(&"move_left", &"move_right")) # Slow down the player if they're not trying to move. if abs(walk) < WALK_FORCE * 0.2: # The velocity, slowed down a bit, and then reassigned. diff --git a/2d/dynamic_tilemap_layers/project.godot b/2d/dynamic_tilemap_layers/project.godot index bea3de2c..a138cdd8 100644 --- a/2d/dynamic_tilemap_layers/project.godot +++ b/2d/dynamic_tilemap_layers/project.godot @@ -14,10 +14,14 @@ config/name="Dynamic TileMap Layers" config/description="Example of how to make a kinematic character controller in 2D using CharacterBody2D. The character moves around, is affected by moving platforms, can jump through one-way collision platforms, etc." +config/tags=PackedStringArray("2d", "demo", "official", "tilemap") run/main_scene="res://world.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.png" -config/tags=PackedStringArray("2d", "demo", "official", "tilemap") + +[debug] + +gdscript/warnings/untyped_declaration=1 [display] diff --git a/2d/finite_state_machine/debug/states_stack_displayer.gd b/2d/finite_state_machine/debug/states_stack_displayer.gd index 7d3ae0b6..790e2f0d 100644 --- a/2d/finite_state_machine/debug/states_stack_displayer.gd +++ b/2d/finite_state_machine/debug/states_stack_displayer.gd @@ -1,14 +1,16 @@ extends Panel -@onready var fsm_node = get_node(^"../../Player/StateMachine") +@onready var fsm_node: Node = get_node(^"../../Player/StateMachine") -func _process(_delta): - var states_names = "" - var numbers = "" - var index = 0 - for state in fsm_node.states_stack: - states_names += String(state.get_name()) + "\n" +func _process(_delta: float) -> void: + var states_names := "" + var numbers := "" + var index := 0 + + for state: Node in fsm_node.states_stack: + states_names += String(state.name) + "\n" numbers += str(index) + "\n" index += 1 + %States.text = states_names %Numbers.text = numbers diff --git a/2d/finite_state_machine/player/bullet/bullet.gd b/2d/finite_state_machine/player/bullet/bullet.gd index bcb49f88..190f7bdd 100644 --- a/2d/finite_state_machine/player/bullet/bullet.gd +++ b/2d/finite_state_machine/player/bullet/bullet.gd @@ -1,23 +1,23 @@ extends CharacterBody2D -var direction = Vector2() -@export var speed: float = 1000.0 +var direction := Vector2() +@export var speed := 1000.0 -@onready var root = get_tree().root +@onready var root := get_tree().root -func _ready(): +func _ready() -> void: set_as_top_level(true) -func _physics_process(delta): +func _physics_process(delta: float) -> void: if not root.get_visible_rect().has_point(position): queue_free() - var motion = direction * speed * delta - var collision_info = move_and_collide(motion) + var motion := direction * speed * delta + var collision_info := move_and_collide(motion) if collision_info: queue_free() -func _draw(): +func _draw() -> void: draw_circle(Vector2(), $CollisionShape2D.shape.radius, Color.WHITE) diff --git a/2d/finite_state_machine/player/bullet/bullet_spawner.gd b/2d/finite_state_machine/player/bullet/bullet_spawner.gd index 2bacd033..558a55ec 100644 --- a/2d/finite_state_machine/player/bullet/bullet_spawner.gd +++ b/2d/finite_state_machine/player/bullet/bullet_spawner.gd @@ -1,18 +1,18 @@ extends Node2D -var bullet = preload("Bullet.tscn") +var bullet := preload("Bullet.tscn") -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("fire"): fire() -func fire(): +func fire() -> void: if not $CooldownTimer.is_stopped(): return $CooldownTimer.start() - var new_bullet = bullet.instantiate() + var new_bullet := bullet.instantiate() add_child(new_bullet) new_bullet.position = global_position new_bullet.direction = owner.look_direction diff --git a/2d/finite_state_machine/player/player_controller.gd b/2d/finite_state_machine/player/player_controller.gd index 578ac13d..05822099 100644 --- a/2d/finite_state_machine/player/player_controller.gd +++ b/2d/finite_state_machine/player/player_controller.gd @@ -3,25 +3,26 @@ extends CharacterBody2D # It can move, collide with the world, etc... # The player has a state machine, but the body and the state machine are separate. -signal direction_changed(new_direction) +signal direction_changed(new_direction: Vector2) -var look_direction = Vector2.RIGHT: +var look_direction := Vector2.RIGHT: set(value): look_direction = value set_look_direction(value) -func take_damage(attacker, amount, effect = null): +func take_damage(attacker: Node, amount: float, effect: Node = null) -> void: if is_ancestor_of(attacker): return + $States/Stagger.knockback_direction = (attacker.global_position - global_position).normalized() $Health.take_damage(amount, effect) -func set_dead(value): +func set_dead(value: bool) -> void: set_process_input(not value) set_physics_process(not value) $CollisionPolygon2D.disabled = value -func set_look_direction(value): +func set_look_direction(value: Vector2) -> void: direction_changed.emit(value) diff --git a/2d/finite_state_machine/player/player_state_machine.gd b/2d/finite_state_machine/player/player_state_machine.gd index 33169fad..369ee269 100644 --- a/2d/finite_state_machine/player/player_state_machine.gd +++ b/2d/finite_state_machine/player/player_state_machine.gd @@ -1,12 +1,12 @@ extends "res://state_machine/state_machine.gd" -@onready var idle = $Idle -@onready var move = $Move -@onready var jump = $Jump -@onready var stagger = $Stagger -@onready var attack = $Attack +@onready var idle: Node = $Idle +@onready var move: Node = $Move +@onready var jump: Node = $Jump +@onready var stagger: Node = $Stagger +@onready var attack: Node = $Attack -func _ready(): +func _ready() -> void: states_map = { "idle": idle, "move": move, @@ -16,7 +16,7 @@ func _ready(): } -func _change_state(state_name): +func _change_state(state_name: String) -> void: # The base state_machine interface this node extends does most of the work. if not _active: return @@ -24,10 +24,11 @@ func _change_state(state_name): states_stack.push_front(states_map[state_name]) if state_name == "jump" and current_state == move: jump.initialize(move.speed, move.velocity) + super._change_state(state_name) -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: # Here we only handle input that can interrupt states, attacking in this case, # otherwise we let the state node handle it. if event.is_action_pressed("attack"): @@ -35,4 +36,5 @@ func _unhandled_input(event): return _change_state("attack") return + current_state.handle_input(event) diff --git a/2d/finite_state_machine/player/states/combat/attack.gd b/2d/finite_state_machine/player/states/combat/attack.gd index 0712a6de..917b3871 100644 --- a/2d/finite_state_machine/player/states/combat/attack.gd +++ b/2d/finite_state_machine/player/states/combat/attack.gd @@ -1,8 +1,8 @@ extends "res://state_machine/state.gd" -func enter(): +func enter() -> void: owner.get_node(^"AnimationPlayer").play("idle") -func _on_Sword_attack_finished(): +func _on_Sword_attack_finished() -> void: finished.emit("previous") diff --git a/2d/finite_state_machine/player/states/combat/stagger.gd b/2d/finite_state_machine/player/states/combat/stagger.gd index ea360748..80f4d968 100644 --- a/2d/finite_state_machine/player/states/combat/stagger.gd +++ b/2d/finite_state_machine/player/states/combat/stagger.gd @@ -3,10 +3,10 @@ extends "res://state_machine/state.gd" # The animation only affects the Body Sprite2D's modulate property so it # could stack with other animations if we had two AnimationPlayer nodes. -func enter(): +func enter() -> void: owner.get_node(^"AnimationPlayer").play("stagger") -func _on_animation_finished(anim_name): +func _on_animation_finished(anim_name: String) -> void: assert(anim_name == "stagger") finished.emit("previous") diff --git a/2d/finite_state_machine/player/states/debug/state_name_displayer.gd b/2d/finite_state_machine/player/states/debug/state_name_displayer.gd index 9d00e073..5d2dd9f5 100644 --- a/2d/finite_state_machine/player/states/debug/state_name_displayer.gd +++ b/2d/finite_state_machine/player/states/debug/state_name_displayer.gd @@ -1,14 +1,14 @@ extends Label -var start_position = Vector2() +var start_position := Vector2() -func _ready(): +func _ready() -> void: start_position = position -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: position = $"../BodyPivot".position + start_position -func _on_StateMachine_state_changed(current_state): - text = String(current_state.get_name()) +func _on_StateMachine_state_changed(current_state: Node) -> void: + text = String(current_state.name) diff --git a/2d/finite_state_machine/player/states/die.gd b/2d/finite_state_machine/player/states/die.gd index 4899eb76..5a4a255a 100644 --- a/2d/finite_state_machine/player/states/die.gd +++ b/2d/finite_state_machine/player/states/die.gd @@ -1,10 +1,10 @@ extends "res://state_machine/state.gd" # Initialize the state. E.g. change the animation. -func enter(): +func enter() -> void: owner.set_dead(true) owner.get_node(^"AnimationPlayer").play("die") -func _on_animation_finished(_anim_name): +func _on_animation_finished(_anim_name: String) -> void: finished.emit("dead") diff --git a/2d/finite_state_machine/player/states/motion/in_air/jump.gd b/2d/finite_state_machine/player/states/motion/in_air/jump.gd index 6ca3fef8..cc42424a 100644 --- a/2d/finite_state_machine/player/states/motion/in_air/jump.gd +++ b/2d/finite_state_machine/player/states/motion/in_air/jump.gd @@ -1,23 +1,23 @@ extends "../motion.gd" -@export var base_max_horizontal_speed: float = 400.0 +@export var base_max_horizontal_speed := 400.0 -@export var air_acceleration: float = 1000.0 -@export var air_deceleration: float = 2000.0 -@export var air_steering_power: float = 50.0 +@export var air_acceleration := 1000.0 +@export var air_deceleration := 2000.0 +@export var air_steering_power := 50.0 -@export var gravity: float = 1600.0 +@export var gravity := 1600.0 -var enter_velocity = Vector2() +var enter_velocity := Vector2() -var max_horizontal_speed = 0.0 -var horizontal_speed = 0.0 -var horizontal_velocity = Vector2() +var max_horizontal_speed := 0.0 +var horizontal_speed := 0.0 +var horizontal_velocity := Vector2() -var vertical_speed = 0.0 -var height = 0.0 +var vertical_speed := 0.0 +var height := 0.0 -func initialize(speed, velocity): +func initialize(speed: float, velocity: Vector2) -> void: horizontal_speed = speed if speed > 0.0: max_horizontal_speed = speed @@ -26,8 +26,8 @@ func initialize(speed, velocity): enter_velocity = velocity -func enter(): - var input_direction = get_input_direction() +func enter() -> void: + var input_direction := get_input_direction() update_look_direction(input_direction) if input_direction: @@ -39,8 +39,8 @@ func enter(): owner.get_node(^"AnimationPlayer").play("idle") -func update(delta): - var input_direction = get_input_direction() +func update(delta: float) -> void: + var input_direction := get_input_direction() update_look_direction(input_direction) move_horizontally(delta, input_direction) @@ -49,22 +49,22 @@ func update(delta): finished.emit("previous") -func move_horizontally(delta, direction): +func move_horizontally(delta: float, direction: Vector2) -> void: if direction: horizontal_speed += air_acceleration * delta else: horizontal_speed -= air_deceleration * delta horizontal_speed = clamp(horizontal_speed, 0, max_horizontal_speed) - var target_velocity = horizontal_speed * direction.normalized() - var steering_velocity = (target_velocity - horizontal_velocity).normalized() * air_steering_power + var target_velocity := horizontal_speed * direction.normalized() + var steering_velocity := (target_velocity - horizontal_velocity).normalized() * air_steering_power horizontal_velocity += steering_velocity owner.velocity = horizontal_velocity owner.move_and_slide() -func animate_jump_height(delta): +func animate_jump_height(delta: float) -> void: vertical_speed -= gravity * delta height += vertical_speed * delta height = max(0.0, height) diff --git a/2d/finite_state_machine/player/states/motion/motion.gd b/2d/finite_state_machine/player/states/motion/motion.gd index 16d40ce8..19f2c559 100644 --- a/2d/finite_state_machine/player/states/motion/motion.gd +++ b/2d/finite_state_machine/player/states/motion/motion.gd @@ -1,19 +1,18 @@ extends "res://state_machine/state.gd" # Collection of important methods to handle direction and animation. -func handle_input(event): +func handle_input(event: InputEvent) -> void: if event.is_action_pressed("simulate_damage"): finished.emit("stagger") -func get_input_direction(): - var input_direction = Vector2( +func get_input_direction() -> Vector2: + return Vector2( Input.get_axis(&"move_left", &"move_right"), Input.get_axis(&"move_up", &"move_down") ) - return input_direction -func update_look_direction(direction): +func update_look_direction(direction: Vector2) -> void: if direction and owner.look_direction != direction: owner.look_direction = direction diff --git a/2d/finite_state_machine/player/states/motion/on_ground/idle.gd b/2d/finite_state_machine/player/states/motion/on_ground/idle.gd index c1778507..3cca0343 100644 --- a/2d/finite_state_machine/player/states/motion/on_ground/idle.gd +++ b/2d/finite_state_machine/player/states/motion/on_ground/idle.gd @@ -1,14 +1,14 @@ extends "on_ground.gd" -func enter(): +func enter() -> void: owner.get_node(^"AnimationPlayer").play("idle") -func handle_input(event): +func handle_input(event: InputEvent) -> void: return super.handle_input(event) -func update(_delta): - var input_direction = get_input_direction() +func update(_delta: float) -> void: + var input_direction: Vector2 = get_input_direction() if input_direction: finished.emit("move") diff --git a/2d/finite_state_machine/player/states/motion/on_ground/move.gd b/2d/finite_state_machine/player/states/motion/on_ground/move.gd index 931be2f1..b722b7f8 100644 --- a/2d/finite_state_machine/player/states/motion/on_ground/move.gd +++ b/2d/finite_state_machine/player/states/motion/on_ground/move.gd @@ -1,23 +1,23 @@ extends "on_ground.gd" -@export var max_walk_speed: float = 450 -@export var max_run_speed: float = 700 +@export var max_walk_speed := 450.0 +@export var max_run_speed := 700.0 -func enter(): +func enter() -> void: speed = 0.0 velocity = Vector2() - var input_direction = get_input_direction() + var input_direction := get_input_direction() update_look_direction(input_direction) owner.get_node(^"AnimationPlayer").play("walk") -func handle_input(event): +func handle_input(event: InputEvent) -> void: return super.handle_input(event) -func update(_delta): - var input_direction = get_input_direction() +func update(_delta: float) -> void: + var input_direction := get_input_direction() if input_direction.is_zero_approx(): finished.emit("idle") update_look_direction(input_direction) @@ -27,16 +27,17 @@ func update(_delta): else: speed = max_walk_speed - var collision_info = move(speed, input_direction) + var collision_info := move(speed, input_direction) if not collision_info: return if speed == max_run_speed and collision_info.collider.is_in_group("environment"): - return null + return -func move(speed, direction): - owner.velocity = direction.normalized() * speed +func move(p_speed: float, direction: Vector2) -> KinematicCollision2D: + owner.velocity = direction.normalized() * p_speed owner.move_and_slide() if owner.get_slide_collision_count() == 0: - return + return null + return owner.get_slide_collision(0) diff --git a/2d/finite_state_machine/player/states/motion/on_ground/on_ground.gd b/2d/finite_state_machine/player/states/motion/on_ground/on_ground.gd index 61e1edbd..a20e283f 100644 --- a/2d/finite_state_machine/player/states/motion/on_ground/on_ground.gd +++ b/2d/finite_state_machine/player/states/motion/on_ground/on_ground.gd @@ -1,10 +1,10 @@ extends "../motion.gd" # warning-ignore-all:unused_class_variable -var speed = 0.0 -var velocity = Vector2() +var speed := 0.0 +var velocity := Vector2() -func handle_input(event): +func handle_input(event: InputEvent) -> void: if event.is_action_pressed("jump"): finished.emit("jump") return super.handle_input(event) diff --git a/2d/finite_state_machine/player/weapon/sword.gd b/2d/finite_state_machine/player/weapon/sword.gd index bd571cd2..f5410ee5 100644 --- a/2d/finite_state_machine/player/weapon/sword.gd +++ b/2d/finite_state_machine/player/weapon/sword.gd @@ -2,41 +2,50 @@ extends Area2D signal attack_finished -enum States { IDLE, ATTACK } -var state = null +enum States { + IDLE, + ATTACK, +} -enum AttackInputStates { IDLE, LISTENING, REGISTERED } -var attack_input_state = AttackInputStates.IDLE -var ready_for_next_attack = false +enum AttackInputStates { + IDLE, + LISTENING, + REGISTERED, +} + +var state: States = States.IDLE +var attack_input_state := AttackInputStates.IDLE +var ready_for_next_attack := false const MAX_COMBO_COUNT = 3 -var combo_count = 0 +var combo_count := 0 -var attack_current = {} -var combo = [{ +var attack_current := {} +var combo := [{ "damage": 1, "animation": "attack_fast", - "effect": null + "effect": null, }, { "damage": 1, "animation": "attack_fast", - "effect": null + "effect": null, }, { "damage": 3, "animation": "attack_medium", - "effect": null - }] + "effect": null, + } +] -var hit_objects = [] +var hit_objects := [] -func _ready(): +func _ready() -> void: $AnimationPlayer.animation_finished.connect(_on_animation_finished) body_entered.connect(_on_body_entered) _change_state(States.IDLE) -func _change_state(new_state): +func _change_state(new_state: States) -> void: match state: States.ATTACK: hit_objects = [] @@ -57,7 +66,7 @@ func _change_state(new_state): state = new_state -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: if not state == States.ATTACK: return if attack_input_state != AttackInputStates.LISTENING: @@ -66,36 +75,37 @@ func _unhandled_input(event): attack_input_state = AttackInputStates.REGISTERED -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if attack_input_state == AttackInputStates.REGISTERED and ready_for_next_attack: attack() -func attack(): +func attack() -> void: combo_count += 1 _change_state(States.ATTACK) # Use with AnimationPlayer func track. -func set_attack_input_listening(): +func set_attack_input_listening() -> void: attack_input_state = AttackInputStates.LISTENING # Use with AnimationPlayer func track. -func set_ready_for_next_attack(): +func set_ready_for_next_attack() -> void: ready_for_next_attack = true -func _on_body_entered(body): +func _on_body_entered(body: Node2D) -> void: if not body.has_node("Health"): return if body.get_rid().get_id() in hit_objects: return + hit_objects.append(body.get_rid().get_id()) body.take_damage(self, attack_current["damage"], attack_current["effect"]) -func _on_animation_finished(_name): +func _on_animation_finished(_name: String) -> void: if attack_current.is_empty(): return @@ -106,6 +116,6 @@ func _on_animation_finished(_name): attack_finished.emit() -func _on_StateMachine_state_changed(current_state): +func _on_StateMachine_state_changed(current_state: Node) -> void: if current_state.name == "Attack": attack() diff --git a/2d/finite_state_machine/player/weapon/weapon_pivot.gd b/2d/finite_state_machine/player/weapon/weapon_pivot.gd index 68579c1c..7d5c42ce 100644 --- a/2d/finite_state_machine/player/weapon/weapon_pivot.gd +++ b/2d/finite_state_machine/player/weapon/weapon_pivot.gd @@ -1,13 +1,13 @@ extends Marker2D -var z_index_start = 0 +var z_index_start := 0 -func _ready(): +func _ready() -> void: owner.direction_changed.connect(_on_Parent_direction_changed) z_index_start = z_index -func _on_Parent_direction_changed(direction): +func _on_Parent_direction_changed(direction: Vector2) -> void: rotation = direction.angle() match direction: Vector2.UP: diff --git a/2d/finite_state_machine/project.godot b/2d/finite_state_machine/project.godot index 96561815..8b17a922 100644 --- a/2d/finite_state_machine/project.godot +++ b/2d/finite_state_machine/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://Demo.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1280 diff --git a/2d/finite_state_machine/state_machine/state.gd b/2d/finite_state_machine/state_machine/state.gd index a2a43d4f..bac82b6e 100644 --- a/2d/finite_state_machine/state_machine/state.gd +++ b/2d/finite_state_machine/state_machine/state.gd @@ -4,25 +4,25 @@ extends Node # and makes sure every State object had all of these methods. # warning-ignore:unused_signal -signal finished(next_state_name) +signal finished(next_state_name: String) # Initialize the state. E.g. change the animation. -func enter(): +func enter() -> void: pass # Clean up the state. Reinitialize values like a timer. -func exit(): +func exit() -> void: pass -func handle_input(_event): +func handle_input(_event: InputEvent) -> void: pass -func update(_delta): +func update(_delta: float) -> void: pass -func _on_animation_finished(_anim_name): +func _on_animation_finished(_anim_name: String) -> void: pass diff --git a/2d/finite_state_machine/state_machine/state_machine.gd b/2d/finite_state_machine/state_machine/state_machine.gd index 294bd389..59c2e8a4 100644 --- a/2d/finite_state_machine/state_machine/state_machine.gd +++ b/2d/finite_state_machine/state_machine/state_machine.gd @@ -5,39 +5,39 @@ extends Node # and changing the current/active state. # See the PlayerV2 scene for an example on how to use it. -signal state_changed(current_state) +signal state_changed(current_state: Node) # You should set a starting node from the inspector or on the node that inherits # from this state machine interface. If you don't, the game will default to # the first state in the state machine's children. @export var start_state: NodePath -var states_map = {} +var states_map := {} -var states_stack = [] -var current_state = null -var _active = false: +var states_stack := [] +var current_state: Node = null +var _active := false: set(value): _active = value set_active(value) -func _enter_tree(): +func _enter_tree() -> void: if start_state.is_empty(): start_state = get_child(0).get_path() for child in get_children(): - var err = child.finished.connect(_change_state) + var err: bool = child.finished.connect(_change_state) if err: printerr(err) initialize(start_state) -func initialize(initial_state): +func initialize(initial_state: NodePath) -> void: _active = true states_stack.push_front(get_node(initial_state)) current_state = states_stack[0] current_state.enter() -func set_active(value): +func set_active(value: bool) -> void: set_physics_process(value) set_process_input(value) if not _active: @@ -45,21 +45,22 @@ func set_active(value): current_state = null -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: current_state.handle_input(event) -func _physics_process(delta): +func _physics_process(delta: float) -> void: current_state.update(delta) -func _on_animation_finished(anim_name): +func _on_animation_finished(anim_name: String) -> void: if not _active: return + current_state._on_animation_finished(anim_name) -func _change_state(state_name): +func _change_state(state_name: String) -> void: if not _active: return current_state.exit() diff --git a/2d/glow/beach_cave.gd b/2d/glow/beach_cave.gd index f412f4b6..77ecf034 100644 --- a/2d/glow/beach_cave.gd +++ b/2d/glow/beach_cave.gd @@ -2,11 +2,11 @@ extends Node2D const CAVE_LIMIT = 1000 -var glow_map = preload("res://glow_map.webp") +var glow_map := preload("res://glow_map.webp") -@onready var cave = $Cave +@onready var cave: Node2D = $Cave -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseMotion and event.button_mask > 0: cave.position.x = clampf(cave.position.x + event.relative.x, -CAVE_LIMIT, 0) diff --git a/2d/glow/beach_cave.tscn b/2d/glow/beach_cave.tscn index fa0ef170..a47a95b0 100644 --- a/2d/glow/beach_cave.tscn +++ b/2d/glow/beach_cave.tscn @@ -37,7 +37,6 @@ environment = SubResource("1") [node name="Camera2D" type="Camera2D" parent="."] offset = Vector2(540, 360) -current = true [node name="Label" type="Label" parent="."] visible = false diff --git a/2d/glow/project.godot b/2d/glow/project.godot index 7dbfc4ed..828e810b 100644 --- a/2d/glow/project.godot +++ b/2d/glow/project.godot @@ -20,6 +20,10 @@ config/features=PackedStringArray("4.2") config/icon="res://icon.webp" run/name="" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1080 diff --git a/2d/hexagonal_map/map.tscn b/2d/hexagonal_map/map.tscn index 4a1af56d..1a9ae50a 100644 --- a/2d/hexagonal_map/map.tscn +++ b/2d/hexagonal_map/map.tscn @@ -11,4 +11,5 @@ format = 2 layer_0/tile_data = PackedInt32Array(-458747, 0, 0, -458746, 0, 0, -393212, 0, 0, -393211, 0, 0, -393210, 0, 0, -393209, 0, 0, -393208, 0, 0, -393207, 0, 0, -327678, 0, 0, -327677, 0, 0, -327676, 0, 0, -327675, 6, 0, -327674, 6, 0, -327673, 6, 0, -327672, 6, 0, -327671, 0, 0, -327670, 0, 0, -327669, 0, 0, -262142, 0, 0, -262141, 0, 0, -262140, 6, 0, -262139, 6, 0, -262138, 6, 0, -262137, 6, 0, -262136, 6, 0, -262135, 0, 0, -262134, 0, 0, -262133, 0, 0, -262132, 0, 0, -262131, 0, 0, -196606, 0, 0, -196605, 0, 0, -196604, 6, 0, -196603, 6, 0, -196602, 6, 0, -196601, 6, 0, -196600, 1, 0, -196599, 0, 0, -196598, 1, 0, -196597, 1, 0, -196596, 0, 0, -196595, 0, 0, -196594, 0, 0, -131071, 9, 0, -131070, 0, 0, -131069, 0, 0, -131068, 2, 0, -131067, 2, 0, -131066, 0, 0, -131065, 21, 0, -131064, 19, 0, -131063, 0, 0, -131062, 0, 0, -131061, 16, 0, -131060, 0, 0, -131059, 0, 0, -131058, 0, 0, -131057, 0, 0, -131056, 0, 0, -65534, 0, 0, -65533, 1, 0, -65532, 0, 0, -65531, 0, 0, -65530, 20, 0, -65529, 19, 0, -65528, 2, 0, -65527, 0, 0, -65526, 14, 0, -65525, 0, 0, -65524, 0, 0, -65523, 0, 0, -65522, 23, 0, -65521, 0, 0, -65520, 0, 0, -65519, 0, 0, 3, 1, 0, 4, 2, 0, 5, 0, 0, 6, 1, 0, 7, 1, 0, 8, 0, 0, 9, 10, 0, 10, 12, 0, 11, 0, 0, 12, 0, 0, 13, 8, 0, 14, 0, 0, 15, 0, 0, 16, 0, 0, 17, 0, 0, 65538, 0, 0, 65539, 0, 0, 65540, 2, 0, 65541, 0, 0, 65542, 1, 0, 65543, 15, 0, 65544, 0, 0, 65545, 0, 0, 65546, 0, 0, 65547, 0, 0, 65548, 0, 0, 65549, 25, 0, 65550, 8, 0, 65551, 0, 0, 65552, 21, 0, 65553, 0, 0, 131074, 0, 0, 131075, 1, 0, 131076, 0, 0, 131077, 1, 0, 131078, 0, 0, 131079, 0, 0, 131080, 0, 0, 131081, 5, 0, 131082, 0, 0, 131083, 0, 0, 131084, 0, 0, 131085, 0, 0, 131086, 0, 0, 131087, 0, 0, 131088, 0, 0, 131089, 0, 0, 196610, 0, 0, 196611, 0, 0, 196612, 0, 0, 196613, 23, 0, 196614, 0, 0, 196615, 0, 0, 196616, 0, 0, 196617, 5, 0, 196618, 5, 0, 196619, 0, 0, 196620, 0, 0, 196621, 0, 0, 196622, 0, 0, 196623, 23, 0, 196624, 0, 0, 262148, 0, 0, 262149, 0, 0, 262150, 0, 0, 262151, 0, 0, 262152, 8, 0, 262153, 5, 0, 262154, 5, 0, 262155, 0, 0, 262156, 0, 0, 262157, 21, 0, 262158, 0, 0, 262159, 0, 0, 262160, 0, 0, 327686, 0, 0, 327687, 0, 0, 327688, 0, 0, 327689, 0, 0, 327690, 0, 0, 327691, 0, 0, 327692, 0, 0, 327693, 0, 0, 327694, 0, 0) [node name="Troll" parent="." instance=ExtResource("2")] +modulate = Color(1.5, 1.5, 1.5, 1) position = Vector2(602.819, -39.2876) diff --git a/2d/hexagonal_map/project.godot b/2d/hexagonal_map/project.godot index 684a7f35..a839ceec 100644 --- a/2d/hexagonal_map/project.godot +++ b/2d/hexagonal_map/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://map.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/2d/hexagonal_map/troll.gd b/2d/hexagonal_map/troll.gd index 4547c265..c50907d7 100644 --- a/2d/hexagonal_map/troll.gd +++ b/2d/hexagonal_map/troll.gd @@ -4,8 +4,8 @@ const MOTION_SPEED = 30 const FRICTION_FACTOR = 0.89 const TAN30DEG = tan(deg_to_rad(30)) -func _physics_process(_delta): - var motion = Vector2() +func _physics_process(_delta: float) -> void: + var motion := Vector2() motion.x = Input.get_axis(&"move_left", &"move_right") motion.y = Input.get_axis(&"move_up", &"move_down") # Make diagonal movement fit for hexagonal tiles. diff --git a/2d/hexagonal_map/troll.tscn b/2d/hexagonal_map/troll.tscn index 92377559..3e7efade 100644 --- a/2d/hexagonal_map/troll.tscn +++ b/2d/hexagonal_map/troll.tscn @@ -15,7 +15,9 @@ texture = ExtResource("2") [node name="Shadow" type="Sprite2D" parent="."] modulate = Color(0, 0, 0, 0.501961) show_behind_parent = true -position = Vector2(3, 3) +position = Vector2(16.4422, 4.89438) +scale = Vector2(0.794259, 1.04505) +skew = 0.523599 texture = ExtResource("2") [node name="CollisionShape2D" type="CollisionShape2D" parent="."] @@ -23,4 +25,3 @@ position = Vector2(3.24216, 19.453) shape = SubResource("1") [node name="Camera2D" type="Camera2D" parent="."] -current = true diff --git a/2d/instancing/ball.tscn b/2d/instancing/ball.tscn index 71796a40..43cdbab6 100644 --- a/2d/instancing/ball.tscn +++ b/2d/instancing/ball.tscn @@ -1,18 +1,18 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=4 format=3 uid="uid://cgx884jv27maj"] -[ext_resource path="res://bowling_ball.png" type="Texture2D" id=1] +[ext_resource type="Texture2D" uid="uid://cyqshsjd3qwo0" path="res://bowling_ball.png" id="1"] -[sub_resource type="PhysicsMaterial" id=1] +[sub_resource type="PhysicsMaterial" id="1"] bounce = 0.4 -[sub_resource type="CircleShape2D" id=2] +[sub_resource type="CircleShape2D" id="2"] radius = 30.0 -[node name="Ball" type="RigidDynamicBody2D"] -physics_material_override = SubResource( 1 ) +[node name="Ball" type="RigidBody2D"] +physics_material_override = SubResource("1") [node name="Sprite2D" type="Sprite2D" parent="."] -texture = ExtResource( 1 ) +texture = ExtResource("1") [node name="Collision" type="CollisionShape2D" parent="."] -shape = SubResource( 2 ) +shape = SubResource("2") diff --git a/2d/instancing/ball_factory.gd b/2d/instancing/ball_factory.gd index f72ff67e..4950930d 100644 --- a/2d/instancing/ball_factory.gd +++ b/2d/instancing/ball_factory.gd @@ -2,15 +2,16 @@ extends Node2D @export var ball_scene: PackedScene = preload("res://ball.tscn") -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: if event.is_echo(): return + if event is InputEventMouseButton and event.is_pressed(): if event.button_index == MOUSE_BUTTON_LEFT: spawn(get_global_mouse_position()) -func spawn(spawn_global_position): - var instance = ball_scene.instantiate() +func spawn(spawn_global_position: Vector2) -> void: + var instance: Node2D = ball_scene.instantiate() instance.global_position = spawn_global_position add_child(instance) diff --git a/2d/instancing/project.godot b/2d/instancing/project.godot index c9b993b2..3e2a0664 100644 --- a/2d/instancing/project.godot +++ b/2d/instancing/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://scene_instancing.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" @@ -25,6 +29,7 @@ window/stretch/aspect="expand" [physics] +common/physics_ticks_per_second=120 2d/default_gravity=300 [rendering] diff --git a/2d/instancing/scene_instancing.tscn b/2d/instancing/scene_instancing.tscn index 6b42e2ae..b8a4addd 100644 --- a/2d/instancing/scene_instancing.tscn +++ b/2d/instancing/scene_instancing.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=13 format=3 uid="uid://rcsr8t4nw526"] [ext_resource type="Script" path="res://ball_factory.gd" id="1"] -[ext_resource type="PackedScene" path="res://ball.tscn" id="2"] +[ext_resource type="PackedScene" uid="uid://cgx884jv27maj" path="res://ball.tscn" id="2"] [sub_resource type="PhysicsMaterial" id="1"] bounce = 0.4 @@ -35,7 +35,9 @@ bounce = 0.4 [node name="SceneInstancing" type="Node2D"] -[node name="InfoLabel" type="Label" parent="."] +[node name="CanvasLayer" type="CanvasLayer" parent="."] + +[node name="InfoLabel" type="Label" parent="CanvasLayer"] offset_left = 16.0 offset_top = 16.0 offset_right = 370.0 diff --git a/2d/kinematic_character/level/princess.gd b/2d/kinematic_character/level/princess.gd index f9e721ca..42944485 100644 --- a/2d/kinematic_character/level/princess.gd +++ b/2d/kinematic_character/level/princess.gd @@ -1,5 +1,5 @@ extends Node -func _on_body_entered(body): +func _on_body_entered(body: Node2D) -> void: if body.name == "Player": $"../WinText".show() diff --git a/2d/kinematic_character/player/player.gd b/2d/kinematic_character/player/player.gd index 6bdbb58b..7ce919a4 100644 --- a/2d/kinematic_character/player/player.gd +++ b/2d/kinematic_character/player/player.gd @@ -5,11 +5,11 @@ const WALK_MAX_SPEED = 200 const STOP_FORCE = 1300 const JUMP_SPEED = 200 -@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") +@onready var gravity := float(ProjectSettings.get_setting("physics/2d/default_gravity")) -func _physics_process(delta): +func _physics_process(delta: float) -> void: # Horizontal movement code. First, get the player's input. - var walk = WALK_FORCE * (Input.get_axis(&"move_left", &"move_right")) + var walk := WALK_FORCE * (Input.get_axis(&"move_left", &"move_right")) # Slow down the player if they're not trying to move. if abs(walk) < WALK_FORCE * 0.2: # The velocity, slowed down a bit, and then reassigned. diff --git a/2d/kinematic_character/project.godot b/2d/kinematic_character/project.godot index 26c2bf62..e4ac8757 100644 --- a/2d/kinematic_character/project.godot +++ b/2d/kinematic_character/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://world.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=530 diff --git a/2d/light2d_as_mask/project.godot b/2d/light2d_as_mask/project.godot index 2f120845..9f2c672e 100644 --- a/2d/light2d_as_mask/project.godot +++ b/2d/light2d_as_mask/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://lightmask.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/2d/lights_and_shadows/light_shadows.gd b/2d/lights_and_shadows/light_shadows.gd index 29621f3e..c49caa54 100644 --- a/2d/lights_and_shadows/light_shadows.gd +++ b/2d/lights_and_shadows/light_shadows.gd @@ -1,7 +1,7 @@ extends Node2D -func _input(event): +func _input(event: InputEvent) -> void: if event.is_action_pressed("toggle_directional_light"): $DirectionalLight2D.visible = not $DirectionalLight2D.visible diff --git a/2d/lights_and_shadows/project.godot b/2d/lights_and_shadows/project.godot index 36978d62..936e47d5 100644 --- a/2d/lights_and_shadows/project.godot +++ b/2d/lights_and_shadows/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://light_shadows.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=800 diff --git a/2d/navigation/character.gd b/2d/navigation/character.gd index aa3354f5..b99ea907 100644 --- a/2d/navigation/character.gd +++ b/2d/navigation/character.gd @@ -1,11 +1,10 @@ extends CharacterBody2D +var movement_speed := 200.0 -var movement_speed: float = 200.0 @onready var navigation_agent: NavigationAgent2D = $NavigationAgent2D - -func _ready(): +func _ready() -> void: # These values need to be adjusted for the actor's speed # and the navigation layout. navigation_agent.path_desired_distance = 2.0 @@ -15,17 +14,18 @@ func _ready(): # The "click" event is a custom input action defined in # Project > Project Settings > Input Map tab. -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: if not event.is_action_pressed("click"): return + set_movement_target(get_global_mouse_position()) -func set_movement_target(movement_target: Vector2): +func set_movement_target(movement_target: Vector2) -> void: navigation_agent.target_position = movement_target -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if navigation_agent.is_navigation_finished(): return diff --git a/2d/navigation/project.godot b/2d/navigation/project.godot index d26d6e7a..5013022d 100644 --- a/2d/navigation/project.godot +++ b/2d/navigation/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://navigation.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=800 @@ -33,6 +37,10 @@ click={ ] } +[physics] + +common/physics_ticks_per_second=120 + [rendering] renderer/rendering_method="gl_compatibility" diff --git a/2d/navigation_astar/character.gd b/2d/navigation_astar/character.gd index b6b9ef2a..6f5ea1dc 100644 --- a/2d/navigation_astar/character.gd +++ b/2d/navigation_astar/character.gd @@ -1,29 +1,33 @@ extends Node2D -enum State { IDLE, FOLLOW } +enum State { + IDLE, + FOLLOW, +} const MASS = 10.0 const ARRIVE_DISTANCE = 10.0 -@export var speed: float = 200.0 +@export_range(10, 500, 0.1, "or_greater") var speed := 200.0 -var _state = State.IDLE -var _velocity = Vector2() +var _state := State.IDLE +var _velocity := Vector2() -@onready var _tile_map = $"../TileMap" +var _click_position := Vector2() +var _path := PackedVector2Array() +var _next_point := Vector2() -var _click_position = Vector2() -var _path = PackedVector2Array() -var _next_point = Vector2() +@onready var _tile_map: TileMap = $"../TileMap" -func _ready(): +func _ready() -> void: _change_state(State.IDLE) -func _process(_delta): +func _process(_delta: float) -> void: if _state != State.FOLLOW: return - var arrived_to_next_point = _move_to(_next_point) + + var arrived_to_next_point := _move_to(_next_point) if arrived_to_next_point: _path.remove_at(0) if _path.is_empty(): @@ -32,7 +36,7 @@ func _process(_delta): _next_point = _path[0] -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: _click_position = get_global_mouse_position() if _tile_map.is_point_walkable(_click_position): if event.is_action_pressed(&"teleport_to", false, true): @@ -42,16 +46,16 @@ func _unhandled_input(event): _change_state(State.FOLLOW) -func _move_to(local_position): - var desired_velocity = (local_position - position).normalized() * speed - var steering = desired_velocity - _velocity +func _move_to(local_position: Vector2) -> float: + var desired_velocity := (local_position - position).normalized() * speed + var steering := desired_velocity - _velocity _velocity += steering / MASS position += _velocity * get_process_delta_time() rotation = _velocity.angle() return position.distance_to(local_position) < ARRIVE_DISTANCE -func _change_state(new_state): +func _change_state(new_state: State) -> void: if new_state == State.IDLE: _tile_map.clear_path() elif new_state == State.FOLLOW: diff --git a/2d/navigation_astar/pathfind_astar.gd b/2d/navigation_astar/pathfind_astar.gd index 5701cab5..a7187d15 100644 --- a/2d/navigation_astar/pathfind_astar.gd +++ b/2d/navigation_astar/pathfind_astar.gd @@ -1,19 +1,23 @@ extends TileMap -enum Tile { OBSTACLE, START_POINT, END_POINT } +enum Tile { + OBSTACLE, + START_POINT, + END_POINT, +} const CELL_SIZE = Vector2i(64, 64) const BASE_LINE_WIDTH = 3.0 const DRAW_COLOR = Color.WHITE * Color(1, 1, 1, 0.5) # The object for pathfinding on 2D grids. -var _astar = AStarGrid2D.new() +var _astar := AStarGrid2D.new() -var _start_point = Vector2i() -var _end_point = Vector2i() -var _path = PackedVector2Array() +var _start_point := Vector2i() +var _end_point := Vector2i() +var _path := PackedVector2Array() -func _ready(): +func _ready() -> void: # Region should match the size of the playable area plus one (in tiles). # In this demo, the playable area is 17×9 tiles, so the rect size is 18×10. _astar.region = Rect2i(0, 0, 18, 10) @@ -26,35 +30,35 @@ func _ready(): for i in range(_astar.region.position.x, _astar.region.end.x): for j in range(_astar.region.position.y, _astar.region.end.y): - var pos = Vector2i(i, j) + var pos := Vector2i(i, j) if get_cell_source_id(0, pos) == Tile.OBSTACLE: _astar.set_point_solid(pos) -func _draw(): +func _draw() -> void: if _path.is_empty(): return - var last_point = _path[0] + var last_point := _path[0] for index in range(1, len(_path)): - var current_point = _path[index] + var current_point := _path[index] draw_line(last_point, current_point, DRAW_COLOR, BASE_LINE_WIDTH, true) draw_circle(current_point, BASE_LINE_WIDTH * 2.0, DRAW_COLOR) last_point = current_point -func round_local_position(local_position): +func round_local_position(local_position: Vector2i) -> Vector2i: return map_to_local(local_to_map(local_position)) -func is_point_walkable(local_position): - var map_position = local_to_map(local_position) +func is_point_walkable(local_position: Vector2i) -> bool: + var map_position := local_to_map(local_position) if _astar.is_in_boundsv(map_position): return not _astar.is_point_solid(map_position) return false -func clear_path(): +func clear_path() -> void: if not _path.is_empty(): _path.clear() erase_cell(0, _start_point) @@ -63,7 +67,7 @@ func clear_path(): queue_redraw() -func find_path(local_start_point, local_end_point): +func find_path(local_start_point: Vector2i, local_end_point: Vector2i) -> PackedVector2Array: clear_path() _start_point = local_to_map(local_start_point) diff --git a/2d/navigation_astar/project.godot b/2d/navigation_astar/project.godot index 203f3bcf..d45c68e2 100644 --- a/2d/navigation_astar/project.godot +++ b/2d/navigation_astar/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://game.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/2d/particles/particles.tscn b/2d/particles/particles.tscn index 0de90a42..bdf9b285 100644 --- a/2d/particles/particles.tscn +++ b/2d/particles/particles.tscn @@ -46,8 +46,8 @@ curve = SubResource("4") [sub_resource type="ParticleProcessMaterial" id="6"] emission_shape = 1 emission_sphere_radius = 8.0 -gravity = Vector3(0, -250, 0) angular_velocity_curve = SubResource("3") +gravity = Vector3(0, -250, 0) scale_curve = SubResource("5") color_ramp = SubResource("GradientTexture1D_fv41j") @@ -61,8 +61,8 @@ particles_anim_loop = false [sub_resource type="ParticleProcessMaterial" id="8"] emission_shape = 1 emission_sphere_radius = 75.0 -gravity = Vector3(0, -26, 0) angular_velocity_curve = SubResource("3") +gravity = Vector3(0, -26, 0) scale_curve = SubResource("5") color = Color(0, 0.67, 2, 1) hue_variation_max = 0.02 @@ -83,15 +83,13 @@ point_count = 3 curve = SubResource("Curve_vsw1v") [sub_resource type="ParticleProcessMaterial" id="11"] +particle_flag_disable_z = true emission_shape = 1 emission_sphere_radius = 30.0 -particle_flag_disable_z = true +angle_max = 360.0 gravity = Vector3(0, 0, 0) -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 radial_accel_min = 15.0 radial_accel_max = 15.0 -angle_max = 360.0 scale_curve = SubResource("CurveTexture_b7coa") color_ramp = SubResource("10") @@ -173,7 +171,7 @@ radial_accel_curve = SubResource("24") scale_curve = SubResource("26") color_ramp = SubResource("22") -[sub_resource type="Image" id="Image_74irx"] +[sub_resource type="Image" id="Image_r68lw"] data = { "data": PackedByteArray(0, 0, 208, 65, 0, 0, 184, 66, 0, 0, 208, 65, 0, 0, 186, 66, 0, 0, 208, 65, 0, 0, 188, 66, 0, 0, 208, 65, 0, 0, 190, 66, 0, 0, 208, 65, 0, 0, 192, 66, 0, 0, 208, 65, 0, 0, 194, 66, 0, 0, 208, 65, 0, 0, 196, 66, 0, 0, 208, 65, 0, 0, 198, 66, 0, 0, 208, 65, 0, 0, 200, 66, 0, 0, 208, 65, 0, 0, 202, 66, 0, 0, 208, 65, 0, 0, 46, 67, 0, 0, 208, 65, 0, 0, 47, 67, 0, 0, 208, 65, 0, 0, 48, 67, 0, 0, 208, 65, 0, 0, 49, 67, 0, 0, 208, 65, 0, 0, 50, 67, 0, 0, 208, 65, 0, 0, 51, 67, 0, 0, 208, 65, 0, 0, 52, 67, 0, 0, 208, 65, 0, 0, 53, 67, 0, 0, 208, 65, 0, 0, 54, 67, 0, 0, 208, 65, 0, 0, 55, 67, 0, 0, 216, 65, 0, 0, 184, 66, 0, 0, 216, 65, 0, 0, 186, 66, 0, 0, 216, 65, 0, 0, 188, 66, 0, 0, 216, 65, 0, 0, 190, 66, 0, 0, 216, 65, 0, 0, 192, 66, 0, 0, 216, 65, 0, 0, 194, 66, 0, 0, 216, 65, 0, 0, 196, 66, 0, 0, 216, 65, 0, 0, 198, 66, 0, 0, 216, 65, 0, 0, 200, 66, 0, 0, 216, 65, 0, 0, 202, 66, 0, 0, 216, 65, 0, 0, 204, 66, 0, 0, 216, 65, 0, 0, 45, 67, 0, 0, 216, 65, 0, 0, 46, 67, 0, 0, 216, 65, 0, 0, 47, 67, 0, 0, 216, 65, 0, 0, 48, 67, 0, 0, 216, 65, 0, 0, 49, 67, 0, 0, 216, 65, 0, 0, 50, 67, 0, 0, 216, 65, 0, 0, 51, 67, 0, 0, 216, 65, 0, 0, 52, 67, 0, 0, 216, 65, 0, 0, 53, 67, 0, 0, 216, 65, 0, 0, 54, 67, 0, 0, 216, 65, 0, 0, 55, 67, 0, 0, 224, 65, 0, 0, 184, 66, 0, 0, 224, 65, 0, 0, 186, 66, 0, 0, 224, 65, 0, 0, 188, 66, 0, 0, 224, 65, 0, 0, 190, 66, 0, 0, 224, 65, 0, 0, 192, 66, 0, 0, 224, 65, 0, 0, 194, 66, 0, 0, 224, 65, 0, 0, 196, 66, 0, 0, 224, 65, 0, 0, 198, 66, 0, 0, 224, 65, 0, 0, 200, 66, 0, 0, 224, 65, 0, 0, 202, 66, 0, 0, 224, 65, 0, 0, 204, 66, 0, 0, 224, 65, 0, 0, 206, 66, 0, 0, 224, 65, 0, 0, 45, 67, 0, 0, 224, 65, 0, 0, 46, 67, 0, 0, 224, 65, 0, 0, 47, 67, 0, 0, 224, 65, 0, 0, 48, 67, 0, 0, 224, 65, 0, 0, 49, 67, 0, 0, 224, 65, 0, 0, 50, 67, 0, 0, 224, 65, 0, 0, 51, 67, 0, 0, 224, 65, 0, 0, 52, 67, 0, 0, 224, 65, 0, 0, 53, 67, 0, 0, 224, 65, 0, 0, 54, 67, 0, 0, 224, 65, 0, 0, 55, 67, 0, 0, 232, 65, 0, 0, 184, 66, 0, 0, 232, 65, 0, 0, 186, 66, 0, 0, 232, 65, 0, 0, 188, 66, 0, 0, 232, 65, 0, 0, 190, 66, 0, 0, 232, 65, 0, 0, 192, 66, 0, 0, 232, 65, 0, 0, 194, 66, 0, 0, 232, 65, 0, 0, 196, 66, 0, 0, 232, 65, 0, 0, 198, 66, 0, 0, 232, 65, 0, 0, 200, 66, 0, 0, 232, 65, 0, 0, 202, 66, 0, 0, 232, 65, 0, 0, 204, 66, 0, 0, 232, 65, 0, 0, 206, 66, 0, 0, 232, 65, 0, 0, 45, 67, 0, 0, 232, 65, 0, 0, 46, 67, 0, 0, 232, 65, 0, 0, 47, 67, 0, 0, 232, 65, 0, 0, 48, 67, 0, 0, 232, 65, 0, 0, 49, 67, 0, 0, 232, 65, 0, 0, 50, 67, 0, 0, 232, 65, 0, 0, 51, 67, 0, 0, 232, 65, 0, 0, 52, 67, 0, 0, 232, 65, 0, 0, 53, 67, 0, 0, 232, 65, 0, 0, 54, 67, 0, 0, 232, 65, 0, 0, 55, 67, 0, 0, 240, 65, 0, 0, 184, 66, 0, 0, 240, 65, 0, 0, 186, 66, 0, 0, 240, 65, 0, 0, 188, 66, 0, 0, 240, 65, 0, 0, 190, 66, 0, 0, 240, 65, 0, 0, 192, 66, 0, 0, 240, 65, 0, 0, 194, 66, 0, 0, 240, 65, 0, 0, 196, 66, 0, 0, 240, 65, 0, 0, 198, 66, 0, 0, 240, 65, 0, 0, 200, 66, 0, 0, 240, 65, 0, 0, 202, 66, 0, 0, 240, 65, 0, 0, 204, 66, 0, 0, 240, 65, 0, 0, 206, 66, 0, 0, 240, 65, 0, 0, 44, 67, 0, 0, 240, 65, 0, 0, 45, 67, 0, 0, 240, 65, 0, 0, 46, 67, 0, 0, 240, 65, 0, 0, 47, 67, 0, 0, 240, 65, 0, 0, 48, 67, 0, 0, 240, 65, 0, 0, 49, 67, 0, 0, 240, 65, 0, 0, 50, 67, 0, 0, 240, 65, 0, 0, 51, 67, 0, 0, 240, 65, 0, 0, 52, 67, 0, 0, 240, 65, 0, 0, 53, 67, 0, 0, 240, 65, 0, 0, 54, 67, 0, 0, 240, 65, 0, 0, 55, 67, 0, 0, 248, 65, 0, 0, 184, 66, 0, 0, 248, 65, 0, 0, 186, 66, 0, 0, 248, 65, 0, 0, 188, 66, 0, 0, 248, 65, 0, 0, 190, 66, 0, 0, 248, 65, 0, 0, 192, 66, 0, 0, 248, 65, 0, 0, 194, 66, 0, 0, 248, 65, 0, 0, 196, 66, 0, 0, 248, 65, 0, 0, 198, 66, 0, 0, 248, 65, 0, 0, 200, 66, 0, 0, 248, 65, 0, 0, 202, 66, 0, 0, 248, 65, 0, 0, 204, 66, 0, 0, 248, 65, 0, 0, 206, 66, 0, 0, 248, 65, 0, 0, 44, 67, 0, 0, 248, 65, 0, 0, 45, 67, 0, 0, 248, 65, 0, 0, 46, 67, 0, 0, 248, 65, 0, 0, 47, 67, 0, 0, 248, 65, 0, 0, 48, 67, 0, 0, 248, 65, 0, 0, 49, 67, 0, 0, 248, 65, 0, 0, 50, 67, 0, 0, 248, 65, 0, 0, 51, 67, 0, 0, 248, 65, 0, 0, 52, 67, 0, 0, 248, 65, 0, 0, 53, 67, 0, 0, 248, 65, 0, 0, 54, 67, 0, 0, 248, 65, 0, 0, 55, 67, 0, 0, 0, 66, 0, 0, 184, 66, 0, 0, 0, 66, 0, 0, 186, 66, 0, 0, 0, 66, 0, 0, 188, 66, 0, 0, 0, 66, 0, 0, 190, 66, 0, 0, 0, 66, 0, 0, 192, 66, 0, 0, 0, 66, 0, 0, 194, 66, 0, 0, 0, 66, 0, 0, 196, 66, 0, 0, 0, 66, 0, 0, 198, 66, 0, 0, 0, 66, 0, 0, 200, 66, 0, 0, 0, 66, 0, 0, 202, 66, 0, 0, 0, 66, 0, 0, 204, 66, 0, 0, 0, 66, 0, 0, 206, 66, 0, 0, 0, 66, 0, 0, 44, 67, 0, 0, 0, 66, 0, 0, 45, 67, 0, 0, 0, 66, 0, 0, 46, 67, 0, 0, 0, 66, 0, 0, 47, 67, 0, 0, 0, 66, 0, 0, 48, 67, 0, 0, 0, 66, 0, 0, 49, 67, 0, 0, 0, 66, 0, 0, 50, 67, 0, 0, 0, 66, 0, 0, 51, 67, 0, 0, 0, 66, 0, 0, 52, 67, 0, 0, 0, 66, 0, 0, 53, 67, 0, 0, 0, 66, 0, 0, 54, 67, 0, 0, 0, 66, 0, 0, 55, 67, 0, 0, 4, 66, 0, 0, 184, 66, 0, 0, 4, 66, 0, 0, 186, 66, 0, 0, 4, 66, 0, 0, 188, 66, 0, 0, 4, 66, 0, 0, 190, 66, 0, 0, 4, 66, 0, 0, 192, 66, 0, 0, 4, 66, 0, 0, 194, 66, 0, 0, 4, 66, 0, 0, 196, 66, 0, 0, 4, 66, 0, 0, 198, 66, 0, 0, 4, 66, 0, 0, 200, 66, 0, 0, 4, 66, 0, 0, 202, 66, 0, 0, 4, 66, 0, 0, 204, 66, 0, 0, 4, 66, 0, 0, 206, 66, 0, 0, 4, 66, 0, 0, 44, 67, 0, 0, 4, 66, 0, 0, 45, 67, 0, 0, 4, 66, 0, 0, 46, 67, 0, 0, 4, 66, 0, 0, 47, 67, 0, 0, 4, 66, 0, 0, 48, 67, 0, 0, 4, 66, 0, 0, 49, 67, 0, 0, 4, 66, 0, 0, 50, 67, 0, 0, 4, 66, 0, 0, 51, 67, 0, 0, 4, 66, 0, 0, 52, 67, 0, 0, 4, 66, 0, 0, 53, 67, 0, 0, 4, 66, 0, 0, 54, 67, 0, 0, 4, 66, 0, 0, 55, 67, 0, 0, 8, 66, 0, 0, 184, 66, 0, 0, 8, 66, 0, 0, 186, 66, 0, 0, 8, 66, 0, 0, 188, 66, 0, 0, 8, 66, 0, 0, 190, 66, 0, 0, 8, 66, 0, 0, 192, 66, 0, 0, 8, 66, 0, 0, 194, 66, 0, 0, 8, 66, 0, 0, 196, 66, 0, 0, 8, 66, 0, 0, 198, 66, 0, 0, 8, 66, 0, 0, 200, 66, 0, 0, 8, 66, 0, 0, 202, 66, 0, 0, 8, 66, 0, 0, 204, 66, 0, 0, 8, 66, 0, 0, 206, 66, 0, 0, 8, 66, 0, 0, 208, 66, 0, 0, 8, 66, 0, 0, 43, 67, 0, 0, 8, 66, 0, 0, 44, 67, 0, 0, 8, 66, 0, 0, 45, 67, 0, 0, 8, 66, 0, 0, 46, 67, 0, 0, 8, 66, 0, 0, 47, 67, 0, 0, 8, 66, 0, 0, 48, 67, 0, 0, 8, 66, 0, 0, 49, 67, 0, 0, 8, 66, 0, 0, 50, 67, 0, 0, 8, 66, 0, 0, 51, 67, 0, 0, 8, 66, 0, 0, 52, 67, 0, 0, 8, 66, 0, 0, 53, 67, 0, 0, 8, 66, 0, 0, 54, 67, 0, 0, 8, 66, 0, 0, 55, 67, 0, 0, 12, 66, 0, 0, 184, 66, 0, 0, 12, 66, 0, 0, 186, 66, 0, 0, 12, 66, 0, 0, 188, 66, 0, 0, 12, 66, 0, 0, 190, 66, 0, 0, 12, 66, 0, 0, 192, 66, 0, 0, 12, 66, 0, 0, 194, 66, 0, 0, 12, 66, 0, 0, 196, 66, 0, 0, 12, 66, 0, 0, 198, 66, 0, 0, 12, 66, 0, 0, 200, 66, 0, 0, 12, 66, 0, 0, 202, 66, 0, 0, 12, 66, 0, 0, 204, 66, 0, 0, 12, 66, 0, 0, 206, 66, 0, 0, 12, 66, 0, 0, 208, 66, 0, 0, 12, 66, 0, 0, 210, 66, 0, 0, 12, 66, 0, 0, 43, 67, 0, 0, 12, 66, 0, 0, 44, 67, 0, 0, 12, 66, 0, 0, 45, 67, 0, 0, 12, 66, 0, 0, 46, 67, 0, 0, 12, 66, 0, 0, 47, 67, 0, 0, 12, 66, 0, 0, 48, 67, 0, 0, 12, 66, 0, 0, 49, 67, 0, 0, 12, 66, 0, 0, 50, 67, 0, 0, 12, 66, 0, 0, 51, 67, 0, 0, 12, 66, 0, 0, 52, 67, 0, 0, 12, 66, 0, 0, 53, 67, 0, 0, 12, 66, 0, 0, 54, 67, 0, 0, 12, 66, 0, 0, 55, 67, 0, 0, 16, 66, 0, 0, 184, 66, 0, 0, 16, 66, 0, 0, 186, 66, 0, 0, 16, 66, 0, 0, 188, 66, 0, 0, 16, 66, 0, 0, 190, 66, 0, 0, 16, 66, 0, 0, 192, 66, 0, 0, 16, 66, 0, 0, 194, 66, 0, 0, 16, 66, 0, 0, 196, 66, 0, 0, 16, 66, 0, 0, 198, 66, 0, 0, 16, 66, 0, 0, 200, 66, 0, 0, 16, 66, 0, 0, 202, 66, 0, 0, 16, 66, 0, 0, 204, 66, 0, 0, 16, 66, 0, 0, 206, 66, 0, 0, 16, 66, 0, 0, 208, 66, 0, 0, 16, 66, 0, 0, 210, 66, 0, 0, 16, 66, 0, 0, 212, 66, 0, 0, 16, 66, 0, 0, 41, 67, 0, 0, 16, 66, 0, 0, 42, 67, 0, 0, 16, 66, 0, 0, 43, 67, 0, 0, 16, 66, 0, 0, 44, 67, 0, 0, 16, 66, 0, 0, 45, 67, 0, 0, 16, 66, 0, 0, 46, 67, 0, 0, 16, 66, 0, 0, 47, 67, 0, 0, 16, 66, 0, 0, 48, 67, 0, 0, 16, 66, 0, 0, 49, 67, 0, 0, 16, 66, 0, 0, 50, 67, 0, 0, 16, 66, 0, 0, 51, 67, 0, 0, 16, 66, 0, 0, 52, 67, 0, 0, 16, 66, 0, 0, 53, 67, 0, 0, 16, 66, 0, 0, 54, 67, 0, 0, 16, 66, 0, 0, 55, 67, 0, 0, 20, 66, 0, 0, 184, 66, 0, 0, 20, 66, 0, 0, 186, 66, 0, 0, 20, 66, 0, 0, 188, 66, 0, 0, 20, 66, 0, 0, 190, 66, 0, 0, 20, 66, 0, 0, 192, 66, 0, 0, 20, 66, 0, 0, 194, 66, 0, 0, 20, 66, 0, 0, 196, 66, 0, 0, 20, 66, 0, 0, 198, 66, 0, 0, 20, 66, 0, 0, 200, 66, 0, 0, 20, 66, 0, 0, 202, 66, 0, 0, 20, 66, 0, 0, 204, 66, 0, 0, 20, 66, 0, 0, 206, 66, 0, 0, 20, 66, 0, 0, 208, 66, 0, 0, 20, 66, 0, 0, 210, 66, 0, 0, 20, 66, 0, 0, 212, 66, 0, 0, 20, 66, 0, 0, 214, 66, 0, 0, 20, 66, 0, 0, 216, 66, 0, 0, 20, 66, 0, 0, 40, 67, 0, 0, 20, 66, 0, 0, 41, 67, 0, 0, 20, 66, 0, 0, 42, 67, 0, 0, 20, 66, 0, 0, 43, 67, 0, 0, 20, 66, 0, 0, 44, 67, 0, 0, 20, 66, 0, 0, 45, 67, 0, 0, 20, 66, 0, 0, 46, 67, 0, 0, 20, 66, 0, 0, 47, 67, 0, 0, 20, 66, 0, 0, 48, 67, 0, 0, 20, 66, 0, 0, 49, 67, 0, 0, 20, 66, 0, 0, 50, 67, 0, 0, 20, 66, 0, 0, 51, 67, 0, 0, 20, 66, 0, 0, 52, 67, 0, 0, 20, 66, 0, 0, 53, 67, 0, 0, 20, 66, 0, 0, 54, 67, 0, 0, 20, 66, 0, 0, 55, 67, 0, 0, 24, 66, 0, 0, 184, 66, 0, 0, 24, 66, 0, 0, 186, 66, 0, 0, 24, 66, 0, 0, 188, 66, 0, 0, 24, 66, 0, 0, 190, 66, 0, 0, 24, 66, 0, 0, 192, 66, 0, 0, 24, 66, 0, 0, 194, 66, 0, 0, 24, 66, 0, 0, 196, 66, 0, 0, 24, 66, 0, 0, 198, 66, 0, 0, 24, 66, 0, 0, 200, 66, 0, 0, 24, 66, 0, 0, 202, 66, 0, 0, 24, 66, 0, 0, 204, 66, 0, 0, 24, 66, 0, 0, 206, 66, 0, 0, 24, 66, 0, 0, 208, 66, 0, 0, 24, 66, 0, 0, 210, 66, 0, 0, 24, 66, 0, 0, 212, 66, 0, 0, 24, 66, 0, 0, 214, 66, 0, 0, 24, 66, 0, 0, 216, 66, 0, 0, 24, 66, 0, 0, 218, 66, 0, 0, 24, 66, 0, 0, 220, 66, 0, 0, 24, 66, 0, 0, 222, 66, 0, 0, 24, 66, 0, 0, 224, 66, 0, 0, 24, 66, 0, 0, 226, 66, 0, 0, 24, 66, 0, 0, 228, 66, 0, 0, 24, 66, 0, 0, 230, 66, 0, 0, 24, 66, 0, 0, 232, 66, 0, 0, 24, 66, 0, 0, 234, 66, 0, 0, 24, 66, 0, 0, 236, 66, 0, 0, 24, 66, 0, 0, 238, 66, 0, 0, 24, 66, 0, 0, 240, 66, 0, 0, 24, 66, 0, 0, 242, 66, 0, 0, 24, 66, 0, 0, 244, 66, 0, 0, 24, 66, 0, 0, 246, 66, 0, 0, 24, 66, 0, 0, 248, 66, 0, 0, 24, 66, 0, 0, 250, 66, 0, 0, 24, 66, 0, 0, 252, 66, 0, 0, 24, 66, 0, 0, 254, 66, 0, 0, 24, 66, 0, 0, 0, 67, 0, 0, 24, 66, 0, 0, 1, 67, 0, 0, 24, 66, 0, 0, 2, 67, 0, 0, 24, 66, 0, 0, 3, 67, 0, 0, 24, 66, 0, 0, 4, 67, 0, 0, 24, 66, 0, 0, 5, 67, 0, 0, 24, 66, 0, 0, 6, 67, 0, 0, 24, 66, 0, 0, 7, 67, 0, 0, 24, 66, 0, 0, 8, 67, 0, 0, 24, 66, 0, 0, 9, 67, 0, 0, 24, 66, 0, 0, 10, 67, 0, 0, 24, 66, 0, 0, 11, 67, 0, 0, 24, 66, 0, 0, 12, 67, 0, 0, 24, 66, 0, 0, 13, 67, 0, 0, 24, 66, 0, 0, 14, 67, 0, 0, 24, 66, 0, 0, 15, 67, 0, 0, 24, 66, 0, 0, 16, 67, 0, 0, 24, 66, 0, 0, 17, 67, 0, 0, 24, 66, 0, 0, 18, 67, 0, 0, 24, 66, 0, 0, 19, 67, 0, 0, 24, 66, 0, 0, 20, 67, 0, 0, 24, 66, 0, 0, 21, 67, 0, 0, 24, 66, 0, 0, 22, 67, 0, 0, 24, 66, 0, 0, 23, 67, 0, 0, 24, 66, 0, 0, 24, 67, 0, 0, 24, 66, 0, 0, 25, 67, 0, 0, 24, 66, 0, 0, 26, 67, 0, 0, 24, 66, 0, 0, 27, 67, 0, 0, 24, 66, 0, 0, 28, 67, 0, 0, 24, 66, 0, 0, 29, 67, 0, 0, 24, 66, 0, 0, 30, 67, 0, 0, 24, 66, 0, 0, 31, 67, 0, 0, 24, 66, 0, 0, 32, 67, 0, 0, 24, 66, 0, 0, 33, 67, 0, 0, 24, 66, 0, 0, 34, 67, 0, 0, 24, 66, 0, 0, 35, 67, 0, 0, 24, 66, 0, 0, 36, 67, 0, 0, 24, 66, 0, 0, 37, 67, 0, 0, 24, 66, 0, 0, 38, 67, 0, 0, 24, 66, 0, 0, 39, 67, 0, 0, 24, 66, 0, 0, 40, 67, 0, 0, 24, 66, 0, 0, 41, 67, 0, 0, 24, 66, 0, 0, 42, 67, 0, 0, 24, 66, 0, 0, 43, 67, 0, 0, 24, 66, 0, 0, 44, 67, 0, 0, 24, 66, 0, 0, 45, 67, 0, 0, 24, 66, 0, 0, 46, 67, 0, 0, 24, 66, 0, 0, 47, 67, 0, 0, 24, 66, 0, 0, 48, 67, 0, 0, 24, 66, 0, 0, 49, 67, 0, 0, 24, 66, 0, 0, 50, 67, 0, 0, 24, 66, 0, 0, 51, 67, 0, 0, 24, 66, 0, 0, 52, 67, 0, 0, 24, 66, 0, 0, 53, 67, 0, 0, 24, 66, 0, 0, 54, 67, 0, 0, 24, 66, 0, 0, 55, 67, 0, 0, 28, 66, 0, 0, 184, 66, 0, 0, 28, 66, 0, 0, 186, 66, 0, 0, 28, 66, 0, 0, 188, 66, 0, 0, 28, 66, 0, 0, 190, 66, 0, 0, 28, 66, 0, 0, 192, 66, 0, 0, 28, 66, 0, 0, 194, 66, 0, 0, 28, 66, 0, 0, 196, 66, 0, 0, 28, 66, 0, 0, 198, 66, 0, 0, 28, 66, 0, 0, 200, 66, 0, 0, 28, 66, 0, 0, 202, 66, 0, 0, 28, 66, 0, 0, 204, 66, 0, 0, 28, 66, 0, 0, 206, 66, 0, 0, 28, 66, 0, 0, 208, 66, 0, 0, 28, 66, 0, 0, 210, 66, 0, 0, 28, 66, 0, 0, 212, 66, 0, 0, 28, 66, 0, 0, 214, 66, 0, 0, 28, 66, 0, 0, 216, 66, 0, 0, 28, 66, 0, 0, 218, 66, 0, 0, 28, 66, 0, 0, 220, 66, 0, 0, 28, 66, 0, 0, 222, 66, 0, 0, 28, 66, 0, 0, 224, 66, 0, 0, 28, 66, 0, 0, 226, 66, 0, 0, 28, 66, 0, 0, 228, 66, 0, 0, 28, 66, 0, 0, 230, 66, 0, 0, 28, 66, 0, 0, 232, 66, 0, 0, 28, 66, 0, 0, 234, 66, 0, 0, 28, 66, 0, 0, 236, 66, 0, 0, 28, 66, 0, 0, 238, 66, 0, 0, 28, 66, 0, 0, 240, 66, 0, 0, 28, 66, 0, 0, 242, 66, 0, 0, 28, 66, 0, 0, 244, 66, 0, 0, 28, 66, 0, 0, 246, 66, 0, 0, 28, 66, 0, 0, 248, 66, 0, 0, 28, 66, 0, 0, 250, 66, 0, 0, 28, 66, 0, 0, 252, 66, 0, 0, 28, 66, 0, 0, 254, 66, 0, 0, 28, 66, 0, 0, 0, 67, 0, 0, 28, 66, 0, 0, 1, 67, 0, 0, 28, 66, 0, 0, 2, 67, 0, 0, 28, 66, 0, 0, 3, 67, 0, 0, 28, 66, 0, 0, 4, 67, 0, 0, 28, 66, 0, 0, 5, 67, 0, 0, 28, 66, 0, 0, 6, 67, 0, 0, 28, 66, 0, 0, 7, 67, 0, 0, 28, 66, 0, 0, 8, 67, 0, 0, 28, 66, 0, 0, 9, 67, 0, 0, 28, 66, 0, 0, 10, 67, 0, 0, 28, 66, 0, 0, 11, 67, 0, 0, 28, 66, 0, 0, 12, 67, 0, 0, 28, 66, 0, 0, 13, 67, 0, 0, 28, 66, 0, 0, 14, 67, 0, 0, 28, 66, 0, 0, 15, 67, 0, 0, 28, 66, 0, 0, 16, 67, 0, 0, 28, 66, 0, 0, 17, 67, 0, 0, 28, 66, 0, 0, 18, 67, 0, 0, 28, 66, 0, 0, 19, 67, 0, 0, 28, 66, 0, 0, 20, 67, 0, 0, 28, 66, 0, 0, 21, 67, 0, 0, 28, 66, 0, 0, 22, 67, 0, 0, 28, 66, 0, 0, 23, 67, 0, 0, 28, 66, 0, 0, 24, 67, 0, 0, 28, 66, 0, 0, 25, 67, 0, 0, 28, 66, 0, 0, 26, 67, 0, 0, 28, 66, 0, 0, 27, 67, 0, 0, 28, 66, 0, 0, 28, 67, 0, 0, 28, 66, 0, 0, 29, 67, 0, 0, 28, 66, 0, 0, 30, 67, 0, 0, 28, 66, 0, 0, 31, 67, 0, 0, 28, 66, 0, 0, 32, 67, 0, 0, 28, 66, 0, 0, 33, 67, 0, 0, 28, 66, 0, 0, 34, 67, 0, 0, 28, 66, 0, 0, 35, 67, 0, 0, 28, 66, 0, 0, 36, 67, 0, 0, 28, 66, 0, 0, 37, 67, 0, 0, 28, 66, 0, 0, 38, 67, 0, 0, 28, 66, 0, 0, 39, 67, 0, 0, 28, 66, 0, 0, 40, 67, 0, 0, 28, 66, 0, 0, 41, 67, 0, 0, 28, 66, 0, 0, 42, 67, 0, 0, 28, 66, 0, 0, 43, 67, 0, 0, 28, 66, 0, 0, 44, 67, 0, 0, 28, 66, 0, 0, 45, 67, 0, 0, 28, 66, 0, 0, 46, 67, 0, 0, 28, 66, 0, 0, 47, 67, 0, 0, 28, 66, 0, 0, 48, 67, 0, 0, 28, 66, 0, 0, 49, 67, 0, 0, 28, 66, 0, 0, 50, 67, 0, 0, 28, 66, 0, 0, 51, 67, 0, 0, 28, 66, 0, 0, 52, 67, 0, 0, 28, 66, 0, 0, 53, 67, 0, 0, 28, 66, 0, 0, 54, 67, 0, 0, 28, 66, 0, 0, 55, 67, 0, 0, 32, 66, 0, 0, 184, 66, 0, 0, 32, 66, 0, 0, 186, 66, 0, 0, 32, 66, 0, 0, 188, 66, 0, 0, 32, 66, 0, 0, 190, 66, 0, 0, 32, 66, 0, 0, 192, 66, 0, 0, 32, 66, 0, 0, 194, 66, 0, 0, 32, 66, 0, 0, 196, 66, 0, 0, 32, 66, 0, 0, 198, 66, 0, 0, 32, 66, 0, 0, 200, 66, 0, 0, 32, 66, 0, 0, 202, 66, 0, 0, 32, 66, 0, 0, 204, 66, 0, 0, 32, 66, 0, 0, 206, 66, 0, 0, 32, 66, 0, 0, 208, 66, 0, 0, 32, 66, 0, 0, 210, 66, 0, 0, 32, 66, 0, 0, 212, 66, 0, 0, 32, 66, 0, 0, 214, 66, 0, 0, 32, 66, 0, 0, 216, 66, 0, 0, 32, 66, 0, 0, 218, 66, 0, 0, 32, 66, 0, 0, 220, 66, 0, 0, 32, 66, 0, 0, 222, 66, 0, 0, 32, 66, 0, 0, 224, 66, 0, 0, 32, 66, 0, 0, 226, 66, 0, 0, 32, 66, 0, 0, 228, 66, 0, 0, 32, 66, 0, 0, 230, 66, 0, 0, 32, 66, 0, 0, 232, 66, 0, 0, 32, 66, 0, 0, 234, 66, 0, 0, 32, 66, 0, 0, 236, 66, 0, 0, 32, 66, 0, 0, 238, 66, 0, 0, 32, 66, 0, 0, 240, 66, 0, 0, 32, 66, 0, 0, 242, 66, 0, 0, 32, 66, 0, 0, 244, 66, 0, 0, 32, 66, 0, 0, 246, 66, 0, 0, 32, 66, 0, 0, 248, 66, 0, 0, 32, 66, 0, 0, 250, 66, 0, 0, 32, 66, 0, 0, 252, 66, 0, 0, 32, 66, 0, 0, 254, 66, 0, 0, 32, 66, 0, 0, 0, 67, 0, 0, 32, 66, 0, 0, 1, 67, 0, 0, 32, 66, 0, 0, 2, 67, 0, 0, 32, 66, 0, 0, 3, 67, 0, 0, 32, 66, 0, 0, 4, 67, 0, 0, 32, 66, 0, 0, 5, 67, 0, 0, 32, 66, 0, 0, 6, 67, 0, 0, 32, 66, 0, 0, 7, 67, 0, 0, 32, 66, 0, 0, 8, 67, 0, 0, 32, 66, 0, 0, 9, 67, 0, 0, 32, 66, 0, 0, 10, 67, 0, 0, 32, 66, 0, 0, 11, 67, 0, 0, 32, 66, 0, 0, 12, 67, 0, 0, 32, 66, 0, 0, 13, 67, 0, 0, 32, 66, 0, 0, 14, 67, 0, 0, 32, 66, 0, 0, 15, 67, 0, 0, 32, 66, 0, 0, 16, 67, 0, 0, 32, 66, 0, 0, 17, 67, 0, 0, 32, 66, 0, 0, 18, 67, 0, 0, 32, 66, 0, 0, 19, 67, 0, 0, 32, 66, 0, 0, 20, 67, 0, 0, 32, 66, 0, 0, 21, 67, 0, 0, 32, 66, 0, 0, 22, 67, 0, 0, 32, 66, 0, 0, 23, 67, 0, 0, 32, 66, 0, 0, 24, 67, 0, 0, 32, 66, 0, 0, 25, 67, 0, 0, 32, 66, 0, 0, 26, 67, 0, 0, 32, 66, 0, 0, 27, 67, 0, 0, 32, 66, 0, 0, 28, 67, 0, 0, 32, 66, 0, 0, 29, 67, 0, 0, 32, 66, 0, 0, 30, 67, 0, 0, 32, 66, 0, 0, 31, 67, 0, 0, 32, 66, 0, 0, 32, 67, 0, 0, 32, 66, 0, 0, 33, 67, 0, 0, 32, 66, 0, 0, 34, 67, 0, 0, 32, 66, 0, 0, 35, 67, 0, 0, 32, 66, 0, 0, 36, 67, 0, 0, 32, 66, 0, 0, 37, 67, 0, 0, 32, 66, 0, 0, 38, 67, 0, 0, 32, 66, 0, 0, 39, 67, 0, 0, 32, 66, 0, 0, 40, 67, 0, 0, 32, 66, 0, 0, 41, 67, 0, 0, 32, 66, 0, 0, 42, 67, 0, 0, 32, 66, 0, 0, 43, 67, 0, 0, 32, 66, 0, 0, 44, 67, 0, 0, 32, 66, 0, 0, 45, 67, 0, 0, 32, 66, 0, 0, 46, 67, 0, 0, 32, 66, 0, 0, 47, 67, 0, 0, 32, 66, 0, 0, 48, 67, 0, 0, 32, 66, 0, 0, 49, 67, 0, 0, 32, 66, 0, 0, 50, 67, 0, 0, 32, 66, 0, 0, 51, 67, 0, 0, 32, 66, 0, 0, 52, 67, 0, 0, 32, 66, 0, 0, 53, 67, 0, 0, 32, 66, 0, 0, 54, 67, 0, 0, 32, 66, 0, 0, 55, 67, 0, 0, 36, 66, 0, 0, 184, 66, 0, 0, 36, 66, 0, 0, 186, 66, 0, 0, 36, 66, 0, 0, 188, 66, 0, 0, 36, 66, 0, 0, 190, 66, 0, 0, 36, 66, 0, 0, 192, 66, 0, 0, 36, 66, 0, 0, 194, 66, 0, 0, 36, 66, 0, 0, 196, 66, 0, 0, 36, 66, 0, 0, 198, 66, 0, 0, 36, 66, 0, 0, 200, 66, 0, 0, 36, 66, 0, 0, 202, 66, 0, 0, 36, 66, 0, 0, 204, 66, 0, 0, 36, 66, 0, 0, 206, 66, 0, 0, 36, 66, 0, 0, 208, 66, 0, 0, 36, 66, 0, 0, 210, 66, 0, 0, 36, 66, 0, 0, 212, 66, 0, 0, 36, 66, 0, 0, 214, 66, 0, 0, 36, 66, 0, 0, 216, 66, 0, 0, 36, 66, 0, 0, 218, 66, 0, 0, 36, 66, 0, 0, 220, 66, 0, 0, 36, 66, 0, 0, 222, 66, 0, 0, 36, 66, 0, 0, 224, 66, 0, 0, 36, 66, 0, 0, 226, 66, 0, 0, 36, 66, 0, 0, 228, 66, 0, 0, 36, 66, 0, 0, 230, 66, 0, 0, 36, 66, 0, 0, 232, 66, 0, 0, 36, 66, 0, 0, 234, 66, 0, 0, 36, 66, 0, 0, 236, 66, 0, 0, 36, 66, 0, 0, 238, 66, 0, 0, 36, 66, 0, 0, 240, 66, 0, 0, 36, 66, 0, 0, 242, 66, 0, 0, 36, 66, 0, 0, 244, 66, 0, 0, 36, 66, 0, 0, 246, 66, 0, 0, 36, 66, 0, 0, 248, 66, 0, 0, 36, 66, 0, 0, 250, 66, 0, 0, 36, 66, 0, 0, 252, 66, 0, 0, 36, 66, 0, 0, 254, 66, 0, 0, 36, 66, 0, 0, 0, 67, 0, 0, 36, 66, 0, 0, 1, 67, 0, 0, 36, 66, 0, 0, 2, 67, 0, 0, 36, 66, 0, 0, 3, 67, 0, 0, 36, 66, 0, 0, 4, 67, 0, 0, 36, 66, 0, 0, 5, 67, 0, 0, 36, 66, 0, 0, 6, 67, 0, 0, 36, 66, 0, 0, 7, 67, 0, 0, 36, 66, 0, 0, 8, 67, 0, 0, 36, 66, 0, 0, 9, 67, 0, 0, 36, 66, 0, 0, 10, 67, 0, 0, 36, 66, 0, 0, 11, 67, 0, 0, 36, 66, 0, 0, 12, 67, 0, 0, 36, 66, 0, 0, 13, 67, 0, 0, 36, 66, 0, 0, 14, 67, 0, 0, 36, 66, 0, 0, 15, 67, 0, 0, 36, 66, 0, 0, 16, 67, 0, 0, 36, 66, 0, 0, 17, 67, 0, 0, 36, 66, 0, 0, 18, 67, 0, 0, 36, 66, 0, 0, 19, 67, 0, 0, 36, 66, 0, 0, 20, 67, 0, 0, 36, 66, 0, 0, 21, 67, 0, 0, 36, 66, 0, 0, 22, 67, 0, 0, 36, 66, 0, 0, 23, 67, 0, 0, 36, 66, 0, 0, 24, 67, 0, 0, 36, 66, 0, 0, 25, 67, 0, 0, 36, 66, 0, 0, 26, 67, 0, 0, 36, 66, 0, 0, 27, 67, 0, 0, 36, 66, 0, 0, 28, 67, 0, 0, 36, 66, 0, 0, 29, 67, 0, 0, 36, 66, 0, 0, 30, 67, 0, 0, 36, 66, 0, 0, 31, 67, 0, 0, 36, 66, 0, 0, 32, 67, 0, 0, 36, 66, 0, 0, 33, 67, 0, 0, 36, 66, 0, 0, 34, 67, 0, 0, 36, 66, 0, 0, 35, 67, 0, 0, 36, 66, 0, 0, 36, 67, 0, 0, 36, 66, 0, 0, 37, 67, 0, 0, 36, 66, 0, 0, 38, 67, 0, 0, 36, 66, 0, 0, 39, 67, 0, 0, 36, 66, 0, 0, 40, 67, 0, 0, 36, 66, 0, 0, 41, 67, 0, 0, 36, 66, 0, 0, 42, 67, 0, 0, 36, 66, 0, 0, 43, 67, 0, 0, 36, 66, 0, 0, 44, 67, 0, 0, 36, 66, 0, 0, 45, 67, 0, 0, 36, 66, 0, 0, 46, 67, 0, 0, 36, 66, 0, 0, 47, 67, 0, 0, 36, 66, 0, 0, 48, 67, 0, 0, 36, 66, 0, 0, 49, 67, 0, 0, 36, 66, 0, 0, 50, 67, 0, 0, 36, 66, 0, 0, 51, 67, 0, 0, 36, 66, 0, 0, 52, 67, 0, 0, 36, 66, 0, 0, 53, 67, 0, 0, 36, 66, 0, 0, 54, 67, 0, 0, 36, 66, 0, 0, 55, 67, 0, 0, 40, 66, 0, 0, 184, 66, 0, 0, 40, 66, 0, 0, 186, 66, 0, 0, 40, 66, 0, 0, 188, 66, 0, 0, 40, 66, 0, 0, 190, 66, 0, 0, 40, 66, 0, 0, 192, 66, 0, 0, 40, 66, 0, 0, 194, 66, 0, 0, 40, 66, 0, 0, 196, 66, 0, 0, 40, 66, 0, 0, 198, 66, 0, 0, 40, 66, 0, 0, 200, 66, 0, 0, 40, 66, 0, 0, 202, 66, 0, 0, 40, 66, 0, 0, 204, 66, 0, 0, 40, 66, 0, 0, 206, 66, 0, 0, 40, 66, 0, 0, 208, 66, 0, 0, 40, 66, 0, 0, 210, 66, 0, 0, 40, 66, 0, 0, 212, 66, 0, 0, 40, 66, 0, 0, 214, 66, 0, 0, 40, 66, 0, 0, 216, 66, 0, 0, 40, 66, 0, 0, 218, 66, 0, 0, 40, 66, 0, 0, 220, 66, 0, 0, 40, 66, 0, 0, 222, 66, 0, 0, 40, 66, 0, 0, 224, 66, 0, 0, 40, 66, 0, 0, 226, 66, 0, 0, 40, 66, 0, 0, 228, 66, 0, 0, 40, 66, 0, 0, 230, 66, 0, 0, 40, 66, 0, 0, 232, 66, 0, 0, 40, 66, 0, 0, 234, 66, 0, 0, 40, 66, 0, 0, 236, 66, 0, 0, 40, 66, 0, 0, 238, 66, 0, 0, 40, 66, 0, 0, 240, 66, 0, 0, 40, 66, 0, 0, 242, 66, 0, 0, 40, 66, 0, 0, 244, 66, 0, 0, 40, 66, 0, 0, 246, 66, 0, 0, 40, 66, 0, 0, 248, 66, 0, 0, 40, 66, 0, 0, 250, 66, 0, 0, 40, 66, 0, 0, 252, 66, 0, 0, 40, 66, 0, 0, 254, 66, 0, 0, 40, 66, 0, 0, 0, 67, 0, 0, 40, 66, 0, 0, 1, 67, 0, 0, 40, 66, 0, 0, 2, 67, 0, 0, 40, 66, 0, 0, 3, 67, 0, 0, 40, 66, 0, 0, 4, 67, 0, 0, 40, 66, 0, 0, 5, 67, 0, 0, 40, 66, 0, 0, 6, 67, 0, 0, 40, 66, 0, 0, 7, 67, 0, 0, 40, 66, 0, 0, 8, 67, 0, 0, 40, 66, 0, 0, 9, 67, 0, 0, 40, 66, 0, 0, 10, 67, 0, 0, 40, 66, 0, 0, 11, 67, 0, 0, 40, 66, 0, 0, 12, 67, 0, 0, 40, 66, 0, 0, 13, 67, 0, 0, 40, 66, 0, 0, 14, 67, 0, 0, 40, 66, 0, 0, 15, 67, 0, 0, 40, 66, 0, 0, 16, 67, 0, 0, 40, 66, 0, 0, 17, 67, 0, 0, 40, 66, 0, 0, 18, 67, 0, 0, 40, 66, 0, 0, 19, 67, 0, 0, 40, 66, 0, 0, 20, 67, 0, 0, 40, 66, 0, 0, 21, 67, 0, 0, 40, 66, 0, 0, 22, 67, 0, 0, 40, 66, 0, 0, 23, 67, 0, 0, 40, 66, 0, 0, 24, 67, 0, 0, 40, 66, 0, 0, 25, 67, 0, 0, 40, 66, 0, 0, 26, 67, 0, 0, 40, 66, 0, 0, 27, 67, 0, 0, 40, 66, 0, 0, 28, 67, 0, 0, 40, 66, 0, 0, 29, 67, 0, 0, 40, 66, 0, 0, 30, 67, 0, 0, 40, 66, 0, 0, 31, 67, 0, 0, 40, 66, 0, 0, 32, 67, 0, 0, 40, 66, 0, 0, 33, 67, 0, 0, 40, 66, 0, 0, 34, 67, 0, 0, 40, 66, 0, 0, 35, 67, 0, 0, 40, 66, 0, 0, 36, 67, 0, 0, 40, 66, 0, 0, 37, 67, 0, 0, 40, 66, 0, 0, 38, 67, 0, 0, 40, 66, 0, 0, 39, 67, 0, 0, 40, 66, 0, 0, 40, 67, 0, 0, 40, 66, 0, 0, 41, 67, 0, 0, 40, 66, 0, 0, 42, 67, 0, 0, 40, 66, 0, 0, 43, 67, 0, 0, 40, 66, 0, 0, 44, 67, 0, 0, 40, 66, 0, 0, 45, 67, 0, 0, 40, 66, 0, 0, 46, 67, 0, 0, 40, 66, 0, 0, 47, 67, 0, 0, 40, 66, 0, 0, 48, 67, 0, 0, 40, 66, 0, 0, 49, 67, 0, 0, 40, 66, 0, 0, 50, 67, 0, 0, 40, 66, 0, 0, 51, 67, 0, 0, 40, 66, 0, 0, 52, 67, 0, 0, 40, 66, 0, 0, 53, 67, 0, 0, 40, 66, 0, 0, 54, 67, 0, 0, 40, 66, 0, 0, 55, 67, 0, 0, 44, 66, 0, 0, 184, 66, 0, 0, 44, 66, 0, 0, 186, 66, 0, 0, 44, 66, 0, 0, 188, 66, 0, 0, 44, 66, 0, 0, 190, 66, 0, 0, 44, 66, 0, 0, 192, 66, 0, 0, 44, 66, 0, 0, 194, 66, 0, 0, 44, 66, 0, 0, 196, 66, 0, 0, 44, 66, 0, 0, 198, 66, 0, 0, 44, 66, 0, 0, 200, 66, 0, 0, 44, 66, 0, 0, 202, 66, 0, 0, 44, 66, 0, 0, 204, 66, 0, 0, 44, 66, 0, 0, 206, 66, 0, 0, 44, 66, 0, 0, 208, 66, 0, 0, 44, 66, 0, 0, 210, 66, 0, 0, 44, 66, 0, 0, 212, 66, 0, 0, 44, 66, 0, 0, 214, 66, 0, 0, 44, 66, 0, 0, 216, 66, 0, 0, 44, 66, 0, 0, 218, 66, 0, 0, 44, 66, 0, 0, 220, 66, 0, 0, 44, 66, 0, 0, 222, 66, 0, 0, 44, 66, 0, 0, 224, 66, 0, 0, 44, 66, 0, 0, 226, 66, 0, 0, 44, 66, 0, 0, 228, 66, 0, 0, 44, 66, 0, 0, 230, 66, 0, 0, 44, 66, 0, 0, 232, 66, 0, 0, 44, 66, 0, 0, 234, 66, 0, 0, 44, 66, 0, 0, 236, 66, 0, 0, 44, 66, 0, 0, 238, 66, 0, 0, 44, 66, 0, 0, 240, 66, 0, 0, 44, 66, 0, 0, 242, 66, 0, 0, 44, 66, 0, 0, 244, 66, 0, 0, 44, 66, 0, 0, 246, 66, 0, 0, 44, 66, 0, 0, 248, 66, 0, 0, 44, 66, 0, 0, 250, 66, 0, 0, 44, 66, 0, 0, 252, 66, 0, 0, 44, 66, 0, 0, 254, 66, 0, 0, 44, 66, 0, 0, 0, 67, 0, 0, 44, 66, 0, 0, 1, 67, 0, 0, 44, 66, 0, 0, 2, 67, 0, 0, 44, 66, 0, 0, 3, 67, 0, 0, 44, 66, 0, 0, 4, 67, 0, 0, 44, 66, 0, 0, 5, 67, 0, 0, 44, 66, 0, 0, 6, 67, 0, 0, 44, 66, 0, 0, 7, 67, 0, 0, 44, 66, 0, 0, 8, 67, 0, 0, 44, 66, 0, 0, 9, 67, 0, 0, 44, 66, 0, 0, 10, 67, 0, 0, 44, 66, 0, 0, 11, 67, 0, 0, 44, 66, 0, 0, 12, 67, 0, 0, 44, 66, 0, 0, 13, 67, 0, 0, 44, 66, 0, 0, 14, 67, 0, 0, 44, 66, 0, 0, 15, 67, 0, 0, 44, 66, 0, 0, 16, 67, 0, 0, 44, 66, 0, 0, 17, 67, 0, 0, 44, 66, 0, 0, 18, 67, 0, 0, 44, 66, 0, 0, 19, 67, 0, 0, 44, 66, 0, 0, 20, 67, 0, 0, 44, 66, 0, 0, 21, 67, 0, 0, 44, 66, 0, 0, 22, 67, 0, 0, 44, 66, 0, 0, 23, 67, 0, 0, 44, 66, 0, 0, 24, 67, 0, 0, 44, 66, 0, 0, 25, 67, 0, 0, 44, 66, 0, 0, 26, 67, 0, 0, 44, 66, 0, 0, 27, 67, 0, 0, 44, 66, 0, 0, 28, 67, 0, 0, 44, 66, 0, 0, 29, 67, 0, 0, 44, 66, 0, 0, 30, 67, 0, 0, 44, 66, 0, 0, 31, 67, 0, 0, 44, 66, 0, 0, 32, 67, 0, 0, 44, 66, 0, 0, 33, 67, 0, 0, 44, 66, 0, 0, 34, 67, 0, 0, 44, 66, 0, 0, 35, 67, 0, 0, 44, 66, 0, 0, 36, 67, 0, 0, 44, 66, 0, 0, 37, 67, 0, 0, 44, 66, 0, 0, 38, 67, 0, 0, 44, 66, 0, 0, 39, 67, 0, 0, 44, 66, 0, 0, 40, 67, 0, 0, 44, 66, 0, 0, 41, 67, 0, 0, 44, 66, 0, 0, 42, 67, 0, 0, 44, 66, 0, 0, 43, 67, 0, 0, 44, 66, 0, 0, 44, 67, 0, 0, 44, 66, 0, 0, 45, 67, 0, 0, 44, 66, 0, 0, 46, 67, 0, 0, 44, 66, 0, 0, 47, 67, 0, 0, 44, 66, 0, 0, 48, 67, 0, 0, 44, 66, 0, 0, 49, 67, 0, 0, 44, 66, 0, 0, 50, 67, 0, 0, 44, 66, 0, 0, 51, 67, 0, 0, 44, 66, 0, 0, 52, 67, 0, 0, 44, 66, 0, 0, 53, 67, 0, 0, 44, 66, 0, 0, 54, 67, 0, 0, 44, 66, 0, 0, 55, 67, 0, 0, 48, 66, 0, 0, 184, 66, 0, 0, 48, 66, 0, 0, 186, 66, 0, 0, 48, 66, 0, 0, 188, 66, 0, 0, 48, 66, 0, 0, 190, 66, 0, 0, 48, 66, 0, 0, 192, 66, 0, 0, 48, 66, 0, 0, 194, 66, 0, 0, 48, 66, 0, 0, 196, 66, 0, 0, 48, 66, 0, 0, 198, 66, 0, 0, 48, 66, 0, 0, 200, 66, 0, 0, 48, 66, 0, 0, 202, 66, 0, 0, 48, 66, 0, 0, 204, 66, 0, 0, 48, 66, 0, 0, 206, 66, 0, 0, 48, 66, 0, 0, 208, 66, 0, 0, 48, 66, 0, 0, 210, 66, 0, 0, 48, 66, 0, 0, 212, 66, 0, 0, 48, 66, 0, 0, 214, 66, 0, 0, 48, 66, 0, 0, 216, 66, 0, 0, 48, 66, 0, 0, 218, 66, 0, 0, 48, 66, 0, 0, 220, 66, 0, 0, 48, 66, 0, 0, 222, 66, 0, 0, 48, 66, 0, 0, 224, 66, 0, 0, 48, 66, 0, 0, 226, 66, 0, 0, 48, 66, 0, 0, 228, 66, 0, 0, 48, 66, 0, 0, 230, 66, 0, 0, 48, 66, 0, 0, 232, 66, 0, 0, 48, 66, 0, 0, 234, 66, 0, 0, 48, 66, 0, 0, 236, 66, 0, 0, 48, 66, 0, 0, 238, 66, 0, 0, 48, 66, 0, 0, 240, 66, 0, 0, 48, 66, 0, 0, 242, 66, 0, 0, 48, 66, 0, 0, 244, 66, 0, 0, 48, 66, 0, 0, 246, 66, 0, 0, 48, 66, 0, 0, 248, 66, 0, 0, 48, 66, 0, 0, 250, 66, 0, 0, 48, 66, 0, 0, 252, 66, 0, 0, 48, 66, 0, 0, 254, 66, 0, 0, 48, 66, 0, 0, 0, 67, 0, 0, 48, 66, 0, 0, 1, 67, 0, 0, 48, 66, 0, 0, 2, 67, 0, 0, 48, 66, 0, 0, 3, 67, 0, 0, 48, 66, 0, 0, 4, 67, 0, 0, 48, 66, 0, 0, 5, 67, 0, 0, 48, 66, 0, 0, 6, 67, 0, 0, 48, 66, 0, 0, 7, 67, 0, 0, 48, 66, 0, 0, 8, 67, 0, 0, 48, 66, 0, 0, 9, 67, 0, 0, 48, 66, 0, 0, 10, 67, 0, 0, 48, 66, 0, 0, 11, 67, 0, 0, 48, 66, 0, 0, 12, 67, 0, 0, 48, 66, 0, 0, 13, 67, 0, 0, 48, 66, 0, 0, 14, 67, 0, 0, 48, 66, 0, 0, 15, 67, 0, 0, 48, 66, 0, 0, 16, 67, 0, 0, 48, 66, 0, 0, 17, 67, 0, 0, 48, 66, 0, 0, 18, 67, 0, 0, 48, 66, 0, 0, 19, 67, 0, 0, 48, 66, 0, 0, 20, 67, 0, 0, 48, 66, 0, 0, 21, 67, 0, 0, 48, 66, 0, 0, 22, 67, 0, 0, 48, 66, 0, 0, 23, 67, 0, 0, 48, 66, 0, 0, 24, 67, 0, 0, 48, 66, 0, 0, 25, 67, 0, 0, 48, 66, 0, 0, 26, 67, 0, 0, 48, 66, 0, 0, 27, 67, 0, 0, 48, 66, 0, 0, 28, 67, 0, 0, 48, 66, 0, 0, 29, 67, 0, 0, 48, 66, 0, 0, 30, 67, 0, 0, 48, 66, 0, 0, 31, 67, 0, 0, 48, 66, 0, 0, 32, 67, 0, 0, 48, 66, 0, 0, 33, 67, 0, 0, 48, 66, 0, 0, 34, 67, 0, 0, 48, 66, 0, 0, 35, 67, 0, 0, 48, 66, 0, 0, 36, 67, 0, 0, 48, 66, 0, 0, 37, 67, 0, 0, 48, 66, 0, 0, 38, 67, 0, 0, 48, 66, 0, 0, 39, 67, 0, 0, 48, 66, 0, 0, 40, 67, 0, 0, 48, 66, 0, 0, 41, 67, 0, 0, 48, 66, 0, 0, 42, 67, 0, 0, 48, 66, 0, 0, 43, 67, 0, 0, 48, 66, 0, 0, 44, 67, 0, 0, 48, 66, 0, 0, 45, 67, 0, 0, 48, 66, 0, 0, 46, 67, 0, 0, 48, 66, 0, 0, 47, 67, 0, 0, 48, 66, 0, 0, 48, 67, 0, 0, 48, 66, 0, 0, 49, 67, 0, 0, 48, 66, 0, 0, 50, 67, 0, 0, 48, 66, 0, 0, 51, 67, 0, 0, 48, 66, 0, 0, 52, 67, 0, 0, 48, 66, 0, 0, 53, 67, 0, 0, 48, 66, 0, 0, 54, 67, 0, 0, 48, 66, 0, 0, 55, 67, 0, 0, 52, 66, 0, 0, 184, 66, 0, 0, 52, 66, 0, 0, 186, 66, 0, 0, 52, 66, 0, 0, 188, 66, 0, 0, 52, 66, 0, 0, 190, 66, 0, 0, 52, 66, 0, 0, 192, 66, 0, 0, 52, 66, 0, 0, 194, 66, 0, 0, 52, 66, 0, 0, 196, 66, 0, 0, 52, 66, 0, 0, 198, 66, 0, 0, 52, 66, 0, 0, 200, 66, 0, 0, 52, 66, 0, 0, 202, 66, 0, 0, 52, 66, 0, 0, 204, 66, 0, 0, 52, 66, 0, 0, 206, 66, 0, 0, 52, 66, 0, 0, 208, 66, 0, 0, 52, 66, 0, 0, 210, 66, 0, 0, 52, 66, 0, 0, 212, 66, 0, 0, 52, 66, 0, 0, 214, 66, 0, 0, 52, 66, 0, 0, 216, 66, 0, 0, 52, 66, 0, 0, 218, 66, 0, 0, 52, 66, 0, 0, 220, 66, 0, 0, 52, 66, 0, 0, 222, 66, 0, 0, 52, 66, 0, 0, 224, 66, 0, 0, 52, 66, 0, 0, 226, 66, 0, 0, 52, 66, 0, 0, 228, 66, 0, 0, 52, 66, 0, 0, 230, 66, 0, 0, 52, 66, 0, 0, 232, 66, 0, 0, 52, 66, 0, 0, 234, 66, 0, 0, 52, 66, 0, 0, 236, 66, 0, 0, 52, 66, 0, 0, 238, 66, 0, 0, 52, 66, 0, 0, 240, 66, 0, 0, 52, 66, 0, 0, 242, 66, 0, 0, 52, 66, 0, 0, 244, 66, 0, 0, 52, 66, 0, 0, 246, 66, 0, 0, 52, 66, 0, 0, 248, 66, 0, 0, 52, 66, 0, 0, 250, 66, 0, 0, 52, 66, 0, 0, 252, 66, 0, 0, 52, 66, 0, 0, 254, 66, 0, 0, 52, 66, 0, 0, 0, 67, 0, 0, 52, 66, 0, 0, 1, 67, 0, 0, 52, 66, 0, 0, 2, 67, 0, 0, 52, 66, 0, 0, 3, 67, 0, 0, 52, 66, 0, 0, 4, 67, 0, 0, 52, 66, 0, 0, 5, 67, 0, 0, 52, 66, 0, 0, 6, 67, 0, 0, 52, 66, 0, 0, 7, 67, 0, 0, 52, 66, 0, 0, 8, 67, 0, 0, 52, 66, 0, 0, 9, 67, 0, 0, 52, 66, 0, 0, 10, 67, 0, 0, 52, 66, 0, 0, 11, 67, 0, 0, 52, 66, 0, 0, 12, 67, 0, 0, 52, 66, 0, 0, 13, 67, 0, 0, 52, 66, 0, 0, 14, 67, 0, 0, 52, 66, 0, 0, 15, 67, 0, 0, 52, 66, 0, 0, 16, 67, 0, 0, 52, 66, 0, 0, 17, 67, 0, 0, 52, 66, 0, 0, 18, 67, 0, 0, 52, 66, 0, 0, 19, 67, 0, 0, 52, 66, 0, 0, 20, 67, 0, 0, 52, 66, 0, 0, 21, 67, 0, 0, 52, 66, 0, 0, 22, 67, 0, 0, 52, 66, 0, 0, 23, 67, 0, 0, 52, 66, 0, 0, 24, 67, 0, 0, 52, 66, 0, 0, 25, 67, 0, 0, 52, 66, 0, 0, 26, 67, 0, 0, 52, 66, 0, 0, 27, 67, 0, 0, 52, 66, 0, 0, 28, 67, 0, 0, 52, 66, 0, 0, 29, 67, 0, 0, 52, 66, 0, 0, 30, 67, 0, 0, 52, 66, 0, 0, 31, 67, 0, 0, 52, 66, 0, 0, 32, 67, 0, 0, 52, 66, 0, 0, 33, 67, 0, 0, 52, 66, 0, 0, 34, 67, 0, 0, 52, 66, 0, 0, 35, 67, 0, 0, 52, 66, 0, 0, 36, 67, 0, 0, 52, 66, 0, 0, 37, 67, 0, 0, 52, 66, 0, 0, 38, 67, 0, 0, 52, 66, 0, 0, 39, 67, 0, 0, 52, 66, 0, 0, 40, 67, 0, 0, 52, 66, 0, 0, 41, 67, 0, 0, 52, 66, 0, 0, 42, 67, 0, 0, 52, 66, 0, 0, 43, 67, 0, 0, 52, 66, 0, 0, 44, 67, 0, 0, 52, 66, 0, 0, 45, 67, 0, 0, 52, 66, 0, 0, 46, 67, 0, 0, 52, 66, 0, 0, 47, 67, 0, 0, 52, 66, 0, 0, 48, 67, 0, 0, 52, 66, 0, 0, 49, 67, 0, 0, 52, 66, 0, 0, 50, 67, 0, 0, 52, 66, 0, 0, 51, 67, 0, 0, 52, 66, 0, 0, 52, 67, 0, 0, 52, 66, 0, 0, 53, 67, 0, 0, 52, 66, 0, 0, 54, 67, 0, 0, 52, 66, 0, 0, 55, 67, 0, 0, 56, 66, 0, 0, 184, 66, 0, 0, 56, 66, 0, 0, 186, 66, 0, 0, 56, 66, 0, 0, 188, 66, 0, 0, 56, 66, 0, 0, 190, 66, 0, 0, 56, 66, 0, 0, 192, 66, 0, 0, 56, 66, 0, 0, 194, 66, 0, 0, 56, 66, 0, 0, 196, 66, 0, 0, 56, 66, 0, 0, 198, 66, 0, 0, 56, 66, 0, 0, 200, 66, 0, 0, 56, 66, 0, 0, 202, 66, 0, 0, 56, 66, 0, 0, 204, 66, 0, 0, 56, 66, 0, 0, 206, 66, 0, 0, 56, 66, 0, 0, 208, 66, 0, 0, 56, 66, 0, 0, 210, 66, 0, 0, 56, 66, 0, 0, 212, 66, 0, 0, 56, 66, 0, 0, 214, 66, 0, 0, 56, 66, 0, 0, 216, 66, 0, 0, 56, 66, 0, 0, 218, 66, 0, 0, 56, 66, 0, 0, 220, 66, 0, 0, 56, 66, 0, 0, 222, 66, 0, 0, 56, 66, 0, 0, 224, 66, 0, 0, 56, 66, 0, 0, 226, 66, 0, 0, 56, 66, 0, 0, 228, 66, 0, 0, 56, 66, 0, 0, 230, 66, 0, 0, 56, 66, 0, 0, 232, 66, 0, 0, 56, 66, 0, 0, 234, 66, 0, 0, 56, 66, 0, 0, 236, 66, 0, 0, 56, 66, 0, 0, 238, 66, 0, 0, 56, 66, 0, 0, 240, 66, 0, 0, 56, 66, 0, 0, 242, 66, 0, 0, 56, 66, 0, 0, 244, 66, 0, 0, 56, 66, 0, 0, 246, 66, 0, 0, 56, 66, 0, 0, 248, 66, 0, 0, 56, 66, 0, 0, 250, 66, 0, 0, 56, 66, 0, 0, 252, 66, 0, 0, 56, 66, 0, 0, 254, 66, 0, 0, 56, 66, 0, 0, 0, 67, 0, 0, 56, 66, 0, 0, 1, 67, 0, 0, 56, 66, 0, 0, 2, 67, 0, 0, 56, 66, 0, 0, 3, 67, 0, 0, 56, 66, 0, 0, 4, 67, 0, 0, 56, 66, 0, 0, 5, 67, 0, 0, 56, 66, 0, 0, 6, 67, 0, 0, 56, 66, 0, 0, 7, 67, 0, 0, 56, 66, 0, 0, 8, 67, 0, 0, 56, 66, 0, 0, 9, 67, 0, 0, 56, 66, 0, 0, 10, 67, 0, 0, 56, 66, 0, 0, 11, 67, 0, 0, 56, 66, 0, 0, 12, 67, 0, 0, 56, 66, 0, 0, 13, 67, 0, 0, 56, 66, 0, 0, 14, 67, 0, 0, 56, 66, 0, 0, 15, 67, 0, 0, 56, 66, 0, 0, 16, 67, 0, 0, 56, 66, 0, 0, 17, 67, 0, 0, 56, 66, 0, 0, 18, 67, 0, 0, 56, 66, 0, 0, 19, 67, 0, 0, 56, 66, 0, 0, 20, 67, 0, 0, 56, 66, 0, 0, 21, 67, 0, 0, 56, 66, 0, 0, 22, 67, 0, 0, 56, 66, 0, 0, 23, 67, 0, 0, 56, 66, 0, 0, 24, 67, 0, 0, 56, 66, 0, 0, 25, 67, 0, 0, 56, 66, 0, 0, 26, 67, 0, 0, 56, 66, 0, 0, 27, 67, 0, 0, 56, 66, 0, 0, 28, 67, 0, 0, 56, 66, 0, 0, 29, 67, 0, 0, 56, 66, 0, 0, 30, 67, 0, 0, 56, 66, 0, 0, 31, 67, 0, 0, 56, 66, 0, 0, 32, 67, 0, 0, 56, 66, 0, 0, 33, 67, 0, 0, 56, 66, 0, 0, 34, 67, 0, 0, 56, 66, 0, 0, 35, 67, 0, 0, 56, 66, 0, 0, 36, 67, 0, 0, 56, 66, 0, 0, 37, 67, 0, 0, 56, 66, 0, 0, 38, 67, 0, 0, 56, 66, 0, 0, 39, 67, 0, 0, 56, 66, 0, 0, 40, 67, 0, 0, 56, 66, 0, 0, 41, 67, 0, 0, 56, 66, 0, 0, 42, 67, 0, 0, 56, 66, 0, 0, 43, 67, 0, 0, 56, 66, 0, 0, 44, 67, 0, 0, 56, 66, 0, 0, 45, 67, 0, 0, 56, 66, 0, 0, 46, 67, 0, 0, 56, 66, 0, 0, 47, 67, 0, 0, 56, 66, 0, 0, 48, 67, 0, 0, 56, 66, 0, 0, 49, 67, 0, 0, 56, 66, 0, 0, 50, 67, 0, 0, 56, 66, 0, 0, 51, 67, 0, 0, 56, 66, 0, 0, 52, 67, 0, 0, 56, 66, 0, 0, 53, 67, 0, 0, 56, 66, 0, 0, 54, 67, 0, 0, 56, 66, 0, 0, 55, 67, 0, 0, 60, 66, 0, 0, 184, 66, 0, 0, 60, 66, 0, 0, 186, 66, 0, 0, 60, 66, 0, 0, 188, 66, 0, 0, 60, 66, 0, 0, 190, 66, 0, 0, 60, 66, 0, 0, 192, 66, 0, 0, 60, 66, 0, 0, 194, 66, 0, 0, 60, 66, 0, 0, 196, 66, 0, 0, 60, 66, 0, 0, 198, 66, 0, 0, 60, 66, 0, 0, 200, 66, 0, 0, 60, 66, 0, 0, 202, 66, 0, 0, 60, 66, 0, 0, 204, 66, 0, 0, 60, 66, 0, 0, 206, 66, 0, 0, 60, 66, 0, 0, 208, 66, 0, 0, 60, 66, 0, 0, 210, 66, 0, 0, 60, 66, 0, 0, 212, 66, 0, 0, 60, 66, 0, 0, 214, 66, 0, 0, 60, 66, 0, 0, 216, 66, 0, 0, 60, 66, 0, 0, 218, 66, 0, 0, 60, 66, 0, 0, 220, 66, 0, 0, 60, 66, 0, 0, 222, 66, 0, 0, 60, 66, 0, 0, 224, 66, 0, 0, 60, 66, 0, 0, 226, 66, 0, 0, 60, 66, 0, 0, 228, 66, 0, 0, 60, 66, 0, 0, 230, 66, 0, 0, 60, 66, 0, 0, 232, 66, 0, 0, 60, 66, 0, 0, 234, 66, 0, 0, 60, 66, 0, 0, 236, 66, 0, 0, 60, 66, 0, 0, 238, 66, 0, 0, 60, 66, 0, 0, 240, 66, 0, 0, 60, 66, 0, 0, 242, 66, 0, 0, 60, 66, 0, 0, 244, 66, 0, 0, 60, 66, 0, 0, 246, 66, 0, 0, 60, 66, 0, 0, 248, 66, 0, 0, 60, 66, 0, 0, 250, 66, 0, 0, 60, 66, 0, 0, 252, 66, 0, 0, 60, 66, 0, 0, 254, 66, 0, 0, 60, 66, 0, 0, 0, 67, 0, 0, 60, 66, 0, 0, 1, 67, 0, 0, 60, 66, 0, 0, 2, 67, 0, 0, 60, 66, 0, 0, 3, 67, 0, 0, 60, 66, 0, 0, 4, 67, 0, 0, 60, 66, 0, 0, 5, 67, 0, 0, 60, 66, 0, 0, 6, 67, 0, 0, 60, 66, 0, 0, 7, 67, 0, 0, 60, 66, 0, 0, 8, 67, 0, 0, 60, 66, 0, 0, 9, 67, 0, 0, 60, 66, 0, 0, 10, 67, 0, 0, 60, 66, 0, 0, 11, 67, 0, 0, 60, 66, 0, 0, 12, 67, 0, 0, 60, 66, 0, 0, 13, 67, 0, 0, 60, 66, 0, 0, 14, 67, 0, 0, 60, 66, 0, 0, 15, 67, 0, 0, 60, 66, 0, 0, 16, 67, 0, 0, 60, 66, 0, 0, 17, 67, 0, 0, 60, 66, 0, 0, 18, 67, 0, 0, 60, 66, 0, 0, 19, 67, 0, 0, 60, 66, 0, 0, 20, 67, 0, 0, 60, 66, 0, 0, 21, 67, 0, 0, 60, 66, 0, 0, 22, 67, 0, 0, 60, 66, 0, 0, 23, 67, 0, 0, 60, 66, 0, 0, 24, 67, 0, 0, 60, 66, 0, 0, 25, 67, 0, 0, 60, 66, 0, 0, 26, 67, 0, 0, 60, 66, 0, 0, 27, 67, 0, 0, 60, 66, 0, 0, 28, 67, 0, 0, 60, 66, 0, 0, 29, 67, 0, 0, 60, 66, 0, 0, 30, 67, 0, 0, 60, 66, 0, 0, 31, 67, 0, 0, 60, 66, 0, 0, 32, 67, 0, 0, 60, 66, 0, 0, 33, 67, 0, 0, 60, 66, 0, 0, 34, 67, 0, 0, 60, 66, 0, 0, 35, 67, 0, 0, 60, 66, 0, 0, 36, 67, 0, 0, 60, 66, 0, 0, 37, 67, 0, 0, 60, 66, 0, 0, 38, 67, 0, 0, 60, 66, 0, 0, 39, 67, 0, 0, 60, 66, 0, 0, 40, 67, 0, 0, 60, 66, 0, 0, 41, 67, 0, 0, 60, 66, 0, 0, 42, 67, 0, 0, 60, 66, 0, 0, 43, 67, 0, 0, 60, 66, 0, 0, 44, 67, 0, 0, 60, 66, 0, 0, 45, 67, 0, 0, 60, 66, 0, 0, 46, 67, 0, 0, 60, 66, 0, 0, 47, 67, 0, 0, 60, 66, 0, 0, 48, 67, 0, 0, 60, 66, 0, 0, 49, 67, 0, 0, 60, 66, 0, 0, 50, 67, 0, 0, 60, 66, 0, 0, 51, 67, 0, 0, 60, 66, 0, 0, 52, 67, 0, 0, 60, 66, 0, 0, 53, 67, 0, 0, 60, 66, 0, 0, 54, 67, 0, 0, 60, 66, 0, 0, 55, 67, 0, 0, 64, 66, 0, 0, 184, 66, 0, 0, 64, 66, 0, 0, 186, 66, 0, 0, 64, 66, 0, 0, 188, 66, 0, 0, 64, 66, 0, 0, 190, 66, 0, 0, 64, 66, 0, 0, 192, 66, 0, 0, 64, 66, 0, 0, 194, 66, 0, 0, 64, 66, 0, 0, 196, 66, 0, 0, 64, 66, 0, 0, 198, 66, 0, 0, 64, 66, 0, 0, 200, 66, 0, 0, 64, 66, 0, 0, 202, 66, 0, 0, 64, 66, 0, 0, 204, 66, 0, 0, 64, 66, 0, 0, 206, 66, 0, 0, 64, 66, 0, 0, 208, 66, 0, 0, 64, 66, 0, 0, 210, 66, 0, 0, 64, 66, 0, 0, 212, 66, 0, 0, 64, 66, 0, 0, 214, 66, 0, 0, 64, 66, 0, 0, 216, 66, 0, 0, 64, 66, 0, 0, 218, 66, 0, 0, 64, 66, 0, 0, 220, 66, 0, 0, 64, 66, 0, 0, 222, 66, 0, 0, 64, 66, 0, 0, 224, 66, 0, 0, 64, 66, 0, 0, 226, 66, 0, 0, 64, 66, 0, 0, 228, 66, 0, 0, 64, 66, 0, 0, 230, 66, 0, 0, 64, 66, 0, 0, 232, 66, 0, 0, 64, 66, 0, 0, 234, 66, 0, 0, 64, 66, 0, 0, 236, 66, 0, 0, 64, 66, 0, 0, 238, 66, 0, 0, 64, 66, 0, 0, 240, 66, 0, 0, 64, 66, 0, 0, 242, 66, 0, 0, 64, 66, 0, 0, 244, 66, 0, 0, 64, 66, 0, 0, 246, 66, 0, 0, 64, 66, 0, 0, 248, 66, 0, 0, 64, 66, 0, 0, 250, 66, 0, 0, 64, 66, 0, 0, 252, 66, 0, 0, 64, 66, 0, 0, 254, 66, 0, 0, 64, 66, 0, 0, 0, 67, 0, 0, 64, 66, 0, 0, 1, 67, 0, 0, 64, 66, 0, 0, 2, 67, 0, 0, 64, 66, 0, 0, 3, 67, 0, 0, 64, 66, 0, 0, 4, 67, 0, 0, 64, 66, 0, 0, 5, 67, 0, 0, 64, 66, 0, 0, 6, 67, 0, 0, 64, 66, 0, 0, 7, 67, 0, 0, 64, 66, 0, 0, 8, 67, 0, 0, 64, 66, 0, 0, 9, 67, 0, 0, 64, 66, 0, 0, 10, 67, 0, 0, 64, 66, 0, 0, 11, 67, 0, 0, 64, 66, 0, 0, 12, 67, 0, 0, 64, 66, 0, 0, 13, 67, 0, 0, 64, 66, 0, 0, 14, 67, 0, 0, 64, 66, 0, 0, 15, 67, 0, 0, 64, 66, 0, 0, 16, 67, 0, 0, 64, 66, 0, 0, 17, 67, 0, 0, 64, 66, 0, 0, 18, 67, 0, 0, 64, 66, 0, 0, 19, 67, 0, 0, 64, 66, 0, 0, 20, 67, 0, 0, 64, 66, 0, 0, 21, 67, 0, 0, 64, 66, 0, 0, 22, 67, 0, 0, 64, 66, 0, 0, 23, 67, 0, 0, 64, 66, 0, 0, 24, 67, 0, 0, 64, 66, 0, 0, 25, 67, 0, 0, 64, 66, 0, 0, 26, 67, 0, 0, 64, 66, 0, 0, 27, 67, 0, 0, 64, 66, 0, 0, 28, 67, 0, 0, 64, 66, 0, 0, 29, 67, 0, 0, 64, 66, 0, 0, 30, 67, 0, 0, 64, 66, 0, 0, 31, 67, 0, 0, 64, 66, 0, 0, 32, 67, 0, 0, 64, 66, 0, 0, 33, 67, 0, 0, 64, 66, 0, 0, 34, 67, 0, 0, 64, 66, 0, 0, 35, 67, 0, 0, 64, 66, 0, 0, 36, 67, 0, 0, 64, 66, 0, 0, 37, 67, 0, 0, 64, 66, 0, 0, 38, 67, 0, 0, 64, 66, 0, 0, 39, 67, 0, 0, 64, 66, 0, 0, 40, 67, 0, 0, 64, 66, 0, 0, 41, 67, 0, 0, 64, 66, 0, 0, 42, 67, 0, 0, 64, 66, 0, 0, 43, 67, 0, 0, 64, 66, 0, 0, 44, 67, 0, 0, 64, 66, 0, 0, 45, 67, 0, 0, 64, 66, 0, 0, 46, 67, 0, 0, 64, 66, 0, 0, 47, 67, 0, 0, 64, 66, 0, 0, 48, 67, 0, 0, 64, 66, 0, 0, 49, 67, 0, 0, 64, 66, 0, 0, 50, 67, 0, 0, 64, 66, 0, 0, 51, 67, 0, 0, 64, 66, 0, 0, 52, 67, 0, 0, 64, 66, 0, 0, 53, 67, 0, 0, 64, 66, 0, 0, 54, 67, 0, 0, 64, 66, 0, 0, 55, 67, 0, 0, 68, 66, 0, 0, 184, 66, 0, 0, 68, 66, 0, 0, 186, 66, 0, 0, 68, 66, 0, 0, 188, 66, 0, 0, 68, 66, 0, 0, 190, 66, 0, 0, 68, 66, 0, 0, 192, 66, 0, 0, 68, 66, 0, 0, 194, 66, 0, 0, 68, 66, 0, 0, 196, 66, 0, 0, 68, 66, 0, 0, 198, 66, 0, 0, 68, 66, 0, 0, 200, 66, 0, 0, 68, 66, 0, 0, 202, 66, 0, 0, 68, 66, 0, 0, 204, 66, 0, 0, 68, 66, 0, 0, 206, 66, 0, 0, 68, 66, 0, 0, 208, 66, 0, 0, 68, 66, 0, 0, 210, 66, 0, 0, 68, 66, 0, 0, 212, 66, 0, 0, 68, 66, 0, 0, 214, 66, 0, 0, 68, 66, 0, 0, 216, 66, 0, 0, 68, 66, 0, 0, 218, 66, 0, 0, 68, 66, 0, 0, 220, 66, 0, 0, 68, 66, 0, 0, 222, 66, 0, 0, 68, 66, 0, 0, 224, 66, 0, 0, 68, 66, 0, 0, 226, 66, 0, 0, 68, 66, 0, 0, 228, 66, 0, 0, 68, 66, 0, 0, 230, 66, 0, 0, 68, 66, 0, 0, 232, 66, 0, 0, 68, 66, 0, 0, 234, 66, 0, 0, 68, 66, 0, 0, 236, 66, 0, 0, 68, 66, 0, 0, 238, 66, 0, 0, 68, 66, 0, 0, 240, 66, 0, 0, 68, 66, 0, 0, 242, 66, 0, 0, 68, 66, 0, 0, 244, 66, 0, 0, 68, 66, 0, 0, 246, 66, 0, 0, 68, 66, 0, 0, 248, 66, 0, 0, 68, 66, 0, 0, 250, 66, 0, 0, 68, 66, 0, 0, 252, 66, 0, 0, 68, 66, 0, 0, 254, 66, 0, 0, 68, 66, 0, 0, 0, 67, 0, 0, 68, 66, 0, 0, 1, 67, 0, 0, 68, 66, 0, 0, 2, 67, 0, 0, 68, 66, 0, 0, 3, 67, 0, 0, 68, 66, 0, 0, 4, 67, 0, 0, 68, 66, 0, 0, 5, 67, 0, 0, 68, 66, 0, 0, 6, 67, 0, 0, 68, 66, 0, 0, 7, 67, 0, 0, 68, 66, 0, 0, 8, 67, 0, 0, 68, 66, 0, 0, 9, 67, 0, 0, 68, 66, 0, 0, 10, 67, 0, 0, 68, 66, 0, 0, 11, 67, 0, 0, 68, 66, 0, 0, 12, 67, 0, 0, 68, 66, 0, 0, 13, 67, 0, 0, 68, 66, 0, 0, 14, 67, 0, 0, 68, 66, 0, 0, 15, 67, 0, 0, 68, 66, 0, 0, 16, 67, 0, 0, 68, 66, 0, 0, 17, 67, 0, 0, 68, 66, 0, 0, 18, 67, 0, 0, 68, 66, 0, 0, 19, 67, 0, 0, 68, 66, 0, 0, 20, 67, 0, 0, 68, 66, 0, 0, 21, 67, 0, 0, 68, 66, 0, 0, 22, 67, 0, 0, 68, 66, 0, 0, 23, 67, 0, 0, 68, 66, 0, 0, 24, 67, 0, 0, 68, 66, 0, 0, 25, 67, 0, 0, 68, 66, 0, 0, 26, 67, 0, 0, 68, 66, 0, 0, 27, 67, 0, 0, 68, 66, 0, 0, 28, 67, 0, 0, 68, 66, 0, 0, 29, 67, 0, 0, 68, 66, 0, 0, 30, 67, 0, 0, 68, 66, 0, 0, 31, 67, 0, 0, 68, 66, 0, 0, 32, 67, 0, 0, 68, 66, 0, 0, 33, 67, 0, 0, 68, 66, 0, 0, 34, 67, 0, 0, 68, 66, 0, 0, 35, 67, 0, 0, 68, 66, 0, 0, 36, 67, 0, 0, 68, 66, 0, 0, 37, 67, 0, 0, 68, 66, 0, 0, 38, 67, 0, 0, 68, 66, 0, 0, 39, 67, 0, 0, 68, 66, 0, 0, 40, 67, 0, 0, 68, 66, 0, 0, 41, 67, 0, 0, 68, 66, 0, 0, 42, 67, 0, 0, 68, 66, 0, 0, 43, 67, 0, 0, 68, 66, 0, 0, 44, 67, 0, 0, 68, 66, 0, 0, 45, 67, 0, 0, 68, 66, 0, 0, 46, 67, 0, 0, 68, 66, 0, 0, 47, 67, 0, 0, 68, 66, 0, 0, 48, 67, 0, 0, 68, 66, 0, 0, 49, 67, 0, 0, 68, 66, 0, 0, 50, 67, 0, 0, 68, 66, 0, 0, 51, 67, 0, 0, 68, 66, 0, 0, 52, 67, 0, 0, 68, 66, 0, 0, 53, 67, 0, 0, 68, 66, 0, 0, 54, 67, 0, 0, 68, 66, 0, 0, 55, 67, 0, 0, 72, 66, 0, 0, 184, 66, 0, 0, 72, 66, 0, 0, 186, 66, 0, 0, 72, 66, 0, 0, 188, 66, 0, 0, 72, 66, 0, 0, 190, 66, 0, 0, 72, 66, 0, 0, 192, 66, 0, 0, 72, 66, 0, 0, 194, 66, 0, 0, 72, 66, 0, 0, 196, 66, 0, 0, 72, 66, 0, 0, 198, 66, 0, 0, 72, 66, 0, 0, 200, 66, 0, 0, 72, 66, 0, 0, 202, 66, 0, 0, 72, 66, 0, 0, 204, 66, 0, 0, 72, 66, 0, 0, 206, 66, 0, 0, 72, 66, 0, 0, 208, 66, 0, 0, 72, 66, 0, 0, 210, 66, 0, 0, 72, 66, 0, 0, 212, 66, 0, 0, 72, 66, 0, 0, 214, 66, 0, 0, 72, 66, 0, 0, 216, 66, 0, 0, 72, 66, 0, 0, 218, 66, 0, 0, 72, 66, 0, 0, 220, 66, 0, 0, 72, 66, 0, 0, 222, 66, 0, 0, 72, 66, 0, 0, 224, 66, 0, 0, 72, 66, 0, 0, 226, 66, 0, 0, 72, 66, 0, 0, 228, 66, 0, 0, 72, 66, 0, 0, 230, 66, 0, 0, 72, 66, 0, 0, 232, 66, 0, 0, 72, 66, 0, 0, 234, 66, 0, 0, 72, 66, 0, 0, 236, 66, 0, 0, 72, 66, 0, 0, 238, 66, 0, 0, 72, 66, 0, 0, 240, 66, 0, 0, 72, 66, 0, 0, 242, 66, 0, 0, 72, 66, 0, 0, 244, 66, 0, 0, 72, 66, 0, 0, 246, 66, 0, 0, 72, 66, 0, 0, 248, 66, 0, 0, 72, 66, 0, 0, 250, 66, 0, 0, 72, 66, 0, 0, 252, 66, 0, 0, 72, 66, 0, 0, 254, 66, 0, 0, 72, 66, 0, 0, 0, 67, 0, 0, 72, 66, 0, 0, 1, 67, 0, 0, 72, 66, 0, 0, 2, 67, 0, 0, 72, 66, 0, 0, 3, 67, 0, 0, 72, 66, 0, 0, 4, 67, 0, 0, 72, 66, 0, 0, 5, 67, 0, 0, 72, 66, 0, 0, 6, 67, 0, 0, 72, 66, 0, 0, 7, 67, 0, 0, 72, 66, 0, 0, 8, 67, 0, 0, 72, 66, 0, 0, 9, 67, 0, 0, 72, 66, 0, 0, 10, 67, 0, 0, 72, 66, 0, 0, 11, 67, 0, 0, 72, 66, 0, 0, 12, 67, 0, 0, 72, 66, 0, 0, 13, 67, 0, 0, 72, 66, 0, 0, 14, 67, 0, 0, 72, 66, 0, 0, 15, 67, 0, 0, 72, 66, 0, 0, 16, 67, 0, 0, 72, 66, 0, 0, 17, 67, 0, 0, 72, 66, 0, 0, 18, 67, 0, 0, 72, 66, 0, 0, 19, 67, 0, 0, 72, 66, 0, 0, 20, 67, 0, 0, 72, 66, 0, 0, 21, 67, 0, 0, 72, 66, 0, 0, 22, 67, 0, 0, 72, 66, 0, 0, 23, 67, 0, 0, 72, 66, 0, 0, 24, 67, 0, 0, 72, 66, 0, 0, 25, 67, 0, 0, 72, 66, 0, 0, 26, 67, 0, 0, 72, 66, 0, 0, 27, 67, 0, 0, 72, 66, 0, 0, 28, 67, 0, 0, 72, 66, 0, 0, 29, 67, 0, 0, 72, 66, 0, 0, 30, 67, 0, 0, 72, 66, 0, 0, 31, 67, 0, 0, 72, 66, 0, 0, 32, 67, 0, 0, 72, 66, 0, 0, 33, 67, 0, 0, 72, 66, 0, 0, 34, 67, 0, 0, 72, 66, 0, 0, 35, 67, 0, 0, 72, 66, 0, 0, 36, 67, 0, 0, 72, 66, 0, 0, 37, 67, 0, 0, 72, 66, 0, 0, 38, 67, 0, 0, 72, 66, 0, 0, 39, 67, 0, 0, 72, 66, 0, 0, 40, 67, 0, 0, 72, 66, 0, 0, 41, 67, 0, 0, 72, 66, 0, 0, 42, 67, 0, 0, 72, 66, 0, 0, 43, 67, 0, 0, 72, 66, 0, 0, 44, 67, 0, 0, 72, 66, 0, 0, 45, 67, 0, 0, 72, 66, 0, 0, 46, 67, 0, 0, 72, 66, 0, 0, 47, 67, 0, 0, 72, 66, 0, 0, 48, 67, 0, 0, 72, 66, 0, 0, 49, 67, 0, 0, 72, 66, 0, 0, 50, 67, 0, 0, 72, 66, 0, 0, 51, 67, 0, 0, 72, 66, 0, 0, 52, 67, 0, 0, 72, 66, 0, 0, 53, 67, 0, 0, 72, 66, 0, 0, 54, 67, 0, 0, 72, 66, 0, 0, 55, 67, 0, 0, 76, 66, 0, 0, 184, 66, 0, 0, 76, 66, 0, 0, 186, 66, 0, 0, 76, 66, 0, 0, 188, 66, 0, 0, 76, 66, 0, 0, 190, 66, 0, 0, 76, 66, 0, 0, 192, 66, 0, 0, 76, 66, 0, 0, 194, 66, 0, 0, 76, 66, 0, 0, 196, 66, 0, 0, 76, 66, 0, 0, 198, 66, 0, 0, 76, 66, 0, 0, 200, 66, 0, 0, 76, 66, 0, 0, 202, 66, 0, 0, 76, 66, 0, 0, 204, 66, 0, 0, 76, 66, 0, 0, 206, 66, 0, 0, 76, 66, 0, 0, 208, 66, 0, 0, 76, 66, 0, 0, 210, 66, 0, 0, 76, 66, 0, 0, 212, 66, 0, 0, 76, 66, 0, 0, 214, 66, 0, 0, 76, 66, 0, 0, 216, 66, 0, 0, 76, 66, 0, 0, 218, 66, 0, 0, 76, 66, 0, 0, 220, 66, 0, 0, 76, 66, 0, 0, 222, 66, 0, 0, 76, 66, 0, 0, 224, 66, 0, 0, 76, 66, 0, 0, 226, 66, 0, 0, 76, 66, 0, 0, 228, 66, 0, 0, 76, 66, 0, 0, 230, 66, 0, 0, 76, 66, 0, 0, 232, 66, 0, 0, 76, 66, 0, 0, 234, 66, 0, 0, 76, 66, 0, 0, 236, 66, 0, 0, 76, 66, 0, 0, 238, 66, 0, 0, 76, 66, 0, 0, 240, 66, 0, 0, 76, 66, 0, 0, 242, 66, 0, 0, 76, 66, 0, 0, 244, 66, 0, 0, 76, 66, 0, 0, 246, 66, 0, 0, 76, 66, 0, 0, 248, 66, 0, 0, 76, 66, 0, 0, 250, 66, 0, 0, 76, 66, 0, 0, 252, 66, 0, 0, 76, 66, 0, 0, 254, 66, 0, 0, 76, 66, 0, 0, 0, 67, 0, 0, 76, 66, 0, 0, 1, 67, 0, 0, 76, 66, 0, 0, 2, 67, 0, 0, 76, 66, 0, 0, 3, 67, 0, 0, 76, 66, 0, 0, 4, 67, 0, 0, 76, 66, 0, 0, 5, 67, 0, 0, 76, 66, 0, 0, 6, 67, 0, 0, 76, 66, 0, 0, 7, 67, 0, 0, 76, 66, 0, 0, 8, 67, 0, 0, 76, 66, 0, 0, 9, 67, 0, 0, 76, 66, 0, 0, 10, 67, 0, 0, 76, 66, 0, 0, 11, 67, 0, 0, 76, 66, 0, 0, 12, 67, 0, 0, 76, 66, 0, 0, 13, 67, 0, 0, 76, 66, 0, 0, 14, 67, 0, 0, 76, 66, 0, 0, 15, 67, 0, 0, 76, 66, 0, 0, 16, 67, 0, 0, 76, 66, 0, 0, 17, 67, 0, 0, 76, 66, 0, 0, 18, 67, 0, 0, 76, 66, 0, 0, 19, 67, 0, 0, 76, 66, 0, 0, 20, 67, 0, 0, 76, 66, 0, 0, 21, 67, 0, 0, 76, 66, 0, 0, 22, 67, 0, 0, 76, 66, 0, 0, 23, 67, 0, 0, 76, 66, 0, 0, 24, 67, 0, 0, 76, 66, 0, 0, 25, 67, 0, 0, 76, 66, 0, 0, 26, 67, 0, 0, 76, 66, 0, 0, 27, 67, 0, 0, 76, 66, 0, 0, 28, 67, 0, 0, 76, 66, 0, 0, 29, 67, 0, 0, 76, 66, 0, 0, 30, 67, 0, 0, 76, 66, 0, 0, 31, 67, 0, 0, 76, 66, 0, 0, 32, 67, 0, 0, 76, 66, 0, 0, 33, 67, 0, 0, 76, 66, 0, 0, 34, 67, 0, 0, 76, 66, 0, 0, 35, 67, 0, 0, 76, 66, 0, 0, 36, 67, 0, 0, 76, 66, 0, 0, 37, 67, 0, 0, 76, 66, 0, 0, 38, 67, 0, 0, 76, 66, 0, 0, 39, 67, 0, 0, 76, 66, 0, 0, 40, 67, 0, 0, 76, 66, 0, 0, 41, 67, 0, 0, 76, 66, 0, 0, 42, 67, 0, 0, 76, 66, 0, 0, 43, 67, 0, 0, 76, 66, 0, 0, 44, 67, 0, 0, 76, 66, 0, 0, 45, 67, 0, 0, 76, 66, 0, 0, 46, 67, 0, 0, 76, 66, 0, 0, 47, 67, 0, 0, 76, 66, 0, 0, 48, 67, 0, 0, 76, 66, 0, 0, 49, 67, 0, 0, 76, 66, 0, 0, 50, 67, 0, 0, 76, 66, 0, 0, 51, 67, 0, 0, 76, 66, 0, 0, 52, 67, 0, 0, 76, 66, 0, 0, 53, 67, 0, 0, 76, 66, 0, 0, 54, 67, 0, 0, 76, 66, 0, 0, 55, 67, 0, 0, 80, 66, 0, 0, 184, 66, 0, 0, 80, 66, 0, 0, 186, 66, 0, 0, 80, 66, 0, 0, 188, 66, 0, 0, 80, 66, 0, 0, 190, 66, 0, 0, 80, 66, 0, 0, 192, 66, 0, 0, 80, 66, 0, 0, 194, 66, 0, 0, 80, 66, 0, 0, 196, 66, 0, 0, 80, 66, 0, 0, 198, 66, 0, 0, 80, 66, 0, 0, 200, 66, 0, 0, 80, 66, 0, 0, 202, 66, 0, 0, 80, 66, 0, 0, 204, 66, 0, 0, 80, 66, 0, 0, 206, 66, 0, 0, 80, 66, 0, 0, 208, 66, 0, 0, 80, 66, 0, 0, 210, 66, 0, 0, 80, 66, 0, 0, 212, 66, 0, 0, 80, 66, 0, 0, 214, 66, 0, 0, 80, 66, 0, 0, 216, 66, 0, 0, 80, 66, 0, 0, 218, 66, 0, 0, 80, 66, 0, 0, 220, 66, 0, 0, 80, 66, 0, 0, 222, 66, 0, 0, 80, 66, 0, 0, 224, 66, 0, 0, 80, 66, 0, 0, 226, 66, 0, 0, 80, 66, 0, 0, 228, 66, 0, 0, 80, 66, 0, 0, 230, 66, 0, 0, 80, 66, 0, 0, 232, 66, 0, 0, 80, 66, 0, 0, 234, 66, 0, 0, 80, 66, 0, 0, 236, 66, 0, 0, 80, 66, 0, 0, 238, 66, 0, 0, 80, 66, 0, 0, 240, 66, 0, 0, 80, 66, 0, 0, 242, 66, 0, 0, 80, 66, 0, 0, 244, 66, 0, 0, 80, 66, 0, 0, 246, 66, 0, 0, 80, 66, 0, 0, 248, 66, 0, 0, 80, 66, 0, 0, 250, 66, 0, 0, 80, 66, 0, 0, 252, 66, 0, 0, 80, 66, 0, 0, 254, 66, 0, 0, 80, 66, 0, 0, 0, 67, 0, 0, 80, 66, 0, 0, 1, 67, 0, 0, 80, 66, 0, 0, 2, 67, 0, 0, 80, 66, 0, 0, 3, 67, 0, 0, 80, 66, 0, 0, 4, 67, 0, 0, 80, 66, 0, 0, 5, 67, 0, 0, 80, 66, 0, 0, 6, 67, 0, 0, 80, 66, 0, 0, 7, 67, 0, 0, 80, 66, 0, 0, 8, 67, 0, 0, 80, 66, 0, 0, 9, 67, 0, 0, 80, 66, 0, 0, 10, 67, 0, 0, 80, 66, 0, 0, 11, 67, 0, 0, 80, 66, 0, 0, 12, 67, 0, 0, 80, 66, 0, 0, 13, 67, 0, 0, 80, 66, 0, 0, 14, 67, 0, 0, 80, 66, 0, 0, 15, 67, 0, 0, 80, 66, 0, 0, 16, 67, 0, 0, 80, 66, 0, 0, 17, 67, 0, 0, 80, 66, 0, 0, 18, 67, 0, 0, 80, 66, 0, 0, 19, 67, 0, 0, 80, 66, 0, 0, 20, 67, 0, 0, 80, 66, 0, 0, 21, 67, 0, 0, 80, 66, 0, 0, 22, 67, 0, 0, 80, 66, 0, 0, 23, 67, 0, 0, 80, 66, 0, 0, 24, 67, 0, 0, 80, 66, 0, 0, 25, 67, 0, 0, 80, 66, 0, 0, 26, 67, 0, 0, 80, 66, 0, 0, 27, 67, 0, 0, 80, 66, 0, 0, 28, 67, 0, 0, 80, 66, 0, 0, 29, 67, 0, 0, 80, 66, 0, 0, 30, 67, 0, 0, 80, 66, 0, 0, 31, 67, 0, 0, 80, 66, 0, 0, 32, 67, 0, 0, 80, 66, 0, 0, 33, 67, 0, 0, 80, 66, 0, 0, 34, 67, 0, 0, 80, 66, 0, 0, 35, 67, 0, 0, 80, 66, 0, 0, 36, 67, 0, 0, 80, 66, 0, 0, 37, 67, 0, 0, 80, 66, 0, 0, 38, 67, 0, 0, 80, 66, 0, 0, 39, 67, 0, 0, 80, 66, 0, 0, 40, 67, 0, 0, 80, 66, 0, 0, 41, 67, 0, 0, 80, 66, 0, 0, 42, 67, 0, 0, 80, 66, 0, 0, 43, 67, 0, 0, 80, 66, 0, 0, 44, 67, 0, 0, 80, 66, 0, 0, 45, 67, 0, 0, 80, 66, 0, 0, 46, 67, 0, 0, 80, 66, 0, 0, 47, 67, 0, 0, 80, 66, 0, 0, 48, 67, 0, 0, 80, 66, 0, 0, 49, 67, 0, 0, 80, 66, 0, 0, 50, 67, 0, 0, 80, 66, 0, 0, 51, 67, 0, 0, 80, 66, 0, 0, 52, 67, 0, 0, 80, 66, 0, 0, 53, 67, 0, 0, 80, 66, 0, 0, 54, 67, 0, 0, 80, 66, 0, 0, 55, 67, 0, 0, 84, 66, 0, 0, 184, 66, 0, 0, 84, 66, 0, 0, 186, 66, 0, 0, 84, 66, 0, 0, 188, 66, 0, 0, 84, 66, 0, 0, 190, 66, 0, 0, 84, 66, 0, 0, 192, 66, 0, 0, 84, 66, 0, 0, 194, 66, 0, 0, 84, 66, 0, 0, 196, 66, 0, 0, 84, 66, 0, 0, 198, 66, 0, 0, 84, 66, 0, 0, 200, 66, 0, 0, 84, 66, 0, 0, 202, 66, 0, 0, 84, 66, 0, 0, 204, 66, 0, 0, 84, 66, 0, 0, 206, 66, 0, 0, 84, 66, 0, 0, 208, 66, 0, 0, 84, 66, 0, 0, 210, 66, 0, 0, 84, 66, 0, 0, 212, 66, 0, 0, 84, 66, 0, 0, 214, 66, 0, 0, 84, 66, 0, 0, 216, 66, 0, 0, 84, 66, 0, 0, 218, 66, 0, 0, 84, 66, 0, 0, 220, 66, 0, 0, 84, 66, 0, 0, 222, 66, 0, 0, 84, 66, 0, 0, 224, 66, 0, 0, 84, 66, 0, 0, 226, 66, 0, 0, 84, 66, 0, 0, 228, 66, 0, 0, 84, 66, 0, 0, 230, 66, 0, 0, 84, 66, 0, 0, 232, 66, 0, 0, 84, 66, 0, 0, 234, 66, 0, 0, 84, 66, 0, 0, 236, 66, 0, 0, 84, 66, 0, 0, 238, 66, 0, 0, 84, 66, 0, 0, 240, 66, 0, 0, 84, 66, 0, 0, 242, 66, 0, 0, 84, 66, 0, 0, 244, 66, 0, 0, 84, 66, 0, 0, 246, 66, 0, 0, 84, 66, 0, 0, 248, 66, 0, 0, 84, 66, 0, 0, 250, 66, 0, 0, 84, 66, 0, 0, 252, 66, 0, 0, 84, 66, 0, 0, 254, 66, 0, 0, 84, 66, 0, 0, 0, 67, 0, 0, 84, 66, 0, 0, 1, 67, 0, 0, 84, 66, 0, 0, 2, 67, 0, 0, 84, 66, 0, 0, 3, 67, 0, 0, 84, 66, 0, 0, 4, 67, 0, 0, 84, 66, 0, 0, 5, 67, 0, 0, 84, 66, 0, 0, 6, 67, 0, 0, 84, 66, 0, 0, 7, 67, 0, 0, 84, 66, 0, 0, 8, 67, 0, 0, 84, 66, 0, 0, 9, 67, 0, 0, 84, 66, 0, 0, 10, 67, 0, 0, 84, 66, 0, 0, 11, 67, 0, 0, 84, 66, 0, 0, 12, 67, 0, 0, 84, 66, 0, 0, 13, 67, 0, 0, 84, 66, 0, 0, 14, 67, 0, 0, 84, 66, 0, 0, 15, 67, 0, 0, 84, 66, 0, 0, 16, 67, 0, 0, 84, 66, 0, 0, 17, 67, 0, 0, 84, 66, 0, 0, 18, 67, 0, 0, 84, 66, 0, 0, 19, 67, 0, 0, 84, 66, 0, 0, 20, 67, 0, 0, 84, 66, 0, 0, 21, 67, 0, 0, 84, 66, 0, 0, 22, 67, 0, 0, 84, 66, 0, 0, 23, 67, 0, 0, 84, 66, 0, 0, 24, 67, 0, 0, 84, 66, 0, 0, 25, 67, 0, 0, 84, 66, 0, 0, 26, 67, 0, 0, 84, 66, 0, 0, 27, 67, 0, 0, 84, 66, 0, 0, 28, 67, 0, 0, 84, 66, 0, 0, 29, 67, 0, 0, 84, 66, 0, 0, 30, 67, 0, 0, 84, 66, 0, 0, 31, 67, 0, 0, 84, 66, 0, 0, 32, 67, 0, 0, 84, 66, 0, 0, 33, 67, 0, 0, 84, 66, 0, 0, 34, 67, 0, 0, 84, 66, 0, 0, 35, 67, 0, 0, 84, 66, 0, 0, 36, 67, 0, 0, 84, 66, 0, 0, 37, 67, 0, 0, 84, 66, 0, 0, 38, 67, 0, 0, 84, 66, 0, 0, 39, 67, 0, 0, 84, 66, 0, 0, 40, 67, 0, 0, 84, 66, 0, 0, 41, 67, 0, 0, 84, 66, 0, 0, 42, 67, 0, 0, 84, 66, 0, 0, 43, 67, 0, 0, 84, 66, 0, 0, 44, 67, 0, 0, 84, 66, 0, 0, 45, 67, 0, 0, 84, 66, 0, 0, 46, 67, 0, 0, 84, 66, 0, 0, 47, 67, 0, 0, 84, 66, 0, 0, 48, 67, 0, 0, 84, 66, 0, 0, 49, 67, 0, 0, 84, 66, 0, 0, 50, 67, 0, 0, 84, 66, 0, 0, 51, 67, 0, 0, 84, 66, 0, 0, 52, 67, 0, 0, 84, 66, 0, 0, 53, 67, 0, 0, 84, 66, 0, 0, 54, 67, 0, 0, 84, 66, 0, 0, 55, 67, 0, 0, 88, 66, 0, 0, 184, 66, 0, 0, 88, 66, 0, 0, 186, 66, 0, 0, 88, 66, 0, 0, 188, 66, 0, 0, 88, 66, 0, 0, 190, 66, 0, 0, 88, 66, 0, 0, 192, 66, 0, 0, 88, 66, 0, 0, 194, 66, 0, 0, 88, 66, 0, 0, 196, 66, 0, 0, 88, 66, 0, 0, 198, 66, 0, 0, 88, 66, 0, 0, 200, 66, 0, 0, 88, 66, 0, 0, 202, 66, 0, 0, 88, 66, 0, 0, 204, 66, 0, 0, 88, 66, 0, 0, 206, 66, 0, 0, 88, 66, 0, 0, 208, 66, 0, 0, 88, 66, 0, 0, 210, 66, 0, 0, 88, 66, 0, 0, 212, 66, 0, 0, 88, 66, 0, 0, 214, 66, 0, 0, 88, 66, 0, 0, 216, 66, 0, 0, 88, 66, 0, 0, 218, 66, 0, 0, 88, 66, 0, 0, 220, 66, 0, 0, 88, 66, 0, 0, 222, 66, 0, 0, 88, 66, 0, 0, 224, 66, 0, 0, 88, 66, 0, 0, 226, 66, 0, 0, 88, 66, 0, 0, 228, 66, 0, 0, 88, 66, 0, 0, 230, 66, 0, 0, 88, 66, 0, 0, 232, 66, 0, 0, 88, 66, 0, 0, 234, 66, 0, 0, 88, 66, 0, 0, 236, 66, 0, 0, 88, 66, 0, 0, 238, 66, 0, 0, 88, 66, 0, 0, 240, 66, 0, 0, 88, 66, 0, 0, 242, 66, 0, 0, 88, 66, 0, 0, 244, 66, 0, 0, 88, 66, 0, 0, 246, 66, 0, 0, 88, 66, 0, 0, 248, 66, 0, 0, 88, 66, 0, 0, 250, 66, 0, 0, 88, 66, 0, 0, 252, 66, 0, 0, 88, 66, 0, 0, 254, 66, 0, 0, 88, 66, 0, 0, 0, 67, 0, 0, 88, 66, 0, 0, 1, 67, 0, 0, 88, 66, 0, 0, 2, 67, 0, 0, 88, 66, 0, 0, 3, 67, 0, 0, 88, 66, 0, 0, 4, 67, 0, 0, 88, 66, 0, 0, 5, 67, 0, 0, 88, 66, 0, 0, 6, 67, 0, 0, 88, 66, 0, 0, 7, 67, 0, 0, 88, 66, 0, 0, 8, 67, 0, 0, 88, 66, 0, 0, 9, 67, 0, 0, 88, 66, 0, 0, 10, 67, 0, 0, 88, 66, 0, 0, 11, 67, 0, 0, 88, 66, 0, 0, 12, 67, 0, 0, 88, 66, 0, 0, 13, 67, 0, 0, 88, 66, 0, 0, 14, 67, 0, 0, 88, 66, 0, 0, 15, 67, 0, 0, 88, 66, 0, 0, 16, 67, 0, 0, 88, 66, 0, 0, 17, 67, 0, 0, 88, 66, 0, 0, 18, 67, 0, 0, 88, 66, 0, 0, 19, 67, 0, 0, 88, 66, 0, 0, 20, 67, 0, 0, 88, 66, 0, 0, 21, 67, 0, 0, 88, 66, 0, 0, 22, 67, 0, 0, 88, 66, 0, 0, 23, 67, 0, 0, 88, 66, 0, 0, 24, 67, 0, 0, 88, 66, 0, 0, 25, 67, 0, 0, 88, 66, 0, 0, 26, 67, 0, 0, 88, 66, 0, 0, 27, 67, 0, 0, 88, 66, 0, 0, 28, 67, 0, 0, 88, 66, 0, 0, 29, 67, 0, 0, 88, 66, 0, 0, 30, 67, 0, 0, 88, 66, 0, 0, 31, 67, 0, 0, 88, 66, 0, 0, 32, 67, 0, 0, 88, 66, 0, 0, 33, 67, 0, 0, 88, 66, 0, 0, 34, 67, 0, 0, 88, 66, 0, 0, 35, 67, 0, 0, 88, 66, 0, 0, 36, 67, 0, 0, 88, 66, 0, 0, 37, 67, 0, 0, 88, 66, 0, 0, 38, 67, 0, 0, 88, 66, 0, 0, 39, 67, 0, 0, 88, 66, 0, 0, 40, 67, 0, 0, 88, 66, 0, 0, 41, 67, 0, 0, 88, 66, 0, 0, 42, 67, 0, 0, 88, 66, 0, 0, 43, 67, 0, 0, 88, 66, 0, 0, 44, 67, 0, 0, 88, 66, 0, 0, 45, 67, 0, 0, 88, 66, 0, 0, 46, 67, 0, 0, 88, 66, 0, 0, 47, 67, 0, 0, 88, 66, 0, 0, 48, 67, 0, 0, 88, 66, 0, 0, 49, 67, 0, 0, 88, 66, 0, 0, 50, 67, 0, 0, 88, 66, 0, 0, 51, 67, 0, 0, 88, 66, 0, 0, 52, 67, 0, 0, 88, 66, 0, 0, 53, 67, 0, 0, 88, 66, 0, 0, 54, 67, 0, 0, 88, 66, 0, 0, 55, 67, 0, 0, 92, 66, 0, 0, 184, 66, 0, 0, 92, 66, 0, 0, 186, 66, 0, 0, 92, 66, 0, 0, 188, 66, 0, 0, 92, 66, 0, 0, 190, 66, 0, 0, 92, 66, 0, 0, 192, 66, 0, 0, 92, 66, 0, 0, 194, 66, 0, 0, 92, 66, 0, 0, 196, 66, 0, 0, 92, 66, 0, 0, 198, 66, 0, 0, 92, 66, 0, 0, 200, 66, 0, 0, 92, 66, 0, 0, 202, 66, 0, 0, 92, 66, 0, 0, 204, 66, 0, 0, 92, 66, 0, 0, 206, 66, 0, 0, 92, 66, 0, 0, 208, 66, 0, 0, 92, 66, 0, 0, 210, 66, 0, 0, 92, 66, 0, 0, 212, 66, 0, 0, 92, 66, 0, 0, 214, 66, 0, 0, 92, 66, 0, 0, 216, 66, 0, 0, 92, 66, 0, 0, 218, 66, 0, 0, 92, 66, 0, 0, 220, 66, 0, 0, 92, 66, 0, 0, 222, 66, 0, 0, 92, 66, 0, 0, 224, 66, 0, 0, 92, 66, 0, 0, 226, 66, 0, 0, 92, 66, 0, 0, 228, 66, 0, 0, 92, 66, 0, 0, 230, 66, 0, 0, 92, 66, 0, 0, 232, 66, 0, 0, 92, 66, 0, 0, 234, 66, 0, 0, 92, 66, 0, 0, 236, 66, 0, 0, 92, 66, 0, 0, 238, 66, 0, 0, 92, 66, 0, 0, 240, 66, 0, 0, 92, 66, 0, 0, 242, 66, 0, 0, 92, 66, 0, 0, 244, 66, 0, 0, 92, 66, 0, 0, 246, 66, 0, 0, 92, 66, 0, 0, 248, 66, 0, 0, 92, 66, 0, 0, 250, 66, 0, 0, 92, 66, 0, 0, 252, 66, 0, 0, 92, 66, 0, 0, 254, 66, 0, 0, 92, 66, 0, 0, 0, 67, 0, 0, 92, 66, 0, 0, 1, 67, 0, 0, 92, 66, 0, 0, 2, 67, 0, 0, 92, 66, 0, 0, 3, 67, 0, 0, 92, 66, 0, 0, 4, 67, 0, 0, 92, 66, 0, 0, 5, 67, 0, 0, 92, 66, 0, 0, 6, 67, 0, 0, 92, 66, 0, 0, 7, 67, 0, 0, 92, 66, 0, 0, 8, 67, 0, 0, 92, 66, 0, 0, 9, 67, 0, 0, 92, 66, 0, 0, 10, 67, 0, 0, 92, 66, 0, 0, 11, 67, 0, 0, 92, 66, 0, 0, 12, 67, 0, 0, 92, 66, 0, 0, 13, 67, 0, 0, 92, 66, 0, 0, 14, 67, 0, 0, 92, 66, 0, 0, 15, 67, 0, 0, 92, 66, 0, 0, 16, 67, 0, 0, 92, 66, 0, 0, 17, 67, 0, 0, 92, 66, 0, 0, 18, 67, 0, 0, 92, 66, 0, 0, 19, 67, 0, 0, 92, 66, 0, 0, 20, 67, 0, 0, 92, 66, 0, 0, 21, 67, 0, 0, 92, 66, 0, 0, 22, 67, 0, 0, 92, 66, 0, 0, 23, 67, 0, 0, 92, 66, 0, 0, 24, 67, 0, 0, 92, 66, 0, 0, 25, 67, 0, 0, 92, 66, 0, 0, 26, 67, 0, 0, 92, 66, 0, 0, 27, 67, 0, 0, 92, 66, 0, 0, 28, 67, 0, 0, 92, 66, 0, 0, 29, 67, 0, 0, 92, 66, 0, 0, 30, 67, 0, 0, 92, 66, 0, 0, 31, 67, 0, 0, 92, 66, 0, 0, 32, 67, 0, 0, 92, 66, 0, 0, 33, 67, 0, 0, 92, 66, 0, 0, 34, 67, 0, 0, 92, 66, 0, 0, 35, 67, 0, 0, 92, 66, 0, 0, 36, 67, 0, 0, 92, 66, 0, 0, 37, 67, 0, 0, 92, 66, 0, 0, 38, 67, 0, 0, 92, 66, 0, 0, 39, 67, 0, 0, 92, 66, 0, 0, 40, 67, 0, 0, 92, 66, 0, 0, 41, 67, 0, 0, 92, 66, 0, 0, 42, 67, 0, 0, 92, 66, 0, 0, 43, 67, 0, 0, 92, 66, 0, 0, 44, 67, 0, 0, 92, 66, 0, 0, 45, 67, 0, 0, 92, 66, 0, 0, 46, 67, 0, 0, 92, 66, 0, 0, 47, 67, 0, 0, 92, 66, 0, 0, 48, 67, 0, 0, 92, 66, 0, 0, 49, 67, 0, 0, 92, 66, 0, 0, 50, 67, 0, 0, 92, 66, 0, 0, 51, 67, 0, 0, 92, 66, 0, 0, 52, 67, 0, 0, 92, 66, 0, 0, 53, 67, 0, 0, 92, 66, 0, 0, 54, 67, 0, 0, 92, 66, 0, 0, 55, 67, 0, 0, 96, 66, 0, 0, 184, 66, 0, 0, 96, 66, 0, 0, 186, 66, 0, 0, 96, 66, 0, 0, 188, 66, 0, 0, 96, 66, 0, 0, 190, 66, 0, 0, 96, 66, 0, 0, 192, 66, 0, 0, 96, 66, 0, 0, 194, 66, 0, 0, 96, 66, 0, 0, 196, 66, 0, 0, 96, 66, 0, 0, 198, 66, 0, 0, 96, 66, 0, 0, 200, 66, 0, 0, 96, 66, 0, 0, 202, 66, 0, 0, 96, 66, 0, 0, 204, 66, 0, 0, 96, 66, 0, 0, 206, 66, 0, 0, 96, 66, 0, 0, 208, 66, 0, 0, 96, 66, 0, 0, 210, 66, 0, 0, 96, 66, 0, 0, 212, 66, 0, 0, 96, 66, 0, 0, 214, 66, 0, 0, 96, 66, 0, 0, 216, 66, 0, 0, 96, 66, 0, 0, 218, 66, 0, 0, 96, 66, 0, 0, 220, 66, 0, 0, 96, 66, 0, 0, 222, 66, 0, 0, 96, 66, 0, 0, 224, 66, 0, 0, 96, 66, 0, 0, 226, 66, 0, 0, 96, 66, 0, 0, 228, 66, 0, 0, 96, 66, 0, 0, 230, 66, 0, 0, 96, 66, 0, 0, 232, 66, 0, 0, 96, 66, 0, 0, 234, 66, 0, 0, 96, 66, 0, 0, 236, 66, 0, 0, 96, 66, 0, 0, 238, 66, 0, 0, 96, 66, 0, 0, 240, 66, 0, 0, 96, 66, 0, 0, 242, 66, 0, 0, 96, 66, 0, 0, 244, 66, 0, 0, 96, 66, 0, 0, 246, 66, 0, 0, 96, 66, 0, 0, 248, 66, 0, 0, 96, 66, 0, 0, 250, 66, 0, 0, 96, 66, 0, 0, 252, 66, 0, 0, 96, 66, 0, 0, 254, 66, 0, 0, 96, 66, 0, 0, 0, 67, 0, 0, 96, 66, 0, 0, 1, 67, 0, 0, 96, 66, 0, 0, 2, 67, 0, 0, 96, 66, 0, 0, 3, 67, 0, 0, 96, 66, 0, 0, 4, 67, 0, 0, 96, 66, 0, 0, 5, 67, 0, 0, 96, 66, 0, 0, 6, 67, 0, 0, 96, 66, 0, 0, 7, 67, 0, 0, 96, 66, 0, 0, 8, 67, 0, 0, 96, 66, 0, 0, 9, 67, 0, 0, 96, 66, 0, 0, 10, 67, 0, 0, 96, 66, 0, 0, 11, 67, 0, 0, 96, 66, 0, 0, 12, 67, 0, 0, 96, 66, 0, 0, 13, 67, 0, 0, 96, 66, 0, 0, 14, 67, 0, 0, 96, 66, 0, 0, 15, 67, 0, 0, 96, 66, 0, 0, 16, 67, 0, 0, 96, 66, 0, 0, 17, 67, 0, 0, 96, 66, 0, 0, 18, 67, 0, 0, 96, 66, 0, 0, 19, 67, 0, 0, 96, 66, 0, 0, 20, 67, 0, 0, 96, 66, 0, 0, 21, 67, 0, 0, 96, 66, 0, 0, 22, 67, 0, 0, 96, 66, 0, 0, 23, 67, 0, 0, 96, 66, 0, 0, 24, 67, 0, 0, 96, 66, 0, 0, 25, 67, 0, 0, 96, 66, 0, 0, 26, 67, 0, 0, 96, 66, 0, 0, 27, 67, 0, 0, 96, 66, 0, 0, 28, 67, 0, 0, 96, 66, 0, 0, 29, 67, 0, 0, 96, 66, 0, 0, 30, 67, 0, 0, 96, 66, 0, 0, 31, 67, 0, 0, 96, 66, 0, 0, 32, 67, 0, 0, 96, 66, 0, 0, 33, 67, 0, 0, 96, 66, 0, 0, 34, 67, 0, 0, 96, 66, 0, 0, 35, 67, 0, 0, 96, 66, 0, 0, 36, 67, 0, 0, 96, 66, 0, 0, 37, 67, 0, 0, 96, 66, 0, 0, 38, 67, 0, 0, 96, 66, 0, 0, 39, 67, 0, 0, 96, 66, 0, 0, 40, 67, 0, 0, 96, 66, 0, 0, 41, 67, 0, 0, 96, 66, 0, 0, 42, 67, 0, 0, 96, 66, 0, 0, 43, 67, 0, 0, 96, 66, 0, 0, 44, 67, 0, 0, 96, 66, 0, 0, 45, 67, 0, 0, 96, 66, 0, 0, 46, 67, 0, 0, 96, 66, 0, 0, 47, 67, 0, 0, 96, 66, 0, 0, 48, 67, 0, 0, 96, 66, 0, 0, 49, 67, 0, 0, 96, 66, 0, 0, 50, 67, 0, 0, 96, 66, 0, 0, 51, 67, 0, 0, 96, 66, 0, 0, 52, 67, 0, 0, 96, 66, 0, 0, 53, 67, 0, 0, 96, 66, 0, 0, 54, 67, 0, 0, 96, 66, 0, 0, 55, 67, 0, 0, 100, 66, 0, 0, 184, 66, 0, 0, 100, 66, 0, 0, 186, 66, 0, 0, 100, 66, 0, 0, 188, 66, 0, 0, 100, 66, 0, 0, 190, 66, 0, 0, 100, 66, 0, 0, 192, 66, 0, 0, 100, 66, 0, 0, 194, 66, 0, 0, 100, 66, 0, 0, 196, 66, 0, 0, 100, 66, 0, 0, 198, 66, 0, 0, 100, 66, 0, 0, 200, 66, 0, 0, 100, 66, 0, 0, 202, 66, 0, 0, 100, 66, 0, 0, 204, 66, 0, 0, 100, 66, 0, 0, 206, 66, 0, 0, 100, 66, 0, 0, 208, 66, 0, 0, 100, 66, 0, 0, 210, 66, 0, 0, 100, 66, 0, 0, 212, 66, 0, 0, 100, 66, 0, 0, 214, 66, 0, 0, 100, 66, 0, 0, 216, 66, 0, 0, 100, 66, 0, 0, 218, 66, 0, 0, 100, 66, 0, 0, 220, 66, 0, 0, 100, 66, 0, 0, 222, 66, 0, 0, 100, 66, 0, 0, 224, 66, 0, 0, 100, 66, 0, 0, 226, 66, 0, 0, 100, 66, 0, 0, 228, 66, 0, 0, 100, 66, 0, 0, 230, 66, 0, 0, 100, 66, 0, 0, 232, 66, 0, 0, 100, 66, 0, 0, 234, 66, 0, 0, 100, 66, 0, 0, 236, 66, 0, 0, 100, 66, 0, 0, 238, 66, 0, 0, 100, 66, 0, 0, 240, 66, 0, 0, 100, 66, 0, 0, 242, 66, 0, 0, 100, 66, 0, 0, 244, 66, 0, 0, 100, 66, 0, 0, 246, 66, 0, 0, 100, 66, 0, 0, 248, 66, 0, 0, 100, 66, 0, 0, 250, 66, 0, 0, 100, 66, 0, 0, 252, 66, 0, 0, 100, 66, 0, 0, 254, 66, 0, 0, 100, 66, 0, 0, 0, 67, 0, 0, 100, 66, 0, 0, 1, 67, 0, 0, 100, 66, 0, 0, 2, 67, 0, 0, 100, 66, 0, 0, 3, 67, 0, 0, 100, 66, 0, 0, 4, 67, 0, 0, 100, 66, 0, 0, 5, 67, 0, 0, 100, 66, 0, 0, 6, 67, 0, 0, 100, 66, 0, 0, 7, 67, 0, 0, 100, 66, 0, 0, 8, 67, 0, 0, 100, 66, 0, 0, 9, 67, 0, 0, 100, 66, 0, 0, 10, 67, 0, 0, 100, 66, 0, 0, 11, 67, 0, 0, 100, 66, 0, 0, 12, 67, 0, 0, 100, 66, 0, 0, 13, 67, 0, 0, 100, 66, 0, 0, 14, 67, 0, 0, 100, 66, 0, 0, 15, 67, 0, 0, 100, 66, 0, 0, 16, 67, 0, 0, 100, 66, 0, 0, 17, 67, 0, 0, 100, 66, 0, 0, 18, 67, 0, 0, 100, 66, 0, 0, 19, 67, 0, 0, 100, 66, 0, 0, 20, 67, 0, 0, 100, 66, 0, 0, 21, 67, 0, 0, 100, 66, 0, 0, 22, 67, 0, 0, 100, 66, 0, 0, 23, 67, 0, 0, 100, 66, 0, 0, 24, 67, 0, 0, 100, 66, 0, 0, 25, 67, 0, 0, 100, 66, 0, 0, 26, 67, 0, 0, 100, 66, 0, 0, 27, 67, 0, 0, 100, 66, 0, 0, 28, 67, 0, 0, 100, 66, 0, 0, 29, 67, 0, 0, 100, 66, 0, 0, 30, 67, 0, 0, 100, 66, 0, 0, 31, 67, 0, 0, 100, 66, 0, 0, 32, 67, 0, 0, 100, 66, 0, 0, 33, 67, 0, 0, 100, 66, 0, 0, 34, 67, 0, 0, 100, 66, 0, 0, 35, 67, 0, 0, 100, 66, 0, 0, 36, 67, 0, 0, 100, 66, 0, 0, 37, 67, 0, 0, 100, 66, 0, 0, 38, 67, 0, 0, 100, 66, 0, 0, 39, 67, 0, 0, 100, 66, 0, 0, 40, 67, 0, 0, 100, 66, 0, 0, 41, 67, 0, 0, 100, 66, 0, 0, 42, 67, 0, 0, 100, 66, 0, 0, 43, 67, 0, 0, 100, 66, 0, 0, 44, 67, 0, 0, 100, 66, 0, 0, 45, 67, 0, 0, 100, 66, 0, 0, 46, 67, 0, 0, 100, 66, 0, 0, 47, 67, 0, 0, 100, 66, 0, 0, 48, 67, 0, 0, 100, 66, 0, 0, 49, 67, 0, 0, 100, 66, 0, 0, 50, 67, 0, 0, 100, 66, 0, 0, 51, 67, 0, 0, 100, 66, 0, 0, 52, 67, 0, 0, 100, 66, 0, 0, 53, 67, 0, 0, 100, 66, 0, 0, 54, 67, 0, 0, 100, 66, 0, 0, 55, 67, 0, 0, 104, 66, 0, 0, 184, 66, 0, 0, 104, 66, 0, 0, 186, 66, 0, 0, 104, 66, 0, 0, 188, 66, 0, 0, 104, 66, 0, 0, 190, 66, 0, 0, 104, 66, 0, 0, 192, 66, 0, 0, 104, 66, 0, 0, 194, 66, 0, 0, 104, 66, 0, 0, 196, 66, 0, 0, 104, 66, 0, 0, 198, 66, 0, 0, 104, 66, 0, 0, 200, 66, 0, 0, 104, 66, 0, 0, 202, 66, 0, 0, 104, 66, 0, 0, 204, 66, 0, 0, 104, 66, 0, 0, 206, 66, 0, 0, 104, 66, 0, 0, 208, 66, 0, 0, 104, 66, 0, 0, 210, 66, 0, 0, 104, 66, 0, 0, 212, 66, 0, 0, 104, 66, 0, 0, 214, 66, 0, 0, 104, 66, 0, 0, 216, 66, 0, 0, 104, 66, 0, 0, 218, 66, 0, 0, 104, 66, 0, 0, 220, 66, 0, 0, 104, 66, 0, 0, 222, 66, 0, 0, 104, 66, 0, 0, 224, 66, 0, 0, 104, 66, 0, 0, 226, 66, 0, 0, 104, 66, 0, 0, 228, 66, 0, 0, 104, 66, 0, 0, 230, 66, 0, 0, 104, 66, 0, 0, 232, 66, 0, 0, 104, 66, 0, 0, 234, 66, 0, 0, 104, 66, 0, 0, 236, 66, 0, 0, 104, 66, 0, 0, 238, 66, 0, 0, 104, 66, 0, 0, 240, 66, 0, 0, 104, 66, 0, 0, 242, 66, 0, 0, 104, 66, 0, 0, 244, 66, 0, 0, 104, 66, 0, 0, 246, 66, 0, 0, 104, 66, 0, 0, 248, 66, 0, 0, 104, 66, 0, 0, 250, 66, 0, 0, 104, 66, 0, 0, 252, 66, 0, 0, 104, 66, 0, 0, 254, 66, 0, 0, 104, 66, 0, 0, 0, 67, 0, 0, 104, 66, 0, 0, 1, 67, 0, 0, 104, 66, 0, 0, 2, 67, 0, 0, 104, 66, 0, 0, 3, 67, 0, 0, 104, 66, 0, 0, 4, 67, 0, 0, 104, 66, 0, 0, 5, 67, 0, 0, 104, 66, 0, 0, 6, 67, 0, 0, 104, 66, 0, 0, 7, 67, 0, 0, 104, 66, 0, 0, 8, 67, 0, 0, 104, 66, 0, 0, 9, 67, 0, 0, 104, 66, 0, 0, 10, 67, 0, 0, 104, 66, 0, 0, 11, 67, 0, 0, 104, 66, 0, 0, 12, 67, 0, 0, 104, 66, 0, 0, 13, 67, 0, 0, 104, 66, 0, 0, 14, 67, 0, 0, 104, 66, 0, 0, 15, 67, 0, 0, 104, 66, 0, 0, 16, 67, 0, 0, 104, 66, 0, 0, 17, 67, 0, 0, 104, 66, 0, 0, 18, 67, 0, 0, 104, 66, 0, 0, 19, 67, 0, 0, 104, 66, 0, 0, 20, 67, 0, 0, 104, 66, 0, 0, 21, 67, 0, 0, 104, 66, 0, 0, 22, 67, 0, 0, 104, 66, 0, 0, 23, 67, 0, 0, 104, 66, 0, 0, 24, 67, 0, 0, 104, 66, 0, 0, 25, 67, 0, 0, 104, 66, 0, 0, 26, 67, 0, 0, 104, 66, 0, 0, 27, 67, 0, 0, 104, 66, 0, 0, 28, 67, 0, 0, 104, 66, 0, 0, 29, 67, 0, 0, 104, 66, 0, 0, 30, 67, 0, 0, 104, 66, 0, 0, 31, 67, 0, 0, 104, 66, 0, 0, 32, 67, 0, 0, 104, 66, 0, 0, 33, 67, 0, 0, 104, 66, 0, 0, 34, 67, 0, 0, 104, 66, 0, 0, 35, 67, 0, 0, 104, 66, 0, 0, 36, 67, 0, 0, 104, 66, 0, 0, 37, 67, 0, 0, 104, 66, 0, 0, 38, 67, 0, 0, 104, 66, 0, 0, 39, 67, 0, 0, 104, 66, 0, 0, 40, 67, 0, 0, 104, 66, 0, 0, 41, 67, 0, 0, 104, 66, 0, 0, 42, 67, 0, 0, 104, 66, 0, 0, 43, 67, 0, 0, 104, 66, 0, 0, 44, 67, 0, 0, 104, 66, 0, 0, 45, 67, 0, 0, 104, 66, 0, 0, 46, 67, 0, 0, 104, 66, 0, 0, 47, 67, 0, 0, 104, 66, 0, 0, 48, 67, 0, 0, 104, 66, 0, 0, 49, 67, 0, 0, 104, 66, 0, 0, 50, 67, 0, 0, 104, 66, 0, 0, 51, 67, 0, 0, 104, 66, 0, 0, 52, 67, 0, 0, 104, 66, 0, 0, 53, 67, 0, 0, 104, 66, 0, 0, 54, 67, 0, 0, 104, 66, 0, 0, 55, 67, 0, 0, 108, 66, 0, 0, 184, 66, 0, 0, 108, 66, 0, 0, 186, 66, 0, 0, 108, 66, 0, 0, 188, 66, 0, 0, 108, 66, 0, 0, 190, 66, 0, 0, 108, 66, 0, 0, 192, 66, 0, 0, 108, 66, 0, 0, 194, 66, 0, 0, 108, 66, 0, 0, 196, 66, 0, 0, 108, 66, 0, 0, 198, 66, 0, 0, 108, 66, 0, 0, 200, 66, 0, 0, 108, 66, 0, 0, 202, 66, 0, 0, 108, 66, 0, 0, 204, 66, 0, 0, 108, 66, 0, 0, 206, 66, 0, 0, 108, 66, 0, 0, 208, 66, 0, 0, 108, 66, 0, 0, 210, 66, 0, 0, 108, 66, 0, 0, 212, 66, 0, 0, 108, 66, 0, 0, 214, 66, 0, 0, 108, 66, 0, 0, 216, 66, 0, 0, 108, 66, 0, 0, 218, 66, 0, 0, 108, 66, 0, 0, 220, 66, 0, 0, 108, 66, 0, 0, 222, 66, 0, 0, 108, 66, 0, 0, 224, 66, 0, 0, 108, 66, 0, 0, 226, 66, 0, 0, 108, 66, 0, 0, 228, 66, 0, 0, 108, 66, 0, 0, 230, 66, 0, 0, 108, 66, 0, 0, 232, 66, 0, 0, 108, 66, 0, 0, 234, 66, 0, 0, 108, 66, 0, 0, 236, 66, 0, 0, 108, 66, 0, 0, 238, 66, 0, 0, 108, 66, 0, 0, 240, 66, 0, 0, 108, 66, 0, 0, 242, 66, 0, 0, 108, 66, 0, 0, 244, 66, 0, 0, 108, 66, 0, 0, 246, 66, 0, 0, 108, 66, 0, 0, 248, 66, 0, 0, 108, 66, 0, 0, 250, 66, 0, 0, 108, 66, 0, 0, 252, 66, 0, 0, 108, 66, 0, 0, 254, 66, 0, 0, 108, 66, 0, 0, 0, 67, 0, 0, 108, 66, 0, 0, 1, 67, 0, 0, 108, 66, 0, 0, 2, 67, 0, 0, 108, 66, 0, 0, 3, 67, 0, 0, 108, 66, 0, 0, 4, 67, 0, 0, 108, 66, 0, 0, 5, 67, 0, 0, 108, 66, 0, 0, 6, 67, 0, 0, 108, 66, 0, 0, 7, 67, 0, 0, 108, 66, 0, 0, 8, 67, 0, 0, 108, 66, 0, 0, 9, 67, 0, 0, 108, 66, 0, 0, 10, 67, 0, 0, 108, 66, 0, 0, 11, 67, 0, 0, 108, 66, 0, 0, 12, 67, 0, 0, 108, 66, 0, 0, 13, 67, 0, 0, 108, 66, 0, 0, 14, 67, 0, 0, 108, 66, 0, 0, 15, 67, 0, 0, 108, 66, 0, 0, 16, 67, 0, 0, 108, 66, 0, 0, 17, 67, 0, 0, 108, 66, 0, 0, 18, 67, 0, 0, 108, 66, 0, 0, 19, 67, 0, 0, 108, 66, 0, 0, 20, 67, 0, 0, 108, 66, 0, 0, 21, 67, 0, 0, 108, 66, 0, 0, 22, 67, 0, 0, 108, 66, 0, 0, 23, 67, 0, 0, 108, 66, 0, 0, 24, 67, 0, 0, 108, 66, 0, 0, 25, 67, 0, 0, 108, 66, 0, 0, 26, 67, 0, 0, 108, 66, 0, 0, 27, 67, 0, 0, 108, 66, 0, 0, 28, 67, 0, 0, 108, 66, 0, 0, 29, 67, 0, 0, 108, 66, 0, 0, 30, 67, 0, 0, 108, 66, 0, 0, 31, 67, 0, 0, 108, 66, 0, 0, 32, 67, 0, 0, 108, 66, 0, 0, 33, 67, 0, 0, 108, 66, 0, 0, 34, 67, 0, 0, 108, 66, 0, 0, 35, 67, 0, 0, 108, 66, 0, 0, 36, 67, 0, 0, 108, 66, 0, 0, 37, 67, 0, 0, 108, 66, 0, 0, 38, 67, 0, 0, 108, 66, 0, 0, 39, 67, 0, 0, 108, 66, 0, 0, 40, 67, 0, 0, 108, 66, 0, 0, 41, 67, 0, 0, 108, 66, 0, 0, 42, 67, 0, 0, 108, 66, 0, 0, 43, 67, 0, 0, 108, 66, 0, 0, 44, 67, 0, 0, 108, 66, 0, 0, 45, 67, 0, 0, 108, 66, 0, 0, 46, 67, 0, 0, 108, 66, 0, 0, 47, 67, 0, 0, 108, 66, 0, 0, 48, 67, 0, 0, 108, 66, 0, 0, 49, 67, 0, 0, 108, 66, 0, 0, 50, 67, 0, 0, 108, 66, 0, 0, 51, 67, 0, 0, 108, 66, 0, 0, 52, 67, 0, 0, 108, 66, 0, 0, 53, 67, 0, 0, 108, 66, 0, 0, 54, 67, 0, 0, 108, 66, 0, 0, 55, 67, 0, 0, 112, 66, 0, 0, 184, 66, 0, 0, 112, 66, 0, 0, 186, 66, 0, 0, 112, 66, 0, 0, 188, 66, 0, 0, 112, 66, 0, 0, 190, 66, 0, 0, 112, 66, 0, 0, 192, 66, 0, 0, 112, 66, 0, 0, 194, 66, 0, 0, 112, 66, 0, 0, 196, 66, 0, 0, 112, 66, 0, 0, 198, 66, 0, 0, 112, 66, 0, 0, 200, 66, 0, 0, 112, 66, 0, 0, 202, 66, 0, 0, 112, 66, 0, 0, 204, 66, 0, 0, 112, 66, 0, 0, 206, 66, 0, 0, 112, 66, 0, 0, 208, 66, 0, 0, 112, 66, 0, 0, 210, 66, 0, 0, 112, 66, 0, 0, 212, 66, 0, 0, 112, 66, 0, 0, 214, 66, 0, 0, 112, 66, 0, 0, 216, 66, 0, 0, 112, 66, 0, 0, 218, 66, 0, 0, 112, 66, 0, 0, 220, 66, 0, 0, 112, 66, 0, 0, 222, 66, 0, 0, 112, 66, 0, 0, 224, 66, 0, 0, 112, 66, 0, 0, 226, 66, 0, 0, 112, 66, 0, 0, 228, 66, 0, 0, 112, 66, 0, 0, 230, 66, 0, 0, 112, 66, 0, 0, 232, 66, 0, 0, 112, 66, 0, 0, 234, 66, 0, 0, 112, 66, 0, 0, 236, 66, 0, 0, 112, 66, 0, 0, 238, 66, 0, 0, 112, 66, 0, 0, 240, 66, 0, 0, 112, 66, 0, 0, 242, 66, 0, 0, 112, 66, 0, 0, 244, 66, 0, 0, 112, 66, 0, 0, 246, 66, 0, 0, 112, 66, 0, 0, 248, 66, 0, 0, 112, 66, 0, 0, 250, 66, 0, 0, 112, 66, 0, 0, 252, 66, 0, 0, 112, 66, 0, 0, 254, 66, 0, 0, 112, 66, 0, 0, 0, 67, 0, 0, 112, 66, 0, 0, 1, 67, 0, 0, 112, 66, 0, 0, 2, 67, 0, 0, 112, 66, 0, 0, 3, 67, 0, 0, 112, 66, 0, 0, 4, 67, 0, 0, 112, 66, 0, 0, 5, 67, 0, 0, 112, 66, 0, 0, 6, 67, 0, 0, 112, 66, 0, 0, 7, 67, 0, 0, 112, 66, 0, 0, 8, 67, 0, 0, 112, 66, 0, 0, 9, 67, 0, 0, 112, 66, 0, 0, 10, 67, 0, 0, 112, 66, 0, 0, 11, 67, 0, 0, 112, 66, 0, 0, 12, 67, 0, 0, 112, 66, 0, 0, 13, 67, 0, 0, 112, 66, 0, 0, 14, 67, 0, 0, 112, 66, 0, 0, 15, 67, 0, 0, 112, 66, 0, 0, 16, 67, 0, 0, 112, 66, 0, 0, 17, 67, 0, 0, 112, 66, 0, 0, 18, 67, 0, 0, 112, 66, 0, 0, 19, 67, 0, 0, 112, 66, 0, 0, 20, 67, 0, 0, 112, 66, 0, 0, 21, 67, 0, 0, 112, 66, 0, 0, 22, 67, 0, 0, 112, 66, 0, 0, 23, 67, 0, 0, 112, 66, 0, 0, 24, 67, 0, 0, 112, 66, 0, 0, 25, 67, 0, 0, 112, 66, 0, 0, 26, 67, 0, 0, 112, 66, 0, 0, 27, 67, 0, 0, 112, 66, 0, 0, 28, 67, 0, 0, 112, 66, 0, 0, 29, 67, 0, 0, 112, 66, 0, 0, 30, 67, 0, 0, 112, 66, 0, 0, 31, 67, 0, 0, 112, 66, 0, 0, 32, 67, 0, 0, 112, 66, 0, 0, 33, 67, 0, 0, 112, 66, 0, 0, 34, 67, 0, 0, 112, 66, 0, 0, 35, 67, 0, 0, 112, 66, 0, 0, 36, 67, 0, 0, 112, 66, 0, 0, 37, 67, 0, 0, 112, 66, 0, 0, 38, 67, 0, 0, 112, 66, 0, 0, 39, 67, 0, 0, 112, 66, 0, 0, 40, 67, 0, 0, 112, 66, 0, 0, 41, 67, 0, 0, 112, 66, 0, 0, 42, 67, 0, 0, 112, 66, 0, 0, 43, 67, 0, 0, 112, 66, 0, 0, 44, 67, 0, 0, 112, 66, 0, 0, 45, 67, 0, 0, 112, 66, 0, 0, 46, 67, 0, 0, 112, 66, 0, 0, 47, 67, 0, 0, 112, 66, 0, 0, 48, 67, 0, 0, 112, 66, 0, 0, 49, 67, 0, 0, 112, 66, 0, 0, 50, 67, 0, 0, 112, 66, 0, 0, 51, 67, 0, 0, 112, 66, 0, 0, 52, 67, 0, 0, 112, 66, 0, 0, 53, 67, 0, 0, 112, 66, 0, 0, 54, 67, 0, 0, 112, 66, 0, 0, 55, 67, 0, 0, 116, 66, 0, 0, 184, 66, 0, 0, 116, 66, 0, 0, 186, 66, 0, 0, 116, 66, 0, 0, 188, 66, 0, 0, 116, 66, 0, 0, 190, 66, 0, 0, 116, 66, 0, 0, 192, 66, 0, 0, 116, 66, 0, 0, 194, 66, 0, 0, 116, 66, 0, 0, 196, 66, 0, 0, 116, 66, 0, 0, 198, 66, 0, 0, 116, 66, 0, 0, 200, 66, 0, 0, 116, 66, 0, 0, 202, 66, 0, 0, 116, 66, 0, 0, 204, 66, 0, 0, 116, 66, 0, 0, 206, 66, 0, 0, 116, 66, 0, 0, 208, 66, 0, 0, 116, 66, 0, 0, 210, 66, 0, 0, 116, 66, 0, 0, 212, 66, 0, 0, 116, 66, 0, 0, 214, 66, 0, 0, 116, 66, 0, 0, 216, 66, 0, 0, 116, 66, 0, 0, 218, 66, 0, 0, 116, 66, 0, 0, 220, 66, 0, 0, 116, 66, 0, 0, 222, 66, 0, 0, 116, 66, 0, 0, 224, 66, 0, 0, 116, 66, 0, 0, 226, 66, 0, 0, 116, 66, 0, 0, 228, 66, 0, 0, 116, 66, 0, 0, 230, 66, 0, 0, 116, 66, 0, 0, 232, 66, 0, 0, 116, 66, 0, 0, 234, 66, 0, 0, 116, 66, 0, 0, 236, 66, 0, 0, 116, 66, 0, 0, 238, 66, 0, 0, 116, 66, 0, 0, 240, 66, 0, 0, 116, 66, 0, 0, 242, 66, 0, 0, 116, 66, 0, 0, 244, 66, 0, 0, 116, 66, 0, 0, 246, 66, 0, 0, 116, 66, 0, 0, 248, 66, 0, 0, 116, 66, 0, 0, 250, 66, 0, 0, 116, 66, 0, 0, 252, 66, 0, 0, 116, 66, 0, 0, 254, 66, 0, 0, 116, 66, 0, 0, 0, 67, 0, 0, 116, 66, 0, 0, 1, 67, 0, 0, 116, 66, 0, 0, 2, 67, 0, 0, 116, 66, 0, 0, 3, 67, 0, 0, 116, 66, 0, 0, 4, 67, 0, 0, 116, 66, 0, 0, 5, 67, 0, 0, 116, 66, 0, 0, 6, 67, 0, 0, 116, 66, 0, 0, 7, 67, 0, 0, 116, 66, 0, 0, 8, 67, 0, 0, 116, 66, 0, 0, 9, 67, 0, 0, 116, 66, 0, 0, 10, 67, 0, 0, 116, 66, 0, 0, 11, 67, 0, 0, 116, 66, 0, 0, 12, 67, 0, 0, 116, 66, 0, 0, 13, 67, 0, 0, 116, 66, 0, 0, 14, 67, 0, 0, 116, 66, 0, 0, 15, 67, 0, 0, 116, 66, 0, 0, 16, 67, 0, 0, 116, 66, 0, 0, 17, 67, 0, 0, 116, 66, 0, 0, 18, 67, 0, 0, 116, 66, 0, 0, 19, 67, 0, 0, 116, 66, 0, 0, 20, 67, 0, 0, 116, 66, 0, 0, 21, 67, 0, 0, 116, 66, 0, 0, 22, 67, 0, 0, 116, 66, 0, 0, 23, 67, 0, 0, 116, 66, 0, 0, 24, 67, 0, 0, 116, 66, 0, 0, 25, 67, 0, 0, 116, 66, 0, 0, 26, 67, 0, 0, 116, 66, 0, 0, 27, 67, 0, 0, 116, 66, 0, 0, 28, 67, 0, 0, 116, 66, 0, 0, 29, 67, 0, 0, 116, 66, 0, 0, 30, 67, 0, 0, 116, 66, 0, 0, 31, 67, 0, 0, 116, 66, 0, 0, 32, 67, 0, 0, 116, 66, 0, 0, 33, 67, 0, 0, 116, 66, 0, 0, 34, 67, 0, 0, 116, 66, 0, 0, 35, 67, 0, 0, 116, 66, 0, 0, 36, 67, 0, 0, 116, 66, 0, 0, 37, 67, 0, 0, 116, 66, 0, 0, 38, 67, 0, 0, 116, 66, 0, 0, 39, 67, 0, 0, 116, 66, 0, 0, 40, 67, 0, 0, 116, 66, 0, 0, 41, 67, 0, 0, 116, 66, 0, 0, 42, 67, 0, 0, 116, 66, 0, 0, 43, 67, 0, 0, 116, 66, 0, 0, 44, 67, 0, 0, 116, 66, 0, 0, 45, 67, 0, 0, 116, 66, 0, 0, 46, 67, 0, 0, 116, 66, 0, 0, 47, 67, 0, 0, 116, 66, 0, 0, 48, 67, 0, 0, 116, 66, 0, 0, 49, 67, 0, 0, 116, 66, 0, 0, 50, 67, 0, 0, 116, 66, 0, 0, 51, 67, 0, 0, 116, 66, 0, 0, 52, 67, 0, 0, 116, 66, 0, 0, 53, 67, 0, 0, 116, 66, 0, 0, 54, 67, 0, 0, 116, 66, 0, 0, 55, 67, 0, 0, 120, 66, 0, 0, 184, 66, 0, 0, 120, 66, 0, 0, 186, 66, 0, 0, 120, 66, 0, 0, 188, 66, 0, 0, 120, 66, 0, 0, 190, 66, 0, 0, 120, 66, 0, 0, 192, 66, 0, 0, 120, 66, 0, 0, 194, 66, 0, 0, 120, 66, 0, 0, 196, 66, 0, 0, 120, 66, 0, 0, 198, 66, 0, 0, 120, 66, 0, 0, 200, 66, 0, 0, 120, 66, 0, 0, 202, 66, 0, 0, 120, 66, 0, 0, 204, 66, 0, 0, 120, 66, 0, 0, 206, 66, 0, 0, 120, 66, 0, 0, 208, 66, 0, 0, 120, 66, 0, 0, 210, 66, 0, 0, 120, 66, 0, 0, 212, 66, 0, 0, 120, 66, 0, 0, 214, 66, 0, 0, 120, 66, 0, 0, 216, 66, 0, 0, 120, 66, 0, 0, 0, 67, 0, 0, 120, 66, 0, 0, 1, 67, 0, 0, 120, 66, 0, 0, 2, 67, 0, 0, 120, 66, 0, 0, 3, 67, 0, 0, 120, 66, 0, 0, 4, 67, 0, 0, 120, 66, 0, 0, 5, 67, 0, 0, 120, 66, 0, 0, 6, 67, 0, 0, 120, 66, 0, 0, 7, 67, 0, 0, 120, 66, 0, 0, 8, 67, 0, 0, 120, 66, 0, 0, 9, 67, 0, 0, 120, 66, 0, 0, 10, 67, 0, 0, 120, 66, 0, 0, 11, 67, 0, 0, 120, 66, 0, 0, 12, 67, 0, 0, 120, 66, 0, 0, 13, 67, 0, 0, 120, 66, 0, 0, 40, 67, 0, 0, 120, 66, 0, 0, 41, 67, 0, 0, 120, 66, 0, 0, 42, 67, 0, 0, 120, 66, 0, 0, 43, 67, 0, 0, 120, 66, 0, 0, 44, 67, 0, 0, 120, 66, 0, 0, 45, 67, 0, 0, 120, 66, 0, 0, 46, 67, 0, 0, 120, 66, 0, 0, 47, 67, 0, 0, 120, 66, 0, 0, 48, 67, 0, 0, 120, 66, 0, 0, 49, 67, 0, 0, 120, 66, 0, 0, 50, 67, 0, 0, 120, 66, 0, 0, 51, 67, 0, 0, 120, 66, 0, 0, 52, 67, 0, 0, 120, 66, 0, 0, 53, 67, 0, 0, 120, 66, 0, 0, 54, 67, 0, 0, 120, 66, 0, 0, 55, 67, 0, 0, 124, 66, 0, 0, 184, 66, 0, 0, 124, 66, 0, 0, 186, 66, 0, 0, 124, 66, 0, 0, 188, 66, 0, 0, 124, 66, 0, 0, 190, 66, 0, 0, 124, 66, 0, 0, 192, 66, 0, 0, 124, 66, 0, 0, 194, 66, 0, 0, 124, 66, 0, 0, 196, 66, 0, 0, 124, 66, 0, 0, 198, 66, 0, 0, 124, 66, 0, 0, 200, 66, 0, 0, 124, 66, 0, 0, 202, 66, 0, 0, 124, 66, 0, 0, 204, 66, 0, 0, 124, 66, 0, 0, 206, 66, 0, 0, 124, 66, 0, 0, 208, 66, 0, 0, 124, 66, 0, 0, 210, 66, 0, 0, 124, 66, 0, 0, 212, 66, 0, 0, 124, 66, 0, 0, 0, 67, 0, 0, 124, 66, 0, 0, 1, 67, 0, 0, 124, 66, 0, 0, 2, 67, 0, 0, 124, 66, 0, 0, 3, 67, 0, 0, 124, 66, 0, 0, 4, 67, 0, 0, 124, 66, 0, 0, 5, 67, 0, 0, 124, 66, 0, 0, 6, 67, 0, 0, 124, 66, 0, 0, 7, 67, 0, 0, 124, 66, 0, 0, 8, 67, 0, 0, 124, 66, 0, 0, 9, 67, 0, 0, 124, 66, 0, 0, 10, 67, 0, 0, 124, 66, 0, 0, 11, 67, 0, 0, 124, 66, 0, 0, 12, 67, 0, 0, 124, 66, 0, 0, 13, 67, 0, 0, 124, 66, 0, 0, 41, 67, 0, 0, 124, 66, 0, 0, 42, 67, 0, 0, 124, 66, 0, 0, 43, 67, 0, 0, 124, 66, 0, 0, 44, 67, 0, 0, 124, 66, 0, 0, 45, 67, 0, 0, 124, 66, 0, 0, 46, 67, 0, 0, 124, 66, 0, 0, 47, 67, 0, 0, 124, 66, 0, 0, 48, 67, 0, 0, 124, 66, 0, 0, 49, 67, 0, 0, 124, 66, 0, 0, 50, 67, 0, 0, 124, 66, 0, 0, 51, 67, 0, 0, 124, 66, 0, 0, 52, 67, 0, 0, 124, 66, 0, 0, 53, 67, 0, 0, 124, 66, 0, 0, 54, 67, 0, 0, 124, 66, 0, 0, 55, 67, 0, 0, 128, 66, 0, 0, 184, 66, 0, 0, 128, 66, 0, 0, 186, 66, 0, 0, 128, 66, 0, 0, 188, 66, 0, 0, 128, 66, 0, 0, 190, 66, 0, 0, 128, 66, 0, 0, 192, 66, 0, 0, 128, 66, 0, 0, 194, 66, 0, 0, 128, 66, 0, 0, 196, 66, 0, 0, 128, 66, 0, 0, 198, 66, 0, 0, 128, 66, 0, 0, 200, 66, 0, 0, 128, 66, 0, 0, 202, 66, 0, 0, 128, 66, 0, 0, 204, 66, 0, 0, 128, 66, 0, 0, 206, 66, 0, 0, 128, 66, 0, 0, 208, 66, 0, 0, 128, 66, 0, 0, 210, 66, 0, 0, 128, 66, 0, 0, 0, 67, 0, 0, 128, 66, 0, 0, 1, 67, 0, 0, 128, 66, 0, 0, 2, 67, 0, 0, 128, 66, 0, 0, 3, 67, 0, 0, 128, 66, 0, 0, 4, 67, 0, 0, 128, 66, 0, 0, 5, 67, 0, 0, 128, 66, 0, 0, 6, 67, 0, 0, 128, 66, 0, 0, 7, 67, 0, 0, 128, 66, 0, 0, 8, 67, 0, 0, 128, 66, 0, 0, 9, 67, 0, 0, 128, 66, 0, 0, 10, 67, 0, 0, 128, 66, 0, 0, 11, 67, 0, 0, 128, 66, 0, 0, 12, 67, 0, 0, 128, 66, 0, 0, 13, 67, 0, 0, 128, 66, 0, 0, 43, 67, 0, 0, 128, 66, 0, 0, 44, 67, 0, 0, 128, 66, 0, 0, 45, 67, 0, 0, 128, 66, 0, 0, 46, 67, 0, 0, 128, 66, 0, 0, 47, 67, 0, 0, 128, 66, 0, 0, 48, 67, 0, 0, 128, 66, 0, 0, 49, 67, 0, 0, 128, 66, 0, 0, 50, 67, 0, 0, 128, 66, 0, 0, 51, 67, 0, 0, 128, 66, 0, 0, 52, 67, 0, 0, 128, 66, 0, 0, 53, 67, 0, 0, 128, 66, 0, 0, 54, 67, 0, 0, 128, 66, 0, 0, 55, 67, 0, 0, 130, 66, 0, 0, 184, 66, 0, 0, 130, 66, 0, 0, 186, 66, 0, 0, 130, 66, 0, 0, 188, 66, 0, 0, 130, 66, 0, 0, 190, 66, 0, 0, 130, 66, 0, 0, 192, 66, 0, 0, 130, 66, 0, 0, 194, 66, 0, 0, 130, 66, 0, 0, 196, 66, 0, 0, 130, 66, 0, 0, 198, 66, 0, 0, 130, 66, 0, 0, 200, 66, 0, 0, 130, 66, 0, 0, 202, 66, 0, 0, 130, 66, 0, 0, 204, 66, 0, 0, 130, 66, 0, 0, 206, 66, 0, 0, 130, 66, 0, 0, 208, 66, 0, 0, 130, 66, 0, 0, 0, 67, 0, 0, 130, 66, 0, 0, 1, 67, 0, 0, 130, 66, 0, 0, 2, 67, 0, 0, 130, 66, 0, 0, 3, 67, 0, 0, 130, 66, 0, 0, 4, 67, 0, 0, 130, 66, 0, 0, 5, 67, 0, 0, 130, 66, 0, 0, 6, 67, 0, 0, 130, 66, 0, 0, 7, 67, 0, 0, 130, 66, 0, 0, 8, 67, 0, 0, 130, 66, 0, 0, 9, 67, 0, 0, 130, 66, 0, 0, 10, 67, 0, 0, 130, 66, 0, 0, 11, 67, 0, 0, 130, 66, 0, 0, 12, 67, 0, 0, 130, 66, 0, 0, 13, 67, 0, 0, 130, 66, 0, 0, 43, 67, 0, 0, 130, 66, 0, 0, 44, 67, 0, 0, 130, 66, 0, 0, 45, 67, 0, 0, 130, 66, 0, 0, 46, 67, 0, 0, 130, 66, 0, 0, 47, 67, 0, 0, 130, 66, 0, 0, 48, 67, 0, 0, 130, 66, 0, 0, 49, 67, 0, 0, 130, 66, 0, 0, 50, 67, 0, 0, 130, 66, 0, 0, 51, 67, 0, 0, 130, 66, 0, 0, 52, 67, 0, 0, 130, 66, 0, 0, 53, 67, 0, 0, 130, 66, 0, 0, 54, 67, 0, 0, 130, 66, 0, 0, 55, 67, 0, 0, 132, 66, 0, 0, 184, 66, 0, 0, 132, 66, 0, 0, 186, 66, 0, 0, 132, 66, 0, 0, 188, 66, 0, 0, 132, 66, 0, 0, 190, 66, 0, 0, 132, 66, 0, 0, 192, 66, 0, 0, 132, 66, 0, 0, 194, 66, 0, 0, 132, 66, 0, 0, 196, 66, 0, 0, 132, 66, 0, 0, 198, 66, 0, 0, 132, 66, 0, 0, 200, 66, 0, 0, 132, 66, 0, 0, 202, 66, 0, 0, 132, 66, 0, 0, 204, 66, 0, 0, 132, 66, 0, 0, 206, 66, 0, 0, 132, 66, 0, 0, 0, 67, 0, 0, 132, 66, 0, 0, 1, 67, 0, 0, 132, 66, 0, 0, 2, 67, 0, 0, 132, 66, 0, 0, 3, 67, 0, 0, 132, 66, 0, 0, 4, 67, 0, 0, 132, 66, 0, 0, 5, 67, 0, 0, 132, 66, 0, 0, 6, 67, 0, 0, 132, 66, 0, 0, 7, 67, 0, 0, 132, 66, 0, 0, 8, 67, 0, 0, 132, 66, 0, 0, 9, 67, 0, 0, 132, 66, 0, 0, 10, 67, 0, 0, 132, 66, 0, 0, 11, 67, 0, 0, 132, 66, 0, 0, 12, 67, 0, 0, 132, 66, 0, 0, 13, 67, 0, 0, 132, 66, 0, 0, 44, 67, 0, 0, 132, 66, 0, 0, 45, 67, 0, 0, 132, 66, 0, 0, 46, 67, 0, 0, 132, 66, 0, 0, 47, 67, 0, 0, 132, 66, 0, 0, 48, 67, 0, 0, 132, 66, 0, 0, 49, 67, 0, 0, 132, 66, 0, 0, 50, 67, 0, 0, 132, 66, 0, 0, 51, 67, 0, 0, 132, 66, 0, 0, 52, 67, 0, 0, 132, 66, 0, 0, 53, 67, 0, 0, 132, 66, 0, 0, 54, 67, 0, 0, 132, 66, 0, 0, 55, 67, 0, 0, 134, 66, 0, 0, 184, 66, 0, 0, 134, 66, 0, 0, 186, 66, 0, 0, 134, 66, 0, 0, 188, 66, 0, 0, 134, 66, 0, 0, 190, 66, 0, 0, 134, 66, 0, 0, 192, 66, 0, 0, 134, 66, 0, 0, 194, 66, 0, 0, 134, 66, 0, 0, 196, 66, 0, 0, 134, 66, 0, 0, 198, 66, 0, 0, 134, 66, 0, 0, 200, 66, 0, 0, 134, 66, 0, 0, 202, 66, 0, 0, 134, 66, 0, 0, 204, 66, 0, 0, 134, 66, 0, 0, 206, 66, 0, 0, 134, 66, 0, 0, 0, 67, 0, 0, 134, 66, 0, 0, 1, 67, 0, 0, 134, 66, 0, 0, 2, 67, 0, 0, 134, 66, 0, 0, 3, 67, 0, 0, 134, 66, 0, 0, 4, 67, 0, 0, 134, 66, 0, 0, 5, 67, 0, 0, 134, 66, 0, 0, 6, 67, 0, 0, 134, 66, 0, 0, 7, 67, 0, 0, 134, 66, 0, 0, 8, 67, 0, 0, 134, 66, 0, 0, 9, 67, 0, 0, 134, 66, 0, 0, 10, 67, 0, 0, 134, 66, 0, 0, 11, 67, 0, 0, 134, 66, 0, 0, 12, 67, 0, 0, 134, 66, 0, 0, 13, 67, 0, 0, 134, 66, 0, 0, 44, 67, 0, 0, 134, 66, 0, 0, 45, 67, 0, 0, 134, 66, 0, 0, 46, 67, 0, 0, 134, 66, 0, 0, 47, 67, 0, 0, 134, 66, 0, 0, 48, 67, 0, 0, 134, 66, 0, 0, 49, 67, 0, 0, 134, 66, 0, 0, 50, 67, 0, 0, 134, 66, 0, 0, 51, 67, 0, 0, 134, 66, 0, 0, 52, 67, 0, 0, 134, 66, 0, 0, 53, 67, 0, 0, 134, 66, 0, 0, 54, 67, 0, 0, 134, 66, 0, 0, 55, 67, 0, 0, 136, 66, 0, 0, 184, 66, 0, 0, 136, 66, 0, 0, 186, 66, 0, 0, 136, 66, 0, 0, 188, 66, 0, 0, 136, 66, 0, 0, 190, 66, 0, 0, 136, 66, 0, 0, 192, 66, 0, 0, 136, 66, 0, 0, 194, 66, 0, 0, 136, 66, 0, 0, 196, 66, 0, 0, 136, 66, 0, 0, 198, 66, 0, 0, 136, 66, 0, 0, 200, 66, 0, 0, 136, 66, 0, 0, 202, 66, 0, 0, 136, 66, 0, 0, 204, 66, 0, 0, 136, 66, 0, 0, 206, 66, 0, 0, 136, 66, 0, 0, 0, 67, 0, 0, 136, 66, 0, 0, 1, 67, 0, 0, 136, 66, 0, 0, 2, 67, 0, 0, 136, 66, 0, 0, 3, 67, 0, 0, 136, 66, 0, 0, 4, 67, 0, 0, 136, 66, 0, 0, 5, 67, 0, 0, 136, 66, 0, 0, 6, 67, 0, 0, 136, 66, 0, 0, 7, 67, 0, 0, 136, 66, 0, 0, 8, 67, 0, 0, 136, 66, 0, 0, 9, 67, 0, 0, 136, 66, 0, 0, 10, 67, 0, 0, 136, 66, 0, 0, 11, 67, 0, 0, 136, 66, 0, 0, 12, 67, 0, 0, 136, 66, 0, 0, 13, 67, 0, 0, 136, 66, 0, 0, 44, 67, 0, 0, 136, 66, 0, 0, 45, 67, 0, 0, 136, 66, 0, 0, 46, 67, 0, 0, 136, 66, 0, 0, 47, 67, 0, 0, 136, 66, 0, 0, 48, 67, 0, 0, 136, 66, 0, 0, 49, 67, 0, 0, 136, 66, 0, 0, 50, 67, 0, 0, 136, 66, 0, 0, 51, 67, 0, 0, 136, 66, 0, 0, 52, 67, 0, 0, 136, 66, 0, 0, 53, 67, 0, 0, 136, 66, 0, 0, 54, 67, 0, 0, 136, 66, 0, 0, 55, 67, 0, 0, 138, 66, 0, 0, 184, 66, 0, 0, 138, 66, 0, 0, 186, 66, 0, 0, 138, 66, 0, 0, 188, 66, 0, 0, 138, 66, 0, 0, 190, 66, 0, 0, 138, 66, 0, 0, 192, 66, 0, 0, 138, 66, 0, 0, 194, 66, 0, 0, 138, 66, 0, 0, 196, 66, 0, 0, 138, 66, 0, 0, 198, 66, 0, 0, 138, 66, 0, 0, 200, 66, 0, 0, 138, 66, 0, 0, 202, 66, 0, 0, 138, 66, 0, 0, 204, 66, 0, 0, 138, 66, 0, 0, 206, 66, 0, 0, 138, 66, 0, 0, 0, 67, 0, 0, 138, 66, 0, 0, 1, 67, 0, 0, 138, 66, 0, 0, 2, 67, 0, 0, 138, 66, 0, 0, 3, 67, 0, 0, 138, 66, 0, 0, 4, 67, 0, 0, 138, 66, 0, 0, 5, 67, 0, 0, 138, 66, 0, 0, 6, 67, 0, 0, 138, 66, 0, 0, 7, 67, 0, 0, 138, 66, 0, 0, 8, 67, 0, 0, 138, 66, 0, 0, 9, 67, 0, 0, 138, 66, 0, 0, 10, 67, 0, 0, 138, 66, 0, 0, 11, 67, 0, 0, 138, 66, 0, 0, 12, 67, 0, 0, 138, 66, 0, 0, 13, 67, 0, 0, 138, 66, 0, 0, 44, 67, 0, 0, 138, 66, 0, 0, 45, 67, 0, 0, 138, 66, 0, 0, 46, 67, 0, 0, 138, 66, 0, 0, 47, 67, 0, 0, 138, 66, 0, 0, 48, 67, 0, 0, 138, 66, 0, 0, 49, 67, 0, 0, 138, 66, 0, 0, 50, 67, 0, 0, 138, 66, 0, 0, 51, 67, 0, 0, 138, 66, 0, 0, 52, 67, 0, 0, 138, 66, 0, 0, 53, 67, 0, 0, 138, 66, 0, 0, 54, 67, 0, 0, 138, 66, 0, 0, 55, 67, 0, 0, 140, 66, 0, 0, 184, 66, 0, 0, 140, 66, 0, 0, 186, 66, 0, 0, 140, 66, 0, 0, 188, 66, 0, 0, 140, 66, 0, 0, 190, 66, 0, 0, 140, 66, 0, 0, 192, 66, 0, 0, 140, 66, 0, 0, 194, 66, 0, 0, 140, 66, 0, 0, 196, 66, 0, 0, 140, 66, 0, 0, 198, 66, 0, 0, 140, 66, 0, 0, 200, 66, 0, 0, 140, 66, 0, 0, 202, 66, 0, 0, 140, 66, 0, 0, 204, 66, 0, 0, 140, 66, 0, 0, 206, 66, 0, 0, 140, 66, 0, 0, 0, 67, 0, 0, 140, 66, 0, 0, 1, 67, 0, 0, 140, 66, 0, 0, 2, 67, 0, 0, 140, 66, 0, 0, 3, 67, 0, 0, 140, 66, 0, 0, 4, 67, 0, 0, 140, 66, 0, 0, 5, 67, 0, 0, 140, 66, 0, 0, 6, 67, 0, 0, 140, 66, 0, 0, 7, 67, 0, 0, 140, 66, 0, 0, 8, 67, 0, 0, 140, 66, 0, 0, 9, 67, 0, 0, 140, 66, 0, 0, 10, 67, 0, 0, 140, 66, 0, 0, 11, 67, 0, 0, 140, 66, 0, 0, 12, 67, 0, 0, 140, 66, 0, 0, 13, 67, 0, 0, 140, 66, 0, 0, 45, 67, 0, 0, 140, 66, 0, 0, 46, 67, 0, 0, 140, 66, 0, 0, 47, 67, 0, 0, 140, 66, 0, 0, 48, 67, 0, 0, 140, 66, 0, 0, 49, 67, 0, 0, 140, 66, 0, 0, 50, 67, 0, 0, 140, 66, 0, 0, 51, 67, 0, 0, 140, 66, 0, 0, 52, 67, 0, 0, 140, 66, 0, 0, 53, 67, 0, 0, 140, 66, 0, 0, 54, 67, 0, 0, 140, 66, 0, 0, 55, 67, 0, 0, 142, 66, 0, 0, 184, 66, 0, 0, 142, 66, 0, 0, 186, 66, 0, 0, 142, 66, 0, 0, 188, 66, 0, 0, 142, 66, 0, 0, 190, 66, 0, 0, 142, 66, 0, 0, 192, 66, 0, 0, 142, 66, 0, 0, 194, 66, 0, 0, 142, 66, 0, 0, 196, 66, 0, 0, 142, 66, 0, 0, 198, 66, 0, 0, 142, 66, 0, 0, 200, 66, 0, 0, 142, 66, 0, 0, 202, 66, 0, 0, 142, 66, 0, 0, 204, 66, 0, 0, 142, 66, 0, 0, 206, 66, 0, 0, 142, 66, 0, 0, 0, 67, 0, 0, 142, 66, 0, 0, 1, 67, 0, 0, 142, 66, 0, 0, 2, 67, 0, 0, 142, 66, 0, 0, 3, 67, 0, 0, 142, 66, 0, 0, 4, 67, 0, 0, 142, 66, 0, 0, 5, 67, 0, 0, 142, 66, 0, 0, 6, 67, 0, 0, 142, 66, 0, 0, 7, 67, 0, 0, 142, 66, 0, 0, 8, 67, 0, 0, 142, 66, 0, 0, 9, 67, 0, 0, 142, 66, 0, 0, 10, 67, 0, 0, 142, 66, 0, 0, 11, 67, 0, 0, 142, 66, 0, 0, 12, 67, 0, 0, 142, 66, 0, 0, 13, 67, 0, 0, 142, 66, 0, 0, 45, 67, 0, 0, 142, 66, 0, 0, 46, 67, 0, 0, 142, 66, 0, 0, 47, 67, 0, 0, 142, 66, 0, 0, 48, 67, 0, 0, 142, 66, 0, 0, 49, 67, 0, 0, 142, 66, 0, 0, 50, 67, 0, 0, 142, 66, 0, 0, 51, 67, 0, 0, 142, 66, 0, 0, 52, 67, 0, 0, 142, 66, 0, 0, 53, 67, 0, 0, 142, 66, 0, 0, 54, 67, 0, 0, 142, 66, 0, 0, 55, 67, 0, 0, 144, 66, 0, 0, 184, 66, 0, 0, 144, 66, 0, 0, 186, 66, 0, 0, 144, 66, 0, 0, 188, 66, 0, 0, 144, 66, 0, 0, 190, 66, 0, 0, 144, 66, 0, 0, 192, 66, 0, 0, 144, 66, 0, 0, 194, 66, 0, 0, 144, 66, 0, 0, 196, 66, 0, 0, 144, 66, 0, 0, 198, 66, 0, 0, 144, 66, 0, 0, 200, 66, 0, 0, 144, 66, 0, 0, 202, 66, 0, 0, 144, 66, 0, 0, 204, 66, 0, 0, 144, 66, 0, 0, 0, 67, 0, 0, 144, 66, 0, 0, 1, 67, 0, 0, 144, 66, 0, 0, 2, 67, 0, 0, 144, 66, 0, 0, 3, 67, 0, 0, 144, 66, 0, 0, 4, 67, 0, 0, 144, 66, 0, 0, 5, 67, 0, 0, 144, 66, 0, 0, 6, 67, 0, 0, 144, 66, 0, 0, 7, 67, 0, 0, 144, 66, 0, 0, 8, 67, 0, 0, 144, 66, 0, 0, 9, 67, 0, 0, 144, 66, 0, 0, 10, 67, 0, 0, 144, 66, 0, 0, 11, 67, 0, 0, 144, 66, 0, 0, 12, 67, 0, 0, 144, 66, 0, 0, 13, 67, 0, 0, 144, 66, 0, 0, 45, 67, 0, 0, 144, 66, 0, 0, 46, 67, 0, 0, 144, 66, 0, 0, 47, 67, 0, 0, 144, 66, 0, 0, 48, 67, 0, 0, 144, 66, 0, 0, 49, 67, 0, 0, 144, 66, 0, 0, 50, 67, 0, 0, 144, 66, 0, 0, 51, 67, 0, 0, 144, 66, 0, 0, 52, 67, 0, 0, 144, 66, 0, 0, 53, 67, 0, 0, 144, 66, 0, 0, 54, 67, 0, 0, 144, 66, 0, 0, 55, 67, 0, 0, 146, 66, 0, 0, 184, 66, 0, 0, 146, 66, 0, 0, 186, 66, 0, 0, 146, 66, 0, 0, 188, 66, 0, 0, 146, 66, 0, 0, 190, 66, 0, 0, 146, 66, 0, 0, 192, 66, 0, 0, 146, 66, 0, 0, 194, 66, 0, 0, 146, 66, 0, 0, 196, 66, 0, 0, 146, 66, 0, 0, 198, 66, 0, 0, 146, 66, 0, 0, 200, 66, 0, 0, 146, 66, 0, 0, 202, 66, 0, 0, 146, 66, 0, 0, 0, 67, 0, 0, 146, 66, 0, 0, 1, 67, 0, 0, 146, 66, 0, 0, 2, 67, 0, 0, 146, 66, 0, 0, 3, 67, 0, 0, 146, 66, 0, 0, 4, 67, 0, 0, 146, 66, 0, 0, 5, 67, 0, 0, 146, 66, 0, 0, 6, 67, 0, 0, 146, 66, 0, 0, 7, 67, 0, 0, 146, 66, 0, 0, 8, 67, 0, 0, 146, 66, 0, 0, 9, 67, 0, 0, 146, 66, 0, 0, 10, 67, 0, 0, 146, 66, 0, 0, 11, 67, 0, 0, 146, 66, 0, 0, 12, 67, 0, 0, 146, 66, 0, 0, 13, 67, 0, 0, 146, 66, 0, 0, 46, 67, 0, 0, 146, 66, 0, 0, 47, 67, 0, 0, 146, 66, 0, 0, 48, 67, 0, 0, 146, 66, 0, 0, 49, 67, 0, 0, 146, 66, 0, 0, 50, 67, 0, 0, 146, 66, 0, 0, 51, 67, 0, 0, 146, 66, 0, 0, 52, 67, 0, 0, 146, 66, 0, 0, 53, 67, 0, 0, 146, 66, 0, 0, 54, 67, 0, 0, 146, 66, 0, 0, 55, 67, 0, 0, 148, 66, 0, 0, 0, 67, 0, 0, 148, 66, 0, 0, 1, 67, 0, 0, 148, 66, 0, 0, 2, 67, 0, 0, 148, 66, 0, 0, 3, 67, 0, 0, 148, 66, 0, 0, 4, 67, 0, 0, 148, 66, 0, 0, 5, 67, 0, 0, 148, 66, 0, 0, 6, 67, 0, 0, 148, 66, 0, 0, 7, 67, 0, 0, 148, 66, 0, 0, 8, 67, 0, 0, 148, 66, 0, 0, 9, 67, 0, 0, 148, 66, 0, 0, 10, 67, 0, 0, 148, 66, 0, 0, 11, 67, 0, 0, 148, 66, 0, 0, 12, 67, 0, 0, 148, 66, 0, 0, 13, 67, 0, 0, 150, 66, 0, 0, 0, 67, 0, 0, 150, 66, 0, 0, 1, 67, 0, 0, 150, 66, 0, 0, 2, 67, 0, 0, 150, 66, 0, 0, 3, 67, 0, 0, 150, 66, 0, 0, 4, 67, 0, 0, 150, 66, 0, 0, 5, 67, 0, 0, 150, 66, 0, 0, 6, 67, 0, 0, 150, 66, 0, 0, 7, 67, 0, 0, 150, 66, 0, 0, 8, 67, 0, 0, 150, 66, 0, 0, 9, 67, 0, 0, 150, 66, 0, 0, 10, 67, 0, 0, 150, 66, 0, 0, 11, 67, 0, 0, 150, 66, 0, 0, 12, 67, 0, 0, 150, 66, 0, 0, 13, 67, 0, 0, 152, 66, 0, 0, 0, 67, 0, 0, 152, 66, 0, 0, 1, 67, 0, 0, 152, 66, 0, 0, 2, 67, 0, 0, 152, 66, 0, 0, 3, 67, 0, 0, 152, 66, 0, 0, 4, 67, 0, 0, 152, 66, 0, 0, 5, 67, 0, 0, 152, 66, 0, 0, 6, 67, 0, 0, 152, 66, 0, 0, 7, 67, 0, 0, 152, 66, 0, 0, 8, 67, 0, 0, 152, 66, 0, 0, 9, 67, 0, 0, 152, 66, 0, 0, 10, 67, 0, 0, 152, 66, 0, 0, 11, 67, 0, 0, 152, 66, 0, 0, 12, 67, 0, 0, 152, 66, 0, 0, 13, 67, 0, 0, 154, 66, 0, 0, 0, 67, 0, 0, 154, 66, 0, 0, 1, 67, 0, 0, 154, 66, 0, 0, 2, 67, 0, 0, 154, 66, 0, 0, 3, 67, 0, 0, 154, 66, 0, 0, 4, 67, 0, 0, 154, 66, 0, 0, 5, 67, 0, 0, 154, 66, 0, 0, 6, 67, 0, 0, 154, 66, 0, 0, 7, 67, 0, 0, 154, 66, 0, 0, 8, 67, 0, 0, 154, 66, 0, 0, 9, 67, 0, 0, 154, 66, 0, 0, 10, 67, 0, 0, 154, 66, 0, 0, 11, 67, 0, 0, 154, 66, 0, 0, 12, 67, 0, 0, 154, 66, 0, 0, 13, 67, 0, 0, 156, 66, 0, 0, 0, 67, 0, 0, 156, 66, 0, 0, 1, 67, 0, 0, 156, 66, 0, 0, 2, 67, 0, 0, 156, 66, 0, 0, 3, 67, 0, 0, 156, 66, 0, 0, 4, 67, 0, 0, 156, 66, 0, 0, 5, 67, 0, 0, 156, 66, 0, 0, 6, 67, 0, 0, 156, 66, 0, 0, 7, 67, 0, 0, 156, 66, 0, 0, 8, 67, 0, 0, 156, 66, 0, 0, 9, 67, 0, 0, 156, 66, 0, 0, 10, 67, 0, 0, 156, 66, 0, 0, 11, 67, 0, 0, 156, 66, 0, 0, 12, 67, 0, 0, 156, 66, 0, 0, 13, 67, 0, 0, 158, 66, 0, 0, 0, 67, 0, 0, 158, 66, 0, 0, 1, 67, 0, 0, 158, 66, 0, 0, 2, 67, 0, 0, 158, 66, 0, 0, 3, 67, 0, 0, 158, 66, 0, 0, 4, 67, 0, 0, 158, 66, 0, 0, 5, 67, 0, 0, 158, 66, 0, 0, 6, 67, 0, 0, 158, 66, 0, 0, 7, 67, 0, 0, 158, 66, 0, 0, 8, 67, 0, 0, 158, 66, 0, 0, 9, 67, 0, 0, 158, 66, 0, 0, 10, 67, 0, 0, 158, 66, 0, 0, 11, 67, 0, 0, 158, 66, 0, 0, 12, 67, 0, 0, 158, 66, 0, 0, 13, 67, 0, 0, 160, 66, 0, 0, 0, 67, 0, 0, 160, 66, 0, 0, 1, 67, 0, 0, 160, 66, 0, 0, 2, 67, 0, 0, 160, 66, 0, 0, 3, 67, 0, 0, 160, 66, 0, 0, 4, 67, 0, 0, 160, 66, 0, 0, 5, 67, 0, 0, 160, 66, 0, 0, 6, 67, 0, 0, 160, 66, 0, 0, 7, 67, 0, 0, 160, 66, 0, 0, 8, 67, 0, 0, 160, 66, 0, 0, 9, 67, 0, 0, 160, 66, 0, 0, 10, 67, 0, 0, 160, 66, 0, 0, 11, 67, 0, 0, 160, 66, 0, 0, 12, 67, 0, 0, 160, 66, 0, 0, 13, 67, 0, 0, 162, 66, 0, 0, 0, 67, 0, 0, 162, 66, 0, 0, 1, 67, 0, 0, 162, 66, 0, 0, 2, 67, 0, 0, 162, 66, 0, 0, 3, 67, 0, 0, 162, 66, 0, 0, 4, 67, 0, 0, 162, 66, 0, 0, 5, 67, 0, 0, 162, 66, 0, 0, 6, 67, 0, 0, 162, 66, 0, 0, 7, 67, 0, 0, 162, 66, 0, 0, 8, 67, 0, 0, 162, 66, 0, 0, 9, 67, 0, 0, 162, 66, 0, 0, 10, 67, 0, 0, 162, 66, 0, 0, 11, 67, 0, 0, 162, 66, 0, 0, 12, 67, 0, 0, 162, 66, 0, 0, 13, 67, 0, 0, 164, 66, 0, 0, 0, 67, 0, 0, 164, 66, 0, 0, 1, 67, 0, 0, 164, 66, 0, 0, 2, 67, 0, 0, 164, 66, 0, 0, 3, 67, 0, 0, 164, 66, 0, 0, 4, 67, 0, 0, 164, 66, 0, 0, 5, 67, 0, 0, 164, 66, 0, 0, 6, 67, 0, 0, 164, 66, 0, 0, 7, 67, 0, 0, 164, 66, 0, 0, 8, 67, 0, 0, 164, 66, 0, 0, 9, 67, 0, 0, 164, 66, 0, 0, 10, 67, 0, 0, 164, 66, 0, 0, 11, 67, 0, 0, 164, 66, 0, 0, 12, 67, 0, 0, 164, 66, 0, 0, 13, 67, 0, 0, 166, 66, 0, 0, 0, 67, 0, 0, 166, 66, 0, 0, 1, 67, 0, 0, 166, 66, 0, 0, 2, 67, 0, 0, 166, 66, 0, 0, 3, 67, 0, 0, 166, 66, 0, 0, 4, 67, 0, 0, 166, 66, 0, 0, 5, 67, 0, 0, 166, 66, 0, 0, 6, 67, 0, 0, 166, 66, 0, 0, 7, 67, 0, 0, 166, 66, 0, 0, 8, 67, 0, 0, 166, 66, 0, 0, 9, 67, 0, 0, 166, 66, 0, 0, 10, 67, 0, 0, 166, 66, 0, 0, 11, 67, 0, 0, 166, 66, 0, 0, 12, 67, 0, 0, 166, 66, 0, 0, 13, 67, 0, 0, 168, 66, 0, 0, 184, 66, 0, 0, 168, 66, 0, 0, 186, 66, 0, 0, 168, 66, 0, 0, 188, 66, 0, 0, 168, 66, 0, 0, 190, 66, 0, 0, 168, 66, 0, 0, 192, 66, 0, 0, 168, 66, 0, 0, 194, 66, 0, 0, 168, 66, 0, 0, 196, 66, 0, 0, 168, 66, 0, 0, 198, 66, 0, 0, 168, 66, 0, 0, 200, 66, 0, 0, 168, 66, 0, 0, 202, 66, 0, 0, 168, 66, 0, 0, 0, 67, 0, 0, 168, 66, 0, 0, 1, 67, 0, 0, 168, 66, 0, 0, 2, 67, 0, 0, 168, 66, 0, 0, 3, 67, 0, 0, 168, 66, 0, 0, 4, 67, 0, 0, 168, 66, 0, 0, 5, 67, 0, 0, 168, 66, 0, 0, 6, 67, 0, 0, 168, 66, 0, 0, 7, 67, 0, 0, 168, 66, 0, 0, 8, 67, 0, 0, 168, 66, 0, 0, 9, 67, 0, 0, 168, 66, 0, 0, 10, 67, 0, 0, 168, 66, 0, 0, 11, 67, 0, 0, 168, 66, 0, 0, 12, 67, 0, 0, 168, 66, 0, 0, 13, 67, 0, 0, 168, 66, 0, 0, 46, 67, 0, 0, 168, 66, 0, 0, 47, 67, 0, 0, 168, 66, 0, 0, 48, 67, 0, 0, 168, 66, 0, 0, 49, 67, 0, 0, 168, 66, 0, 0, 50, 67, 0, 0, 168, 66, 0, 0, 51, 67, 0, 0, 168, 66, 0, 0, 52, 67, 0, 0, 168, 66, 0, 0, 53, 67, 0, 0, 168, 66, 0, 0, 54, 67, 0, 0, 168, 66, 0, 0, 55, 67, 0, 0, 170, 66, 0, 0, 184, 66, 0, 0, 170, 66, 0, 0, 186, 66, 0, 0, 170, 66, 0, 0, 188, 66, 0, 0, 170, 66, 0, 0, 190, 66, 0, 0, 170, 66, 0, 0, 192, 66, 0, 0, 170, 66, 0, 0, 194, 66, 0, 0, 170, 66, 0, 0, 196, 66, 0, 0, 170, 66, 0, 0, 198, 66, 0, 0, 170, 66, 0, 0, 200, 66, 0, 0, 170, 66, 0, 0, 202, 66, 0, 0, 170, 66, 0, 0, 204, 66, 0, 0, 170, 66, 0, 0, 0, 67, 0, 0, 170, 66, 0, 0, 1, 67, 0, 0, 170, 66, 0, 0, 2, 67, 0, 0, 170, 66, 0, 0, 3, 67, 0, 0, 170, 66, 0, 0, 4, 67, 0, 0, 170, 66, 0, 0, 5, 67, 0, 0, 170, 66, 0, 0, 6, 67, 0, 0, 170, 66, 0, 0, 7, 67, 0, 0, 170, 66, 0, 0, 8, 67, 0, 0, 170, 66, 0, 0, 9, 67, 0, 0, 170, 66, 0, 0, 10, 67, 0, 0, 170, 66, 0, 0, 11, 67, 0, 0, 170, 66, 0, 0, 12, 67, 0, 0, 170, 66, 0, 0, 13, 67, 0, 0, 170, 66, 0, 0, 45, 67, 0, 0, 170, 66, 0, 0, 46, 67, 0, 0, 170, 66, 0, 0, 47, 67, 0, 0, 170, 66, 0, 0, 48, 67, 0, 0, 170, 66, 0, 0, 49, 67, 0, 0, 170, 66, 0, 0, 50, 67, 0, 0, 170, 66, 0, 0, 51, 67, 0, 0, 170, 66, 0, 0, 52, 67, 0, 0, 170, 66, 0, 0, 53, 67, 0, 0, 170, 66, 0, 0, 54, 67, 0, 0, 170, 66, 0, 0, 55, 67, 0, 0, 172, 66, 0, 0, 184, 66, 0, 0, 172, 66, 0, 0, 186, 66, 0, 0, 172, 66, 0, 0, 188, 66, 0, 0, 172, 66, 0, 0, 190, 66, 0, 0, 172, 66, 0, 0, 192, 66, 0, 0, 172, 66, 0, 0, 194, 66, 0, 0, 172, 66, 0, 0, 196, 66, 0, 0, 172, 66, 0, 0, 198, 66, 0, 0, 172, 66, 0, 0, 200, 66, 0, 0, 172, 66, 0, 0, 202, 66, 0, 0, 172, 66, 0, 0, 204, 66, 0, 0, 172, 66, 0, 0, 206, 66, 0, 0, 172, 66, 0, 0, 0, 67, 0, 0, 172, 66, 0, 0, 1, 67, 0, 0, 172, 66, 0, 0, 2, 67, 0, 0, 172, 66, 0, 0, 3, 67, 0, 0, 172, 66, 0, 0, 4, 67, 0, 0, 172, 66, 0, 0, 5, 67, 0, 0, 172, 66, 0, 0, 6, 67, 0, 0, 172, 66, 0, 0, 7, 67, 0, 0, 172, 66, 0, 0, 8, 67, 0, 0, 172, 66, 0, 0, 9, 67, 0, 0, 172, 66, 0, 0, 10, 67, 0, 0, 172, 66, 0, 0, 11, 67, 0, 0, 172, 66, 0, 0, 12, 67, 0, 0, 172, 66, 0, 0, 13, 67, 0, 0, 172, 66, 0, 0, 45, 67, 0, 0, 172, 66, 0, 0, 46, 67, 0, 0, 172, 66, 0, 0, 47, 67, 0, 0, 172, 66, 0, 0, 48, 67, 0, 0, 172, 66, 0, 0, 49, 67, 0, 0, 172, 66, 0, 0, 50, 67, 0, 0, 172, 66, 0, 0, 51, 67, 0, 0, 172, 66, 0, 0, 52, 67, 0, 0, 172, 66, 0, 0, 53, 67, 0, 0, 172, 66, 0, 0, 54, 67, 0, 0, 172, 66, 0, 0, 55, 67, 0, 0, 174, 66, 0, 0, 184, 66, 0, 0, 174, 66, 0, 0, 186, 66, 0, 0, 174, 66, 0, 0, 188, 66, 0, 0, 174, 66, 0, 0, 190, 66, 0, 0, 174, 66, 0, 0, 192, 66, 0, 0, 174, 66, 0, 0, 194, 66, 0, 0, 174, 66, 0, 0, 196, 66, 0, 0, 174, 66, 0, 0, 198, 66, 0, 0, 174, 66, 0, 0, 200, 66, 0, 0, 174, 66, 0, 0, 202, 66, 0, 0, 174, 66, 0, 0, 204, 66, 0, 0, 174, 66, 0, 0, 206, 66, 0, 0, 174, 66, 0, 0, 0, 67, 0, 0, 174, 66, 0, 0, 1, 67, 0, 0, 174, 66, 0, 0, 2, 67, 0, 0, 174, 66, 0, 0, 3, 67, 0, 0, 174, 66, 0, 0, 4, 67, 0, 0, 174, 66, 0, 0, 5, 67, 0, 0, 174, 66, 0, 0, 6, 67, 0, 0, 174, 66, 0, 0, 7, 67, 0, 0, 174, 66, 0, 0, 8, 67, 0, 0, 174, 66, 0, 0, 9, 67, 0, 0, 174, 66, 0, 0, 10, 67, 0, 0, 174, 66, 0, 0, 11, 67, 0, 0, 174, 66, 0, 0, 12, 67, 0, 0, 174, 66, 0, 0, 13, 67, 0, 0, 174, 66, 0, 0, 45, 67, 0, 0, 174, 66, 0, 0, 46, 67, 0, 0, 174, 66, 0, 0, 47, 67, 0, 0, 174, 66, 0, 0, 48, 67, 0, 0, 174, 66, 0, 0, 49, 67, 0, 0, 174, 66, 0, 0, 50, 67, 0, 0, 174, 66, 0, 0, 51, 67, 0, 0, 174, 66, 0, 0, 52, 67, 0, 0, 174, 66, 0, 0, 53, 67, 0, 0, 174, 66, 0, 0, 54, 67, 0, 0, 174, 66, 0, 0, 55, 67, 0, 0, 176, 66, 0, 0, 184, 66, 0, 0, 176, 66, 0, 0, 186, 66, 0, 0, 176, 66, 0, 0, 188, 66, 0, 0, 176, 66, 0, 0, 190, 66, 0, 0, 176, 66, 0, 0, 192, 66, 0, 0, 176, 66, 0, 0, 194, 66, 0, 0, 176, 66, 0, 0, 196, 66, 0, 0, 176, 66, 0, 0, 198, 66, 0, 0, 176, 66, 0, 0, 200, 66, 0, 0, 176, 66, 0, 0, 202, 66, 0, 0, 176, 66, 0, 0, 204, 66, 0, 0, 176, 66, 0, 0, 206, 66, 0, 0, 176, 66, 0, 0, 0, 67, 0, 0, 176, 66, 0, 0, 1, 67, 0, 0, 176, 66, 0, 0, 2, 67, 0, 0, 176, 66, 0, 0, 3, 67, 0, 0, 176, 66, 0, 0, 4, 67, 0, 0, 176, 66, 0, 0, 5, 67, 0, 0, 176, 66, 0, 0, 6, 67, 0, 0, 176, 66, 0, 0, 7, 67, 0, 0, 176, 66, 0, 0, 8, 67, 0, 0, 176, 66, 0, 0, 9, 67, 0, 0, 176, 66, 0, 0, 10, 67, 0, 0, 176, 66, 0, 0, 11, 67, 0, 0, 176, 66, 0, 0, 12, 67, 0, 0, 176, 66, 0, 0, 13, 67, 0, 0, 176, 66, 0, 0, 44, 67, 0, 0, 176, 66, 0, 0, 45, 67, 0, 0, 176, 66, 0, 0, 46, 67, 0, 0, 176, 66, 0, 0, 47, 67, 0, 0, 176, 66, 0, 0, 48, 67, 0, 0, 176, 66, 0, 0, 49, 67, 0, 0, 176, 66, 0, 0, 50, 67, 0, 0, 176, 66, 0, 0, 51, 67, 0, 0, 176, 66, 0, 0, 52, 67, 0, 0, 176, 66, 0, 0, 53, 67, 0, 0, 176, 66, 0, 0, 54, 67, 0, 0, 176, 66, 0, 0, 55, 67, 0, 0, 178, 66, 0, 0, 184, 66, 0, 0, 178, 66, 0, 0, 186, 66, 0, 0, 178, 66, 0, 0, 188, 66, 0, 0, 178, 66, 0, 0, 190, 66, 0, 0, 178, 66, 0, 0, 192, 66, 0, 0, 178, 66, 0, 0, 194, 66, 0, 0, 178, 66, 0, 0, 196, 66, 0, 0, 178, 66, 0, 0, 198, 66, 0, 0, 178, 66, 0, 0, 200, 66, 0, 0, 178, 66, 0, 0, 202, 66, 0, 0, 178, 66, 0, 0, 204, 66, 0, 0, 178, 66, 0, 0, 206, 66, 0, 0, 178, 66, 0, 0, 0, 67, 0, 0, 178, 66, 0, 0, 1, 67, 0, 0, 178, 66, 0, 0, 2, 67, 0, 0, 178, 66, 0, 0, 3, 67, 0, 0, 178, 66, 0, 0, 4, 67, 0, 0, 178, 66, 0, 0, 5, 67, 0, 0, 178, 66, 0, 0, 6, 67, 0, 0, 178, 66, 0, 0, 7, 67, 0, 0, 178, 66, 0, 0, 8, 67, 0, 0, 178, 66, 0, 0, 9, 67, 0, 0, 178, 66, 0, 0, 10, 67, 0, 0, 178, 66, 0, 0, 11, 67, 0, 0, 178, 66, 0, 0, 12, 67, 0, 0, 178, 66, 0, 0, 13, 67, 0, 0, 178, 66, 0, 0, 44, 67, 0, 0, 178, 66, 0, 0, 45, 67, 0, 0, 178, 66, 0, 0, 46, 67, 0, 0, 178, 66, 0, 0, 47, 67, 0, 0, 178, 66, 0, 0, 48, 67, 0, 0, 178, 66, 0, 0, 49, 67, 0, 0, 178, 66, 0, 0, 50, 67, 0, 0, 178, 66, 0, 0, 51, 67, 0, 0, 178, 66, 0, 0, 52, 67, 0, 0, 178, 66, 0, 0, 53, 67, 0, 0, 178, 66, 0, 0, 54, 67, 0, 0, 178, 66, 0, 0, 55, 67, 0, 0, 180, 66, 0, 0, 184, 66, 0, 0, 180, 66, 0, 0, 186, 66, 0, 0, 180, 66, 0, 0, 188, 66, 0, 0, 180, 66, 0, 0, 190, 66, 0, 0, 180, 66, 0, 0, 192, 66, 0, 0, 180, 66, 0, 0, 194, 66, 0, 0, 180, 66, 0, 0, 196, 66, 0, 0, 180, 66, 0, 0, 198, 66, 0, 0, 180, 66, 0, 0, 200, 66, 0, 0, 180, 66, 0, 0, 202, 66, 0, 0, 180, 66, 0, 0, 204, 66, 0, 0, 180, 66, 0, 0, 206, 66, 0, 0, 180, 66, 0, 0, 0, 67, 0, 0, 180, 66, 0, 0, 1, 67, 0, 0, 180, 66, 0, 0, 2, 67, 0, 0, 180, 66, 0, 0, 3, 67, 0, 0, 180, 66, 0, 0, 4, 67, 0, 0, 180, 66, 0, 0, 5, 67, 0, 0, 180, 66, 0, 0, 6, 67, 0, 0, 180, 66, 0, 0, 7, 67, 0, 0, 180, 66, 0, 0, 8, 67, 0, 0, 180, 66, 0, 0, 9, 67, 0, 0, 180, 66, 0, 0, 10, 67, 0, 0, 180, 66, 0, 0, 11, 67, 0, 0, 180, 66, 0, 0, 12, 67, 0, 0, 180, 66, 0, 0, 13, 67, 0, 0, 180, 66, 0, 0, 44, 67, 0, 0, 180, 66, 0, 0, 45, 67, 0, 0, 180, 66, 0, 0, 46, 67, 0, 0, 180, 66, 0, 0, 47, 67, 0, 0, 180, 66, 0, 0, 48, 67, 0, 0, 180, 66, 0, 0, 49, 67, 0, 0, 180, 66, 0, 0, 50, 67, 0, 0, 180, 66, 0, 0, 51, 67, 0, 0, 180, 66, 0, 0, 52, 67, 0, 0, 180, 66, 0, 0, 53, 67, 0, 0, 180, 66, 0, 0, 54, 67, 0, 0, 180, 66, 0, 0, 55, 67, 0, 0, 182, 66, 0, 0, 184, 66, 0, 0, 182, 66, 0, 0, 186, 66, 0, 0, 182, 66, 0, 0, 188, 66, 0, 0, 182, 66, 0, 0, 190, 66, 0, 0, 182, 66, 0, 0, 192, 66, 0, 0, 182, 66, 0, 0, 194, 66, 0, 0, 182, 66, 0, 0, 196, 66, 0, 0, 182, 66, 0, 0, 198, 66, 0, 0, 182, 66, 0, 0, 200, 66, 0, 0, 182, 66, 0, 0, 202, 66, 0, 0, 182, 66, 0, 0, 204, 66, 0, 0, 182, 66, 0, 0, 206, 66, 0, 0, 182, 66, 0, 0, 0, 67, 0, 0, 182, 66, 0, 0, 1, 67, 0, 0, 182, 66, 0, 0, 2, 67, 0, 0, 182, 66, 0, 0, 3, 67, 0, 0, 182, 66, 0, 0, 4, 67, 0, 0, 182, 66, 0, 0, 5, 67, 0, 0, 182, 66, 0, 0, 6, 67, 0, 0, 182, 66, 0, 0, 7, 67, 0, 0, 182, 66, 0, 0, 8, 67, 0, 0, 182, 66, 0, 0, 9, 67, 0, 0, 182, 66, 0, 0, 10, 67, 0, 0, 182, 66, 0, 0, 11, 67, 0, 0, 182, 66, 0, 0, 12, 67, 0, 0, 182, 66, 0, 0, 13, 67, 0, 0, 182, 66, 0, 0, 44, 67, 0, 0, 182, 66, 0, 0, 45, 67, 0, 0, 182, 66, 0, 0, 46, 67, 0, 0, 182, 66, 0, 0, 47, 67, 0, 0, 182, 66, 0, 0, 48, 67, 0, 0, 182, 66, 0, 0, 49, 67, 0, 0, 182, 66, 0, 0, 50, 67, 0, 0, 182, 66, 0, 0, 51, 67, 0, 0, 182, 66, 0, 0, 52, 67, 0, 0, 182, 66, 0, 0, 53, 67, 0, 0, 182, 66, 0, 0, 54, 67, 0, 0, 182, 66, 0, 0, 55, 67, 0, 0, 184, 66, 0, 0, 184, 66, 0, 0, 184, 66, 0, 0, 186, 66, 0, 0, 184, 66, 0, 0, 188, 66, 0, 0, 184, 66, 0, 0, 190, 66, 0, 0, 184, 66, 0, 0, 192, 66, 0, 0, 184, 66, 0, 0, 194, 66, 0, 0, 184, 66, 0, 0, 196, 66, 0, 0, 184, 66, 0, 0, 198, 66, 0, 0, 184, 66, 0, 0, 200, 66, 0, 0, 184, 66, 0, 0, 202, 66, 0, 0, 184, 66, 0, 0, 204, 66, 0, 0, 184, 66, 0, 0, 206, 66, 0, 0, 184, 66, 0, 0, 208, 66, 0, 0, 184, 66, 0, 0, 0, 67, 0, 0, 184, 66, 0, 0, 1, 67, 0, 0, 184, 66, 0, 0, 2, 67, 0, 0, 184, 66, 0, 0, 3, 67, 0, 0, 184, 66, 0, 0, 4, 67, 0, 0, 184, 66, 0, 0, 5, 67, 0, 0, 184, 66, 0, 0, 6, 67, 0, 0, 184, 66, 0, 0, 7, 67, 0, 0, 184, 66, 0, 0, 8, 67, 0, 0, 184, 66, 0, 0, 9, 67, 0, 0, 184, 66, 0, 0, 10, 67, 0, 0, 184, 66, 0, 0, 11, 67, 0, 0, 184, 66, 0, 0, 12, 67, 0, 0, 184, 66, 0, 0, 13, 67, 0, 0, 184, 66, 0, 0, 43, 67, 0, 0, 184, 66, 0, 0, 44, 67, 0, 0, 184, 66, 0, 0, 45, 67, 0, 0, 184, 66, 0, 0, 46, 67, 0, 0, 184, 66, 0, 0, 47, 67, 0, 0, 184, 66, 0, 0, 48, 67, 0, 0, 184, 66, 0, 0, 49, 67, 0, 0, 184, 66, 0, 0, 50, 67, 0, 0, 184, 66, 0, 0, 51, 67, 0, 0, 184, 66, 0, 0, 52, 67, 0, 0, 184, 66, 0, 0, 53, 67, 0, 0, 184, 66, 0, 0, 54, 67, 0, 0, 184, 66, 0, 0, 55, 67, 0, 0, 186, 66, 0, 0, 184, 66, 0, 0, 186, 66, 0, 0, 186, 66, 0, 0, 186, 66, 0, 0, 188, 66, 0, 0, 186, 66, 0, 0, 190, 66, 0, 0, 186, 66, 0, 0, 192, 66, 0, 0, 186, 66, 0, 0, 194, 66, 0, 0, 186, 66, 0, 0, 196, 66, 0, 0, 186, 66, 0, 0, 198, 66, 0, 0, 186, 66, 0, 0, 200, 66, 0, 0, 186, 66, 0, 0, 202, 66, 0, 0, 186, 66, 0, 0, 204, 66, 0, 0, 186, 66, 0, 0, 206, 66, 0, 0, 186, 66, 0, 0, 208, 66, 0, 0, 186, 66, 0, 0, 210, 66, 0, 0, 186, 66, 0, 0, 0, 67, 0, 0, 186, 66, 0, 0, 1, 67, 0, 0, 186, 66, 0, 0, 2, 67, 0, 0, 186, 66, 0, 0, 3, 67, 0, 0, 186, 66, 0, 0, 4, 67, 0, 0, 186, 66, 0, 0, 5, 67, 0, 0, 186, 66, 0, 0, 6, 67, 0, 0, 186, 66, 0, 0, 7, 67, 0, 0, 186, 66, 0, 0, 8, 67, 0, 0, 186, 66, 0, 0, 9, 67, 0, 0, 186, 66, 0, 0, 10, 67, 0, 0, 186, 66, 0, 0, 11, 67, 0, 0, 186, 66, 0, 0, 12, 67, 0, 0, 186, 66, 0, 0, 13, 67, 0, 0, 186, 66, 0, 0, 43, 67, 0, 0, 186, 66, 0, 0, 44, 67, 0, 0, 186, 66, 0, 0, 45, 67, 0, 0, 186, 66, 0, 0, 46, 67, 0, 0, 186, 66, 0, 0, 47, 67, 0, 0, 186, 66, 0, 0, 48, 67, 0, 0, 186, 66, 0, 0, 49, 67, 0, 0, 186, 66, 0, 0, 50, 67, 0, 0, 186, 66, 0, 0, 51, 67, 0, 0, 186, 66, 0, 0, 52, 67, 0, 0, 186, 66, 0, 0, 53, 67, 0, 0, 186, 66, 0, 0, 54, 67, 0, 0, 186, 66, 0, 0, 55, 67, 0, 0, 188, 66, 0, 0, 184, 66, 0, 0, 188, 66, 0, 0, 186, 66, 0, 0, 188, 66, 0, 0, 188, 66, 0, 0, 188, 66, 0, 0, 190, 66, 0, 0, 188, 66, 0, 0, 192, 66, 0, 0, 188, 66, 0, 0, 194, 66, 0, 0, 188, 66, 0, 0, 196, 66, 0, 0, 188, 66, 0, 0, 198, 66, 0, 0, 188, 66, 0, 0, 200, 66, 0, 0, 188, 66, 0, 0, 202, 66, 0, 0, 188, 66, 0, 0, 204, 66, 0, 0, 188, 66, 0, 0, 206, 66, 0, 0, 188, 66, 0, 0, 208, 66, 0, 0, 188, 66, 0, 0, 210, 66, 0, 0, 188, 66, 0, 0, 212, 66, 0, 0, 188, 66, 0, 0, 0, 67, 0, 0, 188, 66, 0, 0, 1, 67, 0, 0, 188, 66, 0, 0, 2, 67, 0, 0, 188, 66, 0, 0, 3, 67, 0, 0, 188, 66, 0, 0, 4, 67, 0, 0, 188, 66, 0, 0, 5, 67, 0, 0, 188, 66, 0, 0, 6, 67, 0, 0, 188, 66, 0, 0, 7, 67, 0, 0, 188, 66, 0, 0, 8, 67, 0, 0, 188, 66, 0, 0, 9, 67, 0, 0, 188, 66, 0, 0, 10, 67, 0, 0, 188, 66, 0, 0, 11, 67, 0, 0, 188, 66, 0, 0, 12, 67, 0, 0, 188, 66, 0, 0, 13, 67, 0, 0, 188, 66, 0, 0, 41, 67, 0, 0, 188, 66, 0, 0, 42, 67, 0, 0, 188, 66, 0, 0, 43, 67, 0, 0, 188, 66, 0, 0, 44, 67, 0, 0, 188, 66, 0, 0, 45, 67, 0, 0, 188, 66, 0, 0, 46, 67, 0, 0, 188, 66, 0, 0, 47, 67, 0, 0, 188, 66, 0, 0, 48, 67, 0, 0, 188, 66, 0, 0, 49, 67, 0, 0, 188, 66, 0, 0, 50, 67, 0, 0, 188, 66, 0, 0, 51, 67, 0, 0, 188, 66, 0, 0, 52, 67, 0, 0, 188, 66, 0, 0, 53, 67, 0, 0, 188, 66, 0, 0, 54, 67, 0, 0, 188, 66, 0, 0, 55, 67, 0, 0, 190, 66, 0, 0, 184, 66, 0, 0, 190, 66, 0, 0, 186, 66, 0, 0, 190, 66, 0, 0, 188, 66, 0, 0, 190, 66, 0, 0, 190, 66, 0, 0, 190, 66, 0, 0, 192, 66, 0, 0, 190, 66, 0, 0, 194, 66, 0, 0, 190, 66, 0, 0, 196, 66, 0, 0, 190, 66, 0, 0, 198, 66, 0, 0, 190, 66, 0, 0, 200, 66, 0, 0, 190, 66, 0, 0, 202, 66, 0, 0, 190, 66, 0, 0, 204, 66, 0, 0, 190, 66, 0, 0, 206, 66, 0, 0, 190, 66, 0, 0, 208, 66, 0, 0, 190, 66, 0, 0, 210, 66, 0, 0, 190, 66, 0, 0, 212, 66, 0, 0, 190, 66, 0, 0, 214, 66, 0, 0, 190, 66, 0, 0, 216, 66, 0, 0, 190, 66, 0, 0, 0, 67, 0, 0, 190, 66, 0, 0, 1, 67, 0, 0, 190, 66, 0, 0, 2, 67, 0, 0, 190, 66, 0, 0, 3, 67, 0, 0, 190, 66, 0, 0, 4, 67, 0, 0, 190, 66, 0, 0, 5, 67, 0, 0, 190, 66, 0, 0, 6, 67, 0, 0, 190, 66, 0, 0, 7, 67, 0, 0, 190, 66, 0, 0, 8, 67, 0, 0, 190, 66, 0, 0, 9, 67, 0, 0, 190, 66, 0, 0, 10, 67, 0, 0, 190, 66, 0, 0, 11, 67, 0, 0, 190, 66, 0, 0, 12, 67, 0, 0, 190, 66, 0, 0, 13, 67, 0, 0, 190, 66, 0, 0, 40, 67, 0, 0, 190, 66, 0, 0, 41, 67, 0, 0, 190, 66, 0, 0, 42, 67, 0, 0, 190, 66, 0, 0, 43, 67, 0, 0, 190, 66, 0, 0, 44, 67, 0, 0, 190, 66, 0, 0, 45, 67, 0, 0, 190, 66, 0, 0, 46, 67, 0, 0, 190, 66, 0, 0, 47, 67, 0, 0, 190, 66, 0, 0, 48, 67, 0, 0, 190, 66, 0, 0, 49, 67, 0, 0, 190, 66, 0, 0, 50, 67, 0, 0, 190, 66, 0, 0, 51, 67, 0, 0, 190, 66, 0, 0, 52, 67, 0, 0, 190, 66, 0, 0, 53, 67, 0, 0, 190, 66, 0, 0, 54, 67, 0, 0, 190, 66, 0, 0, 55, 67, 0, 0, 192, 66, 0, 0, 184, 66, 0, 0, 192, 66, 0, 0, 186, 66, 0, 0, 192, 66, 0, 0, 188, 66, 0, 0, 192, 66, 0, 0, 190, 66, 0, 0, 192, 66, 0, 0, 192, 66, 0, 0, 192, 66, 0, 0, 194, 66, 0, 0, 192, 66, 0, 0, 196, 66, 0, 0, 192, 66, 0, 0, 198, 66, 0, 0, 192, 66, 0, 0, 200, 66, 0, 0, 192, 66, 0, 0, 202, 66, 0, 0, 192, 66, 0, 0, 204, 66, 0, 0, 192, 66, 0, 0, 206, 66, 0, 0, 192, 66, 0, 0, 208, 66, 0, 0, 192, 66, 0, 0, 210, 66, 0, 0, 192, 66, 0, 0, 212, 66, 0, 0, 192, 66, 0, 0, 214, 66, 0, 0, 192, 66, 0, 0, 216, 66, 0, 0, 192, 66, 0, 0, 218, 66, 0, 0, 192, 66, 0, 0, 220, 66, 0, 0, 192, 66, 0, 0, 222, 66, 0, 0, 192, 66, 0, 0, 224, 66, 0, 0, 192, 66, 0, 0, 226, 66, 0, 0, 192, 66, 0, 0, 228, 66, 0, 0, 192, 66, 0, 0, 230, 66, 0, 0, 192, 66, 0, 0, 232, 66, 0, 0, 192, 66, 0, 0, 234, 66, 0, 0, 192, 66, 0, 0, 236, 66, 0, 0, 192, 66, 0, 0, 238, 66, 0, 0, 192, 66, 0, 0, 240, 66, 0, 0, 192, 66, 0, 0, 242, 66, 0, 0, 192, 66, 0, 0, 244, 66, 0, 0, 192, 66, 0, 0, 246, 66, 0, 0, 192, 66, 0, 0, 248, 66, 0, 0, 192, 66, 0, 0, 250, 66, 0, 0, 192, 66, 0, 0, 252, 66, 0, 0, 192, 66, 0, 0, 254, 66, 0, 0, 192, 66, 0, 0, 0, 67, 0, 0, 192, 66, 0, 0, 1, 67, 0, 0, 192, 66, 0, 0, 2, 67, 0, 0, 192, 66, 0, 0, 3, 67, 0, 0, 192, 66, 0, 0, 4, 67, 0, 0, 192, 66, 0, 0, 5, 67, 0, 0, 192, 66, 0, 0, 6, 67, 0, 0, 192, 66, 0, 0, 7, 67, 0, 0, 192, 66, 0, 0, 8, 67, 0, 0, 192, 66, 0, 0, 9, 67, 0, 0, 192, 66, 0, 0, 10, 67, 0, 0, 192, 66, 0, 0, 11, 67, 0, 0, 192, 66, 0, 0, 12, 67, 0, 0, 192, 66, 0, 0, 13, 67, 0, 0, 192, 66, 0, 0, 14, 67, 0, 0, 192, 66, 0, 0, 15, 67, 0, 0, 192, 66, 0, 0, 16, 67, 0, 0, 192, 66, 0, 0, 17, 67, 0, 0, 192, 66, 0, 0, 18, 67, 0, 0, 192, 66, 0, 0, 19, 67, 0, 0, 192, 66, 0, 0, 20, 67, 0, 0, 192, 66, 0, 0, 21, 67, 0, 0, 192, 66, 0, 0, 22, 67, 0, 0, 192, 66, 0, 0, 23, 67, 0, 0, 192, 66, 0, 0, 24, 67, 0, 0, 192, 66, 0, 0, 25, 67, 0, 0, 192, 66, 0, 0, 26, 67, 0, 0, 192, 66, 0, 0, 27, 67, 0, 0, 192, 66, 0, 0, 28, 67, 0, 0, 192, 66, 0, 0, 29, 67, 0, 0, 192, 66, 0, 0, 30, 67, 0, 0, 192, 66, 0, 0, 31, 67, 0, 0, 192, 66, 0, 0, 32, 67, 0, 0, 192, 66, 0, 0, 33, 67, 0, 0, 192, 66, 0, 0, 34, 67, 0, 0, 192, 66, 0, 0, 35, 67, 0, 0, 192, 66, 0, 0, 36, 67, 0, 0, 192, 66, 0, 0, 37, 67, 0, 0, 192, 66, 0, 0, 38, 67, 0, 0, 192, 66, 0, 0, 39, 67, 0, 0, 192, 66, 0, 0, 40, 67, 0, 0, 192, 66, 0, 0, 41, 67, 0, 0, 192, 66, 0, 0, 42, 67, 0, 0, 192, 66, 0, 0, 43, 67, 0, 0, 192, 66, 0, 0, 44, 67, 0, 0, 192, 66, 0, 0, 45, 67, 0, 0, 192, 66, 0, 0, 46, 67, 0, 0, 192, 66, 0, 0, 47, 67, 0, 0, 192, 66, 0, 0, 48, 67, 0, 0, 192, 66, 0, 0, 49, 67, 0, 0, 192, 66, 0, 0, 50, 67, 0, 0, 192, 66, 0, 0, 51, 67, 0, 0, 192, 66, 0, 0, 52, 67, 0, 0, 192, 66, 0, 0, 53, 67, 0, 0, 192, 66, 0, 0, 54, 67, 0, 0, 192, 66, 0, 0, 55, 67, 0, 0, 194, 66, 0, 0, 184, 66, 0, 0, 194, 66, 0, 0, 186, 66, 0, 0, 194, 66, 0, 0, 188, 66, 0, 0, 194, 66, 0, 0, 190, 66, 0, 0, 194, 66, 0, 0, 192, 66, 0, 0, 194, 66, 0, 0, 194, 66, 0, 0, 194, 66, 0, 0, 196, 66, 0, 0, 194, 66, 0, 0, 198, 66, 0, 0, 194, 66, 0, 0, 200, 66, 0, 0, 194, 66, 0, 0, 202, 66, 0, 0, 194, 66, 0, 0, 204, 66, 0, 0, 194, 66, 0, 0, 206, 66, 0, 0, 194, 66, 0, 0, 208, 66, 0, 0, 194, 66, 0, 0, 210, 66, 0, 0, 194, 66, 0, 0, 212, 66, 0, 0, 194, 66, 0, 0, 214, 66, 0, 0, 194, 66, 0, 0, 216, 66, 0, 0, 194, 66, 0, 0, 218, 66, 0, 0, 194, 66, 0, 0, 220, 66, 0, 0, 194, 66, 0, 0, 222, 66, 0, 0, 194, 66, 0, 0, 224, 66, 0, 0, 194, 66, 0, 0, 226, 66, 0, 0, 194, 66, 0, 0, 228, 66, 0, 0, 194, 66, 0, 0, 230, 66, 0, 0, 194, 66, 0, 0, 232, 66, 0, 0, 194, 66, 0, 0, 234, 66, 0, 0, 194, 66, 0, 0, 236, 66, 0, 0, 194, 66, 0, 0, 238, 66, 0, 0, 194, 66, 0, 0, 240, 66, 0, 0, 194, 66, 0, 0, 242, 66, 0, 0, 194, 66, 0, 0, 244, 66, 0, 0, 194, 66, 0, 0, 246, 66, 0, 0, 194, 66, 0, 0, 248, 66, 0, 0, 194, 66, 0, 0, 250, 66, 0, 0, 194, 66, 0, 0, 252, 66, 0, 0, 194, 66, 0, 0, 254, 66, 0, 0, 194, 66, 0, 0, 0, 67, 0, 0, 194, 66, 0, 0, 1, 67, 0, 0, 194, 66, 0, 0, 2, 67, 0, 0, 194, 66, 0, 0, 3, 67, 0, 0, 194, 66, 0, 0, 4, 67, 0, 0, 194, 66, 0, 0, 5, 67, 0, 0, 194, 66, 0, 0, 6, 67, 0, 0, 194, 66, 0, 0, 7, 67, 0, 0, 194, 66, 0, 0, 8, 67, 0, 0, 194, 66, 0, 0, 9, 67, 0, 0, 194, 66, 0, 0, 10, 67, 0, 0, 194, 66, 0, 0, 11, 67, 0, 0, 194, 66, 0, 0, 12, 67, 0, 0, 194, 66, 0, 0, 13, 67, 0, 0, 194, 66, 0, 0, 14, 67, 0, 0, 194, 66, 0, 0, 15, 67, 0, 0, 194, 66, 0, 0, 16, 67, 0, 0, 194, 66, 0, 0, 17, 67, 0, 0, 194, 66, 0, 0, 18, 67, 0, 0, 194, 66, 0, 0, 19, 67, 0, 0, 194, 66, 0, 0, 20, 67, 0, 0, 194, 66, 0, 0, 21, 67, 0, 0, 194, 66, 0, 0, 22, 67, 0, 0, 194, 66, 0, 0, 23, 67, 0, 0, 194, 66, 0, 0, 24, 67, 0, 0, 194, 66, 0, 0, 25, 67, 0, 0, 194, 66, 0, 0, 26, 67, 0, 0, 194, 66, 0, 0, 27, 67, 0, 0, 194, 66, 0, 0, 28, 67, 0, 0, 194, 66, 0, 0, 29, 67, 0, 0, 194, 66, 0, 0, 30, 67, 0, 0, 194, 66, 0, 0, 31, 67, 0, 0, 194, 66, 0, 0, 32, 67, 0, 0, 194, 66, 0, 0, 33, 67, 0, 0, 194, 66, 0, 0, 34, 67, 0, 0, 194, 66, 0, 0, 35, 67, 0, 0, 194, 66, 0, 0, 36, 67, 0, 0, 194, 66, 0, 0, 37, 67, 0, 0, 194, 66, 0, 0, 38, 67, 0, 0, 194, 66, 0, 0, 39, 67, 0, 0, 194, 66, 0, 0, 40, 67, 0, 0, 194, 66, 0, 0, 41, 67, 0, 0, 194, 66, 0, 0, 42, 67, 0, 0, 194, 66, 0, 0, 43, 67, 0, 0, 194, 66, 0, 0, 44, 67, 0, 0, 194, 66, 0, 0, 45, 67, 0, 0, 194, 66, 0, 0, 46, 67, 0, 0, 194, 66, 0, 0, 47, 67, 0, 0, 194, 66, 0, 0, 48, 67, 0, 0, 194, 66, 0, 0, 49, 67, 0, 0, 194, 66, 0, 0, 50, 67, 0, 0, 194, 66, 0, 0, 51, 67, 0, 0, 194, 66, 0, 0, 52, 67, 0, 0, 194, 66, 0, 0, 53, 67, 0, 0, 194, 66, 0, 0, 54, 67, 0, 0, 194, 66, 0, 0, 55, 67, 0, 0, 196, 66, 0, 0, 184, 66, 0, 0, 196, 66, 0, 0, 186, 66, 0, 0, 196, 66, 0, 0, 188, 66, 0, 0, 196, 66, 0, 0, 190, 66, 0, 0, 196, 66, 0, 0, 192, 66, 0, 0, 196, 66, 0, 0, 194, 66, 0, 0, 196, 66, 0, 0, 196, 66, 0, 0, 196, 66, 0, 0, 198, 66, 0, 0, 196, 66, 0, 0, 200, 66, 0, 0, 196, 66, 0, 0, 202, 66, 0, 0, 196, 66, 0, 0, 204, 66, 0, 0, 196, 66, 0, 0, 206, 66, 0, 0, 196, 66, 0, 0, 208, 66, 0, 0, 196, 66, 0, 0, 210, 66, 0, 0, 196, 66, 0, 0, 212, 66, 0, 0, 196, 66, 0, 0, 214, 66, 0, 0, 196, 66, 0, 0, 216, 66, 0, 0, 196, 66, 0, 0, 218, 66, 0, 0, 196, 66, 0, 0, 220, 66, 0, 0, 196, 66, 0, 0, 222, 66, 0, 0, 196, 66, 0, 0, 224, 66, 0, 0, 196, 66, 0, 0, 226, 66, 0, 0, 196, 66, 0, 0, 228, 66, 0, 0, 196, 66, 0, 0, 230, 66, 0, 0, 196, 66, 0, 0, 232, 66, 0, 0, 196, 66, 0, 0, 234, 66, 0, 0, 196, 66, 0, 0, 236, 66, 0, 0, 196, 66, 0, 0, 238, 66, 0, 0, 196, 66, 0, 0, 240, 66, 0, 0, 196, 66, 0, 0, 242, 66, 0, 0, 196, 66, 0, 0, 244, 66, 0, 0, 196, 66, 0, 0, 246, 66, 0, 0, 196, 66, 0, 0, 248, 66, 0, 0, 196, 66, 0, 0, 250, 66, 0, 0, 196, 66, 0, 0, 252, 66, 0, 0, 196, 66, 0, 0, 254, 66, 0, 0, 196, 66, 0, 0, 0, 67, 0, 0, 196, 66, 0, 0, 1, 67, 0, 0, 196, 66, 0, 0, 2, 67, 0, 0, 196, 66, 0, 0, 3, 67, 0, 0, 196, 66, 0, 0, 4, 67, 0, 0, 196, 66, 0, 0, 5, 67, 0, 0, 196, 66, 0, 0, 6, 67, 0, 0, 196, 66, 0, 0, 7, 67, 0, 0, 196, 66, 0, 0, 8, 67, 0, 0, 196, 66, 0, 0, 9, 67, 0, 0, 196, 66, 0, 0, 10, 67, 0, 0, 196, 66, 0, 0, 11, 67, 0, 0, 196, 66, 0, 0, 12, 67, 0, 0, 196, 66, 0, 0, 13, 67, 0, 0, 196, 66, 0, 0, 14, 67, 0, 0, 196, 66, 0, 0, 15, 67, 0, 0, 196, 66, 0, 0, 16, 67, 0, 0, 196, 66, 0, 0, 17, 67, 0, 0, 196, 66, 0, 0, 18, 67, 0, 0, 196, 66, 0, 0, 19, 67, 0, 0, 196, 66, 0, 0, 20, 67, 0, 0, 196, 66, 0, 0, 21, 67, 0, 0, 196, 66, 0, 0, 22, 67, 0, 0, 196, 66, 0, 0, 23, 67, 0, 0, 196, 66, 0, 0, 24, 67, 0, 0, 196, 66, 0, 0, 25, 67, 0, 0, 196, 66, 0, 0, 26, 67, 0, 0, 196, 66, 0, 0, 27, 67, 0, 0, 196, 66, 0, 0, 28, 67, 0, 0, 196, 66, 0, 0, 29, 67, 0, 0, 196, 66, 0, 0, 30, 67, 0, 0, 196, 66, 0, 0, 31, 67, 0, 0, 196, 66, 0, 0, 32, 67, 0, 0, 196, 66, 0, 0, 33, 67, 0, 0, 196, 66, 0, 0, 34, 67, 0, 0, 196, 66, 0, 0, 35, 67, 0, 0, 196, 66, 0, 0, 36, 67, 0, 0, 196, 66, 0, 0, 37, 67, 0, 0, 196, 66, 0, 0, 38, 67, 0, 0, 196, 66, 0, 0, 39, 67, 0, 0, 196, 66, 0, 0, 40, 67, 0, 0, 196, 66, 0, 0, 41, 67, 0, 0, 196, 66, 0, 0, 42, 67, 0, 0, 196, 66, 0, 0, 43, 67, 0, 0, 196, 66, 0, 0, 44, 67, 0, 0, 196, 66, 0, 0, 45, 67, 0, 0, 196, 66, 0, 0, 46, 67, 0, 0, 196, 66, 0, 0, 47, 67, 0, 0, 196, 66, 0, 0, 48, 67, 0, 0, 196, 66, 0, 0, 49, 67, 0, 0, 196, 66, 0, 0, 50, 67, 0, 0, 196, 66, 0, 0, 51, 67, 0, 0, 196, 66, 0, 0, 52, 67, 0, 0, 196, 66, 0, 0, 53, 67, 0, 0, 196, 66, 0, 0, 54, 67, 0, 0, 196, 66, 0, 0, 55, 67, 0, 0, 198, 66, 0, 0, 184, 66, 0, 0, 198, 66, 0, 0, 186, 66, 0, 0, 198, 66, 0, 0, 188, 66, 0, 0, 198, 66, 0, 0, 190, 66, 0, 0, 198, 66, 0, 0, 192, 66, 0, 0, 198, 66, 0, 0, 194, 66, 0, 0, 198, 66, 0, 0, 196, 66, 0, 0, 198, 66, 0, 0, 198, 66, 0, 0, 198, 66, 0, 0, 200, 66, 0, 0, 198, 66, 0, 0, 202, 66, 0, 0, 198, 66, 0, 0, 204, 66, 0, 0, 198, 66, 0, 0, 206, 66, 0, 0, 198, 66, 0, 0, 208, 66, 0, 0, 198, 66, 0, 0, 210, 66, 0, 0, 198, 66, 0, 0, 212, 66, 0, 0, 198, 66, 0, 0, 214, 66, 0, 0, 198, 66, 0, 0, 216, 66, 0, 0, 198, 66, 0, 0, 218, 66, 0, 0, 198, 66, 0, 0, 220, 66, 0, 0, 198, 66, 0, 0, 222, 66, 0, 0, 198, 66, 0, 0, 224, 66, 0, 0, 198, 66, 0, 0, 226, 66, 0, 0, 198, 66, 0, 0, 228, 66, 0, 0, 198, 66, 0, 0, 230, 66, 0, 0, 198, 66, 0, 0, 232, 66, 0, 0, 198, 66, 0, 0, 234, 66, 0, 0, 198, 66, 0, 0, 236, 66, 0, 0, 198, 66, 0, 0, 238, 66, 0, 0, 198, 66, 0, 0, 240, 66, 0, 0, 198, 66, 0, 0, 242, 66, 0, 0, 198, 66, 0, 0, 244, 66, 0, 0, 198, 66, 0, 0, 246, 66, 0, 0, 198, 66, 0, 0, 248, 66, 0, 0, 198, 66, 0, 0, 250, 66, 0, 0, 198, 66, 0, 0, 252, 66, 0, 0, 198, 66, 0, 0, 254, 66, 0, 0, 198, 66, 0, 0, 0, 67, 0, 0, 198, 66, 0, 0, 1, 67, 0, 0, 198, 66, 0, 0, 2, 67, 0, 0, 198, 66, 0, 0, 3, 67, 0, 0, 198, 66, 0, 0, 4, 67, 0, 0, 198, 66, 0, 0, 5, 67, 0, 0, 198, 66, 0, 0, 6, 67, 0, 0, 198, 66, 0, 0, 7, 67, 0, 0, 198, 66, 0, 0, 8, 67, 0, 0, 198, 66, 0, 0, 9, 67, 0, 0, 198, 66, 0, 0, 10, 67, 0, 0, 198, 66, 0, 0, 11, 67, 0, 0, 198, 66, 0, 0, 12, 67, 0, 0, 198, 66, 0, 0, 13, 67, 0, 0, 198, 66, 0, 0, 14, 67, 0, 0, 198, 66, 0, 0, 15, 67, 0, 0, 198, 66, 0, 0, 16, 67, 0, 0, 198, 66, 0, 0, 17, 67, 0, 0, 198, 66, 0, 0, 18, 67, 0, 0, 198, 66, 0, 0, 19, 67, 0, 0, 198, 66, 0, 0, 20, 67, 0, 0, 198, 66, 0, 0, 21, 67, 0, 0, 198, 66, 0, 0, 22, 67, 0, 0, 198, 66, 0, 0, 23, 67, 0, 0, 198, 66, 0, 0, 24, 67, 0, 0, 198, 66, 0, 0, 25, 67, 0, 0, 198, 66, 0, 0, 26, 67, 0, 0, 198, 66, 0, 0, 27, 67, 0, 0, 198, 66, 0, 0, 28, 67, 0, 0, 198, 66, 0, 0, 29, 67, 0, 0, 198, 66, 0, 0, 30, 67, 0, 0, 198, 66, 0, 0, 31, 67, 0, 0, 198, 66, 0, 0, 32, 67, 0, 0, 198, 66, 0, 0, 33, 67, 0, 0, 198, 66, 0, 0, 34, 67, 0, 0, 198, 66, 0, 0, 35, 67, 0, 0, 198, 66, 0, 0, 36, 67, 0, 0, 198, 66, 0, 0, 37, 67, 0, 0, 198, 66, 0, 0, 38, 67, 0, 0, 198, 66, 0, 0, 39, 67, 0, 0, 198, 66, 0, 0, 40, 67, 0, 0, 198, 66, 0, 0, 41, 67, 0, 0, 198, 66, 0, 0, 42, 67, 0, 0, 198, 66, 0, 0, 43, 67, 0, 0, 198, 66, 0, 0, 44, 67, 0, 0, 198, 66, 0, 0, 45, 67, 0, 0, 198, 66, 0, 0, 46, 67, 0, 0, 198, 66, 0, 0, 47, 67, 0, 0, 198, 66, 0, 0, 48, 67, 0, 0, 198, 66, 0, 0, 49, 67, 0, 0, 198, 66, 0, 0, 50, 67, 0, 0, 198, 66, 0, 0, 51, 67, 0, 0, 198, 66, 0, 0, 52, 67, 0, 0, 198, 66, 0, 0, 53, 67, 0, 0, 198, 66, 0, 0, 54, 67, 0, 0, 198, 66, 0, 0, 55, 67, 0, 0, 200, 66, 0, 0, 184, 66, 0, 0, 200, 66, 0, 0, 186, 66, 0, 0, 200, 66, 0, 0, 188, 66, 0, 0, 200, 66, 0, 0, 190, 66, 0, 0, 200, 66, 0, 0, 192, 66, 0, 0, 200, 66, 0, 0, 194, 66, 0, 0, 200, 66, 0, 0, 196, 66, 0, 0, 200, 66, 0, 0, 198, 66, 0, 0, 200, 66, 0, 0, 200, 66, 0, 0, 200, 66, 0, 0, 202, 66, 0, 0, 200, 66, 0, 0, 204, 66, 0, 0, 200, 66, 0, 0, 206, 66, 0, 0, 200, 66, 0, 0, 208, 66, 0, 0, 200, 66, 0, 0, 210, 66, 0, 0, 200, 66, 0, 0, 212, 66, 0, 0, 200, 66, 0, 0, 214, 66, 0, 0, 200, 66, 0, 0, 216, 66, 0, 0, 200, 66, 0, 0, 218, 66, 0, 0, 200, 66, 0, 0, 220, 66, 0, 0, 200, 66, 0, 0, 222, 66, 0, 0, 200, 66, 0, 0, 224, 66, 0, 0, 200, 66, 0, 0, 226, 66, 0, 0, 200, 66, 0, 0, 228, 66, 0, 0, 200, 66, 0, 0, 230, 66, 0, 0, 200, 66, 0, 0, 232, 66, 0, 0, 200, 66, 0, 0, 234, 66, 0, 0, 200, 66, 0, 0, 236, 66, 0, 0, 200, 66, 0, 0, 238, 66, 0, 0, 200, 66, 0, 0, 240, 66, 0, 0, 200, 66, 0, 0, 242, 66, 0, 0, 200, 66, 0, 0, 244, 66, 0, 0, 200, 66, 0, 0, 246, 66, 0, 0, 200, 66, 0, 0, 248, 66, 0, 0, 200, 66, 0, 0, 250, 66, 0, 0, 200, 66, 0, 0, 252, 66, 0, 0, 200, 66, 0, 0, 254, 66, 0, 0, 200, 66, 0, 0, 0, 67, 0, 0, 200, 66, 0, 0, 1, 67, 0, 0, 200, 66, 0, 0, 2, 67, 0, 0, 200, 66, 0, 0, 3, 67, 0, 0, 200, 66, 0, 0, 4, 67, 0, 0, 200, 66, 0, 0, 5, 67, 0, 0, 200, 66, 0, 0, 6, 67, 0, 0, 200, 66, 0, 0, 7, 67, 0, 0, 200, 66, 0, 0, 8, 67, 0, 0, 200, 66, 0, 0, 9, 67, 0, 0, 200, 66, 0, 0, 10, 67, 0, 0, 200, 66, 0, 0, 11, 67, 0, 0, 200, 66, 0, 0, 12, 67, 0, 0, 200, 66, 0, 0, 13, 67, 0, 0, 200, 66, 0, 0, 14, 67, 0, 0, 200, 66, 0, 0, 15, 67, 0, 0, 200, 66, 0, 0, 16, 67, 0, 0, 200, 66, 0, 0, 17, 67, 0, 0, 200, 66, 0, 0, 18, 67, 0, 0, 200, 66, 0, 0, 19, 67, 0, 0, 200, 66, 0, 0, 20, 67, 0, 0, 200, 66, 0, 0, 21, 67, 0, 0, 200, 66, 0, 0, 22, 67, 0, 0, 200, 66, 0, 0, 23, 67, 0, 0, 200, 66, 0, 0, 24, 67, 0, 0, 200, 66, 0, 0, 25, 67, 0, 0, 200, 66, 0, 0, 26, 67, 0, 0, 200, 66, 0, 0, 27, 67, 0, 0, 200, 66, 0, 0, 28, 67, 0, 0, 200, 66, 0, 0, 29, 67, 0, 0, 200, 66, 0, 0, 30, 67, 0, 0, 200, 66, 0, 0, 31, 67, 0, 0, 200, 66, 0, 0, 32, 67, 0, 0, 200, 66, 0, 0, 33, 67, 0, 0, 200, 66, 0, 0, 34, 67, 0, 0, 200, 66, 0, 0, 35, 67, 0, 0, 200, 66, 0, 0, 36, 67, 0, 0, 200, 66, 0, 0, 37, 67, 0, 0, 200, 66, 0, 0, 38, 67, 0, 0, 200, 66, 0, 0, 39, 67, 0, 0, 200, 66, 0, 0, 40, 67, 0, 0, 200, 66, 0, 0, 41, 67, 0, 0, 200, 66, 0, 0, 42, 67, 0, 0, 200, 66, 0, 0, 43, 67, 0, 0, 200, 66, 0, 0, 44, 67, 0, 0, 200, 66, 0, 0, 45, 67, 0, 0, 200, 66, 0, 0, 46, 67, 0, 0, 200, 66, 0, 0, 47, 67, 0, 0, 200, 66, 0, 0, 48, 67, 0, 0, 200, 66, 0, 0, 49, 67, 0, 0, 200, 66, 0, 0, 50, 67, 0, 0, 200, 66, 0, 0, 51, 67, 0, 0, 200, 66, 0, 0, 52, 67, 0, 0, 200, 66, 0, 0, 53, 67, 0, 0, 200, 66, 0, 0, 54, 67, 0, 0, 200, 66, 0, 0, 55, 67, 0, 0, 202, 66, 0, 0, 184, 66, 0, 0, 202, 66, 0, 0, 186, 66, 0, 0, 202, 66, 0, 0, 188, 66, 0, 0, 202, 66, 0, 0, 190, 66, 0, 0, 202, 66, 0, 0, 192, 66, 0, 0, 202, 66, 0, 0, 194, 66, 0, 0, 202, 66, 0, 0, 196, 66, 0, 0, 202, 66, 0, 0, 198, 66, 0, 0, 202, 66, 0, 0, 200, 66, 0, 0, 202, 66, 0, 0, 202, 66, 0, 0, 202, 66, 0, 0, 204, 66, 0, 0, 202, 66, 0, 0, 206, 66, 0, 0, 202, 66, 0, 0, 208, 66, 0, 0, 202, 66, 0, 0, 210, 66, 0, 0, 202, 66, 0, 0, 212, 66, 0, 0, 202, 66, 0, 0, 214, 66, 0, 0, 202, 66, 0, 0, 216, 66, 0, 0, 202, 66, 0, 0, 218, 66, 0, 0, 202, 66, 0, 0, 220, 66, 0, 0, 202, 66, 0, 0, 222, 66, 0, 0, 202, 66, 0, 0, 224, 66, 0, 0, 202, 66, 0, 0, 226, 66, 0, 0, 202, 66, 0, 0, 228, 66, 0, 0, 202, 66, 0, 0, 230, 66, 0, 0, 202, 66, 0, 0, 232, 66, 0, 0, 202, 66, 0, 0, 234, 66, 0, 0, 202, 66, 0, 0, 236, 66, 0, 0, 202, 66, 0, 0, 238, 66, 0, 0, 202, 66, 0, 0, 240, 66, 0, 0, 202, 66, 0, 0, 242, 66, 0, 0, 202, 66, 0, 0, 244, 66, 0, 0, 202, 66, 0, 0, 246, 66, 0, 0, 202, 66, 0, 0, 248, 66, 0, 0, 202, 66, 0, 0, 250, 66, 0, 0, 202, 66, 0, 0, 252, 66, 0, 0, 202, 66, 0, 0, 254, 66, 0, 0, 202, 66, 0, 0, 0, 67, 0, 0, 202, 66, 0, 0, 1, 67, 0, 0, 202, 66, 0, 0, 2, 67, 0, 0, 202, 66, 0, 0, 3, 67, 0, 0, 202, 66, 0, 0, 4, 67, 0, 0, 202, 66, 0, 0, 5, 67, 0, 0, 202, 66, 0, 0, 6, 67, 0, 0, 202, 66, 0, 0, 7, 67, 0, 0, 202, 66, 0, 0, 8, 67, 0, 0, 202, 66, 0, 0, 9, 67, 0, 0, 202, 66, 0, 0, 10, 67, 0, 0, 202, 66, 0, 0, 11, 67, 0, 0, 202, 66, 0, 0, 12, 67, 0, 0, 202, 66, 0, 0, 13, 67, 0, 0, 202, 66, 0, 0, 14, 67, 0, 0, 202, 66, 0, 0, 15, 67, 0, 0, 202, 66, 0, 0, 16, 67, 0, 0, 202, 66, 0, 0, 17, 67, 0, 0, 202, 66, 0, 0, 18, 67, 0, 0, 202, 66, 0, 0, 19, 67, 0, 0, 202, 66, 0, 0, 20, 67, 0, 0, 202, 66, 0, 0, 21, 67, 0, 0, 202, 66, 0, 0, 22, 67, 0, 0, 202, 66, 0, 0, 23, 67, 0, 0, 202, 66, 0, 0, 24, 67, 0, 0, 202, 66, 0, 0, 25, 67, 0, 0, 202, 66, 0, 0, 26, 67, 0, 0, 202, 66, 0, 0, 27, 67, 0, 0, 202, 66, 0, 0, 28, 67, 0, 0, 202, 66, 0, 0, 29, 67, 0, 0, 202, 66, 0, 0, 30, 67, 0, 0, 202, 66, 0, 0, 31, 67, 0, 0, 202, 66, 0, 0, 32, 67, 0, 0, 202, 66, 0, 0, 33, 67, 0, 0, 202, 66, 0, 0, 34, 67, 0, 0, 202, 66, 0, 0, 35, 67, 0, 0, 202, 66, 0, 0, 36, 67, 0, 0, 202, 66, 0, 0, 37, 67, 0, 0, 202, 66, 0, 0, 38, 67, 0, 0, 202, 66, 0, 0, 39, 67, 0, 0, 202, 66, 0, 0, 40, 67, 0, 0, 202, 66, 0, 0, 41, 67, 0, 0, 202, 66, 0, 0, 42, 67, 0, 0, 202, 66, 0, 0, 43, 67, 0, 0, 202, 66, 0, 0, 44, 67, 0, 0, 202, 66, 0, 0, 45, 67, 0, 0, 202, 66, 0, 0, 46, 67, 0, 0, 202, 66, 0, 0, 47, 67, 0, 0, 202, 66, 0, 0, 48, 67, 0, 0, 202, 66, 0, 0, 49, 67, 0, 0, 202, 66, 0, 0, 50, 67, 0, 0, 202, 66, 0, 0, 51, 67, 0, 0, 202, 66, 0, 0, 52, 67, 0, 0, 202, 66, 0, 0, 53, 67, 0, 0, 202, 66, 0, 0, 54, 67, 0, 0, 202, 66, 0, 0, 55, 67, 0, 0, 204, 66, 0, 0, 184, 66, 0, 0, 204, 66, 0, 0, 186, 66, 0, 0, 204, 66, 0, 0, 188, 66, 0, 0, 204, 66, 0, 0, 190, 66, 0, 0, 204, 66, 0, 0, 192, 66, 0, 0, 204, 66, 0, 0, 194, 66, 0, 0, 204, 66, 0, 0, 196, 66, 0, 0, 204, 66, 0, 0, 198, 66, 0, 0, 204, 66, 0, 0, 200, 66, 0, 0, 204, 66, 0, 0, 202, 66, 0, 0, 204, 66, 0, 0, 204, 66, 0, 0, 204, 66, 0, 0, 206, 66, 0, 0, 204, 66, 0, 0, 208, 66, 0, 0, 204, 66, 0, 0, 210, 66, 0, 0, 204, 66, 0, 0, 212, 66, 0, 0, 204, 66, 0, 0, 214, 66, 0, 0, 204, 66, 0, 0, 216, 66, 0, 0, 204, 66, 0, 0, 218, 66, 0, 0, 204, 66, 0, 0, 220, 66, 0, 0, 204, 66, 0, 0, 222, 66, 0, 0, 204, 66, 0, 0, 224, 66, 0, 0, 204, 66, 0, 0, 226, 66, 0, 0, 204, 66, 0, 0, 228, 66, 0, 0, 204, 66, 0, 0, 230, 66, 0, 0, 204, 66, 0, 0, 232, 66, 0, 0, 204, 66, 0, 0, 234, 66, 0, 0, 204, 66, 0, 0, 236, 66, 0, 0, 204, 66, 0, 0, 238, 66, 0, 0, 204, 66, 0, 0, 240, 66, 0, 0, 204, 66, 0, 0, 242, 66, 0, 0, 204, 66, 0, 0, 244, 66, 0, 0, 204, 66, 0, 0, 246, 66, 0, 0, 204, 66, 0, 0, 248, 66, 0, 0, 204, 66, 0, 0, 250, 66, 0, 0, 204, 66, 0, 0, 252, 66, 0, 0, 204, 66, 0, 0, 254, 66, 0, 0, 204, 66, 0, 0, 0, 67, 0, 0, 204, 66, 0, 0, 1, 67, 0, 0, 204, 66, 0, 0, 2, 67, 0, 0, 204, 66, 0, 0, 3, 67, 0, 0, 204, 66, 0, 0, 4, 67, 0, 0, 204, 66, 0, 0, 5, 67, 0, 0, 204, 66, 0, 0, 6, 67, 0, 0, 204, 66, 0, 0, 7, 67, 0, 0, 204, 66, 0, 0, 8, 67, 0, 0, 204, 66, 0, 0, 9, 67, 0, 0, 204, 66, 0, 0, 10, 67, 0, 0, 204, 66, 0, 0, 11, 67, 0, 0, 204, 66, 0, 0, 12, 67, 0, 0, 204, 66, 0, 0, 13, 67, 0, 0, 204, 66, 0, 0, 14, 67, 0, 0, 204, 66, 0, 0, 15, 67, 0, 0, 204, 66, 0, 0, 16, 67, 0, 0, 204, 66, 0, 0, 17, 67, 0, 0, 204, 66, 0, 0, 18, 67, 0, 0, 204, 66, 0, 0, 19, 67, 0, 0, 204, 66, 0, 0, 20, 67, 0, 0, 204, 66, 0, 0, 21, 67, 0, 0, 204, 66, 0, 0, 22, 67, 0, 0, 204, 66, 0, 0, 23, 67, 0, 0, 204, 66, 0, 0, 24, 67, 0, 0, 204, 66, 0, 0, 25, 67, 0, 0, 204, 66, 0, 0, 26, 67, 0, 0, 204, 66, 0, 0, 27, 67, 0, 0, 204, 66, 0, 0, 28, 67, 0, 0, 204, 66, 0, 0, 29, 67, 0, 0, 204, 66, 0, 0, 30, 67, 0, 0, 204, 66, 0, 0, 31, 67, 0, 0, 204, 66, 0, 0, 32, 67, 0, 0, 204, 66, 0, 0, 33, 67, 0, 0, 204, 66, 0, 0, 34, 67, 0, 0, 204, 66, 0, 0, 35, 67, 0, 0, 204, 66, 0, 0, 36, 67, 0, 0, 204, 66, 0, 0, 37, 67, 0, 0, 204, 66, 0, 0, 38, 67, 0, 0, 204, 66, 0, 0, 39, 67, 0, 0, 204, 66, 0, 0, 40, 67, 0, 0, 204, 66, 0, 0, 41, 67, 0, 0, 204, 66, 0, 0, 42, 67, 0, 0, 204, 66, 0, 0, 43, 67, 0, 0, 204, 66, 0, 0, 44, 67, 0, 0, 204, 66, 0, 0, 45, 67, 0, 0, 204, 66, 0, 0, 46, 67, 0, 0, 204, 66, 0, 0, 47, 67, 0, 0, 204, 66, 0, 0, 48, 67, 0, 0, 204, 66, 0, 0, 49, 67, 0, 0, 204, 66, 0, 0, 50, 67, 0, 0, 204, 66, 0, 0, 51, 67, 0, 0, 204, 66, 0, 0, 52, 67, 0, 0, 204, 66, 0, 0, 53, 67, 0, 0, 204, 66, 0, 0, 54, 67, 0, 0, 204, 66, 0, 0, 55, 67, 0, 0, 206, 66, 0, 0, 184, 66, 0, 0, 206, 66, 0, 0, 186, 66, 0, 0, 206, 66, 0, 0, 188, 66, 0, 0, 206, 66, 0, 0, 190, 66, 0, 0, 206, 66, 0, 0, 192, 66, 0, 0, 206, 66, 0, 0, 194, 66, 0, 0, 206, 66, 0, 0, 196, 66, 0, 0, 206, 66, 0, 0, 198, 66, 0, 0, 206, 66, 0, 0, 200, 66, 0, 0, 206, 66, 0, 0, 202, 66, 0, 0, 206, 66, 0, 0, 204, 66, 0, 0, 206, 66, 0, 0, 206, 66, 0, 0, 206, 66, 0, 0, 208, 66, 0, 0, 206, 66, 0, 0, 210, 66, 0, 0, 206, 66, 0, 0, 212, 66, 0, 0, 206, 66, 0, 0, 214, 66, 0, 0, 206, 66, 0, 0, 216, 66, 0, 0, 206, 66, 0, 0, 218, 66, 0, 0, 206, 66, 0, 0, 220, 66, 0, 0, 206, 66, 0, 0, 222, 66, 0, 0, 206, 66, 0, 0, 224, 66, 0, 0, 206, 66, 0, 0, 226, 66, 0, 0, 206, 66, 0, 0, 228, 66, 0, 0, 206, 66, 0, 0, 230, 66, 0, 0, 206, 66, 0, 0, 232, 66, 0, 0, 206, 66, 0, 0, 234, 66, 0, 0, 206, 66, 0, 0, 236, 66, 0, 0, 206, 66, 0, 0, 238, 66, 0, 0, 206, 66, 0, 0, 240, 66, 0, 0, 206, 66, 0, 0, 242, 66, 0, 0, 206, 66, 0, 0, 244, 66, 0, 0, 206, 66, 0, 0, 246, 66, 0, 0, 206, 66, 0, 0, 248, 66, 0, 0, 206, 66, 0, 0, 250, 66, 0, 0, 206, 66, 0, 0, 252, 66, 0, 0, 206, 66, 0, 0, 254, 66, 0, 0, 206, 66, 0, 0, 0, 67, 0, 0, 206, 66, 0, 0, 1, 67, 0, 0, 206, 66, 0, 0, 2, 67, 0, 0, 206, 66, 0, 0, 3, 67, 0, 0, 206, 66, 0, 0, 4, 67, 0, 0, 206, 66, 0, 0, 5, 67, 0, 0, 206, 66, 0, 0, 6, 67, 0, 0, 206, 66, 0, 0, 7, 67, 0, 0, 206, 66, 0, 0, 8, 67, 0, 0, 206, 66, 0, 0, 9, 67, 0, 0, 206, 66, 0, 0, 10, 67, 0, 0, 206, 66, 0, 0, 11, 67, 0, 0, 206, 66, 0, 0, 12, 67, 0, 0, 206, 66, 0, 0, 13, 67, 0, 0, 206, 66, 0, 0, 14, 67, 0, 0, 206, 66, 0, 0, 15, 67, 0, 0, 206, 66, 0, 0, 16, 67, 0, 0, 206, 66, 0, 0, 17, 67, 0, 0, 206, 66, 0, 0, 18, 67, 0, 0, 206, 66, 0, 0, 19, 67, 0, 0, 206, 66, 0, 0, 20, 67, 0, 0, 206, 66, 0, 0, 21, 67, 0, 0, 206, 66, 0, 0, 22, 67, 0, 0, 206, 66, 0, 0, 23, 67, 0, 0, 206, 66, 0, 0, 24, 67, 0, 0, 206, 66, 0, 0, 25, 67, 0, 0, 206, 66, 0, 0, 26, 67, 0, 0, 206, 66, 0, 0, 27, 67, 0, 0, 206, 66, 0, 0, 28, 67, 0, 0, 206, 66, 0, 0, 29, 67, 0, 0, 206, 66, 0, 0, 30, 67, 0, 0, 206, 66, 0, 0, 31, 67, 0, 0, 206, 66, 0, 0, 32, 67, 0, 0, 206, 66, 0, 0, 33, 67, 0, 0, 206, 66, 0, 0, 34, 67, 0, 0, 206, 66, 0, 0, 35, 67, 0, 0, 206, 66, 0, 0, 36, 67, 0, 0, 206, 66, 0, 0, 37, 67, 0, 0, 206, 66, 0, 0, 38, 67, 0, 0, 206, 66, 0, 0, 39, 67, 0, 0, 206, 66, 0, 0, 40, 67, 0, 0, 206, 66, 0, 0, 41, 67, 0, 0, 206, 66, 0, 0, 42, 67, 0, 0, 206, 66, 0, 0, 43, 67, 0, 0, 206, 66, 0, 0, 44, 67, 0, 0, 206, 66, 0, 0, 45, 67, 0, 0, 206, 66, 0, 0, 46, 67, 0, 0, 206, 66, 0, 0, 47, 67, 0, 0, 206, 66, 0, 0, 48, 67, 0, 0, 206, 66, 0, 0, 49, 67, 0, 0, 206, 66, 0, 0, 50, 67, 0, 0, 206, 66, 0, 0, 51, 67, 0, 0, 206, 66, 0, 0, 52, 67, 0, 0, 206, 66, 0, 0, 53, 67, 0, 0, 206, 66, 0, 0, 54, 67, 0, 0, 206, 66, 0, 0, 55, 67, 0, 0, 208, 66, 0, 0, 184, 66, 0, 0, 208, 66, 0, 0, 186, 66, 0, 0, 208, 66, 0, 0, 188, 66, 0, 0, 208, 66, 0, 0, 190, 66, 0, 0, 208, 66, 0, 0, 192, 66, 0, 0, 208, 66, 0, 0, 194, 66, 0, 0, 208, 66, 0, 0, 196, 66, 0, 0, 208, 66, 0, 0, 198, 66, 0, 0, 208, 66, 0, 0, 200, 66, 0, 0, 208, 66, 0, 0, 202, 66, 0, 0, 208, 66, 0, 0, 204, 66, 0, 0, 208, 66, 0, 0, 206, 66, 0, 0, 208, 66, 0, 0, 208, 66, 0, 0, 208, 66, 0, 0, 210, 66, 0, 0, 208, 66, 0, 0, 212, 66, 0, 0, 208, 66, 0, 0, 214, 66, 0, 0, 208, 66, 0, 0, 216, 66, 0, 0, 208, 66, 0, 0, 218, 66, 0, 0, 208, 66, 0, 0, 220, 66, 0, 0, 208, 66, 0, 0, 222, 66, 0, 0, 208, 66, 0, 0, 224, 66, 0, 0, 208, 66, 0, 0, 226, 66, 0, 0, 208, 66, 0, 0, 228, 66, 0, 0, 208, 66, 0, 0, 230, 66, 0, 0, 208, 66, 0, 0, 232, 66, 0, 0, 208, 66, 0, 0, 234, 66, 0, 0, 208, 66, 0, 0, 236, 66, 0, 0, 208, 66, 0, 0, 238, 66, 0, 0, 208, 66, 0, 0, 240, 66, 0, 0, 208, 66, 0, 0, 242, 66, 0, 0, 208, 66, 0, 0, 244, 66, 0, 0, 208, 66, 0, 0, 246, 66, 0, 0, 208, 66, 0, 0, 248, 66, 0, 0, 208, 66, 0, 0, 250, 66, 0, 0, 208, 66, 0, 0, 252, 66, 0, 0, 208, 66, 0, 0, 254, 66, 0, 0, 208, 66, 0, 0, 0, 67, 0, 0, 208, 66, 0, 0, 1, 67, 0, 0, 208, 66, 0, 0, 2, 67, 0, 0, 208, 66, 0, 0, 3, 67, 0, 0, 208, 66, 0, 0, 4, 67, 0, 0, 208, 66, 0, 0, 5, 67, 0, 0, 208, 66, 0, 0, 6, 67, 0, 0, 208, 66, 0, 0, 7, 67, 0, 0, 208, 66, 0, 0, 8, 67, 0, 0, 208, 66, 0, 0, 9, 67, 0, 0, 208, 66, 0, 0, 10, 67, 0, 0, 208, 66, 0, 0, 11, 67, 0, 0, 208, 66, 0, 0, 12, 67, 0, 0, 208, 66, 0, 0, 13, 67, 0, 0, 208, 66, 0, 0, 14, 67, 0, 0, 208, 66, 0, 0, 15, 67, 0, 0, 208, 66, 0, 0, 16, 67, 0, 0, 208, 66, 0, 0, 17, 67, 0, 0, 208, 66, 0, 0, 18, 67, 0, 0, 208, 66, 0, 0, 19, 67, 0, 0, 208, 66, 0, 0, 20, 67, 0, 0, 208, 66, 0, 0, 21, 67, 0, 0, 208, 66, 0, 0, 22, 67, 0, 0, 208, 66, 0, 0, 23, 67, 0, 0, 208, 66, 0, 0, 24, 67, 0, 0, 208, 66, 0, 0, 25, 67, 0, 0, 208, 66, 0, 0, 26, 67, 0, 0, 208, 66, 0, 0, 27, 67, 0, 0, 208, 66, 0, 0, 28, 67, 0, 0, 208, 66, 0, 0, 29, 67, 0, 0, 208, 66, 0, 0, 30, 67, 0, 0, 208, 66, 0, 0, 31, 67, 0, 0, 208, 66, 0, 0, 32, 67, 0, 0, 208, 66, 0, 0, 33, 67, 0, 0, 208, 66, 0, 0, 34, 67, 0, 0, 208, 66, 0, 0, 35, 67, 0, 0, 208, 66, 0, 0, 36, 67, 0, 0, 208, 66, 0, 0, 37, 67, 0, 0, 208, 66, 0, 0, 38, 67, 0, 0, 208, 66, 0, 0, 39, 67, 0, 0, 208, 66, 0, 0, 40, 67, 0, 0, 208, 66, 0, 0, 41, 67, 0, 0, 208, 66, 0, 0, 42, 67, 0, 0, 208, 66, 0, 0, 43, 67, 0, 0, 208, 66, 0, 0, 44, 67, 0, 0, 208, 66, 0, 0, 45, 67, 0, 0, 208, 66, 0, 0, 46, 67, 0, 0, 208, 66, 0, 0, 47, 67, 0, 0, 208, 66, 0, 0, 48, 67, 0, 0, 208, 66, 0, 0, 49, 67, 0, 0, 208, 66, 0, 0, 50, 67, 0, 0, 208, 66, 0, 0, 51, 67, 0, 0, 208, 66, 0, 0, 52, 67, 0, 0, 208, 66, 0, 0, 53, 67, 0, 0, 208, 66, 0, 0, 54, 67, 0, 0, 208, 66, 0, 0, 55, 67, 0, 0, 210, 66, 0, 0, 184, 66, 0, 0, 210, 66, 0, 0, 186, 66, 0, 0, 210, 66, 0, 0, 188, 66, 0, 0, 210, 66, 0, 0, 190, 66, 0, 0, 210, 66, 0, 0, 192, 66, 0, 0, 210, 66, 0, 0, 194, 66, 0, 0, 210, 66, 0, 0, 196, 66, 0, 0, 210, 66, 0, 0, 198, 66, 0, 0, 210, 66, 0, 0, 200, 66, 0, 0, 210, 66, 0, 0, 202, 66, 0, 0, 210, 66, 0, 0, 204, 66, 0, 0, 210, 66, 0, 0, 206, 66, 0, 0, 210, 66, 0, 0, 208, 66, 0, 0, 210, 66, 0, 0, 210, 66, 0, 0, 210, 66, 0, 0, 212, 66, 0, 0, 210, 66, 0, 0, 214, 66, 0, 0, 210, 66, 0, 0, 216, 66, 0, 0, 210, 66, 0, 0, 218, 66, 0, 0, 210, 66, 0, 0, 220, 66, 0, 0, 210, 66, 0, 0, 222, 66, 0, 0, 210, 66, 0, 0, 224, 66, 0, 0, 210, 66, 0, 0, 226, 66, 0, 0, 210, 66, 0, 0, 228, 66, 0, 0, 210, 66, 0, 0, 230, 66, 0, 0, 210, 66, 0, 0, 232, 66, 0, 0, 210, 66, 0, 0, 234, 66, 0, 0, 210, 66, 0, 0, 236, 66, 0, 0, 210, 66, 0, 0, 238, 66, 0, 0, 210, 66, 0, 0, 240, 66, 0, 0, 210, 66, 0, 0, 242, 66, 0, 0, 210, 66, 0, 0, 244, 66, 0, 0, 210, 66, 0, 0, 246, 66, 0, 0, 210, 66, 0, 0, 248, 66, 0, 0, 210, 66, 0, 0, 250, 66, 0, 0, 210, 66, 0, 0, 252, 66, 0, 0, 210, 66, 0, 0, 254, 66, 0, 0, 210, 66, 0, 0, 0, 67, 0, 0, 210, 66, 0, 0, 1, 67, 0, 0, 210, 66, 0, 0, 2, 67, 0, 0, 210, 66, 0, 0, 3, 67, 0, 0, 210, 66, 0, 0, 4, 67, 0, 0, 210, 66, 0, 0, 5, 67, 0, 0, 210, 66, 0, 0, 6, 67, 0, 0, 210, 66, 0, 0, 7, 67, 0, 0, 210, 66, 0, 0, 8, 67, 0, 0, 210, 66, 0, 0, 9, 67, 0, 0, 210, 66, 0, 0, 10, 67, 0, 0, 210, 66, 0, 0, 11, 67, 0, 0, 210, 66, 0, 0, 12, 67, 0, 0, 210, 66, 0, 0, 13, 67, 0, 0, 210, 66, 0, 0, 14, 67, 0, 0, 210, 66, 0, 0, 15, 67, 0, 0, 210, 66, 0, 0, 16, 67, 0, 0, 210, 66, 0, 0, 17, 67, 0, 0, 210, 66, 0, 0, 18, 67, 0, 0, 210, 66, 0, 0, 19, 67, 0, 0, 210, 66, 0, 0, 20, 67, 0, 0, 210, 66, 0, 0, 21, 67, 0, 0, 210, 66, 0, 0, 22, 67, 0, 0, 210, 66, 0, 0, 23, 67, 0, 0, 210, 66, 0, 0, 24, 67, 0, 0, 210, 66, 0, 0, 25, 67, 0, 0, 210, 66, 0, 0, 26, 67, 0, 0, 210, 66, 0, 0, 27, 67, 0, 0, 210, 66, 0, 0, 28, 67, 0, 0, 210, 66, 0, 0, 29, 67, 0, 0, 210, 66, 0, 0, 30, 67, 0, 0, 210, 66, 0, 0, 31, 67, 0, 0, 210, 66, 0, 0, 32, 67, 0, 0, 210, 66, 0, 0, 33, 67, 0, 0, 210, 66, 0, 0, 34, 67, 0, 0, 210, 66, 0, 0, 35, 67, 0, 0, 210, 66, 0, 0, 36, 67, 0, 0, 210, 66, 0, 0, 37, 67, 0, 0, 210, 66, 0, 0, 38, 67, 0, 0, 210, 66, 0, 0, 39, 67, 0, 0, 210, 66, 0, 0, 40, 67, 0, 0, 210, 66, 0, 0, 41, 67, 0, 0, 210, 66, 0, 0, 42, 67, 0, 0, 210, 66, 0, 0, 43, 67, 0, 0, 210, 66, 0, 0, 44, 67, 0, 0, 210, 66, 0, 0, 45, 67, 0, 0, 210, 66, 0, 0, 46, 67, 0, 0, 210, 66, 0, 0, 47, 67, 0, 0, 210, 66, 0, 0, 48, 67, 0, 0, 210, 66, 0, 0, 49, 67, 0, 0, 210, 66, 0, 0, 50, 67, 0, 0, 210, 66, 0, 0, 51, 67, 0, 0, 210, 66, 0, 0, 52, 67, 0, 0, 210, 66, 0, 0, 53, 67, 0, 0, 210, 66, 0, 0, 54, 67, 0, 0, 210, 66, 0, 0, 55, 67, 0, 0, 212, 66, 0, 0, 184, 66, 0, 0, 212, 66, 0, 0, 186, 66, 0, 0, 212, 66, 0, 0, 188, 66, 0, 0, 212, 66, 0, 0, 190, 66, 0, 0, 212, 66, 0, 0, 192, 66, 0, 0, 212, 66, 0, 0, 194, 66, 0, 0, 212, 66, 0, 0, 196, 66, 0, 0, 212, 66, 0, 0, 198, 66, 0, 0, 212, 66, 0, 0, 200, 66, 0, 0, 212, 66, 0, 0, 202, 66, 0, 0, 212, 66, 0, 0, 204, 66, 0, 0, 212, 66, 0, 0, 206, 66, 0, 0, 212, 66, 0, 0, 208, 66, 0, 0, 212, 66, 0, 0, 210, 66, 0, 0, 212, 66, 0, 0, 212, 66, 0, 0, 212, 66, 0, 0, 214, 66, 0, 0, 212, 66, 0, 0, 216, 66, 0, 0, 212, 66, 0, 0, 218, 66, 0, 0, 212, 66, 0, 0, 220, 66, 0, 0, 212, 66, 0, 0, 222, 66, 0, 0, 212, 66, 0, 0, 224, 66, 0, 0, 212, 66, 0, 0, 226, 66, 0, 0, 212, 66, 0, 0, 228, 66, 0, 0, 212, 66, 0, 0, 230, 66, 0, 0, 212, 66, 0, 0, 232, 66, 0, 0, 212, 66, 0, 0, 234, 66, 0, 0, 212, 66, 0, 0, 236, 66, 0, 0, 212, 66, 0, 0, 238, 66, 0, 0, 212, 66, 0, 0, 240, 66, 0, 0, 212, 66, 0, 0, 242, 66, 0, 0, 212, 66, 0, 0, 244, 66, 0, 0, 212, 66, 0, 0, 246, 66, 0, 0, 212, 66, 0, 0, 248, 66, 0, 0, 212, 66, 0, 0, 250, 66, 0, 0, 212, 66, 0, 0, 252, 66, 0, 0, 212, 66, 0, 0, 254, 66, 0, 0, 212, 66, 0, 0, 0, 67, 0, 0, 212, 66, 0, 0, 1, 67, 0, 0, 212, 66, 0, 0, 2, 67, 0, 0, 212, 66, 0, 0, 3, 67, 0, 0, 212, 66, 0, 0, 4, 67, 0, 0, 212, 66, 0, 0, 5, 67, 0, 0, 212, 66, 0, 0, 6, 67, 0, 0, 212, 66, 0, 0, 7, 67, 0, 0, 212, 66, 0, 0, 8, 67, 0, 0, 212, 66, 0, 0, 9, 67, 0, 0, 212, 66, 0, 0, 10, 67, 0, 0, 212, 66, 0, 0, 11, 67, 0, 0, 212, 66, 0, 0, 12, 67, 0, 0, 212, 66, 0, 0, 13, 67, 0, 0, 212, 66, 0, 0, 14, 67, 0, 0, 212, 66, 0, 0, 15, 67, 0, 0, 212, 66, 0, 0, 16, 67, 0, 0, 212, 66, 0, 0, 17, 67, 0, 0, 212, 66, 0, 0, 18, 67, 0, 0, 212, 66, 0, 0, 19, 67, 0, 0, 212, 66, 0, 0, 20, 67, 0, 0, 212, 66, 0, 0, 21, 67, 0, 0, 212, 66, 0, 0, 22, 67, 0, 0, 212, 66, 0, 0, 23, 67, 0, 0, 212, 66, 0, 0, 24, 67, 0, 0, 212, 66, 0, 0, 25, 67, 0, 0, 212, 66, 0, 0, 26, 67, 0, 0, 212, 66, 0, 0, 27, 67, 0, 0, 212, 66, 0, 0, 28, 67, 0, 0, 212, 66, 0, 0, 29, 67, 0, 0, 212, 66, 0, 0, 30, 67, 0, 0, 212, 66, 0, 0, 31, 67, 0, 0, 212, 66, 0, 0, 32, 67, 0, 0, 212, 66, 0, 0, 33, 67, 0, 0, 212, 66, 0, 0, 34, 67, 0, 0, 212, 66, 0, 0, 35, 67, 0, 0, 212, 66, 0, 0, 36, 67, 0, 0, 212, 66, 0, 0, 37, 67, 0, 0, 212, 66, 0, 0, 38, 67, 0, 0, 212, 66, 0, 0, 39, 67, 0, 0, 212, 66, 0, 0, 40, 67, 0, 0, 212, 66, 0, 0, 41, 67, 0, 0, 212, 66, 0, 0, 42, 67, 0, 0, 212, 66, 0, 0, 43, 67, 0, 0, 212, 66, 0, 0, 44, 67, 0, 0, 212, 66, 0, 0, 45, 67, 0, 0, 212, 66, 0, 0, 46, 67, 0, 0, 212, 66, 0, 0, 47, 67, 0, 0, 212, 66, 0, 0, 48, 67, 0, 0, 212, 66, 0, 0, 49, 67, 0, 0, 212, 66, 0, 0, 50, 67, 0, 0, 212, 66, 0, 0, 51, 67, 0, 0, 212, 66, 0, 0, 52, 67, 0, 0, 212, 66, 0, 0, 53, 67, 0, 0, 212, 66, 0, 0, 54, 67, 0, 0, 212, 66, 0, 0, 55, 67, 0, 0, 214, 66, 0, 0, 184, 66, 0, 0, 214, 66, 0, 0, 186, 66, 0, 0, 214, 66, 0, 0, 188, 66, 0, 0, 214, 66, 0, 0, 190, 66, 0, 0, 214, 66, 0, 0, 192, 66, 0, 0, 214, 66, 0, 0, 194, 66, 0, 0, 214, 66, 0, 0, 196, 66, 0, 0, 214, 66, 0, 0, 198, 66, 0, 0, 214, 66, 0, 0, 200, 66, 0, 0, 214, 66, 0, 0, 202, 66, 0, 0, 214, 66, 0, 0, 204, 66, 0, 0, 214, 66, 0, 0, 206, 66, 0, 0, 214, 66, 0, 0, 208, 66, 0, 0, 214, 66, 0, 0, 210, 66, 0, 0, 214, 66, 0, 0, 212, 66, 0, 0, 214, 66, 0, 0, 214, 66, 0, 0, 214, 66, 0, 0, 216, 66, 0, 0, 214, 66, 0, 0, 218, 66, 0, 0, 214, 66, 0, 0, 220, 66, 0, 0, 214, 66, 0, 0, 222, 66, 0, 0, 214, 66, 0, 0, 224, 66, 0, 0, 214, 66, 0, 0, 226, 66, 0, 0, 214, 66, 0, 0, 228, 66, 0, 0, 214, 66, 0, 0, 230, 66, 0, 0, 214, 66, 0, 0, 232, 66, 0, 0, 214, 66, 0, 0, 234, 66, 0, 0, 214, 66, 0, 0, 236, 66, 0, 0, 214, 66, 0, 0, 238, 66, 0, 0, 214, 66, 0, 0, 240, 66, 0, 0, 214, 66, 0, 0, 242, 66, 0, 0, 214, 66, 0, 0, 244, 66, 0, 0, 214, 66, 0, 0, 246, 66, 0, 0, 214, 66, 0, 0, 248, 66, 0, 0, 214, 66, 0, 0, 250, 66, 0, 0, 214, 66, 0, 0, 252, 66, 0, 0, 214, 66, 0, 0, 254, 66, 0, 0, 214, 66, 0, 0, 0, 67, 0, 0, 214, 66, 0, 0, 1, 67, 0, 0, 214, 66, 0, 0, 2, 67, 0, 0, 214, 66, 0, 0, 3, 67, 0, 0, 214, 66, 0, 0, 4, 67, 0, 0, 214, 66, 0, 0, 5, 67, 0, 0, 214, 66, 0, 0, 6, 67, 0, 0, 214, 66, 0, 0, 7, 67, 0, 0, 214, 66, 0, 0, 8, 67, 0, 0, 214, 66, 0, 0, 9, 67, 0, 0, 214, 66, 0, 0, 10, 67, 0, 0, 214, 66, 0, 0, 11, 67, 0, 0, 214, 66, 0, 0, 12, 67, 0, 0, 214, 66, 0, 0, 13, 67, 0, 0, 214, 66, 0, 0, 14, 67, 0, 0, 214, 66, 0, 0, 15, 67, 0, 0, 214, 66, 0, 0, 16, 67, 0, 0, 214, 66, 0, 0, 17, 67, 0, 0, 214, 66, 0, 0, 18, 67, 0, 0, 214, 66, 0, 0, 19, 67, 0, 0, 214, 66, 0, 0, 20, 67, 0, 0, 214, 66, 0, 0, 21, 67, 0, 0, 214, 66, 0, 0, 22, 67, 0, 0, 214, 66, 0, 0, 23, 67, 0, 0, 214, 66, 0, 0, 24, 67, 0, 0, 214, 66, 0, 0, 25, 67, 0, 0, 214, 66, 0, 0, 26, 67, 0, 0, 214, 66, 0, 0, 27, 67, 0, 0, 214, 66, 0, 0, 28, 67, 0, 0, 214, 66, 0, 0, 29, 67, 0, 0, 214, 66, 0, 0, 30, 67, 0, 0, 214, 66, 0, 0, 31, 67, 0, 0, 214, 66, 0, 0, 32, 67, 0, 0, 214, 66, 0, 0, 33, 67, 0, 0, 214, 66, 0, 0, 34, 67, 0, 0, 214, 66, 0, 0, 35, 67, 0, 0, 214, 66, 0, 0, 36, 67, 0, 0, 214, 66, 0, 0, 37, 67, 0, 0, 214, 66, 0, 0, 38, 67, 0, 0, 214, 66, 0, 0, 39, 67, 0, 0, 214, 66, 0, 0, 40, 67, 0, 0, 214, 66, 0, 0, 41, 67, 0, 0, 214, 66, 0, 0, 42, 67, 0, 0, 214, 66, 0, 0, 43, 67, 0, 0, 214, 66, 0, 0, 44, 67, 0, 0, 214, 66, 0, 0, 45, 67, 0, 0, 214, 66, 0, 0, 46, 67, 0, 0, 214, 66, 0, 0, 47, 67, 0, 0, 214, 66, 0, 0, 48, 67, 0, 0, 214, 66, 0, 0, 49, 67, 0, 0, 214, 66, 0, 0, 50, 67, 0, 0, 214, 66, 0, 0, 51, 67, 0, 0, 214, 66, 0, 0, 52, 67, 0, 0, 214, 66, 0, 0, 53, 67, 0, 0, 214, 66, 0, 0, 54, 67, 0, 0, 214, 66, 0, 0, 55, 67, 0, 0, 216, 66, 0, 0, 184, 66, 0, 0, 216, 66, 0, 0, 186, 66, 0, 0, 216, 66, 0, 0, 188, 66, 0, 0, 216, 66, 0, 0, 190, 66, 0, 0, 216, 66, 0, 0, 192, 66, 0, 0, 216, 66, 0, 0, 194, 66, 0, 0, 216, 66, 0, 0, 196, 66, 0, 0, 216, 66, 0, 0, 198, 66, 0, 0, 216, 66, 0, 0, 200, 66, 0, 0, 216, 66, 0, 0, 202, 66, 0, 0, 216, 66, 0, 0, 204, 66, 0, 0, 216, 66, 0, 0, 206, 66, 0, 0, 216, 66, 0, 0, 208, 66, 0, 0, 216, 66, 0, 0, 210, 66, 0, 0, 216, 66, 0, 0, 212, 66, 0, 0, 216, 66, 0, 0, 214, 66, 0, 0, 216, 66, 0, 0, 216, 66, 0, 0, 216, 66, 0, 0, 218, 66, 0, 0, 216, 66, 0, 0, 220, 66, 0, 0, 216, 66, 0, 0, 222, 66, 0, 0, 216, 66, 0, 0, 224, 66, 0, 0, 216, 66, 0, 0, 226, 66, 0, 0, 216, 66, 0, 0, 228, 66, 0, 0, 216, 66, 0, 0, 230, 66, 0, 0, 216, 66, 0, 0, 232, 66, 0, 0, 216, 66, 0, 0, 234, 66, 0, 0, 216, 66, 0, 0, 236, 66, 0, 0, 216, 66, 0, 0, 238, 66, 0, 0, 216, 66, 0, 0, 240, 66, 0, 0, 216, 66, 0, 0, 242, 66, 0, 0, 216, 66, 0, 0, 244, 66, 0, 0, 216, 66, 0, 0, 246, 66, 0, 0, 216, 66, 0, 0, 248, 66, 0, 0, 216, 66, 0, 0, 250, 66, 0, 0, 216, 66, 0, 0, 252, 66, 0, 0, 216, 66, 0, 0, 254, 66, 0, 0, 216, 66, 0, 0, 0, 67, 0, 0, 216, 66, 0, 0, 1, 67, 0, 0, 216, 66, 0, 0, 2, 67, 0, 0, 216, 66, 0, 0, 3, 67, 0, 0, 216, 66, 0, 0, 4, 67, 0, 0, 216, 66, 0, 0, 5, 67, 0, 0, 216, 66, 0, 0, 6, 67, 0, 0, 216, 66, 0, 0, 7, 67, 0, 0, 216, 66, 0, 0, 8, 67, 0, 0, 216, 66, 0, 0, 9, 67, 0, 0, 216, 66, 0, 0, 10, 67, 0, 0, 216, 66, 0, 0, 11, 67, 0, 0, 216, 66, 0, 0, 12, 67, 0, 0, 216, 66, 0, 0, 13, 67, 0, 0, 216, 66, 0, 0, 14, 67, 0, 0, 216, 66, 0, 0, 15, 67, 0, 0, 216, 66, 0, 0, 16, 67, 0, 0, 216, 66, 0, 0, 17, 67, 0, 0, 216, 66, 0, 0, 18, 67, 0, 0, 216, 66, 0, 0, 19, 67, 0, 0, 216, 66, 0, 0, 20, 67, 0, 0, 216, 66, 0, 0, 21, 67, 0, 0, 216, 66, 0, 0, 22, 67, 0, 0, 216, 66, 0, 0, 23, 67, 0, 0, 216, 66, 0, 0, 24, 67, 0, 0, 216, 66, 0, 0, 25, 67, 0, 0, 216, 66, 0, 0, 26, 67, 0, 0, 216, 66, 0, 0, 27, 67, 0, 0, 216, 66, 0, 0, 28, 67, 0, 0, 216, 66, 0, 0, 29, 67, 0, 0, 216, 66, 0, 0, 30, 67, 0, 0, 216, 66, 0, 0, 31, 67, 0, 0, 216, 66, 0, 0, 32, 67, 0, 0, 216, 66, 0, 0, 33, 67, 0, 0, 216, 66, 0, 0, 34, 67, 0, 0, 216, 66, 0, 0, 35, 67, 0, 0, 216, 66, 0, 0, 36, 67, 0, 0, 216, 66, 0, 0, 37, 67, 0, 0, 216, 66, 0, 0, 38, 67, 0, 0, 216, 66, 0, 0, 39, 67, 0, 0, 216, 66, 0, 0, 40, 67, 0, 0, 216, 66, 0, 0, 41, 67, 0, 0, 216, 66, 0, 0, 42, 67, 0, 0, 216, 66, 0, 0, 43, 67, 0, 0, 216, 66, 0, 0, 44, 67, 0, 0, 216, 66, 0, 0, 45, 67, 0, 0, 216, 66, 0, 0, 46, 67, 0, 0, 216, 66, 0, 0, 47, 67, 0, 0, 216, 66, 0, 0, 48, 67, 0, 0, 216, 66, 0, 0, 49, 67, 0, 0, 216, 66, 0, 0, 50, 67, 0, 0, 216, 66, 0, 0, 51, 67, 0, 0, 216, 66, 0, 0, 52, 67, 0, 0, 216, 66, 0, 0, 53, 67, 0, 0, 216, 66, 0, 0, 54, 67, 0, 0, 216, 66, 0, 0, 55, 67, 0, 0, 218, 66, 0, 0, 184, 66, 0, 0, 218, 66, 0, 0, 186, 66, 0, 0, 218, 66, 0, 0, 188, 66, 0, 0, 218, 66, 0, 0, 190, 66, 0, 0, 218, 66, 0, 0, 192, 66, 0, 0, 218, 66, 0, 0, 194, 66, 0, 0, 218, 66, 0, 0, 196, 66, 0, 0, 218, 66, 0, 0, 198, 66, 0, 0, 218, 66, 0, 0, 200, 66, 0, 0, 218, 66, 0, 0, 202, 66, 0, 0, 218, 66, 0, 0, 204, 66, 0, 0, 218, 66, 0, 0, 206, 66, 0, 0, 218, 66, 0, 0, 208, 66, 0, 0, 218, 66, 0, 0, 210, 66, 0, 0, 218, 66, 0, 0, 212, 66, 0, 0, 218, 66, 0, 0, 214, 66, 0, 0, 218, 66, 0, 0, 216, 66, 0, 0, 218, 66, 0, 0, 218, 66, 0, 0, 218, 66, 0, 0, 220, 66, 0, 0, 218, 66, 0, 0, 222, 66, 0, 0, 218, 66, 0, 0, 224, 66, 0, 0, 218, 66, 0, 0, 226, 66, 0, 0, 218, 66, 0, 0, 228, 66, 0, 0, 218, 66, 0, 0, 230, 66, 0, 0, 218, 66, 0, 0, 232, 66, 0, 0, 218, 66, 0, 0, 234, 66, 0, 0, 218, 66, 0, 0, 236, 66, 0, 0, 218, 66, 0, 0, 238, 66, 0, 0, 218, 66, 0, 0, 240, 66, 0, 0, 218, 66, 0, 0, 242, 66, 0, 0, 218, 66, 0, 0, 244, 66, 0, 0, 218, 66, 0, 0, 246, 66, 0, 0, 218, 66, 0, 0, 248, 66, 0, 0, 218, 66, 0, 0, 250, 66, 0, 0, 218, 66, 0, 0, 252, 66, 0, 0, 218, 66, 0, 0, 254, 66, 0, 0, 218, 66, 0, 0, 0, 67, 0, 0, 218, 66, 0, 0, 1, 67, 0, 0, 218, 66, 0, 0, 2, 67, 0, 0, 218, 66, 0, 0, 3, 67, 0, 0, 218, 66, 0, 0, 4, 67, 0, 0, 218, 66, 0, 0, 5, 67, 0, 0, 218, 66, 0, 0, 6, 67, 0, 0, 218, 66, 0, 0, 7, 67, 0, 0, 218, 66, 0, 0, 8, 67, 0, 0, 218, 66, 0, 0, 9, 67, 0, 0, 218, 66, 0, 0, 10, 67, 0, 0, 218, 66, 0, 0, 11, 67, 0, 0, 218, 66, 0, 0, 12, 67, 0, 0, 218, 66, 0, 0, 13, 67, 0, 0, 218, 66, 0, 0, 14, 67, 0, 0, 218, 66, 0, 0, 15, 67, 0, 0, 218, 66, 0, 0, 16, 67, 0, 0, 218, 66, 0, 0, 17, 67, 0, 0, 218, 66, 0, 0, 18, 67, 0, 0, 218, 66, 0, 0, 19, 67, 0, 0, 218, 66, 0, 0, 20, 67, 0, 0, 218, 66, 0, 0, 21, 67, 0, 0, 218, 66, 0, 0, 22, 67, 0, 0, 218, 66, 0, 0, 23, 67, 0, 0, 218, 66, 0, 0, 24, 67, 0, 0, 218, 66, 0, 0, 25, 67, 0, 0, 218, 66, 0, 0, 26, 67, 0, 0, 218, 66, 0, 0, 27, 67, 0, 0, 218, 66, 0, 0, 28, 67, 0, 0, 218, 66, 0, 0, 29, 67, 0, 0, 218, 66, 0, 0, 30, 67, 0, 0, 218, 66, 0, 0, 31, 67, 0, 0, 218, 66, 0, 0, 32, 67, 0, 0, 218, 66, 0, 0, 33, 67, 0, 0, 218, 66, 0, 0, 34, 67, 0, 0, 218, 66, 0, 0, 35, 67, 0, 0, 218, 66, 0, 0, 36, 67, 0, 0, 218, 66, 0, 0, 37, 67, 0, 0, 218, 66, 0, 0, 38, 67, 0, 0, 218, 66, 0, 0, 39, 67, 0, 0, 218, 66, 0, 0, 40, 67, 0, 0, 218, 66, 0, 0, 41, 67, 0, 0, 218, 66, 0, 0, 42, 67, 0, 0, 218, 66, 0, 0, 43, 67, 0, 0, 218, 66, 0, 0, 44, 67, 0, 0, 218, 66, 0, 0, 45, 67, 0, 0, 218, 66, 0, 0, 46, 67, 0, 0, 218, 66, 0, 0, 47, 67, 0, 0, 218, 66, 0, 0, 48, 67, 0, 0, 218, 66, 0, 0, 49, 67, 0, 0, 218, 66, 0, 0, 50, 67, 0, 0, 218, 66, 0, 0, 51, 67, 0, 0, 218, 66, 0, 0, 52, 67, 0, 0, 218, 66, 0, 0, 53, 67, 0, 0, 218, 66, 0, 0, 54, 67, 0, 0, 218, 66, 0, 0, 55, 67, 0, 0, 220, 66, 0, 0, 184, 66, 0, 0, 220, 66, 0, 0, 186, 66, 0, 0, 220, 66, 0, 0, 188, 66, 0, 0, 220, 66, 0, 0, 190, 66, 0, 0, 220, 66, 0, 0, 192, 66, 0, 0, 220, 66, 0, 0, 194, 66, 0, 0, 220, 66, 0, 0, 196, 66, 0, 0, 220, 66, 0, 0, 198, 66, 0, 0, 220, 66, 0, 0, 200, 66, 0, 0, 220, 66, 0, 0, 202, 66, 0, 0, 220, 66, 0, 0, 204, 66, 0, 0, 220, 66, 0, 0, 206, 66, 0, 0, 220, 66, 0, 0, 208, 66, 0, 0, 220, 66, 0, 0, 210, 66, 0, 0, 220, 66, 0, 0, 212, 66, 0, 0, 220, 66, 0, 0, 214, 66, 0, 0, 220, 66, 0, 0, 216, 66, 0, 0, 220, 66, 0, 0, 218, 66, 0, 0, 220, 66, 0, 0, 220, 66, 0, 0, 220, 66, 0, 0, 222, 66, 0, 0, 220, 66, 0, 0, 224, 66, 0, 0, 220, 66, 0, 0, 226, 66, 0, 0, 220, 66, 0, 0, 228, 66, 0, 0, 220, 66, 0, 0, 230, 66, 0, 0, 220, 66, 0, 0, 232, 66, 0, 0, 220, 66, 0, 0, 234, 66, 0, 0, 220, 66, 0, 0, 236, 66, 0, 0, 220, 66, 0, 0, 238, 66, 0, 0, 220, 66, 0, 0, 240, 66, 0, 0, 220, 66, 0, 0, 242, 66, 0, 0, 220, 66, 0, 0, 244, 66, 0, 0, 220, 66, 0, 0, 246, 66, 0, 0, 220, 66, 0, 0, 248, 66, 0, 0, 220, 66, 0, 0, 250, 66, 0, 0, 220, 66, 0, 0, 252, 66, 0, 0, 220, 66, 0, 0, 254, 66, 0, 0, 220, 66, 0, 0, 0, 67, 0, 0, 220, 66, 0, 0, 1, 67, 0, 0, 220, 66, 0, 0, 2, 67, 0, 0, 220, 66, 0, 0, 3, 67, 0, 0, 220, 66, 0, 0, 4, 67, 0, 0, 220, 66, 0, 0, 5, 67, 0, 0, 220, 66, 0, 0, 6, 67, 0, 0, 220, 66, 0, 0, 7, 67, 0, 0, 220, 66, 0, 0, 8, 67, 0, 0, 220, 66, 0, 0, 9, 67, 0, 0, 220, 66, 0, 0, 10, 67, 0, 0, 220, 66, 0, 0, 11, 67, 0, 0, 220, 66, 0, 0, 12, 67, 0, 0, 220, 66, 0, 0, 13, 67, 0, 0, 220, 66, 0, 0, 14, 67, 0, 0, 220, 66, 0, 0, 15, 67, 0, 0, 220, 66, 0, 0, 16, 67, 0, 0, 220, 66, 0, 0, 17, 67, 0, 0, 220, 66, 0, 0, 18, 67, 0, 0, 220, 66, 0, 0, 19, 67, 0, 0, 220, 66, 0, 0, 20, 67, 0, 0, 220, 66, 0, 0, 21, 67, 0, 0, 220, 66, 0, 0, 22, 67, 0, 0, 220, 66, 0, 0, 23, 67, 0, 0, 220, 66, 0, 0, 24, 67, 0, 0, 220, 66, 0, 0, 25, 67, 0, 0, 220, 66, 0, 0, 26, 67, 0, 0, 220, 66, 0, 0, 27, 67, 0, 0, 220, 66, 0, 0, 28, 67, 0, 0, 220, 66, 0, 0, 29, 67, 0, 0, 220, 66, 0, 0, 30, 67, 0, 0, 220, 66, 0, 0, 31, 67, 0, 0, 220, 66, 0, 0, 32, 67, 0, 0, 220, 66, 0, 0, 33, 67, 0, 0, 220, 66, 0, 0, 34, 67, 0, 0, 220, 66, 0, 0, 35, 67, 0, 0, 220, 66, 0, 0, 36, 67, 0, 0, 220, 66, 0, 0, 37, 67, 0, 0, 220, 66, 0, 0, 38, 67, 0, 0, 220, 66, 0, 0, 39, 67, 0, 0, 220, 66, 0, 0, 40, 67, 0, 0, 220, 66, 0, 0, 41, 67, 0, 0, 220, 66, 0, 0, 42, 67, 0, 0, 220, 66, 0, 0, 43, 67, 0, 0, 220, 66, 0, 0, 44, 67, 0, 0, 220, 66, 0, 0, 45, 67, 0, 0, 220, 66, 0, 0, 46, 67, 0, 0, 220, 66, 0, 0, 47, 67, 0, 0, 220, 66, 0, 0, 48, 67, 0, 0, 220, 66, 0, 0, 49, 67, 0, 0, 220, 66, 0, 0, 50, 67, 0, 0, 220, 66, 0, 0, 51, 67, 0, 0, 220, 66, 0, 0, 52, 67, 0, 0, 220, 66, 0, 0, 53, 67, 0, 0, 220, 66, 0, 0, 54, 67, 0, 0, 220, 66, 0, 0, 55, 67, 0, 0, 222, 66, 0, 0, 184, 66, 0, 0, 222, 66, 0, 0, 186, 66, 0, 0, 222, 66, 0, 0, 188, 66, 0, 0, 222, 66, 0, 0, 190, 66, 0, 0, 222, 66, 0, 0, 192, 66, 0, 0, 222, 66, 0, 0, 194, 66, 0, 0, 222, 66, 0, 0, 196, 66, 0, 0, 222, 66, 0, 0, 198, 66, 0, 0, 222, 66, 0, 0, 200, 66, 0, 0, 222, 66, 0, 0, 202, 66, 0, 0, 222, 66, 0, 0, 204, 66, 0, 0, 222, 66, 0, 0, 206, 66, 0, 0, 222, 66, 0, 0, 208, 66, 0, 0, 222, 66, 0, 0, 210, 66, 0, 0, 222, 66, 0, 0, 212, 66, 0, 0, 222, 66, 0, 0, 214, 66, 0, 0, 222, 66, 0, 0, 216, 66, 0, 0, 222, 66, 0, 0, 218, 66, 0, 0, 222, 66, 0, 0, 220, 66, 0, 0, 222, 66, 0, 0, 222, 66, 0, 0, 222, 66, 0, 0, 224, 66, 0, 0, 222, 66, 0, 0, 226, 66, 0, 0, 222, 66, 0, 0, 228, 66, 0, 0, 222, 66, 0, 0, 230, 66, 0, 0, 222, 66, 0, 0, 232, 66, 0, 0, 222, 66, 0, 0, 234, 66, 0, 0, 222, 66, 0, 0, 236, 66, 0, 0, 222, 66, 0, 0, 238, 66, 0, 0, 222, 66, 0, 0, 240, 66, 0, 0, 222, 66, 0, 0, 242, 66, 0, 0, 222, 66, 0, 0, 244, 66, 0, 0, 222, 66, 0, 0, 246, 66, 0, 0, 222, 66, 0, 0, 248, 66, 0, 0, 222, 66, 0, 0, 250, 66, 0, 0, 222, 66, 0, 0, 252, 66, 0, 0, 222, 66, 0, 0, 254, 66, 0, 0, 222, 66, 0, 0, 0, 67, 0, 0, 222, 66, 0, 0, 1, 67, 0, 0, 222, 66, 0, 0, 2, 67, 0, 0, 222, 66, 0, 0, 3, 67, 0, 0, 222, 66, 0, 0, 4, 67, 0, 0, 222, 66, 0, 0, 5, 67, 0, 0, 222, 66, 0, 0, 6, 67, 0, 0, 222, 66, 0, 0, 7, 67, 0, 0, 222, 66, 0, 0, 8, 67, 0, 0, 222, 66, 0, 0, 9, 67, 0, 0, 222, 66, 0, 0, 10, 67, 0, 0, 222, 66, 0, 0, 11, 67, 0, 0, 222, 66, 0, 0, 12, 67, 0, 0, 222, 66, 0, 0, 13, 67, 0, 0, 222, 66, 0, 0, 14, 67, 0, 0, 222, 66, 0, 0, 15, 67, 0, 0, 222, 66, 0, 0, 16, 67, 0, 0, 222, 66, 0, 0, 17, 67, 0, 0, 222, 66, 0, 0, 18, 67, 0, 0, 222, 66, 0, 0, 19, 67, 0, 0, 222, 66, 0, 0, 20, 67, 0, 0, 222, 66, 0, 0, 21, 67, 0, 0, 222, 66, 0, 0, 22, 67, 0, 0, 222, 66, 0, 0, 23, 67, 0, 0, 222, 66, 0, 0, 24, 67, 0, 0, 222, 66, 0, 0, 25, 67, 0, 0, 222, 66, 0, 0, 26, 67, 0, 0, 222, 66, 0, 0, 27, 67, 0, 0, 222, 66, 0, 0, 28, 67, 0, 0, 222, 66, 0, 0, 29, 67, 0, 0, 222, 66, 0, 0, 30, 67, 0, 0, 222, 66, 0, 0, 31, 67, 0, 0, 222, 66, 0, 0, 32, 67, 0, 0, 222, 66, 0, 0, 33, 67, 0, 0, 222, 66, 0, 0, 34, 67, 0, 0, 222, 66, 0, 0, 35, 67, 0, 0, 222, 66, 0, 0, 36, 67, 0, 0, 222, 66, 0, 0, 37, 67, 0, 0, 222, 66, 0, 0, 38, 67, 0, 0, 222, 66, 0, 0, 39, 67, 0, 0, 222, 66, 0, 0, 40, 67, 0, 0, 222, 66, 0, 0, 41, 67, 0, 0, 222, 66, 0, 0, 42, 67, 0, 0, 222, 66, 0, 0, 43, 67, 0, 0, 222, 66, 0, 0, 44, 67, 0, 0, 222, 66, 0, 0, 45, 67, 0, 0, 222, 66, 0, 0, 46, 67, 0, 0, 222, 66, 0, 0, 47, 67, 0, 0, 222, 66, 0, 0, 48, 67, 0, 0, 222, 66, 0, 0, 49, 67, 0, 0, 222, 66, 0, 0, 50, 67, 0, 0, 222, 66, 0, 0, 51, 67, 0, 0, 222, 66, 0, 0, 52, 67, 0, 0, 222, 66, 0, 0, 53, 67, 0, 0, 222, 66, 0, 0, 54, 67, 0, 0, 222, 66, 0, 0, 55, 67, 0, 0, 224, 66, 0, 0, 184, 66, 0, 0, 224, 66, 0, 0, 186, 66, 0, 0, 224, 66, 0, 0, 188, 66, 0, 0, 224, 66, 0, 0, 190, 66, 0, 0, 224, 66, 0, 0, 192, 66, 0, 0, 224, 66, 0, 0, 194, 66, 0, 0, 224, 66, 0, 0, 196, 66, 0, 0, 224, 66, 0, 0, 198, 66, 0, 0, 224, 66, 0, 0, 200, 66, 0, 0, 224, 66, 0, 0, 202, 66, 0, 0, 224, 66, 0, 0, 204, 66, 0, 0, 224, 66, 0, 0, 206, 66, 0, 0, 224, 66, 0, 0, 208, 66, 0, 0, 224, 66, 0, 0, 210, 66, 0, 0, 224, 66, 0, 0, 212, 66, 0, 0, 224, 66, 0, 0, 214, 66, 0, 0, 224, 66, 0, 0, 216, 66, 0, 0, 224, 66, 0, 0, 218, 66, 0, 0, 224, 66, 0, 0, 220, 66, 0, 0, 224, 66, 0, 0, 222, 66, 0, 0, 224, 66, 0, 0, 224, 66, 0, 0, 224, 66, 0, 0, 226, 66, 0, 0, 224, 66, 0, 0, 228, 66, 0, 0, 224, 66, 0, 0, 230, 66, 0, 0, 224, 66, 0, 0, 232, 66, 0, 0, 224, 66, 0, 0, 234, 66, 0, 0, 224, 66, 0, 0, 236, 66, 0, 0, 224, 66, 0, 0, 238, 66, 0, 0, 224, 66, 0, 0, 240, 66, 0, 0, 224, 66, 0, 0, 242, 66, 0, 0, 224, 66, 0, 0, 244, 66, 0, 0, 224, 66, 0, 0, 246, 66, 0, 0, 224, 66, 0, 0, 248, 66, 0, 0, 224, 66, 0, 0, 250, 66, 0, 0, 224, 66, 0, 0, 252, 66, 0, 0, 224, 66, 0, 0, 254, 66, 0, 0, 224, 66, 0, 0, 0, 67, 0, 0, 224, 66, 0, 0, 1, 67, 0, 0, 224, 66, 0, 0, 2, 67, 0, 0, 224, 66, 0, 0, 3, 67, 0, 0, 224, 66, 0, 0, 4, 67, 0, 0, 224, 66, 0, 0, 5, 67, 0, 0, 224, 66, 0, 0, 6, 67, 0, 0, 224, 66, 0, 0, 7, 67, 0, 0, 224, 66, 0, 0, 8, 67, 0, 0, 224, 66, 0, 0, 9, 67, 0, 0, 224, 66, 0, 0, 10, 67, 0, 0, 224, 66, 0, 0, 11, 67, 0, 0, 224, 66, 0, 0, 12, 67, 0, 0, 224, 66, 0, 0, 13, 67, 0, 0, 224, 66, 0, 0, 14, 67, 0, 0, 224, 66, 0, 0, 15, 67, 0, 0, 224, 66, 0, 0, 16, 67, 0, 0, 224, 66, 0, 0, 17, 67, 0, 0, 224, 66, 0, 0, 18, 67, 0, 0, 224, 66, 0, 0, 19, 67, 0, 0, 224, 66, 0, 0, 20, 67, 0, 0, 224, 66, 0, 0, 21, 67, 0, 0, 224, 66, 0, 0, 22, 67, 0, 0, 224, 66, 0, 0, 23, 67, 0, 0, 224, 66, 0, 0, 24, 67, 0, 0, 224, 66, 0, 0, 25, 67, 0, 0, 224, 66, 0, 0, 26, 67, 0, 0, 224, 66, 0, 0, 27, 67, 0, 0, 224, 66, 0, 0, 28, 67, 0, 0, 224, 66, 0, 0, 29, 67, 0, 0, 224, 66, 0, 0, 30, 67, 0, 0, 224, 66, 0, 0, 31, 67, 0, 0, 224, 66, 0, 0, 32, 67, 0, 0, 224, 66, 0, 0, 33, 67, 0, 0, 224, 66, 0, 0, 34, 67, 0, 0, 224, 66, 0, 0, 35, 67, 0, 0, 224, 66, 0, 0, 36, 67, 0, 0, 224, 66, 0, 0, 37, 67, 0, 0, 224, 66, 0, 0, 38, 67, 0, 0, 224, 66, 0, 0, 39, 67, 0, 0, 224, 66, 0, 0, 40, 67, 0, 0, 224, 66, 0, 0, 41, 67, 0, 0, 224, 66, 0, 0, 42, 67, 0, 0, 224, 66, 0, 0, 43, 67, 0, 0, 224, 66, 0, 0, 44, 67, 0, 0, 224, 66, 0, 0, 45, 67, 0, 0, 224, 66, 0, 0, 46, 67, 0, 0, 224, 66, 0, 0, 47, 67, 0, 0, 224, 66, 0, 0, 48, 67, 0, 0, 224, 66, 0, 0, 49, 67, 0, 0, 224, 66, 0, 0, 50, 67, 0, 0, 224, 66, 0, 0, 51, 67, 0, 0, 224, 66, 0, 0, 52, 67, 0, 0, 224, 66, 0, 0, 53, 67, 0, 0, 224, 66, 0, 0, 54, 67, 0, 0, 224, 66, 0, 0, 55, 67, 0, 0, 226, 66, 0, 0, 184, 66, 0, 0, 226, 66, 0, 0, 186, 66, 0, 0, 226, 66, 0, 0, 188, 66, 0, 0, 226, 66, 0, 0, 190, 66, 0, 0, 226, 66, 0, 0, 192, 66, 0, 0, 226, 66, 0, 0, 194, 66, 0, 0, 226, 66, 0, 0, 196, 66, 0, 0, 226, 66, 0, 0, 198, 66, 0, 0, 226, 66, 0, 0, 200, 66, 0, 0, 226, 66, 0, 0, 202, 66, 0, 0, 226, 66, 0, 0, 204, 66, 0, 0, 226, 66, 0, 0, 206, 66, 0, 0, 226, 66, 0, 0, 208, 66, 0, 0, 226, 66, 0, 0, 210, 66, 0, 0, 226, 66, 0, 0, 212, 66, 0, 0, 226, 66, 0, 0, 214, 66, 0, 0, 226, 66, 0, 0, 216, 66, 0, 0, 226, 66, 0, 0, 218, 66, 0, 0, 226, 66, 0, 0, 220, 66, 0, 0, 226, 66, 0, 0, 222, 66, 0, 0, 226, 66, 0, 0, 224, 66, 0, 0, 226, 66, 0, 0, 226, 66, 0, 0, 226, 66, 0, 0, 228, 66, 0, 0, 226, 66, 0, 0, 230, 66, 0, 0, 226, 66, 0, 0, 232, 66, 0, 0, 226, 66, 0, 0, 234, 66, 0, 0, 226, 66, 0, 0, 236, 66, 0, 0, 226, 66, 0, 0, 238, 66, 0, 0, 226, 66, 0, 0, 240, 66, 0, 0, 226, 66, 0, 0, 242, 66, 0, 0, 226, 66, 0, 0, 244, 66, 0, 0, 226, 66, 0, 0, 246, 66, 0, 0, 226, 66, 0, 0, 248, 66, 0, 0, 226, 66, 0, 0, 250, 66, 0, 0, 226, 66, 0, 0, 252, 66, 0, 0, 226, 66, 0, 0, 254, 66, 0, 0, 226, 66, 0, 0, 0, 67, 0, 0, 226, 66, 0, 0, 1, 67, 0, 0, 226, 66, 0, 0, 2, 67, 0, 0, 226, 66, 0, 0, 3, 67, 0, 0, 226, 66, 0, 0, 4, 67, 0, 0, 226, 66, 0, 0, 5, 67, 0, 0, 226, 66, 0, 0, 6, 67, 0, 0, 226, 66, 0, 0, 7, 67, 0, 0, 226, 66, 0, 0, 8, 67, 0, 0, 226, 66, 0, 0, 9, 67, 0, 0, 226, 66, 0, 0, 10, 67, 0, 0, 226, 66, 0, 0, 11, 67, 0, 0, 226, 66, 0, 0, 12, 67, 0, 0, 226, 66, 0, 0, 13, 67, 0, 0, 226, 66, 0, 0, 14, 67, 0, 0, 226, 66, 0, 0, 15, 67, 0, 0, 226, 66, 0, 0, 16, 67, 0, 0, 226, 66, 0, 0, 17, 67, 0, 0, 226, 66, 0, 0, 18, 67, 0, 0, 226, 66, 0, 0, 19, 67, 0, 0, 226, 66, 0, 0, 20, 67, 0, 0, 226, 66, 0, 0, 21, 67, 0, 0, 226, 66, 0, 0, 22, 67, 0, 0, 226, 66, 0, 0, 23, 67, 0, 0, 226, 66, 0, 0, 24, 67, 0, 0, 226, 66, 0, 0, 25, 67, 0, 0, 226, 66, 0, 0, 26, 67, 0, 0, 226, 66, 0, 0, 27, 67, 0, 0, 226, 66, 0, 0, 28, 67, 0, 0, 226, 66, 0, 0, 29, 67, 0, 0, 226, 66, 0, 0, 30, 67, 0, 0, 226, 66, 0, 0, 31, 67, 0, 0, 226, 66, 0, 0, 32, 67, 0, 0, 226, 66, 0, 0, 33, 67, 0, 0, 226, 66, 0, 0, 34, 67, 0, 0, 226, 66, 0, 0, 35, 67, 0, 0, 226, 66, 0, 0, 36, 67, 0, 0, 226, 66, 0, 0, 37, 67, 0, 0, 226, 66, 0, 0, 38, 67, 0, 0, 226, 66, 0, 0, 39, 67, 0, 0, 226, 66, 0, 0, 40, 67, 0, 0, 226, 66, 0, 0, 41, 67, 0, 0, 226, 66, 0, 0, 42, 67, 0, 0, 226, 66, 0, 0, 43, 67, 0, 0, 226, 66, 0, 0, 44, 67, 0, 0, 226, 66, 0, 0, 45, 67, 0, 0, 226, 66, 0, 0, 46, 67, 0, 0, 226, 66, 0, 0, 47, 67, 0, 0, 226, 66, 0, 0, 48, 67, 0, 0, 226, 66, 0, 0, 49, 67, 0, 0, 226, 66, 0, 0, 50, 67, 0, 0, 226, 66, 0, 0, 51, 67, 0, 0, 226, 66, 0, 0, 52, 67, 0, 0, 226, 66, 0, 0, 53, 67, 0, 0, 226, 66, 0, 0, 54, 67, 0, 0, 226, 66, 0, 0, 55, 67, 0, 0, 228, 66, 0, 0, 184, 66, 0, 0, 228, 66, 0, 0, 186, 66, 0, 0, 228, 66, 0, 0, 188, 66, 0, 0, 228, 66, 0, 0, 190, 66, 0, 0, 228, 66, 0, 0, 192, 66, 0, 0, 228, 66, 0, 0, 194, 66, 0, 0, 228, 66, 0, 0, 196, 66, 0, 0, 228, 66, 0, 0, 198, 66, 0, 0, 228, 66, 0, 0, 200, 66, 0, 0, 228, 66, 0, 0, 202, 66, 0, 0, 228, 66, 0, 0, 204, 66, 0, 0, 228, 66, 0, 0, 206, 66, 0, 0, 228, 66, 0, 0, 208, 66, 0, 0, 228, 66, 0, 0, 210, 66, 0, 0, 228, 66, 0, 0, 212, 66, 0, 0, 228, 66, 0, 0, 214, 66, 0, 0, 228, 66, 0, 0, 216, 66, 0, 0, 228, 66, 0, 0, 218, 66, 0, 0, 228, 66, 0, 0, 220, 66, 0, 0, 228, 66, 0, 0, 222, 66, 0, 0, 228, 66, 0, 0, 224, 66, 0, 0, 228, 66, 0, 0, 226, 66, 0, 0, 228, 66, 0, 0, 228, 66, 0, 0, 228, 66, 0, 0, 230, 66, 0, 0, 228, 66, 0, 0, 232, 66, 0, 0, 228, 66, 0, 0, 234, 66, 0, 0, 228, 66, 0, 0, 236, 66, 0, 0, 228, 66, 0, 0, 238, 66, 0, 0, 228, 66, 0, 0, 240, 66, 0, 0, 228, 66, 0, 0, 242, 66, 0, 0, 228, 66, 0, 0, 244, 66, 0, 0, 228, 66, 0, 0, 246, 66, 0, 0, 228, 66, 0, 0, 248, 66, 0, 0, 228, 66, 0, 0, 250, 66, 0, 0, 228, 66, 0, 0, 252, 66, 0, 0, 228, 66, 0, 0, 254, 66, 0, 0, 228, 66, 0, 0, 0, 67, 0, 0, 228, 66, 0, 0, 1, 67, 0, 0, 228, 66, 0, 0, 2, 67, 0, 0, 228, 66, 0, 0, 3, 67, 0, 0, 228, 66, 0, 0, 4, 67, 0, 0, 228, 66, 0, 0, 5, 67, 0, 0, 228, 66, 0, 0, 6, 67, 0, 0, 228, 66, 0, 0, 7, 67, 0, 0, 228, 66, 0, 0, 8, 67, 0, 0, 228, 66, 0, 0, 9, 67, 0, 0, 228, 66, 0, 0, 10, 67, 0, 0, 228, 66, 0, 0, 11, 67, 0, 0, 228, 66, 0, 0, 12, 67, 0, 0, 228, 66, 0, 0, 13, 67, 0, 0, 228, 66, 0, 0, 14, 67, 0, 0, 228, 66, 0, 0, 15, 67, 0, 0, 228, 66, 0, 0, 16, 67, 0, 0, 228, 66, 0, 0, 17, 67, 0, 0, 228, 66, 0, 0, 18, 67, 0, 0, 228, 66, 0, 0, 19, 67, 0, 0, 228, 66, 0, 0, 20, 67, 0, 0, 228, 66, 0, 0, 21, 67, 0, 0, 228, 66, 0, 0, 22, 67, 0, 0, 228, 66, 0, 0, 23, 67, 0, 0, 228, 66, 0, 0, 24, 67, 0, 0, 228, 66, 0, 0, 25, 67, 0, 0, 228, 66, 0, 0, 26, 67, 0, 0, 228, 66, 0, 0, 27, 67, 0, 0, 228, 66, 0, 0, 28, 67, 0, 0, 228, 66, 0, 0, 29, 67, 0, 0, 228, 66, 0, 0, 30, 67, 0, 0, 228, 66, 0, 0, 31, 67, 0, 0, 228, 66, 0, 0, 32, 67, 0, 0, 228, 66, 0, 0, 33, 67, 0, 0, 228, 66, 0, 0, 34, 67, 0, 0, 228, 66, 0, 0, 35, 67, 0, 0, 228, 66, 0, 0, 36, 67, 0, 0, 228, 66, 0, 0, 37, 67, 0, 0, 228, 66, 0, 0, 38, 67, 0, 0, 228, 66, 0, 0, 39, 67, 0, 0, 228, 66, 0, 0, 40, 67, 0, 0, 228, 66, 0, 0, 41, 67, 0, 0, 228, 66, 0, 0, 42, 67, 0, 0, 228, 66, 0, 0, 43, 67, 0, 0, 228, 66, 0, 0, 44, 67, 0, 0, 228, 66, 0, 0, 45, 67, 0, 0, 228, 66, 0, 0, 46, 67, 0, 0, 228, 66, 0, 0, 47, 67, 0, 0, 228, 66, 0, 0, 48, 67, 0, 0, 228, 66, 0, 0, 49, 67, 0, 0, 228, 66, 0, 0, 50, 67, 0, 0, 228, 66, 0, 0, 51, 67, 0, 0, 228, 66, 0, 0, 52, 67, 0, 0, 228, 66, 0, 0, 53, 67, 0, 0, 228, 66, 0, 0, 54, 67, 0, 0, 228, 66, 0, 0, 55, 67, 0, 0, 230, 66, 0, 0, 184, 66, 0, 0, 230, 66, 0, 0, 186, 66, 0, 0, 230, 66, 0, 0, 188, 66, 0, 0, 230, 66, 0, 0, 190, 66, 0, 0, 230, 66, 0, 0, 192, 66, 0, 0, 230, 66, 0, 0, 194, 66, 0, 0, 230, 66, 0, 0, 196, 66, 0, 0, 230, 66, 0, 0, 198, 66, 0, 0, 230, 66, 0, 0, 200, 66, 0, 0, 230, 66, 0, 0, 202, 66, 0, 0, 230, 66, 0, 0, 204, 66, 0, 0, 230, 66, 0, 0, 206, 66, 0, 0, 230, 66, 0, 0, 208, 66, 0, 0, 230, 66, 0, 0, 210, 66, 0, 0, 230, 66, 0, 0, 212, 66, 0, 0, 230, 66, 0, 0, 214, 66, 0, 0, 230, 66, 0, 0, 216, 66, 0, 0, 230, 66, 0, 0, 218, 66, 0, 0, 230, 66, 0, 0, 220, 66, 0, 0, 230, 66, 0, 0, 222, 66, 0, 0, 230, 66, 0, 0, 224, 66, 0, 0, 230, 66, 0, 0, 226, 66, 0, 0, 230, 66, 0, 0, 228, 66, 0, 0, 230, 66, 0, 0, 230, 66, 0, 0, 230, 66, 0, 0, 232, 66, 0, 0, 230, 66, 0, 0, 234, 66, 0, 0, 230, 66, 0, 0, 236, 66, 0, 0, 230, 66, 0, 0, 238, 66, 0, 0, 230, 66, 0, 0, 240, 66, 0, 0, 230, 66, 0, 0, 242, 66, 0, 0, 230, 66, 0, 0, 244, 66, 0, 0, 230, 66, 0, 0, 246, 66, 0, 0, 230, 66, 0, 0, 248, 66, 0, 0, 230, 66, 0, 0, 250, 66, 0, 0, 230, 66, 0, 0, 252, 66, 0, 0, 230, 66, 0, 0, 254, 66, 0, 0, 230, 66, 0, 0, 0, 67, 0, 0, 230, 66, 0, 0, 1, 67, 0, 0, 230, 66, 0, 0, 2, 67, 0, 0, 230, 66, 0, 0, 3, 67, 0, 0, 230, 66, 0, 0, 4, 67, 0, 0, 230, 66, 0, 0, 5, 67, 0, 0, 230, 66, 0, 0, 6, 67, 0, 0, 230, 66, 0, 0, 7, 67, 0, 0, 230, 66, 0, 0, 8, 67, 0, 0, 230, 66, 0, 0, 9, 67, 0, 0, 230, 66, 0, 0, 10, 67, 0, 0, 230, 66, 0, 0, 11, 67, 0, 0, 230, 66, 0, 0, 12, 67, 0, 0, 230, 66, 0, 0, 13, 67, 0, 0, 230, 66, 0, 0, 14, 67, 0, 0, 230, 66, 0, 0, 15, 67, 0, 0, 230, 66, 0, 0, 16, 67, 0, 0, 230, 66, 0, 0, 17, 67, 0, 0, 230, 66, 0, 0, 18, 67, 0, 0, 230, 66, 0, 0, 19, 67, 0, 0, 230, 66, 0, 0, 20, 67, 0, 0, 230, 66, 0, 0, 21, 67, 0, 0, 230, 66, 0, 0, 22, 67, 0, 0, 230, 66, 0, 0, 23, 67, 0, 0, 230, 66, 0, 0, 24, 67, 0, 0, 230, 66, 0, 0, 25, 67, 0, 0, 230, 66, 0, 0, 26, 67, 0, 0, 230, 66, 0, 0, 27, 67, 0, 0, 230, 66, 0, 0, 28, 67, 0, 0, 230, 66, 0, 0, 29, 67, 0, 0, 230, 66, 0, 0, 30, 67, 0, 0, 230, 66, 0, 0, 31, 67, 0, 0, 230, 66, 0, 0, 32, 67, 0, 0, 230, 66, 0, 0, 33, 67, 0, 0, 230, 66, 0, 0, 34, 67, 0, 0, 230, 66, 0, 0, 35, 67, 0, 0, 230, 66, 0, 0, 36, 67, 0, 0, 230, 66, 0, 0, 37, 67, 0, 0, 230, 66, 0, 0, 38, 67, 0, 0, 230, 66, 0, 0, 39, 67, 0, 0, 230, 66, 0, 0, 40, 67, 0, 0, 230, 66, 0, 0, 41, 67, 0, 0, 230, 66, 0, 0, 42, 67, 0, 0, 230, 66, 0, 0, 43, 67, 0, 0, 230, 66, 0, 0, 44, 67, 0, 0, 230, 66, 0, 0, 45, 67, 0, 0, 230, 66, 0, 0, 46, 67, 0, 0, 230, 66, 0, 0, 47, 67, 0, 0, 230, 66, 0, 0, 48, 67, 0, 0, 230, 66, 0, 0, 49, 67, 0, 0, 230, 66, 0, 0, 50, 67, 0, 0, 230, 66, 0, 0, 51, 67, 0, 0, 230, 66, 0, 0, 52, 67, 0, 0, 230, 66, 0, 0, 53, 67, 0, 0, 230, 66, 0, 0, 54, 67, 0, 0, 230, 66, 0, 0, 55, 67, 0, 0, 232, 66, 0, 0, 184, 66, 0, 0, 232, 66, 0, 0, 186, 66, 0, 0, 232, 66, 0, 0, 188, 66, 0, 0, 232, 66, 0, 0, 190, 66, 0, 0, 232, 66, 0, 0, 192, 66, 0, 0, 232, 66, 0, 0, 194, 66, 0, 0, 232, 66, 0, 0, 196, 66, 0, 0, 232, 66, 0, 0, 198, 66, 0, 0, 232, 66, 0, 0, 200, 66, 0, 0, 232, 66, 0, 0, 202, 66, 0, 0, 232, 66, 0, 0, 204, 66, 0, 0, 232, 66, 0, 0, 206, 66, 0, 0, 232, 66, 0, 0, 208, 66, 0, 0, 232, 66, 0, 0, 210, 66, 0, 0, 232, 66, 0, 0, 212, 66, 0, 0, 232, 66, 0, 0, 214, 66, 0, 0, 232, 66, 0, 0, 216, 66, 0, 0, 232, 66, 0, 0, 218, 66, 0, 0, 232, 66, 0, 0, 220, 66, 0, 0, 232, 66, 0, 0, 222, 66, 0, 0, 232, 66, 0, 0, 224, 66, 0, 0, 232, 66, 0, 0, 226, 66, 0, 0, 232, 66, 0, 0, 228, 66, 0, 0, 232, 66, 0, 0, 230, 66, 0, 0, 232, 66, 0, 0, 232, 66, 0, 0, 232, 66, 0, 0, 234, 66, 0, 0, 232, 66, 0, 0, 236, 66, 0, 0, 232, 66, 0, 0, 238, 66, 0, 0, 232, 66, 0, 0, 240, 66, 0, 0, 232, 66, 0, 0, 242, 66, 0, 0, 232, 66, 0, 0, 244, 66, 0, 0, 232, 66, 0, 0, 246, 66, 0, 0, 232, 66, 0, 0, 248, 66, 0, 0, 232, 66, 0, 0, 250, 66, 0, 0, 232, 66, 0, 0, 252, 66, 0, 0, 232, 66, 0, 0, 254, 66, 0, 0, 232, 66, 0, 0, 0, 67, 0, 0, 232, 66, 0, 0, 1, 67, 0, 0, 232, 66, 0, 0, 2, 67, 0, 0, 232, 66, 0, 0, 3, 67, 0, 0, 232, 66, 0, 0, 4, 67, 0, 0, 232, 66, 0, 0, 5, 67, 0, 0, 232, 66, 0, 0, 6, 67, 0, 0, 232, 66, 0, 0, 7, 67, 0, 0, 232, 66, 0, 0, 8, 67, 0, 0, 232, 66, 0, 0, 9, 67, 0, 0, 232, 66, 0, 0, 10, 67, 0, 0, 232, 66, 0, 0, 11, 67, 0, 0, 232, 66, 0, 0, 12, 67, 0, 0, 232, 66, 0, 0, 13, 67, 0, 0, 232, 66, 0, 0, 14, 67, 0, 0, 232, 66, 0, 0, 15, 67, 0, 0, 232, 66, 0, 0, 16, 67, 0, 0, 232, 66, 0, 0, 17, 67, 0, 0, 232, 66, 0, 0, 18, 67, 0, 0, 232, 66, 0, 0, 19, 67, 0, 0, 232, 66, 0, 0, 20, 67, 0, 0, 232, 66, 0, 0, 21, 67, 0, 0, 232, 66, 0, 0, 22, 67, 0, 0, 232, 66, 0, 0, 23, 67, 0, 0, 232, 66, 0, 0, 24, 67, 0, 0, 232, 66, 0, 0, 25, 67, 0, 0, 232, 66, 0, 0, 26, 67, 0, 0, 232, 66, 0, 0, 27, 67, 0, 0, 232, 66, 0, 0, 28, 67, 0, 0, 232, 66, 0, 0, 29, 67, 0, 0, 232, 66, 0, 0, 30, 67, 0, 0, 232, 66, 0, 0, 31, 67, 0, 0, 232, 66, 0, 0, 32, 67, 0, 0, 232, 66, 0, 0, 33, 67, 0, 0, 232, 66, 0, 0, 34, 67, 0, 0, 232, 66, 0, 0, 35, 67, 0, 0, 232, 66, 0, 0, 36, 67, 0, 0, 232, 66, 0, 0, 37, 67, 0, 0, 232, 66, 0, 0, 38, 67, 0, 0, 232, 66, 0, 0, 39, 67, 0, 0, 232, 66, 0, 0, 40, 67, 0, 0, 232, 66, 0, 0, 41, 67, 0, 0, 232, 66, 0, 0, 42, 67, 0, 0, 232, 66, 0, 0, 43, 67, 0, 0, 232, 66, 0, 0, 44, 67, 0, 0, 232, 66, 0, 0, 45, 67, 0, 0, 232, 66, 0, 0, 46, 67, 0, 0, 232, 66, 0, 0, 47, 67, 0, 0, 232, 66, 0, 0, 48, 67, 0, 0, 232, 66, 0, 0, 49, 67, 0, 0, 232, 66, 0, 0, 50, 67, 0, 0, 232, 66, 0, 0, 51, 67, 0, 0, 232, 66, 0, 0, 52, 67, 0, 0, 232, 66, 0, 0, 53, 67, 0, 0, 232, 66, 0, 0, 54, 67, 0, 0, 232, 66, 0, 0, 55, 67, 0, 0, 234, 66, 0, 0, 184, 66, 0, 0, 234, 66, 0, 0, 186, 66, 0, 0, 234, 66, 0, 0, 188, 66, 0, 0, 234, 66, 0, 0, 190, 66, 0, 0, 234, 66, 0, 0, 192, 66, 0, 0, 234, 66, 0, 0, 194, 66, 0, 0, 234, 66, 0, 0, 196, 66, 0, 0, 234, 66, 0, 0, 198, 66, 0, 0, 234, 66, 0, 0, 200, 66, 0, 0, 234, 66, 0, 0, 202, 66, 0, 0, 234, 66, 0, 0, 204, 66, 0, 0, 234, 66, 0, 0, 206, 66, 0, 0, 234, 66, 0, 0, 208, 66, 0, 0, 234, 66, 0, 0, 210, 66, 0, 0, 234, 66, 0, 0, 212, 66, 0, 0, 234, 66, 0, 0, 214, 66, 0, 0, 234, 66, 0, 0, 216, 66, 0, 0, 234, 66, 0, 0, 218, 66, 0, 0, 234, 66, 0, 0, 220, 66, 0, 0, 234, 66, 0, 0, 222, 66, 0, 0, 234, 66, 0, 0, 224, 66, 0, 0, 234, 66, 0, 0, 226, 66, 0, 0, 234, 66, 0, 0, 228, 66, 0, 0, 234, 66, 0, 0, 230, 66, 0, 0, 234, 66, 0, 0, 232, 66, 0, 0, 234, 66, 0, 0, 234, 66, 0, 0, 234, 66, 0, 0, 236, 66, 0, 0, 234, 66, 0, 0, 238, 66, 0, 0, 234, 66, 0, 0, 240, 66, 0, 0, 234, 66, 0, 0, 242, 66, 0, 0, 234, 66, 0, 0, 244, 66, 0, 0, 234, 66, 0, 0, 246, 66, 0, 0, 234, 66, 0, 0, 248, 66, 0, 0, 234, 66, 0, 0, 250, 66, 0, 0, 234, 66, 0, 0, 252, 66, 0, 0, 234, 66, 0, 0, 254, 66, 0, 0, 234, 66, 0, 0, 0, 67, 0, 0, 234, 66, 0, 0, 1, 67, 0, 0, 234, 66, 0, 0, 2, 67, 0, 0, 234, 66, 0, 0, 3, 67, 0, 0, 234, 66, 0, 0, 4, 67, 0, 0, 234, 66, 0, 0, 5, 67, 0, 0, 234, 66, 0, 0, 6, 67, 0, 0, 234, 66, 0, 0, 7, 67, 0, 0, 234, 66, 0, 0, 8, 67, 0, 0, 234, 66, 0, 0, 9, 67, 0, 0, 234, 66, 0, 0, 10, 67, 0, 0, 234, 66, 0, 0, 11, 67, 0, 0, 234, 66, 0, 0, 12, 67, 0, 0, 234, 66, 0, 0, 13, 67, 0, 0, 234, 66, 0, 0, 14, 67, 0, 0, 234, 66, 0, 0, 15, 67, 0, 0, 234, 66, 0, 0, 16, 67, 0, 0, 234, 66, 0, 0, 17, 67, 0, 0, 234, 66, 0, 0, 18, 67, 0, 0, 234, 66, 0, 0, 19, 67, 0, 0, 234, 66, 0, 0, 20, 67, 0, 0, 234, 66, 0, 0, 21, 67, 0, 0, 234, 66, 0, 0, 22, 67, 0, 0, 234, 66, 0, 0, 23, 67, 0, 0, 234, 66, 0, 0, 24, 67, 0, 0, 234, 66, 0, 0, 25, 67, 0, 0, 234, 66, 0, 0, 26, 67, 0, 0, 234, 66, 0, 0, 27, 67, 0, 0, 234, 66, 0, 0, 28, 67, 0, 0, 234, 66, 0, 0, 29, 67, 0, 0, 234, 66, 0, 0, 30, 67, 0, 0, 234, 66, 0, 0, 31, 67, 0, 0, 234, 66, 0, 0, 32, 67, 0, 0, 234, 66, 0, 0, 33, 67, 0, 0, 234, 66, 0, 0, 34, 67, 0, 0, 234, 66, 0, 0, 35, 67, 0, 0, 234, 66, 0, 0, 36, 67, 0, 0, 234, 66, 0, 0, 37, 67, 0, 0, 234, 66, 0, 0, 38, 67, 0, 0, 234, 66, 0, 0, 39, 67, 0, 0, 234, 66, 0, 0, 40, 67, 0, 0, 234, 66, 0, 0, 41, 67, 0, 0, 234, 66, 0, 0, 42, 67, 0, 0, 234, 66, 0, 0, 43, 67, 0, 0, 234, 66, 0, 0, 44, 67, 0, 0, 234, 66, 0, 0, 45, 67, 0, 0, 234, 66, 0, 0, 46, 67, 0, 0, 234, 66, 0, 0, 47, 67, 0, 0, 234, 66, 0, 0, 48, 67, 0, 0, 234, 66, 0, 0, 49, 67, 0, 0, 234, 66, 0, 0, 50, 67, 0, 0, 234, 66, 0, 0, 51, 67, 0, 0, 234, 66, 0, 0, 52, 67, 0, 0, 234, 66, 0, 0, 53, 67, 0, 0, 234, 66, 0, 0, 54, 67, 0, 0, 234, 66, 0, 0, 55, 67, 0, 0, 236, 66, 0, 0, 184, 66, 0, 0, 236, 66, 0, 0, 186, 66, 0, 0, 236, 66, 0, 0, 188, 66, 0, 0, 236, 66, 0, 0, 190, 66, 0, 0, 236, 66, 0, 0, 192, 66, 0, 0, 236, 66, 0, 0, 194, 66, 0, 0, 236, 66, 0, 0, 196, 66, 0, 0, 236, 66, 0, 0, 198, 66, 0, 0, 236, 66, 0, 0, 200, 66, 0, 0, 236, 66, 0, 0, 202, 66, 0, 0, 236, 66, 0, 0, 204, 66, 0, 0, 236, 66, 0, 0, 206, 66, 0, 0, 236, 66, 0, 0, 208, 66, 0, 0, 236, 66, 0, 0, 210, 66, 0, 0, 236, 66, 0, 0, 212, 66, 0, 0, 236, 66, 0, 0, 214, 66, 0, 0, 236, 66, 0, 0, 216, 66, 0, 0, 236, 66, 0, 0, 218, 66, 0, 0, 236, 66, 0, 0, 220, 66, 0, 0, 236, 66, 0, 0, 222, 66, 0, 0, 236, 66, 0, 0, 224, 66, 0, 0, 236, 66, 0, 0, 226, 66, 0, 0, 236, 66, 0, 0, 228, 66, 0, 0, 236, 66, 0, 0, 230, 66, 0, 0, 236, 66, 0, 0, 232, 66, 0, 0, 236, 66, 0, 0, 234, 66, 0, 0, 236, 66, 0, 0, 236, 66, 0, 0, 236, 66, 0, 0, 238, 66, 0, 0, 236, 66, 0, 0, 240, 66, 0, 0, 236, 66, 0, 0, 242, 66, 0, 0, 236, 66, 0, 0, 244, 66, 0, 0, 236, 66, 0, 0, 246, 66, 0, 0, 236, 66, 0, 0, 248, 66, 0, 0, 236, 66, 0, 0, 250, 66, 0, 0, 236, 66, 0, 0, 252, 66, 0, 0, 236, 66, 0, 0, 254, 66, 0, 0, 236, 66, 0, 0, 0, 67, 0, 0, 236, 66, 0, 0, 1, 67, 0, 0, 236, 66, 0, 0, 2, 67, 0, 0, 236, 66, 0, 0, 3, 67, 0, 0, 236, 66, 0, 0, 4, 67, 0, 0, 236, 66, 0, 0, 5, 67, 0, 0, 236, 66, 0, 0, 6, 67, 0, 0, 236, 66, 0, 0, 7, 67, 0, 0, 236, 66, 0, 0, 8, 67, 0, 0, 236, 66, 0, 0, 9, 67, 0, 0, 236, 66, 0, 0, 10, 67, 0, 0, 236, 66, 0, 0, 11, 67, 0, 0, 236, 66, 0, 0, 12, 67, 0, 0, 236, 66, 0, 0, 13, 67, 0, 0, 236, 66, 0, 0, 14, 67, 0, 0, 236, 66, 0, 0, 15, 67, 0, 0, 236, 66, 0, 0, 16, 67, 0, 0, 236, 66, 0, 0, 17, 67, 0, 0, 236, 66, 0, 0, 18, 67, 0, 0, 236, 66, 0, 0, 19, 67, 0, 0, 236, 66, 0, 0, 20, 67, 0, 0, 236, 66, 0, 0, 21, 67, 0, 0, 236, 66, 0, 0, 22, 67, 0, 0, 236, 66, 0, 0, 23, 67, 0, 0, 236, 66, 0, 0, 24, 67, 0, 0, 236, 66, 0, 0, 25, 67, 0, 0, 236, 66, 0, 0, 26, 67, 0, 0, 236, 66, 0, 0, 27, 67, 0, 0, 236, 66, 0, 0, 28, 67, 0, 0, 236, 66, 0, 0, 29, 67, 0, 0, 236, 66, 0, 0, 30, 67, 0, 0, 236, 66, 0, 0, 31, 67, 0, 0, 236, 66, 0, 0, 32, 67, 0, 0, 236, 66, 0, 0, 33, 67, 0, 0, 236, 66, 0, 0, 34, 67, 0, 0, 236, 66, 0, 0, 35, 67, 0, 0, 236, 66, 0, 0, 36, 67, 0, 0, 236, 66, 0, 0, 37, 67, 0, 0, 236, 66, 0, 0, 38, 67, 0, 0, 236, 66, 0, 0, 39, 67, 0, 0, 236, 66, 0, 0, 40, 67, 0, 0, 236, 66, 0, 0, 41, 67, 0, 0, 236, 66, 0, 0, 42, 67, 0, 0, 236, 66, 0, 0, 43, 67, 0, 0, 236, 66, 0, 0, 44, 67, 0, 0, 236, 66, 0, 0, 45, 67, 0, 0, 236, 66, 0, 0, 46, 67, 0, 0, 236, 66, 0, 0, 47, 67, 0, 0, 236, 66, 0, 0, 48, 67, 0, 0, 236, 66, 0, 0, 49, 67, 0, 0, 236, 66, 0, 0, 50, 67, 0, 0, 236, 66, 0, 0, 51, 67, 0, 0, 236, 66, 0, 0, 52, 67, 0, 0, 236, 66, 0, 0, 53, 67, 0, 0, 236, 66, 0, 0, 54, 67, 0, 0, 236, 66, 0, 0, 55, 67, 0, 0, 238, 66, 0, 0, 184, 66, 0, 0, 238, 66, 0, 0, 186, 66, 0, 0, 238, 66, 0, 0, 188, 66, 0, 0, 238, 66, 0, 0, 190, 66, 0, 0, 238, 66, 0, 0, 192, 66, 0, 0, 238, 66, 0, 0, 194, 66, 0, 0, 238, 66, 0, 0, 196, 66, 0, 0, 238, 66, 0, 0, 198, 66, 0, 0, 238, 66, 0, 0, 200, 66, 0, 0, 238, 66, 0, 0, 202, 66, 0, 0, 238, 66, 0, 0, 204, 66, 0, 0, 238, 66, 0, 0, 206, 66, 0, 0, 238, 66, 0, 0, 208, 66, 0, 0, 238, 66, 0, 0, 210, 66, 0, 0, 238, 66, 0, 0, 212, 66, 0, 0, 238, 66, 0, 0, 214, 66, 0, 0, 238, 66, 0, 0, 216, 66, 0, 0, 238, 66, 0, 0, 218, 66, 0, 0, 238, 66, 0, 0, 220, 66, 0, 0, 238, 66, 0, 0, 222, 66, 0, 0, 238, 66, 0, 0, 224, 66, 0, 0, 238, 66, 0, 0, 226, 66, 0, 0, 238, 66, 0, 0, 228, 66, 0, 0, 238, 66, 0, 0, 230, 66, 0, 0, 238, 66, 0, 0, 232, 66, 0, 0, 238, 66, 0, 0, 234, 66, 0, 0, 238, 66, 0, 0, 236, 66, 0, 0, 238, 66, 0, 0, 238, 66, 0, 0, 238, 66, 0, 0, 240, 66, 0, 0, 238, 66, 0, 0, 242, 66, 0, 0, 238, 66, 0, 0, 244, 66, 0, 0, 238, 66, 0, 0, 246, 66, 0, 0, 238, 66, 0, 0, 248, 66, 0, 0, 238, 66, 0, 0, 250, 66, 0, 0, 238, 66, 0, 0, 252, 66, 0, 0, 238, 66, 0, 0, 254, 66, 0, 0, 238, 66, 0, 0, 0, 67, 0, 0, 238, 66, 0, 0, 1, 67, 0, 0, 238, 66, 0, 0, 2, 67, 0, 0, 238, 66, 0, 0, 3, 67, 0, 0, 238, 66, 0, 0, 4, 67, 0, 0, 238, 66, 0, 0, 5, 67, 0, 0, 238, 66, 0, 0, 6, 67, 0, 0, 238, 66, 0, 0, 7, 67, 0, 0, 238, 66, 0, 0, 8, 67, 0, 0, 238, 66, 0, 0, 9, 67, 0, 0, 238, 66, 0, 0, 10, 67, 0, 0, 238, 66, 0, 0, 11, 67, 0, 0, 238, 66, 0, 0, 12, 67, 0, 0, 238, 66, 0, 0, 13, 67, 0, 0, 238, 66, 0, 0, 14, 67, 0, 0, 238, 66, 0, 0, 15, 67, 0, 0, 238, 66, 0, 0, 16, 67, 0, 0, 238, 66, 0, 0, 17, 67, 0, 0, 238, 66, 0, 0, 18, 67, 0, 0, 238, 66, 0, 0, 19, 67, 0, 0, 238, 66, 0, 0, 20, 67, 0, 0, 238, 66, 0, 0, 21, 67, 0, 0, 238, 66, 0, 0, 22, 67, 0, 0, 238, 66, 0, 0, 23, 67, 0, 0, 238, 66, 0, 0, 24, 67, 0, 0, 238, 66, 0, 0, 25, 67, 0, 0, 238, 66, 0, 0, 26, 67, 0, 0, 238, 66, 0, 0, 27, 67, 0, 0, 238, 66, 0, 0, 28, 67, 0, 0, 238, 66, 0, 0, 29, 67, 0, 0, 238, 66, 0, 0, 30, 67, 0, 0, 238, 66, 0, 0, 31, 67, 0, 0, 238, 66, 0, 0, 32, 67, 0, 0, 238, 66, 0, 0, 33, 67, 0, 0, 238, 66, 0, 0, 34, 67, 0, 0, 238, 66, 0, 0, 35, 67, 0, 0, 238, 66, 0, 0, 36, 67, 0, 0, 238, 66, 0, 0, 37, 67, 0, 0, 238, 66, 0, 0, 38, 67, 0, 0, 238, 66, 0, 0, 39, 67, 0, 0, 238, 66, 0, 0, 40, 67, 0, 0, 238, 66, 0, 0, 41, 67, 0, 0, 238, 66, 0, 0, 42, 67, 0, 0, 238, 66, 0, 0, 43, 67, 0, 0, 238, 66, 0, 0, 44, 67, 0, 0, 238, 66, 0, 0, 45, 67, 0, 0, 238, 66, 0, 0, 46, 67, 0, 0, 238, 66, 0, 0, 47, 67, 0, 0, 238, 66, 0, 0, 48, 67, 0, 0, 238, 66, 0, 0, 49, 67, 0, 0, 238, 66, 0, 0, 50, 67, 0, 0, 238, 66, 0, 0, 51, 67, 0, 0, 238, 66, 0, 0, 52, 67, 0, 0, 238, 66, 0, 0, 53, 67, 0, 0, 238, 66, 0, 0, 54, 67, 0, 0, 238, 66, 0, 0, 55, 67, 0, 0, 240, 66, 0, 0, 184, 66, 0, 0, 240, 66, 0, 0, 186, 66, 0, 0, 240, 66, 0, 0, 188, 66, 0, 0, 240, 66, 0, 0, 190, 66, 0, 0, 240, 66, 0, 0, 192, 66, 0, 0, 240, 66, 0, 0, 194, 66, 0, 0, 240, 66, 0, 0, 196, 66, 0, 0, 240, 66, 0, 0, 198, 66, 0, 0, 240, 66, 0, 0, 200, 66, 0, 0, 240, 66, 0, 0, 202, 66, 0, 0, 240, 66, 0, 0, 204, 66, 0, 0, 240, 66, 0, 0, 206, 66, 0, 0, 240, 66, 0, 0, 208, 66, 0, 0, 240, 66, 0, 0, 210, 66, 0, 0, 240, 66, 0, 0, 212, 66, 0, 0, 240, 66, 0, 0, 214, 66, 0, 0, 240, 66, 0, 0, 216, 66, 0, 0, 240, 66, 0, 0, 40, 67, 0, 0, 240, 66, 0, 0, 41, 67, 0, 0, 240, 66, 0, 0, 42, 67, 0, 0, 240, 66, 0, 0, 43, 67, 0, 0, 240, 66, 0, 0, 44, 67, 0, 0, 240, 66, 0, 0, 45, 67, 0, 0, 240, 66, 0, 0, 46, 67, 0, 0, 240, 66, 0, 0, 47, 67, 0, 0, 240, 66, 0, 0, 48, 67, 0, 0, 240, 66, 0, 0, 49, 67, 0, 0, 240, 66, 0, 0, 50, 67, 0, 0, 240, 66, 0, 0, 51, 67, 0, 0, 240, 66, 0, 0, 52, 67, 0, 0, 240, 66, 0, 0, 53, 67, 0, 0, 240, 66, 0, 0, 54, 67, 0, 0, 240, 66, 0, 0, 55, 67, 0, 0, 242, 66, 0, 0, 184, 66, 0, 0, 242, 66, 0, 0, 186, 66, 0, 0, 242, 66, 0, 0, 188, 66, 0, 0, 242, 66, 0, 0, 190, 66, 0, 0, 242, 66, 0, 0, 192, 66, 0, 0, 242, 66, 0, 0, 194, 66, 0, 0, 242, 66, 0, 0, 196, 66, 0, 0, 242, 66, 0, 0, 198, 66, 0, 0, 242, 66, 0, 0, 200, 66, 0, 0, 242, 66, 0, 0, 202, 66, 0, 0, 242, 66, 0, 0, 204, 66, 0, 0, 242, 66, 0, 0, 206, 66, 0, 0, 242, 66, 0, 0, 208, 66, 0, 0, 242, 66, 0, 0, 210, 66, 0, 0, 242, 66, 0, 0, 212, 66, 0, 0, 242, 66, 0, 0, 41, 67, 0, 0, 242, 66, 0, 0, 42, 67, 0, 0, 242, 66, 0, 0, 43, 67, 0, 0, 242, 66, 0, 0, 44, 67, 0, 0, 242, 66, 0, 0, 45, 67, 0, 0, 242, 66, 0, 0, 46, 67, 0, 0, 242, 66, 0, 0, 47, 67, 0, 0, 242, 66, 0, 0, 48, 67, 0, 0, 242, 66, 0, 0, 49, 67, 0, 0, 242, 66, 0, 0, 50, 67, 0, 0, 242, 66, 0, 0, 51, 67, 0, 0, 242, 66, 0, 0, 52, 67, 0, 0, 242, 66, 0, 0, 53, 67, 0, 0, 242, 66, 0, 0, 54, 67, 0, 0, 242, 66, 0, 0, 55, 67, 0, 0, 244, 66, 0, 0, 184, 66, 0, 0, 244, 66, 0, 0, 186, 66, 0, 0, 244, 66, 0, 0, 188, 66, 0, 0, 244, 66, 0, 0, 190, 66, 0, 0, 244, 66, 0, 0, 192, 66, 0, 0, 244, 66, 0, 0, 194, 66, 0, 0, 244, 66, 0, 0, 196, 66, 0, 0, 244, 66, 0, 0, 198, 66, 0, 0, 244, 66, 0, 0, 200, 66, 0, 0, 244, 66, 0, 0, 202, 66, 0, 0, 244, 66, 0, 0, 204, 66, 0, 0, 244, 66, 0, 0, 206, 66, 0, 0, 244, 66, 0, 0, 208, 66, 0, 0, 244, 66, 0, 0, 210, 66, 0, 0, 244, 66, 0, 0, 43, 67, 0, 0, 244, 66, 0, 0, 44, 67, 0, 0, 244, 66, 0, 0, 45, 67, 0, 0, 244, 66, 0, 0, 46, 67, 0, 0, 244, 66, 0, 0, 47, 67, 0, 0, 244, 66, 0, 0, 48, 67, 0, 0, 244, 66, 0, 0, 49, 67, 0, 0, 244, 66, 0, 0, 50, 67, 0, 0, 244, 66, 0, 0, 51, 67, 0, 0, 244, 66, 0, 0, 52, 67, 0, 0, 244, 66, 0, 0, 53, 67, 0, 0, 244, 66, 0, 0, 54, 67, 0, 0, 244, 66, 0, 0, 55, 67, 0, 0, 246, 66, 0, 0, 184, 66, 0, 0, 246, 66, 0, 0, 186, 66, 0, 0, 246, 66, 0, 0, 188, 66, 0, 0, 246, 66, 0, 0, 190, 66, 0, 0, 246, 66, 0, 0, 192, 66, 0, 0, 246, 66, 0, 0, 194, 66, 0, 0, 246, 66, 0, 0, 196, 66, 0, 0, 246, 66, 0, 0, 198, 66, 0, 0, 246, 66, 0, 0, 200, 66, 0, 0, 246, 66, 0, 0, 202, 66, 0, 0, 246, 66, 0, 0, 204, 66, 0, 0, 246, 66, 0, 0, 206, 66, 0, 0, 246, 66, 0, 0, 208, 66, 0, 0, 246, 66, 0, 0, 43, 67, 0, 0, 246, 66, 0, 0, 44, 67, 0, 0, 246, 66, 0, 0, 45, 67, 0, 0, 246, 66, 0, 0, 46, 67, 0, 0, 246, 66, 0, 0, 47, 67, 0, 0, 246, 66, 0, 0, 48, 67, 0, 0, 246, 66, 0, 0, 49, 67, 0, 0, 246, 66, 0, 0, 50, 67, 0, 0, 246, 66, 0, 0, 51, 67, 0, 0, 246, 66, 0, 0, 52, 67, 0, 0, 246, 66, 0, 0, 53, 67, 0, 0, 246, 66, 0, 0, 54, 67, 0, 0, 246, 66, 0, 0, 55, 67, 0, 0, 248, 66, 0, 0, 184, 66, 0, 0, 248, 66, 0, 0, 186, 66, 0, 0, 248, 66, 0, 0, 188, 66, 0, 0, 248, 66, 0, 0, 190, 66, 0, 0, 248, 66, 0, 0, 192, 66, 0, 0, 248, 66, 0, 0, 194, 66, 0, 0, 248, 66, 0, 0, 196, 66, 0, 0, 248, 66, 0, 0, 198, 66, 0, 0, 248, 66, 0, 0, 200, 66, 0, 0, 248, 66, 0, 0, 202, 66, 0, 0, 248, 66, 0, 0, 204, 66, 0, 0, 248, 66, 0, 0, 206, 66, 0, 0, 248, 66, 0, 0, 44, 67, 0, 0, 248, 66, 0, 0, 45, 67, 0, 0, 248, 66, 0, 0, 46, 67, 0, 0, 248, 66, 0, 0, 47, 67, 0, 0, 248, 66, 0, 0, 48, 67, 0, 0, 248, 66, 0, 0, 49, 67, 0, 0, 248, 66, 0, 0, 50, 67, 0, 0, 248, 66, 0, 0, 51, 67, 0, 0, 248, 66, 0, 0, 52, 67, 0, 0, 248, 66, 0, 0, 53, 67, 0, 0, 248, 66, 0, 0, 54, 67, 0, 0, 248, 66, 0, 0, 55, 67, 0, 0, 250, 66, 0, 0, 184, 66, 0, 0, 250, 66, 0, 0, 186, 66, 0, 0, 250, 66, 0, 0, 188, 66, 0, 0, 250, 66, 0, 0, 190, 66, 0, 0, 250, 66, 0, 0, 192, 66, 0, 0, 250, 66, 0, 0, 194, 66, 0, 0, 250, 66, 0, 0, 196, 66, 0, 0, 250, 66, 0, 0, 198, 66, 0, 0, 250, 66, 0, 0, 200, 66, 0, 0, 250, 66, 0, 0, 202, 66, 0, 0, 250, 66, 0, 0, 204, 66, 0, 0, 250, 66, 0, 0, 206, 66, 0, 0, 250, 66, 0, 0, 44, 67, 0, 0, 250, 66, 0, 0, 45, 67, 0, 0, 250, 66, 0, 0, 46, 67, 0, 0, 250, 66, 0, 0, 47, 67, 0, 0, 250, 66, 0, 0, 48, 67, 0, 0, 250, 66, 0, 0, 49, 67, 0, 0, 250, 66, 0, 0, 50, 67, 0, 0, 250, 66, 0, 0, 51, 67, 0, 0, 250, 66, 0, 0, 52, 67, 0, 0, 250, 66, 0, 0, 53, 67, 0, 0, 250, 66, 0, 0, 54, 67, 0, 0, 250, 66, 0, 0, 55, 67, 0, 0, 252, 66, 0, 0, 184, 66, 0, 0, 252, 66, 0, 0, 186, 66, 0, 0, 252, 66, 0, 0, 188, 66, 0, 0, 252, 66, 0, 0, 190, 66, 0, 0, 252, 66, 0, 0, 192, 66, 0, 0, 252, 66, 0, 0, 194, 66, 0, 0, 252, 66, 0, 0, 196, 66, 0, 0, 252, 66, 0, 0, 198, 66, 0, 0, 252, 66, 0, 0, 200, 66, 0, 0, 252, 66, 0, 0, 202, 66, 0, 0, 252, 66, 0, 0, 204, 66, 0, 0, 252, 66, 0, 0, 206, 66, 0, 0, 252, 66, 0, 0, 44, 67, 0, 0, 252, 66, 0, 0, 45, 67, 0, 0, 252, 66, 0, 0, 46, 67, 0, 0, 252, 66, 0, 0, 47, 67, 0, 0, 252, 66, 0, 0, 48, 67, 0, 0, 252, 66, 0, 0, 49, 67, 0, 0, 252, 66, 0, 0, 50, 67, 0, 0, 252, 66, 0, 0, 51, 67, 0, 0, 252, 66, 0, 0, 52, 67, 0, 0, 252, 66, 0, 0, 53, 67, 0, 0, 252, 66, 0, 0, 54, 67, 0, 0, 252, 66, 0, 0, 55, 67, 0, 0, 254, 66, 0, 0, 184, 66, 0, 0, 254, 66, 0, 0, 186, 66, 0, 0, 254, 66, 0, 0, 188, 66, 0, 0, 254, 66, 0, 0, 190, 66, 0, 0, 254, 66, 0, 0, 192, 66, 0, 0, 254, 66, 0, 0, 194, 66, 0, 0, 254, 66, 0, 0, 196, 66, 0, 0, 254, 66, 0, 0, 198, 66, 0, 0, 254, 66, 0, 0, 200, 66, 0, 0, 254, 66, 0, 0, 202, 66, 0, 0, 254, 66, 0, 0, 204, 66, 0, 0, 254, 66, 0, 0, 206, 66, 0, 0, 254, 66, 0, 0, 44, 67, 0, 0, 254, 66, 0, 0, 45, 67, 0, 0, 254, 66, 0, 0, 46, 67, 0, 0, 254, 66, 0, 0, 47, 67, 0, 0, 254, 66, 0, 0, 48, 67, 0, 0, 254, 66, 0, 0, 49, 67, 0, 0, 254, 66, 0, 0, 50, 67, 0, 0, 254, 66, 0, 0, 51, 67, 0, 0, 254, 66, 0, 0, 52, 67, 0, 0, 254, 66, 0, 0, 53, 67, 0, 0, 254, 66, 0, 0, 54, 67, 0, 0, 254, 66, 0, 0, 55, 67, 0, 0, 0, 67, 0, 0, 184, 66, 0, 0, 0, 67, 0, 0, 186, 66, 0, 0, 0, 67, 0, 0, 188, 66, 0, 0, 0, 67, 0, 0, 190, 66, 0, 0, 0, 67, 0, 0, 192, 66, 0, 0, 0, 67, 0, 0, 194, 66, 0, 0, 0, 67, 0, 0, 196, 66, 0, 0, 0, 67, 0, 0, 198, 66, 0, 0, 0, 67, 0, 0, 200, 66, 0, 0, 0, 67, 0, 0, 202, 66, 0, 0, 0, 67, 0, 0, 204, 66, 0, 0, 0, 67, 0, 0, 206, 66, 0, 0, 0, 67, 0, 0, 45, 67, 0, 0, 0, 67, 0, 0, 46, 67, 0, 0, 0, 67, 0, 0, 47, 67, 0, 0, 0, 67, 0, 0, 48, 67, 0, 0, 0, 67, 0, 0, 49, 67, 0, 0, 0, 67, 0, 0, 50, 67, 0, 0, 0, 67, 0, 0, 51, 67, 0, 0, 0, 67, 0, 0, 52, 67, 0, 0, 0, 67, 0, 0, 53, 67, 0, 0, 0, 67, 0, 0, 54, 67, 0, 0, 0, 67, 0, 0, 55, 67, 0, 0, 1, 67, 0, 0, 184, 66, 0, 0, 1, 67, 0, 0, 186, 66, 0, 0, 1, 67, 0, 0, 188, 66, 0, 0, 1, 67, 0, 0, 190, 66, 0, 0, 1, 67, 0, 0, 192, 66, 0, 0, 1, 67, 0, 0, 194, 66, 0, 0, 1, 67, 0, 0, 196, 66, 0, 0, 1, 67, 0, 0, 198, 66, 0, 0, 1, 67, 0, 0, 200, 66, 0, 0, 1, 67, 0, 0, 202, 66, 0, 0, 1, 67, 0, 0, 204, 66, 0, 0, 1, 67, 0, 0, 206, 66, 0, 0, 1, 67, 0, 0, 45, 67, 0, 0, 1, 67, 0, 0, 46, 67, 0, 0, 1, 67, 0, 0, 47, 67, 0, 0, 1, 67, 0, 0, 48, 67, 0, 0, 1, 67, 0, 0, 49, 67, 0, 0, 1, 67, 0, 0, 50, 67, 0, 0, 1, 67, 0, 0, 51, 67, 0, 0, 1, 67, 0, 0, 52, 67, 0, 0, 1, 67, 0, 0, 53, 67, 0, 0, 1, 67, 0, 0, 54, 67, 0, 0, 1, 67, 0, 0, 55, 67, 0, 0, 2, 67, 0, 0, 184, 66, 0, 0, 2, 67, 0, 0, 186, 66, 0, 0, 2, 67, 0, 0, 188, 66, 0, 0, 2, 67, 0, 0, 190, 66, 0, 0, 2, 67, 0, 0, 192, 66, 0, 0, 2, 67, 0, 0, 194, 66, 0, 0, 2, 67, 0, 0, 196, 66, 0, 0, 2, 67, 0, 0, 198, 66, 0, 0, 2, 67, 0, 0, 200, 66, 0, 0, 2, 67, 0, 0, 202, 66, 0, 0, 2, 67, 0, 0, 204, 66, 0, 0, 2, 67, 0, 0, 45, 67, 0, 0, 2, 67, 0, 0, 46, 67, 0, 0, 2, 67, 0, 0, 47, 67, 0, 0, 2, 67, 0, 0, 48, 67, 0, 0, 2, 67, 0, 0, 49, 67, 0, 0, 2, 67, 0, 0, 50, 67, 0, 0, 2, 67, 0, 0, 51, 67, 0, 0, 2, 67, 0, 0, 52, 67, 0, 0, 2, 67, 0, 0, 53, 67, 0, 0, 2, 67, 0, 0, 54, 67, 0, 0, 2, 67, 0, 0, 55, 67, 0, 0, 3, 67, 0, 0, 184, 66, 0, 0, 3, 67, 0, 0, 186, 66, 0, 0, 3, 67, 0, 0, 188, 66, 0, 0, 3, 67, 0, 0, 190, 66, 0, 0, 3, 67, 0, 0, 192, 66, 0, 0, 3, 67, 0, 0, 194, 66, 0, 0, 3, 67, 0, 0, 196, 66, 0, 0, 3, 67, 0, 0, 198, 66, 0, 0, 3, 67, 0, 0, 200, 66, 0, 0, 3, 67, 0, 0, 202, 66, 0, 0, 3, 67, 0, 0, 46, 67, 0, 0, 3, 67, 0, 0, 47, 67, 0, 0, 3, 67, 0, 0, 48, 67, 0, 0, 3, 67, 0, 0, 49, 67, 0, 0, 3, 67, 0, 0, 50, 67, 0, 0, 3, 67, 0, 0, 51, 67, 0, 0, 3, 67, 0, 0, 52, 67, 0, 0, 3, 67, 0, 0, 53, 67, 0, 0, 3, 67, 0, 0, 54, 67, 0, 0, 3, 67, 0, 0, 55, 67, 0, 0, 10, 67, 0, 0, 184, 66, 0, 0, 10, 67, 0, 0, 186, 66, 0, 0, 10, 67, 0, 0, 188, 66, 0, 0, 10, 67, 0, 0, 190, 66, 0, 0, 10, 67, 0, 0, 192, 66, 0, 0, 10, 67, 0, 0, 194, 66, 0, 0, 10, 67, 0, 0, 196, 66, 0, 0, 10, 67, 0, 0, 198, 66, 0, 0, 10, 67, 0, 0, 200, 66, 0, 0, 10, 67, 0, 0, 202, 66, 0, 0, 10, 67, 0, 0, 46, 67, 0, 0, 10, 67, 0, 0, 47, 67, 0, 0, 10, 67, 0, 0, 48, 67, 0, 0, 10, 67, 0, 0, 49, 67, 0, 0, 10, 67, 0, 0, 50, 67, 0, 0, 10, 67, 0, 0, 51, 67, 0, 0, 10, 67, 0, 0, 52, 67, 0, 0, 10, 67, 0, 0, 53, 67, 0, 0, 10, 67, 0, 0, 54, 67, 0, 0, 10, 67, 0, 0, 55, 67, 0, 0, 11, 67, 0, 0, 184, 66, 0, 0, 11, 67, 0, 0, 186, 66, 0, 0, 11, 67, 0, 0, 188, 66, 0, 0, 11, 67, 0, 0, 190, 66, 0, 0, 11, 67, 0, 0, 192, 66, 0, 0, 11, 67, 0, 0, 194, 66, 0, 0, 11, 67, 0, 0, 196, 66, 0, 0, 11, 67, 0, 0, 198, 66, 0, 0, 11, 67, 0, 0, 200, 66, 0, 0, 11, 67, 0, 0, 202, 66, 0, 0, 11, 67, 0, 0, 204, 66, 0, 0, 11, 67, 0, 0, 45, 67, 0, 0, 11, 67, 0, 0, 46, 67, 0, 0, 11, 67, 0, 0, 47, 67, 0, 0, 11, 67, 0, 0, 48, 67, 0, 0, 11, 67, 0, 0, 49, 67, 0, 0, 11, 67, 0, 0, 50, 67, 0, 0, 11, 67, 0, 0, 51, 67, 0, 0, 11, 67, 0, 0, 52, 67, 0, 0, 11, 67, 0, 0, 53, 67, 0, 0, 11, 67, 0, 0, 54, 67, 0, 0, 11, 67, 0, 0, 55, 67, 0, 0, 12, 67, 0, 0, 184, 66, 0, 0, 12, 67, 0, 0, 186, 66, 0, 0, 12, 67, 0, 0, 188, 66, 0, 0, 12, 67, 0, 0, 190, 66, 0, 0, 12, 67, 0, 0, 192, 66, 0, 0, 12, 67, 0, 0, 194, 66, 0, 0, 12, 67, 0, 0, 196, 66, 0, 0, 12, 67, 0, 0, 198, 66, 0, 0, 12, 67, 0, 0, 200, 66, 0, 0, 12, 67, 0, 0, 202, 66, 0, 0, 12, 67, 0, 0, 204, 66, 0, 0, 12, 67, 0, 0, 45, 67, 0, 0, 12, 67, 0, 0, 46, 67, 0, 0, 12, 67, 0, 0, 47, 67, 0, 0, 12, 67, 0, 0, 48, 67, 0, 0, 12, 67, 0, 0, 49, 67, 0, 0, 12, 67, 0, 0, 50, 67, 0, 0, 12, 67, 0, 0, 51, 67, 0, 0, 12, 67, 0, 0, 52, 67, 0, 0, 12, 67, 0, 0, 53, 67, 0, 0, 12, 67, 0, 0, 54, 67, 0, 0, 12, 67, 0, 0, 55, 67, 0, 0, 13, 67, 0, 0, 184, 66, 0, 0, 13, 67, 0, 0, 186, 66, 0, 0, 13, 67, 0, 0, 188, 66, 0, 0, 13, 67, 0, 0, 190, 66, 0, 0, 13, 67, 0, 0, 192, 66, 0, 0, 13, 67, 0, 0, 194, 66, 0, 0, 13, 67, 0, 0, 196, 66, 0, 0, 13, 67, 0, 0, 198, 66, 0, 0, 13, 67, 0, 0, 200, 66, 0, 0, 13, 67, 0, 0, 202, 66, 0, 0, 13, 67, 0, 0, 204, 66, 0, 0, 13, 67, 0, 0, 45, 67, 0, 0, 13, 67, 0, 0, 46, 67, 0, 0, 13, 67, 0, 0, 47, 67, 0, 0, 13, 67, 0, 0, 48, 67, 0, 0, 13, 67, 0, 0, 49, 67, 0, 0, 13, 67, 0, 0, 50, 67, 0, 0, 13, 67, 0, 0, 51, 67, 0, 0, 13, 67, 0, 0, 52, 67, 0, 0, 13, 67, 0, 0, 53, 67, 0, 0, 13, 67, 0, 0, 54, 67, 0, 0, 13, 67, 0, 0, 55, 67, 0, 0, 14, 67, 0, 0, 184, 66, 0, 0, 14, 67, 0, 0, 186, 66, 0, 0, 14, 67, 0, 0, 188, 66, 0, 0, 14, 67, 0, 0, 190, 66, 0, 0, 14, 67, 0, 0, 192, 66, 0, 0, 14, 67, 0, 0, 194, 66, 0, 0, 14, 67, 0, 0, 196, 66, 0, 0, 14, 67, 0, 0, 198, 66, 0, 0, 14, 67, 0, 0, 200, 66, 0, 0, 14, 67, 0, 0, 202, 66, 0, 0, 14, 67, 0, 0, 204, 66, 0, 0, 14, 67, 0, 0, 44, 67, 0, 0, 14, 67, 0, 0, 45, 67, 0, 0, 14, 67, 0, 0, 46, 67, 0, 0, 14, 67, 0, 0, 47, 67, 0, 0, 14, 67, 0, 0, 48, 67, 0, 0, 14, 67, 0, 0, 49, 67, 0, 0, 14, 67, 0, 0, 50, 67, 0, 0, 14, 67, 0, 0, 51, 67, 0, 0, 14, 67, 0, 0, 52, 67, 0, 0, 14, 67, 0, 0, 53, 67, 0, 0, 14, 67, 0, 0, 54, 67, 0, 0, 14, 67, 0, 0, 55, 67, 0, 0, 15, 67, 0, 0, 184, 66, 0, 0, 15, 67, 0, 0, 186, 66, 0, 0, 15, 67, 0, 0, 188, 66, 0, 0, 15, 67, 0, 0, 190, 66, 0, 0, 15, 67, 0, 0, 192, 66, 0, 0, 15, 67, 0, 0, 194, 66, 0, 0, 15, 67, 0, 0, 196, 66, 0, 0, 15, 67, 0, 0, 198, 66, 0, 0, 15, 67, 0, 0, 200, 66, 0, 0, 15, 67, 0, 0, 202, 66, 0, 0, 15, 67, 0, 0, 204, 66, 0, 0, 15, 67, 0, 0, 206, 66, 0, 0, 15, 67, 0, 0, 44, 67, 0, 0, 15, 67, 0, 0, 45, 67, 0, 0, 15, 67, 0, 0, 46, 67, 0, 0, 15, 67, 0, 0, 47, 67, 0, 0, 15, 67, 0, 0, 48, 67, 0, 0, 15, 67, 0, 0, 49, 67, 0, 0, 15, 67, 0, 0, 50, 67, 0, 0, 15, 67, 0, 0, 51, 67, 0, 0, 15, 67, 0, 0, 52, 67, 0, 0, 15, 67, 0, 0, 53, 67, 0, 0, 15, 67, 0, 0, 54, 67, 0, 0, 15, 67, 0, 0, 55, 67, 0, 0, 16, 67, 0, 0, 184, 66, 0, 0, 16, 67, 0, 0, 186, 66, 0, 0, 16, 67, 0, 0, 188, 66, 0, 0, 16, 67, 0, 0, 190, 66, 0, 0, 16, 67, 0, 0, 192, 66, 0, 0, 16, 67, 0, 0, 194, 66, 0, 0, 16, 67, 0, 0, 196, 66, 0, 0, 16, 67, 0, 0, 198, 66, 0, 0, 16, 67, 0, 0, 200, 66, 0, 0, 16, 67, 0, 0, 202, 66, 0, 0, 16, 67, 0, 0, 204, 66, 0, 0, 16, 67, 0, 0, 206, 66, 0, 0, 16, 67, 0, 0, 44, 67, 0, 0, 16, 67, 0, 0, 45, 67, 0, 0, 16, 67, 0, 0, 46, 67, 0, 0, 16, 67, 0, 0, 47, 67, 0, 0, 16, 67, 0, 0, 48, 67, 0, 0, 16, 67, 0, 0, 49, 67, 0, 0, 16, 67, 0, 0, 50, 67, 0, 0, 16, 67, 0, 0, 51, 67, 0, 0, 16, 67, 0, 0, 52, 67, 0, 0, 16, 67, 0, 0, 53, 67, 0, 0, 16, 67, 0, 0, 54, 67, 0, 0, 16, 67, 0, 0, 55, 67, 0, 0, 17, 67, 0, 0, 184, 66, 0, 0, 17, 67, 0, 0, 186, 66, 0, 0, 17, 67, 0, 0, 188, 66, 0, 0, 17, 67, 0, 0, 190, 66, 0, 0, 17, 67, 0, 0, 192, 66, 0, 0, 17, 67, 0, 0, 194, 66, 0, 0, 17, 67, 0, 0, 196, 66, 0, 0, 17, 67, 0, 0, 198, 66, 0, 0, 17, 67, 0, 0, 200, 66, 0, 0, 17, 67, 0, 0, 202, 66, 0, 0, 17, 67, 0, 0, 204, 66, 0, 0, 17, 67, 0, 0, 206, 66, 0, 0, 17, 67, 0, 0, 44, 67, 0, 0, 17, 67, 0, 0, 45, 67, 0, 0, 17, 67, 0, 0, 46, 67, 0, 0, 17, 67, 0, 0, 47, 67, 0, 0, 17, 67, 0, 0, 48, 67, 0, 0, 17, 67, 0, 0, 49, 67, 0, 0, 17, 67, 0, 0, 50, 67, 0, 0, 17, 67, 0, 0, 51, 67, 0, 0, 17, 67, 0, 0, 52, 67, 0, 0, 17, 67, 0, 0, 53, 67, 0, 0, 17, 67, 0, 0, 54, 67, 0, 0, 17, 67, 0, 0, 55, 67, 0, 0, 18, 67, 0, 0, 184, 66, 0, 0, 18, 67, 0, 0, 186, 66, 0, 0, 18, 67, 0, 0, 188, 66, 0, 0, 18, 67, 0, 0, 190, 66, 0, 0, 18, 67, 0, 0, 192, 66, 0, 0, 18, 67, 0, 0, 194, 66, 0, 0, 18, 67, 0, 0, 196, 66, 0, 0, 18, 67, 0, 0, 198, 66, 0, 0, 18, 67, 0, 0, 200, 66, 0, 0, 18, 67, 0, 0, 202, 66, 0, 0, 18, 67, 0, 0, 204, 66, 0, 0, 18, 67, 0, 0, 206, 66, 0, 0, 18, 67, 0, 0, 44, 67, 0, 0, 18, 67, 0, 0, 45, 67, 0, 0, 18, 67, 0, 0, 46, 67, 0, 0, 18, 67, 0, 0, 47, 67, 0, 0, 18, 67, 0, 0, 48, 67, 0, 0, 18, 67, 0, 0, 49, 67, 0, 0, 18, 67, 0, 0, 50, 67, 0, 0, 18, 67, 0, 0, 51, 67, 0, 0, 18, 67, 0, 0, 52, 67, 0, 0, 18, 67, 0, 0, 53, 67, 0, 0, 18, 67, 0, 0, 54, 67, 0, 0, 18, 67, 0, 0, 55, 67, 0, 0, 19, 67, 0, 0, 184, 66, 0, 0, 19, 67, 0, 0, 186, 66, 0, 0, 19, 67, 0, 0, 188, 66, 0, 0, 19, 67, 0, 0, 190, 66, 0, 0, 19, 67, 0, 0, 192, 66, 0, 0, 19, 67, 0, 0, 194, 66, 0, 0, 19, 67, 0, 0, 196, 66, 0, 0, 19, 67, 0, 0, 198, 66, 0, 0, 19, 67, 0, 0, 200, 66, 0, 0, 19, 67, 0, 0, 202, 66, 0, 0, 19, 67, 0, 0, 204, 66, 0, 0, 19, 67, 0, 0, 206, 66, 0, 0, 19, 67, 0, 0, 208, 66, 0, 0, 19, 67, 0, 0, 43, 67, 0, 0, 19, 67, 0, 0, 44, 67, 0, 0, 19, 67, 0, 0, 45, 67, 0, 0, 19, 67, 0, 0, 46, 67, 0, 0, 19, 67, 0, 0, 47, 67, 0, 0, 19, 67, 0, 0, 48, 67, 0, 0, 19, 67, 0, 0, 49, 67, 0, 0, 19, 67, 0, 0, 50, 67, 0, 0, 19, 67, 0, 0, 51, 67, 0, 0, 19, 67, 0, 0, 52, 67, 0, 0, 19, 67, 0, 0, 53, 67, 0, 0, 19, 67, 0, 0, 54, 67, 0, 0, 19, 67, 0, 0, 55, 67, 0, 0, 20, 67, 0, 0, 184, 66, 0, 0, 20, 67, 0, 0, 186, 66, 0, 0, 20, 67, 0, 0, 188, 66, 0, 0, 20, 67, 0, 0, 190, 66, 0, 0, 20, 67, 0, 0, 192, 66, 0, 0, 20, 67, 0, 0, 194, 66, 0, 0, 20, 67, 0, 0, 196, 66, 0, 0, 20, 67, 0, 0, 198, 66, 0, 0, 20, 67, 0, 0, 200, 66, 0, 0, 20, 67, 0, 0, 202, 66, 0, 0, 20, 67, 0, 0, 204, 66, 0, 0, 20, 67, 0, 0, 206, 66, 0, 0, 20, 67, 0, 0, 208, 66, 0, 0, 20, 67, 0, 0, 210, 66, 0, 0, 20, 67, 0, 0, 42, 67, 0, 0, 20, 67, 0, 0, 43, 67, 0, 0, 20, 67, 0, 0, 44, 67, 0, 0, 20, 67, 0, 0, 45, 67, 0, 0, 20, 67, 0, 0, 46, 67, 0, 0, 20, 67, 0, 0, 47, 67, 0, 0, 20, 67, 0, 0, 48, 67, 0, 0, 20, 67, 0, 0, 49, 67, 0, 0, 20, 67, 0, 0, 50, 67, 0, 0, 20, 67, 0, 0, 51, 67, 0, 0, 20, 67, 0, 0, 52, 67, 0, 0, 20, 67, 0, 0, 53, 67, 0, 0, 20, 67, 0, 0, 54, 67, 0, 0, 20, 67, 0, 0, 55, 67, 0, 0, 21, 67, 0, 0, 184, 66, 0, 0, 21, 67, 0, 0, 186, 66, 0, 0, 21, 67, 0, 0, 188, 66, 0, 0, 21, 67, 0, 0, 190, 66, 0, 0, 21, 67, 0, 0, 192, 66, 0, 0, 21, 67, 0, 0, 194, 66, 0, 0, 21, 67, 0, 0, 196, 66, 0, 0, 21, 67, 0, 0, 198, 66, 0, 0, 21, 67, 0, 0, 200, 66, 0, 0, 21, 67, 0, 0, 202, 66, 0, 0, 21, 67, 0, 0, 204, 66, 0, 0, 21, 67, 0, 0, 206, 66, 0, 0, 21, 67, 0, 0, 208, 66, 0, 0, 21, 67, 0, 0, 210, 66, 0, 0, 21, 67, 0, 0, 212, 66, 0, 0, 21, 67, 0, 0, 214, 66, 0, 0, 21, 67, 0, 0, 40, 67, 0, 0, 21, 67, 0, 0, 41, 67, 0, 0, 21, 67, 0, 0, 42, 67, 0, 0, 21, 67, 0, 0, 43, 67, 0, 0, 21, 67, 0, 0, 44, 67, 0, 0, 21, 67, 0, 0, 45, 67, 0, 0, 21, 67, 0, 0, 46, 67, 0, 0, 21, 67, 0, 0, 47, 67, 0, 0, 21, 67, 0, 0, 48, 67, 0, 0, 21, 67, 0, 0, 49, 67, 0, 0, 21, 67, 0, 0, 50, 67, 0, 0, 21, 67, 0, 0, 51, 67, 0, 0, 21, 67, 0, 0, 52, 67, 0, 0, 21, 67, 0, 0, 53, 67, 0, 0, 21, 67, 0, 0, 54, 67, 0, 0, 21, 67, 0, 0, 55, 67, 0, 0, 22, 67, 0, 0, 184, 66, 0, 0, 22, 67, 0, 0, 186, 66, 0, 0, 22, 67, 0, 0, 188, 66, 0, 0, 22, 67, 0, 0, 190, 66, 0, 0, 22, 67, 0, 0, 192, 66, 0, 0, 22, 67, 0, 0, 194, 66, 0, 0, 22, 67, 0, 0, 196, 66, 0, 0, 22, 67, 0, 0, 198, 66, 0, 0, 22, 67, 0, 0, 200, 66, 0, 0, 22, 67, 0, 0, 202, 66, 0, 0, 22, 67, 0, 0, 204, 66, 0, 0, 22, 67, 0, 0, 206, 66, 0, 0, 22, 67, 0, 0, 208, 66, 0, 0, 22, 67, 0, 0, 210, 66, 0, 0, 22, 67, 0, 0, 212, 66, 0, 0, 22, 67, 0, 0, 214, 66, 0, 0, 22, 67, 0, 0, 216, 66, 0, 0, 22, 67, 0, 0, 218, 66, 0, 0, 22, 67, 0, 0, 220, 66, 0, 0, 22, 67, 0, 0, 222, 66, 0, 0, 22, 67, 0, 0, 224, 66, 0, 0, 22, 67, 0, 0, 226, 66, 0, 0, 22, 67, 0, 0, 228, 66, 0, 0, 22, 67, 0, 0, 230, 66, 0, 0, 22, 67, 0, 0, 232, 66, 0, 0, 22, 67, 0, 0, 234, 66, 0, 0, 22, 67, 0, 0, 236, 66, 0, 0, 22, 67, 0, 0, 238, 66, 0, 0, 22, 67, 0, 0, 240, 66, 0, 0, 22, 67, 0, 0, 242, 66, 0, 0, 22, 67, 0, 0, 244, 66, 0, 0, 22, 67, 0, 0, 246, 66, 0, 0, 22, 67, 0, 0, 248, 66, 0, 0, 22, 67, 0, 0, 250, 66, 0, 0, 22, 67, 0, 0, 252, 66, 0, 0, 22, 67, 0, 0, 254, 66, 0, 0, 22, 67, 0, 0, 0, 67, 0, 0, 22, 67, 0, 0, 1, 67, 0, 0, 22, 67, 0, 0, 2, 67, 0, 0, 22, 67, 0, 0, 3, 67, 0, 0, 22, 67, 0, 0, 4, 67, 0, 0, 22, 67, 0, 0, 5, 67, 0, 0, 22, 67, 0, 0, 6, 67, 0, 0, 22, 67, 0, 0, 7, 67, 0, 0, 22, 67, 0, 0, 8, 67, 0, 0, 22, 67, 0, 0, 9, 67, 0, 0, 22, 67, 0, 0, 10, 67, 0, 0, 22, 67, 0, 0, 11, 67, 0, 0, 22, 67, 0, 0, 12, 67, 0, 0, 22, 67, 0, 0, 13, 67, 0, 0, 22, 67, 0, 0, 14, 67, 0, 0, 22, 67, 0, 0, 15, 67, 0, 0, 22, 67, 0, 0, 16, 67, 0, 0, 22, 67, 0, 0, 17, 67, 0, 0, 22, 67, 0, 0, 18, 67, 0, 0, 22, 67, 0, 0, 19, 67, 0, 0, 22, 67, 0, 0, 20, 67, 0, 0, 22, 67, 0, 0, 21, 67, 0, 0, 22, 67, 0, 0, 22, 67, 0, 0, 22, 67, 0, 0, 23, 67, 0, 0, 22, 67, 0, 0, 24, 67, 0, 0, 22, 67, 0, 0, 25, 67, 0, 0, 22, 67, 0, 0, 26, 67, 0, 0, 22, 67, 0, 0, 27, 67, 0, 0, 22, 67, 0, 0, 28, 67, 0, 0, 22, 67, 0, 0, 29, 67, 0, 0, 22, 67, 0, 0, 30, 67, 0, 0, 22, 67, 0, 0, 31, 67, 0, 0, 22, 67, 0, 0, 32, 67, 0, 0, 22, 67, 0, 0, 33, 67, 0, 0, 22, 67, 0, 0, 34, 67, 0, 0, 22, 67, 0, 0, 35, 67, 0, 0, 22, 67, 0, 0, 36, 67, 0, 0, 22, 67, 0, 0, 37, 67, 0, 0, 22, 67, 0, 0, 38, 67, 0, 0, 22, 67, 0, 0, 39, 67, 0, 0, 22, 67, 0, 0, 40, 67, 0, 0, 22, 67, 0, 0, 41, 67, 0, 0, 22, 67, 0, 0, 42, 67, 0, 0, 22, 67, 0, 0, 43, 67, 0, 0, 22, 67, 0, 0, 44, 67, 0, 0, 22, 67, 0, 0, 45, 67, 0, 0, 22, 67, 0, 0, 46, 67, 0, 0, 22, 67, 0, 0, 47, 67, 0, 0, 22, 67, 0, 0, 48, 67, 0, 0, 22, 67, 0, 0, 49, 67, 0, 0, 22, 67, 0, 0, 50, 67, 0, 0, 22, 67, 0, 0, 51, 67, 0, 0, 22, 67, 0, 0, 52, 67, 0, 0, 22, 67, 0, 0, 53, 67, 0, 0, 22, 67, 0, 0, 54, 67, 0, 0, 22, 67, 0, 0, 55, 67, 0, 0, 23, 67, 0, 0, 184, 66, 0, 0, 23, 67, 0, 0, 186, 66, 0, 0, 23, 67, 0, 0, 188, 66, 0, 0, 23, 67, 0, 0, 190, 66, 0, 0, 23, 67, 0, 0, 192, 66, 0, 0, 23, 67, 0, 0, 194, 66, 0, 0, 23, 67, 0, 0, 196, 66, 0, 0, 23, 67, 0, 0, 198, 66, 0, 0, 23, 67, 0, 0, 200, 66, 0, 0, 23, 67, 0, 0, 202, 66, 0, 0, 23, 67, 0, 0, 204, 66, 0, 0, 23, 67, 0, 0, 206, 66, 0, 0, 23, 67, 0, 0, 208, 66, 0, 0, 23, 67, 0, 0, 210, 66, 0, 0, 23, 67, 0, 0, 212, 66, 0, 0, 23, 67, 0, 0, 214, 66, 0, 0, 23, 67, 0, 0, 216, 66, 0, 0, 23, 67, 0, 0, 218, 66, 0, 0, 23, 67, 0, 0, 220, 66, 0, 0, 23, 67, 0, 0, 222, 66, 0, 0, 23, 67, 0, 0, 224, 66, 0, 0, 23, 67, 0, 0, 226, 66, 0, 0, 23, 67, 0, 0, 228, 66, 0, 0, 23, 67, 0, 0, 230, 66, 0, 0, 23, 67, 0, 0, 232, 66, 0, 0, 23, 67, 0, 0, 234, 66, 0, 0, 23, 67, 0, 0, 236, 66, 0, 0, 23, 67, 0, 0, 238, 66, 0, 0, 23, 67, 0, 0, 240, 66, 0, 0, 23, 67, 0, 0, 242, 66, 0, 0, 23, 67, 0, 0, 244, 66, 0, 0, 23, 67, 0, 0, 246, 66, 0, 0, 23, 67, 0, 0, 248, 66, 0, 0, 23, 67, 0, 0, 250, 66, 0, 0, 23, 67, 0, 0, 252, 66, 0, 0, 23, 67, 0, 0, 254, 66, 0, 0, 23, 67, 0, 0, 0, 67, 0, 0, 23, 67, 0, 0, 1, 67, 0, 0, 23, 67, 0, 0, 2, 67, 0, 0, 23, 67, 0, 0, 3, 67, 0, 0, 23, 67, 0, 0, 4, 67, 0, 0, 23, 67, 0, 0, 5, 67, 0, 0, 23, 67, 0, 0, 6, 67, 0, 0, 23, 67, 0, 0, 7, 67, 0, 0, 23, 67, 0, 0, 8, 67, 0, 0, 23, 67, 0, 0, 9, 67, 0, 0, 23, 67, 0, 0, 10, 67, 0, 0, 23, 67, 0, 0, 11, 67, 0, 0, 23, 67, 0, 0, 12, 67, 0, 0, 23, 67, 0, 0, 13, 67, 0, 0, 23, 67, 0, 0, 14, 67, 0, 0, 23, 67, 0, 0, 15, 67, 0, 0, 23, 67, 0, 0, 16, 67, 0, 0, 23, 67, 0, 0, 17, 67, 0, 0, 23, 67, 0, 0, 18, 67, 0, 0, 23, 67, 0, 0, 19, 67, 0, 0, 23, 67, 0, 0, 20, 67, 0, 0, 23, 67, 0, 0, 21, 67, 0, 0, 23, 67, 0, 0, 22, 67, 0, 0, 23, 67, 0, 0, 23, 67, 0, 0, 23, 67, 0, 0, 24, 67, 0, 0, 23, 67, 0, 0, 25, 67, 0, 0, 23, 67, 0, 0, 26, 67, 0, 0, 23, 67, 0, 0, 27, 67, 0, 0, 23, 67, 0, 0, 28, 67, 0, 0, 23, 67, 0, 0, 29, 67, 0, 0, 23, 67, 0, 0, 30, 67, 0, 0, 23, 67, 0, 0, 31, 67, 0, 0, 23, 67, 0, 0, 32, 67, 0, 0, 23, 67, 0, 0, 33, 67, 0, 0, 23, 67, 0, 0, 34, 67, 0, 0, 23, 67, 0, 0, 35, 67, 0, 0, 23, 67, 0, 0, 36, 67, 0, 0, 23, 67, 0, 0, 37, 67, 0, 0, 23, 67, 0, 0, 38, 67, 0, 0, 23, 67, 0, 0, 39, 67, 0, 0, 23, 67, 0, 0, 40, 67, 0, 0, 23, 67, 0, 0, 41, 67, 0, 0, 23, 67, 0, 0, 42, 67, 0, 0, 23, 67, 0, 0, 43, 67, 0, 0, 23, 67, 0, 0, 44, 67, 0, 0, 23, 67, 0, 0, 45, 67, 0, 0, 23, 67, 0, 0, 46, 67, 0, 0, 23, 67, 0, 0, 47, 67, 0, 0, 23, 67, 0, 0, 48, 67, 0, 0, 23, 67, 0, 0, 49, 67, 0, 0, 23, 67, 0, 0, 50, 67, 0, 0, 23, 67, 0, 0, 51, 67, 0, 0, 23, 67, 0, 0, 52, 67, 0, 0, 23, 67, 0, 0, 53, 67, 0, 0, 23, 67, 0, 0, 54, 67, 0, 0, 23, 67, 0, 0, 55, 67, 0, 0, 24, 67, 0, 0, 184, 66, 0, 0, 24, 67, 0, 0, 186, 66, 0, 0, 24, 67, 0, 0, 188, 66, 0, 0, 24, 67, 0, 0, 190, 66, 0, 0, 24, 67, 0, 0, 192, 66, 0, 0, 24, 67, 0, 0, 194, 66, 0, 0, 24, 67, 0, 0, 196, 66, 0, 0, 24, 67, 0, 0, 198, 66, 0, 0, 24, 67, 0, 0, 200, 66, 0, 0, 24, 67, 0, 0, 202, 66, 0, 0, 24, 67, 0, 0, 204, 66, 0, 0, 24, 67, 0, 0, 206, 66, 0, 0, 24, 67, 0, 0, 208, 66, 0, 0, 24, 67, 0, 0, 210, 66, 0, 0, 24, 67, 0, 0, 212, 66, 0, 0, 24, 67, 0, 0, 214, 66, 0, 0, 24, 67, 0, 0, 216, 66, 0, 0, 24, 67, 0, 0, 218, 66, 0, 0, 24, 67, 0, 0, 220, 66, 0, 0, 24, 67, 0, 0, 222, 66, 0, 0, 24, 67, 0, 0, 224, 66, 0, 0, 24, 67, 0, 0, 226, 66, 0, 0, 24, 67, 0, 0, 228, 66, 0, 0, 24, 67, 0, 0, 230, 66, 0, 0, 24, 67, 0, 0, 232, 66, 0, 0, 24, 67, 0, 0, 234, 66, 0, 0, 24, 67, 0, 0, 236, 66, 0, 0, 24, 67, 0, 0, 238, 66, 0, 0, 24, 67, 0, 0, 240, 66, 0, 0, 24, 67, 0, 0, 242, 66, 0, 0, 24, 67, 0, 0, 244, 66, 0, 0, 24, 67, 0, 0, 246, 66, 0, 0, 24, 67, 0, 0, 248, 66, 0, 0, 24, 67, 0, 0, 250, 66, 0, 0, 24, 67, 0, 0, 252, 66, 0, 0, 24, 67, 0, 0, 254, 66, 0, 0, 24, 67, 0, 0, 0, 67, 0, 0, 24, 67, 0, 0, 1, 67, 0, 0, 24, 67, 0, 0, 2, 67, 0, 0, 24, 67, 0, 0, 3, 67, 0, 0, 24, 67, 0, 0, 4, 67, 0, 0, 24, 67, 0, 0, 5, 67, 0, 0, 24, 67, 0, 0, 6, 67, 0, 0, 24, 67, 0, 0, 7, 67, 0, 0, 24, 67, 0, 0, 8, 67, 0, 0, 24, 67, 0, 0, 9, 67, 0, 0, 24, 67, 0, 0, 10, 67, 0, 0, 24, 67, 0, 0, 11, 67, 0, 0, 24, 67, 0, 0, 12, 67, 0, 0, 24, 67, 0, 0, 13, 67, 0, 0, 24, 67, 0, 0, 14, 67, 0, 0, 24, 67, 0, 0, 15, 67, 0, 0, 24, 67, 0, 0, 16, 67, 0, 0, 24, 67, 0, 0, 17, 67, 0, 0, 24, 67, 0, 0, 18, 67, 0, 0, 24, 67, 0, 0, 19, 67, 0, 0, 24, 67, 0, 0, 20, 67, 0, 0, 24, 67, 0, 0, 21, 67, 0, 0, 24, 67, 0, 0, 22, 67, 0, 0, 24, 67, 0, 0, 23, 67, 0, 0, 24, 67, 0, 0, 24, 67, 0, 0, 24, 67, 0, 0, 25, 67, 0, 0, 24, 67, 0, 0, 26, 67, 0, 0, 24, 67, 0, 0, 27, 67, 0, 0, 24, 67, 0, 0, 28, 67, 0, 0, 24, 67, 0, 0, 29, 67, 0, 0, 24, 67, 0, 0, 30, 67, 0, 0, 24, 67, 0, 0, 31, 67, 0, 0, 24, 67, 0, 0, 32, 67, 0, 0, 24, 67, 0, 0, 33, 67, 0, 0, 24, 67, 0, 0, 34, 67, 0, 0, 24, 67, 0, 0, 35, 67, 0, 0, 24, 67, 0, 0, 36, 67, 0, 0, 24, 67, 0, 0, 37, 67, 0, 0, 24, 67, 0, 0, 38, 67, 0, 0, 24, 67, 0, 0, 39, 67, 0, 0, 24, 67, 0, 0, 40, 67, 0, 0, 24, 67, 0, 0, 41, 67, 0, 0, 24, 67, 0, 0, 42, 67, 0, 0, 24, 67, 0, 0, 43, 67, 0, 0, 24, 67, 0, 0, 44, 67, 0, 0, 24, 67, 0, 0, 45, 67, 0, 0, 24, 67, 0, 0, 46, 67, 0, 0, 24, 67, 0, 0, 47, 67, 0, 0, 24, 67, 0, 0, 48, 67, 0, 0, 24, 67, 0, 0, 49, 67, 0, 0, 24, 67, 0, 0, 50, 67, 0, 0, 24, 67, 0, 0, 51, 67, 0, 0, 24, 67, 0, 0, 52, 67, 0, 0, 24, 67, 0, 0, 53, 67, 0, 0, 24, 67, 0, 0, 54, 67, 0, 0, 24, 67, 0, 0, 55, 67, 0, 0, 25, 67, 0, 0, 184, 66, 0, 0, 25, 67, 0, 0, 186, 66, 0, 0, 25, 67, 0, 0, 188, 66, 0, 0, 25, 67, 0, 0, 190, 66, 0, 0, 25, 67, 0, 0, 192, 66, 0, 0, 25, 67, 0, 0, 194, 66, 0, 0, 25, 67, 0, 0, 196, 66, 0, 0, 25, 67, 0, 0, 198, 66, 0, 0, 25, 67, 0, 0, 200, 66, 0, 0, 25, 67, 0, 0, 202, 66, 0, 0, 25, 67, 0, 0, 204, 66, 0, 0, 25, 67, 0, 0, 206, 66, 0, 0, 25, 67, 0, 0, 208, 66, 0, 0, 25, 67, 0, 0, 210, 66, 0, 0, 25, 67, 0, 0, 212, 66, 0, 0, 25, 67, 0, 0, 214, 66, 0, 0, 25, 67, 0, 0, 216, 66, 0, 0, 25, 67, 0, 0, 218, 66, 0, 0, 25, 67, 0, 0, 220, 66, 0, 0, 25, 67, 0, 0, 222, 66, 0, 0, 25, 67, 0, 0, 224, 66, 0, 0, 25, 67, 0, 0, 226, 66, 0, 0, 25, 67, 0, 0, 228, 66, 0, 0, 25, 67, 0, 0, 230, 66, 0, 0, 25, 67, 0, 0, 232, 66, 0, 0, 25, 67, 0, 0, 234, 66, 0, 0, 25, 67, 0, 0, 236, 66, 0, 0, 25, 67, 0, 0, 238, 66, 0, 0, 25, 67, 0, 0, 240, 66, 0, 0, 25, 67, 0, 0, 242, 66, 0, 0, 25, 67, 0, 0, 244, 66, 0, 0, 25, 67, 0, 0, 246, 66, 0, 0, 25, 67, 0, 0, 248, 66, 0, 0, 25, 67, 0, 0, 250, 66, 0, 0, 25, 67, 0, 0, 252, 66, 0, 0, 25, 67, 0, 0, 254, 66, 0, 0, 25, 67, 0, 0, 0, 67, 0, 0, 25, 67, 0, 0, 1, 67, 0, 0, 25, 67, 0, 0, 2, 67, 0, 0, 25, 67, 0, 0, 3, 67, 0, 0, 25, 67, 0, 0, 4, 67, 0, 0, 25, 67, 0, 0, 5, 67, 0, 0, 25, 67, 0, 0, 6, 67, 0, 0, 25, 67, 0, 0, 7, 67, 0, 0, 25, 67, 0, 0, 8, 67, 0, 0, 25, 67, 0, 0, 9, 67, 0, 0, 25, 67, 0, 0, 10, 67, 0, 0, 25, 67, 0, 0, 11, 67, 0, 0, 25, 67, 0, 0, 12, 67, 0, 0, 25, 67, 0, 0, 13, 67, 0, 0, 25, 67, 0, 0, 14, 67, 0, 0, 25, 67, 0, 0, 15, 67, 0, 0, 25, 67, 0, 0, 16, 67, 0, 0, 25, 67, 0, 0, 17, 67, 0, 0, 25, 67, 0, 0, 18, 67, 0, 0, 25, 67, 0, 0, 19, 67, 0, 0, 25, 67, 0, 0, 20, 67, 0, 0, 25, 67, 0, 0, 21, 67, 0, 0, 25, 67, 0, 0, 22, 67, 0, 0, 25, 67, 0, 0, 23, 67, 0, 0, 25, 67, 0, 0, 24, 67, 0, 0, 25, 67, 0, 0, 25, 67, 0, 0, 25, 67, 0, 0, 26, 67, 0, 0, 25, 67, 0, 0, 27, 67, 0, 0, 25, 67, 0, 0, 28, 67, 0, 0, 25, 67, 0, 0, 29, 67, 0, 0, 25, 67, 0, 0, 30, 67, 0, 0, 25, 67, 0, 0, 31, 67, 0, 0, 25, 67, 0, 0, 32, 67, 0, 0, 25, 67, 0, 0, 33, 67, 0, 0, 25, 67, 0, 0, 34, 67, 0, 0, 25, 67, 0, 0, 35, 67, 0, 0, 25, 67, 0, 0, 36, 67, 0, 0, 25, 67, 0, 0, 37, 67, 0, 0, 25, 67, 0, 0, 38, 67, 0, 0, 25, 67, 0, 0, 39, 67, 0, 0, 25, 67, 0, 0, 40, 67, 0, 0, 25, 67, 0, 0, 41, 67, 0, 0, 25, 67, 0, 0, 42, 67, 0, 0, 25, 67, 0, 0, 43, 67, 0, 0, 25, 67, 0, 0, 44, 67, 0, 0, 25, 67, 0, 0, 45, 67, 0, 0, 25, 67, 0, 0, 46, 67, 0, 0, 25, 67, 0, 0, 47, 67, 0, 0, 25, 67, 0, 0, 48, 67, 0, 0, 25, 67, 0, 0, 49, 67, 0, 0, 25, 67, 0, 0, 50, 67, 0, 0, 25, 67, 0, 0, 51, 67, 0, 0, 25, 67, 0, 0, 52, 67, 0, 0, 25, 67, 0, 0, 53, 67, 0, 0, 25, 67, 0, 0, 54, 67, 0, 0, 25, 67, 0, 0, 55, 67, 0, 0, 26, 67, 0, 0, 184, 66, 0, 0, 26, 67, 0, 0, 186, 66, 0, 0, 26, 67, 0, 0, 188, 66, 0, 0, 26, 67, 0, 0, 190, 66, 0, 0, 26, 67, 0, 0, 192, 66, 0, 0, 26, 67, 0, 0, 194, 66, 0, 0, 26, 67, 0, 0, 196, 66, 0, 0, 26, 67, 0, 0, 198, 66, 0, 0, 26, 67, 0, 0, 200, 66, 0, 0, 26, 67, 0, 0, 202, 66, 0, 0, 26, 67, 0, 0, 204, 66, 0, 0, 26, 67, 0, 0, 206, 66, 0, 0, 26, 67, 0, 0, 208, 66, 0, 0, 26, 67, 0, 0, 210, 66, 0, 0, 26, 67, 0, 0, 212, 66, 0, 0, 26, 67, 0, 0, 214, 66, 0, 0, 26, 67, 0, 0, 216, 66, 0, 0, 26, 67, 0, 0, 218, 66, 0, 0, 26, 67, 0, 0, 220, 66, 0, 0, 26, 67, 0, 0, 222, 66, 0, 0, 26, 67, 0, 0, 224, 66, 0, 0, 26, 67, 0, 0, 226, 66, 0, 0, 26, 67, 0, 0, 228, 66, 0, 0, 26, 67, 0, 0, 230, 66, 0, 0, 26, 67, 0, 0, 232, 66, 0, 0, 26, 67, 0, 0, 234, 66, 0, 0, 26, 67, 0, 0, 236, 66, 0, 0, 26, 67, 0, 0, 238, 66, 0, 0, 26, 67, 0, 0, 240, 66, 0, 0, 26, 67, 0, 0, 242, 66, 0, 0, 26, 67, 0, 0, 244, 66, 0, 0, 26, 67, 0, 0, 246, 66, 0, 0, 26, 67, 0, 0, 248, 66, 0, 0, 26, 67, 0, 0, 250, 66, 0, 0, 26, 67, 0, 0, 252, 66, 0, 0, 26, 67, 0, 0, 254, 66, 0, 0, 26, 67, 0, 0, 0, 67, 0, 0, 26, 67, 0, 0, 1, 67, 0, 0, 26, 67, 0, 0, 2, 67, 0, 0, 26, 67, 0, 0, 3, 67, 0, 0, 26, 67, 0, 0, 4, 67, 0, 0, 26, 67, 0, 0, 5, 67, 0, 0, 26, 67, 0, 0, 6, 67, 0, 0, 26, 67, 0, 0, 7, 67, 0, 0, 26, 67, 0, 0, 8, 67, 0, 0, 26, 67, 0, 0, 9, 67, 0, 0, 26, 67, 0, 0, 10, 67, 0, 0, 26, 67, 0, 0, 11, 67, 0, 0, 26, 67, 0, 0, 12, 67, 0, 0, 26, 67, 0, 0, 13, 67, 0, 0, 26, 67, 0, 0, 14, 67, 0, 0, 26, 67, 0, 0, 15, 67, 0, 0, 26, 67, 0, 0, 16, 67, 0, 0, 26, 67, 0, 0, 17, 67, 0, 0, 26, 67, 0, 0, 18, 67, 0, 0, 26, 67, 0, 0, 19, 67, 0, 0, 26, 67, 0, 0, 20, 67, 0, 0, 26, 67, 0, 0, 21, 67, 0, 0, 26, 67, 0, 0, 22, 67, 0, 0, 26, 67, 0, 0, 23, 67, 0, 0, 26, 67, 0, 0, 24, 67, 0, 0, 26, 67, 0, 0, 25, 67, 0, 0, 26, 67, 0, 0, 26, 67, 0, 0, 26, 67, 0, 0, 27, 67, 0, 0, 26, 67, 0, 0, 28, 67, 0, 0, 26, 67, 0, 0, 29, 67, 0, 0, 26, 67, 0, 0, 30, 67, 0, 0, 26, 67, 0, 0, 31, 67, 0, 0, 26, 67, 0, 0, 32, 67, 0, 0, 26, 67, 0, 0, 33, 67, 0, 0, 26, 67, 0, 0, 34, 67, 0, 0, 26, 67, 0, 0, 35, 67, 0, 0, 26, 67, 0, 0, 36, 67, 0, 0, 26, 67, 0, 0, 37, 67, 0, 0, 26, 67, 0, 0, 38, 67, 0, 0, 26, 67, 0, 0, 39, 67, 0, 0, 26, 67, 0, 0, 40, 67, 0, 0, 26, 67, 0, 0, 41, 67, 0, 0, 26, 67, 0, 0, 42, 67, 0, 0, 26, 67, 0, 0, 43, 67, 0, 0, 26, 67, 0, 0, 44, 67, 0, 0, 26, 67, 0, 0, 45, 67, 0, 0, 26, 67, 0, 0, 46, 67, 0, 0, 26, 67, 0, 0, 47, 67, 0, 0, 26, 67, 0, 0, 48, 67, 0, 0, 26, 67, 0, 0, 49, 67, 0, 0, 26, 67, 0, 0, 50, 67, 0, 0, 26, 67, 0, 0, 51, 67, 0, 0, 26, 67, 0, 0, 52, 67, 0, 0, 26, 67, 0, 0, 53, 67, 0, 0, 26, 67, 0, 0, 54, 67, 0, 0, 26, 67, 0, 0, 55, 67, 0, 0, 27, 67, 0, 0, 184, 66, 0, 0, 27, 67, 0, 0, 186, 66, 0, 0, 27, 67, 0, 0, 188, 66, 0, 0, 27, 67, 0, 0, 190, 66, 0, 0, 27, 67, 0, 0, 192, 66, 0, 0, 27, 67, 0, 0, 194, 66, 0, 0, 27, 67, 0, 0, 196, 66, 0, 0, 27, 67, 0, 0, 198, 66, 0, 0, 27, 67, 0, 0, 200, 66, 0, 0, 27, 67, 0, 0, 202, 66, 0, 0, 27, 67, 0, 0, 204, 66, 0, 0, 27, 67, 0, 0, 206, 66, 0, 0, 27, 67, 0, 0, 208, 66, 0, 0, 27, 67, 0, 0, 210, 66, 0, 0, 27, 67, 0, 0, 212, 66, 0, 0, 27, 67, 0, 0, 214, 66, 0, 0, 27, 67, 0, 0, 216, 66, 0, 0, 27, 67, 0, 0, 218, 66, 0, 0, 27, 67, 0, 0, 220, 66, 0, 0, 27, 67, 0, 0, 222, 66, 0, 0, 27, 67, 0, 0, 224, 66, 0, 0, 27, 67, 0, 0, 226, 66, 0, 0, 27, 67, 0, 0, 228, 66, 0, 0, 27, 67, 0, 0, 230, 66, 0, 0, 27, 67, 0, 0, 232, 66, 0, 0, 27, 67, 0, 0, 234, 66, 0, 0, 27, 67, 0, 0, 236, 66, 0, 0, 27, 67, 0, 0, 238, 66, 0, 0, 27, 67, 0, 0, 240, 66, 0, 0, 27, 67, 0, 0, 242, 66, 0, 0, 27, 67, 0, 0, 244, 66, 0, 0, 27, 67, 0, 0, 246, 66, 0, 0, 27, 67, 0, 0, 248, 66, 0, 0, 27, 67, 0, 0, 250, 66, 0, 0, 27, 67, 0, 0, 252, 66, 0, 0, 27, 67, 0, 0, 254, 66, 0, 0, 27, 67, 0, 0, 0, 67, 0, 0, 27, 67, 0, 0, 1, 67, 0, 0, 27, 67, 0, 0, 2, 67, 0, 0, 27, 67, 0, 0, 3, 67, 0, 0, 27, 67, 0, 0, 4, 67, 0, 0, 27, 67, 0, 0, 5, 67, 0, 0, 27, 67, 0, 0, 6, 67, 0, 0, 27, 67, 0, 0, 7, 67, 0, 0, 27, 67, 0, 0, 8, 67, 0, 0, 27, 67, 0, 0, 9, 67, 0, 0, 27, 67, 0, 0, 10, 67, 0, 0, 27, 67, 0, 0, 11, 67, 0, 0, 27, 67, 0, 0, 12, 67, 0, 0, 27, 67, 0, 0, 13, 67, 0, 0, 27, 67, 0, 0, 14, 67, 0, 0, 27, 67, 0, 0, 15, 67, 0, 0, 27, 67, 0, 0, 16, 67, 0, 0, 27, 67, 0, 0, 17, 67, 0, 0, 27, 67, 0, 0, 18, 67, 0, 0, 27, 67, 0, 0, 19, 67, 0, 0, 27, 67, 0, 0, 20, 67, 0, 0, 27, 67, 0, 0, 21, 67, 0, 0, 27, 67, 0, 0, 22, 67, 0, 0, 27, 67, 0, 0, 23, 67, 0, 0, 27, 67, 0, 0, 24, 67, 0, 0, 27, 67, 0, 0, 25, 67, 0, 0, 27, 67, 0, 0, 26, 67, 0, 0, 27, 67, 0, 0, 27, 67, 0, 0, 27, 67, 0, 0, 28, 67, 0, 0, 27, 67, 0, 0, 29, 67, 0, 0, 27, 67, 0, 0, 30, 67, 0, 0, 27, 67, 0, 0, 31, 67, 0, 0, 27, 67, 0, 0, 32, 67, 0, 0, 27, 67, 0, 0, 33, 67, 0, 0, 27, 67, 0, 0, 34, 67, 0, 0, 27, 67, 0, 0, 35, 67, 0, 0, 27, 67, 0, 0, 36, 67, 0, 0, 27, 67, 0, 0, 37, 67, 0, 0, 27, 67, 0, 0, 38, 67, 0, 0, 27, 67, 0, 0, 39, 67, 0, 0, 27, 67, 0, 0, 40, 67, 0, 0, 27, 67, 0, 0, 41, 67, 0, 0, 27, 67, 0, 0, 42, 67, 0, 0, 27, 67, 0, 0, 43, 67, 0, 0, 27, 67, 0, 0, 44, 67, 0, 0, 27, 67, 0, 0, 45, 67, 0, 0, 27, 67, 0, 0, 46, 67, 0, 0, 27, 67, 0, 0, 47, 67, 0, 0, 27, 67, 0, 0, 48, 67, 0, 0, 27, 67, 0, 0, 49, 67, 0, 0, 27, 67, 0, 0, 50, 67, 0, 0, 27, 67, 0, 0, 51, 67, 0, 0, 27, 67, 0, 0, 52, 67, 0, 0, 27, 67, 0, 0, 53, 67, 0, 0, 27, 67, 0, 0, 54, 67, 0, 0, 27, 67, 0, 0, 55, 67, 0, 0, 28, 67, 0, 0, 184, 66, 0, 0, 28, 67, 0, 0, 186, 66, 0, 0, 28, 67, 0, 0, 188, 66, 0, 0, 28, 67, 0, 0, 190, 66, 0, 0, 28, 67, 0, 0, 192, 66, 0, 0, 28, 67, 0, 0, 194, 66, 0, 0, 28, 67, 0, 0, 196, 66, 0, 0, 28, 67, 0, 0, 198, 66, 0, 0, 28, 67, 0, 0, 200, 66, 0, 0, 28, 67, 0, 0, 202, 66, 0, 0, 28, 67, 0, 0, 204, 66, 0, 0, 28, 67, 0, 0, 206, 66, 0, 0, 28, 67, 0, 0, 208, 66, 0, 0, 28, 67, 0, 0, 210, 66, 0, 0, 28, 67, 0, 0, 212, 66, 0, 0, 28, 67, 0, 0, 214, 66, 0, 0, 28, 67, 0, 0, 216, 66, 0, 0, 28, 67, 0, 0, 218, 66, 0, 0, 28, 67, 0, 0, 220, 66, 0, 0, 28, 67, 0, 0, 222, 66, 0, 0, 28, 67, 0, 0, 224, 66, 0, 0, 28, 67, 0, 0, 226, 66, 0, 0, 28, 67, 0, 0, 228, 66, 0, 0, 28, 67, 0, 0, 230, 66, 0, 0, 28, 67, 0, 0, 232, 66, 0, 0, 28, 67, 0, 0, 234, 66, 0, 0, 28, 67, 0, 0, 236, 66, 0, 0, 28, 67, 0, 0, 238, 66, 0, 0, 28, 67, 0, 0, 240, 66, 0, 0, 28, 67, 0, 0, 242, 66, 0, 0, 28, 67, 0, 0, 244, 66, 0, 0, 28, 67, 0, 0, 246, 66, 0, 0, 28, 67, 0, 0, 248, 66, 0, 0, 28, 67, 0, 0, 250, 66, 0, 0, 28, 67, 0, 0, 252, 66, 0, 0, 28, 67, 0, 0, 254, 66, 0, 0, 28, 67, 0, 0, 0, 67, 0, 0, 28, 67, 0, 0, 1, 67, 0, 0, 28, 67, 0, 0, 2, 67, 0, 0, 28, 67, 0, 0, 3, 67, 0, 0, 28, 67, 0, 0, 4, 67, 0, 0, 28, 67, 0, 0, 5, 67, 0, 0, 28, 67, 0, 0, 6, 67, 0, 0, 28, 67, 0, 0, 7, 67, 0, 0, 28, 67, 0, 0, 8, 67, 0, 0, 28, 67, 0, 0, 9, 67, 0, 0, 28, 67, 0, 0, 10, 67, 0, 0, 28, 67, 0, 0, 11, 67, 0, 0, 28, 67, 0, 0, 12, 67, 0, 0, 28, 67, 0, 0, 13, 67, 0, 0, 28, 67, 0, 0, 14, 67, 0, 0, 28, 67, 0, 0, 15, 67, 0, 0, 28, 67, 0, 0, 16, 67, 0, 0, 28, 67, 0, 0, 17, 67, 0, 0, 28, 67, 0, 0, 18, 67, 0, 0, 28, 67, 0, 0, 19, 67, 0, 0, 28, 67, 0, 0, 20, 67, 0, 0, 28, 67, 0, 0, 21, 67, 0, 0, 28, 67, 0, 0, 22, 67, 0, 0, 28, 67, 0, 0, 23, 67, 0, 0, 28, 67, 0, 0, 24, 67, 0, 0, 28, 67, 0, 0, 25, 67, 0, 0, 28, 67, 0, 0, 26, 67, 0, 0, 28, 67, 0, 0, 27, 67, 0, 0, 28, 67, 0, 0, 28, 67, 0, 0, 28, 67, 0, 0, 29, 67, 0, 0, 28, 67, 0, 0, 30, 67, 0, 0, 28, 67, 0, 0, 31, 67, 0, 0, 28, 67, 0, 0, 32, 67, 0, 0, 28, 67, 0, 0, 33, 67, 0, 0, 28, 67, 0, 0, 34, 67, 0, 0, 28, 67, 0, 0, 35, 67, 0, 0, 28, 67, 0, 0, 36, 67, 0, 0, 28, 67, 0, 0, 37, 67, 0, 0, 28, 67, 0, 0, 38, 67, 0, 0, 28, 67, 0, 0, 39, 67, 0, 0, 28, 67, 0, 0, 40, 67, 0, 0, 28, 67, 0, 0, 41, 67, 0, 0, 28, 67, 0, 0, 42, 67, 0, 0, 28, 67, 0, 0, 43, 67, 0, 0, 28, 67, 0, 0, 44, 67, 0, 0, 28, 67, 0, 0, 45, 67, 0, 0, 28, 67, 0, 0, 46, 67, 0, 0, 28, 67, 0, 0, 47, 67, 0, 0, 28, 67, 0, 0, 48, 67, 0, 0, 28, 67, 0, 0, 49, 67, 0, 0, 28, 67, 0, 0, 50, 67, 0, 0, 28, 67, 0, 0, 51, 67, 0, 0, 28, 67, 0, 0, 52, 67, 0, 0, 28, 67, 0, 0, 53, 67, 0, 0, 28, 67, 0, 0, 54, 67, 0, 0, 28, 67, 0, 0, 55, 67, 0, 0, 29, 67, 0, 0, 184, 66, 0, 0, 29, 67, 0, 0, 186, 66, 0, 0, 29, 67, 0, 0, 188, 66, 0, 0, 29, 67, 0, 0, 190, 66, 0, 0, 29, 67, 0, 0, 192, 66, 0, 0, 29, 67, 0, 0, 194, 66, 0, 0, 29, 67, 0, 0, 196, 66, 0, 0, 29, 67, 0, 0, 198, 66, 0, 0, 29, 67, 0, 0, 200, 66, 0, 0, 29, 67, 0, 0, 202, 66, 0, 0, 29, 67, 0, 0, 204, 66, 0, 0, 29, 67, 0, 0, 206, 66, 0, 0, 29, 67, 0, 0, 208, 66, 0, 0, 29, 67, 0, 0, 210, 66, 0, 0, 29, 67, 0, 0, 212, 66, 0, 0, 29, 67, 0, 0, 214, 66, 0, 0, 29, 67, 0, 0, 216, 66, 0, 0, 29, 67, 0, 0, 218, 66, 0, 0, 29, 67, 0, 0, 220, 66, 0, 0, 29, 67, 0, 0, 222, 66, 0, 0, 29, 67, 0, 0, 224, 66, 0, 0, 29, 67, 0, 0, 226, 66, 0, 0, 29, 67, 0, 0, 228, 66, 0, 0, 29, 67, 0, 0, 230, 66, 0, 0, 29, 67, 0, 0, 232, 66, 0, 0, 29, 67, 0, 0, 234, 66, 0, 0, 29, 67, 0, 0, 236, 66, 0, 0, 29, 67, 0, 0, 238, 66, 0, 0, 29, 67, 0, 0, 240, 66, 0, 0, 29, 67, 0, 0, 242, 66, 0, 0, 29, 67, 0, 0, 244, 66, 0, 0, 29, 67, 0, 0, 246, 66, 0, 0, 29, 67, 0, 0, 248, 66, 0, 0, 29, 67, 0, 0, 250, 66, 0, 0, 29, 67, 0, 0, 252, 66, 0, 0, 29, 67, 0, 0, 254, 66, 0, 0, 29, 67, 0, 0, 0, 67, 0, 0, 29, 67, 0, 0, 1, 67, 0, 0, 29, 67, 0, 0, 2, 67, 0, 0, 29, 67, 0, 0, 3, 67, 0, 0, 29, 67, 0, 0, 4, 67, 0, 0, 29, 67, 0, 0, 5, 67, 0, 0, 29, 67, 0, 0, 6, 67, 0, 0, 29, 67, 0, 0, 7, 67, 0, 0, 29, 67, 0, 0, 8, 67, 0, 0, 29, 67, 0, 0, 9, 67, 0, 0, 29, 67, 0, 0, 10, 67, 0, 0, 29, 67, 0, 0, 11, 67, 0, 0, 29, 67, 0, 0, 12, 67, 0, 0, 29, 67, 0, 0, 13, 67, 0, 0, 29, 67, 0, 0, 14, 67, 0, 0, 29, 67, 0, 0, 15, 67, 0, 0, 29, 67, 0, 0, 16, 67, 0, 0, 29, 67, 0, 0, 17, 67, 0, 0, 29, 67, 0, 0, 18, 67, 0, 0, 29, 67, 0, 0, 19, 67, 0, 0, 29, 67, 0, 0, 20, 67, 0, 0, 29, 67, 0, 0, 21, 67, 0, 0, 29, 67, 0, 0, 22, 67, 0, 0, 29, 67, 0, 0, 23, 67, 0, 0, 29, 67, 0, 0, 24, 67, 0, 0, 29, 67, 0, 0, 25, 67, 0, 0, 29, 67, 0, 0, 26, 67, 0, 0, 29, 67, 0, 0, 27, 67, 0, 0, 29, 67, 0, 0, 28, 67, 0, 0, 29, 67, 0, 0, 29, 67, 0, 0, 29, 67, 0, 0, 30, 67, 0, 0, 29, 67, 0, 0, 31, 67, 0, 0, 29, 67, 0, 0, 32, 67, 0, 0, 29, 67, 0, 0, 33, 67, 0, 0, 29, 67, 0, 0, 34, 67, 0, 0, 29, 67, 0, 0, 35, 67, 0, 0, 29, 67, 0, 0, 36, 67, 0, 0, 29, 67, 0, 0, 37, 67, 0, 0, 29, 67, 0, 0, 38, 67, 0, 0, 29, 67, 0, 0, 39, 67, 0, 0, 29, 67, 0, 0, 40, 67, 0, 0, 29, 67, 0, 0, 41, 67, 0, 0, 29, 67, 0, 0, 42, 67, 0, 0, 29, 67, 0, 0, 43, 67, 0, 0, 29, 67, 0, 0, 44, 67, 0, 0, 29, 67, 0, 0, 45, 67, 0, 0, 29, 67, 0, 0, 46, 67, 0, 0, 29, 67, 0, 0, 47, 67, 0, 0, 29, 67, 0, 0, 48, 67, 0, 0, 29, 67, 0, 0, 49, 67, 0, 0, 29, 67, 0, 0, 50, 67, 0, 0, 29, 67, 0, 0, 51, 67, 0, 0, 29, 67, 0, 0, 52, 67, 0, 0, 29, 67, 0, 0, 53, 67, 0, 0, 29, 67, 0, 0, 54, 67, 0, 0, 29, 67, 0, 0, 55, 67, 0, 0, 30, 67, 0, 0, 184, 66, 0, 0, 30, 67, 0, 0, 186, 66, 0, 0, 30, 67, 0, 0, 188, 66, 0, 0, 30, 67, 0, 0, 190, 66, 0, 0, 30, 67, 0, 0, 192, 66, 0, 0, 30, 67, 0, 0, 194, 66, 0, 0, 30, 67, 0, 0, 196, 66, 0, 0, 30, 67, 0, 0, 198, 66, 0, 0, 30, 67, 0, 0, 200, 66, 0, 0, 30, 67, 0, 0, 202, 66, 0, 0, 30, 67, 0, 0, 204, 66, 0, 0, 30, 67, 0, 0, 206, 66, 0, 0, 30, 67, 0, 0, 208, 66, 0, 0, 30, 67, 0, 0, 210, 66, 0, 0, 30, 67, 0, 0, 212, 66, 0, 0, 30, 67, 0, 0, 214, 66, 0, 0, 30, 67, 0, 0, 216, 66, 0, 0, 30, 67, 0, 0, 218, 66, 0, 0, 30, 67, 0, 0, 220, 66, 0, 0, 30, 67, 0, 0, 222, 66, 0, 0, 30, 67, 0, 0, 224, 66, 0, 0, 30, 67, 0, 0, 226, 66, 0, 0, 30, 67, 0, 0, 228, 66, 0, 0, 30, 67, 0, 0, 230, 66, 0, 0, 30, 67, 0, 0, 232, 66, 0, 0, 30, 67, 0, 0, 234, 66, 0, 0, 30, 67, 0, 0, 236, 66, 0, 0, 30, 67, 0, 0, 238, 66, 0, 0, 30, 67, 0, 0, 240, 66, 0, 0, 30, 67, 0, 0, 242, 66, 0, 0, 30, 67, 0, 0, 244, 66, 0, 0, 30, 67, 0, 0, 246, 66, 0, 0, 30, 67, 0, 0, 248, 66, 0, 0, 30, 67, 0, 0, 250, 66, 0, 0, 30, 67, 0, 0, 252, 66, 0, 0, 30, 67, 0, 0, 254, 66, 0, 0, 30, 67, 0, 0, 0, 67, 0, 0, 30, 67, 0, 0, 1, 67, 0, 0, 30, 67, 0, 0, 2, 67, 0, 0, 30, 67, 0, 0, 3, 67, 0, 0, 30, 67, 0, 0, 4, 67, 0, 0, 30, 67, 0, 0, 5, 67, 0, 0, 30, 67, 0, 0, 6, 67, 0, 0, 30, 67, 0, 0, 7, 67, 0, 0, 30, 67, 0, 0, 8, 67, 0, 0, 30, 67, 0, 0, 9, 67, 0, 0, 30, 67, 0, 0, 10, 67, 0, 0, 30, 67, 0, 0, 11, 67, 0, 0, 30, 67, 0, 0, 12, 67, 0, 0, 30, 67, 0, 0, 13, 67, 0, 0, 30, 67, 0, 0, 14, 67, 0, 0, 30, 67, 0, 0, 15, 67, 0, 0, 30, 67, 0, 0, 16, 67, 0, 0, 30, 67, 0, 0, 17, 67, 0, 0, 30, 67, 0, 0, 18, 67, 0, 0, 30, 67, 0, 0, 19, 67, 0, 0, 30, 67, 0, 0, 20, 67, 0, 0, 30, 67, 0, 0, 21, 67, 0, 0, 30, 67, 0, 0, 22, 67, 0, 0, 30, 67, 0, 0, 23, 67, 0, 0, 30, 67, 0, 0, 24, 67, 0, 0, 30, 67, 0, 0, 25, 67, 0, 0, 30, 67, 0, 0, 26, 67, 0, 0, 30, 67, 0, 0, 27, 67, 0, 0, 30, 67, 0, 0, 28, 67, 0, 0, 30, 67, 0, 0, 29, 67, 0, 0, 30, 67, 0, 0, 30, 67, 0, 0, 30, 67, 0, 0, 31, 67, 0, 0, 30, 67, 0, 0, 32, 67, 0, 0, 30, 67, 0, 0, 33, 67, 0, 0, 30, 67, 0, 0, 34, 67, 0, 0, 30, 67, 0, 0, 35, 67, 0, 0, 30, 67, 0, 0, 36, 67, 0, 0, 30, 67, 0, 0, 37, 67, 0, 0, 30, 67, 0, 0, 38, 67, 0, 0, 30, 67, 0, 0, 39, 67, 0, 0, 30, 67, 0, 0, 40, 67, 0, 0, 30, 67, 0, 0, 41, 67, 0, 0, 30, 67, 0, 0, 42, 67, 0, 0, 30, 67, 0, 0, 43, 67, 0, 0, 30, 67, 0, 0, 44, 67, 0, 0, 30, 67, 0, 0, 45, 67, 0, 0, 30, 67, 0, 0, 46, 67, 0, 0, 30, 67, 0, 0, 47, 67, 0, 0, 30, 67, 0, 0, 48, 67, 0, 0, 30, 67, 0, 0, 49, 67, 0, 0, 30, 67, 0, 0, 50, 67, 0, 0, 30, 67, 0, 0, 51, 67, 0, 0, 30, 67, 0, 0, 52, 67, 0, 0, 30, 67, 0, 0, 53, 67, 0, 0, 30, 67, 0, 0, 54, 67, 0, 0, 30, 67, 0, 0, 55, 67, 0, 0, 31, 67, 0, 0, 184, 66, 0, 0, 31, 67, 0, 0, 186, 66, 0, 0, 31, 67, 0, 0, 188, 66, 0, 0, 31, 67, 0, 0, 190, 66, 0, 0, 31, 67, 0, 0, 192, 66, 0, 0, 31, 67, 0, 0, 194, 66, 0, 0, 31, 67, 0, 0, 196, 66, 0, 0, 31, 67, 0, 0, 198, 66, 0, 0, 31, 67, 0, 0, 200, 66, 0, 0, 31, 67, 0, 0, 202, 66, 0, 0, 31, 67, 0, 0, 204, 66, 0, 0, 31, 67, 0, 0, 206, 66, 0, 0, 31, 67, 0, 0, 208, 66, 0, 0, 31, 67, 0, 0, 210, 66, 0, 0, 31, 67, 0, 0, 212, 66, 0, 0, 31, 67, 0, 0, 214, 66, 0, 0, 31, 67, 0, 0, 216, 66, 0, 0, 31, 67, 0, 0, 218, 66, 0, 0, 31, 67, 0, 0, 220, 66, 0, 0, 31, 67, 0, 0, 222, 66, 0, 0, 31, 67, 0, 0, 224, 66, 0, 0, 31, 67, 0, 0, 226, 66, 0, 0, 31, 67, 0, 0, 228, 66, 0, 0, 31, 67, 0, 0, 230, 66, 0, 0, 31, 67, 0, 0, 232, 66, 0, 0, 31, 67, 0, 0, 234, 66, 0, 0, 31, 67, 0, 0, 236, 66, 0, 0, 31, 67, 0, 0, 238, 66, 0, 0, 31, 67, 0, 0, 240, 66, 0, 0, 31, 67, 0, 0, 242, 66, 0, 0, 31, 67, 0, 0, 244, 66, 0, 0, 31, 67, 0, 0, 246, 66, 0, 0, 31, 67, 0, 0, 248, 66, 0, 0, 31, 67, 0, 0, 250, 66, 0, 0, 31, 67, 0, 0, 252, 66, 0, 0, 31, 67, 0, 0, 254, 66, 0, 0, 31, 67, 0, 0, 0, 67, 0, 0, 31, 67, 0, 0, 1, 67, 0, 0, 31, 67, 0, 0, 2, 67, 0, 0, 31, 67, 0, 0, 3, 67, 0, 0, 31, 67, 0, 0, 4, 67, 0, 0, 31, 67, 0, 0, 5, 67, 0, 0, 31, 67, 0, 0, 6, 67, 0, 0, 31, 67, 0, 0, 7, 67, 0, 0, 31, 67, 0, 0, 8, 67, 0, 0, 31, 67, 0, 0, 9, 67, 0, 0, 31, 67, 0, 0, 10, 67, 0, 0, 31, 67, 0, 0, 11, 67, 0, 0, 31, 67, 0, 0, 12, 67, 0, 0, 31, 67, 0, 0, 13, 67, 0, 0, 31, 67, 0, 0, 14, 67, 0, 0, 31, 67, 0, 0, 15, 67, 0, 0, 31, 67, 0, 0, 16, 67, 0, 0, 31, 67, 0, 0, 17, 67, 0, 0, 31, 67, 0, 0, 18, 67, 0, 0, 31, 67, 0, 0, 19, 67, 0, 0, 31, 67, 0, 0, 20, 67, 0, 0, 31, 67, 0, 0, 21, 67, 0, 0, 31, 67, 0, 0, 22, 67, 0, 0, 31, 67, 0, 0, 23, 67, 0, 0, 31, 67, 0, 0, 24, 67, 0, 0, 31, 67, 0, 0, 25, 67, 0, 0, 31, 67, 0, 0, 26, 67, 0, 0, 31, 67, 0, 0, 27, 67, 0, 0, 31, 67, 0, 0, 28, 67, 0, 0, 31, 67, 0, 0, 29, 67, 0, 0, 31, 67, 0, 0, 30, 67, 0, 0, 31, 67, 0, 0, 31, 67, 0, 0, 31, 67, 0, 0, 32, 67, 0, 0, 31, 67, 0, 0, 33, 67, 0, 0, 31, 67, 0, 0, 34, 67, 0, 0, 31, 67, 0, 0, 35, 67, 0, 0, 31, 67, 0, 0, 36, 67, 0, 0, 31, 67, 0, 0, 37, 67, 0, 0, 31, 67, 0, 0, 38, 67, 0, 0, 31, 67, 0, 0, 39, 67, 0, 0, 31, 67, 0, 0, 40, 67, 0, 0, 31, 67, 0, 0, 41, 67, 0, 0, 31, 67, 0, 0, 42, 67, 0, 0, 31, 67, 0, 0, 43, 67, 0, 0, 31, 67, 0, 0, 44, 67, 0, 0, 31, 67, 0, 0, 45, 67, 0, 0, 31, 67, 0, 0, 46, 67, 0, 0, 31, 67, 0, 0, 47, 67, 0, 0, 31, 67, 0, 0, 48, 67, 0, 0, 31, 67, 0, 0, 49, 67, 0, 0, 31, 67, 0, 0, 50, 67, 0, 0, 31, 67, 0, 0, 51, 67, 0, 0, 31, 67, 0, 0, 52, 67, 0, 0, 31, 67, 0, 0, 53, 67, 0, 0, 31, 67, 0, 0, 54, 67, 0, 0, 31, 67, 0, 0, 55, 67, 0, 0, 32, 67, 0, 0, 184, 66, 0, 0, 32, 67, 0, 0, 186, 66, 0, 0, 32, 67, 0, 0, 188, 66, 0, 0, 32, 67, 0, 0, 190, 66, 0, 0, 32, 67, 0, 0, 192, 66, 0, 0, 32, 67, 0, 0, 194, 66, 0, 0, 32, 67, 0, 0, 196, 66, 0, 0, 32, 67, 0, 0, 198, 66, 0, 0, 32, 67, 0, 0, 200, 66, 0, 0, 32, 67, 0, 0, 202, 66, 0, 0, 32, 67, 0, 0, 204, 66, 0, 0, 32, 67, 0, 0, 206, 66, 0, 0, 32, 67, 0, 0, 208, 66, 0, 0, 32, 67, 0, 0, 210, 66, 0, 0, 32, 67, 0, 0, 212, 66, 0, 0, 32, 67, 0, 0, 214, 66, 0, 0, 32, 67, 0, 0, 216, 66, 0, 0, 32, 67, 0, 0, 218, 66, 0, 0, 32, 67, 0, 0, 220, 66, 0, 0, 32, 67, 0, 0, 222, 66, 0, 0, 32, 67, 0, 0, 224, 66, 0, 0, 32, 67, 0, 0, 226, 66, 0, 0, 32, 67, 0, 0, 228, 66, 0, 0, 32, 67, 0, 0, 230, 66, 0, 0, 32, 67, 0, 0, 232, 66, 0, 0, 32, 67, 0, 0, 234, 66, 0, 0, 32, 67, 0, 0, 236, 66, 0, 0, 32, 67, 0, 0, 238, 66, 0, 0, 32, 67, 0, 0, 240, 66, 0, 0, 32, 67, 0, 0, 242, 66, 0, 0, 32, 67, 0, 0, 244, 66, 0, 0, 32, 67, 0, 0, 246, 66, 0, 0, 32, 67, 0, 0, 248, 66, 0, 0, 32, 67, 0, 0, 250, 66, 0, 0, 32, 67, 0, 0, 252, 66, 0, 0, 32, 67, 0, 0, 254, 66, 0, 0, 32, 67, 0, 0, 0, 67, 0, 0, 32, 67, 0, 0, 1, 67, 0, 0, 32, 67, 0, 0, 2, 67, 0, 0, 32, 67, 0, 0, 3, 67, 0, 0, 32, 67, 0, 0, 4, 67, 0, 0, 32, 67, 0, 0, 5, 67, 0, 0, 32, 67, 0, 0, 6, 67, 0, 0, 32, 67, 0, 0, 7, 67, 0, 0, 32, 67, 0, 0, 8, 67, 0, 0, 32, 67, 0, 0, 9, 67, 0, 0, 32, 67, 0, 0, 10, 67, 0, 0, 32, 67, 0, 0, 11, 67, 0, 0, 32, 67, 0, 0, 12, 67, 0, 0, 32, 67, 0, 0, 13, 67, 0, 0, 32, 67, 0, 0, 14, 67, 0, 0, 32, 67, 0, 0, 15, 67, 0, 0, 32, 67, 0, 0, 16, 67, 0, 0, 32, 67, 0, 0, 17, 67, 0, 0, 32, 67, 0, 0, 18, 67, 0, 0, 32, 67, 0, 0, 19, 67, 0, 0, 32, 67, 0, 0, 20, 67, 0, 0, 32, 67, 0, 0, 21, 67, 0, 0, 32, 67, 0, 0, 22, 67, 0, 0, 32, 67, 0, 0, 23, 67, 0, 0, 32, 67, 0, 0, 24, 67, 0, 0, 32, 67, 0, 0, 25, 67, 0, 0, 32, 67, 0, 0, 26, 67, 0, 0, 32, 67, 0, 0, 27, 67, 0, 0, 32, 67, 0, 0, 28, 67, 0, 0, 32, 67, 0, 0, 29, 67, 0, 0, 32, 67, 0, 0, 30, 67, 0, 0, 32, 67, 0, 0, 31, 67, 0, 0, 32, 67, 0, 0, 32, 67, 0, 0, 32, 67, 0, 0, 33, 67, 0, 0, 32, 67, 0, 0, 34, 67, 0, 0, 32, 67, 0, 0, 35, 67, 0, 0, 32, 67, 0, 0, 36, 67, 0, 0, 32, 67, 0, 0, 37, 67, 0, 0, 32, 67, 0, 0, 38, 67, 0, 0, 32, 67, 0, 0, 39, 67, 0, 0, 32, 67, 0, 0, 40, 67, 0, 0, 32, 67, 0, 0, 41, 67, 0, 0, 32, 67, 0, 0, 42, 67, 0, 0, 32, 67, 0, 0, 43, 67, 0, 0, 32, 67, 0, 0, 44, 67, 0, 0, 32, 67, 0, 0, 45, 67, 0, 0, 32, 67, 0, 0, 46, 67, 0, 0, 32, 67, 0, 0, 47, 67, 0, 0, 32, 67, 0, 0, 48, 67, 0, 0, 32, 67, 0, 0, 49, 67, 0, 0, 32, 67, 0, 0, 50, 67, 0, 0, 32, 67, 0, 0, 51, 67, 0, 0, 32, 67, 0, 0, 52, 67, 0, 0, 32, 67, 0, 0, 53, 67, 0, 0, 32, 67, 0, 0, 54, 67, 0, 0, 32, 67, 0, 0, 55, 67, 0, 0, 33, 67, 0, 0, 184, 66, 0, 0, 33, 67, 0, 0, 186, 66, 0, 0, 33, 67, 0, 0, 188, 66, 0, 0, 33, 67, 0, 0, 190, 66, 0, 0, 33, 67, 0, 0, 192, 66, 0, 0, 33, 67, 0, 0, 194, 66, 0, 0, 33, 67, 0, 0, 196, 66, 0, 0, 33, 67, 0, 0, 198, 66, 0, 0, 33, 67, 0, 0, 200, 66, 0, 0, 33, 67, 0, 0, 202, 66, 0, 0, 33, 67, 0, 0, 204, 66, 0, 0, 33, 67, 0, 0, 206, 66, 0, 0, 33, 67, 0, 0, 208, 66, 0, 0, 33, 67, 0, 0, 210, 66, 0, 0, 33, 67, 0, 0, 212, 66, 0, 0, 33, 67, 0, 0, 214, 66, 0, 0, 33, 67, 0, 0, 216, 66, 0, 0, 33, 67, 0, 0, 218, 66, 0, 0, 33, 67, 0, 0, 220, 66, 0, 0, 33, 67, 0, 0, 222, 66, 0, 0, 33, 67, 0, 0, 224, 66, 0, 0, 33, 67, 0, 0, 226, 66, 0, 0, 33, 67, 0, 0, 228, 66, 0, 0, 33, 67, 0, 0, 230, 66, 0, 0, 33, 67, 0, 0, 232, 66, 0, 0, 33, 67, 0, 0, 234, 66, 0, 0, 33, 67, 0, 0, 236, 66, 0, 0, 33, 67, 0, 0, 238, 66, 0, 0, 33, 67, 0, 0, 240, 66, 0, 0, 33, 67, 0, 0, 242, 66, 0, 0, 33, 67, 0, 0, 244, 66, 0, 0, 33, 67, 0, 0, 246, 66, 0, 0, 33, 67, 0, 0, 248, 66, 0, 0, 33, 67, 0, 0, 250, 66, 0, 0, 33, 67, 0, 0, 252, 66, 0, 0, 33, 67, 0, 0, 254, 66, 0, 0, 33, 67, 0, 0, 0, 67, 0, 0, 33, 67, 0, 0, 1, 67, 0, 0, 33, 67, 0, 0, 2, 67, 0, 0, 33, 67, 0, 0, 3, 67, 0, 0, 33, 67, 0, 0, 4, 67, 0, 0, 33, 67, 0, 0, 5, 67, 0, 0, 33, 67, 0, 0, 6, 67, 0, 0, 33, 67, 0, 0, 7, 67, 0, 0, 33, 67, 0, 0, 8, 67, 0, 0, 33, 67, 0, 0, 9, 67, 0, 0, 33, 67, 0, 0, 10, 67, 0, 0, 33, 67, 0, 0, 11, 67, 0, 0, 33, 67, 0, 0, 12, 67, 0, 0, 33, 67, 0, 0, 13, 67, 0, 0, 33, 67, 0, 0, 14, 67, 0, 0, 33, 67, 0, 0, 15, 67, 0, 0, 33, 67, 0, 0, 16, 67, 0, 0, 33, 67, 0, 0, 17, 67, 0, 0, 33, 67, 0, 0, 18, 67, 0, 0, 33, 67, 0, 0, 19, 67, 0, 0, 33, 67, 0, 0, 20, 67, 0, 0, 33, 67, 0, 0, 21, 67, 0, 0, 33, 67, 0, 0, 22, 67, 0, 0, 33, 67, 0, 0, 23, 67, 0, 0, 33, 67, 0, 0, 24, 67, 0, 0, 33, 67, 0, 0, 25, 67, 0, 0, 33, 67, 0, 0, 26, 67, 0, 0, 33, 67, 0, 0, 27, 67, 0, 0, 33, 67, 0, 0, 28, 67, 0, 0, 33, 67, 0, 0, 29, 67, 0, 0, 33, 67, 0, 0, 30, 67, 0, 0, 33, 67, 0, 0, 31, 67, 0, 0, 33, 67, 0, 0, 32, 67, 0, 0, 33, 67, 0, 0, 33, 67, 0, 0, 33, 67, 0, 0, 34, 67, 0, 0, 33, 67, 0, 0, 35, 67, 0, 0, 33, 67, 0, 0, 36, 67, 0, 0, 33, 67, 0, 0, 37, 67, 0, 0, 33, 67, 0, 0, 38, 67, 0, 0, 33, 67, 0, 0, 39, 67, 0, 0, 33, 67, 0, 0, 40, 67, 0, 0, 33, 67, 0, 0, 41, 67, 0, 0, 33, 67, 0, 0, 42, 67, 0, 0, 33, 67, 0, 0, 43, 67, 0, 0, 33, 67, 0, 0, 44, 67, 0, 0, 33, 67, 0, 0, 45, 67, 0, 0, 33, 67, 0, 0, 46, 67, 0, 0, 33, 67, 0, 0, 47, 67, 0, 0, 33, 67, 0, 0, 48, 67, 0, 0, 33, 67, 0, 0, 49, 67, 0, 0, 33, 67, 0, 0, 50, 67, 0, 0, 33, 67, 0, 0, 51, 67, 0, 0, 33, 67, 0, 0, 52, 67, 0, 0, 33, 67, 0, 0, 53, 67, 0, 0, 33, 67, 0, 0, 54, 67, 0, 0, 33, 67, 0, 0, 55, 67, 0, 0, 34, 67, 0, 0, 184, 66, 0, 0, 34, 67, 0, 0, 186, 66, 0, 0, 34, 67, 0, 0, 188, 66, 0, 0, 34, 67, 0, 0, 190, 66, 0, 0, 34, 67, 0, 0, 192, 66, 0, 0, 34, 67, 0, 0, 194, 66, 0, 0, 34, 67, 0, 0, 196, 66, 0, 0, 34, 67, 0, 0, 198, 66, 0, 0, 34, 67, 0, 0, 200, 66, 0, 0, 34, 67, 0, 0, 202, 66, 0, 0, 34, 67, 0, 0, 204, 66, 0, 0, 34, 67, 0, 0, 206, 66, 0, 0, 34, 67, 0, 0, 208, 66, 0, 0, 34, 67, 0, 0, 210, 66, 0, 0, 34, 67, 0, 0, 212, 66, 0, 0, 34, 67, 0, 0, 214, 66, 0, 0, 34, 67, 0, 0, 216, 66, 0, 0, 34, 67, 0, 0, 218, 66, 0, 0, 34, 67, 0, 0, 220, 66, 0, 0, 34, 67, 0, 0, 222, 66, 0, 0, 34, 67, 0, 0, 224, 66, 0, 0, 34, 67, 0, 0, 226, 66, 0, 0, 34, 67, 0, 0, 228, 66, 0, 0, 34, 67, 0, 0, 230, 66, 0, 0, 34, 67, 0, 0, 232, 66, 0, 0, 34, 67, 0, 0, 234, 66, 0, 0, 34, 67, 0, 0, 236, 66, 0, 0, 34, 67, 0, 0, 238, 66, 0, 0, 34, 67, 0, 0, 240, 66, 0, 0, 34, 67, 0, 0, 242, 66, 0, 0, 34, 67, 0, 0, 244, 66, 0, 0, 34, 67, 0, 0, 246, 66, 0, 0, 34, 67, 0, 0, 248, 66, 0, 0, 34, 67, 0, 0, 250, 66, 0, 0, 34, 67, 0, 0, 252, 66, 0, 0, 34, 67, 0, 0, 254, 66, 0, 0, 34, 67, 0, 0, 0, 67, 0, 0, 34, 67, 0, 0, 1, 67, 0, 0, 34, 67, 0, 0, 2, 67, 0, 0, 34, 67, 0, 0, 3, 67, 0, 0, 34, 67, 0, 0, 4, 67, 0, 0, 34, 67, 0, 0, 5, 67, 0, 0, 34, 67, 0, 0, 6, 67, 0, 0, 34, 67, 0, 0, 7, 67, 0, 0, 34, 67, 0, 0, 8, 67, 0, 0, 34, 67, 0, 0, 9, 67, 0, 0, 34, 67, 0, 0, 10, 67, 0, 0, 34, 67, 0, 0, 11, 67, 0, 0, 34, 67, 0, 0, 12, 67, 0, 0, 34, 67, 0, 0, 13, 67, 0, 0, 34, 67, 0, 0, 14, 67, 0, 0, 34, 67, 0, 0, 15, 67, 0, 0, 34, 67, 0, 0, 16, 67, 0, 0, 34, 67, 0, 0, 17, 67, 0, 0, 34, 67, 0, 0, 18, 67, 0, 0, 34, 67, 0, 0, 19, 67, 0, 0, 34, 67, 0, 0, 20, 67, 0, 0, 34, 67, 0, 0, 21, 67, 0, 0, 34, 67, 0, 0, 22, 67, 0, 0, 34, 67, 0, 0, 23, 67, 0, 0, 34, 67, 0, 0, 24, 67, 0, 0, 34, 67, 0, 0, 25, 67, 0, 0, 34, 67, 0, 0, 26, 67, 0, 0, 34, 67, 0, 0, 27, 67, 0, 0, 34, 67, 0, 0, 28, 67, 0, 0, 34, 67, 0, 0, 29, 67, 0, 0, 34, 67, 0, 0, 30, 67, 0, 0, 34, 67, 0, 0, 31, 67, 0, 0, 34, 67, 0, 0, 32, 67, 0, 0, 34, 67, 0, 0, 33, 67, 0, 0, 34, 67, 0, 0, 34, 67, 0, 0, 34, 67, 0, 0, 35, 67, 0, 0, 34, 67, 0, 0, 36, 67, 0, 0, 34, 67, 0, 0, 37, 67, 0, 0, 34, 67, 0, 0, 38, 67, 0, 0, 34, 67, 0, 0, 39, 67, 0, 0, 34, 67, 0, 0, 40, 67, 0, 0, 34, 67, 0, 0, 41, 67, 0, 0, 34, 67, 0, 0, 42, 67, 0, 0, 34, 67, 0, 0, 43, 67, 0, 0, 34, 67, 0, 0, 44, 67, 0, 0, 34, 67, 0, 0, 45, 67, 0, 0, 34, 67, 0, 0, 46, 67, 0, 0, 34, 67, 0, 0, 47, 67, 0, 0, 34, 67, 0, 0, 48, 67, 0, 0, 34, 67, 0, 0, 49, 67, 0, 0, 34, 67, 0, 0, 50, 67, 0, 0, 34, 67, 0, 0, 51, 67, 0, 0, 34, 67, 0, 0, 52, 67, 0, 0, 34, 67, 0, 0, 53, 67, 0, 0, 34, 67, 0, 0, 54, 67, 0, 0, 34, 67, 0, 0, 55, 67, 0, 0, 35, 67, 0, 0, 184, 66, 0, 0, 35, 67, 0, 0, 186, 66, 0, 0, 35, 67, 0, 0, 188, 66, 0, 0, 35, 67, 0, 0, 190, 66, 0, 0, 35, 67, 0, 0, 192, 66, 0, 0, 35, 67, 0, 0, 194, 66, 0, 0, 35, 67, 0, 0, 196, 66, 0, 0, 35, 67, 0, 0, 198, 66, 0, 0, 35, 67, 0, 0, 200, 66, 0, 0, 35, 67, 0, 0, 202, 66, 0, 0, 35, 67, 0, 0, 204, 66, 0, 0, 35, 67, 0, 0, 206, 66, 0, 0, 35, 67, 0, 0, 208, 66, 0, 0, 35, 67, 0, 0, 210, 66, 0, 0, 35, 67, 0, 0, 212, 66, 0, 0, 35, 67, 0, 0, 214, 66, 0, 0, 35, 67, 0, 0, 216, 66, 0, 0, 35, 67, 0, 0, 218, 66, 0, 0, 35, 67, 0, 0, 220, 66, 0, 0, 35, 67, 0, 0, 222, 66, 0, 0, 35, 67, 0, 0, 224, 66, 0, 0, 35, 67, 0, 0, 226, 66, 0, 0, 35, 67, 0, 0, 228, 66, 0, 0, 35, 67, 0, 0, 230, 66, 0, 0, 35, 67, 0, 0, 232, 66, 0, 0, 35, 67, 0, 0, 234, 66, 0, 0, 35, 67, 0, 0, 236, 66, 0, 0, 35, 67, 0, 0, 238, 66, 0, 0, 35, 67, 0, 0, 240, 66, 0, 0, 35, 67, 0, 0, 242, 66, 0, 0, 35, 67, 0, 0, 244, 66, 0, 0, 35, 67, 0, 0, 246, 66, 0, 0, 35, 67, 0, 0, 248, 66, 0, 0, 35, 67, 0, 0, 250, 66, 0, 0, 35, 67, 0, 0, 252, 66, 0, 0, 35, 67, 0, 0, 254, 66, 0, 0, 35, 67, 0, 0, 0, 67, 0, 0, 35, 67, 0, 0, 1, 67, 0, 0, 35, 67, 0, 0, 2, 67, 0, 0, 35, 67, 0, 0, 3, 67, 0, 0, 35, 67, 0, 0, 4, 67, 0, 0, 35, 67, 0, 0, 5, 67, 0, 0, 35, 67, 0, 0, 6, 67, 0, 0, 35, 67, 0, 0, 7, 67, 0, 0, 35, 67, 0, 0, 8, 67, 0, 0, 35, 67, 0, 0, 9, 67, 0, 0, 35, 67, 0, 0, 10, 67, 0, 0, 35, 67, 0, 0, 11, 67, 0, 0, 35, 67, 0, 0, 12, 67, 0, 0, 35, 67, 0, 0, 13, 67, 0, 0, 35, 67, 0, 0, 14, 67, 0, 0, 35, 67, 0, 0, 15, 67, 0, 0, 35, 67, 0, 0, 16, 67, 0, 0, 35, 67, 0, 0, 17, 67, 0, 0, 35, 67, 0, 0, 18, 67, 0, 0, 35, 67, 0, 0, 19, 67, 0, 0, 35, 67, 0, 0, 20, 67, 0, 0, 35, 67, 0, 0, 21, 67, 0, 0, 35, 67, 0, 0, 22, 67, 0, 0, 35, 67, 0, 0, 23, 67, 0, 0, 35, 67, 0, 0, 24, 67, 0, 0, 35, 67, 0, 0, 25, 67, 0, 0, 35, 67, 0, 0, 26, 67, 0, 0, 35, 67, 0, 0, 27, 67, 0, 0, 35, 67, 0, 0, 28, 67, 0, 0, 35, 67, 0, 0, 29, 67, 0, 0, 35, 67, 0, 0, 30, 67, 0, 0, 35, 67, 0, 0, 31, 67, 0, 0, 35, 67, 0, 0, 32, 67, 0, 0, 35, 67, 0, 0, 33, 67, 0, 0, 35, 67, 0, 0, 34, 67, 0, 0, 35, 67, 0, 0, 35, 67, 0, 0, 35, 67, 0, 0, 36, 67, 0, 0, 35, 67, 0, 0, 37, 67, 0, 0, 35, 67, 0, 0, 38, 67, 0, 0, 35, 67, 0, 0, 39, 67, 0, 0, 35, 67, 0, 0, 40, 67, 0, 0, 35, 67, 0, 0, 41, 67, 0, 0, 35, 67, 0, 0, 42, 67, 0, 0, 35, 67, 0, 0, 43, 67, 0, 0, 35, 67, 0, 0, 44, 67, 0, 0, 35, 67, 0, 0, 45, 67, 0, 0, 35, 67, 0, 0, 46, 67, 0, 0, 35, 67, 0, 0, 47, 67, 0, 0, 35, 67, 0, 0, 48, 67, 0, 0, 35, 67, 0, 0, 49, 67, 0, 0, 35, 67, 0, 0, 50, 67, 0, 0, 35, 67, 0, 0, 51, 67, 0, 0, 35, 67, 0, 0, 52, 67, 0, 0, 35, 67, 0, 0, 53, 67, 0, 0, 35, 67, 0, 0, 54, 67, 0, 0, 35, 67, 0, 0, 55, 67, 0, 0, 36, 67, 0, 0, 184, 66, 0, 0, 36, 67, 0, 0, 186, 66, 0, 0, 36, 67, 0, 0, 188, 66, 0, 0, 36, 67, 0, 0, 190, 66, 0, 0, 36, 67, 0, 0, 192, 66, 0, 0, 36, 67, 0, 0, 194, 66, 0, 0, 36, 67, 0, 0, 196, 66, 0, 0, 36, 67, 0, 0, 198, 66, 0, 0, 36, 67, 0, 0, 200, 66, 0, 0, 36, 67, 0, 0, 202, 66, 0, 0, 36, 67, 0, 0, 204, 66, 0, 0, 36, 67, 0, 0, 206, 66, 0, 0, 36, 67, 0, 0, 208, 66, 0, 0, 36, 67, 0, 0, 210, 66, 0, 0, 36, 67, 0, 0, 212, 66, 0, 0, 36, 67, 0, 0, 214, 66, 0, 0, 36, 67, 0, 0, 216, 66, 0, 0, 36, 67, 0, 0, 218, 66, 0, 0, 36, 67, 0, 0, 220, 66, 0, 0, 36, 67, 0, 0, 222, 66, 0, 0, 36, 67, 0, 0, 224, 66, 0, 0, 36, 67, 0, 0, 226, 66, 0, 0, 36, 67, 0, 0, 228, 66, 0, 0, 36, 67, 0, 0, 230, 66, 0, 0, 36, 67, 0, 0, 232, 66, 0, 0, 36, 67, 0, 0, 234, 66, 0, 0, 36, 67, 0, 0, 236, 66, 0, 0, 36, 67, 0, 0, 238, 66, 0, 0, 36, 67, 0, 0, 240, 66, 0, 0, 36, 67, 0, 0, 242, 66, 0, 0, 36, 67, 0, 0, 244, 66, 0, 0, 36, 67, 0, 0, 246, 66, 0, 0, 36, 67, 0, 0, 248, 66, 0, 0, 36, 67, 0, 0, 250, 66, 0, 0, 36, 67, 0, 0, 252, 66, 0, 0, 36, 67, 0, 0, 254, 66, 0, 0, 36, 67, 0, 0, 0, 67, 0, 0, 36, 67, 0, 0, 1, 67, 0, 0, 36, 67, 0, 0, 2, 67, 0, 0, 36, 67, 0, 0, 3, 67, 0, 0, 36, 67, 0, 0, 4, 67, 0, 0, 36, 67, 0, 0, 5, 67, 0, 0, 36, 67, 0, 0, 6, 67, 0, 0, 36, 67, 0, 0, 7, 67, 0, 0, 36, 67, 0, 0, 8, 67, 0, 0, 36, 67, 0, 0, 9, 67, 0, 0, 36, 67, 0, 0, 10, 67, 0, 0, 36, 67, 0, 0, 11, 67, 0, 0, 36, 67, 0, 0, 12, 67, 0, 0, 36, 67, 0, 0, 13, 67, 0, 0, 36, 67, 0, 0, 14, 67, 0, 0, 36, 67, 0, 0, 15, 67, 0, 0, 36, 67, 0, 0, 16, 67, 0, 0, 36, 67, 0, 0, 17, 67, 0, 0, 36, 67, 0, 0, 18, 67, 0, 0, 36, 67, 0, 0, 19, 67, 0, 0, 36, 67, 0, 0, 20, 67, 0, 0, 36, 67, 0, 0, 21, 67, 0, 0, 36, 67, 0, 0, 22, 67, 0, 0, 36, 67, 0, 0, 23, 67, 0, 0, 36, 67, 0, 0, 24, 67, 0, 0, 36, 67, 0, 0, 25, 67, 0, 0, 36, 67, 0, 0, 26, 67, 0, 0, 36, 67, 0, 0, 27, 67, 0, 0, 36, 67, 0, 0, 28, 67, 0, 0, 36, 67, 0, 0, 29, 67, 0, 0, 36, 67, 0, 0, 30, 67, 0, 0, 36, 67, 0, 0, 31, 67, 0, 0, 36, 67, 0, 0, 32, 67, 0, 0, 36, 67, 0, 0, 33, 67, 0, 0, 36, 67, 0, 0, 34, 67, 0, 0, 36, 67, 0, 0, 35, 67, 0, 0, 36, 67, 0, 0, 36, 67, 0, 0, 36, 67, 0, 0, 37, 67, 0, 0, 36, 67, 0, 0, 38, 67, 0, 0, 36, 67, 0, 0, 39, 67, 0, 0, 36, 67, 0, 0, 40, 67, 0, 0, 36, 67, 0, 0, 41, 67, 0, 0, 36, 67, 0, 0, 42, 67, 0, 0, 36, 67, 0, 0, 43, 67, 0, 0, 36, 67, 0, 0, 44, 67, 0, 0, 36, 67, 0, 0, 45, 67, 0, 0, 36, 67, 0, 0, 46, 67, 0, 0, 36, 67, 0, 0, 47, 67, 0, 0, 36, 67, 0, 0, 48, 67, 0, 0, 36, 67, 0, 0, 49, 67, 0, 0, 36, 67, 0, 0, 50, 67, 0, 0, 36, 67, 0, 0, 51, 67, 0, 0, 36, 67, 0, 0, 52, 67, 0, 0, 36, 67, 0, 0, 53, 67, 0, 0, 36, 67, 0, 0, 54, 67, 0, 0, 36, 67, 0, 0, 55, 67, 0, 0, 37, 67, 0, 0, 184, 66, 0, 0, 37, 67, 0, 0, 186, 66, 0, 0, 37, 67, 0, 0, 188, 66, 0, 0, 37, 67, 0, 0, 190, 66, 0, 0, 37, 67, 0, 0, 192, 66, 0, 0, 37, 67, 0, 0, 194, 66, 0, 0, 37, 67, 0, 0, 196, 66, 0, 0, 37, 67, 0, 0, 198, 66, 0, 0, 37, 67, 0, 0, 200, 66, 0, 0, 37, 67, 0, 0, 202, 66, 0, 0, 37, 67, 0, 0, 204, 66, 0, 0, 37, 67, 0, 0, 206, 66, 0, 0, 37, 67, 0, 0, 208, 66, 0, 0, 37, 67, 0, 0, 210, 66, 0, 0, 37, 67, 0, 0, 212, 66, 0, 0, 37, 67, 0, 0, 214, 66, 0, 0, 37, 67, 0, 0, 216, 66, 0, 0, 37, 67, 0, 0, 218, 66, 0, 0, 37, 67, 0, 0, 220, 66, 0, 0, 37, 67, 0, 0, 222, 66, 0, 0, 37, 67, 0, 0, 224, 66, 0, 0, 37, 67, 0, 0, 226, 66, 0, 0, 37, 67, 0, 0, 228, 66, 0, 0, 37, 67, 0, 0, 230, 66, 0, 0, 37, 67, 0, 0, 232, 66, 0, 0, 37, 67, 0, 0, 234, 66, 0, 0, 37, 67, 0, 0, 236, 66, 0, 0, 37, 67, 0, 0, 238, 66, 0, 0, 37, 67, 0, 0, 240, 66, 0, 0, 37, 67, 0, 0, 242, 66, 0, 0, 37, 67, 0, 0, 244, 66, 0, 0, 37, 67, 0, 0, 246, 66, 0, 0, 37, 67, 0, 0, 248, 66, 0, 0, 37, 67, 0, 0, 250, 66, 0, 0, 37, 67, 0, 0, 252, 66, 0, 0, 37, 67, 0, 0, 254, 66, 0, 0, 37, 67, 0, 0, 0, 67, 0, 0, 37, 67, 0, 0, 1, 67, 0, 0, 37, 67, 0, 0, 2, 67, 0, 0, 37, 67, 0, 0, 3, 67, 0, 0, 37, 67, 0, 0, 4, 67, 0, 0, 37, 67, 0, 0, 5, 67, 0, 0, 37, 67, 0, 0, 6, 67, 0, 0, 37, 67, 0, 0, 7, 67, 0, 0, 37, 67, 0, 0, 8, 67, 0, 0, 37, 67, 0, 0, 9, 67, 0, 0, 37, 67, 0, 0, 10, 67, 0, 0, 37, 67, 0, 0, 11, 67, 0, 0, 37, 67, 0, 0, 12, 67, 0, 0, 37, 67, 0, 0, 13, 67, 0, 0, 37, 67, 0, 0, 14, 67, 0, 0, 37, 67, 0, 0, 15, 67, 0, 0, 37, 67, 0, 0, 16, 67, 0, 0, 37, 67, 0, 0, 17, 67, 0, 0, 37, 67, 0, 0, 18, 67, 0, 0, 37, 67, 0, 0, 19, 67, 0, 0, 37, 67, 0, 0, 20, 67, 0, 0, 37, 67, 0, 0, 21, 67, 0, 0, 37, 67, 0, 0, 22, 67, 0, 0, 37, 67, 0, 0, 23, 67, 0, 0, 37, 67, 0, 0, 24, 67, 0, 0, 37, 67, 0, 0, 25, 67, 0, 0, 37, 67, 0, 0, 26, 67, 0, 0, 37, 67, 0, 0, 27, 67, 0, 0, 37, 67, 0, 0, 28, 67, 0, 0, 37, 67, 0, 0, 29, 67, 0, 0, 37, 67, 0, 0, 30, 67, 0, 0, 37, 67, 0, 0, 31, 67, 0, 0, 37, 67, 0, 0, 32, 67, 0, 0, 37, 67, 0, 0, 33, 67, 0, 0, 37, 67, 0, 0, 34, 67, 0, 0, 37, 67, 0, 0, 35, 67, 0, 0, 37, 67, 0, 0, 36, 67, 0, 0, 37, 67, 0, 0, 37, 67, 0, 0, 37, 67, 0, 0, 38, 67, 0, 0, 37, 67, 0, 0, 39, 67, 0, 0, 37, 67, 0, 0, 40, 67, 0, 0, 37, 67, 0, 0, 41, 67, 0, 0, 37, 67, 0, 0, 42, 67, 0, 0, 37, 67, 0, 0, 43, 67, 0, 0, 37, 67, 0, 0, 44, 67, 0, 0, 37, 67, 0, 0, 45, 67, 0, 0, 37, 67, 0, 0, 46, 67, 0, 0, 37, 67, 0, 0, 47, 67, 0, 0, 37, 67, 0, 0, 48, 67, 0, 0, 37, 67, 0, 0, 49, 67, 0, 0, 37, 67, 0, 0, 50, 67, 0, 0, 37, 67, 0, 0, 51, 67, 0, 0, 37, 67, 0, 0, 52, 67, 0, 0, 37, 67, 0, 0, 53, 67, 0, 0, 37, 67, 0, 0, 54, 67, 0, 0, 37, 67, 0, 0, 55, 67, 0, 0, 38, 67, 0, 0, 184, 66, 0, 0, 38, 67, 0, 0, 186, 66, 0, 0, 38, 67, 0, 0, 188, 66, 0, 0, 38, 67, 0, 0, 190, 66, 0, 0, 38, 67, 0, 0, 192, 66, 0, 0, 38, 67, 0, 0, 194, 66, 0, 0, 38, 67, 0, 0, 196, 66, 0, 0, 38, 67, 0, 0, 198, 66, 0, 0, 38, 67, 0, 0, 200, 66, 0, 0, 38, 67, 0, 0, 202, 66, 0, 0, 38, 67, 0, 0, 204, 66, 0, 0, 38, 67, 0, 0, 206, 66, 0, 0, 38, 67, 0, 0, 208, 66, 0, 0, 38, 67, 0, 0, 210, 66, 0, 0, 38, 67, 0, 0, 212, 66, 0, 0, 38, 67, 0, 0, 214, 66, 0, 0, 38, 67, 0, 0, 216, 66, 0, 0, 38, 67, 0, 0, 218, 66, 0, 0, 38, 67, 0, 0, 220, 66, 0, 0, 38, 67, 0, 0, 222, 66, 0, 0, 38, 67, 0, 0, 224, 66, 0, 0, 38, 67, 0, 0, 226, 66, 0, 0, 38, 67, 0, 0, 228, 66, 0, 0, 38, 67, 0, 0, 230, 66, 0, 0, 38, 67, 0, 0, 232, 66, 0, 0, 38, 67, 0, 0, 234, 66, 0, 0, 38, 67, 0, 0, 236, 66, 0, 0, 38, 67, 0, 0, 238, 66, 0, 0, 38, 67, 0, 0, 240, 66, 0, 0, 38, 67, 0, 0, 242, 66, 0, 0, 38, 67, 0, 0, 244, 66, 0, 0, 38, 67, 0, 0, 246, 66, 0, 0, 38, 67, 0, 0, 248, 66, 0, 0, 38, 67, 0, 0, 250, 66, 0, 0, 38, 67, 0, 0, 252, 66, 0, 0, 38, 67, 0, 0, 254, 66, 0, 0, 38, 67, 0, 0, 0, 67, 0, 0, 38, 67, 0, 0, 1, 67, 0, 0, 38, 67, 0, 0, 2, 67, 0, 0, 38, 67, 0, 0, 3, 67, 0, 0, 38, 67, 0, 0, 4, 67, 0, 0, 38, 67, 0, 0, 5, 67, 0, 0, 38, 67, 0, 0, 6, 67, 0, 0, 38, 67, 0, 0, 7, 67, 0, 0, 38, 67, 0, 0, 8, 67, 0, 0, 38, 67, 0, 0, 9, 67, 0, 0, 38, 67, 0, 0, 10, 67, 0, 0, 38, 67, 0, 0, 11, 67, 0, 0, 38, 67, 0, 0, 12, 67, 0, 0, 38, 67, 0, 0, 13, 67, 0, 0, 38, 67, 0, 0, 14, 67, 0, 0, 38, 67, 0, 0, 15, 67, 0, 0, 38, 67, 0, 0, 16, 67, 0, 0, 38, 67, 0, 0, 17, 67, 0, 0, 38, 67, 0, 0, 18, 67, 0, 0, 38, 67, 0, 0, 19, 67, 0, 0, 38, 67, 0, 0, 20, 67, 0, 0, 38, 67, 0, 0, 21, 67, 0, 0, 38, 67, 0, 0, 22, 67, 0, 0, 38, 67, 0, 0, 23, 67, 0, 0, 38, 67, 0, 0, 24, 67, 0, 0, 38, 67, 0, 0, 25, 67, 0, 0, 38, 67, 0, 0, 26, 67, 0, 0, 38, 67, 0, 0, 27, 67, 0, 0, 38, 67, 0, 0, 28, 67, 0, 0, 38, 67, 0, 0, 29, 67, 0, 0, 38, 67, 0, 0, 30, 67, 0, 0, 38, 67, 0, 0, 31, 67, 0, 0, 38, 67, 0, 0, 32, 67, 0, 0, 38, 67, 0, 0, 33, 67, 0, 0, 38, 67, 0, 0, 34, 67, 0, 0, 38, 67, 0, 0, 35, 67, 0, 0, 38, 67, 0, 0, 36, 67, 0, 0, 38, 67, 0, 0, 37, 67, 0, 0, 38, 67, 0, 0, 38, 67, 0, 0, 38, 67, 0, 0, 39, 67, 0, 0, 38, 67, 0, 0, 40, 67, 0, 0, 38, 67, 0, 0, 41, 67, 0, 0, 38, 67, 0, 0, 42, 67, 0, 0, 38, 67, 0, 0, 43, 67, 0, 0, 38, 67, 0, 0, 44, 67, 0, 0, 38, 67, 0, 0, 45, 67, 0, 0, 38, 67, 0, 0, 46, 67, 0, 0, 38, 67, 0, 0, 47, 67, 0, 0, 38, 67, 0, 0, 48, 67, 0, 0, 38, 67, 0, 0, 49, 67, 0, 0, 38, 67, 0, 0, 50, 67, 0, 0, 38, 67, 0, 0, 51, 67, 0, 0, 38, 67, 0, 0, 52, 67, 0, 0, 38, 67, 0, 0, 53, 67, 0, 0, 38, 67, 0, 0, 54, 67, 0, 0, 38, 67, 0, 0, 55, 67, 0, 0, 39, 67, 0, 0, 184, 66, 0, 0, 39, 67, 0, 0, 186, 66, 0, 0, 39, 67, 0, 0, 188, 66, 0, 0, 39, 67, 0, 0, 190, 66, 0, 0, 39, 67, 0, 0, 192, 66, 0, 0, 39, 67, 0, 0, 194, 66, 0, 0, 39, 67, 0, 0, 196, 66, 0, 0, 39, 67, 0, 0, 198, 66, 0, 0, 39, 67, 0, 0, 200, 66, 0, 0, 39, 67, 0, 0, 202, 66, 0, 0, 39, 67, 0, 0, 204, 66, 0, 0, 39, 67, 0, 0, 206, 66, 0, 0, 39, 67, 0, 0, 208, 66, 0, 0, 39, 67, 0, 0, 210, 66, 0, 0, 39, 67, 0, 0, 212, 66, 0, 0, 39, 67, 0, 0, 214, 66, 0, 0, 39, 67, 0, 0, 216, 66, 0, 0, 39, 67, 0, 0, 218, 66, 0, 0, 39, 67, 0, 0, 220, 66, 0, 0, 39, 67, 0, 0, 222, 66, 0, 0, 39, 67, 0, 0, 224, 66, 0, 0, 39, 67, 0, 0, 226, 66, 0, 0, 39, 67, 0, 0, 228, 66, 0, 0, 39, 67, 0, 0, 230, 66, 0, 0, 39, 67, 0, 0, 232, 66, 0, 0, 39, 67, 0, 0, 234, 66, 0, 0, 39, 67, 0, 0, 236, 66, 0, 0, 39, 67, 0, 0, 238, 66, 0, 0, 39, 67, 0, 0, 240, 66, 0, 0, 39, 67, 0, 0, 242, 66, 0, 0, 39, 67, 0, 0, 244, 66, 0, 0, 39, 67, 0, 0, 246, 66, 0, 0, 39, 67, 0, 0, 248, 66, 0, 0, 39, 67, 0, 0, 250, 66, 0, 0, 39, 67, 0, 0, 252, 66, 0, 0, 39, 67, 0, 0, 254, 66, 0, 0, 39, 67, 0, 0, 0, 67, 0, 0, 39, 67, 0, 0, 1, 67, 0, 0, 39, 67, 0, 0, 2, 67, 0, 0, 39, 67, 0, 0, 3, 67, 0, 0, 39, 67, 0, 0, 4, 67, 0, 0, 39, 67, 0, 0, 5, 67, 0, 0, 39, 67, 0, 0, 6, 67, 0, 0, 39, 67, 0, 0, 7, 67, 0, 0, 39, 67, 0, 0, 8, 67, 0, 0, 39, 67, 0, 0, 9, 67, 0, 0, 39, 67, 0, 0, 10, 67, 0, 0, 39, 67, 0, 0, 11, 67, 0, 0, 39, 67, 0, 0, 12, 67, 0, 0, 39, 67, 0, 0, 13, 67, 0, 0, 39, 67, 0, 0, 14, 67, 0, 0, 39, 67, 0, 0, 15, 67, 0, 0, 39, 67, 0, 0, 16, 67, 0, 0, 39, 67, 0, 0, 17, 67, 0, 0, 39, 67, 0, 0, 18, 67, 0, 0, 39, 67, 0, 0, 19, 67, 0, 0, 39, 67, 0, 0, 20, 67, 0, 0, 39, 67, 0, 0, 21, 67, 0, 0, 39, 67, 0, 0, 22, 67, 0, 0, 39, 67, 0, 0, 23, 67, 0, 0, 39, 67, 0, 0, 24, 67, 0, 0, 39, 67, 0, 0, 25, 67, 0, 0, 39, 67, 0, 0, 26, 67, 0, 0, 39, 67, 0, 0, 27, 67, 0, 0, 39, 67, 0, 0, 28, 67, 0, 0, 39, 67, 0, 0, 29, 67, 0, 0, 39, 67, 0, 0, 30, 67, 0, 0, 39, 67, 0, 0, 31, 67, 0, 0, 39, 67, 0, 0, 32, 67, 0, 0, 39, 67, 0, 0, 33, 67, 0, 0, 39, 67, 0, 0, 34, 67, 0, 0, 39, 67, 0, 0, 35, 67, 0, 0, 39, 67, 0, 0, 36, 67, 0, 0, 39, 67, 0, 0, 37, 67, 0, 0, 39, 67, 0, 0, 38, 67, 0, 0, 39, 67, 0, 0, 39, 67, 0, 0, 39, 67, 0, 0, 40, 67, 0, 0, 39, 67, 0, 0, 41, 67, 0, 0, 39, 67, 0, 0, 42, 67, 0, 0, 39, 67, 0, 0, 43, 67, 0, 0, 39, 67, 0, 0, 44, 67, 0, 0, 39, 67, 0, 0, 45, 67, 0, 0, 39, 67, 0, 0, 46, 67, 0, 0, 39, 67, 0, 0, 47, 67, 0, 0, 39, 67, 0, 0, 48, 67, 0, 0, 39, 67, 0, 0, 49, 67, 0, 0, 39, 67, 0, 0, 50, 67, 0, 0, 39, 67, 0, 0, 51, 67, 0, 0, 39, 67, 0, 0, 52, 67, 0, 0, 39, 67, 0, 0, 53, 67, 0, 0, 39, 67, 0, 0, 54, 67, 0, 0, 39, 67, 0, 0, 55, 67, 0, 0, 40, 67, 0, 0, 184, 66, 0, 0, 40, 67, 0, 0, 186, 66, 0, 0, 40, 67, 0, 0, 188, 66, 0, 0, 40, 67, 0, 0, 190, 66, 0, 0, 40, 67, 0, 0, 192, 66, 0, 0, 40, 67, 0, 0, 194, 66, 0, 0, 40, 67, 0, 0, 196, 66, 0, 0, 40, 67, 0, 0, 198, 66, 0, 0, 40, 67, 0, 0, 200, 66, 0, 0, 40, 67, 0, 0, 202, 66, 0, 0, 40, 67, 0, 0, 204, 66, 0, 0, 40, 67, 0, 0, 206, 66, 0, 0, 40, 67, 0, 0, 208, 66, 0, 0, 40, 67, 0, 0, 210, 66, 0, 0, 40, 67, 0, 0, 212, 66, 0, 0, 40, 67, 0, 0, 214, 66, 0, 0, 40, 67, 0, 0, 216, 66, 0, 0, 40, 67, 0, 0, 218, 66, 0, 0, 40, 67, 0, 0, 220, 66, 0, 0, 40, 67, 0, 0, 222, 66, 0, 0, 40, 67, 0, 0, 224, 66, 0, 0, 40, 67, 0, 0, 226, 66, 0, 0, 40, 67, 0, 0, 228, 66, 0, 0, 40, 67, 0, 0, 230, 66, 0, 0, 40, 67, 0, 0, 232, 66, 0, 0, 40, 67, 0, 0, 234, 66, 0, 0, 40, 67, 0, 0, 236, 66, 0, 0, 40, 67, 0, 0, 238, 66, 0, 0, 40, 67, 0, 0, 240, 66, 0, 0, 40, 67, 0, 0, 242, 66, 0, 0, 40, 67, 0, 0, 244, 66, 0, 0, 40, 67, 0, 0, 246, 66, 0, 0, 40, 67, 0, 0, 248, 66, 0, 0, 40, 67, 0, 0, 250, 66, 0, 0, 40, 67, 0, 0, 252, 66, 0, 0, 40, 67, 0, 0, 254, 66, 0, 0, 40, 67, 0, 0, 0, 67, 0, 0, 40, 67, 0, 0, 1, 67, 0, 0, 40, 67, 0, 0, 2, 67, 0, 0, 40, 67, 0, 0, 3, 67, 0, 0, 40, 67, 0, 0, 4, 67, 0, 0, 40, 67, 0, 0, 5, 67, 0, 0, 40, 67, 0, 0, 6, 67, 0, 0, 40, 67, 0, 0, 7, 67, 0, 0, 40, 67, 0, 0, 8, 67, 0, 0, 40, 67, 0, 0, 9, 67, 0, 0, 40, 67, 0, 0, 10, 67, 0, 0, 40, 67, 0, 0, 11, 67, 0, 0, 40, 67, 0, 0, 12, 67, 0, 0, 40, 67, 0, 0, 13, 67, 0, 0, 40, 67, 0, 0, 14, 67, 0, 0, 40, 67, 0, 0, 15, 67, 0, 0, 40, 67, 0, 0, 16, 67, 0, 0, 40, 67, 0, 0, 17, 67, 0, 0, 40, 67, 0, 0, 18, 67, 0, 0, 40, 67, 0, 0, 19, 67, 0, 0, 40, 67, 0, 0, 20, 67, 0, 0, 40, 67, 0, 0, 21, 67, 0, 0, 40, 67, 0, 0, 22, 67, 0, 0, 40, 67, 0, 0, 23, 67, 0, 0, 40, 67, 0, 0, 24, 67, 0, 0, 40, 67, 0, 0, 25, 67, 0, 0, 40, 67, 0, 0, 26, 67, 0, 0, 40, 67, 0, 0, 27, 67, 0, 0, 40, 67, 0, 0, 28, 67, 0, 0, 40, 67, 0, 0, 29, 67, 0, 0, 40, 67, 0, 0, 30, 67, 0, 0, 40, 67, 0, 0, 31, 67, 0, 0, 40, 67, 0, 0, 32, 67, 0, 0, 40, 67, 0, 0, 33, 67, 0, 0, 40, 67, 0, 0, 34, 67, 0, 0, 40, 67, 0, 0, 35, 67, 0, 0, 40, 67, 0, 0, 36, 67, 0, 0, 40, 67, 0, 0, 37, 67, 0, 0, 40, 67, 0, 0, 38, 67, 0, 0, 40, 67, 0, 0, 39, 67, 0, 0, 40, 67, 0, 0, 40, 67, 0, 0, 40, 67, 0, 0, 41, 67, 0, 0, 40, 67, 0, 0, 42, 67, 0, 0, 40, 67, 0, 0, 43, 67, 0, 0, 40, 67, 0, 0, 44, 67, 0, 0, 40, 67, 0, 0, 45, 67, 0, 0, 40, 67, 0, 0, 46, 67, 0, 0, 40, 67, 0, 0, 47, 67, 0, 0, 40, 67, 0, 0, 48, 67, 0, 0, 40, 67, 0, 0, 49, 67, 0, 0, 40, 67, 0, 0, 50, 67, 0, 0, 40, 67, 0, 0, 51, 67, 0, 0, 40, 67, 0, 0, 52, 67, 0, 0, 40, 67, 0, 0, 53, 67, 0, 0, 40, 67, 0, 0, 54, 67, 0, 0, 40, 67, 0, 0, 55, 67, 0, 0, 41, 67, 0, 0, 184, 66, 0, 0, 41, 67, 0, 0, 186, 66, 0, 0, 41, 67, 0, 0, 188, 66, 0, 0, 41, 67, 0, 0, 190, 66, 0, 0, 41, 67, 0, 0, 192, 66, 0, 0, 41, 67, 0, 0, 194, 66, 0, 0, 41, 67, 0, 0, 196, 66, 0, 0, 41, 67, 0, 0, 198, 66, 0, 0, 41, 67, 0, 0, 200, 66, 0, 0, 41, 67, 0, 0, 202, 66, 0, 0, 41, 67, 0, 0, 204, 66, 0, 0, 41, 67, 0, 0, 206, 66, 0, 0, 41, 67, 0, 0, 208, 66, 0, 0, 41, 67, 0, 0, 210, 66, 0, 0, 41, 67, 0, 0, 212, 66, 0, 0, 41, 67, 0, 0, 214, 66, 0, 0, 41, 67, 0, 0, 216, 66, 0, 0, 41, 67, 0, 0, 218, 66, 0, 0, 41, 67, 0, 0, 220, 66, 0, 0, 41, 67, 0, 0, 222, 66, 0, 0, 41, 67, 0, 0, 224, 66, 0, 0, 41, 67, 0, 0, 226, 66, 0, 0, 41, 67, 0, 0, 228, 66, 0, 0, 41, 67, 0, 0, 230, 66, 0, 0, 41, 67, 0, 0, 232, 66, 0, 0, 41, 67, 0, 0, 234, 66, 0, 0, 41, 67, 0, 0, 236, 66, 0, 0, 41, 67, 0, 0, 238, 66, 0, 0, 41, 67, 0, 0, 240, 66, 0, 0, 41, 67, 0, 0, 242, 66, 0, 0, 41, 67, 0, 0, 244, 66, 0, 0, 41, 67, 0, 0, 246, 66, 0, 0, 41, 67, 0, 0, 248, 66, 0, 0, 41, 67, 0, 0, 250, 66, 0, 0, 41, 67, 0, 0, 252, 66, 0, 0, 41, 67, 0, 0, 254, 66, 0, 0, 41, 67, 0, 0, 0, 67, 0, 0, 41, 67, 0, 0, 1, 67, 0, 0, 41, 67, 0, 0, 2, 67, 0, 0, 41, 67, 0, 0, 3, 67, 0, 0, 41, 67, 0, 0, 4, 67, 0, 0, 41, 67, 0, 0, 5, 67, 0, 0, 41, 67, 0, 0, 6, 67, 0, 0, 41, 67, 0, 0, 7, 67, 0, 0, 41, 67, 0, 0, 8, 67, 0, 0, 41, 67, 0, 0, 9, 67, 0, 0, 41, 67, 0, 0, 10, 67, 0, 0, 41, 67, 0, 0, 11, 67, 0, 0, 41, 67, 0, 0, 12, 67, 0, 0, 41, 67, 0, 0, 13, 67, 0, 0, 41, 67, 0, 0, 14, 67, 0, 0, 41, 67, 0, 0, 15, 67, 0, 0, 41, 67, 0, 0, 16, 67, 0, 0, 41, 67, 0, 0, 17, 67, 0, 0, 41, 67, 0, 0, 18, 67, 0, 0, 41, 67, 0, 0, 19, 67, 0, 0, 41, 67, 0, 0, 20, 67, 0, 0, 41, 67, 0, 0, 21, 67, 0, 0, 41, 67, 0, 0, 22, 67, 0, 0, 41, 67, 0, 0, 23, 67, 0, 0, 41, 67, 0, 0, 24, 67, 0, 0, 41, 67, 0, 0, 25, 67, 0, 0, 41, 67, 0, 0, 26, 67, 0, 0, 41, 67, 0, 0, 27, 67, 0, 0, 41, 67, 0, 0, 28, 67, 0, 0, 41, 67, 0, 0, 29, 67, 0, 0, 41, 67, 0, 0, 30, 67, 0, 0, 41, 67, 0, 0, 31, 67, 0, 0, 41, 67, 0, 0, 32, 67, 0, 0, 41, 67, 0, 0, 33, 67, 0, 0, 41, 67, 0, 0, 34, 67, 0, 0, 41, 67, 0, 0, 35, 67, 0, 0, 41, 67, 0, 0, 36, 67, 0, 0, 41, 67, 0, 0, 37, 67, 0, 0, 41, 67, 0, 0, 38, 67, 0, 0, 41, 67, 0, 0, 39, 67, 0, 0, 41, 67, 0, 0, 40, 67, 0, 0, 41, 67, 0, 0, 41, 67, 0, 0, 41, 67, 0, 0, 42, 67, 0, 0, 41, 67, 0, 0, 43, 67, 0, 0, 41, 67, 0, 0, 44, 67, 0, 0, 41, 67, 0, 0, 45, 67, 0, 0, 41, 67, 0, 0, 46, 67, 0, 0, 41, 67, 0, 0, 47, 67, 0, 0, 41, 67, 0, 0, 48, 67, 0, 0, 41, 67, 0, 0, 49, 67, 0, 0, 41, 67, 0, 0, 50, 67, 0, 0, 41, 67, 0, 0, 51, 67, 0, 0, 41, 67, 0, 0, 52, 67, 0, 0, 41, 67, 0, 0, 53, 67, 0, 0, 41, 67, 0, 0, 54, 67, 0, 0, 41, 67, 0, 0, 55, 67, 0, 0, 42, 67, 0, 0, 184, 66, 0, 0, 42, 67, 0, 0, 186, 66, 0, 0, 42, 67, 0, 0, 188, 66, 0, 0, 42, 67, 0, 0, 190, 66, 0, 0, 42, 67, 0, 0, 192, 66, 0, 0, 42, 67, 0, 0, 194, 66, 0, 0, 42, 67, 0, 0, 196, 66, 0, 0, 42, 67, 0, 0, 198, 66, 0, 0, 42, 67, 0, 0, 200, 66, 0, 0, 42, 67, 0, 0, 202, 66, 0, 0, 42, 67, 0, 0, 204, 66, 0, 0, 42, 67, 0, 0, 206, 66, 0, 0, 42, 67, 0, 0, 208, 66, 0, 0, 42, 67, 0, 0, 210, 66, 0, 0, 42, 67, 0, 0, 212, 66, 0, 0, 42, 67, 0, 0, 214, 66, 0, 0, 42, 67, 0, 0, 216, 66, 0, 0, 42, 67, 0, 0, 218, 66, 0, 0, 42, 67, 0, 0, 220, 66, 0, 0, 42, 67, 0, 0, 222, 66, 0, 0, 42, 67, 0, 0, 224, 66, 0, 0, 42, 67, 0, 0, 226, 66, 0, 0, 42, 67, 0, 0, 228, 66, 0, 0, 42, 67, 0, 0, 230, 66, 0, 0, 42, 67, 0, 0, 232, 66, 0, 0, 42, 67, 0, 0, 234, 66, 0, 0, 42, 67, 0, 0, 236, 66, 0, 0, 42, 67, 0, 0, 238, 66, 0, 0, 42, 67, 0, 0, 240, 66, 0, 0, 42, 67, 0, 0, 242, 66, 0, 0, 42, 67, 0, 0, 244, 66, 0, 0, 42, 67, 0, 0, 246, 66, 0, 0, 42, 67, 0, 0, 248, 66, 0, 0, 42, 67, 0, 0, 250, 66, 0, 0, 42, 67, 0, 0, 252, 66, 0, 0, 42, 67, 0, 0, 254, 66, 0, 0, 42, 67, 0, 0, 0, 67, 0, 0, 42, 67, 0, 0, 1, 67, 0, 0, 42, 67, 0, 0, 2, 67, 0, 0, 42, 67, 0, 0, 3, 67, 0, 0, 42, 67, 0, 0, 4, 67, 0, 0, 42, 67, 0, 0, 5, 67, 0, 0, 42, 67, 0, 0, 6, 67, 0, 0, 42, 67, 0, 0, 7, 67, 0, 0, 42, 67, 0, 0, 8, 67, 0, 0, 42, 67, 0, 0, 9, 67, 0, 0, 42, 67, 0, 0, 10, 67, 0, 0, 42, 67, 0, 0, 11, 67, 0, 0, 42, 67, 0, 0, 12, 67, 0, 0, 42, 67, 0, 0, 13, 67, 0, 0, 42, 67, 0, 0, 14, 67, 0, 0, 42, 67, 0, 0, 15, 67, 0, 0, 42, 67, 0, 0, 16, 67, 0, 0, 42, 67, 0, 0, 17, 67, 0, 0, 42, 67, 0, 0, 18, 67, 0, 0, 42, 67, 0, 0, 19, 67, 0, 0, 42, 67, 0, 0, 20, 67, 0, 0, 42, 67, 0, 0, 21, 67, 0, 0, 42, 67, 0, 0, 22, 67, 0, 0, 42, 67, 0, 0, 23, 67, 0, 0, 42, 67, 0, 0, 24, 67, 0, 0, 42, 67, 0, 0, 25, 67, 0, 0, 42, 67, 0, 0, 26, 67, 0, 0, 42, 67, 0, 0, 27, 67, 0, 0, 42, 67, 0, 0, 28, 67, 0, 0, 42, 67, 0, 0, 29, 67, 0, 0, 42, 67, 0, 0, 30, 67, 0, 0, 42, 67, 0, 0, 31, 67, 0, 0, 42, 67, 0, 0, 32, 67, 0, 0, 42, 67, 0, 0, 33, 67, 0, 0, 42, 67, 0, 0, 34, 67, 0, 0, 42, 67, 0, 0, 35, 67, 0, 0, 42, 67, 0, 0, 36, 67, 0, 0, 42, 67, 0, 0, 37, 67, 0, 0, 42, 67, 0, 0, 38, 67, 0, 0, 42, 67, 0, 0, 39, 67, 0, 0, 42, 67, 0, 0, 40, 67, 0, 0, 42, 67, 0, 0, 41, 67, 0, 0, 42, 67, 0, 0, 42, 67, 0, 0, 42, 67, 0, 0, 43, 67, 0, 0, 42, 67, 0, 0, 44, 67, 0, 0, 42, 67, 0, 0, 45, 67, 0, 0, 42, 67, 0, 0, 46, 67, 0, 0, 42, 67, 0, 0, 47, 67, 0, 0, 42, 67, 0, 0, 48, 67, 0, 0, 42, 67, 0, 0, 49, 67, 0, 0, 42, 67, 0, 0, 50, 67, 0, 0, 42, 67, 0, 0, 51, 67, 0, 0, 42, 67, 0, 0, 52, 67, 0, 0, 42, 67, 0, 0, 53, 67, 0, 0, 42, 67, 0, 0, 54, 67, 0, 0, 42, 67, 0, 0, 55, 67, 0, 0, 43, 67, 0, 0, 184, 66, 0, 0, 43, 67, 0, 0, 186, 66, 0, 0, 43, 67, 0, 0, 188, 66, 0, 0, 43, 67, 0, 0, 190, 66, 0, 0, 43, 67, 0, 0, 192, 66, 0, 0, 43, 67, 0, 0, 194, 66, 0, 0, 43, 67, 0, 0, 196, 66, 0, 0, 43, 67, 0, 0, 198, 66, 0, 0, 43, 67, 0, 0, 200, 66, 0, 0, 43, 67, 0, 0, 202, 66, 0, 0, 43, 67, 0, 0, 204, 66, 0, 0, 43, 67, 0, 0, 206, 66, 0, 0, 43, 67, 0, 0, 208, 66, 0, 0, 43, 67, 0, 0, 210, 66, 0, 0, 43, 67, 0, 0, 212, 66, 0, 0, 43, 67, 0, 0, 214, 66, 0, 0, 43, 67, 0, 0, 216, 66, 0, 0, 43, 67, 0, 0, 218, 66, 0, 0, 43, 67, 0, 0, 220, 66, 0, 0, 43, 67, 0, 0, 222, 66, 0, 0, 43, 67, 0, 0, 224, 66, 0, 0, 43, 67, 0, 0, 226, 66, 0, 0, 43, 67, 0, 0, 228, 66, 0, 0, 43, 67, 0, 0, 230, 66, 0, 0, 43, 67, 0, 0, 232, 66, 0, 0, 43, 67, 0, 0, 234, 66, 0, 0, 43, 67, 0, 0, 236, 66, 0, 0, 43, 67, 0, 0, 238, 66, 0, 0, 43, 67, 0, 0, 240, 66, 0, 0, 43, 67, 0, 0, 242, 66, 0, 0, 43, 67, 0, 0, 244, 66, 0, 0, 43, 67, 0, 0, 246, 66, 0, 0, 43, 67, 0, 0, 248, 66, 0, 0, 43, 67, 0, 0, 250, 66, 0, 0, 43, 67, 0, 0, 252, 66, 0, 0, 43, 67, 0, 0, 254, 66, 0, 0, 43, 67, 0, 0, 0, 67, 0, 0, 43, 67, 0, 0, 1, 67, 0, 0, 43, 67, 0, 0, 2, 67, 0, 0, 43, 67, 0, 0, 3, 67, 0, 0, 43, 67, 0, 0, 4, 67, 0, 0, 43, 67, 0, 0, 5, 67, 0, 0, 43, 67, 0, 0, 6, 67, 0, 0, 43, 67, 0, 0, 7, 67, 0, 0, 43, 67, 0, 0, 8, 67, 0, 0, 43, 67, 0, 0, 9, 67, 0, 0, 43, 67, 0, 0, 10, 67, 0, 0, 43, 67, 0, 0, 11, 67, 0, 0, 43, 67, 0, 0, 12, 67, 0, 0, 43, 67, 0, 0, 13, 67, 0, 0, 43, 67, 0, 0, 14, 67, 0, 0, 43, 67, 0, 0, 15, 67, 0, 0, 43, 67, 0, 0, 16, 67, 0, 0, 43, 67, 0, 0, 17, 67, 0, 0, 43, 67, 0, 0, 18, 67, 0, 0, 43, 67, 0, 0, 19, 67, 0, 0, 43, 67, 0, 0, 20, 67, 0, 0, 43, 67, 0, 0, 21, 67, 0, 0, 43, 67, 0, 0, 22, 67, 0, 0, 43, 67, 0, 0, 23, 67, 0, 0, 43, 67, 0, 0, 24, 67, 0, 0, 43, 67, 0, 0, 25, 67, 0, 0, 43, 67, 0, 0, 26, 67, 0, 0, 43, 67, 0, 0, 27, 67, 0, 0, 43, 67, 0, 0, 28, 67, 0, 0, 43, 67, 0, 0, 29, 67, 0, 0, 43, 67, 0, 0, 30, 67, 0, 0, 43, 67, 0, 0, 31, 67, 0, 0, 43, 67, 0, 0, 32, 67, 0, 0, 43, 67, 0, 0, 33, 67, 0, 0, 43, 67, 0, 0, 34, 67, 0, 0, 43, 67, 0, 0, 35, 67, 0, 0, 43, 67, 0, 0, 36, 67, 0, 0, 43, 67, 0, 0, 37, 67, 0, 0, 43, 67, 0, 0, 38, 67, 0, 0, 43, 67, 0, 0, 39, 67, 0, 0, 43, 67, 0, 0, 40, 67, 0, 0, 43, 67, 0, 0, 41, 67, 0, 0, 43, 67, 0, 0, 42, 67, 0, 0, 43, 67, 0, 0, 43, 67, 0, 0, 43, 67, 0, 0, 44, 67, 0, 0, 43, 67, 0, 0, 45, 67, 0, 0, 43, 67, 0, 0, 46, 67, 0, 0, 43, 67, 0, 0, 47, 67, 0, 0, 43, 67, 0, 0, 48, 67, 0, 0, 43, 67, 0, 0, 49, 67, 0, 0, 43, 67, 0, 0, 50, 67, 0, 0, 43, 67, 0, 0, 51, 67, 0, 0, 43, 67, 0, 0, 52, 67, 0, 0, 43, 67, 0, 0, 53, 67, 0, 0, 43, 67, 0, 0, 54, 67, 0, 0, 43, 67, 0, 0, 55, 67, 0, 0, 44, 67, 0, 0, 184, 66, 0, 0, 44, 67, 0, 0, 186, 66, 0, 0, 44, 67, 0, 0, 188, 66, 0, 0, 44, 67, 0, 0, 190, 66, 0, 0, 44, 67, 0, 0, 192, 66, 0, 0, 44, 67, 0, 0, 194, 66, 0, 0, 44, 67, 0, 0, 196, 66, 0, 0, 44, 67, 0, 0, 198, 66, 0, 0, 44, 67, 0, 0, 200, 66, 0, 0, 44, 67, 0, 0, 202, 66, 0, 0, 44, 67, 0, 0, 204, 66, 0, 0, 44, 67, 0, 0, 206, 66, 0, 0, 44, 67, 0, 0, 208, 66, 0, 0, 44, 67, 0, 0, 210, 66, 0, 0, 44, 67, 0, 0, 212, 66, 0, 0, 44, 67, 0, 0, 214, 66, 0, 0, 44, 67, 0, 0, 216, 66, 0, 0, 44, 67, 0, 0, 218, 66, 0, 0, 44, 67, 0, 0, 220, 66, 0, 0, 44, 67, 0, 0, 222, 66, 0, 0, 44, 67, 0, 0, 224, 66, 0, 0, 44, 67, 0, 0, 226, 66, 0, 0, 44, 67, 0, 0, 228, 66, 0, 0, 44, 67, 0, 0, 230, 66, 0, 0, 44, 67, 0, 0, 232, 66, 0, 0, 44, 67, 0, 0, 234, 66, 0, 0, 44, 67, 0, 0, 236, 66, 0, 0, 44, 67, 0, 0, 238, 66, 0, 0, 44, 67, 0, 0, 240, 66, 0, 0, 44, 67, 0, 0, 242, 66, 0, 0, 44, 67, 0, 0, 244, 66, 0, 0, 44, 67, 0, 0, 246, 66, 0, 0, 44, 67, 0, 0, 248, 66, 0, 0, 44, 67, 0, 0, 250, 66, 0, 0, 44, 67, 0, 0, 252, 66, 0, 0, 44, 67, 0, 0, 254, 66, 0, 0, 44, 67, 0, 0, 0, 67, 0, 0, 44, 67, 0, 0, 1, 67, 0, 0, 44, 67, 0, 0, 2, 67, 0, 0, 44, 67, 0, 0, 3, 67, 0, 0, 44, 67, 0, 0, 4, 67, 0, 0, 44, 67, 0, 0, 5, 67, 0, 0, 44, 67, 0, 0, 6, 67, 0, 0, 44, 67, 0, 0, 7, 67, 0, 0, 44, 67, 0, 0, 8, 67, 0, 0, 44, 67, 0, 0, 9, 67, 0, 0, 44, 67, 0, 0, 10, 67, 0, 0, 44, 67, 0, 0, 11, 67, 0, 0, 44, 67, 0, 0, 12, 67, 0, 0, 44, 67, 0, 0, 13, 67, 0, 0, 44, 67, 0, 0, 14, 67, 0, 0, 44, 67, 0, 0, 15, 67, 0, 0, 44, 67, 0, 0, 16, 67, 0, 0, 44, 67, 0, 0, 17, 67, 0, 0, 44, 67, 0, 0, 18, 67, 0, 0, 44, 67, 0, 0, 19, 67, 0, 0, 44, 67, 0, 0, 20, 67, 0, 0, 44, 67, 0, 0, 21, 67, 0, 0, 44, 67, 0, 0, 22, 67, 0, 0, 44, 67, 0, 0, 23, 67, 0, 0, 44, 67, 0, 0, 24, 67, 0, 0, 44, 67, 0, 0, 25, 67, 0, 0, 44, 67, 0, 0, 26, 67, 0, 0, 44, 67, 0, 0, 27, 67, 0, 0, 44, 67, 0, 0, 28, 67, 0, 0, 44, 67, 0, 0, 29, 67, 0, 0, 44, 67, 0, 0, 30, 67, 0, 0, 44, 67, 0, 0, 31, 67, 0, 0, 44, 67, 0, 0, 32, 67, 0, 0, 44, 67, 0, 0, 33, 67, 0, 0, 44, 67, 0, 0, 34, 67, 0, 0, 44, 67, 0, 0, 35, 67, 0, 0, 44, 67, 0, 0, 36, 67, 0, 0, 44, 67, 0, 0, 37, 67, 0, 0, 44, 67, 0, 0, 38, 67, 0, 0, 44, 67, 0, 0, 39, 67, 0, 0, 44, 67, 0, 0, 40, 67, 0, 0, 44, 67, 0, 0, 41, 67, 0, 0, 44, 67, 0, 0, 42, 67, 0, 0, 44, 67, 0, 0, 43, 67, 0, 0, 44, 67, 0, 0, 44, 67, 0, 0, 44, 67, 0, 0, 45, 67, 0, 0, 44, 67, 0, 0, 46, 67, 0, 0, 44, 67, 0, 0, 47, 67, 0, 0, 44, 67, 0, 0, 48, 67, 0, 0, 44, 67, 0, 0, 49, 67, 0, 0, 44, 67, 0, 0, 50, 67, 0, 0, 44, 67, 0, 0, 51, 67, 0, 0, 44, 67, 0, 0, 52, 67, 0, 0, 44, 67, 0, 0, 53, 67, 0, 0, 44, 67, 0, 0, 54, 67, 0, 0, 44, 67, 0, 0, 55, 67, 0, 0, 45, 67, 0, 0, 184, 66, 0, 0, 45, 67, 0, 0, 186, 66, 0, 0, 45, 67, 0, 0, 188, 66, 0, 0, 45, 67, 0, 0, 190, 66, 0, 0, 45, 67, 0, 0, 192, 66, 0, 0, 45, 67, 0, 0, 194, 66, 0, 0, 45, 67, 0, 0, 196, 66, 0, 0, 45, 67, 0, 0, 198, 66, 0, 0, 45, 67, 0, 0, 200, 66, 0, 0, 45, 67, 0, 0, 202, 66, 0, 0, 45, 67, 0, 0, 204, 66, 0, 0, 45, 67, 0, 0, 206, 66, 0, 0, 45, 67, 0, 0, 208, 66, 0, 0, 45, 67, 0, 0, 210, 66, 0, 0, 45, 67, 0, 0, 212, 66, 0, 0, 45, 67, 0, 0, 214, 66, 0, 0, 45, 67, 0, 0, 216, 66, 0, 0, 45, 67, 0, 0, 218, 66, 0, 0, 45, 67, 0, 0, 220, 66, 0, 0, 45, 67, 0, 0, 222, 66, 0, 0, 45, 67, 0, 0, 224, 66, 0, 0, 45, 67, 0, 0, 226, 66, 0, 0, 45, 67, 0, 0, 228, 66, 0, 0, 45, 67, 0, 0, 230, 66, 0, 0, 45, 67, 0, 0, 232, 66, 0, 0, 45, 67, 0, 0, 234, 66, 0, 0, 45, 67, 0, 0, 236, 66, 0, 0, 45, 67, 0, 0, 238, 66, 0, 0, 45, 67, 0, 0, 240, 66, 0, 0, 45, 67, 0, 0, 242, 66, 0, 0, 45, 67, 0, 0, 244, 66, 0, 0, 45, 67, 0, 0, 246, 66, 0, 0, 45, 67, 0, 0, 248, 66, 0, 0, 45, 67, 0, 0, 250, 66, 0, 0, 45, 67, 0, 0, 252, 66, 0, 0, 45, 67, 0, 0, 254, 66, 0, 0, 45, 67, 0, 0, 0, 67, 0, 0, 45, 67, 0, 0, 1, 67, 0, 0, 45, 67, 0, 0, 2, 67, 0, 0, 45, 67, 0, 0, 3, 67, 0, 0, 45, 67, 0, 0, 4, 67, 0, 0, 45, 67, 0, 0, 5, 67, 0, 0, 45, 67, 0, 0, 6, 67, 0, 0, 45, 67, 0, 0, 7, 67, 0, 0, 45, 67, 0, 0, 8, 67, 0, 0, 45, 67, 0, 0, 9, 67, 0, 0, 45, 67, 0, 0, 10, 67, 0, 0, 45, 67, 0, 0, 11, 67, 0, 0, 45, 67, 0, 0, 12, 67, 0, 0, 45, 67, 0, 0, 13, 67, 0, 0, 45, 67, 0, 0, 14, 67, 0, 0, 45, 67, 0, 0, 15, 67, 0, 0, 45, 67, 0, 0, 16, 67, 0, 0, 45, 67, 0, 0, 17, 67, 0, 0, 45, 67, 0, 0, 18, 67, 0, 0, 45, 67, 0, 0, 19, 67, 0, 0, 45, 67, 0, 0, 20, 67, 0, 0, 45, 67, 0, 0, 21, 67, 0, 0, 45, 67, 0, 0, 22, 67, 0, 0, 45, 67, 0, 0, 23, 67, 0, 0, 45, 67, 0, 0, 24, 67, 0, 0, 45, 67, 0, 0, 25, 67, 0, 0, 45, 67, 0, 0, 26, 67, 0, 0, 45, 67, 0, 0, 27, 67, 0, 0, 45, 67, 0, 0, 28, 67, 0, 0, 45, 67, 0, 0, 29, 67, 0, 0, 45, 67, 0, 0, 30, 67, 0, 0, 45, 67, 0, 0, 31, 67, 0, 0, 45, 67, 0, 0, 32, 67, 0, 0, 45, 67, 0, 0, 33, 67, 0, 0, 45, 67, 0, 0, 34, 67, 0, 0, 45, 67, 0, 0, 35, 67, 0, 0, 45, 67, 0, 0, 36, 67, 0, 0, 45, 67, 0, 0, 37, 67, 0, 0, 45, 67, 0, 0, 38, 67, 0, 0, 45, 67, 0, 0, 39, 67, 0, 0, 45, 67, 0, 0, 40, 67, 0, 0, 45, 67, 0, 0, 41, 67, 0, 0, 45, 67, 0, 0, 42, 67, 0, 0, 45, 67, 0, 0, 43, 67, 0, 0, 45, 67, 0, 0, 44, 67, 0, 0, 45, 67, 0, 0, 45, 67, 0, 0, 45, 67, 0, 0, 46, 67, 0, 0, 45, 67, 0, 0, 47, 67, 0, 0, 45, 67, 0, 0, 48, 67, 0, 0, 45, 67, 0, 0, 49, 67, 0, 0, 45, 67, 0, 0, 50, 67, 0, 0, 45, 67, 0, 0, 51, 67, 0, 0, 45, 67, 0, 0, 52, 67, 0, 0, 45, 67, 0, 0, 53, 67, 0, 0, 45, 67, 0, 0, 54, 67, 0, 0, 45, 67, 0, 0, 55, 67, 0, 0, 46, 67, 0, 0, 184, 66, 0, 0, 46, 67, 0, 0, 186, 66, 0, 0, 46, 67, 0, 0, 188, 66, 0, 0, 46, 67, 0, 0, 190, 66, 0, 0, 46, 67, 0, 0, 192, 66, 0, 0, 46, 67, 0, 0, 194, 66, 0, 0, 46, 67, 0, 0, 196, 66, 0, 0, 46, 67, 0, 0, 198, 66, 0, 0, 46, 67, 0, 0, 200, 66, 0, 0, 46, 67, 0, 0, 202, 66, 0, 0, 46, 67, 0, 0, 204, 66, 0, 0, 46, 67, 0, 0, 206, 66, 0, 0, 46, 67, 0, 0, 208, 66, 0, 0, 46, 67, 0, 0, 210, 66, 0, 0, 46, 67, 0, 0, 212, 66, 0, 0, 46, 67, 0, 0, 214, 66, 0, 0, 46, 67, 0, 0, 40, 67, 0, 0, 46, 67, 0, 0, 41, 67, 0, 0, 46, 67, 0, 0, 42, 67, 0, 0, 46, 67, 0, 0, 43, 67, 0, 0, 46, 67, 0, 0, 44, 67, 0, 0, 46, 67, 0, 0, 45, 67, 0, 0, 46, 67, 0, 0, 46, 67, 0, 0, 46, 67, 0, 0, 47, 67, 0, 0, 46, 67, 0, 0, 48, 67, 0, 0, 46, 67, 0, 0, 49, 67, 0, 0, 46, 67, 0, 0, 50, 67, 0, 0, 46, 67, 0, 0, 51, 67, 0, 0, 46, 67, 0, 0, 52, 67, 0, 0, 46, 67, 0, 0, 53, 67, 0, 0, 46, 67, 0, 0, 54, 67, 0, 0, 46, 67, 0, 0, 55, 67, 0, 0, 47, 67, 0, 0, 184, 66, 0, 0, 47, 67, 0, 0, 186, 66, 0, 0, 47, 67, 0, 0, 188, 66, 0, 0, 47, 67, 0, 0, 190, 66, 0, 0, 47, 67, 0, 0, 192, 66, 0, 0, 47, 67, 0, 0, 194, 66, 0, 0, 47, 67, 0, 0, 196, 66, 0, 0, 47, 67, 0, 0, 198, 66, 0, 0, 47, 67, 0, 0, 200, 66, 0, 0, 47, 67, 0, 0, 202, 66, 0, 0, 47, 67, 0, 0, 204, 66, 0, 0, 47, 67, 0, 0, 206, 66, 0, 0, 47, 67, 0, 0, 208, 66, 0, 0, 47, 67, 0, 0, 210, 66, 0, 0, 47, 67, 0, 0, 42, 67, 0, 0, 47, 67, 0, 0, 43, 67, 0, 0, 47, 67, 0, 0, 44, 67, 0, 0, 47, 67, 0, 0, 45, 67, 0, 0, 47, 67, 0, 0, 46, 67, 0, 0, 47, 67, 0, 0, 47, 67, 0, 0, 47, 67, 0, 0, 48, 67, 0, 0, 47, 67, 0, 0, 49, 67, 0, 0, 47, 67, 0, 0, 50, 67, 0, 0, 47, 67, 0, 0, 51, 67, 0, 0, 47, 67, 0, 0, 52, 67, 0, 0, 47, 67, 0, 0, 53, 67, 0, 0, 47, 67, 0, 0, 54, 67, 0, 0, 47, 67, 0, 0, 55, 67, 0, 0, 48, 67, 0, 0, 184, 66, 0, 0, 48, 67, 0, 0, 186, 66, 0, 0, 48, 67, 0, 0, 188, 66, 0, 0, 48, 67, 0, 0, 190, 66, 0, 0, 48, 67, 0, 0, 192, 66, 0, 0, 48, 67, 0, 0, 194, 66, 0, 0, 48, 67, 0, 0, 196, 66, 0, 0, 48, 67, 0, 0, 198, 66, 0, 0, 48, 67, 0, 0, 200, 66, 0, 0, 48, 67, 0, 0, 202, 66, 0, 0, 48, 67, 0, 0, 204, 66, 0, 0, 48, 67, 0, 0, 206, 66, 0, 0, 48, 67, 0, 0, 208, 66, 0, 0, 48, 67, 0, 0, 43, 67, 0, 0, 48, 67, 0, 0, 44, 67, 0, 0, 48, 67, 0, 0, 45, 67, 0, 0, 48, 67, 0, 0, 46, 67, 0, 0, 48, 67, 0, 0, 47, 67, 0, 0, 48, 67, 0, 0, 48, 67, 0, 0, 48, 67, 0, 0, 49, 67, 0, 0, 48, 67, 0, 0, 50, 67, 0, 0, 48, 67, 0, 0, 51, 67, 0, 0, 48, 67, 0, 0, 52, 67, 0, 0, 48, 67, 0, 0, 53, 67, 0, 0, 48, 67, 0, 0, 54, 67, 0, 0, 48, 67, 0, 0, 55, 67, 0, 0, 49, 67, 0, 0, 184, 66, 0, 0, 49, 67, 0, 0, 186, 66, 0, 0, 49, 67, 0, 0, 188, 66, 0, 0, 49, 67, 0, 0, 190, 66, 0, 0, 49, 67, 0, 0, 192, 66, 0, 0, 49, 67, 0, 0, 194, 66, 0, 0, 49, 67, 0, 0, 196, 66, 0, 0, 49, 67, 0, 0, 198, 66, 0, 0, 49, 67, 0, 0, 200, 66, 0, 0, 49, 67, 0, 0, 202, 66, 0, 0, 49, 67, 0, 0, 204, 66, 0, 0, 49, 67, 0, 0, 206, 66, 0, 0, 49, 67, 0, 0, 44, 67, 0, 0, 49, 67, 0, 0, 45, 67, 0, 0, 49, 67, 0, 0, 46, 67, 0, 0, 49, 67, 0, 0, 47, 67, 0, 0, 49, 67, 0, 0, 48, 67, 0, 0, 49, 67, 0, 0, 49, 67, 0, 0, 49, 67, 0, 0, 50, 67, 0, 0, 49, 67, 0, 0, 51, 67, 0, 0, 49, 67, 0, 0, 52, 67, 0, 0, 49, 67, 0, 0, 53, 67, 0, 0, 49, 67, 0, 0, 54, 67, 0, 0, 49, 67, 0, 0, 55, 67, 0, 0, 50, 67, 0, 0, 184, 66, 0, 0, 50, 67, 0, 0, 186, 66, 0, 0, 50, 67, 0, 0, 188, 66, 0, 0, 50, 67, 0, 0, 190, 66, 0, 0, 50, 67, 0, 0, 192, 66, 0, 0, 50, 67, 0, 0, 194, 66, 0, 0, 50, 67, 0, 0, 196, 66, 0, 0, 50, 67, 0, 0, 198, 66, 0, 0, 50, 67, 0, 0, 200, 66, 0, 0, 50, 67, 0, 0, 202, 66, 0, 0, 50, 67, 0, 0, 204, 66, 0, 0, 50, 67, 0, 0, 206, 66, 0, 0, 50, 67, 0, 0, 44, 67, 0, 0, 50, 67, 0, 0, 45, 67, 0, 0, 50, 67, 0, 0, 46, 67, 0, 0, 50, 67, 0, 0, 47, 67, 0, 0, 50, 67, 0, 0, 48, 67, 0, 0, 50, 67, 0, 0, 49, 67, 0, 0, 50, 67, 0, 0, 50, 67, 0, 0, 50, 67, 0, 0, 51, 67, 0, 0, 50, 67, 0, 0, 52, 67, 0, 0, 50, 67, 0, 0, 53, 67, 0, 0, 50, 67, 0, 0, 54, 67, 0, 0, 50, 67, 0, 0, 55, 67, 0, 0, 51, 67, 0, 0, 184, 66, 0, 0, 51, 67, 0, 0, 186, 66, 0, 0, 51, 67, 0, 0, 188, 66, 0, 0, 51, 67, 0, 0, 190, 66, 0, 0, 51, 67, 0, 0, 192, 66, 0, 0, 51, 67, 0, 0, 194, 66, 0, 0, 51, 67, 0, 0, 196, 66, 0, 0, 51, 67, 0, 0, 198, 66, 0, 0, 51, 67, 0, 0, 200, 66, 0, 0, 51, 67, 0, 0, 202, 66, 0, 0, 51, 67, 0, 0, 204, 66, 0, 0, 51, 67, 0, 0, 206, 66, 0, 0, 51, 67, 0, 0, 44, 67, 0, 0, 51, 67, 0, 0, 45, 67, 0, 0, 51, 67, 0, 0, 46, 67, 0, 0, 51, 67, 0, 0, 47, 67, 0, 0, 51, 67, 0, 0, 48, 67, 0, 0, 51, 67, 0, 0, 49, 67, 0, 0, 51, 67, 0, 0, 50, 67, 0, 0, 51, 67, 0, 0, 51, 67, 0, 0, 51, 67, 0, 0, 52, 67, 0, 0, 51, 67, 0, 0, 53, 67, 0, 0, 51, 67, 0, 0, 54, 67, 0, 0, 51, 67, 0, 0, 55, 67, 0, 0, 52, 67, 0, 0, 184, 66, 0, 0, 52, 67, 0, 0, 186, 66, 0, 0, 52, 67, 0, 0, 188, 66, 0, 0, 52, 67, 0, 0, 190, 66, 0, 0, 52, 67, 0, 0, 192, 66, 0, 0, 52, 67, 0, 0, 194, 66, 0, 0, 52, 67, 0, 0, 196, 66, 0, 0, 52, 67, 0, 0, 198, 66, 0, 0, 52, 67, 0, 0, 200, 66, 0, 0, 52, 67, 0, 0, 202, 66, 0, 0, 52, 67, 0, 0, 204, 66, 0, 0, 52, 67, 0, 0, 206, 66, 0, 0, 52, 67, 0, 0, 44, 67, 0, 0, 52, 67, 0, 0, 45, 67, 0, 0, 52, 67, 0, 0, 46, 67, 0, 0, 52, 67, 0, 0, 47, 67, 0, 0, 52, 67, 0, 0, 48, 67, 0, 0, 52, 67, 0, 0, 49, 67, 0, 0, 52, 67, 0, 0, 50, 67, 0, 0, 52, 67, 0, 0, 51, 67, 0, 0, 52, 67, 0, 0, 52, 67, 0, 0, 52, 67, 0, 0, 53, 67, 0, 0, 52, 67, 0, 0, 54, 67, 0, 0, 52, 67, 0, 0, 55, 67, 0, 0, 53, 67, 0, 0, 184, 66, 0, 0, 53, 67, 0, 0, 186, 66, 0, 0, 53, 67, 0, 0, 188, 66, 0, 0, 53, 67, 0, 0, 190, 66, 0, 0, 53, 67, 0, 0, 192, 66, 0, 0, 53, 67, 0, 0, 194, 66, 0, 0, 53, 67, 0, 0, 196, 66, 0, 0, 53, 67, 0, 0, 198, 66, 0, 0, 53, 67, 0, 0, 200, 66, 0, 0, 53, 67, 0, 0, 202, 66, 0, 0, 53, 67, 0, 0, 204, 66, 0, 0, 53, 67, 0, 0, 206, 66, 0, 0, 53, 67, 0, 0, 45, 67, 0, 0, 53, 67, 0, 0, 46, 67, 0, 0, 53, 67, 0, 0, 47, 67, 0, 0, 53, 67, 0, 0, 48, 67, 0, 0, 53, 67, 0, 0, 49, 67, 0, 0, 53, 67, 0, 0, 50, 67, 0, 0, 53, 67, 0, 0, 51, 67, 0, 0, 53, 67, 0, 0, 52, 67, 0, 0, 53, 67, 0, 0, 53, 67, 0, 0, 53, 67, 0, 0, 54, 67, 0, 0, 53, 67, 0, 0, 55, 67, 0, 0, 54, 67, 0, 0, 184, 66, 0, 0, 54, 67, 0, 0, 186, 66, 0, 0, 54, 67, 0, 0, 188, 66, 0, 0, 54, 67, 0, 0, 190, 66, 0, 0, 54, 67, 0, 0, 192, 66, 0, 0, 54, 67, 0, 0, 194, 66, 0, 0, 54, 67, 0, 0, 196, 66, 0, 0, 54, 67, 0, 0, 198, 66, 0, 0, 54, 67, 0, 0, 200, 66, 0, 0, 54, 67, 0, 0, 202, 66, 0, 0, 54, 67, 0, 0, 204, 66, 0, 0, 54, 67, 0, 0, 45, 67, 0, 0, 54, 67, 0, 0, 46, 67, 0, 0, 54, 67, 0, 0, 47, 67, 0, 0, 54, 67, 0, 0, 48, 67, 0, 0, 54, 67, 0, 0, 49, 67, 0, 0, 54, 67, 0, 0, 50, 67, 0, 0, 54, 67, 0, 0, 51, 67, 0, 0, 54, 67, 0, 0, 52, 67, 0, 0, 54, 67, 0, 0, 53, 67, 0, 0, 54, 67, 0, 0, 54, 67, 0, 0, 54, 67, 0, 0, 55, 67, 0, 0, 55, 67, 0, 0, 184, 66, 0, 0, 55, 67, 0, 0, 186, 66, 0, 0, 55, 67, 0, 0, 188, 66, 0, 0, 55, 67, 0, 0, 190, 66, 0, 0, 55, 67, 0, 0, 192, 66, 0, 0, 55, 67, 0, 0, 194, 66, 0, 0, 55, 67, 0, 0, 196, 66, 0, 0, 55, 67, 0, 0, 198, 66, 0, 0, 55, 67, 0, 0, 200, 66, 0, 0, 55, 67, 0, 0, 202, 66, 0, 0, 55, 67, 0, 0, 204, 66, 0, 0, 55, 67, 0, 0, 45, 67, 0, 0, 55, 67, 0, 0, 46, 67, 0, 0, 55, 67, 0, 0, 47, 67, 0, 0, 55, 67, 0, 0, 48, 67, 0, 0, 55, 67, 0, 0, 49, 67, 0, 0, 55, 67, 0, 0, 50, 67, 0, 0, 55, 67, 0, 0, 51, 67, 0, 0, 55, 67, 0, 0, 52, 67, 0, 0, 55, 67, 0, 0, 53, 67, 0, 0, 55, 67, 0, 0, 54, 67, 0, 0, 55, 67, 0, 0, 55, 67, 0, 0, 56, 67, 0, 0, 184, 66, 0, 0, 56, 67, 0, 0, 186, 66, 0, 0, 56, 67, 0, 0, 188, 66, 0, 0, 56, 67, 0, 0, 190, 66, 0, 0, 56, 67, 0, 0, 192, 66, 0, 0, 56, 67, 0, 0, 194, 66, 0, 0, 56, 67, 0, 0, 196, 66, 0, 0, 56, 67, 0, 0, 198, 66, 0, 0, 56, 67, 0, 0, 200, 66, 0, 0, 56, 67, 0, 0, 202, 66, 0, 0, 56, 67, 0, 0, 204, 66, 0, 0, 56, 67, 0, 0, 45, 67, 0, 0, 56, 67, 0, 0, 46, 67, 0, 0, 56, 67, 0, 0, 47, 67, 0, 0, 56, 67, 0, 0, 48, 67, 0, 0, 56, 67, 0, 0, 49, 67, 0, 0, 56, 67, 0, 0, 50, 67, 0, 0, 56, 67, 0, 0, 51, 67, 0, 0, 56, 67, 0, 0, 52, 67, 0, 0, 56, 67, 0, 0, 53, 67, 0, 0, 56, 67, 0, 0, 54, 67, 0, 0, 56, 67, 0, 0, 55, 67, 0, 0, 57, 67, 0, 0, 184, 66, 0, 0, 57, 67, 0, 0, 186, 66, 0, 0, 57, 67, 0, 0, 188, 66, 0, 0, 57, 67, 0, 0, 190, 66, 0, 0, 57, 67, 0, 0, 192, 66, 0, 0, 57, 67, 0, 0, 194, 66, 0, 0, 57, 67, 0, 0, 196, 66, 0, 0, 57, 67, 0, 0, 198, 66, 0, 0, 57, 67, 0, 0, 200, 66, 0, 0, 57, 67, 0, 0, 202, 66, 0, 0, 57, 67, 0, 0, 46, 67, 0, 0, 57, 67, 0, 0, 47, 67, 0, 0, 57, 67, 0, 0, 48, 67, 0, 0, 57, 67, 0, 0, 49, 67, 0, 0, 57, 67, 0, 0, 50, 67, 0, 0, 57, 67, 0, 0, 51, 67, 0, 0, 57, 67, 0, 0, 52, 67, 0, 0, 57, 67, 0, 0, 53, 67, 0, 0, 57, 67, 0, 0, 54, 67, 0, 0, 57, 67, 0, 0, 55, 67, 0, 0, 72, 67, 0, 0, 198, 66, 0, 0, 72, 67, 0, 0, 200, 66, 0, 0, 72, 67, 0, 0, 202, 66, 0, 0, 72, 67, 0, 0, 204, 66, 0, 0, 72, 67, 0, 0, 206, 66, 0, 0, 72, 67, 0, 0, 208, 66, 0, 0, 72, 67, 0, 0, 210, 66, 0, 0, 72, 67, 0, 0, 212, 66, 0, 0, 72, 67, 0, 0, 214, 66, 0, 0, 72, 67, 0, 0, 216, 66, 0, 0, 72, 67, 0, 0, 218, 66, 0, 0, 72, 67, 0, 0, 220, 66, 0, 0, 72, 67, 0, 0, 222, 66, 0, 0, 72, 67, 0, 0, 42, 67, 0, 0, 72, 67, 0, 0, 43, 67, 0, 0, 72, 67, 0, 0, 44, 67, 0, 0, 72, 67, 0, 0, 45, 67, 0, 0, 72, 67, 0, 0, 46, 67, 0, 0, 72, 67, 0, 0, 47, 67, 0, 0, 72, 67, 0, 0, 48, 67, 0, 0, 72, 67, 0, 0, 49, 67, 0, 0, 73, 67, 0, 0, 196, 66, 0, 0, 73, 67, 0, 0, 198, 66, 0, 0, 73, 67, 0, 0, 200, 66, 0, 0, 73, 67, 0, 0, 202, 66, 0, 0, 73, 67, 0, 0, 204, 66, 0, 0, 73, 67, 0, 0, 206, 66, 0, 0, 73, 67, 0, 0, 208, 66, 0, 0, 73, 67, 0, 0, 210, 66, 0, 0, 73, 67, 0, 0, 212, 66, 0, 0, 73, 67, 0, 0, 214, 66, 0, 0, 73, 67, 0, 0, 216, 66, 0, 0, 73, 67, 0, 0, 218, 66, 0, 0, 73, 67, 0, 0, 220, 66, 0, 0, 73, 67, 0, 0, 222, 66, 0, 0, 73, 67, 0, 0, 224, 66, 0, 0, 73, 67, 0, 0, 226, 66, 0, 0, 73, 67, 0, 0, 228, 66, 0, 0, 73, 67, 0, 0, 230, 66, 0, 0, 73, 67, 0, 0, 41, 67, 0, 0, 73, 67, 0, 0, 42, 67, 0, 0, 73, 67, 0, 0, 43, 67, 0, 0, 73, 67, 0, 0, 44, 67, 0, 0, 73, 67, 0, 0, 45, 67, 0, 0, 73, 67, 0, 0, 46, 67, 0, 0, 73, 67, 0, 0, 47, 67, 0, 0, 73, 67, 0, 0, 48, 67, 0, 0, 73, 67, 0, 0, 49, 67, 0, 0, 73, 67, 0, 0, 50, 67, 0, 0, 74, 67, 0, 0, 190, 66, 0, 0, 74, 67, 0, 0, 192, 66, 0, 0, 74, 67, 0, 0, 194, 66, 0, 0, 74, 67, 0, 0, 196, 66, 0, 0, 74, 67, 0, 0, 198, 66, 0, 0, 74, 67, 0, 0, 200, 66, 0, 0, 74, 67, 0, 0, 202, 66, 0, 0, 74, 67, 0, 0, 204, 66, 0, 0, 74, 67, 0, 0, 206, 66, 0, 0, 74, 67, 0, 0, 208, 66, 0, 0, 74, 67, 0, 0, 210, 66, 0, 0, 74, 67, 0, 0, 212, 66, 0, 0, 74, 67, 0, 0, 214, 66, 0, 0, 74, 67, 0, 0, 216, 66, 0, 0, 74, 67, 0, 0, 218, 66, 0, 0, 74, 67, 0, 0, 220, 66, 0, 0, 74, 67, 0, 0, 222, 66, 0, 0, 74, 67, 0, 0, 224, 66, 0, 0, 74, 67, 0, 0, 226, 66, 0, 0, 74, 67, 0, 0, 228, 66, 0, 0, 74, 67, 0, 0, 230, 66, 0, 0, 74, 67, 0, 0, 232, 66, 0, 0, 74, 67, 0, 0, 234, 66, 0, 0, 74, 67, 0, 0, 236, 66, 0, 0, 74, 67, 0, 0, 238, 66, 0, 0, 74, 67, 0, 0, 240, 66, 0, 0, 74, 67, 0, 0, 242, 66, 0, 0, 74, 67, 0, 0, 244, 66, 0, 0, 74, 67, 0, 0, 246, 66, 0, 0, 74, 67, 0, 0, 39, 67, 0, 0, 74, 67, 0, 0, 40, 67, 0, 0, 74, 67, 0, 0, 41, 67, 0, 0, 74, 67, 0, 0, 42, 67, 0, 0, 74, 67, 0, 0, 43, 67, 0, 0, 74, 67, 0, 0, 44, 67, 0, 0, 74, 67, 0, 0, 45, 67, 0, 0, 74, 67, 0, 0, 46, 67, 0, 0, 74, 67, 0, 0, 47, 67, 0, 0, 74, 67, 0, 0, 48, 67, 0, 0, 74, 67, 0, 0, 49, 67, 0, 0, 74, 67, 0, 0, 50, 67, 0, 0, 74, 67, 0, 0, 51, 67, 0, 0, 74, 67, 0, 0, 52, 67, 0, 0, 75, 67, 0, 0, 188, 66, 0, 0, 75, 67, 0, 0, 190, 66, 0, 0, 75, 67, 0, 0, 192, 66, 0, 0, 75, 67, 0, 0, 194, 66, 0, 0, 75, 67, 0, 0, 196, 66, 0, 0, 75, 67, 0, 0, 198, 66, 0, 0, 75, 67, 0, 0, 200, 66, 0, 0, 75, 67, 0, 0, 202, 66, 0, 0, 75, 67, 0, 0, 204, 66, 0, 0, 75, 67, 0, 0, 206, 66, 0, 0, 75, 67, 0, 0, 208, 66, 0, 0, 75, 67, 0, 0, 210, 66, 0, 0, 75, 67, 0, 0, 212, 66, 0, 0, 75, 67, 0, 0, 214, 66, 0, 0, 75, 67, 0, 0, 216, 66, 0, 0, 75, 67, 0, 0, 218, 66, 0, 0, 75, 67, 0, 0, 220, 66, 0, 0, 75, 67, 0, 0, 222, 66, 0, 0, 75, 67, 0, 0, 224, 66, 0, 0, 75, 67, 0, 0, 226, 66, 0, 0, 75, 67, 0, 0, 228, 66, 0, 0, 75, 67, 0, 0, 230, 66, 0, 0, 75, 67, 0, 0, 232, 66, 0, 0, 75, 67, 0, 0, 234, 66, 0, 0, 75, 67, 0, 0, 236, 66, 0, 0, 75, 67, 0, 0, 238, 66, 0, 0, 75, 67, 0, 0, 240, 66, 0, 0, 75, 67, 0, 0, 242, 66, 0, 0, 75, 67, 0, 0, 244, 66, 0, 0, 75, 67, 0, 0, 246, 66, 0, 0, 75, 67, 0, 0, 248, 66, 0, 0, 75, 67, 0, 0, 250, 66, 0, 0, 75, 67, 0, 0, 252, 66, 0, 0, 75, 67, 0, 0, 254, 66, 0, 0, 75, 67, 0, 0, 38, 67, 0, 0, 75, 67, 0, 0, 39, 67, 0, 0, 75, 67, 0, 0, 40, 67, 0, 0, 75, 67, 0, 0, 41, 67, 0, 0, 75, 67, 0, 0, 42, 67, 0, 0, 75, 67, 0, 0, 43, 67, 0, 0, 75, 67, 0, 0, 44, 67, 0, 0, 75, 67, 0, 0, 45, 67, 0, 0, 75, 67, 0, 0, 46, 67, 0, 0, 75, 67, 0, 0, 47, 67, 0, 0, 75, 67, 0, 0, 48, 67, 0, 0, 75, 67, 0, 0, 49, 67, 0, 0, 75, 67, 0, 0, 50, 67, 0, 0, 75, 67, 0, 0, 51, 67, 0, 0, 75, 67, 0, 0, 52, 67, 0, 0, 75, 67, 0, 0, 53, 67, 0, 0, 76, 67, 0, 0, 186, 66, 0, 0, 76, 67, 0, 0, 188, 66, 0, 0, 76, 67, 0, 0, 190, 66, 0, 0, 76, 67, 0, 0, 192, 66, 0, 0, 76, 67, 0, 0, 194, 66, 0, 0, 76, 67, 0, 0, 196, 66, 0, 0, 76, 67, 0, 0, 198, 66, 0, 0, 76, 67, 0, 0, 200, 66, 0, 0, 76, 67, 0, 0, 202, 66, 0, 0, 76, 67, 0, 0, 204, 66, 0, 0, 76, 67, 0, 0, 206, 66, 0, 0, 76, 67, 0, 0, 208, 66, 0, 0, 76, 67, 0, 0, 210, 66, 0, 0, 76, 67, 0, 0, 212, 66, 0, 0, 76, 67, 0, 0, 214, 66, 0, 0, 76, 67, 0, 0, 216, 66, 0, 0, 76, 67, 0, 0, 218, 66, 0, 0, 76, 67, 0, 0, 220, 66, 0, 0, 76, 67, 0, 0, 222, 66, 0, 0, 76, 67, 0, 0, 224, 66, 0, 0, 76, 67, 0, 0, 226, 66, 0, 0, 76, 67, 0, 0, 228, 66, 0, 0, 76, 67, 0, 0, 230, 66, 0, 0, 76, 67, 0, 0, 232, 66, 0, 0, 76, 67, 0, 0, 234, 66, 0, 0, 76, 67, 0, 0, 236, 66, 0, 0, 76, 67, 0, 0, 238, 66, 0, 0, 76, 67, 0, 0, 240, 66, 0, 0, 76, 67, 0, 0, 242, 66, 0, 0, 76, 67, 0, 0, 244, 66, 0, 0, 76, 67, 0, 0, 246, 66, 0, 0, 76, 67, 0, 0, 248, 66, 0, 0, 76, 67, 0, 0, 250, 66, 0, 0, 76, 67, 0, 0, 252, 66, 0, 0, 76, 67, 0, 0, 254, 66, 0, 0, 76, 67, 0, 0, 0, 67, 0, 0, 76, 67, 0, 0, 1, 67, 0, 0, 76, 67, 0, 0, 2, 67, 0, 0, 76, 67, 0, 0, 3, 67, 0, 0, 76, 67, 0, 0, 4, 67, 0, 0, 76, 67, 0, 0, 5, 67, 0, 0, 76, 67, 0, 0, 6, 67, 0, 0, 76, 67, 0, 0, 7, 67, 0, 0, 76, 67, 0, 0, 8, 67, 0, 0, 76, 67, 0, 0, 37, 67, 0, 0, 76, 67, 0, 0, 38, 67, 0, 0, 76, 67, 0, 0, 39, 67, 0, 0, 76, 67, 0, 0, 40, 67, 0, 0, 76, 67, 0, 0, 41, 67, 0, 0, 76, 67, 0, 0, 42, 67, 0, 0, 76, 67, 0, 0, 43, 67, 0, 0, 76, 67, 0, 0, 44, 67, 0, 0, 76, 67, 0, 0, 45, 67, 0, 0, 76, 67, 0, 0, 46, 67, 0, 0, 76, 67, 0, 0, 47, 67, 0, 0, 76, 67, 0, 0, 48, 67, 0, 0, 76, 67, 0, 0, 49, 67, 0, 0, 76, 67, 0, 0, 50, 67, 0, 0, 76, 67, 0, 0, 51, 67, 0, 0, 76, 67, 0, 0, 52, 67, 0, 0, 76, 67, 0, 0, 53, 67, 0, 0, 76, 67, 0, 0, 54, 67, 0, 0, 77, 67, 0, 0, 184, 66, 0, 0, 77, 67, 0, 0, 186, 66, 0, 0, 77, 67, 0, 0, 188, 66, 0, 0, 77, 67, 0, 0, 190, 66, 0, 0, 77, 67, 0, 0, 192, 66, 0, 0, 77, 67, 0, 0, 194, 66, 0, 0, 77, 67, 0, 0, 196, 66, 0, 0, 77, 67, 0, 0, 198, 66, 0, 0, 77, 67, 0, 0, 200, 66, 0, 0, 77, 67, 0, 0, 202, 66, 0, 0, 77, 67, 0, 0, 204, 66, 0, 0, 77, 67, 0, 0, 206, 66, 0, 0, 77, 67, 0, 0, 208, 66, 0, 0, 77, 67, 0, 0, 210, 66, 0, 0, 77, 67, 0, 0, 212, 66, 0, 0, 77, 67, 0, 0, 214, 66, 0, 0, 77, 67, 0, 0, 216, 66, 0, 0, 77, 67, 0, 0, 218, 66, 0, 0, 77, 67, 0, 0, 220, 66, 0, 0, 77, 67, 0, 0, 222, 66, 0, 0, 77, 67, 0, 0, 224, 66, 0, 0, 77, 67, 0, 0, 226, 66, 0, 0, 77, 67, 0, 0, 228, 66, 0, 0, 77, 67, 0, 0, 230, 66, 0, 0, 77, 67, 0, 0, 232, 66, 0, 0, 77, 67, 0, 0, 234, 66, 0, 0, 77, 67, 0, 0, 236, 66, 0, 0, 77, 67, 0, 0, 238, 66, 0, 0, 77, 67, 0, 0, 240, 66, 0, 0, 77, 67, 0, 0, 242, 66, 0, 0, 77, 67, 0, 0, 244, 66, 0, 0, 77, 67, 0, 0, 246, 66, 0, 0, 77, 67, 0, 0, 248, 66, 0, 0, 77, 67, 0, 0, 250, 66, 0, 0, 77, 67, 0, 0, 252, 66, 0, 0, 77, 67, 0, 0, 254, 66, 0, 0, 77, 67, 0, 0, 0, 67, 0, 0, 77, 67, 0, 0, 1, 67, 0, 0, 77, 67, 0, 0, 2, 67, 0, 0, 77, 67, 0, 0, 3, 67, 0, 0, 77, 67, 0, 0, 4, 67, 0, 0, 77, 67, 0, 0, 5, 67, 0, 0, 77, 67, 0, 0, 6, 67, 0, 0, 77, 67, 0, 0, 7, 67, 0, 0, 77, 67, 0, 0, 8, 67, 0, 0, 77, 67, 0, 0, 9, 67, 0, 0, 77, 67, 0, 0, 10, 67, 0, 0, 77, 67, 0, 0, 11, 67, 0, 0, 77, 67, 0, 0, 12, 67, 0, 0, 77, 67, 0, 0, 36, 67, 0, 0, 77, 67, 0, 0, 37, 67, 0, 0, 77, 67, 0, 0, 38, 67, 0, 0, 77, 67, 0, 0, 39, 67, 0, 0, 77, 67, 0, 0, 40, 67, 0, 0, 77, 67, 0, 0, 41, 67, 0, 0, 77, 67, 0, 0, 42, 67, 0, 0, 77, 67, 0, 0, 43, 67, 0, 0, 77, 67, 0, 0, 44, 67, 0, 0, 77, 67, 0, 0, 45, 67, 0, 0, 77, 67, 0, 0, 46, 67, 0, 0, 77, 67, 0, 0, 47, 67, 0, 0, 77, 67, 0, 0, 48, 67, 0, 0, 77, 67, 0, 0, 49, 67, 0, 0, 77, 67, 0, 0, 50, 67, 0, 0, 77, 67, 0, 0, 51, 67, 0, 0, 77, 67, 0, 0, 52, 67, 0, 0, 77, 67, 0, 0, 53, 67, 0, 0, 77, 67, 0, 0, 54, 67, 0, 0, 77, 67, 0, 0, 55, 67, 0, 0, 78, 67, 0, 0, 184, 66, 0, 0, 78, 67, 0, 0, 186, 66, 0, 0, 78, 67, 0, 0, 188, 66, 0, 0, 78, 67, 0, 0, 190, 66, 0, 0, 78, 67, 0, 0, 192, 66, 0, 0, 78, 67, 0, 0, 194, 66, 0, 0, 78, 67, 0, 0, 196, 66, 0, 0, 78, 67, 0, 0, 198, 66, 0, 0, 78, 67, 0, 0, 200, 66, 0, 0, 78, 67, 0, 0, 202, 66, 0, 0, 78, 67, 0, 0, 204, 66, 0, 0, 78, 67, 0, 0, 206, 66, 0, 0, 78, 67, 0, 0, 208, 66, 0, 0, 78, 67, 0, 0, 210, 66, 0, 0, 78, 67, 0, 0, 212, 66, 0, 0, 78, 67, 0, 0, 214, 66, 0, 0, 78, 67, 0, 0, 216, 66, 0, 0, 78, 67, 0, 0, 218, 66, 0, 0, 78, 67, 0, 0, 220, 66, 0, 0, 78, 67, 0, 0, 222, 66, 0, 0, 78, 67, 0, 0, 224, 66, 0, 0, 78, 67, 0, 0, 226, 66, 0, 0, 78, 67, 0, 0, 228, 66, 0, 0, 78, 67, 0, 0, 230, 66, 0, 0, 78, 67, 0, 0, 232, 66, 0, 0, 78, 67, 0, 0, 234, 66, 0, 0, 78, 67, 0, 0, 236, 66, 0, 0, 78, 67, 0, 0, 238, 66, 0, 0, 78, 67, 0, 0, 240, 66, 0, 0, 78, 67, 0, 0, 242, 66, 0, 0, 78, 67, 0, 0, 244, 66, 0, 0, 78, 67, 0, 0, 246, 66, 0, 0, 78, 67, 0, 0, 248, 66, 0, 0, 78, 67, 0, 0, 250, 66, 0, 0, 78, 67, 0, 0, 252, 66, 0, 0, 78, 67, 0, 0, 254, 66, 0, 0, 78, 67, 0, 0, 0, 67, 0, 0, 78, 67, 0, 0, 1, 67, 0, 0, 78, 67, 0, 0, 2, 67, 0, 0, 78, 67, 0, 0, 3, 67, 0, 0, 78, 67, 0, 0, 4, 67, 0, 0, 78, 67, 0, 0, 5, 67, 0, 0, 78, 67, 0, 0, 6, 67, 0, 0, 78, 67, 0, 0, 7, 67, 0, 0, 78, 67, 0, 0, 8, 67, 0, 0, 78, 67, 0, 0, 9, 67, 0, 0, 78, 67, 0, 0, 10, 67, 0, 0, 78, 67, 0, 0, 11, 67, 0, 0, 78, 67, 0, 0, 12, 67, 0, 0, 78, 67, 0, 0, 13, 67, 0, 0, 78, 67, 0, 0, 14, 67, 0, 0, 78, 67, 0, 0, 15, 67, 0, 0, 78, 67, 0, 0, 16, 67, 0, 0, 78, 67, 0, 0, 17, 67, 0, 0, 78, 67, 0, 0, 18, 67, 0, 0, 78, 67, 0, 0, 19, 67, 0, 0, 78, 67, 0, 0, 20, 67, 0, 0, 78, 67, 0, 0, 21, 67, 0, 0, 78, 67, 0, 0, 22, 67, 0, 0, 78, 67, 0, 0, 23, 67, 0, 0, 78, 67, 0, 0, 24, 67, 0, 0, 78, 67, 0, 0, 25, 67, 0, 0, 78, 67, 0, 0, 26, 67, 0, 0, 78, 67, 0, 0, 36, 67, 0, 0, 78, 67, 0, 0, 37, 67, 0, 0, 78, 67, 0, 0, 38, 67, 0, 0, 78, 67, 0, 0, 39, 67, 0, 0, 78, 67, 0, 0, 40, 67, 0, 0, 78, 67, 0, 0, 41, 67, 0, 0, 78, 67, 0, 0, 42, 67, 0, 0, 78, 67, 0, 0, 43, 67, 0, 0, 78, 67, 0, 0, 44, 67, 0, 0, 78, 67, 0, 0, 45, 67, 0, 0, 78, 67, 0, 0, 46, 67, 0, 0, 78, 67, 0, 0, 47, 67, 0, 0, 78, 67, 0, 0, 48, 67, 0, 0, 78, 67, 0, 0, 49, 67, 0, 0, 78, 67, 0, 0, 50, 67, 0, 0, 78, 67, 0, 0, 51, 67, 0, 0, 78, 67, 0, 0, 52, 67, 0, 0, 78, 67, 0, 0, 53, 67, 0, 0, 78, 67, 0, 0, 54, 67, 0, 0, 78, 67, 0, 0, 55, 67, 0, 0, 79, 67, 0, 0, 182, 66, 0, 0, 79, 67, 0, 0, 184, 66, 0, 0, 79, 67, 0, 0, 186, 66, 0, 0, 79, 67, 0, 0, 188, 66, 0, 0, 79, 67, 0, 0, 190, 66, 0, 0, 79, 67, 0, 0, 192, 66, 0, 0, 79, 67, 0, 0, 194, 66, 0, 0, 79, 67, 0, 0, 196, 66, 0, 0, 79, 67, 0, 0, 198, 66, 0, 0, 79, 67, 0, 0, 200, 66, 0, 0, 79, 67, 0, 0, 202, 66, 0, 0, 79, 67, 0, 0, 204, 66, 0, 0, 79, 67, 0, 0, 206, 66, 0, 0, 79, 67, 0, 0, 208, 66, 0, 0, 79, 67, 0, 0, 210, 66, 0, 0, 79, 67, 0, 0, 212, 66, 0, 0, 79, 67, 0, 0, 214, 66, 0, 0, 79, 67, 0, 0, 216, 66, 0, 0, 79, 67, 0, 0, 218, 66, 0, 0, 79, 67, 0, 0, 220, 66, 0, 0, 79, 67, 0, 0, 222, 66, 0, 0, 79, 67, 0, 0, 224, 66, 0, 0, 79, 67, 0, 0, 226, 66, 0, 0, 79, 67, 0, 0, 228, 66, 0, 0, 79, 67, 0, 0, 230, 66, 0, 0, 79, 67, 0, 0, 232, 66, 0, 0, 79, 67, 0, 0, 234, 66, 0, 0, 79, 67, 0, 0, 236, 66, 0, 0, 79, 67, 0, 0, 238, 66, 0, 0, 79, 67, 0, 0, 240, 66, 0, 0, 79, 67, 0, 0, 242, 66, 0, 0, 79, 67, 0, 0, 244, 66, 0, 0, 79, 67, 0, 0, 246, 66, 0, 0, 79, 67, 0, 0, 248, 66, 0, 0, 79, 67, 0, 0, 250, 66, 0, 0, 79, 67, 0, 0, 252, 66, 0, 0, 79, 67, 0, 0, 254, 66, 0, 0, 79, 67, 0, 0, 0, 67, 0, 0, 79, 67, 0, 0, 1, 67, 0, 0, 79, 67, 0, 0, 2, 67, 0, 0, 79, 67, 0, 0, 3, 67, 0, 0, 79, 67, 0, 0, 4, 67, 0, 0, 79, 67, 0, 0, 5, 67, 0, 0, 79, 67, 0, 0, 6, 67, 0, 0, 79, 67, 0, 0, 7, 67, 0, 0, 79, 67, 0, 0, 8, 67, 0, 0, 79, 67, 0, 0, 9, 67, 0, 0, 79, 67, 0, 0, 10, 67, 0, 0, 79, 67, 0, 0, 11, 67, 0, 0, 79, 67, 0, 0, 12, 67, 0, 0, 79, 67, 0, 0, 13, 67, 0, 0, 79, 67, 0, 0, 14, 67, 0, 0, 79, 67, 0, 0, 15, 67, 0, 0, 79, 67, 0, 0, 16, 67, 0, 0, 79, 67, 0, 0, 17, 67, 0, 0, 79, 67, 0, 0, 18, 67, 0, 0, 79, 67, 0, 0, 19, 67, 0, 0, 79, 67, 0, 0, 20, 67, 0, 0, 79, 67, 0, 0, 21, 67, 0, 0, 79, 67, 0, 0, 22, 67, 0, 0, 79, 67, 0, 0, 23, 67, 0, 0, 79, 67, 0, 0, 24, 67, 0, 0, 79, 67, 0, 0, 25, 67, 0, 0, 79, 67, 0, 0, 26, 67, 0, 0, 79, 67, 0, 0, 27, 67, 0, 0, 79, 67, 0, 0, 35, 67, 0, 0, 79, 67, 0, 0, 36, 67, 0, 0, 79, 67, 0, 0, 37, 67, 0, 0, 79, 67, 0, 0, 38, 67, 0, 0, 79, 67, 0, 0, 39, 67, 0, 0, 79, 67, 0, 0, 40, 67, 0, 0, 79, 67, 0, 0, 41, 67, 0, 0, 79, 67, 0, 0, 42, 67, 0, 0, 79, 67, 0, 0, 43, 67, 0, 0, 79, 67, 0, 0, 44, 67, 0, 0, 79, 67, 0, 0, 45, 67, 0, 0, 79, 67, 0, 0, 46, 67, 0, 0, 79, 67, 0, 0, 47, 67, 0, 0, 79, 67, 0, 0, 48, 67, 0, 0, 79, 67, 0, 0, 49, 67, 0, 0, 79, 67, 0, 0, 50, 67, 0, 0, 79, 67, 0, 0, 51, 67, 0, 0, 79, 67, 0, 0, 52, 67, 0, 0, 79, 67, 0, 0, 53, 67, 0, 0, 79, 67, 0, 0, 54, 67, 0, 0, 79, 67, 0, 0, 55, 67, 0, 0, 79, 67, 0, 0, 56, 67, 0, 0, 80, 67, 0, 0, 182, 66, 0, 0, 80, 67, 0, 0, 184, 66, 0, 0, 80, 67, 0, 0, 186, 66, 0, 0, 80, 67, 0, 0, 188, 66, 0, 0, 80, 67, 0, 0, 190, 66, 0, 0, 80, 67, 0, 0, 192, 66, 0, 0, 80, 67, 0, 0, 194, 66, 0, 0, 80, 67, 0, 0, 196, 66, 0, 0, 80, 67, 0, 0, 198, 66, 0, 0, 80, 67, 0, 0, 200, 66, 0, 0, 80, 67, 0, 0, 202, 66, 0, 0, 80, 67, 0, 0, 204, 66, 0, 0, 80, 67, 0, 0, 206, 66, 0, 0, 80, 67, 0, 0, 208, 66, 0, 0, 80, 67, 0, 0, 210, 66, 0, 0, 80, 67, 0, 0, 212, 66, 0, 0, 80, 67, 0, 0, 214, 66, 0, 0, 80, 67, 0, 0, 216, 66, 0, 0, 80, 67, 0, 0, 218, 66, 0, 0, 80, 67, 0, 0, 220, 66, 0, 0, 80, 67, 0, 0, 222, 66, 0, 0, 80, 67, 0, 0, 224, 66, 0, 0, 80, 67, 0, 0, 226, 66, 0, 0, 80, 67, 0, 0, 228, 66, 0, 0, 80, 67, 0, 0, 230, 66, 0, 0, 80, 67, 0, 0, 232, 66, 0, 0, 80, 67, 0, 0, 234, 66, 0, 0, 80, 67, 0, 0, 236, 66, 0, 0, 80, 67, 0, 0, 238, 66, 0, 0, 80, 67, 0, 0, 240, 66, 0, 0, 80, 67, 0, 0, 242, 66, 0, 0, 80, 67, 0, 0, 244, 66, 0, 0, 80, 67, 0, 0, 246, 66, 0, 0, 80, 67, 0, 0, 248, 66, 0, 0, 80, 67, 0, 0, 250, 66, 0, 0, 80, 67, 0, 0, 252, 66, 0, 0, 80, 67, 0, 0, 254, 66, 0, 0, 80, 67, 0, 0, 0, 67, 0, 0, 80, 67, 0, 0, 1, 67, 0, 0, 80, 67, 0, 0, 2, 67, 0, 0, 80, 67, 0, 0, 3, 67, 0, 0, 80, 67, 0, 0, 4, 67, 0, 0, 80, 67, 0, 0, 5, 67, 0, 0, 80, 67, 0, 0, 6, 67, 0, 0, 80, 67, 0, 0, 7, 67, 0, 0, 80, 67, 0, 0, 8, 67, 0, 0, 80, 67, 0, 0, 9, 67, 0, 0, 80, 67, 0, 0, 10, 67, 0, 0, 80, 67, 0, 0, 11, 67, 0, 0, 80, 67, 0, 0, 12, 67, 0, 0, 80, 67, 0, 0, 13, 67, 0, 0, 80, 67, 0, 0, 14, 67, 0, 0, 80, 67, 0, 0, 15, 67, 0, 0, 80, 67, 0, 0, 16, 67, 0, 0, 80, 67, 0, 0, 17, 67, 0, 0, 80, 67, 0, 0, 18, 67, 0, 0, 80, 67, 0, 0, 19, 67, 0, 0, 80, 67, 0, 0, 20, 67, 0, 0, 80, 67, 0, 0, 21, 67, 0, 0, 80, 67, 0, 0, 22, 67, 0, 0, 80, 67, 0, 0, 23, 67, 0, 0, 80, 67, 0, 0, 24, 67, 0, 0, 80, 67, 0, 0, 25, 67, 0, 0, 80, 67, 0, 0, 26, 67, 0, 0, 80, 67, 0, 0, 27, 67, 0, 0, 80, 67, 0, 0, 34, 67, 0, 0, 80, 67, 0, 0, 35, 67, 0, 0, 80, 67, 0, 0, 36, 67, 0, 0, 80, 67, 0, 0, 37, 67, 0, 0, 80, 67, 0, 0, 38, 67, 0, 0, 80, 67, 0, 0, 39, 67, 0, 0, 80, 67, 0, 0, 40, 67, 0, 0, 80, 67, 0, 0, 41, 67, 0, 0, 80, 67, 0, 0, 42, 67, 0, 0, 80, 67, 0, 0, 43, 67, 0, 0, 80, 67, 0, 0, 44, 67, 0, 0, 80, 67, 0, 0, 45, 67, 0, 0, 80, 67, 0, 0, 46, 67, 0, 0, 80, 67, 0, 0, 47, 67, 0, 0, 80, 67, 0, 0, 48, 67, 0, 0, 80, 67, 0, 0, 49, 67, 0, 0, 80, 67, 0, 0, 50, 67, 0, 0, 80, 67, 0, 0, 51, 67, 0, 0, 80, 67, 0, 0, 52, 67, 0, 0, 80, 67, 0, 0, 53, 67, 0, 0, 80, 67, 0, 0, 54, 67, 0, 0, 80, 67, 0, 0, 55, 67, 0, 0, 80, 67, 0, 0, 56, 67, 0, 0, 80, 67, 0, 0, 57, 67, 0, 0, 81, 67, 0, 0, 180, 66, 0, 0, 81, 67, 0, 0, 182, 66, 0, 0, 81, 67, 0, 0, 184, 66, 0, 0, 81, 67, 0, 0, 186, 66, 0, 0, 81, 67, 0, 0, 188, 66, 0, 0, 81, 67, 0, 0, 190, 66, 0, 0, 81, 67, 0, 0, 192, 66, 0, 0, 81, 67, 0, 0, 194, 66, 0, 0, 81, 67, 0, 0, 196, 66, 0, 0, 81, 67, 0, 0, 198, 66, 0, 0, 81, 67, 0, 0, 200, 66, 0, 0, 81, 67, 0, 0, 202, 66, 0, 0, 81, 67, 0, 0, 204, 66, 0, 0, 81, 67, 0, 0, 206, 66, 0, 0, 81, 67, 0, 0, 208, 66, 0, 0, 81, 67, 0, 0, 210, 66, 0, 0, 81, 67, 0, 0, 212, 66, 0, 0, 81, 67, 0, 0, 214, 66, 0, 0, 81, 67, 0, 0, 216, 66, 0, 0, 81, 67, 0, 0, 218, 66, 0, 0, 81, 67, 0, 0, 220, 66, 0, 0, 81, 67, 0, 0, 222, 66, 0, 0, 81, 67, 0, 0, 224, 66, 0, 0, 81, 67, 0, 0, 226, 66, 0, 0, 81, 67, 0, 0, 228, 66, 0, 0, 81, 67, 0, 0, 230, 66, 0, 0, 81, 67, 0, 0, 232, 66, 0, 0, 81, 67, 0, 0, 234, 66, 0, 0, 81, 67, 0, 0, 236, 66, 0, 0, 81, 67, 0, 0, 238, 66, 0, 0, 81, 67, 0, 0, 240, 66, 0, 0, 81, 67, 0, 0, 242, 66, 0, 0, 81, 67, 0, 0, 244, 66, 0, 0, 81, 67, 0, 0, 246, 66, 0, 0, 81, 67, 0, 0, 248, 66, 0, 0, 81, 67, 0, 0, 250, 66, 0, 0, 81, 67, 0, 0, 252, 66, 0, 0, 81, 67, 0, 0, 254, 66, 0, 0, 81, 67, 0, 0, 0, 67, 0, 0, 81, 67, 0, 0, 1, 67, 0, 0, 81, 67, 0, 0, 2, 67, 0, 0, 81, 67, 0, 0, 3, 67, 0, 0, 81, 67, 0, 0, 4, 67, 0, 0, 81, 67, 0, 0, 5, 67, 0, 0, 81, 67, 0, 0, 6, 67, 0, 0, 81, 67, 0, 0, 7, 67, 0, 0, 81, 67, 0, 0, 8, 67, 0, 0, 81, 67, 0, 0, 9, 67, 0, 0, 81, 67, 0, 0, 10, 67, 0, 0, 81, 67, 0, 0, 11, 67, 0, 0, 81, 67, 0, 0, 12, 67, 0, 0, 81, 67, 0, 0, 13, 67, 0, 0, 81, 67, 0, 0, 14, 67, 0, 0, 81, 67, 0, 0, 15, 67, 0, 0, 81, 67, 0, 0, 16, 67, 0, 0, 81, 67, 0, 0, 17, 67, 0, 0, 81, 67, 0, 0, 18, 67, 0, 0, 81, 67, 0, 0, 19, 67, 0, 0, 81, 67, 0, 0, 20, 67, 0, 0, 81, 67, 0, 0, 21, 67, 0, 0, 81, 67, 0, 0, 22, 67, 0, 0, 81, 67, 0, 0, 23, 67, 0, 0, 81, 67, 0, 0, 24, 67, 0, 0, 81, 67, 0, 0, 25, 67, 0, 0, 81, 67, 0, 0, 26, 67, 0, 0, 81, 67, 0, 0, 27, 67, 0, 0, 81, 67, 0, 0, 34, 67, 0, 0, 81, 67, 0, 0, 35, 67, 0, 0, 81, 67, 0, 0, 36, 67, 0, 0, 81, 67, 0, 0, 37, 67, 0, 0, 81, 67, 0, 0, 38, 67, 0, 0, 81, 67, 0, 0, 39, 67, 0, 0, 81, 67, 0, 0, 40, 67, 0, 0, 81, 67, 0, 0, 41, 67, 0, 0, 81, 67, 0, 0, 42, 67, 0, 0, 81, 67, 0, 0, 43, 67, 0, 0, 81, 67, 0, 0, 44, 67, 0, 0, 81, 67, 0, 0, 45, 67, 0, 0, 81, 67, 0, 0, 46, 67, 0, 0, 81, 67, 0, 0, 47, 67, 0, 0, 81, 67, 0, 0, 48, 67, 0, 0, 81, 67, 0, 0, 49, 67, 0, 0, 81, 67, 0, 0, 50, 67, 0, 0, 81, 67, 0, 0, 51, 67, 0, 0, 81, 67, 0, 0, 52, 67, 0, 0, 81, 67, 0, 0, 53, 67, 0, 0, 81, 67, 0, 0, 54, 67, 0, 0, 81, 67, 0, 0, 55, 67, 0, 0, 81, 67, 0, 0, 56, 67, 0, 0, 81, 67, 0, 0, 57, 67, 0, 0, 82, 67, 0, 0, 180, 66, 0, 0, 82, 67, 0, 0, 182, 66, 0, 0, 82, 67, 0, 0, 184, 66, 0, 0, 82, 67, 0, 0, 186, 66, 0, 0, 82, 67, 0, 0, 188, 66, 0, 0, 82, 67, 0, 0, 190, 66, 0, 0, 82, 67, 0, 0, 192, 66, 0, 0, 82, 67, 0, 0, 194, 66, 0, 0, 82, 67, 0, 0, 196, 66, 0, 0, 82, 67, 0, 0, 198, 66, 0, 0, 82, 67, 0, 0, 200, 66, 0, 0, 82, 67, 0, 0, 202, 66, 0, 0, 82, 67, 0, 0, 204, 66, 0, 0, 82, 67, 0, 0, 206, 66, 0, 0, 82, 67, 0, 0, 208, 66, 0, 0, 82, 67, 0, 0, 210, 66, 0, 0, 82, 67, 0, 0, 212, 66, 0, 0, 82, 67, 0, 0, 214, 66, 0, 0, 82, 67, 0, 0, 216, 66, 0, 0, 82, 67, 0, 0, 218, 66, 0, 0, 82, 67, 0, 0, 220, 66, 0, 0, 82, 67, 0, 0, 222, 66, 0, 0, 82, 67, 0, 0, 224, 66, 0, 0, 82, 67, 0, 0, 226, 66, 0, 0, 82, 67, 0, 0, 228, 66, 0, 0, 82, 67, 0, 0, 230, 66, 0, 0, 82, 67, 0, 0, 232, 66, 0, 0, 82, 67, 0, 0, 234, 66, 0, 0, 82, 67, 0, 0, 236, 66, 0, 0, 82, 67, 0, 0, 238, 66, 0, 0, 82, 67, 0, 0, 240, 66, 0, 0, 82, 67, 0, 0, 242, 66, 0, 0, 82, 67, 0, 0, 244, 66, 0, 0, 82, 67, 0, 0, 246, 66, 0, 0, 82, 67, 0, 0, 248, 66, 0, 0, 82, 67, 0, 0, 250, 66, 0, 0, 82, 67, 0, 0, 252, 66, 0, 0, 82, 67, 0, 0, 254, 66, 0, 0, 82, 67, 0, 0, 0, 67, 0, 0, 82, 67, 0, 0, 1, 67, 0, 0, 82, 67, 0, 0, 2, 67, 0, 0, 82, 67, 0, 0, 3, 67, 0, 0, 82, 67, 0, 0, 4, 67, 0, 0, 82, 67, 0, 0, 5, 67, 0, 0, 82, 67, 0, 0, 6, 67, 0, 0, 82, 67, 0, 0, 7, 67, 0, 0, 82, 67, 0, 0, 8, 67, 0, 0, 82, 67, 0, 0, 9, 67, 0, 0, 82, 67, 0, 0, 10, 67, 0, 0, 82, 67, 0, 0, 11, 67, 0, 0, 82, 67, 0, 0, 12, 67, 0, 0, 82, 67, 0, 0, 13, 67, 0, 0, 82, 67, 0, 0, 14, 67, 0, 0, 82, 67, 0, 0, 15, 67, 0, 0, 82, 67, 0, 0, 16, 67, 0, 0, 82, 67, 0, 0, 17, 67, 0, 0, 82, 67, 0, 0, 18, 67, 0, 0, 82, 67, 0, 0, 19, 67, 0, 0, 82, 67, 0, 0, 20, 67, 0, 0, 82, 67, 0, 0, 21, 67, 0, 0, 82, 67, 0, 0, 22, 67, 0, 0, 82, 67, 0, 0, 23, 67, 0, 0, 82, 67, 0, 0, 24, 67, 0, 0, 82, 67, 0, 0, 25, 67, 0, 0, 82, 67, 0, 0, 26, 67, 0, 0, 82, 67, 0, 0, 27, 67, 0, 0, 82, 67, 0, 0, 34, 67, 0, 0, 82, 67, 0, 0, 35, 67, 0, 0, 82, 67, 0, 0, 36, 67, 0, 0, 82, 67, 0, 0, 37, 67, 0, 0, 82, 67, 0, 0, 38, 67, 0, 0, 82, 67, 0, 0, 39, 67, 0, 0, 82, 67, 0, 0, 40, 67, 0, 0, 82, 67, 0, 0, 41, 67, 0, 0, 82, 67, 0, 0, 42, 67, 0, 0, 82, 67, 0, 0, 43, 67, 0, 0, 82, 67, 0, 0, 44, 67, 0, 0, 82, 67, 0, 0, 45, 67, 0, 0, 82, 67, 0, 0, 46, 67, 0, 0, 82, 67, 0, 0, 47, 67, 0, 0, 82, 67, 0, 0, 48, 67, 0, 0, 82, 67, 0, 0, 49, 67, 0, 0, 82, 67, 0, 0, 50, 67, 0, 0, 82, 67, 0, 0, 51, 67, 0, 0, 82, 67, 0, 0, 52, 67, 0, 0, 82, 67, 0, 0, 53, 67, 0, 0, 82, 67, 0, 0, 54, 67, 0, 0, 82, 67, 0, 0, 55, 67, 0, 0, 82, 67, 0, 0, 56, 67, 0, 0, 82, 67, 0, 0, 57, 67, 0, 0, 83, 67, 0, 0, 180, 66, 0, 0, 83, 67, 0, 0, 182, 66, 0, 0, 83, 67, 0, 0, 184, 66, 0, 0, 83, 67, 0, 0, 186, 66, 0, 0, 83, 67, 0, 0, 188, 66, 0, 0, 83, 67, 0, 0, 190, 66, 0, 0, 83, 67, 0, 0, 192, 66, 0, 0, 83, 67, 0, 0, 194, 66, 0, 0, 83, 67, 0, 0, 196, 66, 0, 0, 83, 67, 0, 0, 198, 66, 0, 0, 83, 67, 0, 0, 200, 66, 0, 0, 83, 67, 0, 0, 202, 66, 0, 0, 83, 67, 0, 0, 204, 66, 0, 0, 83, 67, 0, 0, 206, 66, 0, 0, 83, 67, 0, 0, 208, 66, 0, 0, 83, 67, 0, 0, 210, 66, 0, 0, 83, 67, 0, 0, 212, 66, 0, 0, 83, 67, 0, 0, 214, 66, 0, 0, 83, 67, 0, 0, 216, 66, 0, 0, 83, 67, 0, 0, 218, 66, 0, 0, 83, 67, 0, 0, 220, 66, 0, 0, 83, 67, 0, 0, 222, 66, 0, 0, 83, 67, 0, 0, 224, 66, 0, 0, 83, 67, 0, 0, 226, 66, 0, 0, 83, 67, 0, 0, 228, 66, 0, 0, 83, 67, 0, 0, 230, 66, 0, 0, 83, 67, 0, 0, 232, 66, 0, 0, 83, 67, 0, 0, 234, 66, 0, 0, 83, 67, 0, 0, 236, 66, 0, 0, 83, 67, 0, 0, 238, 66, 0, 0, 83, 67, 0, 0, 240, 66, 0, 0, 83, 67, 0, 0, 242, 66, 0, 0, 83, 67, 0, 0, 244, 66, 0, 0, 83, 67, 0, 0, 246, 66, 0, 0, 83, 67, 0, 0, 248, 66, 0, 0, 83, 67, 0, 0, 250, 66, 0, 0, 83, 67, 0, 0, 252, 66, 0, 0, 83, 67, 0, 0, 254, 66, 0, 0, 83, 67, 0, 0, 0, 67, 0, 0, 83, 67, 0, 0, 1, 67, 0, 0, 83, 67, 0, 0, 2, 67, 0, 0, 83, 67, 0, 0, 3, 67, 0, 0, 83, 67, 0, 0, 4, 67, 0, 0, 83, 67, 0, 0, 5, 67, 0, 0, 83, 67, 0, 0, 6, 67, 0, 0, 83, 67, 0, 0, 7, 67, 0, 0, 83, 67, 0, 0, 8, 67, 0, 0, 83, 67, 0, 0, 9, 67, 0, 0, 83, 67, 0, 0, 10, 67, 0, 0, 83, 67, 0, 0, 11, 67, 0, 0, 83, 67, 0, 0, 12, 67, 0, 0, 83, 67, 0, 0, 13, 67, 0, 0, 83, 67, 0, 0, 14, 67, 0, 0, 83, 67, 0, 0, 15, 67, 0, 0, 83, 67, 0, 0, 16, 67, 0, 0, 83, 67, 0, 0, 17, 67, 0, 0, 83, 67, 0, 0, 18, 67, 0, 0, 83, 67, 0, 0, 19, 67, 0, 0, 83, 67, 0, 0, 20, 67, 0, 0, 83, 67, 0, 0, 21, 67, 0, 0, 83, 67, 0, 0, 22, 67, 0, 0, 83, 67, 0, 0, 23, 67, 0, 0, 83, 67, 0, 0, 24, 67, 0, 0, 83, 67, 0, 0, 25, 67, 0, 0, 83, 67, 0, 0, 26, 67, 0, 0, 83, 67, 0, 0, 27, 67, 0, 0, 83, 67, 0, 0, 34, 67, 0, 0, 83, 67, 0, 0, 35, 67, 0, 0, 83, 67, 0, 0, 36, 67, 0, 0, 83, 67, 0, 0, 37, 67, 0, 0, 83, 67, 0, 0, 38, 67, 0, 0, 83, 67, 0, 0, 39, 67, 0, 0, 83, 67, 0, 0, 40, 67, 0, 0, 83, 67, 0, 0, 41, 67, 0, 0, 83, 67, 0, 0, 42, 67, 0, 0, 83, 67, 0, 0, 43, 67, 0, 0, 83, 67, 0, 0, 44, 67, 0, 0, 83, 67, 0, 0, 45, 67, 0, 0, 83, 67, 0, 0, 46, 67, 0, 0, 83, 67, 0, 0, 47, 67, 0, 0, 83, 67, 0, 0, 48, 67, 0, 0, 83, 67, 0, 0, 49, 67, 0, 0, 83, 67, 0, 0, 50, 67, 0, 0, 83, 67, 0, 0, 51, 67, 0, 0, 83, 67, 0, 0, 52, 67, 0, 0, 83, 67, 0, 0, 53, 67, 0, 0, 83, 67, 0, 0, 54, 67, 0, 0, 83, 67, 0, 0, 55, 67, 0, 0, 83, 67, 0, 0, 56, 67, 0, 0, 83, 67, 0, 0, 57, 67, 0, 0, 84, 67, 0, 0, 180, 66, 0, 0, 84, 67, 0, 0, 182, 66, 0, 0, 84, 67, 0, 0, 184, 66, 0, 0, 84, 67, 0, 0, 186, 66, 0, 0, 84, 67, 0, 0, 188, 66, 0, 0, 84, 67, 0, 0, 190, 66, 0, 0, 84, 67, 0, 0, 192, 66, 0, 0, 84, 67, 0, 0, 194, 66, 0, 0, 84, 67, 0, 0, 196, 66, 0, 0, 84, 67, 0, 0, 198, 66, 0, 0, 84, 67, 0, 0, 200, 66, 0, 0, 84, 67, 0, 0, 202, 66, 0, 0, 84, 67, 0, 0, 204, 66, 0, 0, 84, 67, 0, 0, 206, 66, 0, 0, 84, 67, 0, 0, 208, 66, 0, 0, 84, 67, 0, 0, 210, 66, 0, 0, 84, 67, 0, 0, 212, 66, 0, 0, 84, 67, 0, 0, 214, 66, 0, 0, 84, 67, 0, 0, 216, 66, 0, 0, 84, 67, 0, 0, 218, 66, 0, 0, 84, 67, 0, 0, 220, 66, 0, 0, 84, 67, 0, 0, 222, 66, 0, 0, 84, 67, 0, 0, 224, 66, 0, 0, 84, 67, 0, 0, 226, 66, 0, 0, 84, 67, 0, 0, 228, 66, 0, 0, 84, 67, 0, 0, 230, 66, 0, 0, 84, 67, 0, 0, 232, 66, 0, 0, 84, 67, 0, 0, 234, 66, 0, 0, 84, 67, 0, 0, 236, 66, 0, 0, 84, 67, 0, 0, 238, 66, 0, 0, 84, 67, 0, 0, 240, 66, 0, 0, 84, 67, 0, 0, 242, 66, 0, 0, 84, 67, 0, 0, 244, 66, 0, 0, 84, 67, 0, 0, 246, 66, 0, 0, 84, 67, 0, 0, 248, 66, 0, 0, 84, 67, 0, 0, 250, 66, 0, 0, 84, 67, 0, 0, 252, 66, 0, 0, 84, 67, 0, 0, 254, 66, 0, 0, 84, 67, 0, 0, 0, 67, 0, 0, 84, 67, 0, 0, 1, 67, 0, 0, 84, 67, 0, 0, 2, 67, 0, 0, 84, 67, 0, 0, 3, 67, 0, 0, 84, 67, 0, 0, 4, 67, 0, 0, 84, 67, 0, 0, 5, 67, 0, 0, 84, 67, 0, 0, 6, 67, 0, 0, 84, 67, 0, 0, 7, 67, 0, 0, 84, 67, 0, 0, 8, 67, 0, 0, 84, 67, 0, 0, 9, 67, 0, 0, 84, 67, 0, 0, 10, 67, 0, 0, 84, 67, 0, 0, 11, 67, 0, 0, 84, 67, 0, 0, 12, 67, 0, 0, 84, 67, 0, 0, 13, 67, 0, 0, 84, 67, 0, 0, 14, 67, 0, 0, 84, 67, 0, 0, 15, 67, 0, 0, 84, 67, 0, 0, 16, 67, 0, 0, 84, 67, 0, 0, 17, 67, 0, 0, 84, 67, 0, 0, 18, 67, 0, 0, 84, 67, 0, 0, 19, 67, 0, 0, 84, 67, 0, 0, 20, 67, 0, 0, 84, 67, 0, 0, 21, 67, 0, 0, 84, 67, 0, 0, 22, 67, 0, 0, 84, 67, 0, 0, 23, 67, 0, 0, 84, 67, 0, 0, 24, 67, 0, 0, 84, 67, 0, 0, 25, 67, 0, 0, 84, 67, 0, 0, 26, 67, 0, 0, 84, 67, 0, 0, 27, 67, 0, 0, 84, 67, 0, 0, 34, 67, 0, 0, 84, 67, 0, 0, 35, 67, 0, 0, 84, 67, 0, 0, 36, 67, 0, 0, 84, 67, 0, 0, 37, 67, 0, 0, 84, 67, 0, 0, 38, 67, 0, 0, 84, 67, 0, 0, 39, 67, 0, 0, 84, 67, 0, 0, 40, 67, 0, 0, 84, 67, 0, 0, 41, 67, 0, 0, 84, 67, 0, 0, 42, 67, 0, 0, 84, 67, 0, 0, 43, 67, 0, 0, 84, 67, 0, 0, 44, 67, 0, 0, 84, 67, 0, 0, 45, 67, 0, 0, 84, 67, 0, 0, 46, 67, 0, 0, 84, 67, 0, 0, 47, 67, 0, 0, 84, 67, 0, 0, 48, 67, 0, 0, 84, 67, 0, 0, 49, 67, 0, 0, 84, 67, 0, 0, 50, 67, 0, 0, 84, 67, 0, 0, 51, 67, 0, 0, 84, 67, 0, 0, 52, 67, 0, 0, 84, 67, 0, 0, 53, 67, 0, 0, 84, 67, 0, 0, 54, 67, 0, 0, 84, 67, 0, 0, 55, 67, 0, 0, 84, 67, 0, 0, 56, 67, 0, 0, 84, 67, 0, 0, 57, 67, 0, 0, 85, 67, 0, 0, 180, 66, 0, 0, 85, 67, 0, 0, 182, 66, 0, 0, 85, 67, 0, 0, 184, 66, 0, 0, 85, 67, 0, 0, 186, 66, 0, 0, 85, 67, 0, 0, 188, 66, 0, 0, 85, 67, 0, 0, 190, 66, 0, 0, 85, 67, 0, 0, 192, 66, 0, 0, 85, 67, 0, 0, 194, 66, 0, 0, 85, 67, 0, 0, 196, 66, 0, 0, 85, 67, 0, 0, 198, 66, 0, 0, 85, 67, 0, 0, 200, 66, 0, 0, 85, 67, 0, 0, 202, 66, 0, 0, 85, 67, 0, 0, 204, 66, 0, 0, 85, 67, 0, 0, 206, 66, 0, 0, 85, 67, 0, 0, 208, 66, 0, 0, 85, 67, 0, 0, 210, 66, 0, 0, 85, 67, 0, 0, 212, 66, 0, 0, 85, 67, 0, 0, 214, 66, 0, 0, 85, 67, 0, 0, 216, 66, 0, 0, 85, 67, 0, 0, 218, 66, 0, 0, 85, 67, 0, 0, 220, 66, 0, 0, 85, 67, 0, 0, 222, 66, 0, 0, 85, 67, 0, 0, 224, 66, 0, 0, 85, 67, 0, 0, 226, 66, 0, 0, 85, 67, 0, 0, 228, 66, 0, 0, 85, 67, 0, 0, 230, 66, 0, 0, 85, 67, 0, 0, 232, 66, 0, 0, 85, 67, 0, 0, 234, 66, 0, 0, 85, 67, 0, 0, 236, 66, 0, 0, 85, 67, 0, 0, 238, 66, 0, 0, 85, 67, 0, 0, 240, 66, 0, 0, 85, 67, 0, 0, 242, 66, 0, 0, 85, 67, 0, 0, 244, 66, 0, 0, 85, 67, 0, 0, 246, 66, 0, 0, 85, 67, 0, 0, 248, 66, 0, 0, 85, 67, 0, 0, 250, 66, 0, 0, 85, 67, 0, 0, 252, 66, 0, 0, 85, 67, 0, 0, 254, 66, 0, 0, 85, 67, 0, 0, 0, 67, 0, 0, 85, 67, 0, 0, 1, 67, 0, 0, 85, 67, 0, 0, 2, 67, 0, 0, 85, 67, 0, 0, 3, 67, 0, 0, 85, 67, 0, 0, 4, 67, 0, 0, 85, 67, 0, 0, 5, 67, 0, 0, 85, 67, 0, 0, 6, 67, 0, 0, 85, 67, 0, 0, 7, 67, 0, 0, 85, 67, 0, 0, 8, 67, 0, 0, 85, 67, 0, 0, 9, 67, 0, 0, 85, 67, 0, 0, 10, 67, 0, 0, 85, 67, 0, 0, 11, 67, 0, 0, 85, 67, 0, 0, 12, 67, 0, 0, 85, 67, 0, 0, 13, 67, 0, 0, 85, 67, 0, 0, 14, 67, 0, 0, 85, 67, 0, 0, 15, 67, 0, 0, 85, 67, 0, 0, 16, 67, 0, 0, 85, 67, 0, 0, 17, 67, 0, 0, 85, 67, 0, 0, 18, 67, 0, 0, 85, 67, 0, 0, 19, 67, 0, 0, 85, 67, 0, 0, 20, 67, 0, 0, 85, 67, 0, 0, 21, 67, 0, 0, 85, 67, 0, 0, 22, 67, 0, 0, 85, 67, 0, 0, 23, 67, 0, 0, 85, 67, 0, 0, 24, 67, 0, 0, 85, 67, 0, 0, 25, 67, 0, 0, 85, 67, 0, 0, 26, 67, 0, 0, 85, 67, 0, 0, 27, 67, 0, 0, 85, 67, 0, 0, 34, 67, 0, 0, 85, 67, 0, 0, 35, 67, 0, 0, 85, 67, 0, 0, 36, 67, 0, 0, 85, 67, 0, 0, 37, 67, 0, 0, 85, 67, 0, 0, 38, 67, 0, 0, 85, 67, 0, 0, 39, 67, 0, 0, 85, 67, 0, 0, 40, 67, 0, 0, 85, 67, 0, 0, 41, 67, 0, 0, 85, 67, 0, 0, 42, 67, 0, 0, 85, 67, 0, 0, 43, 67, 0, 0, 85, 67, 0, 0, 44, 67, 0, 0, 85, 67, 0, 0, 45, 67, 0, 0, 85, 67, 0, 0, 46, 67, 0, 0, 85, 67, 0, 0, 47, 67, 0, 0, 85, 67, 0, 0, 48, 67, 0, 0, 85, 67, 0, 0, 49, 67, 0, 0, 85, 67, 0, 0, 50, 67, 0, 0, 85, 67, 0, 0, 51, 67, 0, 0, 85, 67, 0, 0, 52, 67, 0, 0, 85, 67, 0, 0, 53, 67, 0, 0, 85, 67, 0, 0, 54, 67, 0, 0, 85, 67, 0, 0, 55, 67, 0, 0, 85, 67, 0, 0, 56, 67, 0, 0, 85, 67, 0, 0, 57, 67, 0, 0, 86, 67, 0, 0, 180, 66, 0, 0, 86, 67, 0, 0, 182, 66, 0, 0, 86, 67, 0, 0, 184, 66, 0, 0, 86, 67, 0, 0, 186, 66, 0, 0, 86, 67, 0, 0, 188, 66, 0, 0, 86, 67, 0, 0, 190, 66, 0, 0, 86, 67, 0, 0, 192, 66, 0, 0, 86, 67, 0, 0, 194, 66, 0, 0, 86, 67, 0, 0, 196, 66, 0, 0, 86, 67, 0, 0, 198, 66, 0, 0, 86, 67, 0, 0, 200, 66, 0, 0, 86, 67, 0, 0, 202, 66, 0, 0, 86, 67, 0, 0, 204, 66, 0, 0, 86, 67, 0, 0, 206, 66, 0, 0, 86, 67, 0, 0, 208, 66, 0, 0, 86, 67, 0, 0, 210, 66, 0, 0, 86, 67, 0, 0, 212, 66, 0, 0, 86, 67, 0, 0, 214, 66, 0, 0, 86, 67, 0, 0, 216, 66, 0, 0, 86, 67, 0, 0, 218, 66, 0, 0, 86, 67, 0, 0, 220, 66, 0, 0, 86, 67, 0, 0, 222, 66, 0, 0, 86, 67, 0, 0, 224, 66, 0, 0, 86, 67, 0, 0, 226, 66, 0, 0, 86, 67, 0, 0, 228, 66, 0, 0, 86, 67, 0, 0, 230, 66, 0, 0, 86, 67, 0, 0, 232, 66, 0, 0, 86, 67, 0, 0, 234, 66, 0, 0, 86, 67, 0, 0, 236, 66, 0, 0, 86, 67, 0, 0, 238, 66, 0, 0, 86, 67, 0, 0, 240, 66, 0, 0, 86, 67, 0, 0, 242, 66, 0, 0, 86, 67, 0, 0, 244, 66, 0, 0, 86, 67, 0, 0, 246, 66, 0, 0, 86, 67, 0, 0, 248, 66, 0, 0, 86, 67, 0, 0, 250, 66, 0, 0, 86, 67, 0, 0, 252, 66, 0, 0, 86, 67, 0, 0, 254, 66, 0, 0, 86, 67, 0, 0, 0, 67, 0, 0, 86, 67, 0, 0, 1, 67, 0, 0, 86, 67, 0, 0, 2, 67, 0, 0, 86, 67, 0, 0, 3, 67, 0, 0, 86, 67, 0, 0, 4, 67, 0, 0, 86, 67, 0, 0, 5, 67, 0, 0, 86, 67, 0, 0, 6, 67, 0, 0, 86, 67, 0, 0, 7, 67, 0, 0, 86, 67, 0, 0, 8, 67, 0, 0, 86, 67, 0, 0, 9, 67, 0, 0, 86, 67, 0, 0, 10, 67, 0, 0, 86, 67, 0, 0, 11, 67, 0, 0, 86, 67, 0, 0, 12, 67, 0, 0, 86, 67, 0, 0, 13, 67, 0, 0, 86, 67, 0, 0, 14, 67, 0, 0, 86, 67, 0, 0, 15, 67, 0, 0, 86, 67, 0, 0, 16, 67, 0, 0, 86, 67, 0, 0, 17, 67, 0, 0, 86, 67, 0, 0, 18, 67, 0, 0, 86, 67, 0, 0, 19, 67, 0, 0, 86, 67, 0, 0, 20, 67, 0, 0, 86, 67, 0, 0, 21, 67, 0, 0, 86, 67, 0, 0, 22, 67, 0, 0, 86, 67, 0, 0, 23, 67, 0, 0, 86, 67, 0, 0, 24, 67, 0, 0, 86, 67, 0, 0, 25, 67, 0, 0, 86, 67, 0, 0, 26, 67, 0, 0, 86, 67, 0, 0, 27, 67, 0, 0, 86, 67, 0, 0, 34, 67, 0, 0, 86, 67, 0, 0, 35, 67, 0, 0, 86, 67, 0, 0, 36, 67, 0, 0, 86, 67, 0, 0, 37, 67, 0, 0, 86, 67, 0, 0, 38, 67, 0, 0, 86, 67, 0, 0, 39, 67, 0, 0, 86, 67, 0, 0, 40, 67, 0, 0, 86, 67, 0, 0, 41, 67, 0, 0, 86, 67, 0, 0, 42, 67, 0, 0, 86, 67, 0, 0, 43, 67, 0, 0, 86, 67, 0, 0, 44, 67, 0, 0, 86, 67, 0, 0, 45, 67, 0, 0, 86, 67, 0, 0, 46, 67, 0, 0, 86, 67, 0, 0, 47, 67, 0, 0, 86, 67, 0, 0, 48, 67, 0, 0, 86, 67, 0, 0, 49, 67, 0, 0, 86, 67, 0, 0, 50, 67, 0, 0, 86, 67, 0, 0, 51, 67, 0, 0, 86, 67, 0, 0, 52, 67, 0, 0, 86, 67, 0, 0, 53, 67, 0, 0, 86, 67, 0, 0, 54, 67, 0, 0, 86, 67, 0, 0, 55, 67, 0, 0, 86, 67, 0, 0, 56, 67, 0, 0, 86, 67, 0, 0, 57, 67, 0, 0, 87, 67, 0, 0, 180, 66, 0, 0, 87, 67, 0, 0, 182, 66, 0, 0, 87, 67, 0, 0, 184, 66, 0, 0, 87, 67, 0, 0, 186, 66, 0, 0, 87, 67, 0, 0, 188, 66, 0, 0, 87, 67, 0, 0, 190, 66, 0, 0, 87, 67, 0, 0, 192, 66, 0, 0, 87, 67, 0, 0, 194, 66, 0, 0, 87, 67, 0, 0, 196, 66, 0, 0, 87, 67, 0, 0, 198, 66, 0, 0, 87, 67, 0, 0, 200, 66, 0, 0, 87, 67, 0, 0, 202, 66, 0, 0, 87, 67, 0, 0, 204, 66, 0, 0, 87, 67, 0, 0, 206, 66, 0, 0, 87, 67, 0, 0, 208, 66, 0, 0, 87, 67, 0, 0, 210, 66, 0, 0, 87, 67, 0, 0, 212, 66, 0, 0, 87, 67, 0, 0, 214, 66, 0, 0, 87, 67, 0, 0, 216, 66, 0, 0, 87, 67, 0, 0, 218, 66, 0, 0, 87, 67, 0, 0, 220, 66, 0, 0, 87, 67, 0, 0, 222, 66, 0, 0, 87, 67, 0, 0, 224, 66, 0, 0, 87, 67, 0, 0, 226, 66, 0, 0, 87, 67, 0, 0, 228, 66, 0, 0, 87, 67, 0, 0, 230, 66, 0, 0, 87, 67, 0, 0, 232, 66, 0, 0, 87, 67, 0, 0, 234, 66, 0, 0, 87, 67, 0, 0, 236, 66, 0, 0, 87, 67, 0, 0, 238, 66, 0, 0, 87, 67, 0, 0, 240, 66, 0, 0, 87, 67, 0, 0, 242, 66, 0, 0, 87, 67, 0, 0, 244, 66, 0, 0, 87, 67, 0, 0, 246, 66, 0, 0, 87, 67, 0, 0, 248, 66, 0, 0, 87, 67, 0, 0, 250, 66, 0, 0, 87, 67, 0, 0, 252, 66, 0, 0, 87, 67, 0, 0, 254, 66, 0, 0, 87, 67, 0, 0, 0, 67, 0, 0, 87, 67, 0, 0, 1, 67, 0, 0, 87, 67, 0, 0, 2, 67, 0, 0, 87, 67, 0, 0, 3, 67, 0, 0, 87, 67, 0, 0, 4, 67, 0, 0, 87, 67, 0, 0, 5, 67, 0, 0, 87, 67, 0, 0, 6, 67, 0, 0, 87, 67, 0, 0, 7, 67, 0, 0, 87, 67, 0, 0, 8, 67, 0, 0, 87, 67, 0, 0, 9, 67, 0, 0, 87, 67, 0, 0, 10, 67, 0, 0, 87, 67, 0, 0, 11, 67, 0, 0, 87, 67, 0, 0, 12, 67, 0, 0, 87, 67, 0, 0, 13, 67, 0, 0, 87, 67, 0, 0, 14, 67, 0, 0, 87, 67, 0, 0, 15, 67, 0, 0, 87, 67, 0, 0, 16, 67, 0, 0, 87, 67, 0, 0, 17, 67, 0, 0, 87, 67, 0, 0, 18, 67, 0, 0, 87, 67, 0, 0, 19, 67, 0, 0, 87, 67, 0, 0, 20, 67, 0, 0, 87, 67, 0, 0, 21, 67, 0, 0, 87, 67, 0, 0, 22, 67, 0, 0, 87, 67, 0, 0, 23, 67, 0, 0, 87, 67, 0, 0, 24, 67, 0, 0, 87, 67, 0, 0, 25, 67, 0, 0, 87, 67, 0, 0, 26, 67, 0, 0, 87, 67, 0, 0, 27, 67, 0, 0, 87, 67, 0, 0, 34, 67, 0, 0, 87, 67, 0, 0, 35, 67, 0, 0, 87, 67, 0, 0, 36, 67, 0, 0, 87, 67, 0, 0, 37, 67, 0, 0, 87, 67, 0, 0, 38, 67, 0, 0, 87, 67, 0, 0, 39, 67, 0, 0, 87, 67, 0, 0, 40, 67, 0, 0, 87, 67, 0, 0, 41, 67, 0, 0, 87, 67, 0, 0, 42, 67, 0, 0, 87, 67, 0, 0, 43, 67, 0, 0, 87, 67, 0, 0, 44, 67, 0, 0, 87, 67, 0, 0, 45, 67, 0, 0, 87, 67, 0, 0, 46, 67, 0, 0, 87, 67, 0, 0, 47, 67, 0, 0, 87, 67, 0, 0, 48, 67, 0, 0, 87, 67, 0, 0, 49, 67, 0, 0, 87, 67, 0, 0, 50, 67, 0, 0, 87, 67, 0, 0, 51, 67, 0, 0, 87, 67, 0, 0, 52, 67, 0, 0, 87, 67, 0, 0, 53, 67, 0, 0, 87, 67, 0, 0, 54, 67, 0, 0, 87, 67, 0, 0, 55, 67, 0, 0, 87, 67, 0, 0, 56, 67, 0, 0, 87, 67, 0, 0, 57, 67, 0, 0, 88, 67, 0, 0, 180, 66, 0, 0, 88, 67, 0, 0, 182, 66, 0, 0, 88, 67, 0, 0, 184, 66, 0, 0, 88, 67, 0, 0, 186, 66, 0, 0, 88, 67, 0, 0, 188, 66, 0, 0, 88, 67, 0, 0, 190, 66, 0, 0, 88, 67, 0, 0, 192, 66, 0, 0, 88, 67, 0, 0, 194, 66, 0, 0, 88, 67, 0, 0, 196, 66, 0, 0, 88, 67, 0, 0, 198, 66, 0, 0, 88, 67, 0, 0, 200, 66, 0, 0, 88, 67, 0, 0, 202, 66, 0, 0, 88, 67, 0, 0, 204, 66, 0, 0, 88, 67, 0, 0, 206, 66, 0, 0, 88, 67, 0, 0, 208, 66, 0, 0, 88, 67, 0, 0, 210, 66, 0, 0, 88, 67, 0, 0, 212, 66, 0, 0, 88, 67, 0, 0, 214, 66, 0, 0, 88, 67, 0, 0, 216, 66, 0, 0, 88, 67, 0, 0, 218, 66, 0, 0, 88, 67, 0, 0, 220, 66, 0, 0, 88, 67, 0, 0, 222, 66, 0, 0, 88, 67, 0, 0, 224, 66, 0, 0, 88, 67, 0, 0, 226, 66, 0, 0, 88, 67, 0, 0, 228, 66, 0, 0, 88, 67, 0, 0, 230, 66, 0, 0, 88, 67, 0, 0, 232, 66, 0, 0, 88, 67, 0, 0, 234, 66, 0, 0, 88, 67, 0, 0, 236, 66, 0, 0, 88, 67, 0, 0, 238, 66, 0, 0, 88, 67, 0, 0, 240, 66, 0, 0, 88, 67, 0, 0, 242, 66, 0, 0, 88, 67, 0, 0, 244, 66, 0, 0, 88, 67, 0, 0, 246, 66, 0, 0, 88, 67, 0, 0, 248, 66, 0, 0, 88, 67, 0, 0, 250, 66, 0, 0, 88, 67, 0, 0, 252, 66, 0, 0, 88, 67, 0, 0, 254, 66, 0, 0, 88, 67, 0, 0, 0, 67, 0, 0, 88, 67, 0, 0, 1, 67, 0, 0, 88, 67, 0, 0, 2, 67, 0, 0, 88, 67, 0, 0, 3, 67, 0, 0, 88, 67, 0, 0, 4, 67, 0, 0, 88, 67, 0, 0, 5, 67, 0, 0, 88, 67, 0, 0, 6, 67, 0, 0, 88, 67, 0, 0, 7, 67, 0, 0, 88, 67, 0, 0, 8, 67, 0, 0, 88, 67, 0, 0, 9, 67, 0, 0, 88, 67, 0, 0, 10, 67, 0, 0, 88, 67, 0, 0, 11, 67, 0, 0, 88, 67, 0, 0, 12, 67, 0, 0, 88, 67, 0, 0, 13, 67, 0, 0, 88, 67, 0, 0, 14, 67, 0, 0, 88, 67, 0, 0, 15, 67, 0, 0, 88, 67, 0, 0, 16, 67, 0, 0, 88, 67, 0, 0, 17, 67, 0, 0, 88, 67, 0, 0, 18, 67, 0, 0, 88, 67, 0, 0, 19, 67, 0, 0, 88, 67, 0, 0, 20, 67, 0, 0, 88, 67, 0, 0, 21, 67, 0, 0, 88, 67, 0, 0, 22, 67, 0, 0, 88, 67, 0, 0, 23, 67, 0, 0, 88, 67, 0, 0, 24, 67, 0, 0, 88, 67, 0, 0, 25, 67, 0, 0, 88, 67, 0, 0, 26, 67, 0, 0, 88, 67, 0, 0, 27, 67, 0, 0, 88, 67, 0, 0, 35, 67, 0, 0, 88, 67, 0, 0, 36, 67, 0, 0, 88, 67, 0, 0, 37, 67, 0, 0, 88, 67, 0, 0, 38, 67, 0, 0, 88, 67, 0, 0, 39, 67, 0, 0, 88, 67, 0, 0, 40, 67, 0, 0, 88, 67, 0, 0, 41, 67, 0, 0, 88, 67, 0, 0, 42, 67, 0, 0, 88, 67, 0, 0, 43, 67, 0, 0, 88, 67, 0, 0, 44, 67, 0, 0, 88, 67, 0, 0, 45, 67, 0, 0, 88, 67, 0, 0, 46, 67, 0, 0, 88, 67, 0, 0, 47, 67, 0, 0, 88, 67, 0, 0, 48, 67, 0, 0, 88, 67, 0, 0, 49, 67, 0, 0, 88, 67, 0, 0, 50, 67, 0, 0, 88, 67, 0, 0, 51, 67, 0, 0, 88, 67, 0, 0, 52, 67, 0, 0, 88, 67, 0, 0, 53, 67, 0, 0, 88, 67, 0, 0, 54, 67, 0, 0, 88, 67, 0, 0, 55, 67, 0, 0, 88, 67, 0, 0, 56, 67, 0, 0, 89, 67, 0, 0, 182, 66, 0, 0, 89, 67, 0, 0, 184, 66, 0, 0, 89, 67, 0, 0, 186, 66, 0, 0, 89, 67, 0, 0, 188, 66, 0, 0, 89, 67, 0, 0, 190, 66, 0, 0, 89, 67, 0, 0, 192, 66, 0, 0, 89, 67, 0, 0, 194, 66, 0, 0, 89, 67, 0, 0, 196, 66, 0, 0, 89, 67, 0, 0, 198, 66, 0, 0, 89, 67, 0, 0, 200, 66, 0, 0, 89, 67, 0, 0, 202, 66, 0, 0, 89, 67, 0, 0, 204, 66, 0, 0, 89, 67, 0, 0, 206, 66, 0, 0, 89, 67, 0, 0, 208, 66, 0, 0, 89, 67, 0, 0, 210, 66, 0, 0, 89, 67, 0, 0, 212, 66, 0, 0, 89, 67, 0, 0, 214, 66, 0, 0, 89, 67, 0, 0, 216, 66, 0, 0, 89, 67, 0, 0, 218, 66, 0, 0, 89, 67, 0, 0, 220, 66, 0, 0, 89, 67, 0, 0, 222, 66, 0, 0, 89, 67, 0, 0, 224, 66, 0, 0, 89, 67, 0, 0, 226, 66, 0, 0, 89, 67, 0, 0, 228, 66, 0, 0, 89, 67, 0, 0, 230, 66, 0, 0, 89, 67, 0, 0, 232, 66, 0, 0, 89, 67, 0, 0, 234, 66, 0, 0, 89, 67, 0, 0, 236, 66, 0, 0, 89, 67, 0, 0, 238, 66, 0, 0, 89, 67, 0, 0, 240, 66, 0, 0, 89, 67, 0, 0, 242, 66, 0, 0, 89, 67, 0, 0, 244, 66, 0, 0, 89, 67, 0, 0, 246, 66, 0, 0, 89, 67, 0, 0, 248, 66, 0, 0, 89, 67, 0, 0, 250, 66, 0, 0, 89, 67, 0, 0, 252, 66, 0, 0, 89, 67, 0, 0, 254, 66, 0, 0, 89, 67, 0, 0, 0, 67, 0, 0, 89, 67, 0, 0, 1, 67, 0, 0, 89, 67, 0, 0, 2, 67, 0, 0, 89, 67, 0, 0, 3, 67, 0, 0, 89, 67, 0, 0, 4, 67, 0, 0, 89, 67, 0, 0, 5, 67, 0, 0, 89, 67, 0, 0, 6, 67, 0, 0, 89, 67, 0, 0, 7, 67, 0, 0, 89, 67, 0, 0, 8, 67, 0, 0, 89, 67, 0, 0, 9, 67, 0, 0, 89, 67, 0, 0, 10, 67, 0, 0, 89, 67, 0, 0, 11, 67, 0, 0, 89, 67, 0, 0, 12, 67, 0, 0, 89, 67, 0, 0, 13, 67, 0, 0, 89, 67, 0, 0, 14, 67, 0, 0, 89, 67, 0, 0, 15, 67, 0, 0, 89, 67, 0, 0, 16, 67, 0, 0, 89, 67, 0, 0, 17, 67, 0, 0, 89, 67, 0, 0, 18, 67, 0, 0, 89, 67, 0, 0, 19, 67, 0, 0, 89, 67, 0, 0, 20, 67, 0, 0, 89, 67, 0, 0, 21, 67, 0, 0, 89, 67, 0, 0, 22, 67, 0, 0, 89, 67, 0, 0, 23, 67, 0, 0, 89, 67, 0, 0, 24, 67, 0, 0, 89, 67, 0, 0, 25, 67, 0, 0, 89, 67, 0, 0, 26, 67, 0, 0, 89, 67, 0, 0, 36, 67, 0, 0, 89, 67, 0, 0, 37, 67, 0, 0, 89, 67, 0, 0, 38, 67, 0, 0, 89, 67, 0, 0, 39, 67, 0, 0, 89, 67, 0, 0, 40, 67, 0, 0, 89, 67, 0, 0, 41, 67, 0, 0, 89, 67, 0, 0, 42, 67, 0, 0, 89, 67, 0, 0, 43, 67, 0, 0, 89, 67, 0, 0, 44, 67, 0, 0, 89, 67, 0, 0, 45, 67, 0, 0, 89, 67, 0, 0, 46, 67, 0, 0, 89, 67, 0, 0, 47, 67, 0, 0, 89, 67, 0, 0, 48, 67, 0, 0, 89, 67, 0, 0, 49, 67, 0, 0, 89, 67, 0, 0, 50, 67, 0, 0, 89, 67, 0, 0, 51, 67, 0, 0, 89, 67, 0, 0, 52, 67, 0, 0, 89, 67, 0, 0, 53, 67, 0, 0, 89, 67, 0, 0, 54, 67, 0, 0, 89, 67, 0, 0, 55, 67, 0, 0, 90, 67, 0, 0, 184, 66, 0, 0, 90, 67, 0, 0, 186, 66, 0, 0, 90, 67, 0, 0, 188, 66, 0, 0, 90, 67, 0, 0, 190, 66, 0, 0, 90, 67, 0, 0, 192, 66, 0, 0, 90, 67, 0, 0, 194, 66, 0, 0, 90, 67, 0, 0, 196, 66, 0, 0, 90, 67, 0, 0, 198, 66, 0, 0, 90, 67, 0, 0, 200, 66, 0, 0, 90, 67, 0, 0, 202, 66, 0, 0, 90, 67, 0, 0, 204, 66, 0, 0, 90, 67, 0, 0, 206, 66, 0, 0, 90, 67, 0, 0, 208, 66, 0, 0, 90, 67, 0, 0, 210, 66, 0, 0, 90, 67, 0, 0, 212, 66, 0, 0, 90, 67, 0, 0, 214, 66, 0, 0, 90, 67, 0, 0, 216, 66, 0, 0, 90, 67, 0, 0, 218, 66, 0, 0, 90, 67, 0, 0, 220, 66, 0, 0, 90, 67, 0, 0, 222, 66, 0, 0, 90, 67, 0, 0, 224, 66, 0, 0, 90, 67, 0, 0, 226, 66, 0, 0, 90, 67, 0, 0, 228, 66, 0, 0, 90, 67, 0, 0, 230, 66, 0, 0, 90, 67, 0, 0, 232, 66, 0, 0, 90, 67, 0, 0, 234, 66, 0, 0, 90, 67, 0, 0, 236, 66, 0, 0, 90, 67, 0, 0, 238, 66, 0, 0, 90, 67, 0, 0, 240, 66, 0, 0, 90, 67, 0, 0, 242, 66, 0, 0, 90, 67, 0, 0, 244, 66, 0, 0, 90, 67, 0, 0, 246, 66, 0, 0, 90, 67, 0, 0, 248, 66, 0, 0, 90, 67, 0, 0, 250, 66, 0, 0, 90, 67, 0, 0, 252, 66, 0, 0, 90, 67, 0, 0, 254, 66, 0, 0, 90, 67, 0, 0, 0, 67, 0, 0, 90, 67, 0, 0, 1, 67, 0, 0, 90, 67, 0, 0, 2, 67, 0, 0, 90, 67, 0, 0, 3, 67, 0, 0, 90, 67, 0, 0, 4, 67, 0, 0, 90, 67, 0, 0, 5, 67, 0, 0, 90, 67, 0, 0, 6, 67, 0, 0, 90, 67, 0, 0, 7, 67, 0, 0, 90, 67, 0, 0, 8, 67, 0, 0, 90, 67, 0, 0, 9, 67, 0, 0, 90, 67, 0, 0, 10, 67, 0, 0, 90, 67, 0, 0, 11, 67, 0, 0, 90, 67, 0, 0, 12, 67, 0, 0, 90, 67, 0, 0, 13, 67, 0, 0, 90, 67, 0, 0, 14, 67, 0, 0, 90, 67, 0, 0, 15, 67, 0, 0, 90, 67, 0, 0, 36, 67, 0, 0, 90, 67, 0, 0, 37, 67, 0, 0, 90, 67, 0, 0, 38, 67, 0, 0, 90, 67, 0, 0, 39, 67, 0, 0, 90, 67, 0, 0, 40, 67, 0, 0, 90, 67, 0, 0, 41, 67, 0, 0, 90, 67, 0, 0, 42, 67, 0, 0, 90, 67, 0, 0, 43, 67, 0, 0, 90, 67, 0, 0, 44, 67, 0, 0, 90, 67, 0, 0, 45, 67, 0, 0, 90, 67, 0, 0, 46, 67, 0, 0, 90, 67, 0, 0, 47, 67, 0, 0, 90, 67, 0, 0, 48, 67, 0, 0, 90, 67, 0, 0, 49, 67, 0, 0, 90, 67, 0, 0, 50, 67, 0, 0, 90, 67, 0, 0, 51, 67, 0, 0, 90, 67, 0, 0, 52, 67, 0, 0, 90, 67, 0, 0, 53, 67, 0, 0, 90, 67, 0, 0, 54, 67, 0, 0, 90, 67, 0, 0, 55, 67, 0, 0, 91, 67, 0, 0, 184, 66, 0, 0, 91, 67, 0, 0, 186, 66, 0, 0, 91, 67, 0, 0, 188, 66, 0, 0, 91, 67, 0, 0, 190, 66, 0, 0, 91, 67, 0, 0, 192, 66, 0, 0, 91, 67, 0, 0, 194, 66, 0, 0, 91, 67, 0, 0, 196, 66, 0, 0, 91, 67, 0, 0, 198, 66, 0, 0, 91, 67, 0, 0, 200, 66, 0, 0, 91, 67, 0, 0, 202, 66, 0, 0, 91, 67, 0, 0, 204, 66, 0, 0, 91, 67, 0, 0, 206, 66, 0, 0, 91, 67, 0, 0, 208, 66, 0, 0, 91, 67, 0, 0, 210, 66, 0, 0, 91, 67, 0, 0, 212, 66, 0, 0, 91, 67, 0, 0, 214, 66, 0, 0, 91, 67, 0, 0, 216, 66, 0, 0, 91, 67, 0, 0, 218, 66, 0, 0, 91, 67, 0, 0, 220, 66, 0, 0, 91, 67, 0, 0, 222, 66, 0, 0, 91, 67, 0, 0, 224, 66, 0, 0, 91, 67, 0, 0, 226, 66, 0, 0, 91, 67, 0, 0, 228, 66, 0, 0, 91, 67, 0, 0, 230, 66, 0, 0, 91, 67, 0, 0, 232, 66, 0, 0, 91, 67, 0, 0, 234, 66, 0, 0, 91, 67, 0, 0, 236, 66, 0, 0, 91, 67, 0, 0, 238, 66, 0, 0, 91, 67, 0, 0, 240, 66, 0, 0, 91, 67, 0, 0, 242, 66, 0, 0, 91, 67, 0, 0, 244, 66, 0, 0, 91, 67, 0, 0, 246, 66, 0, 0, 91, 67, 0, 0, 248, 66, 0, 0, 91, 67, 0, 0, 250, 66, 0, 0, 91, 67, 0, 0, 252, 66, 0, 0, 91, 67, 0, 0, 254, 66, 0, 0, 91, 67, 0, 0, 0, 67, 0, 0, 91, 67, 0, 0, 1, 67, 0, 0, 91, 67, 0, 0, 2, 67, 0, 0, 91, 67, 0, 0, 3, 67, 0, 0, 91, 67, 0, 0, 4, 67, 0, 0, 91, 67, 0, 0, 5, 67, 0, 0, 91, 67, 0, 0, 6, 67, 0, 0, 91, 67, 0, 0, 7, 67, 0, 0, 91, 67, 0, 0, 8, 67, 0, 0, 91, 67, 0, 0, 9, 67, 0, 0, 91, 67, 0, 0, 10, 67, 0, 0, 91, 67, 0, 0, 37, 67, 0, 0, 91, 67, 0, 0, 38, 67, 0, 0, 91, 67, 0, 0, 39, 67, 0, 0, 91, 67, 0, 0, 40, 67, 0, 0, 91, 67, 0, 0, 41, 67, 0, 0, 91, 67, 0, 0, 42, 67, 0, 0, 91, 67, 0, 0, 43, 67, 0, 0, 91, 67, 0, 0, 44, 67, 0, 0, 91, 67, 0, 0, 45, 67, 0, 0, 91, 67, 0, 0, 46, 67, 0, 0, 91, 67, 0, 0, 47, 67, 0, 0, 91, 67, 0, 0, 48, 67, 0, 0, 91, 67, 0, 0, 49, 67, 0, 0, 91, 67, 0, 0, 50, 67, 0, 0, 91, 67, 0, 0, 51, 67, 0, 0, 91, 67, 0, 0, 52, 67, 0, 0, 91, 67, 0, 0, 53, 67, 0, 0, 91, 67, 0, 0, 54, 67, 0, 0, 92, 67, 0, 0, 186, 66, 0, 0, 92, 67, 0, 0, 188, 66, 0, 0, 92, 67, 0, 0, 190, 66, 0, 0, 92, 67, 0, 0, 192, 66, 0, 0, 92, 67, 0, 0, 194, 66, 0, 0, 92, 67, 0, 0, 196, 66, 0, 0, 92, 67, 0, 0, 198, 66, 0, 0, 92, 67, 0, 0, 200, 66, 0, 0, 92, 67, 0, 0, 202, 66, 0, 0, 92, 67, 0, 0, 204, 66, 0, 0, 92, 67, 0, 0, 206, 66, 0, 0, 92, 67, 0, 0, 208, 66, 0, 0, 92, 67, 0, 0, 210, 66, 0, 0, 92, 67, 0, 0, 212, 66, 0, 0, 92, 67, 0, 0, 214, 66, 0, 0, 92, 67, 0, 0, 216, 66, 0, 0, 92, 67, 0, 0, 218, 66, 0, 0, 92, 67, 0, 0, 220, 66, 0, 0, 92, 67, 0, 0, 222, 66, 0, 0, 92, 67, 0, 0, 224, 66, 0, 0, 92, 67, 0, 0, 226, 66, 0, 0, 92, 67, 0, 0, 228, 66, 0, 0, 92, 67, 0, 0, 230, 66, 0, 0, 92, 67, 0, 0, 232, 66, 0, 0, 92, 67, 0, 0, 234, 66, 0, 0, 92, 67, 0, 0, 236, 66, 0, 0, 92, 67, 0, 0, 238, 66, 0, 0, 92, 67, 0, 0, 240, 66, 0, 0, 92, 67, 0, 0, 242, 66, 0, 0, 92, 67, 0, 0, 244, 66, 0, 0, 92, 67, 0, 0, 246, 66, 0, 0, 92, 67, 0, 0, 248, 66, 0, 0, 92, 67, 0, 0, 250, 66, 0, 0, 92, 67, 0, 0, 252, 66, 0, 0, 92, 67, 0, 0, 254, 66, 0, 0, 92, 67, 0, 0, 0, 67, 0, 0, 92, 67, 0, 0, 1, 67, 0, 0, 92, 67, 0, 0, 2, 67, 0, 0, 92, 67, 0, 0, 3, 67, 0, 0, 92, 67, 0, 0, 38, 67, 0, 0, 92, 67, 0, 0, 39, 67, 0, 0, 92, 67, 0, 0, 40, 67, 0, 0, 92, 67, 0, 0, 41, 67, 0, 0, 92, 67, 0, 0, 42, 67, 0, 0, 92, 67, 0, 0, 43, 67, 0, 0, 92, 67, 0, 0, 44, 67, 0, 0, 92, 67, 0, 0, 45, 67, 0, 0, 92, 67, 0, 0, 46, 67, 0, 0, 92, 67, 0, 0, 47, 67, 0, 0, 92, 67, 0, 0, 48, 67, 0, 0, 92, 67, 0, 0, 49, 67, 0, 0, 92, 67, 0, 0, 50, 67, 0, 0, 92, 67, 0, 0, 51, 67, 0, 0, 92, 67, 0, 0, 52, 67, 0, 0, 92, 67, 0, 0, 53, 67, 0, 0, 93, 67, 0, 0, 188, 66, 0, 0, 93, 67, 0, 0, 190, 66, 0, 0, 93, 67, 0, 0, 192, 66, 0, 0, 93, 67, 0, 0, 194, 66, 0, 0, 93, 67, 0, 0, 196, 66, 0, 0, 93, 67, 0, 0, 198, 66, 0, 0, 93, 67, 0, 0, 200, 66, 0, 0, 93, 67, 0, 0, 202, 66, 0, 0, 93, 67, 0, 0, 204, 66, 0, 0, 93, 67, 0, 0, 206, 66, 0, 0, 93, 67, 0, 0, 208, 66, 0, 0, 93, 67, 0, 0, 210, 66, 0, 0, 93, 67, 0, 0, 212, 66, 0, 0, 93, 67, 0, 0, 214, 66, 0, 0, 93, 67, 0, 0, 216, 66, 0, 0, 93, 67, 0, 0, 218, 66, 0, 0, 93, 67, 0, 0, 220, 66, 0, 0, 93, 67, 0, 0, 222, 66, 0, 0, 93, 67, 0, 0, 224, 66, 0, 0, 93, 67, 0, 0, 226, 66, 0, 0, 93, 67, 0, 0, 228, 66, 0, 0, 93, 67, 0, 0, 230, 66, 0, 0, 93, 67, 0, 0, 232, 66, 0, 0, 93, 67, 0, 0, 234, 66, 0, 0, 93, 67, 0, 0, 236, 66, 0, 0, 93, 67, 0, 0, 238, 66, 0, 0, 93, 67, 0, 0, 240, 66, 0, 0, 93, 67, 0, 0, 242, 66, 0, 0, 93, 67, 0, 0, 244, 66, 0, 0, 93, 67, 0, 0, 246, 66, 0, 0, 93, 67, 0, 0, 248, 66, 0, 0, 93, 67, 0, 0, 250, 66, 0, 0, 93, 67, 0, 0, 252, 66, 0, 0, 93, 67, 0, 0, 254, 66, 0, 0, 93, 67, 0, 0, 0, 67, 0, 0, 93, 67, 0, 0, 39, 67, 0, 0, 93, 67, 0, 0, 40, 67, 0, 0, 93, 67, 0, 0, 41, 67, 0, 0, 93, 67, 0, 0, 42, 67, 0, 0, 93, 67, 0, 0, 43, 67, 0, 0, 93, 67, 0, 0, 44, 67, 0, 0, 93, 67, 0, 0, 45, 67, 0, 0, 93, 67, 0, 0, 46, 67, 0, 0, 93, 67, 0, 0, 47, 67, 0, 0, 93, 67, 0, 0, 48, 67, 0, 0, 93, 67, 0, 0, 49, 67, 0, 0, 93, 67, 0, 0, 50, 67, 0, 0, 93, 67, 0, 0, 51, 67, 0, 0, 93, 67, 0, 0, 52, 67, 0, 0, 94, 67, 0, 0, 190, 66, 0, 0, 94, 67, 0, 0, 192, 66, 0, 0, 94, 67, 0, 0, 194, 66, 0, 0, 94, 67, 0, 0, 196, 66, 0, 0, 94, 67, 0, 0, 198, 66, 0, 0, 94, 67, 0, 0, 200, 66, 0, 0, 94, 67, 0, 0, 202, 66, 0, 0, 94, 67, 0, 0, 204, 66, 0, 0, 94, 67, 0, 0, 206, 66, 0, 0, 94, 67, 0, 0, 208, 66, 0, 0, 94, 67, 0, 0, 210, 66, 0, 0, 94, 67, 0, 0, 212, 66, 0, 0, 94, 67, 0, 0, 214, 66, 0, 0, 94, 67, 0, 0, 216, 66, 0, 0, 94, 67, 0, 0, 218, 66, 0, 0, 94, 67, 0, 0, 220, 66, 0, 0, 94, 67, 0, 0, 222, 66, 0, 0, 94, 67, 0, 0, 224, 66, 0, 0, 94, 67, 0, 0, 226, 66, 0, 0, 94, 67, 0, 0, 228, 66, 0, 0, 94, 67, 0, 0, 230, 66, 0, 0, 94, 67, 0, 0, 232, 66, 0, 0, 94, 67, 0, 0, 234, 66, 0, 0, 94, 67, 0, 0, 236, 66, 0, 0, 94, 67, 0, 0, 238, 66, 0, 0, 94, 67, 0, 0, 240, 66, 0, 0, 94, 67, 0, 0, 242, 66, 0, 0, 94, 67, 0, 0, 244, 66, 0, 0, 94, 67, 0, 0, 41, 67, 0, 0, 94, 67, 0, 0, 42, 67, 0, 0, 94, 67, 0, 0, 43, 67, 0, 0, 94, 67, 0, 0, 44, 67, 0, 0, 94, 67, 0, 0, 45, 67, 0, 0, 94, 67, 0, 0, 46, 67, 0, 0, 94, 67, 0, 0, 47, 67, 0, 0, 94, 67, 0, 0, 48, 67, 0, 0, 94, 67, 0, 0, 49, 67, 0, 0, 94, 67, 0, 0, 50, 67, 0, 0, 95, 67, 0, 0, 192, 66, 0, 0, 95, 67, 0, 0, 194, 66, 0, 0, 95, 67, 0, 0, 196, 66, 0, 0, 95, 67, 0, 0, 198, 66, 0, 0, 95, 67, 0, 0, 200, 66, 0, 0, 95, 67, 0, 0, 202, 66, 0, 0, 95, 67, 0, 0, 204, 66, 0, 0, 95, 67, 0, 0, 206, 66, 0, 0, 95, 67, 0, 0, 208, 66, 0, 0, 95, 67, 0, 0, 210, 66, 0, 0, 95, 67, 0, 0, 212, 66, 0, 0, 95, 67, 0, 0, 214, 66, 0, 0, 95, 67, 0, 0, 216, 66, 0, 0, 95, 67, 0, 0, 218, 66, 0, 0, 95, 67, 0, 0, 220, 66, 0, 0, 95, 67, 0, 0, 222, 66, 0, 0, 95, 67, 0, 0, 224, 66, 0, 0, 95, 67, 0, 0, 226, 66, 0, 0, 95, 67, 0, 0, 228, 66, 0, 0, 95, 67, 0, 0, 230, 66, 0, 0, 95, 67, 0, 0, 232, 66, 0, 0, 95, 67, 0, 0, 234, 66, 0, 0, 95, 67, 0, 0, 236, 66, 0, 0, 95, 67, 0, 0, 238, 66, 0, 0, 95, 67, 0, 0, 42, 67, 0, 0, 95, 67, 0, 0, 43, 67, 0, 0, 95, 67, 0, 0, 44, 67, 0, 0, 95, 67, 0, 0, 45, 67, 0, 0, 95, 67, 0, 0, 46, 67, 0, 0, 95, 67, 0, 0, 47, 67, 0, 0, 95, 67, 0, 0, 48, 67, 0, 0, 95, 67, 0, 0, 49, 67, 0, 0, 96, 67, 0, 0, 196, 66, 0, 0, 96, 67, 0, 0, 198, 66, 0, 0, 96, 67, 0, 0, 200, 66, 0, 0, 96, 67, 0, 0, 202, 66, 0, 0, 96, 67, 0, 0, 204, 66, 0, 0, 96, 67, 0, 0, 206, 66, 0, 0, 96, 67, 0, 0, 208, 66, 0, 0, 96, 67, 0, 0, 210, 66, 0, 0, 96, 67, 0, 0, 212, 66, 0, 0, 96, 67, 0, 0, 214, 66, 0, 0, 96, 67, 0, 0, 216, 66, 0, 0, 96, 67, 0, 0, 218, 66, 0, 0, 96, 67, 0, 0, 220, 66, 0, 0, 96, 67, 0, 0, 222, 66, 0, 0, 96, 67, 0, 0, 224, 66, 0, 0, 96, 67, 0, 0, 226, 66, 0, 0, 97, 67, 0, 0, 200, 66, 0, 0, 97, 67, 0, 0, 202, 66, 0, 0, 97, 67, 0, 0, 204, 66, 0, 0, 97, 67, 0, 0, 206, 66, 0, 0, 97, 67, 0, 0, 208, 66, 0, 0, 97, 67, 0, 0, 210, 66, 0, 0, 97, 67, 0, 0, 212, 66, 0, 0, 97, 67, 0, 0, 214, 66, 0, 0, 97, 67, 0, 0, 216, 66, 0, 0, 97, 67, 0, 0, 218, 66, 0, 0, 97, 67, 0, 0, 220, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 255, 12, 255, 82, 255, 211, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 211, 255, 80, 255, 11, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 255, 12, 255, 82, 255, 211, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 211, 255, 80, 255, 11, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 70, 255, 208, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 209, 255, 74, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 7, 255, 38, 255, 96, 255, 183, 255, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 242, 255, 188, 255, 100, 255, 40, 255, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 5, 255, 23, 255, 93, 255, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 255, 91, 255, 22, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 5, 255, 23, 255, 93, 255, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 255, 91, 255, 22, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 3, 255, 17, 255, 87, 255, 212, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 213, 255, 88, 255, 19, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 25, 255, 117, 255, 186, 255, 231, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 232, 255, 187, 255, 118, 255, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 10, 255, 50, 255, 121, 255, 221, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 221, 255, 119, 255, 49, 255, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 10, 255, 50, 255, 121, 255, 221, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 221, 255, 119, 255, 49, 255, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 8, 255, 42, 255, 112, 255, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 219, 255, 114, 255, 44, 255, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 4, 255, 63, 255, 176, 255, 240, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 255, 176, 255, 62, 255, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 16, 255, 94, 255, 166, 255, 233, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 233, 255, 164, 255, 92, 255, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 16, 255, 94, 255, 166, 255, 233, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 233, 255, 164, 255, 92, 255, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 13, 255, 74, 255, 146, 255, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 229, 255, 151, 255, 79, 255, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 13, 255, 54, 255, 121, 255, 214, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 255, 118, 255, 50, 255, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 5, 255, 55, 255, 146, 255, 209, 255, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 255, 207, 255, 144, 255, 54, 255, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 5, 255, 55, 255, 146, 255, 209, 255, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 255, 207, 255, 144, 255, 54, 255, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 43, 255, 124, 255, 190, 255, 239, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 255, 194, 255, 128, 255, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 25, 255, 101, 255, 172, 255, 238, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 237, 255, 167, 255, 96, 255, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 5, 255, 58, 255, 125, 255, 205, 255, 248, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 248, 255, 205, 255, 124, 255, 57, 255, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 5, 255, 58, 255, 125, 255, 205, 255, 248, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 248, 255, 205, 255, 124, 255, 57, 255, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 34, 255, 99, 255, 193, 255, 244, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 244, 255, 190, 255, 92, 255, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 37, 255, 145, 255, 215, 255, 247, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 246, 255, 210, 255, 140, 255, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 4, 255, 14, 255, 21, 255, 25, 255, 29, 255, 34, 255, 39, 255, 43, 255, 73, 255, 130, 255, 186, 255, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 255, 186, 255, 130, 255, 73, 255, 42, 255, 39, 255, 34, 255, 29, 255, 25, 255, 21, 255, 14, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 4, 255, 14, 255, 21, 255, 25, 255, 29, 255, 34, 255, 39, 255, 43, 255, 73, 255, 130, 255, 186, 255, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 241, 255, 186, 255, 130, 255, 73, 255, 42, 255, 39, 255, 34, 255, 29, 255, 25, 255, 21, 255, 14, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 255, 4, 255, 14, 255, 21, 255, 23, 255, 27, 255, 33, 255, 39, 255, 44, 255, 67, 255, 106, 255, 162, 255, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 155, 255, 98, 255, 61, 255, 40, 255, 36, 255, 31, 255, 26, 255, 22, 255, 20, 255, 14, 255, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 45, 255, 175, 255, 245, 255, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 240, 255, 171, 255, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 15, 255, 58, 255, 87, 255, 100, 255, 117, 255, 137, 255, 159, 255, 181, 255, 203, 255, 222, 255, 239, 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 239, 255, 222, 255, 202, 255, 181, 255, 158, 255, 137, 255, 117, 255, 100, 255, 87, 255, 58, 255, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 15, 255, 58, 255, 87, 255, 100, 255, 117, 255, 137, 255, 159, 255, 181, 255, 203, 255, 222, 255, 239, 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 239, 255, 222, 255, 202, 255, 181, 255, 158, 255, 137, 255, 117, 255, 100, 255, 87, 255, 58, 255, 15, 0, 0, 0, 0, 0, 0, 0, 0, 255, 17, 255, 59, 255, 84, 255, 92, 255, 108, 255, 132, 255, 157, 255, 183, 255, 203, 255, 217, 255, 233, 255, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 231, 255, 213, 255, 194, 255, 173, 255, 148, 255, 125, 255, 104, 255, 89, 255, 82, 255, 58, 255, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 49, 255, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 188, 255, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 27, 255, 107, 255, 155, 255, 170, 255, 187, 255, 207, 255, 229, 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 229, 255, 207, 255, 187, 255, 170, 255, 155, 255, 107, 255, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 27, 255, 107, 255, 155, 255, 170, 255, 187, 255, 207, 255, 229, 255, 252, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 229, 255, 207, 255, 187, 255, 170, 255, 155, 255, 107, 255, 27, 0, 0, 0, 0, 0, 0, 0, 0, 255, 33, 255, 115, 255, 159, 255, 163, 255, 178, 255, 202, 255, 227, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 244, 255, 218, 255, 195, 255, 173, 255, 161, 255, 157, 255, 114, 255, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 51, 255, 199, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 197, 255, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 41, 255, 162, 255, 226, 255, 234, 255, 240, 255, 244, 255, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 244, 255, 240, 255, 234, 255, 226, 255, 162, 255, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 41, 255, 162, 255, 226, 255, 234, 255, 240, 255, 244, 255, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 249, 255, 244, 255, 240, 255, 234, 255, 226, 255, 162, 255, 41, 0, 0, 0, 0, 0, 0, 0, 0, 255, 52, 255, 183, 255, 244, 255, 237, 255, 236, 255, 242, 255, 249, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 247, 255, 241, 255, 235, 255, 236, 255, 244, 255, 182, 255, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 50, 255, 196, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 196, 255, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 47, 255, 187, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 187, 255, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 47, 255, 187, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 187, 255, 47, 0, 0, 0, 0, 0, 0, 0, 0, 255, 61, 255, 213, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 214, 255, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 47, 255, 185, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 186, 255, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 182, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 182, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 182, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 182, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 255, 60, 255, 208, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 208, 255, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 42, 255, 166, 255, 236, 255, 251, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 252, 255, 239, 255, 169, 255, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 255, 59, 255, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 205, 255, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 33, 255, 133, 255, 203, 255, 244, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 245, 255, 208, 255, 137, 255, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 255, 59, 255, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 205, 255, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 21, 255, 86, 255, 157, 255, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 236, 255, 163, 255, 92, 255, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 255, 59, 255, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 205, 255, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 10, 255, 42, 255, 108, 255, 209, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 212, 255, 114, 255, 47, 255, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 46, 255, 180, 255, 250, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 250, 255, 180, 255, 46, 0, 0, 0, 0, 0, 0, 0, 0, 255, 59, 255, 205, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 205, 255, 59, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 57, 255, 168, 255, 234, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 255, 173, 255, 60, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 47, 255, 184, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 184, 255, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 47, 255, 184, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 184, 255, 47, 0, 0, 0, 0, 0, 0, 0, 0, 255, 60, 255, 210, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 210, 255, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 23, 255, 109, 255, 177, 255, 228, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 231, 255, 184, 255, 115, 255, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 49, 255, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 49, 255, 192, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 192, 255, 49, 0, 0, 0, 0, 0, 0, 0, 0, 255, 63, 255, 219, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 219, 255, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 6, 255, 33, 255, 90, 255, 179, 255, 235, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 238, 255, 184, 255, 96, 255, 37, 255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 36, 255, 143, 255, 199, 255, 203, 255, 205, 255, 204, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 204, 255, 205, 255, 203, 255, 199, 255, 143, 255, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 36, 255, 143, 255, 199, 255, 203, 255, 205, 255, 204, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 204, 255, 205, 255, 203, 255, 199, 255, 143, 255, 36, 0, 0, 0, 0, 0, 0, 0, 0, 255, 47, 255, 163, 255, 217, 255, 208, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 203, 255, 208, 255, 217, 255, 163, 255, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 33, 255, 110, 255, 170, 255, 211, 255, 237, 255, 246, 255, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 255, 246, 255, 237, 255, 213, 255, 173, 255, 115, 255, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 9, 255, 37, 255, 51, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 51, 255, 37, 255, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 9, 255, 37, 255, 51, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 51, 255, 37, 255, 9, 0, 0, 0, 0, 0, 0, 0, 0, 255, 12, 255, 42, 255, 55, 255, 53, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 52, 255, 53, 255, 55, 255, 42, 255, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 6, 255, 23, 255, 59, 255, 114, 255, 164, 255, 210, 255, 241, 255, 255, 255, 255, 255, 255, 255, 255, 255, 242, 255, 211, 255, 168, 255, 117, 255, 61, 255, 24, 255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 3, 255, 48, 255, 93, 255, 140, 255, 171, 255, 188, 255, 197, 255, 197, 255, 189, 255, 172, 255, 141, 255, 96, 255, 50, 255, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 11, 255, 23, 255, 35, 255, 44, 255, 48, 255, 50, 255, 50, 255, 48, 255, 44, 255, 36, 255, 24, 255, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), "format": "RGFloat", @@ -183,7 +181,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_4v5mq"] -image = SubResource("Image_74irx") +image = SubResource("Image_r68lw") [sub_resource type="ParticleProcessMaterial" id="28"] emission_shape = 4 @@ -192,7 +190,7 @@ emission_point_count = 10554 gravity = Vector3(0, 0, 0) color = Color(1, 0.550781, 0.550781, 1) -[sub_resource type="Image" id="Image_81f5r"] +[sub_resource type="Image" id="Image_gtq67"] data = { "data": PackedByteArray(242, 4, 53, 191, 244, 4, 53, 191, 6, 238, 108, 191, 252, 232, 193, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 97, 227, 108, 191, 248, 28, 194, 62, 145, 189, 94, 191, 194, 94, 252, 190, 225, 194, 125, 191, 221, 32, 7, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 6, 238, 108, 191, 252, 232, 193, 62, 243, 4, 53, 191, 243, 4, 53, 63, 252, 232, 193, 190, 6, 238, 108, 191, 224, 72, 102, 191, 187, 166, 223, 62, 243, 4, 53, 191, 243, 4, 53, 63, 193, 94, 252, 190, 145, 189, 94, 191, 243, 4, 53, 191, 243, 4, 53, 191, 251, 232, 193, 190, 6, 238, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 187, 166, 223, 190, 224, 72, 102, 63, 247, 28, 194, 190, 97, 227, 108, 63, 8, 157, 132, 190, 141, 67, 119, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 221, 32, 7, 190, 225, 194, 125, 63, 200, 37, 122, 190, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 52, 187, 131, 190, 185, 97, 119, 191, 10, 165, 146, 190, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 220, 32, 7, 190, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 225, 158, 0, 190, 248, 248, 125, 63, 224, 158, 0, 190, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 244, 167, 193, 190, 82, 251, 108, 63, 200, 37, 122, 190, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 228, 113, 23, 191, 20, 102, 78, 63, 7, 59, 27, 191, 30, 145, 75, 63, 193, 94, 252, 190, 145, 189, 94, 191, 178, 171, 227, 190, 65, 76, 101, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 191, 242, 4, 53, 63, 243, 4, 53, 191, 243, 4, 53, 63, 56, 169, 30, 191, 153, 231, 72, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 191, 242, 4, 53, 63, 30, 145, 75, 191, 7, 59, 27, 63, 77, 191, 75, 191, 100, 254, 26, 191, 153, 231, 72, 191, 56, 169, 30, 191, 244, 4, 53, 191, 244, 4, 53, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 21, 102, 78, 191, 227, 113, 23, 63, 117, 233, 92, 191, 16, 92, 1, 63, 97, 227, 108, 191, 248, 28, 194, 62, 145, 189, 94, 191, 193, 94, 252, 190, 74, 151, 80, 191, 51, 105, 20, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 65, 76, 101, 191, 178, 171, 227, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 248, 248, 125, 191, 225, 158, 0, 190, 82, 251, 108, 191, 244, 167, 193, 190, 21, 102, 78, 191, 228, 113, 23, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 65, 76, 101, 63, 178, 171, 227, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 125, 62, 120, 63, 200, 37, 122, 190, 212, 127, 93, 63, 237, 89, 0, 191, 243, 4, 53, 63, 244, 4, 53, 191, 244, 4, 53, 63, 244, 4, 53, 63, 212, 127, 93, 63, 237, 89, 0, 63, 125, 62, 120, 63, 200, 37, 122, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 248, 248, 125, 63, 224, 158, 0, 190, 82, 251, 108, 63, 244, 167, 193, 190, 20, 102, 78, 63, 228, 113, 23, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 21, 102, 78, 63, 228, 113, 23, 63, 117, 233, 92, 63, 16, 92, 1, 63, 98, 227, 108, 63, 248, 28, 194, 62, 235, 89, 0, 63, 213, 127, 93, 191, 237, 89, 0, 63, 212, 127, 93, 63, 145, 189, 94, 63, 194, 94, 252, 190, 74, 151, 80, 63, 51, 105, 20, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 63, 243, 4, 53, 63, 30, 145, 75, 63, 7, 59, 27, 63, 201, 37, 122, 62, 125, 62, 120, 191, 201, 37, 122, 62, 125, 62, 120, 63, 78, 191, 75, 63, 99, 254, 26, 191, 152, 231, 72, 63, 57, 169, 30, 191, 243, 4, 53, 63, 244, 4, 53, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 63, 243, 4, 53, 63, 243, 4, 53, 63, 243, 4, 53, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 55, 169, 30, 63, 153, 231, 72, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 228, 113, 23, 63, 21, 102, 78, 63, 7, 59, 27, 63, 30, 145, 75, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 193, 94, 252, 62, 145, 189, 94, 191, 178, 171, 227, 62, 65, 76, 101, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 244, 167, 193, 62, 82, 251, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 201, 37, 122, 62, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 227, 158, 0, 62, 248, 248, 125, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 227, 158, 0, 62, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 221, 32, 7, 62, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 52, 187, 131, 62, 185, 97, 119, 191, 10, 165, 146, 62, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 222, 32, 7, 62, 225, 194, 125, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 201, 37, 122, 62, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 187, 166, 223, 62, 224, 72, 102, 63, 247, 28, 194, 62, 97, 227, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 9, 157, 132, 62, 140, 67, 119, 191, 14, 82, 8, 50, 0, 0, 128, 63, 251, 232, 193, 62, 6, 238, 108, 191, 224, 72, 102, 63, 187, 166, 223, 62, 243, 4, 53, 63, 243, 4, 53, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 193, 94, 252, 62, 145, 189, 94, 191, 243, 4, 53, 63, 243, 4, 53, 191, 252, 232, 193, 62, 6, 238, 108, 63, 242, 4, 53, 63, 244, 4, 53, 191, 6, 238, 108, 63, 251, 232, 193, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 98, 227, 108, 63, 248, 28, 194, 62, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 145, 189, 94, 63, 191, 94, 252, 190, 225, 194, 125, 63, 220, 32, 7, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 6, 238, 108, 63, 251, 232, 193, 62, 243, 4, 53, 63, 243, 4, 53, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 242, 4, 53, 191, 244, 4, 53, 191, 6, 238, 108, 191, 252, 232, 193, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 97, 227, 108, 191, 248, 28, 194, 62, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 145, 189, 94, 191, 194, 94, 252, 190, 225, 194, 125, 191, 221, 32, 7, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 6, 238, 108, 191, 252, 232, 193, 62, 243, 4, 53, 191, 243, 4, 53, 63, 252, 232, 193, 190, 6, 238, 108, 191, 224, 72, 102, 191, 187, 166, 223, 62, 243, 4, 53, 191, 243, 4, 53, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 193, 94, 252, 190, 145, 189, 94, 191, 243, 4, 53, 191, 243, 4, 53, 191, 251, 232, 193, 190, 6, 238, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 187, 166, 223, 190, 224, 72, 102, 63, 247, 28, 194, 190, 97, 227, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 8, 157, 132, 190, 141, 67, 119, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 221, 32, 7, 190, 225, 194, 125, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 200, 37, 122, 190, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 52, 187, 131, 190, 185, 97, 119, 191, 10, 165, 146, 190, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 220, 32, 7, 190, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 225, 158, 0, 190, 248, 248, 125, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 224, 158, 0, 190, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 244, 167, 193, 190, 82, 251, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 200, 37, 122, 190, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 228, 113, 23, 191, 20, 102, 78, 63, 7, 59, 27, 191, 30, 145, 75, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 193, 94, 252, 190, 145, 189, 94, 191, 178, 171, 227, 190, 65, 76, 101, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 191, 242, 4, 53, 63, 243, 4, 53, 191, 243, 4, 53, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 56, 169, 30, 191, 153, 231, 72, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 191, 242, 4, 53, 63, 30, 145, 75, 191, 7, 59, 27, 63, 200, 37, 122, 190, 125, 62, 120, 191, 201, 37, 122, 190, 125, 62, 120, 63, 77, 191, 75, 191, 100, 254, 26, 191, 153, 231, 72, 191, 56, 169, 30, 191, 244, 4, 53, 191, 244, 4, 53, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 21, 102, 78, 191, 227, 113, 23, 63, 117, 233, 92, 191, 16, 92, 1, 63, 97, 227, 108, 191, 248, 28, 194, 62, 236, 89, 0, 191, 213, 127, 93, 191, 237, 89, 0, 191, 212, 127, 93, 63, 145, 189, 94, 191, 193, 94, 252, 190, 74, 151, 80, 191, 51, 105, 20, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 65, 76, 101, 191, 178, 171, 227, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 125, 62, 120, 191, 201, 37, 122, 190, 213, 127, 93, 191, 236, 89, 0, 191, 244, 4, 53, 191, 244, 4, 53, 191, 244, 4, 53, 191, 243, 4, 53, 63, 212, 127, 93, 191, 236, 89, 0, 63, 125, 62, 120, 191, 201, 37, 122, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 248, 248, 125, 191, 225, 158, 0, 190, 82, 251, 108, 191, 244, 167, 193, 190, 21, 102, 78, 191, 228, 113, 23, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 65, 76, 101, 63, 178, 171, 227, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 248, 248, 125, 63, 224, 158, 0, 190, 82, 251, 108, 63, 244, 167, 193, 190, 20, 102, 78, 63, 228, 113, 23, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 21, 102, 78, 63, 228, 113, 23, 63, 117, 233, 92, 63, 16, 92, 1, 63, 98, 227, 108, 63, 248, 28, 194, 62, 145, 189, 94, 63, 194, 94, 252, 190, 74, 151, 80, 63, 51, 105, 20, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 63, 243, 4, 53, 63, 30, 145, 75, 63, 7, 59, 27, 63, 78, 191, 75, 63, 99, 254, 26, 191, 152, 231, 72, 63, 57, 169, 30, 191, 243, 4, 53, 63, 244, 4, 53, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 63, 243, 4, 53, 63, 243, 4, 53, 63, 243, 4, 53, 63, 55, 169, 30, 63, 153, 231, 72, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 228, 113, 23, 63, 21, 102, 78, 63, 7, 59, 27, 63, 30, 145, 75, 63, 193, 94, 252, 62, 145, 189, 94, 191, 178, 171, 227, 62, 65, 76, 101, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 244, 167, 193, 62, 82, 251, 108, 63, 201, 37, 122, 62, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 227, 158, 0, 62, 248, 248, 125, 63, 227, 158, 0, 62, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 221, 32, 7, 62, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 52, 187, 131, 62, 185, 97, 119, 191, 10, 165, 146, 62, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 222, 32, 7, 62, 225, 194, 125, 63, 201, 37, 122, 62, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 187, 166, 223, 62, 224, 72, 102, 63, 247, 28, 194, 62, 97, 227, 108, 63, 9, 157, 132, 62, 140, 67, 119, 191, 14, 82, 8, 50, 0, 0, 128, 63, 251, 232, 193, 62, 6, 238, 108, 191, 224, 72, 102, 63, 187, 166, 223, 62, 243, 4, 53, 63, 243, 4, 53, 63, 193, 94, 252, 62, 145, 189, 94, 191, 243, 4, 53, 63, 243, 4, 53, 191, 252, 232, 193, 62, 6, 238, 108, 63, 242, 4, 53, 63, 244, 4, 53, 191, 6, 238, 108, 63, 251, 232, 193, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 98, 227, 108, 63, 248, 28, 194, 62, 145, 189, 94, 63, 191, 94, 252, 190, 225, 194, 125, 63, 220, 32, 7, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 6, 238, 108, 63, 251, 232, 193, 62, 243, 4, 53, 63, 243, 4, 53, 63, 242, 4, 53, 191, 244, 4, 53, 191, 6, 238, 108, 191, 252, 232, 193, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 145, 189, 94, 191, 194, 94, 252, 62, 145, 189, 94, 191, 194, 94, 252, 190, 225, 194, 125, 191, 221, 32, 7, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 6, 238, 108, 191, 252, 232, 193, 62, 243, 4, 53, 191, 243, 4, 53, 63, 252, 232, 193, 190, 6, 238, 108, 191, 243, 4, 53, 191, 243, 4, 53, 63, 192, 94, 252, 190, 145, 189, 94, 63, 193, 94, 252, 190, 145, 189, 94, 191, 243, 4, 53, 191, 243, 4, 53, 191, 251, 232, 193, 190, 6, 238, 108, 63, 13, 82, 8, 50, 0, 0, 128, 191, 221, 32, 7, 190, 225, 194, 125, 63, 8, 157, 132, 190, 141, 67, 119, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 225, 158, 0, 190, 248, 248, 125, 63, 200, 37, 122, 190, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 201, 37, 122, 190, 125, 62, 120, 63, 52, 187, 131, 190, 185, 97, 119, 191, 10, 165, 146, 190, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 10, 165, 146, 190, 103, 70, 117, 63, 52, 187, 131, 190, 185, 97, 119, 63, 220, 32, 7, 190, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 221, 32, 7, 190, 225, 194, 125, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 225, 158, 0, 190, 248, 248, 125, 63, 224, 158, 0, 190, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 244, 167, 193, 190, 82, 251, 108, 63, 242, 167, 193, 190, 81, 251, 108, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 228, 113, 23, 191, 20, 102, 78, 63, 7, 59, 27, 191, 30, 145, 75, 63, 7, 59, 27, 191, 30, 145, 75, 191, 228, 113, 23, 191, 21, 102, 78, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 191, 242, 4, 53, 63, 30, 145, 75, 191, 7, 59, 27, 63, 30, 145, 75, 191, 7, 59, 27, 191, 243, 4, 53, 191, 243, 4, 53, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 21, 102, 78, 191, 227, 113, 23, 63, 117, 233, 92, 191, 16, 92, 1, 63, 97, 227, 108, 191, 248, 28, 194, 62, 97, 227, 108, 191, 247, 28, 194, 190, 117, 233, 92, 191, 16, 92, 1, 191, 21, 102, 78, 191, 228, 113, 23, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 65, 76, 101, 191, 178, 171, 227, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 248, 248, 125, 191, 225, 158, 0, 190, 125, 62, 120, 191, 201, 37, 122, 190, 65, 76, 101, 191, 178, 171, 227, 190, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 65, 76, 101, 63, 178, 171, 227, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 248, 248, 125, 63, 224, 158, 0, 190, 125, 62, 120, 63, 201, 37, 122, 190, 65, 76, 101, 63, 178, 171, 227, 190, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 21, 102, 78, 63, 228, 113, 23, 63, 117, 233, 92, 63, 16, 92, 1, 63, 98, 227, 108, 63, 248, 28, 194, 62, 98, 227, 108, 63, 247, 28, 194, 190, 117, 233, 92, 63, 16, 92, 1, 191, 20, 102, 78, 63, 228, 113, 23, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 243, 4, 53, 63, 243, 4, 53, 63, 30, 145, 75, 63, 7, 59, 27, 63, 30, 145, 75, 63, 8, 59, 27, 191, 242, 4, 53, 63, 243, 4, 53, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 228, 113, 23, 63, 21, 102, 78, 63, 7, 59, 27, 63, 30, 145, 75, 63, 8, 59, 27, 63, 30, 145, 75, 191, 227, 113, 23, 63, 21, 102, 78, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 244, 167, 193, 62, 82, 251, 108, 63, 244, 167, 193, 62, 82, 251, 108, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 227, 158, 0, 62, 248, 248, 125, 63, 227, 158, 0, 62, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 221, 32, 7, 62, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 222, 32, 7, 62, 225, 194, 125, 63, 52, 187, 131, 62, 185, 97, 119, 191, 10, 165, 146, 62, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 10, 165, 146, 62, 103, 70, 117, 63, 53, 187, 131, 62, 185, 97, 119, 63, 201, 37, 122, 62, 125, 62, 120, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 201, 37, 122, 62, 125, 62, 120, 63, 227, 158, 0, 62, 248, 248, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 9, 157, 132, 62, 140, 67, 119, 63, 221, 32, 7, 62, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 251, 232, 193, 62, 6, 238, 108, 191, 243, 4, 53, 63, 243, 4, 53, 63, 194, 94, 252, 62, 145, 189, 94, 63, 193, 94, 252, 62, 145, 189, 94, 191, 243, 4, 53, 63, 243, 4, 53, 191, 252, 232, 193, 62, 6, 238, 108, 63, 242, 4, 53, 63, 244, 4, 53, 191, 6, 238, 108, 63, 251, 232, 193, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 145, 189, 94, 63, 192, 94, 252, 62, 145, 189, 94, 63, 191, 94, 252, 190, 225, 194, 125, 63, 220, 32, 7, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 6, 238, 108, 63, 251, 232, 193, 62, 243, 4, 53, 63, 243, 4, 53, 63, 97, 227, 108, 191, 248, 28, 194, 190, 225, 194, 125, 191, 221, 32, 7, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 185, 97, 119, 191, 53, 187, 131, 62, 97, 227, 108, 191, 248, 28, 194, 190, 225, 194, 125, 191, 221, 32, 7, 190, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 97, 227, 108, 191, 248, 28, 194, 62, 145, 189, 94, 191, 193, 94, 252, 190, 224, 72, 102, 191, 187, 166, 223, 190, 103, 70, 117, 191, 10, 165, 146, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 225, 194, 125, 191, 222, 32, 7, 62, 185, 97, 119, 191, 53, 187, 131, 62, 145, 189, 94, 191, 193, 94, 252, 190, 224, 72, 102, 191, 187, 166, 223, 190, 224, 72, 102, 191, 187, 166, 223, 62, 145, 189, 94, 191, 193, 94, 252, 62, 97, 227, 108, 191, 248, 28, 194, 190, 140, 67, 119, 191, 8, 157, 132, 190, 82, 251, 108, 191, 244, 167, 193, 190, 21, 102, 78, 191, 228, 113, 23, 191, 103, 70, 117, 191, 10, 165, 146, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 185, 97, 119, 191, 53, 187, 131, 62, 53, 41, 94, 191, 190, 103, 254, 190, 117, 233, 92, 191, 16, 92, 1, 191, 21, 102, 78, 191, 228, 113, 23, 191, 21, 102, 78, 191, 227, 113, 23, 63, 117, 233, 92, 191, 16, 92, 1, 63, 53, 41, 94, 191, 192, 103, 254, 62, 77, 191, 75, 191, 100, 254, 26, 191, 224, 72, 102, 191, 187, 166, 223, 190, 103, 70, 117, 191, 10, 165, 146, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 225, 194, 125, 191, 222, 32, 7, 62, 185, 97, 119, 191, 53, 187, 131, 62, 77, 191, 75, 191, 100, 254, 26, 191, 74, 151, 80, 191, 51, 105, 20, 191, 74, 151, 80, 191, 51, 105, 20, 63, 77, 191, 75, 191, 100, 254, 26, 63, 100, 254, 26, 191, 77, 191, 75, 191, 243, 4, 53, 191, 243, 4, 53, 191, 103, 70, 117, 191, 10, 165, 146, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 185, 97, 119, 191, 53, 187, 131, 62, 100, 254, 26, 191, 77, 191, 75, 191, 243, 4, 53, 191, 243, 4, 53, 191, 243, 4, 53, 191, 242, 4, 53, 63, 100, 254, 26, 191, 77, 191, 75, 63, 191, 103, 254, 190, 53, 41, 94, 191, 51, 105, 20, 191, 74, 151, 80, 191, 103, 70, 117, 191, 10, 165, 146, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 225, 194, 125, 191, 222, 32, 7, 62, 185, 97, 119, 191, 53, 187, 131, 62, 191, 103, 254, 190, 53, 41, 94, 191, 51, 105, 20, 191, 74, 151, 80, 191, 51, 105, 20, 191, 74, 151, 80, 63, 191, 103, 254, 190, 53, 41, 94, 63, 251, 232, 193, 190, 6, 238, 108, 191, 103, 70, 117, 191, 10, 165, 146, 62, 125, 62, 120, 191, 201, 37, 122, 62, 248, 248, 125, 191, 226, 158, 0, 62, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 225, 194, 125, 191, 222, 32, 7, 62, 145, 189, 94, 191, 194, 94, 252, 62, 16, 92, 1, 191, 118, 233, 92, 191, 16, 92, 1, 191, 117, 233, 92, 63, 248, 28, 194, 190, 98, 227, 108, 191, 178, 171, 227, 190, 65, 76, 101, 191, 243, 4, 53, 191, 243, 4, 53, 63, 192, 94, 252, 190, 145, 189, 94, 63, 193, 94, 252, 190, 145, 189, 94, 191, 228, 113, 23, 191, 21, 102, 78, 191, 228, 113, 23, 191, 20, 102, 78, 63, 192, 94, 252, 190, 145, 189, 94, 63, 251, 232, 193, 190, 6, 238, 108, 191, 221, 32, 7, 190, 225, 194, 125, 63, 248, 28, 194, 190, 97, 227, 108, 191, 187, 166, 223, 190, 224, 72, 102, 191, 187, 166, 223, 190, 224, 72, 102, 63, 247, 28, 194, 190, 97, 227, 108, 63, 52, 187, 131, 190, 185, 97, 119, 191, 10, 165, 146, 190, 103, 70, 117, 191, 14, 82, 8, 50, 0, 0, 128, 63, 220, 32, 7, 190, 225, 194, 125, 191, 221, 32, 7, 190, 225, 194, 125, 63, 220, 32, 7, 190, 225, 194, 125, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 13, 82, 8, 50, 0, 0, 128, 191, 14, 82, 8, 50, 0, 0, 128, 63, 221, 32, 7, 62, 225, 194, 125, 191, 222, 32, 7, 62, 225, 194, 125, 63, 221, 32, 7, 62, 225, 194, 125, 191, 222, 32, 7, 62, 225, 194, 125, 63, 248, 28, 194, 62, 98, 227, 108, 191, 187, 166, 223, 62, 224, 72, 102, 191, 187, 166, 223, 62, 224, 72, 102, 63, 247, 28, 194, 62, 97, 227, 108, 63, 248, 28, 194, 62, 98, 227, 108, 191, 187, 166, 223, 62, 224, 72, 102, 191, 243, 4, 53, 63, 243, 4, 53, 63, 194, 94, 252, 62, 145, 189, 94, 63, 193, 94, 252, 62, 145, 189, 94, 191, 227, 113, 23, 63, 21, 102, 78, 191, 228, 113, 23, 63, 21, 102, 78, 63, 194, 94, 252, 62, 145, 189, 94, 63, 193, 94, 252, 62, 145, 189, 94, 191, 227, 113, 23, 63, 21, 102, 78, 191, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 145, 189, 94, 63, 192, 94, 252, 62, 16, 92, 1, 63, 117, 233, 92, 191, 16, 92, 1, 63, 117, 233, 92, 63, 16, 92, 1, 63, 117, 233, 92, 191, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 185, 97, 119, 63, 52, 187, 131, 62, 192, 103, 254, 62, 53, 41, 94, 191, 51, 105, 20, 63, 74, 151, 80, 191, 51, 105, 20, 63, 74, 151, 80, 63, 191, 103, 254, 62, 53, 41, 94, 63, 192, 103, 254, 62, 53, 41, 94, 191, 51, 105, 20, 63, 74, 151, 80, 191, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 185, 97, 119, 63, 52, 187, 131, 62, 100, 254, 26, 63, 77, 191, 75, 191, 242, 4, 53, 63, 243, 4, 53, 191, 243, 4, 53, 63, 243, 4, 53, 63, 100, 254, 26, 63, 77, 191, 75, 63, 100, 254, 26, 63, 77, 191, 75, 191, 242, 4, 53, 63, 243, 4, 53, 191, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 141, 67, 119, 63, 9, 157, 132, 62, 185, 97, 119, 63, 52, 187, 131, 62, 78, 191, 75, 63, 99, 254, 26, 191, 74, 151, 80, 63, 51, 105, 20, 191, 74, 151, 80, 63, 51, 105, 20, 63, 78, 191, 75, 63, 99, 254, 26, 63, 244, 4, 53, 63, 243, 4, 53, 191, 242, 4, 53, 63, 243, 4, 53, 191, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 185, 97, 119, 63, 52, 187, 131, 62, 53, 41, 94, 63, 190, 103, 254, 190, 117, 233, 92, 63, 16, 92, 1, 191, 20, 102, 78, 63, 228, 113, 23, 191, 21, 102, 78, 63, 228, 113, 23, 63, 117, 233, 92, 63, 16, 92, 1, 63, 53, 41, 94, 63, 191, 103, 254, 62, 78, 191, 75, 63, 99, 254, 26, 191, 74, 151, 80, 63, 51, 105, 20, 191, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 141, 67, 119, 63, 9, 157, 132, 62, 185, 97, 119, 63, 52, 187, 131, 62, 145, 189, 94, 63, 194, 94, 252, 190, 224, 72, 102, 63, 187, 166, 223, 190, 224, 72, 102, 63, 187, 166, 223, 62, 145, 189, 94, 63, 192, 94, 252, 62, 53, 41, 94, 63, 190, 103, 254, 190, 6, 238, 108, 63, 252, 232, 193, 190, 65, 76, 101, 63, 178, 171, 227, 190, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 248, 248, 125, 63, 225, 158, 0, 62, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 185, 97, 119, 63, 52, 187, 131, 62, 98, 227, 108, 63, 247, 28, 194, 190, 225, 194, 125, 63, 220, 32, 7, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 98, 227, 108, 63, 248, 28, 194, 62, 98, 227, 108, 63, 247, 28, 194, 190, 6, 238, 108, 63, 252, 232, 193, 190, 103, 70, 117, 63, 10, 165, 146, 190, 103, 70, 117, 63, 10, 165, 146, 62, 125, 62, 120, 63, 200, 37, 122, 62, 141, 67, 119, 63, 9, 157, 132, 62, 185, 97, 119, 63, 52, 187, 131, 62, 185, 97, 119, 63, 52, 187, 131, 190, 225, 194, 125, 63, 220, 32, 7, 190, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 0, 0, 128, 63, 13, 82, 136, 50, 225, 194, 125, 63, 221, 32, 7, 62, 185, 97, 119, 63, 52, 187, 131, 62, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 28, 0, 1, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 208, 201, 83, 8, 0, 0, 0, 0, 130, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 8, 202, 83, 8, 0, 0, 0, 0, 131, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 64, 202, 83, 8, 0, 0, 0, 0, 132, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 120, 202, 83, 8, 0, 0, 0, 0, 133, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 20, 4, 1, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 176, 202, 83, 8, 0, 0, 0, 0, 134, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 244, 3, 3, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 232, 202, 83, 8, 0, 0, 0, 0, 135, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 32, 203, 83, 8, 0, 0, 0, 0, 136, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 248, 1, 2, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 88, 203, 83, 8, 0, 0, 0, 0, 137, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 144, 203, 83, 8, 0, 0, 0, 0, 138, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 200, 203, 83, 8, 0, 0, 0, 0, 139, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0, 204, 83, 8, 0, 0, 0, 0, 140, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 56, 204, 83, 8, 0, 0, 0, 0, 141, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 112, 204, 83, 8, 0, 0, 0, 0, 142, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 168, 204, 83, 8, 0, 0, 0, 0, 143, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 224, 204, 83, 8, 0, 0, 0, 0, 144, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 24, 205, 83, 8, 0, 0, 0, 0, 145, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 80, 205, 83, 8, 0, 0, 0, 0, 146, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 136, 205, 83, 8, 0, 0, 0, 0, 147, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 192, 205, 83, 8, 0, 0, 0, 0, 148, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 248, 205, 83, 8, 0, 0, 0, 0, 149, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 48, 206, 83, 8, 0, 0, 0, 0, 150, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 104, 206, 83, 8, 0, 0, 0, 0, 151, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 160, 206, 83, 8, 0, 0, 0, 0, 152, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 216, 206, 83, 8, 0, 0, 0, 0, 153, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 16, 207, 83, 8, 0, 0, 0, 0, 154, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 72, 207, 83, 8, 0, 0, 0, 0, 155, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 128, 207, 83, 8, 0, 0, 0, 0, 156, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 184, 207, 83, 8, 0, 0, 0, 0, 157, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 240, 207, 83, 8, 0, 0, 0, 0, 158, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 40, 208, 83, 8, 0, 0, 0, 0, 159, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 96, 208, 83, 8, 0, 0, 0, 0, 160, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 152, 208, 83, 8, 0, 0, 0, 0, 161, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 208, 208, 83, 8, 0, 0, 0, 0, 162, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 8, 209, 83, 8, 0, 0, 0, 0, 163, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 64, 209, 83, 8, 0, 0, 0, 0, 164, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 120, 209, 83, 8, 0, 0, 0, 0, 165, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 176, 209, 83, 8, 0, 0, 0, 0, 166, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 232, 209, 83, 8, 0, 0, 0, 0, 167, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 32, 210, 83, 8, 0, 0, 0, 0, 168, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 88, 210, 83, 8, 0, 0, 0, 0, 169, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 144, 210, 83, 8, 0, 0, 0, 0, 170, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 200, 210, 83, 8, 0, 0, 0, 0, 171, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0, 211, 83, 8, 0, 0, 0, 0, 172, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 56, 211, 83, 8, 0, 0, 0, 0, 173, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 112, 211, 83, 8, 0, 0, 0, 0, 174, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 168, 211, 83, 8, 0, 0, 0, 0, 175, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 224, 211, 83, 8, 0, 0, 0, 0, 176, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 24, 212, 83, 8, 0, 0, 0, 0, 177, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 80, 212, 83, 8, 0, 0, 0, 0, 178, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 136, 212, 83, 8, 0, 0, 0, 0, 179, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 192, 212, 83, 8, 0, 0, 0, 0, 180, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 248, 212, 83, 8, 0, 0, 0, 0, 181, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 48, 213, 83, 8, 0, 0, 0, 0, 182, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 77, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 104, 213, 83, 8, 0, 0, 0, 0, 183, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 160, 213, 83, 8, 0, 0, 0, 0, 184, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 216, 213, 83, 8, 0, 0, 0, 0, 185, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 16, 214, 83, 8, 0, 0, 0, 0, 186, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 72, 214, 83, 8, 0, 0, 0, 0, 187, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 128, 214, 83, 8, 0, 0, 0, 0, 188, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 184, 214, 83, 8, 0, 0, 0, 0, 189, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 240, 214, 83, 8, 0, 0, 0, 0, 190, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 40, 215, 83, 8, 0, 0, 0, 0, 191, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 96, 215, 83, 8, 0, 0, 0, 0, 192, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 152, 215, 83, 8, 0, 0, 0, 0, 193, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 208, 215, 83, 8, 0, 0, 0, 0, 194, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 8, 216, 83, 8, 0, 0, 0, 0, 195, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 64, 216, 83, 8, 0, 0, 0, 0, 196, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 120, 216, 83, 8, 0, 0, 0, 0, 197, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 176, 216, 83, 8, 0, 0, 0, 0, 198, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 232, 216, 83, 8, 0, 0, 0, 0, 199, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 32, 217, 83, 8, 0, 0, 0, 0, 200, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 88, 217, 83, 8, 0, 0, 0, 0, 201, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 144, 217, 83, 8, 0, 0, 0, 0, 202, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 200, 217, 83, 8, 0, 0, 0, 0, 203, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0, 218, 83, 8, 0, 0, 0, 0, 204, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 56, 218, 83, 8, 0, 0, 0, 0, 205, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 112, 218, 83, 8, 0, 0, 0, 0, 206, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 168, 218, 83, 8, 0, 0, 0, 0, 207, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 224, 218, 83, 8, 0, 0, 0, 0, 208, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 24, 219, 83, 8, 0, 0, 0, 0, 209, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 80, 219, 83, 8, 0, 0, 0, 0, 210, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 136, 219, 83, 8, 0, 0, 0, 0, 211, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 192, 219, 83, 8, 0, 0, 0, 0, 212, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 248, 219, 83, 8, 0, 0, 0, 0, 213, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 48, 220, 83, 8, 0, 0, 0, 0, 214, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 104, 220, 83, 8, 0, 0, 0, 0, 215, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 160, 220, 83, 8, 0, 0, 0, 0, 216, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 216, 220, 83, 8, 0, 0, 0, 0, 217, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 16, 221, 83, 8, 0, 0, 0, 0, 218, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 72, 221, 83, 8, 0, 0, 0, 0, 219, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 128, 221, 83, 8, 0, 0, 0, 0, 220, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 184, 221, 83, 8, 0, 0, 0, 0, 221, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 240, 221, 83, 8, 0, 0, 0, 0, 222, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 40, 222, 83, 8, 0, 0, 0, 0, 223, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 96, 222, 83, 8, 0, 0, 0, 0, 224, 5, 0, 0, 0, 0, 0, 0), "format": "RGFloat", @@ -202,9 +200,9 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_jr4op"] -image = SubResource("Image_81f5r") +image = SubResource("Image_gtq67") -[sub_resource type="Image" id="Image_k3r11"] +[sub_resource type="Image" id="Image_5dfpo"] data = { "data": PackedByteArray(0, 0, 208, 65, 0, 0, 184, 66, 0, 0, 208, 65, 0, 0, 186, 66, 0, 0, 208, 65, 0, 0, 188, 66, 0, 0, 208, 65, 0, 0, 190, 66, 0, 0, 208, 65, 0, 0, 192, 66, 0, 0, 208, 65, 0, 0, 194, 66, 0, 0, 208, 65, 0, 0, 196, 66, 0, 0, 208, 65, 0, 0, 198, 66, 0, 0, 208, 65, 0, 0, 200, 66, 0, 0, 208, 65, 0, 0, 202, 66, 0, 0, 208, 65, 0, 0, 46, 67, 0, 0, 208, 65, 0, 0, 47, 67, 0, 0, 208, 65, 0, 0, 48, 67, 0, 0, 208, 65, 0, 0, 49, 67, 0, 0, 208, 65, 0, 0, 50, 67, 0, 0, 208, 65, 0, 0, 51, 67, 0, 0, 208, 65, 0, 0, 52, 67, 0, 0, 208, 65, 0, 0, 53, 67, 0, 0, 208, 65, 0, 0, 54, 67, 0, 0, 208, 65, 0, 0, 55, 67, 0, 0, 216, 65, 0, 0, 184, 66, 0, 0, 216, 65, 0, 0, 202, 66, 0, 0, 216, 65, 0, 0, 204, 66, 0, 0, 216, 65, 0, 0, 45, 67, 0, 0, 216, 65, 0, 0, 46, 67, 0, 0, 216, 65, 0, 0, 55, 67, 0, 0, 224, 65, 0, 0, 184, 66, 0, 0, 224, 65, 0, 0, 204, 66, 0, 0, 224, 65, 0, 0, 206, 66, 0, 0, 224, 65, 0, 0, 45, 67, 0, 0, 224, 65, 0, 0, 55, 67, 0, 0, 232, 65, 0, 0, 184, 66, 0, 0, 232, 65, 0, 0, 206, 66, 0, 0, 232, 65, 0, 0, 45, 67, 0, 0, 232, 65, 0, 0, 55, 67, 0, 0, 240, 65, 0, 0, 184, 66, 0, 0, 240, 65, 0, 0, 206, 66, 0, 0, 240, 65, 0, 0, 44, 67, 0, 0, 240, 65, 0, 0, 45, 67, 0, 0, 240, 65, 0, 0, 55, 67, 0, 0, 248, 65, 0, 0, 184, 66, 0, 0, 248, 65, 0, 0, 206, 66, 0, 0, 248, 65, 0, 0, 44, 67, 0, 0, 248, 65, 0, 0, 55, 67, 0, 0, 0, 66, 0, 0, 184, 66, 0, 0, 0, 66, 0, 0, 206, 66, 0, 0, 0, 66, 0, 0, 44, 67, 0, 0, 0, 66, 0, 0, 55, 67, 0, 0, 4, 66, 0, 0, 184, 66, 0, 0, 4, 66, 0, 0, 206, 66, 0, 0, 4, 66, 0, 0, 44, 67, 0, 0, 4, 66, 0, 0, 55, 67, 0, 0, 8, 66, 0, 0, 184, 66, 0, 0, 8, 66, 0, 0, 206, 66, 0, 0, 8, 66, 0, 0, 208, 66, 0, 0, 8, 66, 0, 0, 43, 67, 0, 0, 8, 66, 0, 0, 44, 67, 0, 0, 8, 66, 0, 0, 55, 67, 0, 0, 12, 66, 0, 0, 184, 66, 0, 0, 12, 66, 0, 0, 208, 66, 0, 0, 12, 66, 0, 0, 210, 66, 0, 0, 12, 66, 0, 0, 43, 67, 0, 0, 12, 66, 0, 0, 55, 67, 0, 0, 16, 66, 0, 0, 184, 66, 0, 0, 16, 66, 0, 0, 210, 66, 0, 0, 16, 66, 0, 0, 212, 66, 0, 0, 16, 66, 0, 0, 41, 67, 0, 0, 16, 66, 0, 0, 42, 67, 0, 0, 16, 66, 0, 0, 43, 67, 0, 0, 16, 66, 0, 0, 55, 67, 0, 0, 20, 66, 0, 0, 184, 66, 0, 0, 20, 66, 0, 0, 212, 66, 0, 0, 20, 66, 0, 0, 214, 66, 0, 0, 20, 66, 0, 0, 216, 66, 0, 0, 20, 66, 0, 0, 40, 67, 0, 0, 20, 66, 0, 0, 41, 67, 0, 0, 20, 66, 0, 0, 55, 67, 0, 0, 24, 66, 0, 0, 184, 66, 0, 0, 24, 66, 0, 0, 216, 66, 0, 0, 24, 66, 0, 0, 218, 66, 0, 0, 24, 66, 0, 0, 220, 66, 0, 0, 24, 66, 0, 0, 222, 66, 0, 0, 24, 66, 0, 0, 224, 66, 0, 0, 24, 66, 0, 0, 226, 66, 0, 0, 24, 66, 0, 0, 228, 66, 0, 0, 24, 66, 0, 0, 230, 66, 0, 0, 24, 66, 0, 0, 232, 66, 0, 0, 24, 66, 0, 0, 234, 66, 0, 0, 24, 66, 0, 0, 236, 66, 0, 0, 24, 66, 0, 0, 238, 66, 0, 0, 24, 66, 0, 0, 240, 66, 0, 0, 24, 66, 0, 0, 242, 66, 0, 0, 24, 66, 0, 0, 244, 66, 0, 0, 24, 66, 0, 0, 246, 66, 0, 0, 24, 66, 0, 0, 248, 66, 0, 0, 24, 66, 0, 0, 250, 66, 0, 0, 24, 66, 0, 0, 252, 66, 0, 0, 24, 66, 0, 0, 254, 66, 0, 0, 24, 66, 0, 0, 0, 67, 0, 0, 24, 66, 0, 0, 1, 67, 0, 0, 24, 66, 0, 0, 2, 67, 0, 0, 24, 66, 0, 0, 3, 67, 0, 0, 24, 66, 0, 0, 4, 67, 0, 0, 24, 66, 0, 0, 5, 67, 0, 0, 24, 66, 0, 0, 6, 67, 0, 0, 24, 66, 0, 0, 7, 67, 0, 0, 24, 66, 0, 0, 8, 67, 0, 0, 24, 66, 0, 0, 9, 67, 0, 0, 24, 66, 0, 0, 10, 67, 0, 0, 24, 66, 0, 0, 11, 67, 0, 0, 24, 66, 0, 0, 12, 67, 0, 0, 24, 66, 0, 0, 13, 67, 0, 0, 24, 66, 0, 0, 14, 67, 0, 0, 24, 66, 0, 0, 15, 67, 0, 0, 24, 66, 0, 0, 16, 67, 0, 0, 24, 66, 0, 0, 17, 67, 0, 0, 24, 66, 0, 0, 18, 67, 0, 0, 24, 66, 0, 0, 19, 67, 0, 0, 24, 66, 0, 0, 20, 67, 0, 0, 24, 66, 0, 0, 21, 67, 0, 0, 24, 66, 0, 0, 22, 67, 0, 0, 24, 66, 0, 0, 23, 67, 0, 0, 24, 66, 0, 0, 24, 67, 0, 0, 24, 66, 0, 0, 25, 67, 0, 0, 24, 66, 0, 0, 26, 67, 0, 0, 24, 66, 0, 0, 27, 67, 0, 0, 24, 66, 0, 0, 28, 67, 0, 0, 24, 66, 0, 0, 29, 67, 0, 0, 24, 66, 0, 0, 30, 67, 0, 0, 24, 66, 0, 0, 31, 67, 0, 0, 24, 66, 0, 0, 32, 67, 0, 0, 24, 66, 0, 0, 33, 67, 0, 0, 24, 66, 0, 0, 34, 67, 0, 0, 24, 66, 0, 0, 35, 67, 0, 0, 24, 66, 0, 0, 36, 67, 0, 0, 24, 66, 0, 0, 37, 67, 0, 0, 24, 66, 0, 0, 38, 67, 0, 0, 24, 66, 0, 0, 39, 67, 0, 0, 24, 66, 0, 0, 40, 67, 0, 0, 24, 66, 0, 0, 55, 67, 0, 0, 28, 66, 0, 0, 184, 66, 0, 0, 28, 66, 0, 0, 55, 67, 0, 0, 32, 66, 0, 0, 184, 66, 0, 0, 32, 66, 0, 0, 55, 67, 0, 0, 36, 66, 0, 0, 184, 66, 0, 0, 36, 66, 0, 0, 55, 67, 0, 0, 40, 66, 0, 0, 184, 66, 0, 0, 40, 66, 0, 0, 55, 67, 0, 0, 44, 66, 0, 0, 184, 66, 0, 0, 44, 66, 0, 0, 55, 67, 0, 0, 48, 66, 0, 0, 184, 66, 0, 0, 48, 66, 0, 0, 55, 67, 0, 0, 52, 66, 0, 0, 184, 66, 0, 0, 52, 66, 0, 0, 55, 67, 0, 0, 56, 66, 0, 0, 184, 66, 0, 0, 56, 66, 0, 0, 55, 67, 0, 0, 60, 66, 0, 0, 184, 66, 0, 0, 60, 66, 0, 0, 55, 67, 0, 0, 64, 66, 0, 0, 184, 66, 0, 0, 64, 66, 0, 0, 55, 67, 0, 0, 68, 66, 0, 0, 184, 66, 0, 0, 68, 66, 0, 0, 55, 67, 0, 0, 72, 66, 0, 0, 184, 66, 0, 0, 72, 66, 0, 0, 55, 67, 0, 0, 76, 66, 0, 0, 184, 66, 0, 0, 76, 66, 0, 0, 55, 67, 0, 0, 80, 66, 0, 0, 184, 66, 0, 0, 80, 66, 0, 0, 55, 67, 0, 0, 84, 66, 0, 0, 184, 66, 0, 0, 84, 66, 0, 0, 55, 67, 0, 0, 88, 66, 0, 0, 184, 66, 0, 0, 88, 66, 0, 0, 55, 67, 0, 0, 92, 66, 0, 0, 184, 66, 0, 0, 92, 66, 0, 0, 55, 67, 0, 0, 96, 66, 0, 0, 184, 66, 0, 0, 96, 66, 0, 0, 55, 67, 0, 0, 100, 66, 0, 0, 184, 66, 0, 0, 100, 66, 0, 0, 55, 67, 0, 0, 104, 66, 0, 0, 184, 66, 0, 0, 104, 66, 0, 0, 55, 67, 0, 0, 108, 66, 0, 0, 184, 66, 0, 0, 108, 66, 0, 0, 55, 67, 0, 0, 112, 66, 0, 0, 184, 66, 0, 0, 112, 66, 0, 0, 55, 67, 0, 0, 116, 66, 0, 0, 184, 66, 0, 0, 116, 66, 0, 0, 216, 66, 0, 0, 116, 66, 0, 0, 218, 66, 0, 0, 116, 66, 0, 0, 220, 66, 0, 0, 116, 66, 0, 0, 222, 66, 0, 0, 116, 66, 0, 0, 224, 66, 0, 0, 116, 66, 0, 0, 226, 66, 0, 0, 116, 66, 0, 0, 228, 66, 0, 0, 116, 66, 0, 0, 230, 66, 0, 0, 116, 66, 0, 0, 232, 66, 0, 0, 116, 66, 0, 0, 234, 66, 0, 0, 116, 66, 0, 0, 236, 66, 0, 0, 116, 66, 0, 0, 238, 66, 0, 0, 116, 66, 0, 0, 240, 66, 0, 0, 116, 66, 0, 0, 242, 66, 0, 0, 116, 66, 0, 0, 244, 66, 0, 0, 116, 66, 0, 0, 246, 66, 0, 0, 116, 66, 0, 0, 248, 66, 0, 0, 116, 66, 0, 0, 250, 66, 0, 0, 116, 66, 0, 0, 252, 66, 0, 0, 116, 66, 0, 0, 254, 66, 0, 0, 116, 66, 0, 0, 0, 67, 0, 0, 116, 66, 0, 0, 13, 67, 0, 0, 116, 66, 0, 0, 14, 67, 0, 0, 116, 66, 0, 0, 15, 67, 0, 0, 116, 66, 0, 0, 16, 67, 0, 0, 116, 66, 0, 0, 17, 67, 0, 0, 116, 66, 0, 0, 18, 67, 0, 0, 116, 66, 0, 0, 19, 67, 0, 0, 116, 66, 0, 0, 20, 67, 0, 0, 116, 66, 0, 0, 21, 67, 0, 0, 116, 66, 0, 0, 22, 67, 0, 0, 116, 66, 0, 0, 23, 67, 0, 0, 116, 66, 0, 0, 24, 67, 0, 0, 116, 66, 0, 0, 25, 67, 0, 0, 116, 66, 0, 0, 26, 67, 0, 0, 116, 66, 0, 0, 27, 67, 0, 0, 116, 66, 0, 0, 28, 67, 0, 0, 116, 66, 0, 0, 29, 67, 0, 0, 116, 66, 0, 0, 30, 67, 0, 0, 116, 66, 0, 0, 31, 67, 0, 0, 116, 66, 0, 0, 32, 67, 0, 0, 116, 66, 0, 0, 33, 67, 0, 0, 116, 66, 0, 0, 34, 67, 0, 0, 116, 66, 0, 0, 35, 67, 0, 0, 116, 66, 0, 0, 36, 67, 0, 0, 116, 66, 0, 0, 37, 67, 0, 0, 116, 66, 0, 0, 38, 67, 0, 0, 116, 66, 0, 0, 39, 67, 0, 0, 116, 66, 0, 0, 40, 67, 0, 0, 116, 66, 0, 0, 55, 67, 0, 0, 120, 66, 0, 0, 184, 66, 0, 0, 120, 66, 0, 0, 212, 66, 0, 0, 120, 66, 0, 0, 214, 66, 0, 0, 120, 66, 0, 0, 216, 66, 0, 0, 120, 66, 0, 0, 0, 67, 0, 0, 120, 66, 0, 0, 13, 67, 0, 0, 120, 66, 0, 0, 40, 67, 0, 0, 120, 66, 0, 0, 41, 67, 0, 0, 120, 66, 0, 0, 55, 67, 0, 0, 124, 66, 0, 0, 184, 66, 0, 0, 124, 66, 0, 0, 210, 66, 0, 0, 124, 66, 0, 0, 212, 66, 0, 0, 124, 66, 0, 0, 0, 67, 0, 0, 124, 66, 0, 0, 13, 67, 0, 0, 124, 66, 0, 0, 41, 67, 0, 0, 124, 66, 0, 0, 42, 67, 0, 0, 124, 66, 0, 0, 43, 67, 0, 0, 124, 66, 0, 0, 55, 67, 0, 0, 128, 66, 0, 0, 184, 66, 0, 0, 128, 66, 0, 0, 208, 66, 0, 0, 128, 66, 0, 0, 210, 66, 0, 0, 128, 66, 0, 0, 0, 67, 0, 0, 128, 66, 0, 0, 13, 67, 0, 0, 128, 66, 0, 0, 43, 67, 0, 0, 128, 66, 0, 0, 55, 67, 0, 0, 130, 66, 0, 0, 184, 66, 0, 0, 130, 66, 0, 0, 206, 66, 0, 0, 130, 66, 0, 0, 208, 66, 0, 0, 130, 66, 0, 0, 0, 67, 0, 0, 130, 66, 0, 0, 13, 67, 0, 0, 130, 66, 0, 0, 43, 67, 0, 0, 130, 66, 0, 0, 44, 67, 0, 0, 130, 66, 0, 0, 55, 67, 0, 0, 132, 66, 0, 0, 184, 66, 0, 0, 132, 66, 0, 0, 206, 66, 0, 0, 132, 66, 0, 0, 0, 67, 0, 0, 132, 66, 0, 0, 13, 67, 0, 0, 132, 66, 0, 0, 44, 67, 0, 0, 132, 66, 0, 0, 55, 67, 0, 0, 134, 66, 0, 0, 184, 66, 0, 0, 134, 66, 0, 0, 206, 66, 0, 0, 134, 66, 0, 0, 0, 67, 0, 0, 134, 66, 0, 0, 13, 67, 0, 0, 134, 66, 0, 0, 44, 67, 0, 0, 134, 66, 0, 0, 55, 67, 0, 0, 136, 66, 0, 0, 184, 66, 0, 0, 136, 66, 0, 0, 206, 66, 0, 0, 136, 66, 0, 0, 0, 67, 0, 0, 136, 66, 0, 0, 13, 67, 0, 0, 136, 66, 0, 0, 44, 67, 0, 0, 136, 66, 0, 0, 55, 67, 0, 0, 138, 66, 0, 0, 184, 66, 0, 0, 138, 66, 0, 0, 206, 66, 0, 0, 138, 66, 0, 0, 0, 67, 0, 0, 138, 66, 0, 0, 13, 67, 0, 0, 138, 66, 0, 0, 44, 67, 0, 0, 138, 66, 0, 0, 45, 67, 0, 0, 138, 66, 0, 0, 55, 67, 0, 0, 140, 66, 0, 0, 184, 66, 0, 0, 140, 66, 0, 0, 206, 66, 0, 0, 140, 66, 0, 0, 0, 67, 0, 0, 140, 66, 0, 0, 13, 67, 0, 0, 140, 66, 0, 0, 45, 67, 0, 0, 140, 66, 0, 0, 55, 67, 0, 0, 142, 66, 0, 0, 184, 66, 0, 0, 142, 66, 0, 0, 204, 66, 0, 0, 142, 66, 0, 0, 206, 66, 0, 0, 142, 66, 0, 0, 0, 67, 0, 0, 142, 66, 0, 0, 13, 67, 0, 0, 142, 66, 0, 0, 45, 67, 0, 0, 142, 66, 0, 0, 55, 67, 0, 0, 144, 66, 0, 0, 184, 66, 0, 0, 144, 66, 0, 0, 202, 66, 0, 0, 144, 66, 0, 0, 204, 66, 0, 0, 144, 66, 0, 0, 0, 67, 0, 0, 144, 66, 0, 0, 13, 67, 0, 0, 144, 66, 0, 0, 45, 67, 0, 0, 144, 66, 0, 0, 46, 67, 0, 0, 144, 66, 0, 0, 55, 67, 0, 0, 146, 66, 0, 0, 184, 66, 0, 0, 146, 66, 0, 0, 186, 66, 0, 0, 146, 66, 0, 0, 188, 66, 0, 0, 146, 66, 0, 0, 190, 66, 0, 0, 146, 66, 0, 0, 192, 66, 0, 0, 146, 66, 0, 0, 194, 66, 0, 0, 146, 66, 0, 0, 196, 66, 0, 0, 146, 66, 0, 0, 198, 66, 0, 0, 146, 66, 0, 0, 200, 66, 0, 0, 146, 66, 0, 0, 202, 66, 0, 0, 146, 66, 0, 0, 0, 67, 0, 0, 146, 66, 0, 0, 13, 67, 0, 0, 146, 66, 0, 0, 46, 67, 0, 0, 146, 66, 0, 0, 47, 67, 0, 0, 146, 66, 0, 0, 48, 67, 0, 0, 146, 66, 0, 0, 49, 67, 0, 0, 146, 66, 0, 0, 50, 67, 0, 0, 146, 66, 0, 0, 51, 67, 0, 0, 146, 66, 0, 0, 52, 67, 0, 0, 146, 66, 0, 0, 53, 67, 0, 0, 146, 66, 0, 0, 54, 67, 0, 0, 146, 66, 0, 0, 55, 67, 0, 0, 148, 66, 0, 0, 0, 67, 0, 0, 148, 66, 0, 0, 13, 67, 0, 0, 150, 66, 0, 0, 0, 67, 0, 0, 150, 66, 0, 0, 13, 67, 0, 0, 152, 66, 0, 0, 0, 67, 0, 0, 152, 66, 0, 0, 13, 67, 0, 0, 154, 66, 0, 0, 0, 67, 0, 0, 154, 66, 0, 0, 13, 67, 0, 0, 156, 66, 0, 0, 0, 67, 0, 0, 156, 66, 0, 0, 13, 67, 0, 0, 158, 66, 0, 0, 0, 67, 0, 0, 158, 66, 0, 0, 13, 67, 0, 0, 160, 66, 0, 0, 0, 67, 0, 0, 160, 66, 0, 0, 13, 67, 0, 0, 162, 66, 0, 0, 0, 67, 0, 0, 162, 66, 0, 0, 13, 67, 0, 0, 164, 66, 0, 0, 0, 67, 0, 0, 164, 66, 0, 0, 13, 67, 0, 0, 166, 66, 0, 0, 0, 67, 0, 0, 166, 66, 0, 0, 13, 67, 0, 0, 168, 66, 0, 0, 184, 66, 0, 0, 168, 66, 0, 0, 186, 66, 0, 0, 168, 66, 0, 0, 188, 66, 0, 0, 168, 66, 0, 0, 190, 66, 0, 0, 168, 66, 0, 0, 192, 66, 0, 0, 168, 66, 0, 0, 194, 66, 0, 0, 168, 66, 0, 0, 196, 66, 0, 0, 168, 66, 0, 0, 198, 66, 0, 0, 168, 66, 0, 0, 200, 66, 0, 0, 168, 66, 0, 0, 202, 66, 0, 0, 168, 66, 0, 0, 0, 67, 0, 0, 168, 66, 0, 0, 13, 67, 0, 0, 168, 66, 0, 0, 46, 67, 0, 0, 168, 66, 0, 0, 47, 67, 0, 0, 168, 66, 0, 0, 48, 67, 0, 0, 168, 66, 0, 0, 49, 67, 0, 0, 168, 66, 0, 0, 50, 67, 0, 0, 168, 66, 0, 0, 51, 67, 0, 0, 168, 66, 0, 0, 52, 67, 0, 0, 168, 66, 0, 0, 53, 67, 0, 0, 168, 66, 0, 0, 54, 67, 0, 0, 168, 66, 0, 0, 55, 67, 0, 0, 170, 66, 0, 0, 184, 66, 0, 0, 170, 66, 0, 0, 202, 66, 0, 0, 170, 66, 0, 0, 204, 66, 0, 0, 170, 66, 0, 0, 0, 67, 0, 0, 170, 66, 0, 0, 13, 67, 0, 0, 170, 66, 0, 0, 45, 67, 0, 0, 170, 66, 0, 0, 46, 67, 0, 0, 170, 66, 0, 0, 55, 67, 0, 0, 172, 66, 0, 0, 184, 66, 0, 0, 172, 66, 0, 0, 204, 66, 0, 0, 172, 66, 0, 0, 206, 66, 0, 0, 172, 66, 0, 0, 0, 67, 0, 0, 172, 66, 0, 0, 13, 67, 0, 0, 172, 66, 0, 0, 45, 67, 0, 0, 172, 66, 0, 0, 55, 67, 0, 0, 174, 66, 0, 0, 184, 66, 0, 0, 174, 66, 0, 0, 206, 66, 0, 0, 174, 66, 0, 0, 0, 67, 0, 0, 174, 66, 0, 0, 13, 67, 0, 0, 174, 66, 0, 0, 45, 67, 0, 0, 174, 66, 0, 0, 55, 67, 0, 0, 176, 66, 0, 0, 184, 66, 0, 0, 176, 66, 0, 0, 206, 66, 0, 0, 176, 66, 0, 0, 0, 67, 0, 0, 176, 66, 0, 0, 13, 67, 0, 0, 176, 66, 0, 0, 44, 67, 0, 0, 176, 66, 0, 0, 45, 67, 0, 0, 176, 66, 0, 0, 55, 67, 0, 0, 178, 66, 0, 0, 184, 66, 0, 0, 178, 66, 0, 0, 206, 66, 0, 0, 178, 66, 0, 0, 0, 67, 0, 0, 178, 66, 0, 0, 13, 67, 0, 0, 178, 66, 0, 0, 44, 67, 0, 0, 178, 66, 0, 0, 55, 67, 0, 0, 180, 66, 0, 0, 184, 66, 0, 0, 180, 66, 0, 0, 206, 66, 0, 0, 180, 66, 0, 0, 0, 67, 0, 0, 180, 66, 0, 0, 13, 67, 0, 0, 180, 66, 0, 0, 44, 67, 0, 0, 180, 66, 0, 0, 55, 67, 0, 0, 182, 66, 0, 0, 184, 66, 0, 0, 182, 66, 0, 0, 206, 66, 0, 0, 182, 66, 0, 0, 0, 67, 0, 0, 182, 66, 0, 0, 13, 67, 0, 0, 182, 66, 0, 0, 44, 67, 0, 0, 182, 66, 0, 0, 55, 67, 0, 0, 184, 66, 0, 0, 184, 66, 0, 0, 184, 66, 0, 0, 206, 66, 0, 0, 184, 66, 0, 0, 208, 66, 0, 0, 184, 66, 0, 0, 0, 67, 0, 0, 184, 66, 0, 0, 13, 67, 0, 0, 184, 66, 0, 0, 43, 67, 0, 0, 184, 66, 0, 0, 44, 67, 0, 0, 184, 66, 0, 0, 55, 67, 0, 0, 186, 66, 0, 0, 184, 66, 0, 0, 186, 66, 0, 0, 208, 66, 0, 0, 186, 66, 0, 0, 210, 66, 0, 0, 186, 66, 0, 0, 0, 67, 0, 0, 186, 66, 0, 0, 13, 67, 0, 0, 186, 66, 0, 0, 43, 67, 0, 0, 186, 66, 0, 0, 55, 67, 0, 0, 188, 66, 0, 0, 184, 66, 0, 0, 188, 66, 0, 0, 210, 66, 0, 0, 188, 66, 0, 0, 212, 66, 0, 0, 188, 66, 0, 0, 0, 67, 0, 0, 188, 66, 0, 0, 13, 67, 0, 0, 188, 66, 0, 0, 41, 67, 0, 0, 188, 66, 0, 0, 42, 67, 0, 0, 188, 66, 0, 0, 43, 67, 0, 0, 188, 66, 0, 0, 55, 67, 0, 0, 190, 66, 0, 0, 184, 66, 0, 0, 190, 66, 0, 0, 212, 66, 0, 0, 190, 66, 0, 0, 214, 66, 0, 0, 190, 66, 0, 0, 216, 66, 0, 0, 190, 66, 0, 0, 0, 67, 0, 0, 190, 66, 0, 0, 13, 67, 0, 0, 190, 66, 0, 0, 40, 67, 0, 0, 190, 66, 0, 0, 41, 67, 0, 0, 190, 66, 0, 0, 55, 67, 0, 0, 192, 66, 0, 0, 184, 66, 0, 0, 192, 66, 0, 0, 216, 66, 0, 0, 192, 66, 0, 0, 218, 66, 0, 0, 192, 66, 0, 0, 220, 66, 0, 0, 192, 66, 0, 0, 222, 66, 0, 0, 192, 66, 0, 0, 224, 66, 0, 0, 192, 66, 0, 0, 226, 66, 0, 0, 192, 66, 0, 0, 228, 66, 0, 0, 192, 66, 0, 0, 230, 66, 0, 0, 192, 66, 0, 0, 232, 66, 0, 0, 192, 66, 0, 0, 234, 66, 0, 0, 192, 66, 0, 0, 236, 66, 0, 0, 192, 66, 0, 0, 238, 66, 0, 0, 192, 66, 0, 0, 240, 66, 0, 0, 192, 66, 0, 0, 242, 66, 0, 0, 192, 66, 0, 0, 244, 66, 0, 0, 192, 66, 0, 0, 246, 66, 0, 0, 192, 66, 0, 0, 248, 66, 0, 0, 192, 66, 0, 0, 250, 66, 0, 0, 192, 66, 0, 0, 252, 66, 0, 0, 192, 66, 0, 0, 254, 66, 0, 0, 192, 66, 0, 0, 0, 67, 0, 0, 192, 66, 0, 0, 13, 67, 0, 0, 192, 66, 0, 0, 14, 67, 0, 0, 192, 66, 0, 0, 15, 67, 0, 0, 192, 66, 0, 0, 16, 67, 0, 0, 192, 66, 0, 0, 17, 67, 0, 0, 192, 66, 0, 0, 18, 67, 0, 0, 192, 66, 0, 0, 19, 67, 0, 0, 192, 66, 0, 0, 20, 67, 0, 0, 192, 66, 0, 0, 21, 67, 0, 0, 192, 66, 0, 0, 22, 67, 0, 0, 192, 66, 0, 0, 23, 67, 0, 0, 192, 66, 0, 0, 24, 67, 0, 0, 192, 66, 0, 0, 25, 67, 0, 0, 192, 66, 0, 0, 26, 67, 0, 0, 192, 66, 0, 0, 27, 67, 0, 0, 192, 66, 0, 0, 28, 67, 0, 0, 192, 66, 0, 0, 29, 67, 0, 0, 192, 66, 0, 0, 30, 67, 0, 0, 192, 66, 0, 0, 31, 67, 0, 0, 192, 66, 0, 0, 32, 67, 0, 0, 192, 66, 0, 0, 33, 67, 0, 0, 192, 66, 0, 0, 34, 67, 0, 0, 192, 66, 0, 0, 35, 67, 0, 0, 192, 66, 0, 0, 36, 67, 0, 0, 192, 66, 0, 0, 37, 67, 0, 0, 192, 66, 0, 0, 38, 67, 0, 0, 192, 66, 0, 0, 39, 67, 0, 0, 192, 66, 0, 0, 40, 67, 0, 0, 192, 66, 0, 0, 55, 67, 0, 0, 194, 66, 0, 0, 184, 66, 0, 0, 194, 66, 0, 0, 55, 67, 0, 0, 196, 66, 0, 0, 184, 66, 0, 0, 196, 66, 0, 0, 55, 67, 0, 0, 198, 66, 0, 0, 184, 66, 0, 0, 198, 66, 0, 0, 55, 67, 0, 0, 200, 66, 0, 0, 184, 66, 0, 0, 200, 66, 0, 0, 55, 67, 0, 0, 202, 66, 0, 0, 184, 66, 0, 0, 202, 66, 0, 0, 55, 67, 0, 0, 204, 66, 0, 0, 184, 66, 0, 0, 204, 66, 0, 0, 55, 67, 0, 0, 206, 66, 0, 0, 184, 66, 0, 0, 206, 66, 0, 0, 55, 67, 0, 0, 208, 66, 0, 0, 184, 66, 0, 0, 208, 66, 0, 0, 55, 67, 0, 0, 210, 66, 0, 0, 184, 66, 0, 0, 210, 66, 0, 0, 55, 67, 0, 0, 212, 66, 0, 0, 184, 66, 0, 0, 212, 66, 0, 0, 55, 67, 0, 0, 214, 66, 0, 0, 184, 66, 0, 0, 214, 66, 0, 0, 55, 67, 0, 0, 216, 66, 0, 0, 184, 66, 0, 0, 216, 66, 0, 0, 55, 67, 0, 0, 218, 66, 0, 0, 184, 66, 0, 0, 218, 66, 0, 0, 55, 67, 0, 0, 220, 66, 0, 0, 184, 66, 0, 0, 220, 66, 0, 0, 55, 67, 0, 0, 222, 66, 0, 0, 184, 66, 0, 0, 222, 66, 0, 0, 55, 67, 0, 0, 224, 66, 0, 0, 184, 66, 0, 0, 224, 66, 0, 0, 55, 67, 0, 0, 226, 66, 0, 0, 184, 66, 0, 0, 226, 66, 0, 0, 55, 67, 0, 0, 228, 66, 0, 0, 184, 66, 0, 0, 228, 66, 0, 0, 55, 67, 0, 0, 230, 66, 0, 0, 184, 66, 0, 0, 230, 66, 0, 0, 55, 67, 0, 0, 232, 66, 0, 0, 184, 66, 0, 0, 232, 66, 0, 0, 55, 67, 0, 0, 234, 66, 0, 0, 184, 66, 0, 0, 234, 66, 0, 0, 55, 67, 0, 0, 236, 66, 0, 0, 184, 66, 0, 0, 236, 66, 0, 0, 55, 67, 0, 0, 238, 66, 0, 0, 184, 66, 0, 0, 238, 66, 0, 0, 216, 66, 0, 0, 238, 66, 0, 0, 218, 66, 0, 0, 238, 66, 0, 0, 220, 66, 0, 0, 238, 66, 0, 0, 222, 66, 0, 0, 238, 66, 0, 0, 224, 66, 0, 0, 238, 66, 0, 0, 226, 66, 0, 0, 238, 66, 0, 0, 228, 66, 0, 0, 238, 66, 0, 0, 230, 66, 0, 0, 238, 66, 0, 0, 232, 66, 0, 0, 238, 66, 0, 0, 234, 66, 0, 0, 238, 66, 0, 0, 236, 66, 0, 0, 238, 66, 0, 0, 238, 66, 0, 0, 238, 66, 0, 0, 240, 66, 0, 0, 238, 66, 0, 0, 242, 66, 0, 0, 238, 66, 0, 0, 244, 66, 0, 0, 238, 66, 0, 0, 246, 66, 0, 0, 238, 66, 0, 0, 248, 66, 0, 0, 238, 66, 0, 0, 250, 66, 0, 0, 238, 66, 0, 0, 252, 66, 0, 0, 238, 66, 0, 0, 254, 66, 0, 0, 238, 66, 0, 0, 0, 67, 0, 0, 238, 66, 0, 0, 1, 67, 0, 0, 238, 66, 0, 0, 2, 67, 0, 0, 238, 66, 0, 0, 3, 67, 0, 0, 238, 66, 0, 0, 4, 67, 0, 0, 238, 66, 0, 0, 5, 67, 0, 0, 238, 66, 0, 0, 6, 67, 0, 0, 238, 66, 0, 0, 7, 67, 0, 0, 238, 66, 0, 0, 8, 67, 0, 0, 238, 66, 0, 0, 9, 67, 0, 0, 238, 66, 0, 0, 10, 67, 0, 0, 238, 66, 0, 0, 11, 67, 0, 0, 238, 66, 0, 0, 12, 67, 0, 0, 238, 66, 0, 0, 13, 67, 0, 0, 238, 66, 0, 0, 14, 67, 0, 0, 238, 66, 0, 0, 15, 67, 0, 0, 238, 66, 0, 0, 16, 67, 0, 0, 238, 66, 0, 0, 17, 67, 0, 0, 238, 66, 0, 0, 18, 67, 0, 0, 238, 66, 0, 0, 19, 67, 0, 0, 238, 66, 0, 0, 20, 67, 0, 0, 238, 66, 0, 0, 21, 67, 0, 0, 238, 66, 0, 0, 22, 67, 0, 0, 238, 66, 0, 0, 23, 67, 0, 0, 238, 66, 0, 0, 24, 67, 0, 0, 238, 66, 0, 0, 25, 67, 0, 0, 238, 66, 0, 0, 26, 67, 0, 0, 238, 66, 0, 0, 27, 67, 0, 0, 238, 66, 0, 0, 28, 67, 0, 0, 238, 66, 0, 0, 29, 67, 0, 0, 238, 66, 0, 0, 30, 67, 0, 0, 238, 66, 0, 0, 31, 67, 0, 0, 238, 66, 0, 0, 32, 67, 0, 0, 238, 66, 0, 0, 33, 67, 0, 0, 238, 66, 0, 0, 34, 67, 0, 0, 238, 66, 0, 0, 35, 67, 0, 0, 238, 66, 0, 0, 36, 67, 0, 0, 238, 66, 0, 0, 37, 67, 0, 0, 238, 66, 0, 0, 38, 67, 0, 0, 238, 66, 0, 0, 39, 67, 0, 0, 238, 66, 0, 0, 40, 67, 0, 0, 238, 66, 0, 0, 55, 67, 0, 0, 240, 66, 0, 0, 184, 66, 0, 0, 240, 66, 0, 0, 212, 66, 0, 0, 240, 66, 0, 0, 214, 66, 0, 0, 240, 66, 0, 0, 216, 66, 0, 0, 240, 66, 0, 0, 40, 67, 0, 0, 240, 66, 0, 0, 41, 67, 0, 0, 240, 66, 0, 0, 55, 67, 0, 0, 242, 66, 0, 0, 184, 66, 0, 0, 242, 66, 0, 0, 210, 66, 0, 0, 242, 66, 0, 0, 212, 66, 0, 0, 242, 66, 0, 0, 41, 67, 0, 0, 242, 66, 0, 0, 42, 67, 0, 0, 242, 66, 0, 0, 43, 67, 0, 0, 242, 66, 0, 0, 55, 67, 0, 0, 244, 66, 0, 0, 184, 66, 0, 0, 244, 66, 0, 0, 208, 66, 0, 0, 244, 66, 0, 0, 210, 66, 0, 0, 244, 66, 0, 0, 43, 67, 0, 0, 244, 66, 0, 0, 55, 67, 0, 0, 246, 66, 0, 0, 184, 66, 0, 0, 246, 66, 0, 0, 206, 66, 0, 0, 246, 66, 0, 0, 208, 66, 0, 0, 246, 66, 0, 0, 43, 67, 0, 0, 246, 66, 0, 0, 44, 67, 0, 0, 246, 66, 0, 0, 55, 67, 0, 0, 248, 66, 0, 0, 184, 66, 0, 0, 248, 66, 0, 0, 206, 66, 0, 0, 248, 66, 0, 0, 44, 67, 0, 0, 248, 66, 0, 0, 55, 67, 0, 0, 250, 66, 0, 0, 184, 66, 0, 0, 250, 66, 0, 0, 206, 66, 0, 0, 250, 66, 0, 0, 44, 67, 0, 0, 250, 66, 0, 0, 55, 67, 0, 0, 252, 66, 0, 0, 184, 66, 0, 0, 252, 66, 0, 0, 206, 66, 0, 0, 252, 66, 0, 0, 44, 67, 0, 0, 252, 66, 0, 0, 55, 67, 0, 0, 254, 66, 0, 0, 184, 66, 0, 0, 254, 66, 0, 0, 206, 66, 0, 0, 254, 66, 0, 0, 44, 67, 0, 0, 254, 66, 0, 0, 45, 67, 0, 0, 254, 66, 0, 0, 55, 67, 0, 0, 0, 67, 0, 0, 184, 66, 0, 0, 0, 67, 0, 0, 206, 66, 0, 0, 0, 67, 0, 0, 45, 67, 0, 0, 0, 67, 0, 0, 55, 67, 0, 0, 1, 67, 0, 0, 184, 66, 0, 0, 1, 67, 0, 0, 204, 66, 0, 0, 1, 67, 0, 0, 206, 66, 0, 0, 1, 67, 0, 0, 45, 67, 0, 0, 1, 67, 0, 0, 55, 67, 0, 0, 2, 67, 0, 0, 184, 66, 0, 0, 2, 67, 0, 0, 202, 66, 0, 0, 2, 67, 0, 0, 204, 66, 0, 0, 2, 67, 0, 0, 45, 67, 0, 0, 2, 67, 0, 0, 46, 67, 0, 0, 2, 67, 0, 0, 55, 67, 0, 0, 3, 67, 0, 0, 184, 66, 0, 0, 3, 67, 0, 0, 186, 66, 0, 0, 3, 67, 0, 0, 188, 66, 0, 0, 3, 67, 0, 0, 190, 66, 0, 0, 3, 67, 0, 0, 192, 66, 0, 0, 3, 67, 0, 0, 194, 66, 0, 0, 3, 67, 0, 0, 196, 66, 0, 0, 3, 67, 0, 0, 198, 66, 0, 0, 3, 67, 0, 0, 200, 66, 0, 0, 3, 67, 0, 0, 202, 66, 0, 0, 3, 67, 0, 0, 46, 67, 0, 0, 3, 67, 0, 0, 47, 67, 0, 0, 3, 67, 0, 0, 48, 67, 0, 0, 3, 67, 0, 0, 49, 67, 0, 0, 3, 67, 0, 0, 50, 67, 0, 0, 3, 67, 0, 0, 51, 67, 0, 0, 3, 67, 0, 0, 52, 67, 0, 0, 3, 67, 0, 0, 53, 67, 0, 0, 3, 67, 0, 0, 54, 67, 0, 0, 3, 67, 0, 0, 55, 67, 0, 0, 10, 67, 0, 0, 184, 66, 0, 0, 10, 67, 0, 0, 186, 66, 0, 0, 10, 67, 0, 0, 188, 66, 0, 0, 10, 67, 0, 0, 190, 66, 0, 0, 10, 67, 0, 0, 192, 66, 0, 0, 10, 67, 0, 0, 194, 66, 0, 0, 10, 67, 0, 0, 196, 66, 0, 0, 10, 67, 0, 0, 198, 66, 0, 0, 10, 67, 0, 0, 200, 66, 0, 0, 10, 67, 0, 0, 202, 66, 0, 0, 10, 67, 0, 0, 46, 67, 0, 0, 10, 67, 0, 0, 47, 67, 0, 0, 10, 67, 0, 0, 48, 67, 0, 0, 10, 67, 0, 0, 49, 67, 0, 0, 10, 67, 0, 0, 50, 67, 0, 0, 10, 67, 0, 0, 51, 67, 0, 0, 10, 67, 0, 0, 52, 67, 0, 0, 10, 67, 0, 0, 53, 67, 0, 0, 10, 67, 0, 0, 54, 67, 0, 0, 10, 67, 0, 0, 55, 67, 0, 0, 11, 67, 0, 0, 184, 66, 0, 0, 11, 67, 0, 0, 202, 66, 0, 0, 11, 67, 0, 0, 204, 66, 0, 0, 11, 67, 0, 0, 45, 67, 0, 0, 11, 67, 0, 0, 46, 67, 0, 0, 11, 67, 0, 0, 55, 67, 0, 0, 12, 67, 0, 0, 184, 66, 0, 0, 12, 67, 0, 0, 204, 66, 0, 0, 12, 67, 0, 0, 45, 67, 0, 0, 12, 67, 0, 0, 55, 67, 0, 0, 13, 67, 0, 0, 184, 66, 0, 0, 13, 67, 0, 0, 204, 66, 0, 0, 13, 67, 0, 0, 45, 67, 0, 0, 13, 67, 0, 0, 55, 67, 0, 0, 14, 67, 0, 0, 184, 66, 0, 0, 14, 67, 0, 0, 204, 66, 0, 0, 14, 67, 0, 0, 44, 67, 0, 0, 14, 67, 0, 0, 45, 67, 0, 0, 14, 67, 0, 0, 55, 67, 0, 0, 15, 67, 0, 0, 184, 66, 0, 0, 15, 67, 0, 0, 204, 66, 0, 0, 15, 67, 0, 0, 206, 66, 0, 0, 15, 67, 0, 0, 44, 67, 0, 0, 15, 67, 0, 0, 55, 67, 0, 0, 16, 67, 0, 0, 184, 66, 0, 0, 16, 67, 0, 0, 206, 66, 0, 0, 16, 67, 0, 0, 44, 67, 0, 0, 16, 67, 0, 0, 55, 67, 0, 0, 17, 67, 0, 0, 184, 66, 0, 0, 17, 67, 0, 0, 206, 66, 0, 0, 17, 67, 0, 0, 44, 67, 0, 0, 17, 67, 0, 0, 55, 67, 0, 0, 18, 67, 0, 0, 184, 66, 0, 0, 18, 67, 0, 0, 206, 66, 0, 0, 18, 67, 0, 0, 44, 67, 0, 0, 18, 67, 0, 0, 55, 67, 0, 0, 19, 67, 0, 0, 184, 66, 0, 0, 19, 67, 0, 0, 206, 66, 0, 0, 19, 67, 0, 0, 208, 66, 0, 0, 19, 67, 0, 0, 43, 67, 0, 0, 19, 67, 0, 0, 44, 67, 0, 0, 19, 67, 0, 0, 55, 67, 0, 0, 20, 67, 0, 0, 184, 66, 0, 0, 20, 67, 0, 0, 208, 66, 0, 0, 20, 67, 0, 0, 210, 66, 0, 0, 20, 67, 0, 0, 42, 67, 0, 0, 20, 67, 0, 0, 43, 67, 0, 0, 20, 67, 0, 0, 55, 67, 0, 0, 21, 67, 0, 0, 184, 66, 0, 0, 21, 67, 0, 0, 210, 66, 0, 0, 21, 67, 0, 0, 212, 66, 0, 0, 21, 67, 0, 0, 214, 66, 0, 0, 21, 67, 0, 0, 40, 67, 0, 0, 21, 67, 0, 0, 41, 67, 0, 0, 21, 67, 0, 0, 42, 67, 0, 0, 21, 67, 0, 0, 55, 67, 0, 0, 22, 67, 0, 0, 184, 66, 0, 0, 22, 67, 0, 0, 214, 66, 0, 0, 22, 67, 0, 0, 216, 66, 0, 0, 22, 67, 0, 0, 218, 66, 0, 0, 22, 67, 0, 0, 220, 66, 0, 0, 22, 67, 0, 0, 222, 66, 0, 0, 22, 67, 0, 0, 224, 66, 0, 0, 22, 67, 0, 0, 226, 66, 0, 0, 22, 67, 0, 0, 228, 66, 0, 0, 22, 67, 0, 0, 230, 66, 0, 0, 22, 67, 0, 0, 232, 66, 0, 0, 22, 67, 0, 0, 234, 66, 0, 0, 22, 67, 0, 0, 236, 66, 0, 0, 22, 67, 0, 0, 238, 66, 0, 0, 22, 67, 0, 0, 240, 66, 0, 0, 22, 67, 0, 0, 242, 66, 0, 0, 22, 67, 0, 0, 244, 66, 0, 0, 22, 67, 0, 0, 246, 66, 0, 0, 22, 67, 0, 0, 248, 66, 0, 0, 22, 67, 0, 0, 250, 66, 0, 0, 22, 67, 0, 0, 252, 66, 0, 0, 22, 67, 0, 0, 254, 66, 0, 0, 22, 67, 0, 0, 0, 67, 0, 0, 22, 67, 0, 0, 1, 67, 0, 0, 22, 67, 0, 0, 2, 67, 0, 0, 22, 67, 0, 0, 3, 67, 0, 0, 22, 67, 0, 0, 4, 67, 0, 0, 22, 67, 0, 0, 5, 67, 0, 0, 22, 67, 0, 0, 6, 67, 0, 0, 22, 67, 0, 0, 7, 67, 0, 0, 22, 67, 0, 0, 8, 67, 0, 0, 22, 67, 0, 0, 9, 67, 0, 0, 22, 67, 0, 0, 10, 67, 0, 0, 22, 67, 0, 0, 11, 67, 0, 0, 22, 67, 0, 0, 12, 67, 0, 0, 22, 67, 0, 0, 13, 67, 0, 0, 22, 67, 0, 0, 14, 67, 0, 0, 22, 67, 0, 0, 15, 67, 0, 0, 22, 67, 0, 0, 16, 67, 0, 0, 22, 67, 0, 0, 17, 67, 0, 0, 22, 67, 0, 0, 18, 67, 0, 0, 22, 67, 0, 0, 19, 67, 0, 0, 22, 67, 0, 0, 20, 67, 0, 0, 22, 67, 0, 0, 21, 67, 0, 0, 22, 67, 0, 0, 22, 67, 0, 0, 22, 67, 0, 0, 23, 67, 0, 0, 22, 67, 0, 0, 24, 67, 0, 0, 22, 67, 0, 0, 25, 67, 0, 0, 22, 67, 0, 0, 26, 67, 0, 0, 22, 67, 0, 0, 27, 67, 0, 0, 22, 67, 0, 0, 28, 67, 0, 0, 22, 67, 0, 0, 29, 67, 0, 0, 22, 67, 0, 0, 30, 67, 0, 0, 22, 67, 0, 0, 31, 67, 0, 0, 22, 67, 0, 0, 32, 67, 0, 0, 22, 67, 0, 0, 33, 67, 0, 0, 22, 67, 0, 0, 34, 67, 0, 0, 22, 67, 0, 0, 35, 67, 0, 0, 22, 67, 0, 0, 36, 67, 0, 0, 22, 67, 0, 0, 37, 67, 0, 0, 22, 67, 0, 0, 38, 67, 0, 0, 22, 67, 0, 0, 39, 67, 0, 0, 22, 67, 0, 0, 40, 67, 0, 0, 22, 67, 0, 0, 55, 67, 0, 0, 23, 67, 0, 0, 184, 66, 0, 0, 23, 67, 0, 0, 55, 67, 0, 0, 24, 67, 0, 0, 184, 66, 0, 0, 24, 67, 0, 0, 55, 67, 0, 0, 25, 67, 0, 0, 184, 66, 0, 0, 25, 67, 0, 0, 55, 67, 0, 0, 26, 67, 0, 0, 184, 66, 0, 0, 26, 67, 0, 0, 55, 67, 0, 0, 27, 67, 0, 0, 184, 66, 0, 0, 27, 67, 0, 0, 55, 67, 0, 0, 28, 67, 0, 0, 184, 66, 0, 0, 28, 67, 0, 0, 55, 67, 0, 0, 29, 67, 0, 0, 184, 66, 0, 0, 29, 67, 0, 0, 55, 67, 0, 0, 30, 67, 0, 0, 184, 66, 0, 0, 30, 67, 0, 0, 55, 67, 0, 0, 31, 67, 0, 0, 184, 66, 0, 0, 31, 67, 0, 0, 55, 67, 0, 0, 32, 67, 0, 0, 184, 66, 0, 0, 32, 67, 0, 0, 55, 67, 0, 0, 33, 67, 0, 0, 184, 66, 0, 0, 33, 67, 0, 0, 55, 67, 0, 0, 34, 67, 0, 0, 184, 66, 0, 0, 34, 67, 0, 0, 55, 67, 0, 0, 35, 67, 0, 0, 184, 66, 0, 0, 35, 67, 0, 0, 55, 67, 0, 0, 36, 67, 0, 0, 184, 66, 0, 0, 36, 67, 0, 0, 55, 67, 0, 0, 37, 67, 0, 0, 184, 66, 0, 0, 37, 67, 0, 0, 55, 67, 0, 0, 38, 67, 0, 0, 184, 66, 0, 0, 38, 67, 0, 0, 55, 67, 0, 0, 39, 67, 0, 0, 184, 66, 0, 0, 39, 67, 0, 0, 55, 67, 0, 0, 40, 67, 0, 0, 184, 66, 0, 0, 40, 67, 0, 0, 55, 67, 0, 0, 41, 67, 0, 0, 184, 66, 0, 0, 41, 67, 0, 0, 55, 67, 0, 0, 42, 67, 0, 0, 184, 66, 0, 0, 42, 67, 0, 0, 55, 67, 0, 0, 43, 67, 0, 0, 184, 66, 0, 0, 43, 67, 0, 0, 55, 67, 0, 0, 44, 67, 0, 0, 184, 66, 0, 0, 44, 67, 0, 0, 55, 67, 0, 0, 45, 67, 0, 0, 184, 66, 0, 0, 45, 67, 0, 0, 214, 66, 0, 0, 45, 67, 0, 0, 216, 66, 0, 0, 45, 67, 0, 0, 218, 66, 0, 0, 45, 67, 0, 0, 220, 66, 0, 0, 45, 67, 0, 0, 222, 66, 0, 0, 45, 67, 0, 0, 224, 66, 0, 0, 45, 67, 0, 0, 226, 66, 0, 0, 45, 67, 0, 0, 228, 66, 0, 0, 45, 67, 0, 0, 230, 66, 0, 0, 45, 67, 0, 0, 232, 66, 0, 0, 45, 67, 0, 0, 234, 66, 0, 0, 45, 67, 0, 0, 236, 66, 0, 0, 45, 67, 0, 0, 238, 66, 0, 0, 45, 67, 0, 0, 240, 66, 0, 0, 45, 67, 0, 0, 242, 66, 0, 0, 45, 67, 0, 0, 244, 66, 0, 0, 45, 67, 0, 0, 246, 66, 0, 0, 45, 67, 0, 0, 248, 66, 0, 0, 45, 67, 0, 0, 250, 66, 0, 0, 45, 67, 0, 0, 252, 66, 0, 0, 45, 67, 0, 0, 254, 66, 0, 0, 45, 67, 0, 0, 0, 67, 0, 0, 45, 67, 0, 0, 1, 67, 0, 0, 45, 67, 0, 0, 2, 67, 0, 0, 45, 67, 0, 0, 3, 67, 0, 0, 45, 67, 0, 0, 4, 67, 0, 0, 45, 67, 0, 0, 5, 67, 0, 0, 45, 67, 0, 0, 6, 67, 0, 0, 45, 67, 0, 0, 7, 67, 0, 0, 45, 67, 0, 0, 8, 67, 0, 0, 45, 67, 0, 0, 9, 67, 0, 0, 45, 67, 0, 0, 10, 67, 0, 0, 45, 67, 0, 0, 11, 67, 0, 0, 45, 67, 0, 0, 12, 67, 0, 0, 45, 67, 0, 0, 13, 67, 0, 0, 45, 67, 0, 0, 14, 67, 0, 0, 45, 67, 0, 0, 15, 67, 0, 0, 45, 67, 0, 0, 16, 67, 0, 0, 45, 67, 0, 0, 17, 67, 0, 0, 45, 67, 0, 0, 18, 67, 0, 0, 45, 67, 0, 0, 19, 67, 0, 0, 45, 67, 0, 0, 20, 67, 0, 0, 45, 67, 0, 0, 21, 67, 0, 0, 45, 67, 0, 0, 22, 67, 0, 0, 45, 67, 0, 0, 23, 67, 0, 0, 45, 67, 0, 0, 24, 67, 0, 0, 45, 67, 0, 0, 25, 67, 0, 0, 45, 67, 0, 0, 26, 67, 0, 0, 45, 67, 0, 0, 27, 67, 0, 0, 45, 67, 0, 0, 28, 67, 0, 0, 45, 67, 0, 0, 29, 67, 0, 0, 45, 67, 0, 0, 30, 67, 0, 0, 45, 67, 0, 0, 31, 67, 0, 0, 45, 67, 0, 0, 32, 67, 0, 0, 45, 67, 0, 0, 33, 67, 0, 0, 45, 67, 0, 0, 34, 67, 0, 0, 45, 67, 0, 0, 35, 67, 0, 0, 45, 67, 0, 0, 36, 67, 0, 0, 45, 67, 0, 0, 37, 67, 0, 0, 45, 67, 0, 0, 38, 67, 0, 0, 45, 67, 0, 0, 39, 67, 0, 0, 45, 67, 0, 0, 40, 67, 0, 0, 45, 67, 0, 0, 55, 67, 0, 0, 46, 67, 0, 0, 184, 66, 0, 0, 46, 67, 0, 0, 210, 66, 0, 0, 46, 67, 0, 0, 212, 66, 0, 0, 46, 67, 0, 0, 214, 66, 0, 0, 46, 67, 0, 0, 40, 67, 0, 0, 46, 67, 0, 0, 41, 67, 0, 0, 46, 67, 0, 0, 42, 67, 0, 0, 46, 67, 0, 0, 55, 67, 0, 0, 47, 67, 0, 0, 184, 66, 0, 0, 47, 67, 0, 0, 208, 66, 0, 0, 47, 67, 0, 0, 210, 66, 0, 0, 47, 67, 0, 0, 42, 67, 0, 0, 47, 67, 0, 0, 43, 67, 0, 0, 47, 67, 0, 0, 55, 67, 0, 0, 48, 67, 0, 0, 184, 66, 0, 0, 48, 67, 0, 0, 206, 66, 0, 0, 48, 67, 0, 0, 208, 66, 0, 0, 48, 67, 0, 0, 43, 67, 0, 0, 48, 67, 0, 0, 44, 67, 0, 0, 48, 67, 0, 0, 55, 67, 0, 0, 49, 67, 0, 0, 184, 66, 0, 0, 49, 67, 0, 0, 206, 66, 0, 0, 49, 67, 0, 0, 44, 67, 0, 0, 49, 67, 0, 0, 55, 67, 0, 0, 50, 67, 0, 0, 184, 66, 0, 0, 50, 67, 0, 0, 206, 66, 0, 0, 50, 67, 0, 0, 44, 67, 0, 0, 50, 67, 0, 0, 55, 67, 0, 0, 51, 67, 0, 0, 184, 66, 0, 0, 51, 67, 0, 0, 206, 66, 0, 0, 51, 67, 0, 0, 44, 67, 0, 0, 51, 67, 0, 0, 55, 67, 0, 0, 52, 67, 0, 0, 184, 66, 0, 0, 52, 67, 0, 0, 206, 66, 0, 0, 52, 67, 0, 0, 44, 67, 0, 0, 52, 67, 0, 0, 45, 67, 0, 0, 52, 67, 0, 0, 55, 67, 0, 0, 53, 67, 0, 0, 184, 66, 0, 0, 53, 67, 0, 0, 204, 66, 0, 0, 53, 67, 0, 0, 206, 66, 0, 0, 53, 67, 0, 0, 45, 67, 0, 0, 53, 67, 0, 0, 55, 67, 0, 0, 54, 67, 0, 0, 184, 66, 0, 0, 54, 67, 0, 0, 204, 66, 0, 0, 54, 67, 0, 0, 45, 67, 0, 0, 54, 67, 0, 0, 55, 67, 0, 0, 55, 67, 0, 0, 184, 66, 0, 0, 55, 67, 0, 0, 204, 66, 0, 0, 55, 67, 0, 0, 45, 67, 0, 0, 55, 67, 0, 0, 55, 67, 0, 0, 56, 67, 0, 0, 184, 66, 0, 0, 56, 67, 0, 0, 202, 66, 0, 0, 56, 67, 0, 0, 204, 66, 0, 0, 56, 67, 0, 0, 45, 67, 0, 0, 56, 67, 0, 0, 46, 67, 0, 0, 56, 67, 0, 0, 55, 67, 0, 0, 57, 67, 0, 0, 184, 66, 0, 0, 57, 67, 0, 0, 186, 66, 0, 0, 57, 67, 0, 0, 188, 66, 0, 0, 57, 67, 0, 0, 190, 66, 0, 0, 57, 67, 0, 0, 192, 66, 0, 0, 57, 67, 0, 0, 194, 66, 0, 0, 57, 67, 0, 0, 196, 66, 0, 0, 57, 67, 0, 0, 198, 66, 0, 0, 57, 67, 0, 0, 200, 66, 0, 0, 57, 67, 0, 0, 202, 66, 0, 0, 57, 67, 0, 0, 46, 67, 0, 0, 57, 67, 0, 0, 47, 67, 0, 0, 57, 67, 0, 0, 48, 67, 0, 0, 57, 67, 0, 0, 49, 67, 0, 0, 57, 67, 0, 0, 50, 67, 0, 0, 57, 67, 0, 0, 51, 67, 0, 0, 57, 67, 0, 0, 52, 67, 0, 0, 57, 67, 0, 0, 53, 67, 0, 0, 57, 67, 0, 0, 54, 67, 0, 0, 57, 67, 0, 0, 55, 67, 0, 0, 72, 67, 0, 0, 198, 66, 0, 0, 72, 67, 0, 0, 200, 66, 0, 0, 72, 67, 0, 0, 202, 66, 0, 0, 72, 67, 0, 0, 204, 66, 0, 0, 72, 67, 0, 0, 206, 66, 0, 0, 72, 67, 0, 0, 208, 66, 0, 0, 72, 67, 0, 0, 210, 66, 0, 0, 72, 67, 0, 0, 212, 66, 0, 0, 72, 67, 0, 0, 214, 66, 0, 0, 72, 67, 0, 0, 216, 66, 0, 0, 72, 67, 0, 0, 218, 66, 0, 0, 72, 67, 0, 0, 220, 66, 0, 0, 72, 67, 0, 0, 222, 66, 0, 0, 72, 67, 0, 0, 42, 67, 0, 0, 72, 67, 0, 0, 43, 67, 0, 0, 72, 67, 0, 0, 44, 67, 0, 0, 72, 67, 0, 0, 45, 67, 0, 0, 72, 67, 0, 0, 46, 67, 0, 0, 72, 67, 0, 0, 47, 67, 0, 0, 72, 67, 0, 0, 48, 67, 0, 0, 72, 67, 0, 0, 49, 67, 0, 0, 73, 67, 0, 0, 196, 66, 0, 0, 73, 67, 0, 0, 198, 66, 0, 0, 73, 67, 0, 0, 222, 66, 0, 0, 73, 67, 0, 0, 224, 66, 0, 0, 73, 67, 0, 0, 226, 66, 0, 0, 73, 67, 0, 0, 228, 66, 0, 0, 73, 67, 0, 0, 230, 66, 0, 0, 73, 67, 0, 0, 41, 67, 0, 0, 73, 67, 0, 0, 42, 67, 0, 0, 73, 67, 0, 0, 49, 67, 0, 0, 73, 67, 0, 0, 50, 67, 0, 0, 74, 67, 0, 0, 190, 66, 0, 0, 74, 67, 0, 0, 192, 66, 0, 0, 74, 67, 0, 0, 194, 66, 0, 0, 74, 67, 0, 0, 196, 66, 0, 0, 74, 67, 0, 0, 230, 66, 0, 0, 74, 67, 0, 0, 232, 66, 0, 0, 74, 67, 0, 0, 234, 66, 0, 0, 74, 67, 0, 0, 236, 66, 0, 0, 74, 67, 0, 0, 238, 66, 0, 0, 74, 67, 0, 0, 240, 66, 0, 0, 74, 67, 0, 0, 242, 66, 0, 0, 74, 67, 0, 0, 244, 66, 0, 0, 74, 67, 0, 0, 246, 66, 0, 0, 74, 67, 0, 0, 39, 67, 0, 0, 74, 67, 0, 0, 40, 67, 0, 0, 74, 67, 0, 0, 41, 67, 0, 0, 74, 67, 0, 0, 50, 67, 0, 0, 74, 67, 0, 0, 51, 67, 0, 0, 74, 67, 0, 0, 52, 67, 0, 0, 75, 67, 0, 0, 188, 66, 0, 0, 75, 67, 0, 0, 190, 66, 0, 0, 75, 67, 0, 0, 246, 66, 0, 0, 75, 67, 0, 0, 248, 66, 0, 0, 75, 67, 0, 0, 250, 66, 0, 0, 75, 67, 0, 0, 252, 66, 0, 0, 75, 67, 0, 0, 254, 66, 0, 0, 75, 67, 0, 0, 38, 67, 0, 0, 75, 67, 0, 0, 39, 67, 0, 0, 75, 67, 0, 0, 52, 67, 0, 0, 75, 67, 0, 0, 53, 67, 0, 0, 76, 67, 0, 0, 186, 66, 0, 0, 76, 67, 0, 0, 188, 66, 0, 0, 76, 67, 0, 0, 254, 66, 0, 0, 76, 67, 0, 0, 0, 67, 0, 0, 76, 67, 0, 0, 1, 67, 0, 0, 76, 67, 0, 0, 2, 67, 0, 0, 76, 67, 0, 0, 3, 67, 0, 0, 76, 67, 0, 0, 4, 67, 0, 0, 76, 67, 0, 0, 5, 67, 0, 0, 76, 67, 0, 0, 6, 67, 0, 0, 76, 67, 0, 0, 7, 67, 0, 0, 76, 67, 0, 0, 8, 67, 0, 0, 76, 67, 0, 0, 37, 67, 0, 0, 76, 67, 0, 0, 38, 67, 0, 0, 76, 67, 0, 0, 53, 67, 0, 0, 76, 67, 0, 0, 54, 67, 0, 0, 77, 67, 0, 0, 184, 66, 0, 0, 77, 67, 0, 0, 186, 66, 0, 0, 77, 67, 0, 0, 8, 67, 0, 0, 77, 67, 0, 0, 9, 67, 0, 0, 77, 67, 0, 0, 10, 67, 0, 0, 77, 67, 0, 0, 11, 67, 0, 0, 77, 67, 0, 0, 12, 67, 0, 0, 77, 67, 0, 0, 36, 67, 0, 0, 77, 67, 0, 0, 37, 67, 0, 0, 77, 67, 0, 0, 54, 67, 0, 0, 77, 67, 0, 0, 55, 67, 0, 0, 78, 67, 0, 0, 184, 66, 0, 0, 78, 67, 0, 0, 12, 67, 0, 0, 78, 67, 0, 0, 13, 67, 0, 0, 78, 67, 0, 0, 14, 67, 0, 0, 78, 67, 0, 0, 15, 67, 0, 0, 78, 67, 0, 0, 16, 67, 0, 0, 78, 67, 0, 0, 17, 67, 0, 0, 78, 67, 0, 0, 18, 67, 0, 0, 78, 67, 0, 0, 19, 67, 0, 0, 78, 67, 0, 0, 20, 67, 0, 0, 78, 67, 0, 0, 21, 67, 0, 0, 78, 67, 0, 0, 22, 67, 0, 0, 78, 67, 0, 0, 23, 67, 0, 0, 78, 67, 0, 0, 24, 67, 0, 0, 78, 67, 0, 0, 25, 67, 0, 0, 78, 67, 0, 0, 26, 67, 0, 0, 78, 67, 0, 0, 36, 67, 0, 0, 78, 67, 0, 0, 55, 67, 0, 0, 79, 67, 0, 0, 182, 66, 0, 0, 79, 67, 0, 0, 184, 66, 0, 0, 79, 67, 0, 0, 26, 67, 0, 0, 79, 67, 0, 0, 27, 67, 0, 0, 79, 67, 0, 0, 35, 67, 0, 0, 79, 67, 0, 0, 36, 67, 0, 0, 79, 67, 0, 0, 55, 67, 0, 0, 79, 67, 0, 0, 56, 67, 0, 0, 80, 67, 0, 0, 182, 66, 0, 0, 80, 67, 0, 0, 27, 67, 0, 0, 80, 67, 0, 0, 34, 67, 0, 0, 80, 67, 0, 0, 35, 67, 0, 0, 80, 67, 0, 0, 56, 67, 0, 0, 80, 67, 0, 0, 57, 67, 0, 0, 81, 67, 0, 0, 180, 66, 0, 0, 81, 67, 0, 0, 182, 66, 0, 0, 81, 67, 0, 0, 27, 67, 0, 0, 81, 67, 0, 0, 34, 67, 0, 0, 81, 67, 0, 0, 57, 67, 0, 0, 82, 67, 0, 0, 180, 66, 0, 0, 82, 67, 0, 0, 27, 67, 0, 0, 82, 67, 0, 0, 34, 67, 0, 0, 82, 67, 0, 0, 57, 67, 0, 0, 83, 67, 0, 0, 180, 66, 0, 0, 83, 67, 0, 0, 27, 67, 0, 0, 83, 67, 0, 0, 34, 67, 0, 0, 83, 67, 0, 0, 57, 67, 0, 0, 84, 67, 0, 0, 180, 66, 0, 0, 84, 67, 0, 0, 27, 67, 0, 0, 84, 67, 0, 0, 34, 67, 0, 0, 84, 67, 0, 0, 57, 67, 0, 0, 85, 67, 0, 0, 180, 66, 0, 0, 85, 67, 0, 0, 27, 67, 0, 0, 85, 67, 0, 0, 34, 67, 0, 0, 85, 67, 0, 0, 57, 67, 0, 0, 86, 67, 0, 0, 180, 66, 0, 0, 86, 67, 0, 0, 27, 67, 0, 0, 86, 67, 0, 0, 34, 67, 0, 0, 86, 67, 0, 0, 57, 67, 0, 0, 87, 67, 0, 0, 180, 66, 0, 0, 87, 67, 0, 0, 27, 67, 0, 0, 87, 67, 0, 0, 34, 67, 0, 0, 87, 67, 0, 0, 35, 67, 0, 0, 87, 67, 0, 0, 56, 67, 0, 0, 87, 67, 0, 0, 57, 67, 0, 0, 88, 67, 0, 0, 180, 66, 0, 0, 88, 67, 0, 0, 182, 66, 0, 0, 88, 67, 0, 0, 26, 67, 0, 0, 88, 67, 0, 0, 27, 67, 0, 0, 88, 67, 0, 0, 35, 67, 0, 0, 88, 67, 0, 0, 36, 67, 0, 0, 88, 67, 0, 0, 55, 67, 0, 0, 88, 67, 0, 0, 56, 67, 0, 0, 89, 67, 0, 0, 182, 66, 0, 0, 89, 67, 0, 0, 184, 66, 0, 0, 89, 67, 0, 0, 15, 67, 0, 0, 89, 67, 0, 0, 16, 67, 0, 0, 89, 67, 0, 0, 17, 67, 0, 0, 89, 67, 0, 0, 18, 67, 0, 0, 89, 67, 0, 0, 19, 67, 0, 0, 89, 67, 0, 0, 20, 67, 0, 0, 89, 67, 0, 0, 21, 67, 0, 0, 89, 67, 0, 0, 22, 67, 0, 0, 89, 67, 0, 0, 23, 67, 0, 0, 89, 67, 0, 0, 24, 67, 0, 0, 89, 67, 0, 0, 25, 67, 0, 0, 89, 67, 0, 0, 26, 67, 0, 0, 89, 67, 0, 0, 36, 67, 0, 0, 89, 67, 0, 0, 55, 67, 0, 0, 90, 67, 0, 0, 184, 66, 0, 0, 90, 67, 0, 0, 10, 67, 0, 0, 90, 67, 0, 0, 11, 67, 0, 0, 90, 67, 0, 0, 12, 67, 0, 0, 90, 67, 0, 0, 13, 67, 0, 0, 90, 67, 0, 0, 14, 67, 0, 0, 90, 67, 0, 0, 15, 67, 0, 0, 90, 67, 0, 0, 36, 67, 0, 0, 90, 67, 0, 0, 37, 67, 0, 0, 90, 67, 0, 0, 54, 67, 0, 0, 90, 67, 0, 0, 55, 67, 0, 0, 91, 67, 0, 0, 184, 66, 0, 0, 91, 67, 0, 0, 186, 66, 0, 0, 91, 67, 0, 0, 3, 67, 0, 0, 91, 67, 0, 0, 4, 67, 0, 0, 91, 67, 0, 0, 5, 67, 0, 0, 91, 67, 0, 0, 6, 67, 0, 0, 91, 67, 0, 0, 7, 67, 0, 0, 91, 67, 0, 0, 8, 67, 0, 0, 91, 67, 0, 0, 9, 67, 0, 0, 91, 67, 0, 0, 10, 67, 0, 0, 91, 67, 0, 0, 37, 67, 0, 0, 91, 67, 0, 0, 38, 67, 0, 0, 91, 67, 0, 0, 53, 67, 0, 0, 91, 67, 0, 0, 54, 67, 0, 0, 92, 67, 0, 0, 186, 66, 0, 0, 92, 67, 0, 0, 188, 66, 0, 0, 92, 67, 0, 0, 0, 67, 0, 0, 92, 67, 0, 0, 1, 67, 0, 0, 92, 67, 0, 0, 2, 67, 0, 0, 92, 67, 0, 0, 3, 67, 0, 0, 92, 67, 0, 0, 38, 67, 0, 0, 92, 67, 0, 0, 39, 67, 0, 0, 92, 67, 0, 0, 52, 67, 0, 0, 92, 67, 0, 0, 53, 67, 0, 0, 93, 67, 0, 0, 188, 66, 0, 0, 93, 67, 0, 0, 190, 66, 0, 0, 93, 67, 0, 0, 244, 66, 0, 0, 93, 67, 0, 0, 246, 66, 0, 0, 93, 67, 0, 0, 248, 66, 0, 0, 93, 67, 0, 0, 250, 66, 0, 0, 93, 67, 0, 0, 252, 66, 0, 0, 93, 67, 0, 0, 254, 66, 0, 0, 93, 67, 0, 0, 0, 67, 0, 0, 93, 67, 0, 0, 39, 67, 0, 0, 93, 67, 0, 0, 40, 67, 0, 0, 93, 67, 0, 0, 41, 67, 0, 0, 93, 67, 0, 0, 50, 67, 0, 0, 93, 67, 0, 0, 51, 67, 0, 0, 93, 67, 0, 0, 52, 67, 0, 0, 94, 67, 0, 0, 190, 66, 0, 0, 94, 67, 0, 0, 192, 66, 0, 0, 94, 67, 0, 0, 238, 66, 0, 0, 94, 67, 0, 0, 240, 66, 0, 0, 94, 67, 0, 0, 242, 66, 0, 0, 94, 67, 0, 0, 244, 66, 0, 0, 94, 67, 0, 0, 41, 67, 0, 0, 94, 67, 0, 0, 42, 67, 0, 0, 94, 67, 0, 0, 49, 67, 0, 0, 94, 67, 0, 0, 50, 67, 0, 0, 95, 67, 0, 0, 192, 66, 0, 0, 95, 67, 0, 0, 194, 66, 0, 0, 95, 67, 0, 0, 196, 66, 0, 0, 95, 67, 0, 0, 226, 66, 0, 0, 95, 67, 0, 0, 228, 66, 0, 0, 95, 67, 0, 0, 230, 66, 0, 0, 95, 67, 0, 0, 232, 66, 0, 0, 95, 67, 0, 0, 234, 66, 0, 0, 95, 67, 0, 0, 236, 66, 0, 0, 95, 67, 0, 0, 238, 66, 0, 0, 95, 67, 0, 0, 42, 67, 0, 0, 95, 67, 0, 0, 43, 67, 0, 0, 95, 67, 0, 0, 44, 67, 0, 0, 95, 67, 0, 0, 45, 67, 0, 0, 95, 67, 0, 0, 46, 67, 0, 0, 95, 67, 0, 0, 47, 67, 0, 0, 95, 67, 0, 0, 48, 67, 0, 0, 95, 67, 0, 0, 49, 67, 0, 0, 96, 67, 0, 0, 196, 66, 0, 0, 96, 67, 0, 0, 198, 66, 0, 0, 96, 67, 0, 0, 200, 66, 0, 0, 96, 67, 0, 0, 220, 66, 0, 0, 96, 67, 0, 0, 222, 66, 0, 0, 96, 67, 0, 0, 224, 66, 0, 0, 96, 67, 0, 0, 226, 66, 0, 0, 97, 67, 0, 0, 200, 66, 0, 0, 97, 67, 0, 0, 202, 66, 0, 0, 97, 67, 0, 0, 204, 66, 0, 0, 97, 67, 0, 0, 206, 66, 0, 0, 97, 67, 0, 0, 208, 66, 0, 0, 97, 67, 0, 0, 210, 66, 0, 0, 97, 67, 0, 0, 212, 66, 0, 0, 97, 67, 0, 0, 214, 66, 0, 0, 97, 67, 0, 0, 216, 66, 0, 0, 97, 67, 0, 0, 218, 66, 0, 0, 97, 67, 0, 0, 220, 66, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 28, 0, 1, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 208, 201, 83, 8, 0, 0, 0, 0, 130, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 8, 202, 83, 8, 0, 0, 0, 0, 131, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 64, 202, 83, 8, 0, 0, 0, 0, 132, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 120, 202, 83, 8, 0, 0, 0, 0, 133, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 20, 4, 1, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 176, 202, 83, 8, 0, 0, 0, 0, 134, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 244, 3, 3, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 232, 202, 83, 8, 0, 0, 0, 0, 135, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 32, 203, 83, 8, 0, 0, 0, 0, 136, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 248, 1, 2, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 88, 203, 83, 8, 0, 0, 0, 0, 137, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 144, 203, 83, 8, 0, 0, 0, 0, 138, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 200, 203, 83, 8, 0, 0, 0, 0, 139, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0, 204, 83, 8, 0, 0, 0, 0, 140, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 56, 204, 83, 8, 0, 0, 0, 0, 141, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 112, 204, 83, 8, 0, 0, 0, 0, 142, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 168, 204, 83, 8, 0, 0, 0, 0, 143, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 224, 204, 83, 8, 0, 0, 0, 0, 144, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 24, 205, 83, 8, 0, 0, 0, 0, 145, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 80, 205, 83, 8, 0, 0, 0, 0, 146, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 136, 205, 83, 8, 0, 0, 0, 0, 147, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 192, 205, 83, 8, 0, 0, 0, 0, 148, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 248, 205, 83, 8, 0, 0, 0, 0, 149, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 48, 206, 83, 8, 0, 0, 0, 0, 150, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 104, 206, 83, 8, 0, 0, 0, 0, 151, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 160, 206, 83, 8, 0, 0, 0, 0, 152, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 216, 206, 83, 8, 0, 0, 0, 0, 153, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 16, 207, 83, 8, 0, 0, 0, 0, 154, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 72, 207, 83, 8, 0, 0, 0, 0, 155, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 128, 207, 83, 8, 0, 0, 0, 0, 156, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 184, 207, 83, 8, 0, 0, 0, 0, 157, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 240, 207, 83, 8, 0, 0, 0, 0, 158, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 40, 208, 83, 8, 0, 0, 0, 0, 159, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 96, 208, 83, 8, 0, 0, 0, 0, 160, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 2, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 152, 208, 83, 8, 0, 0, 0, 0, 161, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 208, 208, 83, 8, 0, 0, 0, 0, 162, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 8, 209, 83, 8, 0, 0, 0, 0, 163, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 64, 209, 83, 8, 0, 0, 0, 0, 164, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 120, 209, 83, 8, 0, 0, 0, 0, 165, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 4, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 176, 209, 83, 8, 0, 0, 0, 0, 166, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 232, 209, 83, 8, 0, 0, 0, 0, 167, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 32, 210, 83, 8, 0, 0, 0, 0, 168, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 88, 210, 83, 8, 0, 0, 0, 0, 169, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 144, 210, 83, 8, 0, 0, 0, 0, 170, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 200, 210, 83, 8, 0, 0, 0, 0, 171, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0, 211, 83, 8, 0, 0, 0, 0, 172, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 56, 211, 83, 8, 0, 0, 0, 0, 173, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 112, 211, 83, 8, 0, 0, 0, 0, 174, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 168, 211, 83, 8, 0, 0, 0, 0, 175, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 224, 211, 83, 8, 0, 0, 0, 0, 176, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 24, 212, 83, 8, 0, 0, 0, 0, 177, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 80, 212, 83, 8, 0, 0, 0, 0, 178, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 136, 212, 83, 8, 0, 0, 0, 0, 179, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 192, 212, 83, 8, 0, 0, 0, 0, 180, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 248, 212, 83, 8, 0, 0, 0, 0, 181, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 48, 213, 83, 8, 0, 0, 0, 0, 182, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 77, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 104, 213, 83, 8, 0, 0, 0, 0, 183, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 160, 213, 83, 8, 0, 0, 0, 0, 184, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 216, 213, 83, 8, 0, 0, 0, 0, 185, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 16, 214, 83, 8, 0, 0, 0, 0, 186, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 72, 214, 83, 8, 0, 0, 0, 0, 187, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 128, 214, 83, 8, 0, 0, 0, 0, 188, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 184, 214, 83, 8, 0, 0, 0, 0, 189, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 240, 214, 83, 8, 0, 0, 0, 0, 190, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 40, 215, 83, 8, 0, 0, 0, 0, 191, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 96, 215, 83, 8, 0, 0, 0, 0, 192, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 152, 215, 83, 8, 0, 0, 0, 0, 193, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 208, 215, 83, 8, 0, 0, 0, 0, 194, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 8, 216, 83, 8, 0, 0, 0, 0, 195, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 64, 216, 83, 8, 0, 0, 0, 0, 196, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 120, 216, 83, 8, 0, 0, 0, 0, 197, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 176, 216, 83, 8, 0, 0, 0, 0, 198, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 232, 216, 83, 8, 0, 0, 0, 0, 199, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 32, 217, 83, 8, 0, 0, 0, 0, 200, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 88, 217, 83, 8, 0, 0, 0, 0, 201, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 144, 217, 83, 8, 0, 0, 0, 0, 202, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 120, 127, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 200, 217, 83, 8, 0, 0, 0, 0, 203, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 0, 218, 83, 8, 0, 0, 0, 0, 204, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 56, 218, 83, 8, 0, 0, 0, 0, 205, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 112, 218, 83, 8, 0, 0, 0, 0, 206, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 168, 218, 83, 8, 0, 0, 0, 0, 207, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 224, 218, 83, 8, 0, 0, 0, 0, 208, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 24, 219, 83, 8, 0, 0, 0, 0, 209, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 80, 219, 83, 8, 0, 0, 0, 0, 210, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 136, 219, 83, 8, 0, 0, 0, 0, 211, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 192, 219, 83, 8, 0, 0, 0, 0, 212, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 248, 219, 83, 8, 0, 0, 0, 0, 213, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 48, 220, 83, 8, 0, 0, 0, 0, 214, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 104, 220, 83, 8, 0, 0, 0, 0, 215, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 160, 220, 83, 8, 0, 0, 0, 0, 216, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 216, 220, 83, 8, 0, 0, 0, 0, 217, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 109, 206, 115, 33, 0, 0, 0, 0, 193, 1, 0, 0, 0, 0, 0, 0, 112, 2, 75, 33, 0, 0, 0, 0, 144, 142, 95, 122, 120, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 18, 207, 32, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 45, 154, 115, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 141, 113, 33, 0, 0, 0, 0, 224, 140, 113, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 96, 218, 8, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 0, 0, 96, 53, 120, 33, 0, 0, 0, 0, 112, 105, 114, 33, 0, 0, 0, 0, 1, 0, 0, 1, 129, 0, 0, 0, 113, 0, 0, 4, 80, 0, 3, 0, 110, 0, 0, 33, 12, 4, 3, 0, 0, 0, 0, 0, 0, 2, 134, 0, 198, 6, 0, 36, 16, 4, 43, 0, 129, 0, 0, 0, 0, 0, 0, 0, 160, 73, 224, 32, 0, 0, 0, 0, 80, 250, 120, 33, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 113, 0, 0, 4, 80, 0, 3, 0, 110, 0, 0, 33, 12, 4, 3, 0, 0, 0, 0, 0, 0, 2, 134, 0, 200, 6, 0, 36, 16, 4, 43, 0, 65, 0, 0, 0, 0, 0, 0, 0, 16, 251, 120, 33, 0, 0, 0, 0, 160, 73, 224, 32, 0, 0, 0, 0, 1, 0, 0, 1, 33, 0, 0, 0, 113, 0, 0, 4, 80, 0, 3, 0, 110, 0, 0, 33, 12, 4, 3, 0, 0, 0, 0, 0, 0, 2, 134, 0, 192, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, 0, 0, 0, 0, 107, 114, 33, 0, 0, 0, 0, 144, 137, 165, 32, 0, 0, 0, 0, 240, 104, 240, 32, 0, 0, 0, 0, 16, 107, 114, 33, 0, 0, 0, 0, 112, 137, 165, 32, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 0, 16, 53, 120, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 53, 120, 33, 0, 0, 0, 0), "format": "RGFloat", @@ -214,7 +212,7 @@ data = { } [sub_resource type="ImageTexture" id="ImageTexture_sshgl"] -image = SubResource("Image_k3r11") +image = SubResource("Image_5dfpo") [sub_resource type="ParticleProcessMaterial" id="29"] emission_shape = 5 @@ -246,11 +244,9 @@ curve = SubResource("Curve_e07dx") particle_flag_disable_z = true direction = Vector3(0, -1, 0) spread = 25.0 -gravity = Vector3(0, 200, 0) initial_velocity_min = 160.0 initial_velocity_max = 160.0 -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 +gravity = Vector3(0, 200, 0) scale_curve = SubResource("CurveTexture_p4r4n") sub_emitter_mode = 2 sub_emitter_amount_at_end = 1 @@ -266,11 +262,9 @@ curve = SubResource("Curve_dlskh") [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_m4hvx"] particle_flag_disable_z = true direction = Vector3(0, -1, 0) -gravity = Vector3(0, -400, 0) initial_velocity_min = 100.0 initial_velocity_max = 100.0 -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 +gravity = Vector3(0, -400, 0) scale_curve = SubResource("CurveTexture_eeisx") color = Color(1, 0.835294, 0, 1) sub_emitter_mode = 2 @@ -285,10 +279,8 @@ gradient = SubResource("Gradient_dxj60") [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_mcjyg"] particle_flag_disable_z = true -gravity = Vector3(0, 0, 0) -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 angle_max = 360.0 +gravity = Vector3(0, 0, 0) scale_curve = SubResource("CurveTexture_eeisx") color_ramp = SubResource("GradientTexture1D_bw7sy") sub_emitter_mode = 2 @@ -310,14 +302,12 @@ curve = SubResource("Curve_6x53c") [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_vbd24"] particle_flag_disable_z = true +angle_max = 360.0 direction = Vector3(0, -1, 0) spread = 0.0 -gravity = Vector3(0, 98, 0) initial_velocity_min = 150.0 initial_velocity_max = 150.0 -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 -angle_max = 360.0 +gravity = Vector3(0, 98, 0) scale_curve = SubResource("CurveTexture_m0l6n") color = Color(0.764706, 0.309804, 1, 1) color_ramp = SubResource("GradientTexture1D_v22dq") @@ -336,15 +326,13 @@ point_count = 3 curve = SubResource("Curve_qu2at") [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_mg3j6"] +particle_flag_disable_z = true emission_shape = 3 emission_box_extents = Vector3(40, 1, 1) -particle_flag_disable_z = true +angle_max = 360.0 gravity = Vector3(0, 400, 0) -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 damping_min = 20.0 damping_max = 200.0 -angle_max = 360.0 scale_curve = SubResource("CurveTexture_mx2gv") hue_variation_max = 0.25 collision_mode = 1 @@ -353,16 +341,14 @@ collision_bounce = 0.15 collision_use_scale = true [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_jtilh"] +particle_flag_disable_z = true emission_shape = 3 emission_box_extents = Vector3(40, 1, 1) -particle_flag_disable_z = true direction = Vector3(0, 1, 0) spread = 5.0 -gravity = Vector3(0, 400, 0) initial_velocity_min = 150.0 initial_velocity_max = 400.0 -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 +gravity = Vector3(0, 400, 0) scale_min = 0.4 scale_max = 0.7 scale_curve = SubResource("CurveTexture_mx2gv") @@ -370,36 +356,32 @@ hue_variation_min = -0.25 collision_mode = 2 [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_wbw05"] +particle_flag_disable_z = true emission_shape = 3 emission_box_extents = Vector3(1, 1, 1) -particle_flag_disable_z = true direction = Vector3(-1, -1, 0) spread = 5.0 -gravity = Vector3(0, 400, 0) initial_velocity_min = 400.0 initial_velocity_max = 400.0 -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 +gravity = Vector3(0, 400, 0) scale_min = 2.0 scale_max = 2.0 scale_curve = SubResource("CurveTexture_mx2gv") color = Color(0, 1, 0, 1) hue_variation_max = 0.3 +collision_mode = 2 sub_emitter_mode = 3 sub_emitter_amount_at_collision = 1 -collision_mode = 2 [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_oib53"] +particle_flag_disable_z = true emission_shape = 3 emission_box_extents = Vector3(40, 1, 1) -particle_flag_disable_z = true direction = Vector3(0, 1, 0) spread = 5.0 -gravity = Vector3(0, 400, 0) initial_velocity_min = 150.0 initial_velocity_max = 400.0 -orbit_velocity_min = 0.0 -orbit_velocity_max = 0.0 +gravity = Vector3(0, 400, 0) scale_min = 0.4 scale_max = 0.7 scale_curve = SubResource("CurveTexture_mx2gv") @@ -478,7 +460,6 @@ environment = SubResource("Environment_y7usk") [node name="Camera2D" type="Camera2D" parent="."] offset = Vector2(576, 324) -current = true [node name="Fire" type="GPUParticles2D" parent="." groups=["trailable_particles"]] texture_filter = 4 @@ -718,10 +699,10 @@ color = Color(1, 1, 0.537255, 0.270588) polygon = PackedVector2Array(770, 451, 777, 410, 828, 404, 853, 447, 853, 494, 805, 518, 763, 493) [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "move_particles" libraries = { "": SubResource("AnimationLibrary_j1xdo") } +autoplay = "move_particles" [node name="CanvasLayer" type="CanvasLayer" parent="."] diff --git a/2d/particles/pause.gd b/2d/particles/pause.gd index 3e1f9d4f..455798c8 100644 --- a/2d/particles/pause.gd +++ b/2d/particles/pause.gd @@ -1,7 +1,7 @@ extends Label -func _input(event): +func _input(event: InputEvent) -> void: if event.is_action_pressed("toggle_pause"): get_tree().paused = not get_tree().paused diff --git a/2d/particles/project.godot b/2d/particles/project.godot index 6a07ac71..e36b74ba 100644 --- a/2d/particles/project.godot +++ b/2d/particles/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://particles.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/2d/physics_platformer/coin/coin.gd b/2d/physics_platformer/coin/coin.gd index 6c83375f..eb6b861f 100644 --- a/2d/physics_platformer/coin/coin.gd +++ b/2d/physics_platformer/coin/coin.gd @@ -1,8 +1,8 @@ class_name Coin extends Area2D -var taken = false +var taken := false -func _on_body_enter(body): +func _on_body_enter(body: Node2D) -> void: if not taken and body is Player: ($AnimationPlayer as AnimationPlayer).play("taken") diff --git a/2d/physics_platformer/enemy/enemy.gd b/2d/physics_platformer/enemy/enemy.gd index 64fefb99..97bc3ad4 100644 --- a/2d/physics_platformer/enemy/enemy.gd +++ b/2d/physics_platformer/enemy/enemy.gd @@ -1,7 +1,6 @@ class_name Enemy extends RigidBody2D - const WALK_SPEED = 50 enum State { diff --git a/2d/physics_platformer/enemy/enemy.tscn b/2d/physics_platformer/enemy/enemy.tscn index 52f3542e..a7dcc1d4 100644 --- a/2d/physics_platformer/enemy/enemy.tscn +++ b/2d/physics_platformer/enemy/enemy.tscn @@ -48,7 +48,7 @@ tracks/0/loop_wrap = true tracks/0/keys = { "times": PackedFloat32Array(0), "transitions": PackedFloat32Array(1), -"update": 0, +"update": 1, "values": [4] } tracks/1/type = "value" diff --git a/2d/physics_platformer/player/bullet.gd b/2d/physics_platformer/player/bullet.gd index 07e286bd..aa954f2b 100644 --- a/2d/physics_platformer/player/bullet.gd +++ b/2d/physics_platformer/player/bullet.gd @@ -1,13 +1,13 @@ class_name Bullet extends RigidBody2D -var disabled = false +var disabled := false -func _ready(): +func _ready() -> void: ($Timer as Timer).start() -func disable(): +func disable() -> void: if disabled: return diff --git a/2d/physics_platformer/player/player.gd b/2d/physics_platformer/player/player.gd index de9f9cc1..b9ec5275 100644 --- a/2d/physics_platformer/player/player.gd +++ b/2d/physics_platformer/player/player.gd @@ -50,7 +50,7 @@ func _integrate_forces(state: PhysicsDirectBodyState2D) -> void: if spawn: _spawn_enemy_above.call_deferred() - # Deapply prev floor velocity. + # Deapply previous floor velocity. velocity.x -= floor_h_velocity floor_h_velocity = 0.0 @@ -59,7 +59,7 @@ func _integrate_forces(state: PhysicsDirectBodyState2D) -> void: var floor_index := -1 for contact_index in state.get_contact_count(): - var collision_normal = state.get_contact_local_normal(contact_index) + var collision_normal := state.get_contact_local_normal(contact_index) if collision_normal.dot(Vector2(0, -1)) > 0.6: found_floor = true diff --git a/2d/physics_platformer/project.godot b/2d/physics_platformer/project.godot index 6d8a56f0..5b78d3a4 100644 --- a/2d/physics_platformer/project.godot +++ b/2d/physics_platformer/project.godot @@ -20,6 +20,10 @@ run/main_scene="res://stage.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=800 diff --git a/2d/physics_tests/assets/tileset/tileset.tres b/2d/physics_tests/assets/tileset/tileset.tres index eb277a94..ebb44481 100644 --- a/2d/physics_tests/assets/tileset/tileset.tres +++ b/2d/physics_tests/assets/tileset/tileset.tres @@ -3,7 +3,7 @@ [ext_resource type="Texture2D" uid="uid://1nmxl2dgdqro" path="res://assets/tileset/tiles_demo.png" id="1"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_4jjf0"] -texture = ExtResource( "1" ) +texture = ExtResource("1") 0:0/next_alternative_id = 8 0:0/0 = 0 0:0/0/modulate = Color(0, 0, 1, 1) @@ -18,4 +18,4 @@ texture = ExtResource( "1" ) [resource] physics_layer_0/collision_layer = 1 -sources/0 = SubResource( "TileSetAtlasSource_4jjf0" ) +sources/0 = SubResource("TileSetAtlasSource_4jjf0") diff --git a/2d/physics_tests/main.tscn b/2d/physics_tests/main.tscn index 5093db34..b3afa6ee 100644 --- a/2d/physics_tests/main.tscn +++ b/2d/physics_tests/main.tscn @@ -51,6 +51,8 @@ offset_top = -19.0 offset_right = 50.0 offset_bottom = -5.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "FPS: 0" script = ExtResource("1") @@ -60,10 +62,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -39.0 -offset_right = 50.0 -offset_bottom = -25.0 +offset_top = -56.0 +offset_right = 128.0 +offset_bottom = -33.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "Physics engine:" script = ExtResource("3") @@ -73,10 +77,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -59.0 -offset_right = 50.0 -offset_bottom = -45.0 +offset_top = -84.0 +offset_right = 125.0 +offset_bottom = -61.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "Godot Version:" script = ExtResource("2") @@ -86,10 +92,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -79.0 +offset_top = -112.0 offset_right = 50.0 -offset_bottom = -65.0 +offset_bottom = -89.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "Test:" script = ExtResource("5") diff --git a/2d/physics_tests/project.godot b/2d/physics_tests/project.godot index b18f4af9..c9ed06e6 100644 --- a/2d/physics_tests/project.godot +++ b/2d/physics_tests/project.godot @@ -21,6 +21,10 @@ config/icon="res://icon.webp" Log="*res://utils/system_log.gd" System="*res://utils/system.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" @@ -51,7 +55,7 @@ toggle_full_screen={ } exit={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777217,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194305,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) ] } toggle_debug_collision={ @@ -71,20 +75,21 @@ toggle_pause={ } character_left={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":113,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null) ] } character_right={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null) ] } character_jump={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":122,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) ] } diff --git a/2d/physics_tests/test.gd b/2d/physics_tests/test.gd index fc484d98..545c396e 100644 --- a/2d/physics_tests/test.gd +++ b/2d/physics_tests/test.gd @@ -1,42 +1,40 @@ class_name Test extends Node2D - signal wait_done() -@export var _enable_debug_collision = true +@export var _enable_debug_collision := true -var _timer -var _timer_started = false +var _timer: Timer +var _timer_started := false -var _wait_physics_ticks_counter = 0 +var _wait_physics_ticks_counter := 0 class Circle2D: extends Node2D - var center - var radius - var color + var center := Vector2() + var radius := 0.0 + var color := Color() - func _draw(): + func _draw() -> void: draw_circle(center, radius, color) -var _drawn_nodes = [] +var _drawn_nodes := [] - -func _enter_tree(): +func _enter_tree() -> void: if not _enable_debug_collision: get_tree().debug_collisions_hint = false -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if _wait_physics_ticks_counter > 0: _wait_physics_ticks_counter -= 1 if _wait_physics_ticks_counter == 0: wait_done.emit() -func add_line(pos_start, pos_end, color): - var line = Line2D.new() +func add_line(pos_start: Vector2, pos_end: Vector2, color: Color) -> void: + var line := Line2D.new() line.points = [pos_start, pos_end] line.width = 1.5 line.default_color = color @@ -44,8 +42,8 @@ func add_line(pos_start, pos_end, color): add_child(line) -func add_circle(pos, radius, color): - var circle = Circle2D.new() +func add_circle(pos: Vector2, radius: float, color: Color) -> void: + var circle := Circle2D.new() circle.center = pos circle.radius = radius circle.color = color @@ -53,8 +51,8 @@ func add_circle(pos, radius, color): add_child(circle) -func add_shape(shape, shape_transform, color): - var collision = CollisionShape2D.new() +func add_shape(shape: Shape2D, shape_transform: Transform2D, color: Color) -> void: + var collision := CollisionShape2D.new() collision.shape = shape collision.transform = shape_transform collision.modulate = color @@ -62,36 +60,36 @@ func add_shape(shape, shape_transform, color): add_child(collision) -func clear_drawn_nodes(): - for node in _drawn_nodes: +func clear_drawn_nodes() -> void: + for node: Node in _drawn_nodes: node.queue_free() _drawn_nodes.clear() -func create_rigidbody(shape, pickable = false, shape_transform = Transform2D.IDENTITY): - var collision = CollisionShape2D.new() +func create_rigidbody(shape: Shape2D, pickable: bool = false, shape_transform: Transform2D = Transform2D.IDENTITY) -> RigidBody2D: + var collision := CollisionShape2D.new() collision.shape = shape collision.transform = shape_transform - var body = RigidBody2D.new() + var body := RigidBody2D.new() body.add_child(collision) if pickable: - var script = load("res://utils/rigidbody_pick.gd") + var script := load("res://utils/rigidbody_pick.gd") body.set_script(script) return body -func create_rigidbody_box(size, pickable = false, use_icon = false, shape_transform = Transform2D.IDENTITY): - var shape = RectangleShape2D.new() +func create_rigidbody_box(size: Vector2, pickable: bool = false, use_icon: bool = false, shape_transform: Transform2D = Transform2D.IDENTITY) -> RigidBody2D: + var shape := RectangleShape2D.new() shape.size = size - var body = create_rigidbody(shape, pickable, shape_transform) + var body := create_rigidbody(shape, pickable, shape_transform) if use_icon: - var texture = load("res://icon.webp") - var icon = Sprite2D.new() + var texture := load("res://icon.webp") + var icon := Sprite2D.new() icon.texture = texture icon.scale = size / texture.get_size() body.add_child(icon) @@ -99,14 +97,15 @@ func create_rigidbody_box(size, pickable = false, use_icon = false, shape_transf return body -func find_node(node_name): - var nodes = find_children(node_name) +func find_node(node_name: String) -> Node: + var nodes := find_children(node_name) if nodes.size() > 0: return nodes[0] + return null -func start_timer(timeout): +func start_timer(timeout: float) -> Timer: if _timer == null: _timer = Timer.new() _timer.one_shot = true @@ -121,21 +120,21 @@ func start_timer(timeout): return _timer -func cancel_timer(): +func cancel_timer() -> void: if _timer_started: _timer.paused = true _timer.timeout.emit() _timer.paused = false -func is_timer_canceled(): +func is_timer_canceled() -> bool: return _timer and _timer.paused -func wait_for_physics_ticks(tick_count): +func wait_for_physics_ticks(tick_count: int) -> Test: _wait_physics_ticks_counter = tick_count return self -func _on_timer_done(): +func _on_timer_done() -> void: _timer_started = false diff --git a/2d/physics_tests/tests.gd b/2d/physics_tests/tests.gd index eb36ecd1..b9d813d6 100644 --- a/2d/physics_tests/tests.gd +++ b/2d/physics_tests/tests.gd @@ -1,7 +1,6 @@ extends Node - -var _tests = [ +var _tests := [ { "id": "Functional Tests/Shapes", "path": "res://tests/functional/test_shapes.tscn", @@ -57,7 +56,7 @@ var _tests = [ ] -func _ready(): - var test_menu = $TestsMenu - for test in _tests: +func _ready() -> void: + var test_menu: OptionMenu = $TestsMenu + for test: Variant in _tests: test_menu.add_test(test.id, test.path) diff --git a/2d/physics_tests/tests/functional/test_character.gd b/2d/physics_tests/tests/functional/test_character.gd index 10bbac07..13aed428 100644 --- a/2d/physics_tests/tests/functional/test_character.gd +++ b/2d/physics_tests/tests/functional/test_character.gd @@ -1,8 +1,7 @@ -extends Test -class_name TestCharacter +class_name Test +extends TestCharacter - -enum E_BodyType { +enum BodyType { CHARACTER_BODY, CHARACTER_BODY_RAY, RIGID_BODY, @@ -19,31 +18,31 @@ const OPTION_MOVE_CHARACTER_STOP_ON_SLOPE = "Move Options/Use stop on slope (Cha const OPTION_MOVE_CHARACTER_FLOOR_ONLY = "Move Options/Move on floor only (Character only)" const OPTION_MOVE_CHARACTER_CONSTANT_SPEED = "Move Options/Use constant speed (Character only)" -@export var _initial_velocity = Vector2.ZERO -@export var _constant_velocity = Vector2.ZERO -@export var _motion_speed = 400.0 -@export var _gravity_force = 50.0 -@export var _jump_force = 1000.0 -@export var _snap_distance = 0.0 -@export var _floor_max_angle = 45.0 -@export var _body_type: E_BodyType = 0 +@export var _initial_velocity := Vector2.ZERO +@export var _constant_velocity := Vector2.ZERO +@export var _motion_speed := 400.0 +@export var _gravity_force := 50.0 +@export var _jump_force := 1000.0 +@export var _snap_distance := 0.0 +@export var _floor_max_angle := 45.0 +@export var _body_type := BodyType.CHARACTER_BODY -@onready var options = $Options +@onready var options: OptionMenu = $Options -var _use_snap = true -var _use_stop_on_slope = true -var _use_floor_only = true -var _use_constant_speed = false +var _use_snap := true +var _use_stop_on_slope := true +var _use_floor_only := true +var _use_constant_speed := false var _body_parent: Node = null -var _character_body_template = null -var _character_body_ray_template = null -var _rigid_body_template = null -var _rigid_body_ray_template = null +var _character_body_template: CharacterBody2D = null +var _character_body_ray_template: CharacterBody2D = null +var _rigid_body_template: RigidBody2D = null +var _rigid_body_ray_template: RigidBody2D = null var _moving_body: PhysicsBody2D = null -func _ready(): +func _ready() -> void: options.option_selected.connect(_on_option_selected) options.option_changed.connect(_on_option_changed) @@ -51,28 +50,28 @@ func _ready(): if _character_body_template: _body_parent = _character_body_template.get_parent() _body_parent.remove_child(_character_body_template) - var enabled = _body_type == E_BodyType.CHARACTER_BODY + var enabled := _body_type == BodyType.CHARACTER_BODY options.add_menu_item(OPTION_OBJECT_TYPE_CHARACTER, true, enabled, true) _character_body_ray_template = find_child("CharacterBodyRay2D") if _character_body_ray_template: _body_parent = _character_body_ray_template.get_parent() _body_parent.remove_child(_character_body_ray_template) - var enabled = _body_type == E_BodyType.CHARACTER_BODY_RAY + var enabled := _body_type == BodyType.CHARACTER_BODY_RAY options.add_menu_item(OPTION_OBJECT_TYPE_CHARACTER_RAY, true, enabled, true) _rigid_body_template = find_child("RigidBody2D") if _rigid_body_template: _body_parent = _rigid_body_template.get_parent() _body_parent.remove_child(_rigid_body_template) - var enabled = _body_type == E_BodyType.RIGID_BODY + var enabled := _body_type == BodyType.RIGID_BODY options.add_menu_item(OPTION_OBJECT_TYPE_RIGID_BODY, true, enabled, true) _rigid_body_ray_template = find_child("RigidBodyRay2D") if _rigid_body_ray_template: _body_parent = _rigid_body_ray_template.get_parent() _body_parent.remove_child(_rigid_body_ray_template) - var enabled = _body_type == E_BodyType.RIGID_BODY_RAY + var enabled := _body_type == BodyType.RIGID_BODY_RAY options.add_menu_item(OPTION_OBJECT_TYPE_RIGID_BODY_RAY, true, enabled, true) options.add_menu_item(OPTION_MOVE_CHARACTER_SNAP, true, _use_snap) @@ -80,15 +79,15 @@ func _ready(): options.add_menu_item(OPTION_MOVE_CHARACTER_FLOOR_ONLY, true, _use_floor_only) options.add_menu_item(OPTION_MOVE_CHARACTER_CONSTANT_SPEED, true, _use_constant_speed) - var floor_slider = find_child("FloorMaxAngle") + var floor_slider: Control = find_child("FloorMaxAngle") if floor_slider: floor_slider.get_node("HSlider").value = _floor_max_angle _start_test() -func _process(_delta): - var label_floor = $LabelFloor +func _process(_delta: float) -> void: + var label_floor: Label = $LabelFloor if _moving_body: if _moving_body.is_on_floor(): label_floor.text = "ON FLOOR" @@ -100,8 +99,8 @@ func _process(_delta): label_floor.visible = false -func _input(event): - var key_event = event as InputEventKey +func _input(event: InputEvent) -> void: + var key_event := event as InputEventKey if key_event and not key_event.pressed: if key_event.keycode == KEY_1: if _character_body_template: @@ -117,7 +116,7 @@ func _input(event): _on_option_selected(OPTION_OBJECT_TYPE_RIGID_BODY_RAY) -func _exit_tree(): +func _exit_tree() -> void: if _character_body_template: _character_body_template.free() if _character_body_ray_template: @@ -128,23 +127,23 @@ func _exit_tree(): _rigid_body_ray_template.free() -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_OBJECT_TYPE_CHARACTER: - _body_type = E_BodyType.CHARACTER_BODY + _body_type = BodyType.CHARACTER_BODY _start_test() OPTION_OBJECT_TYPE_CHARACTER_RAY: - _body_type = E_BodyType.CHARACTER_BODY_RAY + _body_type = BodyType.CHARACTER_BODY_RAY _start_test() OPTION_OBJECT_TYPE_RIGID_BODY: - _body_type = E_BodyType.RIGID_BODY + _body_type = BodyType.RIGID_BODY _start_test() OPTION_OBJECT_TYPE_RIGID_BODY_RAY: - _body_type = E_BodyType.RIGID_BODY_RAY + _body_type = BodyType.RIGID_BODY_RAY _start_test() -func _on_option_changed(option, checked): +func _on_option_changed(option: String, checked: bool) -> void: match option: OPTION_MOVE_CHARACTER_SNAP: _use_snap = checked @@ -164,8 +163,8 @@ func _on_option_changed(option, checked): _moving_body._constant_speed = _use_constant_speed -func _update_floor_max_angle(value): - if (value == _floor_max_angle): +func _update_floor_max_angle(value: float) -> void: + if value == _floor_max_angle: return _floor_max_angle = value @@ -173,7 +172,7 @@ func _update_floor_max_angle(value): _moving_body._floor_max_angle = _floor_max_angle -func _start_test(): +func _start_test() -> void: cancel_timer() if _moving_body: @@ -181,20 +180,19 @@ func _start_test(): _moving_body.queue_free() _moving_body = null - var test_label = "Testing: " + var test_label := "Testing: " - var template = null + var template: PhysicsBody2D = null match _body_type: - E_BodyType.CHARACTER_BODY: + BodyType.CHARACTER_BODY: template = _character_body_template - E_BodyType.CHARACTER_BODY_RAY: + BodyType.CHARACTER_BODY_RAY: template = _character_body_ray_template - E_BodyType.RIGID_BODY: + BodyType.RIGID_BODY: template = _rigid_body_template - E_BodyType.RIGID_BODY_RAY: + BodyType.RIGID_BODY_RAY: template = _rigid_body_ray_template - test_label += String(template.name) _moving_body = template.duplicate() _body_parent.add_child(_moving_body) diff --git a/2d/physics_tests/tests/functional/test_character_pixels.gd b/2d/physics_tests/tests/functional/test_character_pixels.gd index 04630544..630bdb54 100644 --- a/2d/physics_tests/tests/functional/test_character_pixels.gd +++ b/2d/physics_tests/tests/functional/test_character_pixels.gd @@ -1,29 +1,28 @@ extends TestCharacter - const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)" const OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP = "Test Cases/Floor detection (Character Body)" const OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES = "Test Cases/Floor detection with motion changes (Character Body)" const MOTION_CHANGES_DIR = Vector2(1.0, 1.0) -const MOTION_CHANGES_SPEEDS = [0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0] +const MOTION_CHANGES_SPEEDS: Array[float] = [0.5, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0] -var _test_floor_detection = false -var _test_motion_changes = false -var _floor_detected = false -var _floor_lost = false +var _test_floor_detection := false +var _test_motion_changes := false +var _floor_detected := false +var _floor_lost := false -var _failed_reason = "" +var _failed_reason := "" - -func _ready(): +func _ready() -> void: super._ready() options.add_menu_item(OPTION_TEST_CASE_ALL) options.add_menu_item(OPTION_TEST_CASE_DETECT_FLOOR_NO_SNAP) options.add_menu_item(OPTION_TEST_CASE_DETECT_FLOOR_MOTION_CHANGES) -func _physics_process(delta): + +func _physics_process(delta: float) -> void: super._physics_process(delta) if _moving_body: @@ -35,24 +34,23 @@ func _physics_process(delta): Log.print_log("Floor lost.") if _test_motion_changes: - var speed_count = MOTION_CHANGES_SPEEDS.size() - var speed_index = randi() % speed_count - var speed = MOTION_CHANGES_SPEEDS[speed_index] - var velocity = speed * MOTION_CHANGES_DIR + var speed_count := MOTION_CHANGES_SPEEDS.size() + var speed_index := randi() % speed_count + var speed := MOTION_CHANGES_SPEEDS[speed_index] + var velocity := speed * MOTION_CHANGES_DIR _moving_body._constant_velocity = velocity #Log.print_log("Velocity: %s" % velocity) -func _input(event): +func _input(event: InputEvent) -> void: super._input(event) - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - if key_event.keycode == KEY_0: + if event is InputEventKey and not event.pressed: + if event.keycode == KEY_0: await _on_option_selected(OPTION_TEST_CASE_ALL) -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_TEST_CASE_ALL: await _test_all() @@ -66,7 +64,7 @@ func _on_option_selected(option): super._on_option_selected(option) -func _start_test_case(option): +func _start_test_case(option: String) -> void: Log.print_log("* Starting " + option) match option: @@ -74,7 +72,7 @@ func _start_test_case(option): _test_floor_detection = true _test_motion_changes = false _use_snap = false - _body_type = E_BodyType.CHARACTER_BODY + _body_type = BodyType.CHARACTER_BODY _start_test() await start_timer(1.0).timeout @@ -86,7 +84,7 @@ func _start_test_case(option): _test_floor_detection = true _test_motion_changes = true _use_snap = false - _body_type = E_BodyType.CHARACTER_BODY + _body_type = BodyType.CHARACTER_BODY _start_test() await start_timer(4.0).timeout @@ -102,7 +100,7 @@ func _start_test_case(option): Log.print_error("Invalid test case.") -func _test_all(): +func _test_all() -> void: Log.print_log("* TESTING ALL...") # Test floor detection with no snapping. @@ -119,8 +117,8 @@ func _test_all(): Log.print_log("* Done.") -func _set_result(test_passed): - var result = "" +func _set_result(test_passed: bool) -> void: + var result := "" if test_passed: result = "PASSED" else: @@ -134,7 +132,7 @@ func _set_result(test_passed): Log.print_log("Test %s" % result) -func _start_test(): +func _start_test() -> void: super._start_test() _failed_reason = "" diff --git a/2d/physics_tests/tests/functional/test_character_tilemap.gd b/2d/physics_tests/tests/functional/test_character_tilemap.gd index a6fe3551..79a595ec 100644 --- a/2d/physics_tests/tests/functional/test_character_tilemap.gd +++ b/2d/physics_tests/tests/functional/test_character_tilemap.gd @@ -1,6 +1,5 @@ extends TestCharacter - const OPTION_TEST_CASE_ALL = "Test Cases/TEST ALL (0)" const OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID = "Test Cases/Jump through one-way tiles (Rigid Body)" const OPTION_TEST_CASE_JUMP_ONE_WAY_CHARACTER = "Test Cases/Jump through one-way tiles (Character Body)" @@ -8,16 +7,15 @@ const OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID = "Test Cases/Jump through one- const OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_CHARACTER = "Test Cases/Jump through one-way corner (Character Body)" const OPTION_TEST_CASE_FALL_ONE_WAY_CHARACTER = "Test Cases/Fall and pushed on one-way tiles (Character Body)" -var _test_jump_one_way = false -var _test_jump_one_way_corner = false -var _test_fall_one_way = false +var _test_jump_one_way := false +var _test_jump_one_way_corner := false +var _test_fall_one_way := false var _extra_body: PhysicsBody2D = null -var _failed_reason = "" +var _failed_reason := "" - -func _ready(): +func _ready() -> void: super._ready() options.add_menu_item(OPTION_TEST_CASE_ALL) @@ -28,16 +26,15 @@ func _ready(): options.add_menu_item(OPTION_TEST_CASE_FALL_ONE_WAY_CHARACTER) -func _input(event): +func _input(event: InputEvent) -> void: super._input(event) - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - if key_event.keycode == KEY_0: + if event is InputEventKey and not event.pressed: + if event.keycode == KEY_0: await _on_option_selected(OPTION_TEST_CASE_ALL) -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_TEST_CASE_ALL: await _test_all() @@ -60,34 +57,34 @@ func _on_option_selected(option): super._on_option_selected(option) -func _start_test_case(option): +func _start_test_case(option: String) -> void: Log.print_log("* Starting " + option) match option: OPTION_TEST_CASE_JUMP_ONE_WAY_RIGID: - _body_type = E_BodyType.RIGID_BODY + _body_type = BodyType.RIGID_BODY _test_jump_one_way_corner = false await _start_jump_one_way() OPTION_TEST_CASE_JUMP_ONE_WAY_CHARACTER: - _body_type = E_BodyType.CHARACTER_BODY + _body_type = BodyType.CHARACTER_BODY _test_jump_one_way_corner = false await _start_jump_one_way() OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_RIGID: - _body_type = E_BodyType.RIGID_BODY + _body_type = BodyType.RIGID_BODY _test_jump_one_way_corner = true await _start_jump_one_way() OPTION_TEST_CASE_JUMP_ONE_WAY_CORNER_CHARACTER: - _body_type = E_BodyType.CHARACTER_BODY + _body_type = BodyType.CHARACTER_BODY _test_jump_one_way_corner = true await _start_jump_one_way() OPTION_TEST_CASE_FALL_ONE_WAY_CHARACTER: - _body_type = E_BodyType.CHARACTER_BODY + _body_type = BodyType.CHARACTER_BODY await _start_fall_one_way() _: Log.print_error("Invalid test case.") -func _test_all(): +func _test_all() -> void: Log.print_log("* TESTING ALL...") # RigidBody tests. @@ -115,8 +112,8 @@ func _test_all(): Log.print_log("* Done.") -func _set_result(test_passed): - var result = "" +func _set_result(test_passed: bool) -> void: + var result := "" if test_passed: result = "PASSED" else: @@ -130,7 +127,7 @@ func _set_result(test_passed): Log.print_log("Test %s" % result) -func _start_test(): +func _start_test() -> void: if _extra_body: _body_parent.remove_child(_extra_body) _extra_body.queue_free() @@ -167,7 +164,7 @@ func _start_test(): $FallTargetArea2D/CollisionShape2D.disabled = false -func _start_jump_one_way(): +func _start_jump_one_way() -> void: _test_jump_one_way = true _start_test() @@ -178,7 +175,7 @@ func _start_jump_one_way(): _finalize_jump_one_way() -func _start_fall_one_way(): +func _start_fall_one_way() -> void: _test_fall_one_way = true _start_test() @@ -189,8 +186,8 @@ func _start_fall_one_way(): _finalize_fall_one_way() -func _finalize_jump_one_way(): - var passed = true +func _finalize_jump_one_way() -> void: + var passed := true if not $JumpTargetArea2D.overlaps_body(_moving_body): passed = false _failed_reason = ": the body wasn't able to jump all the way through." @@ -201,8 +198,8 @@ func _finalize_jump_one_way(): $JumpTargetArea2D/CollisionShape2D.disabled = true -func _finalize_fall_one_way(): - var passed = true +func _finalize_fall_one_way() -> void: + var passed := true if $FallTargetArea2D.overlaps_body(_moving_body): passed = false _failed_reason = ": the body was pushed through the one-way collision." diff --git a/2d/physics_tests/tests/functional/test_character_tilemap.tscn b/2d/physics_tests/tests/functional/test_character_tilemap.tscn index 63b07d1a..8fb98126 100644 --- a/2d/physics_tests/tests/functional/test_character_tilemap.tscn +++ b/2d/physics_tests/tests/functional/test_character_tilemap.tscn @@ -23,7 +23,7 @@ friction = 0.0 radius = 16.0 [node name="Test" type="Node2D"] -script = ExtResource( "1" ) +script = ExtResource("1") [node name="LabelTestType" type="Label" parent="."] offset_left = 14.0 @@ -31,11 +31,8 @@ offset_top = 79.0 offset_right = 145.0 offset_bottom = 93.0 text = "Testing: " -__meta__ = { -"_edit_use_anchors_": false -} -[node name="Options" parent="." instance=ExtResource( "3" )] +[node name="Options" parent="." instance=ExtResource("3")] [node name="LabelFloor" type="Label" parent="."] offset_left = 14.0 @@ -43,9 +40,6 @@ offset_top = 237.929 offset_right = 145.0 offset_bottom = 251.929 text = "ON FLOOR" -__meta__ = { -"_edit_use_anchors_": false -} [node name="LabelControls" type="Label" parent="."] offset_left = 14.0 @@ -54,82 +48,77 @@ offset_right = 145.0 offset_bottom = 277.291 text = "LEFT/RIGHT - MOVE UP - JUMP" -__meta__ = { -"_edit_use_anchors_": false -} [node name="CharacterBody2D" type="CharacterBody2D" parent="."] position = Vector2(250, 460) collision_mask = 2147483649 -script = ExtResource( "7" ) +script = ExtResource("7") [node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBody2D"] -shape = SubResource( "2" ) +shape = SubResource("2") [node name="CharacterBodyRay2D" type="CharacterBody2D" parent="."] position = Vector2(250, 460) collision_mask = 2147483649 -script = ExtResource( "7" ) +script = ExtResource("7") [node name="CollisionShape2D" type="CollisionShape2D" parent="CharacterBodyRay2D"] position = Vector2(0, -8) -shape = SubResource( "RectangleShape2D_jx2e1" ) +shape = SubResource("RectangleShape2D_jx2e1") [node name="CollisionShapeRay2D" type="CollisionShape2D" parent="CharacterBodyRay2D"] position = Vector2(0, 8) -shape = SubResource( "RayShape2D_206f5" ) +shape = SubResource("RayShape2D_206f5") [node name="CollisionShapeRay2DLeft" type="CollisionShape2D" parent="CharacterBodyRay2D"] position = Vector2(-12, 8) -shape = SubResource( "RayShape2D_206f5" ) +shape = SubResource("RayShape2D_206f5") [node name="CollisionShapeRay2DRight" type="CollisionShape2D" parent="CharacterBodyRay2D"] position = Vector2(12, 8) -shape = SubResource( "RayShape2D_206f5" ) +shape = SubResource("RayShape2D_206f5") -[node name="RigidDynamicBody2D" type="RigidDynamicBody2D" parent="."] +[node name="RigidDynamicBody2D" type="RigidBody2D" parent="."] position = Vector2(250, 460) collision_mask = 2147483649 -physics_material_override = SubResource( "1" ) -contacts_reported = 4 -contact_monitor = true +physics_material_override = SubResource("1") lock_rotation = true -script = ExtResource( "6" ) +contact_monitor = true +script = ExtResource("6") [node name="CollisionShape2D" type="CollisionShape2D" parent="RigidDynamicBody2D"] -shape = SubResource( "2" ) +shape = SubResource("2") -[node name="RigidBodyRay2D" type="RigidDynamicBody2D" parent="."] +[node name="RigidBodyRay2D" type="RigidBody2D" parent="."] position = Vector2(250, 460) collision_mask = 2147483649 -physics_material_override = SubResource( "1" ) -contacts_reported = 4 -contact_monitor = true +physics_material_override = SubResource("1") lock_rotation = true -script = ExtResource( "6" ) +contact_monitor = true +script = ExtResource("6") [node name="CollisionShape2D" type="CollisionShape2D" parent="RigidBodyRay2D"] position = Vector2(0, -8) -shape = SubResource( "RectangleShape2D_jx2e1" ) +shape = SubResource("RectangleShape2D_jx2e1") [node name="CollisionShapeRay2D" type="CollisionShape2D" parent="RigidBodyRay2D"] position = Vector2(0, 8) -shape = SubResource( "RayShape2D_206f5" ) +shape = SubResource("RayShape2D_206f5") [node name="CollisionShapeRay2DLeft" type="CollisionShape2D" parent="RigidBodyRay2D"] position = Vector2(-12, 8) -shape = SubResource( "RayShape2D_206f5" ) +shape = SubResource("RayShape2D_206f5") [node name="CollisionShapeRay2DRight" type="CollisionShape2D" parent="RigidBodyRay2D"] position = Vector2(12, 8) -shape = SubResource( "RayShape2D_206f5" ) +shape = SubResource("RayShape2D_206f5") [node name="JumpTargetArea2D" type="Area2D" parent="."] visible = false position = Vector2(810, 390) [node name="CollisionShape2D" type="CollisionShape2D" parent="JumpTargetArea2D"] -shape = SubResource( "5" ) +shape = SubResource("5") disabled = true [node name="FallTargetArea2D" type="Area2D" parent="."] @@ -137,15 +126,16 @@ visible = false position = Vector2(250, 480) [node name="CollisionShape2D" type="CollisionShape2D" parent="FallTargetArea2D"] -shape = SubResource( "5" ) +shape = SubResource("5") disabled = true -[node name="StaticSceneFlat" parent="." instance=ExtResource( "4" )] +[node name="StaticSceneFlat" parent="." instance=ExtResource("4")] position = Vector2(0, 12) [node name="TileMap" type="TileMap" parent="."] +texture_filter = 1 scale = Vector2(2, 2) -tile_set = ExtResource( "5" ) +tile_set = ExtResource("5") collision_visibility_mode = 1 format = 2 layer_0/tile_data = PackedInt32Array(786438, 65536, 0, 786439, 65536, 0, 786440, 65536, 0, 786441, 65536, 0, 458764, 65536, 0, 524300, 65536, 0, 589836, 65536, 0, 655372, 65536, 0, 720908, 65536, 0, 786444, 65536, 0, 851980, 65536, 0, 917516, 65536, 0, 983052, 65536, 0, 458765, 65536, 0, 524301, 65536, 0, 589837, 65536, 0, 655373, 65536, 0, 720909, 65536, 0, 786445, 65536, 0, 851981, 65536, 0, 917517, 65536, 0, 983053, 65536, 0, 458766, 65536, 0, 524302, 65536, 0, 589838, 65536, 0, 655374, 65536, 0, 720910, 65536, 0, 786446, 65536, 0, 851982, 65536, 0, 917518, 65536, 0, 983054, 65536, 0, 458767, 65536, 0, 524303, 65536, 0, 589839, 65536, 0, 655375, 65536, 0, 720911, 65536, 0, 786447, 65536, 0, 851983, 65536, 0, 917519, 65536, 0, 983055, 65536, 0, 458768, 65536, 0, 524304, 65536, 0, 589840, 65536, 0, 655376, 65536, 0, 720912, 65536, 0, 786448, 65536, 0, 851984, 65536, 0, 917520, 65536, 0, 983056, 65536, 0, 458769, 65536, 0, 524305, 65536, 0, 589841, 65536, 0, 655377, 65536, 0, 720913, 65536, 0, 786449, 65536, 0, 851985, 65536, 0, 917521, 65536, 0, 983057, 65536, 0, 458770, 65536, 0, 524306, 65536, 0, 589842, 65536, 0, 655378, 65536, 0, 720914, 65536, 0, 786450, 65536, 0, 851986, 65536, 0, 917522, 65536, 0, 983058, 65536, 0, 458771, 65536, 0, 524307, 65536, 0, 589843, 65536, 0, 655379, 65536, 0, 720915, 65536, 0, 786451, 65536, 0, 851987, 65536, 0, 917523, 65536, 0, 983059, 65536, 0, 851992, 0, 0, 851993, 0, 0, 720922, 0, 0, 851994, 0, 0, 720923, 0, 0, 851995, 0, 0, 720924, 0, 0, 720925, 0, 0) diff --git a/2d/physics_tests/tests/functional/test_collision_pairs.gd b/2d/physics_tests/tests/functional/test_collision_pairs.gd index 3e4cb071..94a648cb 100644 --- a/2d/physics_tests/tests/functional/test_collision_pairs.gd +++ b/2d/physics_tests/tests/functional/test_collision_pairs.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_TYPE_RECTANGLE = "Collision type/Rectangle (1)" const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)" const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)" @@ -16,17 +15,16 @@ const OPTION_SHAPE_CONCAVE_SEGMENTS = "Shape type/Concave Segments" const OFFSET_RANGE = 120.0 -@export var offset = Vector2.ZERO +@export var offset := Vector2.ZERO -@onready var options = $Options +@onready var options: OptionMenu = $Options -var _update_collision = false -var _collision_test_index = 0 -var _current_offset = Vector2.ZERO -var _collision_shapes = [] +var _update_collision := false +var _collision_test_index := 0 +var _collision_shapes: Array[Shape2D] = [] -func _ready(): +func _ready() -> void: _initialize_collision_shapes() options.add_menu_item(OPTION_TYPE_RECTANGLE) @@ -52,8 +50,8 @@ func _ready(): _update_collision = true -func _input(event): - var key_event = event as InputEventKey +func _input(event: InputEvent) -> void: + var key_event := event as InputEventKey if key_event and not key_event.pressed: if key_event.keycode == KEY_1: _on_option_selected(OPTION_TYPE_RECTANGLE) @@ -67,7 +65,7 @@ func _input(event): _on_option_selected(OPTION_TYPE_CONCAVE_SEGMENTS) -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if not _update_collision: @@ -78,66 +76,64 @@ func _physics_process(delta): _do_collision_test() -func set_h_offset(value): +func set_h_offset(value: float) -> void: offset.x = value * OFFSET_RANGE _update_collision = true -func set_v_offset(value): +func set_v_offset(value: float) -> void: offset.y = -value * OFFSET_RANGE _update_collision = true -func _initialize_collision_shapes(): +func _initialize_collision_shapes() -> void: _collision_shapes.clear() - for node in $Shapes.get_children(): - var body = node as PhysicsBody2D - var shape = body.shape_owner_get_shape(0, 0) + for node: PhysicsBody2D in $Shapes.get_children(): + var body: PhysicsBody2D = node + var shape := body.shape_owner_get_shape(0, 0) shape.resource_name = String(node.name).substr("RigidBody".length()) _collision_shapes.push_back(shape) -func _do_collision_test(): +func _do_collision_test() -> void: clear_drawn_nodes() - var shape = _collision_shapes[_collision_test_index] + var shape := _collision_shapes[_collision_test_index] Log.print_log("* Start %s collision tests..." % shape.resource_name) - var shape_query = PhysicsShapeQueryParameters2D.new() + var shape_query := PhysicsShapeQueryParameters2D.new() shape_query.set_shape(shape) - var shape_scale = Vector2(0.5, 0.5) + var shape_scale := Vector2(0.5, 0.5) shape_query.transform = Transform2D.IDENTITY.scaled(shape_scale) - for node in $Shapes.get_children(): + for node: PhysicsBody2D in $Shapes.get_children(): if not node.visible: continue - var body = node as PhysicsBody2D - var space_state = body.get_world_2d().direct_space_state + var body: PhysicsBody2D = node + var space_state := body.get_world_2d().direct_space_state Log.print_log("* Testing: %s" % String(body.name)) - var center = body.position + var center := body.position # Collision at the center inside. - var res = _add_collision(space_state, center, shape, shape_query) + var res := _add_collision(space_state, center, shape, shape_query) Log.print_log("Collision center inside: %s" % ("NO HIT" if res.is_empty() else "HIT")) Log.print_log("* Done.") -func _add_collision(space_state, pos, shape, shape_query): +func _add_collision(space_state: PhysicsDirectSpaceState2D, pos: Vector2, shape: Shape2D, shape_query: PhysicsShapeQueryParameters2D) -> Array[Vector2]: shape_query.transform.origin = pos + offset - var results = space_state.collide_shape(shape_query) + var results: Array[Vector2] = space_state.collide_shape(shape_query) - var color + var color := Color.GREEN if results.is_empty(): color = Color.WHITE.darkened(0.5) - else: - color = Color.GREEN # Draw collision query shape. add_shape(shape, shape_query.transform, color) @@ -149,7 +145,7 @@ func _add_collision(space_state, pos, shape, shape_query): return results -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_TYPE_RECTANGLE: _collision_test_index = _find_type_index("Rectangle") @@ -168,9 +164,9 @@ func _on_option_selected(option): _update_collision = true -func _find_type_index(type_name): +func _find_type_index(type_name: String) -> int: for type_index in range(_collision_shapes.size()): - var type_shape = _collision_shapes[type_index] + var type_shape := _collision_shapes[type_index] if type_shape.resource_name.find(type_name) > -1: return type_index @@ -178,8 +174,8 @@ func _find_type_index(type_name): return -1 -func _on_option_changed(option, checked): - var node +func _on_option_changed(option: String, checked: bool) -> void: + var node: Node2D match option: OPTION_SHAPE_RECTANGLE: @@ -201,8 +197,8 @@ func _on_option_changed(option, checked): _update_collision = true -func _find_shape_node(type_name): - var node = $Shapes.find_child("RigidBody%s" % type_name) +func _find_shape_node(type_name: String) -> Node2D: + var node: Node2D = $Shapes.find_child("RigidBody%s" % type_name) if not node: Log.print_error("Invalid shape type: " + type_name) diff --git a/2d/physics_tests/tests/functional/test_joints.gd b/2d/physics_tests/tests/functional/test_joints.gd index 1545c01d..d73f4a4a 100644 --- a/2d/physics_tests/tests/functional/test_joints.gd +++ b/2d/physics_tests/tests/functional/test_joints.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_JOINT_TYPE = "Joint Type/%s Joint (%d)" const OPTION_TEST_CASE_BODIES_COLLIDE = "Test case/Attached bodies collide" @@ -11,29 +10,27 @@ const OPTION_TEST_CASE_CHANGE_POSITIONS = "Test case/Set body positions after ad const BOX_SIZE = Vector2(64, 64) -var _update_joint = false -var _selected_joint = null +var _update_joint := false +var _selected_joint: Joint2D = null -var _joint_type = PinJoint2D -var _bodies_collide = false -var _world_attachement = false -var _dynamic_attachement = false -var _destroy_body = false -var _change_positions = false +var _bodies_collide := false +var _world_attachement := false +var _dynamic_attachement := false +var _destroy_body := false +var _change_positions := false -var _joint_types = {} +var _joint_types := {} +func _ready() -> void: + var options: OptionMenu = $Options -func _ready(): - var options = $Options - - var joints = $Joints - for joint_index in range(joints.get_child_count()): - var joint_node = joints.get_child(joint_index) + var joints: Node2D = $Joints + for joint_index in joints.get_child_count(): + var joint_node := joints.get_child(joint_index) joint_node.visible = false - var joint_name = String(joint_node.name) - var joint_short = joint_name.substr(0, joint_name.length() - 7) - var option_name = OPTION_JOINT_TYPE % [joint_short, joint_index + 1] + var joint_name := String(joint_node.name) + var joint_short := joint_name.substr(0, joint_name.length() - 7) + var option_name := OPTION_JOINT_TYPE % [joint_short, joint_index + 1] options.add_menu_item(option_name) _joint_types[option_name] = joint_node @@ -50,29 +47,28 @@ func _ready(): _update_joint = true -func _process(_delta): +func _process(_delta: float) -> void: if _update_joint: _update_joint = false await _create_joint() $LabelJointType.text = "Joint Type: " + String(_selected_joint.name) -func _input(event): - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - var joint_index = key_event.keycode - KEY_1 +func _input(event: InputEvent) -> void: + if event is InputEventKey and not event.pressed: + var joint_index: int = event.keycode - KEY_1 if joint_index >= 0 and joint_index < _joint_types.size(): _selected_joint = _joint_types.values()[joint_index] _update_joint = true -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: if _joint_types.has(option): _selected_joint = _joint_types[option] _update_joint = true -func _on_option_changed(option, checked): +func _on_option_changed(option: String, checked: bool) -> void: match option: OPTION_TEST_CASE_BODIES_COLLIDE: _bodies_collide = checked @@ -91,18 +87,18 @@ func _on_option_changed(option, checked): _update_joint = true -func _create_joint(): +func _create_joint() -> void: cancel_timer() - var root = $Objects + var root: Node2D = $Objects while root.get_child_count(): - var last_child_index = root.get_child_count() - 1 - var last_child = root.get_child(last_child_index) + var last_child_index := root.get_child_count() - 1 + var last_child := root.get_child(last_child_index) root.remove_child(last_child) last_child.queue_free() - var child_body = create_rigidbody_box(BOX_SIZE, true, true) + var child_body := create_rigidbody_box(BOX_SIZE, true, true) if _change_positions: root.add_child(child_body) child_body.position = Vector2(0.0, 40) @@ -110,7 +106,7 @@ func _create_joint(): child_body.position = Vector2(0.0, 40) root.add_child(child_body) - var parent_body = null + var parent_body: PhysicsBody2D = null if not _world_attachement: parent_body = create_rigidbody_box(BOX_SIZE, true, true) if _dynamic_attachement: @@ -125,7 +121,7 @@ func _create_joint(): parent_body.position = Vector2(0.0, -40) root.add_child(parent_body) - var joint = _selected_joint.duplicate() + var joint := _selected_joint.duplicate() joint.visible = true joint.disable_collision = not _bodies_collide root.add_child(joint) diff --git a/2d/physics_tests/tests/functional/test_joints.tscn b/2d/physics_tests/tests/functional/test_joints.tscn index b80d4d45..08966875 100644 --- a/2d/physics_tests/tests/functional/test_joints.tscn +++ b/2d/physics_tests/tests/functional/test_joints.tscn @@ -4,7 +4,7 @@ [ext_resource type="PackedScene" uid="uid://blh3twy74kbkv" path="res://tests/test_options.tscn" id="4"] [node name="JointTest2D" type="Node2D"] -script = ExtResource( "2" ) +script = ExtResource("2") [node name="LabelJointType" type="Label" parent="."] offset_left = 14.0 @@ -12,11 +12,8 @@ offset_top = 79.0 offset_right = 145.0 offset_bottom = 93.0 text = "Joint Type: " -__meta__ = { -"_edit_use_anchors_": false -} -[node name="Options" parent="." instance=ExtResource( "4" )] +[node name="Options" parent="." instance=ExtResource("4")] [node name="Joints" type="Node2D" parent="."] position = Vector2(512, 200) diff --git a/2d/physics_tests/tests/functional/test_one_way_collision.gd b/2d/physics_tests/tests/functional/test_one_way_collision.gd index 5bc495cf..09de201d 100644 --- a/2d/physics_tests/tests/functional/test_one_way_collision.gd +++ b/2d/physics_tests/tests/functional/test_one_way_collision.gd @@ -1,7 +1,6 @@ @tool extends Test - signal all_tests_done() signal test_done() @@ -19,56 +18,56 @@ const OPTION_TEST_CASE_MOVING_PLATFORM_CHARACTER = "Test Cases/Moving Platform ( const TEST_ALL_ANGLES_STEP = 15.0 const TEST_ALL_ANGLES_MAX = 344.0 -@export_range(64, 256, 0.1) var _platform_size = 128.0: +@export_range(64, 256, 0.1) var _platform_size := 128.0: set(value): if value == _platform_size: return _platform_size = value _update_platform_size(value) -@export_range(0, 360, 0.1) var _platform_angle = 0.0: +@export_range(0, 360, 0.1) var _platform_angle := 0.0: set(value): if value == _platform_angle: return _platform_angle = value _update_platform_angle(value) -@export var _platform_speed = 0.0 +@export var _platform_speed := 0.0 -@export_range(0, 360, 0.1) var _body_angle = 0.0: +@export_range(0, 360, 0.1) var _body_angle := 0.0: set(value): if value == _body_angle: return _body_angle = value _update_rigidbody_angle(value) -@export var _body_velocity = Vector2(400.0, 0.0) -@export var _use_character_body = false +@export var _body_velocity := Vector2(400.0, 0.0) +@export var _use_character_body := false -@onready var options = $Options +@onready var options: OptionMenu = $Options -var _rigid_body_template = null -var _character_body_template = null +var _rigid_body_template: RigidBody2D = null +var _character_body_template: CharacterBody2D = null var _moving_body: PhysicsBody2D = null -var _platform_template = null +var _platform_template: StaticBody2D = null var _platform_body: PhysicsBody2D = null -var _platform_velocity = Vector2.ZERO +var _platform_velocity := Vector2.ZERO -@onready var _target_area = $TargetArea2D +@onready var _target_area: Area2D = $TargetArea2D -var _contact_detected = false -var _target_entered = false -var _test_passed = false -var _test_step = 0 +var _contact_detected := false +var _target_entered := false +var _test_passed := false +var _test_step := 0 -var _test_all_angles = false -var _lock_controls = false +var _test_all_angles := false +var _lock_controls := false -var _test_canceled = false +var _test_canceled := false -func _ready(): +func _ready() -> void: if not Engine.is_editor_hint(): options.add_menu_item(OPTION_OBJECT_TYPE_RIGIDBODY, true, not _use_character_body, true) options.add_menu_item(OPTION_OBJECT_TYPE_CHARACTER, true, _use_character_body, true) @@ -103,47 +102,46 @@ func _ready(): _start_test() -func _process(_delta): +func _process(_delta: float) -> void: if not Engine.is_editor_hint(): if Input.is_action_just_pressed(&"ui_accept"): await _reset_test(false) -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if not Engine.is_editor_hint(): if _moving_body and not _contact_detected: if _use_character_body: - var collision = _moving_body.move_and_collide(_body_velocity * delta, false) + var collision := _moving_body.move_and_collide(_body_velocity * delta, false) if collision: - var colliding_body = collision.get_collider() + var colliding_body := collision.get_collider() await _on_contact_detected(colliding_body) if _platform_body and _platform_velocity != Vector2.ZERO: - var motion = _platform_velocity * delta + var motion := _platform_velocity * delta _platform_body.global_position += motion -func _input(event): - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - if key_event.keycode == KEY_0: +func _input(event: InputEvent) -> void: + if event is InputEventKey and not event.pressed: + if event.keycode == KEY_0: await _on_option_selected(OPTION_TEST_CASE_ALL) - if key_event.keycode == KEY_1: + if event.keycode == KEY_1: await _on_option_selected(OPTION_OBJECT_TYPE_RIGIDBODY) - elif key_event.keycode == KEY_2: + elif event.keycode == KEY_2: await _on_option_selected(OPTION_OBJECT_TYPE_CHARACTER) -func _exit_tree(): +func _exit_tree() -> void: if not Engine.is_editor_hint(): _rigid_body_template.free() _character_body_template.free() _platform_template.free() -func _update_platform_size(value, reset = true): +func _update_platform_size(value: float, reset: bool = true) -> void: if _lock_controls: return if value == _platform_size: @@ -153,11 +151,11 @@ func _update_platform_size(value, reset = true): if Engine.is_editor_hint(): $OneWayStaticBody2D/CollisionShape2D.shape.size.x = value else: - var platform_collision = _platform_template.get_child(0) + var platform_collision := _platform_template.get_child(0) platform_collision.shape.size.x = value if _platform_body: # Bug: need to re-add when changing shape. - var child_index = _platform_body.get_index() + var child_index := _platform_body.get_index() remove_child(_platform_body) add_child(_platform_body) move_child(_platform_body, child_index) @@ -165,7 +163,7 @@ func _update_platform_size(value, reset = true): await _reset_test() -func _update_platform_angle(value, reset = true): +func _update_platform_angle(value: float, reset: bool = true) -> void: if _lock_controls: return if value == _platform_angle: @@ -182,7 +180,7 @@ func _update_platform_angle(value, reset = true): await _reset_test() -func _update_rigidbody_angle(value, reset = true): +func _update_rigidbody_angle(value: float, reset: bool = true) -> void: if _lock_controls: return if value == _body_angle: @@ -201,7 +199,7 @@ func _update_rigidbody_angle(value, reset = true): await _reset_test() -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_OBJECT_TYPE_CHARACTER: _use_character_body = true @@ -231,7 +229,7 @@ func _on_option_selected(option): await _test_moving_platform() -func _start_test_case(option): +func _start_test_case(option: String) -> void: Log.print_log("* Starting " + option) await _on_option_selected(option) @@ -239,13 +237,13 @@ func _start_test_case(option): await all_tests_done -func _wait_for_test(): +func _wait_for_test() -> void: await _reset_test() await test_done -func _test_all_rigid_body(): +func _test_all_rigid_body() -> void: Log.print_log("* All RigidBody test cases...") await _update_platform_size(128.0, false) @@ -271,7 +269,7 @@ func _test_all_rigid_body(): return -func _test_all_character_body(): +func _test_all_character_body() -> void: Log.print_log("* All CharacterBody test cases...") await _update_platform_size(128.0, false) @@ -297,7 +295,7 @@ func _test_all_character_body(): return -func _test_moving_platform(): +func _test_moving_platform() -> void: Log.print_log("* Start moving platform tests") Log.print_log("* Platform moving away from body...") @@ -334,7 +332,7 @@ func _test_moving_platform(): all_tests_done.emit() -func _test_all(): +func _test_all() -> void: Log.print_log("* TESTING ALL...") await _test_all_rigid_body() @@ -348,10 +346,10 @@ func _test_all(): Log.print_log("* Done.") -func _start_test(): - var test_label = "Testing: " +func _start_test() -> void: + var test_label := "Testing: " - var platform_angle = _platform_template.rotation + var platform_angle := _platform_template.rotation if _platform_body: platform_angle = _platform_body.rotation _platform_body.remove_child(_target_area) @@ -377,9 +375,9 @@ func _start_test(): add_child(_moving_body) if _platform_speed != 0.0: - var platform_pos = _platform_body.global_position - var body_pos = _moving_body.global_position - var dir = (platform_pos - body_pos).normalized() + var platform_pos := _platform_body.global_position + var body_pos := _moving_body.global_position + var dir := (platform_pos - body_pos).normalized() _platform_velocity = dir * _platform_speed else: _platform_velocity = Vector2.ZERO @@ -400,7 +398,7 @@ func _start_test(): $LabelResult.self_modulate = Color.WHITE -func _reset_test(cancel_test = true): +func _reset_test(cancel_test: bool = true) -> void: _test_canceled = true await _on_timeout() _test_canceled = false @@ -422,14 +420,14 @@ func _reset_test(cancel_test = true): _next_test(true) -func _next_test(force_start = false): +func _next_test(force_start: bool = false) -> void: if _moving_body: remove_child(_moving_body) _moving_body.queue_free() _moving_body = null if _test_all_angles: - var angle = rad_to_deg(_platform_body.rotation) + var angle := rad_to_deg(_platform_body.rotation) if angle >= _platform_angle + TEST_ALL_ANGLES_MAX: _platform_body.rotation = deg_to_rad(_platform_angle) _lock_controls = true @@ -448,7 +446,7 @@ func _next_test(force_start = false): _start_test() -func _on_contact_detected(_body): +func _on_contact_detected(_body: PhysicsBody2D) -> void: if _contact_detected or _target_entered: return @@ -458,7 +456,7 @@ func _on_contact_detected(_body): await _on_timeout() -func _on_target_entered(_body): +func _on_target_entered(_body: PhysicsBody2D) -> void: if _body != _moving_body: return @@ -471,14 +469,14 @@ func _on_target_entered(_body): await _on_timeout() -func _should_collide(): - var platform_rotation = round(rad_to_deg(_platform_body.rotation)) +func _should_collide() -> bool: + var platform_rotation := roundf(rad_to_deg(_platform_body.rotation)) - var angle = fposmod(platform_rotation, 360) + var angle := fposmod(platform_rotation, 360) return angle > 180 -func _on_timeout(): +func _on_timeout() -> void: cancel_timer() if $Timer.is_stopped(): @@ -501,7 +499,7 @@ func _on_timeout(): all_tests_done.emit() return - var was_all_angles = _test_all_angles + var was_all_angles := _test_all_angles _next_test() @@ -511,8 +509,8 @@ func _on_timeout(): all_tests_done.emit() -func _set_result(): - var result = "" +func _set_result() -> void: + var result := "" if _test_passed: result = "PASSED" $LabelResult.self_modulate = Color.GREEN @@ -522,7 +520,7 @@ func _set_result(): $LabelResult.text = result - var platform_angle = rad_to_deg(_platform_body.rotation) + var platform_angle := rad_to_deg(_platform_body.rotation) result += ": size=%.1f, angle=%.1f, body angle=%.1f" % [_platform_size, platform_angle, _body_angle] Log.print_log("Test %s" % result) diff --git a/2d/physics_tests/tests/functional/test_pyramid.gd b/2d/physics_tests/tests/functional/test_pyramid.gd index 6a661fd8..9273dcd5 100644 --- a/2d/physics_tests/tests/functional/test_pyramid.gd +++ b/2d/physics_tests/tests/functional/test_pyramid.gd @@ -1,35 +1,33 @@ extends Test +@export_range(1, 100) var height := 10 +@export var box_size := Vector2(40.0, 40.0) +@export var box_spacing := Vector2(0.0, 0.0) -@export_range(1, 100) var height = 10 -@export var box_size = Vector2(40.0, 40.0) -@export var box_spacing = Vector2(0.0, 0.0) - - -func _ready(): +func _ready() -> void: _create_pyramid() -func _create_pyramid(): - var root_node = $Pyramid +func _create_pyramid() -> void: + var root_node: Node2D = $Pyramid - var template_body = create_rigidbody_box(box_size, true) + var template_body := create_rigidbody_box(box_size, true) - var pos_y = -0.5 * box_size.y - box_spacing.y + var pos_y := -0.5 * box_size.y - box_spacing.y for level in height: - var level_index = height - level - 1 - var num_boxes = 2 * level_index + 1 + var level_index := height - level - 1 + var num_boxes := 2 * level_index + 1 - var row_node = Node2D.new() + var row_node := Node2D.new() row_node.position = Vector2(0.0, pos_y) row_node.name = "Row%02d" % (level + 1) root_node.add_child(row_node) - var pos_x = -0.5 * (num_boxes - 1) * (box_size.x + box_spacing.x) + var pos_x := -0.5 * (num_boxes - 1) * (box_size.x + box_spacing.x) - for box_index in range(num_boxes): - var box = template_body.duplicate() + for box_index in num_boxes: + var box := template_body.duplicate() box.position = Vector2(pos_x, 0.0) box.name = "Box%02d" % (box_index + 1) row_node.add_child(box) diff --git a/2d/physics_tests/tests/functional/test_pyramid.tscn b/2d/physics_tests/tests/functional/test_pyramid.tscn index 070d17dc..04a029da 100644 --- a/2d/physics_tests/tests/functional/test_pyramid.tscn +++ b/2d/physics_tests/tests/functional/test_pyramid.tscn @@ -4,9 +4,9 @@ [ext_resource type="PackedScene" uid="uid://cx2q80okt25o1" path="res://tests/static_scene_flat.tscn" id="2"] [node name="Test" type="Node2D"] -script = ExtResource( "1" ) +script = ExtResource("1") [node name="Pyramid" type="Node2D" parent="."] position = Vector2(512, 500) -[node name="StaticSceneFlat" parent="." instance=ExtResource( "2" )] +[node name="StaticSceneFlat" parent="." instance=ExtResource("2")] diff --git a/2d/physics_tests/tests/functional/test_raycasting.gd b/2d/physics_tests/tests/functional/test_raycasting.gd index 7db62b9e..b1bc2f03 100644 --- a/2d/physics_tests/tests/functional/test_raycasting.gd +++ b/2d/physics_tests/tests/functional/test_raycasting.gd @@ -1,14 +1,12 @@ extends Test - const OPTION_TEST_CASE_HIT_FROM_INSIDE = "Test case/Hit from inside" -var _hit_from_inside = false -var _do_raycasts = false +var _hit_from_inside := false +var _do_raycasts := false - -func _ready(): - var options = $Options +func _ready() -> void: + var options: OptionMenu = $Options options.add_menu_item(OPTION_TEST_CASE_HIT_FROM_INSIDE, true, false) @@ -21,7 +19,7 @@ func _ready(): _do_raycasts = true -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if not _do_raycasts: @@ -34,16 +32,16 @@ func _physics_process(delta): clear_drawn_nodes() for node in $Shapes.get_children(): - var body = node as PhysicsBody2D - var space_state = body.get_world_2d().direct_space_state - var body_name = String(body.name).substr("RigidBody".length()) + var body: PhysicsBody2D = node + var space_state := body.get_world_2d().direct_space_state + var body_name := String(body.name).substr("RigidBody".length()) Log.print_log("* Testing: %s" % body_name) - var center = body.position + var center := body.position # Raycast entering from the top. - var res = _add_raycast(space_state, center - Vector2(0, 100), center) + var res: Dictionary = _add_raycast(space_state, center - Vector2(0, 100), center) Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT")) # Raycast exiting from inside. @@ -63,25 +61,23 @@ func _physics_process(delta): Log.print_log("Raycast inside face: %s" % ("HIT" if res else "NO HIT")) -func _on_option_changed(option, checked): +func _on_option_changed(option: String, checked: bool) -> void: match option: OPTION_TEST_CASE_HIT_FROM_INSIDE: _hit_from_inside = checked _do_raycasts = true -func _add_raycast(space_state, pos_start, pos_end): - var params = PhysicsRayQueryParameters2D.new() +func _add_raycast(space_state: PhysicsDirectSpaceState2D, pos_start: Vector2, pos_end: Vector2) -> Dictionary: + var params := PhysicsRayQueryParameters2D.new() params.from = pos_start params.to = pos_end params.hit_from_inside = _hit_from_inside - var result = space_state.intersect_ray(params) - var color + var result: Dictionary = space_state.intersect_ray(params) + var color := Color.RED.darkened(0.5) if result: color = Color.GREEN.darkened(0.2) - else: - color = Color.RED.darkened(0.5) # Draw raycast line. add_line(pos_start, pos_end, color) @@ -91,8 +87,8 @@ func _add_raycast(space_state, pos_start, pos_end): add_line(pos_end, pos_end + Vector2(5, -10), color) if result: - # Draw raycast hit pos. - var hit_pos = result.position + # Draw raycast hit position. + var hit_pos: Vector2 = result.position add_circle(hit_pos, 4.0, Color.YELLOW) # Draw raycast hit normal. diff --git a/2d/physics_tests/tests/functional/test_stack.gd b/2d/physics_tests/tests/functional/test_stack.gd index a9be5f0a..09786140 100644 --- a/2d/physics_tests/tests/functional/test_stack.gd +++ b/2d/physics_tests/tests/functional/test_stack.gd @@ -1,33 +1,31 @@ extends Test +@export var height := 10 +@export var width := 1 +@export var box_size := Vector2(40.0, 40.0) +@export var box_spacing := Vector2(0.0, 0.0) -@export var height = 10 -@export var width = 1 -@export var box_size = Vector2(40.0, 40.0) -@export var box_spacing = Vector2(0.0, 0.0) - - -func _ready(): +func _ready() -> void: _create_stack() -func _create_stack(): - var root_node = $Stack +func _create_stack() -> void: + var root_node := $Stack - var template_body = create_rigidbody_box(box_size, true) + var template_body := create_rigidbody_box(box_size, true) - var pos_y = -0.5 * box_size.y - box_spacing.y + var pos_y := -0.5 * box_size.y - box_spacing.y - for level in height: - var row_node = Node2D.new() + for level: int in height: + var row_node := Node2D.new() row_node.position = Vector2(0.0, pos_y) row_node.name = "Row%02d" % (level + 1) root_node.add_child(row_node) - var pos_x = -0.5 * (width - 1) * (box_size.x + box_spacing.x) + var pos_x := -0.5 * (width - 1) * (box_size.x + box_spacing.x) - for box_index in range(width): - var box = template_body.duplicate() + for box_index in width: + var box := template_body.duplicate() box.position = Vector2(pos_x, 0.0) box.name = "Box%02d" % (box_index + 1) row_node.add_child(box) diff --git a/2d/physics_tests/tests/performance/test_perf_broadphase.gd b/2d/physics_tests/tests/performance/test_perf_broadphase.gd index 1fb7c012..3c7d1439 100644 --- a/2d/physics_tests/tests/performance/test_perf_broadphase.gd +++ b/2d/physics_tests/tests/performance/test_perf_broadphase.gd @@ -1,20 +1,18 @@ extends Test - const BOX_SIZE = Vector2(40, 40) const BOX_SPACE = Vector2(50, 50) -@export_range(1, 1000) var row_size = 100 -@export_range(1, 1000) var column_size = 100 +@export_range(1, 1000) var row_size := 100 +@export_range(1, 1000) var column_size := 100 -var _objects = [] +var _objects: Array[Node2D] = [] -var _log_physics = false -var _log_physics_time = 0 -var _log_physics_time_start = 0 +var _log_physics := false +var _log_physics_time := 0 +var _log_physics_time_start := 0 - -func _ready(): +func _ready() -> void: await start_timer(1.0).timeout if is_timer_canceled(): return @@ -66,46 +64,46 @@ func _ready(): Log.print_log("* Done.") -func _exit_tree(): +func _exit_tree() -> void: for object in _objects: object.free() -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if _log_physics: - var time = Time.get_ticks_usec() - var time_delta = time - _log_physics_time - var time_total = time - _log_physics_time_start + var time := Time.get_ticks_usec() + var time_delta := time - _log_physics_time + var time_total := time - _log_physics_time_start _log_physics_time = time Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total]) -func _log_physics_start(): +func _log_physics_start() -> void: _log_physics = true _log_physics_time_start = Time.get_ticks_usec() _log_physics_time = _log_physics_time_start -func _log_physics_stop(): +func _log_physics_stop() -> void: _log_physics = false -func _create_objects(): +func _create_objects() -> void: _objects.clear() Log.print_log("* Creating objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() - var pos_x = -0.5 * (row_size - 1) * BOX_SPACE.x + var pos_x := -0.5 * (row_size - 1) * BOX_SPACE.x for row in row_size: - var pos_y = -0.5 * (column_size - 1) * BOX_SPACE.y + var pos_y := -0.5 * (column_size - 1) * BOX_SPACE.y for column in column_size: # Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape. - var box = create_rigidbody_box(BOX_SIZE) + var box := create_rigidbody_box(BOX_SIZE) box.gravity_scale = 0.0 box.position = Vector2(pos_x, pos_y) _objects.push_back(box) @@ -118,11 +116,11 @@ func _create_objects(): Log.print_log(" Create Time: %.3f ms" % (0.001 * timer)) -func _add_objects(): - var root_node = $Objects +func _add_objects() -> void: + var root_node: Node2D = $Objects Log.print_log("* Adding objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() for object in _objects: root_node.add_child(object) @@ -131,9 +129,9 @@ func _add_objects(): Log.print_log(" Add Time: %.3f ms" % (0.001 * timer)) -func _move_objects(): +func _move_objects() -> void: Log.print_log("* Moving objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() for object in _objects: object.position += BOX_SPACE @@ -142,15 +140,15 @@ func _move_objects(): Log.print_log(" Move Time: %.3f ms" % (0.001 * timer)) -func _remove_objects(): - var root_node = $Objects +func _remove_objects() -> void: + var root_node: Node2D = $Objects Log.print_log("* Removing objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() # Remove objects in reversed order to avoid the overhead of changing children index in parent. - var object_count = _objects.size() - for object_index in range(object_count): + var object_count := _objects.size() + for object_index in object_count: root_node.remove_child(_objects[object_count - object_index - 1]) timer = Time.get_ticks_usec() - timer diff --git a/2d/physics_tests/tests/performance/test_perf_broadphase.tscn b/2d/physics_tests/tests/performance/test_perf_broadphase.tscn index cd9d7f0b..0ee4917f 100644 --- a/2d/physics_tests/tests/performance/test_perf_broadphase.tscn +++ b/2d/physics_tests/tests/performance/test_perf_broadphase.tscn @@ -3,10 +3,10 @@ [ext_resource type="Script" path="res://tests/performance/test_perf_broadphase.gd" id="1"] [node name="Test" type="Node2D"] -script = ExtResource( "1" ) -_enable_debug_collision = false +script = ExtResource("1") row_size = 300 column_size = 300 +_enable_debug_collision = false [node name="Objects" type="Node2D" parent="."] position = Vector2(512, 300) diff --git a/2d/physics_tests/tests/performance/test_perf_contacts.gd b/2d/physics_tests/tests/performance/test_perf_contacts.gd index 3a8bb1e2..c453da34 100644 --- a/2d/physics_tests/tests/performance/test_perf_contacts.gd +++ b/2d/physics_tests/tests/performance/test_perf_contacts.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_TYPE_ALL = "Shape type/All" const OPTION_TYPE_RECTANGLE = "Shape type/Rectangle" const OPTION_TYPE_SPHERE = "Shape type/Sphere" @@ -8,27 +7,27 @@ const OPTION_TYPE_CAPSULE = "Shape type/Capsule" const OPTION_TYPE_CONVEX_POLYGON = "Shape type/Convex Polygon" const OPTION_TYPE_CONCAVE_POLYGON = "Shape type/Concave Polygon" -@export var spawns = [] -@export var spawn_count = 100 -@export var spawn_randomize = Vector2.ZERO +@export var spawns: Array[NodePath] = [] +@export var spawn_count := 100 +@export var spawn_randomize := Vector2.ZERO -@onready var options = $Options +@onready var options: OptionMenu = $Options -var _object_templates = [] +var _object_templates: Array[Node2D] = [] -var _log_physics = false -var _log_physics_time = 0 -var _log_physics_time_start = 0 +var _log_physics := false +var _log_physics_time := 0 +var _log_physics_time_start := 0 -func _ready(): +func _ready() -> void: await start_timer(0.5).timeout if is_timer_canceled(): return - var dynamic_shapes = $DynamicShapes + var dynamic_shapes: Node2D = $DynamicShapes while dynamic_shapes.get_child_count(): - var type_node = dynamic_shapes.get_child(0) + var type_node: RigidBody2D = dynamic_shapes.get_child(0) type_node.position = Vector2.ZERO _object_templates.push_back(type_node) dynamic_shapes.remove_child(type_node) @@ -44,33 +43,33 @@ func _ready(): await _start_all_types() -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if _log_physics: - var time = Time.get_ticks_usec() - var time_delta = time - _log_physics_time - var time_total = time - _log_physics_time_start + var time := Time.get_ticks_usec() + var time_delta := time - _log_physics_time + var time_total := time - _log_physics_time_start _log_physics_time = time Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total]) -func _log_physics_start(): +func _log_physics_start() -> void: _log_physics = true _log_physics_time_start = Time.get_ticks_usec() _log_physics_time = _log_physics_time_start -func _log_physics_stop(): +func _log_physics_stop() -> void: _log_physics = false -func _exit_tree(): +func _exit_tree() -> void: for object_template in _object_templates: object_template.free() -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: cancel_timer() _despawn_objects() @@ -90,9 +89,9 @@ func _on_option_selected(option): await _start_type(_find_type_index("ConcavePolygon")) -func _find_type_index(type_name): +func _find_type_index(type_name: String) -> int: for type_index in range(_object_templates.size()): - var type_node = _object_templates[type_index] + var type_node := _object_templates[type_index] if String(type_node.name).find(type_name) > -1: return type_index @@ -100,7 +99,7 @@ func _find_type_index(type_name): return -1 -func _start_type(type_index): +func _start_type(type_index: int) -> void: if type_index < 0: return if type_index >= _object_templates.size(): @@ -142,7 +141,7 @@ func _start_type(type_index): await start_timer(1.0).timeout -func _start_all_types(): +func _start_all_types() -> void: Log.print_log("* Start all types.") for type_index in range(_object_templates.size()): @@ -153,25 +152,25 @@ func _start_all_types(): Log.print_log("* Done all types.") -func _spawn_objects(type_index): - var template_node = _object_templates[type_index] +func _spawn_objects(type_index: int) -> void: + var template_node: RigidBody2D = _object_templates[type_index] Log.print_log("* Spawning: " + String(template_node.name)) for spawn in spawns: - var spawn_parent = get_node(spawn) + var spawn_parent := get_node(spawn) for _node_index in range(spawn_count): # Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape. - var collision = template_node.get_child(0).duplicate() + var collision: Node2D = template_node.get_child(0).duplicate() if collision is CollisionShape2D: collision.shape = collision.shape.duplicate() - var body = template_node.duplicate() + var body: Node2D = template_node.duplicate() body.transform = Transform2D.IDENTITY if spawn_randomize != Vector2.ZERO: body.position.x = randf() * spawn_randomize.x body.position.y = randf() * spawn_randomize.y - var prev_collision = body.get_child(0) + var prev_collision: Node2D = body.get_child(0) body.remove_child(prev_collision) prev_collision.queue_free() body.add_child(collision) @@ -179,29 +178,29 @@ func _spawn_objects(type_index): spawn_parent.add_child(body) -func _activate_objects(): +func _activate_objects() -> void: Log.print_log("* Activating") for spawn in spawns: - var spawn_parent = get_node(spawn) + var spawn_parent := get_node(spawn) - for node_index in range(spawn_parent.get_child_count()): - var node = spawn_parent.get_child(node_index) as RigidBody2D + for node_index in spawn_parent.get_child_count(): + var node := spawn_parent.get_child(node_index) as RigidBody2D node.set_sleeping(false) -func _despawn_objects(): +func _despawn_objects() -> void: Log.print_log("* Despawning") for spawn in spawns: - var spawn_parent = get_node(spawn) + var spawn_parent: Node2D = get_node(spawn) - var object_count = spawn_parent.get_child_count() + var object_count := spawn_parent.get_child_count() if object_count == 0: continue # Remove objects in reversed order to avoid the overhead of changing children index in parent. for object_index in range(object_count): - var node = spawn_parent.get_child(object_count - object_index - 1) + var node: Node2D = spawn_parent.get_child(object_count - object_index - 1) spawn_parent.remove_child(node) node.queue_free() diff --git a/2d/physics_tests/tests/performance/test_perf_contacts.tscn b/2d/physics_tests/tests/performance/test_perf_contacts.tscn index dc31b6c2..0a16bc5c 100644 --- a/2d/physics_tests/tests/performance/test_perf_contacts.tscn +++ b/2d/physics_tests/tests/performance/test_perf_contacts.tscn @@ -15,41 +15,41 @@ radius = 15.0 height = 35.0 [node name="Test" type="Node2D"] -script = ExtResource( "2" ) -_enable_debug_collision = false -spawns = [NodePath("SpawnTarget1")] +script = ExtResource("2") +spawns = Array[NodePath]([NodePath("SpawnTarget1")]) spawn_count = 500 spawn_randomize = Vector2(10, 10) +_enable_debug_collision = false -[node name="Options" parent="." instance=ExtResource( "4" )] +[node name="Options" parent="." instance=ExtResource("4")] [node name="SpawnTarget1" type="Node2D" parent="."] position = Vector2(512, 400) -[node name="StaticScene" parent="." instance=ExtResource( "1" )] +[node name="StaticScene" parent="." instance=ExtResource("1")] position = Vector2(0, 125.017) [node name="DynamicShapes" type="Node2D" parent="."] -[node name="RigidBodyRectangle" type="RigidDynamicBody2D" parent="DynamicShapes"] +[node name="RigidBodyRectangle" type="RigidBody2D" parent="DynamicShapes"] position = Vector2(0, 1024) [node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyRectangle"] -shape = SubResource( "1" ) +shape = SubResource("1") -[node name="RigidBodySphere" type="RigidDynamicBody2D" parent="DynamicShapes"] +[node name="RigidBodySphere" type="RigidBody2D" parent="DynamicShapes"] position = Vector2(100, 1024) [node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodySphere"] -shape = SubResource( "2" ) +shape = SubResource("2") -[node name="RigidBodyCapsule" type="RigidDynamicBody2D" parent="DynamicShapes"] +[node name="RigidBodyCapsule" type="RigidBody2D" parent="DynamicShapes"] position = Vector2(200, 1024) [node name="CollisionShape2D" type="CollisionShape2D" parent="DynamicShapes/RigidBodyCapsule"] -shape = SubResource( "3" ) +shape = SubResource("3") -[node name="RigidBodyConvexPolygon" type="RigidDynamicBody2D" parent="DynamicShapes"] +[node name="RigidBodyConvexPolygon" type="RigidBody2D" parent="DynamicShapes"] position = Vector2(300, 1024) [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConvexPolygon"] @@ -59,9 +59,9 @@ polygon = PackedVector2Array(10.7, -54.5, 28.3596, -49.4067, 47.6282, -34.3806, [node name="GodotIcon" type="Sprite2D" parent="DynamicShapes/RigidBodyConvexPolygon"] self_modulate = Color(1, 1, 1, 0.392157) scale = Vector2(0.25, 0.25) -texture = ExtResource( "3" ) +texture = ExtResource("3") -[node name="RigidBodyConcavePolygon" type="RigidDynamicBody2D" parent="DynamicShapes"] +[node name="RigidBodyConcavePolygon" type="RigidBody2D" parent="DynamicShapes"] position = Vector2(400, 1024) [node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="DynamicShapes/RigidBodyConcavePolygon"] @@ -71,4 +71,4 @@ polygon = PackedVector2Array(-5.93512, -43.2195, 6.44476, -42.9695, 11.127, -54. [node name="GodotIcon" type="Sprite2D" parent="DynamicShapes/RigidBodyConcavePolygon"] self_modulate = Color(1, 1, 1, 0.392157) scale = Vector2(0.25, 0.25) -texture = ExtResource( "3" ) +texture = ExtResource("3") diff --git a/2d/physics_tests/tests_menu.gd b/2d/physics_tests/tests_menu.gd index 580625d9..71f64347 100644 --- a/2d/physics_tests/tests_menu.gd +++ b/2d/physics_tests/tests_menu.gd @@ -2,28 +2,27 @@ extends OptionMenu class TestData: - var id - var scene_path + var id := "" + var scene_path := "" -var _test_list = [] +var _test_list := [] -var _current_test = null +var _current_test: TestData = null var _current_test_scene: Node = null - -func _ready(): +func _ready() -> void: option_selected.connect(_on_option_selected) -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"restart_test"): if _current_test: _start_test(_current_test) -func add_test(id, scene_path): - var test_data = TestData.new() +func add_test(id: String, scene_path: String) -> void: + var test_data := TestData.new() test_data.id = id test_data.scene_path = scene_path _test_list.append(test_data) @@ -31,13 +30,13 @@ func add_test(id, scene_path): add_menu_item(id) -func _on_option_selected(item_path): - for test in _test_list: +func _on_option_selected(item_path: String) -> void: + for test: TestData in _test_list: if test.id == item_path: _start_test(test) -func _start_test(test): +func _start_test(test: TestData) -> void: _current_test = test if _current_test_scene: @@ -45,10 +44,10 @@ func _start_test(test): _current_test_scene = null Log.print_log("*** STARTING TEST: " + test.id) - var scene = load(test.scene_path) + var scene := load(test.scene_path) _current_test_scene = scene.instantiate() get_tree().root.add_child(_current_test_scene) get_tree().root.move_child(_current_test_scene, 0) - var label_test = get_node(^"../LabelTest") + var label_test: Label = $"../LabelTest" label_test.test_name = test.id diff --git a/2d/physics_tests/utils/characterbody_controller.gd b/2d/physics_tests/utils/characterbody_controller.gd index 899855a8..cc23b6b6 100644 --- a/2d/physics_tests/utils/characterbody_controller.gd +++ b/2d/physics_tests/utils/characterbody_controller.gd @@ -1,22 +1,21 @@ extends CharacterBody2D - -var _initial_velocity = Vector2.ZERO -var _constant_velocity = Vector2.ZERO -var _motion_speed = 400.0 -var _gravity_force = 50.0 -var _jump_force = 1000.0 -var _velocity = Vector2.ZERO -var _snap = 0.0 -var _floor_max_angle = 45.0 -var _stop_on_slope = false -var _move_on_floor_only = false -var _constant_speed = false -var _jumping = false -var _keep_velocity = false +var _initial_velocity := Vector2.ZERO +var _constant_velocity := Vector2.ZERO +var _motion_speed := 400.0 +var _gravity_force := 50.0 +var _jump_force := 1000.0 +var _velocity := Vector2.ZERO +var _snap := 0.0 +var _floor_max_angle := 45.0 +var _stop_on_slope := false +var _move_on_floor_only := false +var _constant_speed := false +var _jumping := false +var _keep_velocity := false -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if _initial_velocity != Vector2.ZERO: _velocity = _initial_velocity _initial_velocity = Vector2.ZERO diff --git a/2d/physics_tests/utils/container_log.gd b/2d/physics_tests/utils/container_log.gd index 3ccf84a6..0c0024e5 100644 --- a/2d/physics_tests/utils/container_log.gd +++ b/2d/physics_tests/utils/container_log.gd @@ -1,31 +1,29 @@ extends Control - const MAX_ENTRIES = 100 -var _entry_template +var _entry_template: Label - -func _enter_tree(): +func _enter_tree() -> void: Log.entry_logged.connect(_on_log_entry) - _entry_template = get_child(0) as Label + _entry_template = get_child(0) remove_child(_entry_template) -func _exit_tree(): +func _exit_tree() -> void: _entry_template.free() -func clear(): +func clear() -> void: while get_child_count(): - var entry = get_child(get_child_count() - 1) + var entry := get_child(get_child_count() - 1) remove_child(entry) entry.queue_free() -func _on_log_entry(message, type): - var new_entry = _entry_template.duplicate() as Label +func _on_log_entry(message: String, type: Log.LogType) -> void: + var new_entry: Label = _entry_template.duplicate() new_entry.set_text(message) if type == Log.LogType.ERROR: @@ -34,7 +32,7 @@ func _on_log_entry(message, type): new_entry.modulate = Color.WHITE if get_child_count() >= MAX_ENTRIES: - var first_entry = get_child(0) as Label + var first_entry: Label = get_child(0) remove_child(first_entry) first_entry.queue_free() diff --git a/2d/physics_tests/utils/label_engine.gd b/2d/physics_tests/utils/label_engine.gd index 07392adc..7e97aca9 100644 --- a/2d/physics_tests/utils/label_engine.gd +++ b/2d/physics_tests/utils/label_engine.gd @@ -1,12 +1,13 @@ extends Label +func _ready() -> void: + var engine_name := "" -func _process(_delta): - var engine_name = "" match System.get_physics_engine(): System.PhysicsEngine.GODOT_PHYSICS: engine_name = "GodotPhysics 2D" System.PhysicsEngine.OTHER: - var engine_setting = ProjectSettings.get_setting("physics/2d/physics_engine") + var engine_setting := String(ProjectSettings.get_setting("physics/2d/physics_engine")) engine_name = "Other (%s)" % engine_setting - set_text("Physics engine: %s" % engine_name) + + text = "Physics engine: %s" % engine_name diff --git a/2d/physics_tests/utils/label_fps.gd b/2d/physics_tests/utils/label_fps.gd index 6f2c6f30..8165e7f2 100644 --- a/2d/physics_tests/utils/label_fps.gd +++ b/2d/physics_tests/utils/label_fps.gd @@ -1,5 +1,4 @@ extends Label - -func _process(_delta): - set_text("FPS: %d" % Engine.get_frames_per_second()) +func _process(_delta: float) -> void: + text = "%d FPS (%.2f mspf)" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()] diff --git a/2d/physics_tests/utils/label_pause.gd b/2d/physics_tests/utils/label_pause.gd index d0b9a060..02d5ab0a 100644 --- a/2d/physics_tests/utils/label_pause.gd +++ b/2d/physics_tests/utils/label_pause.gd @@ -1,5 +1,5 @@ extends Label -func _process(_delta): +func _process(_delta: float) -> void: visible = get_tree().paused diff --git a/2d/physics_tests/utils/label_slider_value.gd b/2d/physics_tests/utils/label_slider_value.gd index 4d1ed419..fb97bae8 100644 --- a/2d/physics_tests/utils/label_slider_value.gd +++ b/2d/physics_tests/utils/label_slider_value.gd @@ -2,6 +2,6 @@ extends Label -func _process(_delta): - var slider = get_node(^"../HSlider") +func _process(_delta: float) -> void: + var slider: HSlider = get_node(^"../HSlider") text = "%.1f" % slider.value diff --git a/2d/physics_tests/utils/label_test.gd b/2d/physics_tests/utils/label_test.gd index 01e0c1bc..6fdcc123 100644 --- a/2d/physics_tests/utils/label_test.gd +++ b/2d/physics_tests/utils/label_test.gd @@ -1,7 +1,6 @@ extends Label - -var test_name = "": +var test_name := "": set(value): if (test_name != value): return @@ -9,5 +8,5 @@ var test_name = "": set_text("Test: %s" % test_name) -func _ready(): +func _ready() -> void: set_text("Select a test from the menu to start it") diff --git a/2d/physics_tests/utils/label_version.gd b/2d/physics_tests/utils/label_version.gd index b2185fb9..4303cba7 100644 --- a/2d/physics_tests/utils/label_version.gd +++ b/2d/physics_tests/utils/label_version.gd @@ -1,5 +1,4 @@ extends Label - -func _process(_delta): - set_text("Godot Version: %s" % Engine.get_version_info().string) +func _ready() -> void: + text = "Godot Version: %s" % Engine.get_version_info().string diff --git a/2d/physics_tests/utils/option_menu.gd b/2d/physics_tests/utils/option_menu.gd index ded2cca5..460e361c 100644 --- a/2d/physics_tests/utils/option_menu.gd +++ b/2d/physics_tests/utils/option_menu.gd @@ -1,24 +1,23 @@ class_name OptionMenu extends MenuButton - -signal option_selected(item_path) -signal option_changed(item_path, checked) +signal option_selected(item_path: String) +signal option_changed(item_path: String, checked: bool) -func add_menu_item(item_path, checkbox = false, checked = false, radio = false): - var path_elements = item_path.split("/", false) - var path_element_count = path_elements.size() +func add_menu_item(item_path: String, checkbox: bool = false, checked: bool = false, radio: bool = false) -> void: + var path_elements := item_path.split("/", false) + var path_element_count := path_elements.size() assert(path_element_count > 0) - var path = "" - var popup = get_popup() + var path := "" + var popup := get_popup() for element_index in range(path_element_count - 1): - var popup_label = path_elements[element_index] + var popup_label := path_elements[element_index] path += popup_label + "/" popup = _add_popup(popup, path, popup_label) - var label = path_elements[path_element_count - 1] + var label := path_elements[path_element_count - 1] if radio: popup.add_radio_check_item(label) popup.set_item_checked(popup.get_item_count() - 1, checked) @@ -29,18 +28,18 @@ func add_menu_item(item_path, checkbox = false, checked = false, radio = false): popup.add_item(label) -func _add_item(parent_popup, label): +func _add_item(parent_popup: PopupMenu, label: String) -> void: parent_popup.add_item(label) -func _add_popup(parent_popup, path, label): +func _add_popup(parent_popup: PopupMenu, path: String, label: String) -> PopupMenu: if parent_popup.has_node(label): - var popup_node = parent_popup.get_node(label) - var popup_menu = popup_node as PopupMenu - assert(popup_menu) - return popup_menu + var popup_node := parent_popup.get_node(label) + var new_popup_menu: PopupMenu = popup_node + assert(new_popup_menu) + return new_popup_menu - var popup_menu = PopupMenu.new() + var popup_menu := PopupMenu.new() popup_menu.name = label popup_menu.hide_on_checkable_item_selection = false @@ -52,11 +51,11 @@ func _add_popup(parent_popup, path, label): return popup_menu -func _on_item_pressed(item_index, popup_menu, path): - var item_path = path + popup_menu.get_item_text(item_index) +func _on_item_pressed(item_index: int, popup_menu: PopupMenu, path: String) -> void: + var item_path := path + popup_menu.get_item_text(item_index) if popup_menu.is_item_radio_checkable(item_index): - var checked = popup_menu.is_item_checked(item_index) + var checked := popup_menu.is_item_checked(item_index) if not checked: popup_menu.set_item_checked(item_index, true) for other_index in range(popup_menu.get_item_count()): @@ -64,7 +63,7 @@ func _on_item_pressed(item_index, popup_menu, path): popup_menu.set_item_checked(other_index, false) option_selected.emit(item_path) elif popup_menu.is_item_checkable(item_index): - var checked = not popup_menu.is_item_checked(item_index) + var checked := not popup_menu.is_item_checked(item_index) popup_menu.set_item_checked(item_index, checked) option_changed.emit(item_path, checked) else: diff --git a/2d/physics_tests/utils/rigidbody_controller.gd b/2d/physics_tests/utils/rigidbody_controller.gd index 32f6b2fc..e07bc6f4 100644 --- a/2d/physics_tests/utils/rigidbody_controller.gd +++ b/2d/physics_tests/utils/rigidbody_controller.gd @@ -1,22 +1,21 @@ extends RigidBody2D +var _initial_velocity := Vector2.ZERO +var _constant_velocity := Vector2.ZERO +var _motion_speed := 400.0 +var _gravity_force := 50.0 +var _jump_force := 1000.0 +var _velocity := Vector2.ZERO +var _floor_max_angle := 45.0 +var _on_floor := false +var _jumping := false +var _keep_velocity := false -var _initial_velocity = Vector2.ZERO -var _constant_velocity = Vector2.ZERO -var _motion_speed = 400.0 -var _gravity_force = 50.0 -var _jump_force = 1000.0 -var _velocity = Vector2.ZERO -var _floor_max_angle = 45.0 -var _on_floor = false -var _jumping = false -var _keep_velocity = false - - -func _ready(): +func _ready() -> void: gravity_scale = 0.0 -func _physics_process(_delta): + +func _physics_process(_delta: float) -> void: if _initial_velocity != Vector2.ZERO: _velocity = _initial_velocity _initial_velocity = Vector2.ZERO @@ -54,12 +53,12 @@ func _physics_process(_delta): linear_velocity = _velocity -func _integrate_forces(state): +func _integrate_forces(state: PhysicsDirectBodyState2D) -> void: _on_floor = false - var contacts = state.get_contact_count() + var contacts := state.get_contact_count() for i in contacts: - var normal = state.get_contact_local_normal(i) + var normal := state.get_contact_local_normal(i) # Detect floor. if acos(normal.dot(Vector2.UP)) <= deg_to_rad(_floor_max_angle) + 0.01: @@ -70,5 +69,5 @@ func _integrate_forces(state): _jumping = false _velocity.y = 0.0 -func is_on_floor(): +func is_on_floor() -> bool: return _on_floor diff --git a/2d/physics_tests/utils/rigidbody_pick.gd b/2d/physics_tests/utils/rigidbody_pick.gd index 4ab93aa8..516bb683 100644 --- a/2d/physics_tests/utils/rigidbody_pick.gd +++ b/2d/physics_tests/utils/rigidbody_pick.gd @@ -1,30 +1,29 @@ extends RigidBody2D - -var _picked = false -var _last_mouse_pos = Vector2.ZERO +var _picked := false +var _last_mouse_pos := Vector2.ZERO -func _ready(): +func _ready() -> void: input_pickable = true -func _input(event): - var mouse_event = event as InputEventMouseButton +func _input(event: InputEvent) -> void: + var mouse_event := event as InputEventMouseButton if mouse_event and not mouse_event.pressed: _picked = false -func _input_event(_viewport, event, _shape_idx): - var mouse_event = event as InputEventMouseButton +func _input_event(_viewport: Node, event: InputEvent, _shape_idx: int) -> void: + var mouse_event := event as InputEventMouseButton if mouse_event and mouse_event.pressed: _picked = true _last_mouse_pos = get_global_mouse_position() -func _physics_process(delta): +func _physics_process(delta: float) -> void: if _picked: - var mouse_pos = get_global_mouse_position() + var mouse_pos := get_global_mouse_position() if freeze: global_position = mouse_pos else: diff --git a/2d/physics_tests/utils/scroll_log.gd b/2d/physics_tests/utils/scroll_log.gd index 0e927da4..12496e0d 100644 --- a/2d/physics_tests/utils/scroll_log.gd +++ b/2d/physics_tests/utils/scroll_log.gd @@ -1,24 +1,22 @@ extends ScrollContainer +@export var auto_scroll := false -@export var auto_scroll = false - - -func _ready(): - var scrollbar = get_v_scroll_bar() +func _ready() -> void: + var scrollbar := get_v_scroll_bar() scrollbar.scrolling.connect(_on_scrolling) -func _process(_delta): +func _process(_delta: float) -> void: if auto_scroll: - var scrollbar = get_v_scroll_bar() + var scrollbar := get_v_scroll_bar() scrollbar.value = scrollbar.max_value -func _on_scrolling(): +func _on_scrolling() -> void: auto_scroll = false $"../CheckBoxScroll".button_pressed = false -func _on_check_box_scroll_toggled(button_pressed): +func _on_check_box_scroll_toggled(button_pressed: bool) -> void: auto_scroll = button_pressed diff --git a/2d/physics_tests/utils/slider.gd b/2d/physics_tests/utils/slider.gd index ab555b8a..ae819ee0 100644 --- a/2d/physics_tests/utils/slider.gd +++ b/2d/physics_tests/utils/slider.gd @@ -1,10 +1,10 @@ extends HSlider -@export var snap_step = 1.0 +@export var snap_step := 1.0 -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_key_pressed(KEY_SHIFT): step = 0.1 else: diff --git a/2d/physics_tests/utils/system.gd b/2d/physics_tests/utils/system.gd index c443332b..3092d44d 100644 --- a/2d/physics_tests/utils/system.gd +++ b/2d/physics_tests/utils/system.gd @@ -1,20 +1,20 @@ extends Node - enum PhysicsEngine { GODOT_PHYSICS, OTHER, } -var _engine = PhysicsEngine.OTHER +var _engine: PhysicsEngine = PhysicsEngine.OTHER - -func _enter_tree(): +func _enter_tree() -> void: process_mode = Node.PROCESS_MODE_ALWAYS + # Always enable visible collision shapes on startup + # (same as the Debug > Visible Collision Shapes option). get_tree().debug_collisions_hint = true - var engine_string = ProjectSettings.get_setting("physics/2d/physics_engine") + var engine_string:= String(ProjectSettings.get_setting("physics/2d/physics_engine")) match engine_string: "DEFAULT": _engine = PhysicsEngine.GODOT_PHYSICS @@ -24,7 +24,7 @@ func _enter_tree(): _engine = PhysicsEngine.OTHER -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"toggle_full_screen"): if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) @@ -32,7 +32,7 @@ func _process(_delta): DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) if Input.is_action_just_pressed(&"toggle_debug_collision"): - var debug_collision_enabled = not _is_debug_collision_enabled() + var debug_collision_enabled := not _is_debug_collision_enabled() _set_debug_collision_enabled(debug_collision_enabled) if debug_collision_enabled: Log.print_log("Debug Collision ON") @@ -46,13 +46,13 @@ func _process(_delta): get_tree().quit() -func get_physics_engine(): +func get_physics_engine() -> PhysicsEngine: return _engine -func _set_debug_collision_enabled(enabled): +func _set_debug_collision_enabled(enabled: bool) -> void: get_tree().debug_collisions_hint = enabled -func _is_debug_collision_enabled(): +func _is_debug_collision_enabled() -> bool: return get_tree().debug_collisions_hint diff --git a/2d/physics_tests/utils/system_log.gd b/2d/physics_tests/utils/system_log.gd index 8abfa804..749e9089 100644 --- a/2d/physics_tests/utils/system_log.gd +++ b/2d/physics_tests/utils/system_log.gd @@ -1,20 +1,18 @@ extends Node - enum LogType { LOG, ERROR, } -signal entry_logged(message, type) +signal entry_logged(message: String, type: LogType) - -func print_log(message): +func print_log(message: String) -> void: print(message) entry_logged.emit(message, LogType.LOG) -func print_error(message): +func print_error(message: String) -> void: push_error(message) printerr(message) entry_logged.emit(message, LogType.ERROR) diff --git a/2d/platformer/enemy/enemy.gd b/2d/platformer/enemy/enemy.gd index bd4f8410..969a726a 100644 --- a/2d/platformer/enemy/enemy.gd +++ b/2d/platformer/enemy/enemy.gd @@ -1,5 +1,5 @@ -class_name Enemy extends CharacterBody2D - +class_name Enemy +extends CharacterBody2D enum State { WALKING, diff --git a/2d/platformer/game.gd b/2d/platformer/game.gd index 0ec75a89..5ba24a10 100644 --- a/2d/platformer/game.gd +++ b/2d/platformer/game.gd @@ -1,4 +1,5 @@ -class_name Game extends Node +class_name Game +extends Node @onready var _pause_menu := $InterfaceLayer/PauseMenu as PauseMenu diff --git a/2d/platformer/gui/coins_counter.gd b/2d/platformer/gui/coins_counter.gd index a1ff99ab..2e486c07 100644 --- a/2d/platformer/gui/coins_counter.gd +++ b/2d/platformer/gui/coins_counter.gd @@ -1,5 +1,5 @@ -class_name CoinsCounter extends Panel - +class_name CoinsCounter +extends Panel var _coins_collected: int = 0 diff --git a/2d/platformer/gui/pause_menu.gd b/2d/platformer/gui/pause_menu.gd index 4fff5588..2d459e1b 100644 --- a/2d/platformer/gui/pause_menu.gd +++ b/2d/platformer/gui/pause_menu.gd @@ -1,4 +1,5 @@ -class_name PauseMenu extends Control +class_name PauseMenu +extends Control @export var fade_in_duration := 0.3 diff --git a/2d/platformer/level/coin.gd b/2d/platformer/level/coin.gd index 152cfb1e..43d38543 100644 --- a/2d/platformer/level/coin.gd +++ b/2d/platformer/level/coin.gd @@ -1,4 +1,5 @@ -class_name Coin extends Area2D +class_name Coin +extends Area2D ## Collectible that disappears when the player touches it. diff --git a/2d/platformer/level/level.gd b/2d/platformer/level/level.gd index a30fd92a..f3203239 100644 --- a/2d/platformer/level/level.gd +++ b/2d/platformer/level/level.gd @@ -1,6 +1,5 @@ extends Node2D - const LIMIT_LEFT = -315 const LIMIT_TOP = -250 const LIMIT_RIGHT = 955 diff --git a/2d/platformer/player/bullet.gd b/2d/platformer/player/bullet.gd index 67ce6bf3..6387f417 100644 --- a/2d/platformer/player/bullet.gd +++ b/2d/platformer/player/bullet.gd @@ -1,4 +1,5 @@ -class_name Bullet extends RigidBody2D +class_name Bullet +extends RigidBody2D @onready var animation_player := $AnimationPlayer as AnimationPlayer diff --git a/2d/platformer/player/gun.gd b/2d/platformer/player/gun.gd index 509d9d12..86a6f1fc 100644 --- a/2d/platformer/player/gun.gd +++ b/2d/platformer/player/gun.gd @@ -1,8 +1,8 @@ -class_name Gun extends Marker2D +class_name Gun +extends Marker2D ## Represents a weapon that spawns and shoots bullets. ## The Cooldown timer controls the cooldown duration between shots. - const BULLET_VELOCITY = 850.0 const BULLET_SCENE = preload("res://player/bullet.tscn") diff --git a/2d/platformer/player/player.gd b/2d/platformer/player/player.gd index 29f460e7..55ac27c6 100644 --- a/2d/platformer/player/player.gd +++ b/2d/platformer/player/player.gd @@ -1,5 +1,5 @@ -class_name Player extends CharacterBody2D - +class_name Player +extends CharacterBody2D signal coin_collected() @@ -19,7 +19,7 @@ var gravity: int = ProjectSettings.get("physics/2d/default_gravity") @onready var shoot_timer := $ShootAnimation as Timer @onready var sprite := $Sprite2D as Sprite2D @onready var jump_sound := $Jump as AudioStreamPlayer2D -@onready var gun = sprite.get_node(^"Gun") as Gun +@onready var gun: Gun = sprite.get_node(^"Gun") @onready var camera := $Camera as Camera2D var _double_jump_charged := false diff --git a/2d/platformer/project.godot b/2d/platformer/project.godot index 917571b0..1c1cc2ae 100644 --- a/2d/platformer/project.godot +++ b/2d/platformer/project.godot @@ -27,6 +27,10 @@ config/icon="res://icon.webp" Music="*res://music.tscn" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=800 diff --git a/2d/pong/logic/ball.gd b/2d/pong/logic/ball.gd index e8e9ac1e..2c4c3589 100644 --- a/2d/pong/logic/ball.gd +++ b/2d/pong/logic/ball.gd @@ -2,17 +2,17 @@ extends Area2D const DEFAULT_SPEED = 100 -var _speed = DEFAULT_SPEED -var direction = Vector2.LEFT +var _speed := DEFAULT_SPEED +var direction := Vector2.LEFT -@onready var _initial_pos = position +@onready var _initial_pos := position -func _process(delta): - _speed += delta * 2 +func _process(delta: float) -> void: + _speed += int(delta * 2) position += _speed * delta * direction -func reset(): +func reset() -> void: direction = Vector2.LEFT position = _initial_pos _speed = DEFAULT_SPEED diff --git a/2d/pong/logic/ceiling_floor.gd b/2d/pong/logic/ceiling_floor.gd index c0809d79..481e9542 100644 --- a/2d/pong/logic/ceiling_floor.gd +++ b/2d/pong/logic/ceiling_floor.gd @@ -1,7 +1,7 @@ extends Area2D -@export var _bounce_direction = 1 +@export var _bounce_direction := 1 -func _on_area_entered(area): +func _on_area_entered(area: Area2D) -> void: if area.name == "Ball": area.direction = (area.direction + Vector2(0, _bounce_direction)).normalized() diff --git a/2d/pong/logic/paddle.gd b/2d/pong/logic/paddle.gd index ae201198..40618103 100644 --- a/2d/pong/logic/paddle.gd +++ b/2d/pong/logic/paddle.gd @@ -2,14 +2,14 @@ extends Area2D const MOVE_SPEED = 100 -var _ball_dir -var _up -var _down +var _ball_dir: int +var _up: String +var _down: String -@onready var _screen_size_y = get_viewport_rect().size.y +@onready var _screen_size_y := get_viewport_rect().size.y -func _ready(): - var n = String(name).to_lower() +func _ready() -> void: + var n := String(name).to_lower() _up = n + "_move_up" _down = n + "_move_down" if n == "left": @@ -18,13 +18,13 @@ func _ready(): _ball_dir = -1 -func _process(delta): +func _process(delta: float) -> void: # Move up and down based on input. - var input = Input.get_action_strength(_down) - Input.get_action_strength(_up) + var input := Input.get_action_strength(_down) - Input.get_action_strength(_up) position.y = clamp(position.y + input * MOVE_SPEED * delta, 16, _screen_size_y - 16) -func _on_area_entered(area): +func _on_area_entered(area: Area2D) -> void: if area.name == "Ball": # Assign new direction. area.direction = Vector2(_ball_dir, randf() * 2 - 1).normalized() diff --git a/2d/pong/logic/wall.gd b/2d/pong/logic/wall.gd index 687a1a85..bc4d1bf3 100644 --- a/2d/pong/logic/wall.gd +++ b/2d/pong/logic/wall.gd @@ -1,6 +1,6 @@ extends Area2D -func _on_wall_area_entered(area): +func _on_wall_area_entered(area: Area2D) -> void: if area.name == "Ball": - #oops, ball went out of game place, reset + # Ball went out of bounds, reset. area.reset() diff --git a/2d/pong/project.godot b/2d/pong/project.godot index d59dddc5..bc038df7 100644 --- a/2d/pong/project.godot +++ b/2d/pong/project.godot @@ -18,6 +18,10 @@ run/main_scene="pong.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=640 diff --git a/2d/role_playing_game/combat/combat.gd b/2d/role_playing_game/combat/combat.gd index ef6bc4ec..5768e1e9 100644 --- a/2d/role_playing_game/combat/combat.gd +++ b/2d/role_playing_game/combat/combat.gd @@ -1,12 +1,11 @@ extends Node - -signal combat_finished(winner, loser) +signal combat_finished(winner: Combatant, loser: Combatant) -func initialize(combat_combatants): - for combatant in combat_combatants: - combatant = combatant.instantiate() +func initialize(combat_combatants: Array[PackedScene]) -> void: + for combatant_scene in combat_combatants: + var combatant := combatant_scene.instantiate() if combatant is Combatant: $Combatants.add_combatant(combatant) combatant.get_node("Health").dead.connect(_on_combatant_death.bind(combatant)) @@ -16,19 +15,20 @@ func initialize(combat_combatants): $TurnQueue.initialize() -func clear_combat(): +func clear_combat() -> void: for n in $Combatants.get_children(): n.queue_free() for n in $UI/Combatants.get_children(): n.queue_free() -func finish_combat(winner, loser): +func finish_combat(winner: Combatant, loser: Combatant) -> void: + # FIXME: Error calling from signal 'combat_finished' to callable: 'Node(game.gd)::_on_combat_finished': Cannot convert argument 1 from Object to Object. combat_finished.emit(winner, loser) -func _on_combatant_death(combatant): - var winner +func _on_combatant_death(combatant: Combatant) -> void: + var winner: Combatant if not combatant.name == "Player": winner = $Combatants/Player else: @@ -36,4 +36,5 @@ func _on_combatant_death(combatant): if not n.name == "Player": winner = n break + finish_combat(winner, combatant) diff --git a/2d/role_playing_game/combat/combat.tscn b/2d/role_playing_game/combat/combat.tscn index 270600fa..42dcd3d4 100644 --- a/2d/role_playing_game/combat/combat.tscn +++ b/2d/role_playing_game/combat/combat.tscn @@ -4,7 +4,7 @@ [ext_resource type="Script" path="res://combat/turn_queue.gd" id="2"] [ext_resource type="Theme" uid="uid://dtao6d0ebglcf" path="res://theme/theme.tres" id="3"] [ext_resource type="Script" path="res://combat/interface/ui.gd" id="4"] -[ext_resource type="PackedScene" path="res://combat/interface/info.tscn" id="5"] +[ext_resource type="PackedScene" uid="uid://bypumcqt7j0iv" path="res://combat/interface/info.tscn" id="5"] [ext_resource type="Texture2D" uid="uid://dh804n3h2bl5h" path="res://combat/background/combat_background.png" id="6"] [ext_resource type="Texture2D" uid="uid://mi3mmtft0snh" path="res://decoration/grass.png" id="7"] [ext_resource type="Material" uid="uid://blst65bnoqyam" path="res://decoration/wind_sway.tres" id="8"] @@ -19,7 +19,7 @@ [sub_resource type="GDScript" id="1"] script/source = "extends Node2D -func add_combatant(new_combatant): +func add_combatant(new_combatant: Node2D) -> void: new_combatant.position.x += 200 * get_child_count() add_child(new_combatant) " diff --git a/2d/role_playing_game/combat/combatants/combatant.gd b/2d/role_playing_game/combat/combatants/combatant.gd index d007ebe7..587f4e34 100644 --- a/2d/role_playing_game/combat/combatants/combatant.gd +++ b/2d/role_playing_game/combat/combatants/combatant.gd @@ -1,17 +1,14 @@ class_name Combatant extends Node - signal turn_finished -@export var damage: int = 1 -@export var defense: int = 1 +@export var damage := 1 +@export var defense := 1 -var active = false: set = set_active +var active := false: set = set_active - - -func set_active(value): +func set_active(value: bool) -> void: active = value set_process(value) set_process_input(value) @@ -22,25 +19,20 @@ func set_active(value): $Health.armor = $Health.base_armor -func attack(target): +func attack(target: Combatant) -> void: target.take_damage(damage) turn_finished.emit() -func consume(item): - item.use(self) - turn_finished.emit() - - -func defend(): +func defend() -> void: $Health.armor += defense turn_finished.emit() -func flee(): +func flee() -> void: turn_finished.emit() -func take_damage(damage_to_take): +func take_damage(damage_to_take: float) -> void: $Health.take_damage(damage_to_take) $Sprite2D/AnimationPlayer.play("take_damage") diff --git a/2d/role_playing_game/combat/combatants/health.gd b/2d/role_playing_game/combat/combatants/health.gd index 2181193f..a6eb3645 100644 --- a/2d/role_playing_game/combat/combatants/health.gd +++ b/2d/role_playing_game/combat/combatants/health.gd @@ -1,20 +1,19 @@ extends Node - signal dead -signal health_changed(life) +signal health_changed(life: float) -@export var life = 0 -@export var max_life = 10 -@export var base_armor = 0 -var armor = 0 +@export var life := 0 +@export var max_life := 10 +@export var base_armor := 0 +var armor := 0 -func _ready(): +func _ready() -> void: armor = base_armor -func take_damage(damage): +func take_damage(damage: int) -> void: life = life - damage + armor if life <= 0: dead.emit() @@ -22,11 +21,11 @@ func take_damage(damage): health_changed.emit(life) -func heal(amount): +func heal(amount: int) -> void: life += amount life = clamp(life, life, max_life) health_changed.emit(life) -func get_health_ratio(): - return life / max_life +func get_health_ratio() -> float: + return float(life) / max_life diff --git a/2d/role_playing_game/combat/combatants/opponent.gd b/2d/role_playing_game/combat/combatants/opponent.gd index d73b731f..e4ca8552 100644 --- a/2d/role_playing_game/combat/combatants/opponent.gd +++ b/2d/role_playing_game/combat/combatants/opponent.gd @@ -1,18 +1,20 @@ extends Combatant - -func set_active(value): +func set_active(value: bool) -> void: super.set_active(value) if not active: return if not $Timer.is_inside_tree(): return + $Timer.start() await $Timer.timeout - var target + + var target: Node for actor in get_parent().get_children(): if not actor == self: target = actor break + attack(target) diff --git a/2d/role_playing_game/combat/interface/ui.gd b/2d/role_playing_game/combat/interface/ui.gd index 40bac2e3..0c5728d4 100644 --- a/2d/role_playing_game/combat/interface/ui.gd +++ b/2d/role_playing_game/combat/interface/ui.gd @@ -5,35 +5,39 @@ extends Control @export var info_scene: PackedScene -func initialize(): +func initialize() -> void: for combatant in combatants_node.get_children(): - var health = combatant.get_node("Health") - var info = info_scene.instantiate() - var health_info = info.get_node("VBoxContainer/HealthContainer/Health") + var health := combatant.get_node("Health") + var info := info_scene.instantiate() + var health_info := info.get_node("VBoxContainer/HealthContainer/Health") health_info.value = health.life health_info.max_value = health.max_life info.get_node("VBoxContainer/NameContainer/Name").text = combatant.name health.health_changed.connect(health_info.set_value) $Combatants.add_child(info) + $Buttons/GridContainer/Attack.grab_focus() -func _on_Attack_button_up(): +func _on_Attack_button_up() -> void: if not combatants_node.get_node("Player").active: return + combatants_node.get_node("Player").attack(combatants_node.get_node("Opponent")) -func _on_Defend_button_up(): +func _on_Defend_button_up() -> void: if not combatants_node.get_node("Player").active: return + combatants_node.get_node("Player").defend() -func _on_Flee_button_up(): +func _on_Flee_button_up() -> void: if not combatants_node.get_node("Player").active: return + combatants_node.get_node("Player").flee() - var loser = combatants_node.get_node("Player") - var winner = combatants_node.get_node("Opponent") + var loser: Combatant = combatants_node.get_node("Player") + var winner: Combatant = combatants_node.get_node("Opponent") get_parent().finish_combat(winner, loser) diff --git a/2d/role_playing_game/combat/turn_queue.gd b/2d/role_playing_game/combat/turn_queue.gd index b60d4036..501d0f2d 100644 --- a/2d/role_playing_game/combat/turn_queue.gd +++ b/2d/role_playing_game/combat/turn_queue.gd @@ -1,42 +1,41 @@ extends Node - -signal active_combatant_changed(active_combatant) +signal active_combatant_changed(active_combatant: Combatant) @export var combatants_list: Node -var queue = []: set = set_queue -var active_combatant = null: set = _set_active_combatant +var queue: Array[Node] = []: set = set_queue +var active_combatant: Combatant = null: set = _set_active_combatant -func initialize(): +func initialize() -> void: set_queue(combatants_list.get_children()) play_turn() -func play_turn(): +func play_turn() -> void: await active_combatant.turn_finished get_next_in_queue() play_turn() -func get_next_in_queue(): - var current_combatant = queue.pop_front() +func get_next_in_queue() -> Node: + var current_combatant: Node = queue.pop_front() current_combatant.active = false queue.append(current_combatant) active_combatant = queue[0] return active_combatant -func remove(combatant): - var new_queue = [] +func remove(combatant: Combatant) -> void: + var new_queue := [] for n in queue: new_queue.append(n) - new_queue.remove(new_queue.find(combatant)) + new_queue.remove_at(new_queue.find(combatant)) combatant.queue_free() queue = new_queue -func set_queue(new_queue): +func set_queue(new_queue: Array[Node]) -> void: queue.clear() for node in new_queue: if not node is Combatant: @@ -47,7 +46,7 @@ func set_queue(new_queue): active_combatant = queue[0] -func _set_active_combatant(new_combatant): +func _set_active_combatant(new_combatant: Combatant) -> void: active_combatant = new_combatant active_combatant.active = true active_combatant_changed.emit(active_combatant) diff --git a/2d/role_playing_game/dialogue/dialogue_data/npc.json b/2d/role_playing_game/dialogue/dialogue_data/npc.json old mode 100755 new mode 100644 index 69133663..07254e06 --- a/2d/role_playing_game/dialogue/dialogue_data/npc.json +++ b/2d/role_playing_game/dialogue/dialogue_data/npc.json @@ -1,5 +1,5 @@ { - "dialog_1" : {"name": "UNKNOWN", "text": "Hey, it's a good time to have a JRPG fight, right?"}, - "dialog_2" : {"name": "UNKNOWN", "text": "Let me introduce myself, I'm your OPPONENT"}, - "dialog_3" : {"name": "OPPONENT", "text": "Enough talking. Let's fight!"}, + "dialog_1" : { "name": "UNKNOWN", "text": "Hey, it's a good time to have a JRPG fight, right?" }, + "dialog_2" : { "name": "UNKNOWN", "text": "Let me introduce myself, I'm your OPPONENT." }, + "dialog_3" : { "name": "OPPONENT", "text": "Enough talking. Let's fight!" }, } diff --git a/2d/role_playing_game/dialogue/dialogue_data/object.json b/2d/role_playing_game/dialogue/dialogue_data/object.json old mode 100755 new mode 100644 index 05c8549f..27739e6b --- a/2d/role_playing_game/dialogue/dialogue_data/object.json +++ b/2d/role_playing_game/dialogue/dialogue_data/object.json @@ -1,3 +1,3 @@ { - "dialog_1" : {"name":"PLAYER", "text":"Just a key..." } + "dialog_1" : { "name": "PLAYER", "text": "Just a key..." } } diff --git a/2d/role_playing_game/dialogue/dialogue_data/player_lose.json b/2d/role_playing_game/dialogue/dialogue_data/player_lose.json old mode 100755 new mode 100644 index 38a1bd14..faf807bd --- a/2d/role_playing_game/dialogue/dialogue_data/player_lose.json +++ b/2d/role_playing_game/dialogue/dialogue_data/player_lose.json @@ -1,3 +1,3 @@ { - "dialog_1" : {"name": "OPPONENT", "text": "Aha! I won, maybe you can try again next time"} + "dialog_1" : { "name": "OPPONENT", "text": "Aha! I won, maybe you can try again next time." } } diff --git a/2d/role_playing_game/dialogue/dialogue_data/player_won.json b/2d/role_playing_game/dialogue/dialogue_data/player_won.json old mode 100755 new mode 100644 index f1a13b26..fb3d1b8c --- a/2d/role_playing_game/dialogue/dialogue_data/player_won.json +++ b/2d/role_playing_game/dialogue/dialogue_data/player_won.json @@ -1,3 +1,3 @@ { - "dialog_1" : {"name": "OPPONENT", "text": "Congratulations, you won!"} + "dialog_1" : { "name": "OPPONENT", "text": "Congratulations, you won!" } } diff --git a/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.gd b/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.gd index 9e41d18f..e874ccbf 100644 --- a/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.gd +++ b/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.gd @@ -1,17 +1,16 @@ extends Node - signal dialogue_started signal dialogue_finished @export_file("*.json") var dialogue_file: String -var dialogue_keys = [] -var dialogue_name = "" -var current = 0 -var dialogue_text = "" +var dialogue_keys := [] +var dialogue_name := "" +var current := 0 +var dialogue_text := "" -func start_dialogue(): +func start_dialogue() -> void: dialogue_started.emit() current = 0 index_dialogue() @@ -19,7 +18,7 @@ func start_dialogue(): dialogue_name = dialogue_keys[current].name -func next_dialogue(): +func next_dialogue() -> void: current += 1 if current == dialogue_keys.size(): dialogue_finished.emit() @@ -28,17 +27,18 @@ func next_dialogue(): dialogue_name = dialogue_keys[current].name -func index_dialogue(): - var dialogue = load_dialogue(dialogue_file) +func index_dialogue() -> void: + var dialogue: Dictionary = load_dialogue(dialogue_file) dialogue_keys.clear() - for key in dialogue: + for key: String in dialogue: dialogue_keys.append(dialogue[key]) -func load_dialogue(file_path): - var file = FileAccess.open(file_path, FileAccess.READ) +func load_dialogue(file_path: String) -> Dictionary: + var file := FileAccess.open(file_path, FileAccess.READ) if file: - var test_json_conv = JSON.new() + var test_json_conv := JSON.new() test_json_conv.parse(file.get_as_text()) - var dialogue = test_json_conv.get_data() - return dialogue + return test_json_conv.data + + return {} diff --git a/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.tscn b/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.tscn index d3548eca..949a32fb 100644 --- a/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.tscn +++ b/2d/role_playing_game/dialogue/dialogue_player/dialogue_player.tscn @@ -1,6 +1,6 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=2 format=3 uid="uid://cid4iajexfsg2"] -[ext_resource path="res://dialogue/dialogue_player/dialogue_player.gd" type="Script" id=1] +[ext_resource type="Script" path="res://dialogue/dialogue_player/dialogue_player.gd" id="1"] [node name="DialoguePlayer" type="Node"] -script = ExtResource( 1 ) +script = ExtResource("1") diff --git a/2d/role_playing_game/dialogue/interface/interface.gd b/2d/role_playing_game/dialogue/interface/interface.gd index eefb8d2d..65f829fd 100644 --- a/2d/role_playing_game/dialogue/interface/interface.gd +++ b/2d/role_playing_game/dialogue/interface/interface.gd @@ -1,23 +1,23 @@ extends Control +var dialogue_node: Node = null -var dialogue_node = null +func _ready() -> void: + visible = false -func _ready(): - hide() - - -func show_dialogue(player, dialogue): - show() +func show_dialogue(player: Pawn, dialogue: Node) -> void: + visible = true $Button.grab_focus() dialogue_node = dialogue + for c in dialogue.get_signal_connection_list("dialogue_started"): if player == c.callable.get_object(): dialogue_node.start_dialogue() $Name.text = "[center]" + dialogue_node.dialogue_name + "[/center]" $Text.text = dialogue_node.dialogue_text return + dialogue_node.dialogue_started.connect(player.set_active.bind(false)) dialogue_node.dialogue_finished.connect(player.set_active.bind(true)) dialogue_node.dialogue_finished.connect(hide) @@ -27,13 +27,13 @@ func show_dialogue(player, dialogue): $Text.text = dialogue_node.dialogue_text -func _on_Button_button_up(): +func _on_Button_button_up() -> void: dialogue_node.next_dialogue() $Name.text = "[center]" + dialogue_node.dialogue_name + "[/center]" $Text.text = dialogue_node.dialogue_text -func _on_dialogue_finished(player): +func _on_dialogue_finished(player: Pawn) -> void: dialogue_node.dialogue_started.disconnect(player.set_active) dialogue_node.dialogue_finished.disconnect(player.set_active) dialogue_node.dialogue_finished.disconnect(hide) diff --git a/2d/role_playing_game/game.gd b/2d/role_playing_game/game.gd index f2010153..35b2b62e 100644 --- a/2d/role_playing_game/game.gd +++ b/2d/role_playing_game/game.gd @@ -1,14 +1,13 @@ extends Node - const PLAYER_WIN = "res://dialogue/dialogue_data/player_won.json" const PLAYER_LOSE = "res://dialogue/dialogue_data/player_lose.json" -@export var combat_screen: Node -@export var exploration_screen: Node +@export var combat_screen: Node2D +@export var exploration_screen: Node2D -func _ready(): +func _ready() -> void: combat_screen.combat_finished.connect(_on_combat_finished) for n in $Exploration/Grid.get_children(): @@ -21,7 +20,7 @@ func _ready(): remove_child(combat_screen) -func start_combat(combat_actors): +func start_combat(combat_actors: Array[PackedScene]) -> void: remove_child($Exploration) $AnimationPlayer.play("fade") await $AnimationPlayer.animation_finished @@ -31,19 +30,19 @@ func start_combat(combat_actors): $AnimationPlayer.play_backwards("fade") -func _on_opponent_dialogue_finished(opponent): +func _on_opponent_dialogue_finished(opponent: Pawn) -> void: if opponent.lost: return - var player = $Exploration/Grid/Player - var combatants = [player.combat_actor, opponent.combat_actor] + var player: Node2D = $Exploration/Grid/Player + var combatants: Array[PackedScene] = [player.combat_actor, opponent.combat_actor] start_combat(combatants) -func _on_combat_finished(winner, _loser): +func _on_combat_finished(winner: Combatant, _loser: Combatant) -> void: remove_child(combat_screen) $AnimationPlayer.play_backwards("fade") add_child(exploration_screen) - var dialogue = load("res://dialogue/dialogue_player/dialogue_player.tscn").instantiate() + var dialogue: Node = load("res://dialogue/dialogue_player/dialogue_player.tscn").instantiate() if winner.name == "Player": dialogue.dialogue_file = PLAYER_WIN @@ -51,7 +50,7 @@ func _on_combat_finished(winner, _loser): dialogue.dialogue_file = PLAYER_LOSE await $AnimationPlayer.animation_finished - var player = $Exploration/Grid/Player + var player: Pawn = $Exploration/Grid/Player exploration_screen.get_node("DialogueUI").show_dialogue(player, dialogue) combat_screen.clear_combat() await dialogue.dialogue_finished diff --git a/2d/role_playing_game/grid_movement/grid/grid.gd b/2d/role_playing_game/grid_movement/grid/grid.gd index 2baa7572..089e7145 100644 --- a/2d/role_playing_game/grid_movement/grid/grid.gd +++ b/2d/role_playing_game/grid_movement/grid/grid.gd @@ -1,38 +1,45 @@ extends TileMap +enum CellType { + ACTOR, + OBSTACLE, + OBJECT, +} -enum CellType { ACTOR, OBSTACLE, OBJECT } @export var dialogue_ui: Node - -func _ready(): +func _ready() -> void: for child in get_children(): set_cell(0, local_to_map(child.position), child.type, Vector2i.ZERO) -func get_cell_pawn(cell, type = CellType.ACTOR): +func get_cell_pawn(cell: Vector2i, type: CellType = CellType.ACTOR) -> Node2D: for node in get_children(): if node.type != type: continue if local_to_map(node.position) == cell: - return(node) + return node + + return null -func request_move(pawn, direction: Vector2i): - var cell_start = local_to_map(pawn.position) - var cell_target = cell_start + direction +func request_move(pawn: Pawn, direction: Vector2i) -> Vector2i: + var cell_start := local_to_map(pawn.position) + var cell_target := cell_start + direction - var cell_tile_id = get_cell_source_id(0, cell_target) + var cell_tile_id := get_cell_source_id(0, cell_target) match cell_tile_id: -1: set_cell(0, cell_target, CellType.ACTOR, Vector2i.ZERO) set_cell(0, cell_start, -1, Vector2i.ZERO) return map_to_local(cell_target) CellType.OBJECT, CellType.ACTOR: - var target_pawn = get_cell_pawn(cell_target, cell_tile_id) + var target_pawn := get_cell_pawn(cell_target, cell_tile_id) #print("Cell %s contains %s" % [cell_target, target_pawn.name]) if not target_pawn.has_node("DialoguePlayer"): - return + return Vector2i.ZERO dialogue_ui.show_dialogue(pawn, target_pawn.get_node("DialoguePlayer")) + + return Vector2i.ZERO diff --git a/2d/role_playing_game/grid_movement/pawns/actor.gd b/2d/role_playing_game/grid_movement/pawns/actor.gd index 62d9f5d4..a30776a7 100644 --- a/2d/role_playing_game/grid_movement/pawns/actor.gd +++ b/2d/role_playing_game/grid_movement/pawns/actor.gd @@ -1,6 +1,5 @@ extends Pawn - var lost = false @onready var Grid = get_parent() diff --git a/2d/role_playing_game/grid_movement/pawns/opponent.gd b/2d/role_playing_game/grid_movement/pawns/opponent.gd index 8f3b7c81..fbaa9db2 100644 --- a/2d/role_playing_game/grid_movement/pawns/opponent.gd +++ b/2d/role_playing_game/grid_movement/pawns/opponent.gd @@ -1,11 +1,7 @@ extends Pawn - -#warning-ignore:unused_class_variable @export var combat_actor: PackedScene -#warning-ignore:unused_class_variable -var lost = false +var lost := false - -func _ready(): +func _ready() -> void: set_process(false) diff --git a/2d/role_playing_game/grid_movement/pawns/pawn.gd b/2d/role_playing_game/grid_movement/pawns/pawn.gd index 9195c5d3..2e599bae 100644 --- a/2d/role_playing_game/grid_movement/pawns/pawn.gd +++ b/2d/role_playing_game/grid_movement/pawns/pawn.gd @@ -1,15 +1,17 @@ class_name Pawn extends Node2D +enum CellType { + ACTOR, + OBSTACLE, + OBJECT, +} -enum CellType { ACTOR, OBSTACLE, OBJECT } -#warning-ignore:unused_class_variable -@export var type: CellType = CellType.ACTOR +@export var type := CellType.ACTOR -var active = true: set = set_active +var active := true: set = set_active - -func set_active(value): +func set_active(value: bool) -> void: active = value set_process(value) set_process_input(value) diff --git a/2d/role_playing_game/grid_movement/pawns/walker.gd b/2d/role_playing_game/grid_movement/pawns/walker.gd index 0aa13f67..57715de9 100644 --- a/2d/role_playing_game/grid_movement/pawns/walker.gd +++ b/2d/role_playing_game/grid_movement/pawns/walker.gd @@ -1,53 +1,53 @@ extends Pawn - -#warning-ignore:unused_class_variable @export var combat_actor: PackedScene -#warning-ignore:unused_class_variable -var lost = false -var grid_size -@onready var parent = get_parent() -@onready var animation_playback = $AnimationTree.get("parameters/playback") -@onready var walk_animation_time = $AnimationPlayer.get_animation("walk").length + +var lost := false +var grid_size: float + +@onready var parent := get_parent() +@onready var animation_playback: AnimationNodeStateMachinePlayback = $AnimationTree.get("parameters/playback") +@onready var walk_animation_time: float = $AnimationPlayer.get_animation("walk").length -func _ready(): +func _ready() -> void: update_look_direction(Vector2.RIGHT) grid_size = parent.tile_set.tile_size.x -func _process(_delta): - var input_direction = get_input_direction() +func _process(_delta: float) -> void: + var input_direction := get_input_direction() if input_direction.is_zero_approx(): return + update_look_direction(input_direction) - var target_position = parent.request_move(self, input_direction) + var target_position: Vector2 = parent.request_move(self, input_direction) if target_position: move_to(target_position) elif active: bump() -func get_input_direction(): +func get_input_direction() -> Vector2: return Vector2( - Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), - Input.get_action_strength("move_down") - Input.get_action_strength("move_up") + Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), + Input.get_action_strength("move_down") - Input.get_action_strength("move_up") ) -func update_look_direction(direction): +func update_look_direction(direction: Vector2) -> void: $Pivot/Sprite2D.rotation = direction.angle() -func move_to(target_position): +func move_to(target_position: Vector2) -> void: set_process(false) - var move_direction = (target_position - position).normalized() + var move_direction := (target_position - position).normalized() animation_playback.start("walk") var tween := create_tween() tween.set_ease(Tween.EASE_IN) - var end = $Pivot.position + move_direction * grid_size + var end: Vector2 = $Pivot.position + move_direction * grid_size tween.tween_property($Pivot, "position", end, walk_animation_time) await tween.finished @@ -57,7 +57,8 @@ func move_to(target_position): set_process(true) -func bump(): + +func bump() -> void: set_process(false) animation_playback.start("bump") await $AnimationTree.animation_finished diff --git a/2d/role_playing_game/project.godot b/2d/role_playing_game/project.godot index a8bfdd0e..c33b19a1 100644 --- a/2d/role_playing_game/project.godot +++ b/2d/role_playing_game/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://game.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.svg" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1280 diff --git a/2d/screen_space_shaders/project.godot b/2d/screen_space_shaders/project.godot index 1bfee650..26ed8337 100644 --- a/2d/screen_space_shaders/project.godot +++ b/2d/screen_space_shaders/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://screen_shaders.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=800 diff --git a/2d/screen_space_shaders/screen_shaders.gd b/2d/screen_space_shaders/screen_shaders.gd index 4d5dda35..2e2db590 100644 --- a/2d/screen_space_shaders/screen_shaders.gd +++ b/2d/screen_space_shaders/screen_shaders.gd @@ -1,29 +1,28 @@ extends Control -@onready var effect = $Effect -@onready var effects = $Effects -@onready var picture = $Picture -@onready var pictures = $Pictures +@onready var effect: OptionButton = $Effect +@onready var effects: Control = $Effects +@onready var picture: OptionButton = $Picture +@onready var pictures: Control = $Pictures - -func _ready(): +func _ready() -> void: for c in pictures.get_children(): picture.add_item("PIC: " + String(c.get_name())) for c in effects.get_children(): effect.add_item("FX: " + String(c.get_name())) -func _on_picture_item_selected(ID): - for c in range(pictures.get_child_count()): - if ID == c: +func _on_picture_item_selected(id: int) -> void: + for c in pictures.get_child_count(): + if id == c: pictures.get_child(c).show() else: pictures.get_child(c).hide() -func _on_effect_item_selected(ID): - for c in range(effects.get_child_count()): - if ID == c: +func _on_effect_item_selected(id: int) -> void: + for c in effects.get_child_count(): + if id == c: effects.get_child(c).show() else: effects.get_child(c).hide() diff --git a/2d/screen_space_shaders/screen_shaders.tscn b/2d/screen_space_shaders/screen_shaders.tscn index ef36ef86..eebcbd10 100644 --- a/2d/screen_space_shaders/screen_shaders.tscn +++ b/2d/screen_space_shaders/screen_shaders.tscn @@ -93,39 +93,55 @@ size_flags_horizontal = 2 size_flags_vertical = 2 [node name="Burano" type="TextureRect" parent="Pictures"] -layout_mode = 0 -offset_right = 40.0 -offset_bottom = 40.0 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 2 size_flags_vertical = 2 texture = ExtResource("2") +stretch_mode = 6 [node name="Roby" type="TextureRect" parent="Pictures"] visible = false -layout_mode = 0 -offset_right = 40.0 -offset_bottom = 40.0 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 2 size_flags_vertical = 2 texture = ExtResource("3") +stretch_mode = 6 [node name="Mountains" type="TextureRect" parent="Pictures"] visible = false -layout_mode = 0 -offset_right = 40.0 -offset_bottom = 40.0 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 2 size_flags_vertical = 2 texture = ExtResource("4") +stretch_mode = 6 [node name="Forest" type="TextureRect" parent="Pictures"] visible = false -layout_mode = 0 -offset_right = 40.0 -offset_bottom = 40.0 +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 2 size_flags_vertical = 2 texture = ExtResource("5") +stretch_mode = 6 [node name="Effects" type="Control" parent="."] layout_mode = 1 diff --git a/2d/skeleton/level/level.gd b/2d/skeleton/level/level.gd index df1657d7..1d924fba 100644 --- a/2d/skeleton/level/level.gd +++ b/2d/skeleton/level/level.gd @@ -1,10 +1,10 @@ extends Node2D -func _ready(): - var camera = find_child("Camera2D") - var min_pos = $CameraLimit_min.global_position - var max_pos = $CameraLimit_max.global_position - camera.limit_left = min_pos.x - camera.limit_top = min_pos.y - camera.limit_right = max_pos.x - camera.limit_bottom = max_pos.y +func _ready() -> void: + var camera: Camera2D = find_child("Camera2D") + var min_pos: Vector2 = $CameraLimit_min.global_position + var max_pos: Vector2 = $CameraLimit_max.global_position + camera.limit_left = round(min_pos.x) + camera.limit_top = round(min_pos.y) + camera.limit_right = round(max_pos.x) + camera.limit_bottom = round(max_pos.y) diff --git a/2d/skeleton/player/player.gd b/2d/skeleton/player/player.gd index 4ffab0f1..c8d33def 100644 --- a/2d/skeleton/player/player.gd +++ b/2d/skeleton/player/player.gd @@ -16,21 +16,21 @@ const JUMP_VELOCITY = -400.0 ## Maximum speed at which the player can fall. const TERMINAL_VELOCITY = 400 -var falling_slow = false -var falling_fast = false -var no_move_horizontal_time = 0.0 +var falling_slow := false +var falling_fast := false +var no_move_horizontal_time := 0.0 -@onready var gravity = ProjectSettings.get_setting("physics/2d/default_gravity") -@onready var sprite = $Sprite2D -@onready var sprite_scale = sprite.scale.x +@onready var gravity := float(ProjectSettings.get_setting("physics/2d/default_gravity")) +@onready var sprite: Node2D = $Sprite2D +@onready var sprite_scale := sprite.scale.x -func _ready(): +func _ready() -> void: $AnimationTree.active = true func _physics_process(delta: float) -> void: - var is_jumping = false + var is_jumping := false if Input.is_action_just_pressed("jump"): is_jumping = try_jump() elif Input.is_action_just_released("jump") and velocity.y < 0.0: @@ -98,4 +98,5 @@ func try_jump() -> bool: if is_on_floor(): velocity.y = JUMP_VELOCITY return true + return false diff --git a/2d/skeleton/player/player.tscn b/2d/skeleton/player/player.tscn index 8d2a88e3..eecd14c6 100644 --- a/2d/skeleton/player/player.tscn +++ b/2d/skeleton/player/player.tscn @@ -1770,9 +1770,6 @@ libraries = { [node name="AnimationTree" type="AnimationTree" parent="."] active = false -libraries = { -"": SubResource("AnimationLibrary_sx6h1") -} tree_root = SubResource("23") anim_player = NodePath("../AnimationPlayer") parameters/jump/active = false @@ -1803,13 +1800,11 @@ rest = Transform2D(1, 0, 0, 1, -3, -11) [node name="Chest" type="Bone2D" parent="Sprite2D/Skeleton2D/Hip"] position = Vector2(0, -32) rotation = -0.00707523 -scale = Vector2(1, 1) rest = Transform2D(1, 0, 0, 1, 0, -32) [node name="Head" type="Bone2D" parent="Sprite2D/Skeleton2D/Hip/Chest"] position = Vector2(0, -160) rotation = 0.0539257 -scale = Vector2(1, 1) rest = Transform2D(1, 0, 0, 1, 0, -160) [node name="Chin" type="Bone2D" parent="Sprite2D/Skeleton2D/Hip/Chest/Head"] @@ -1831,7 +1826,6 @@ rest = Transform2D(1, 0, 0, 1, -11, 97) [node name="RightHand" type="Bone2D" parent="Sprite2D/Skeleton2D/Hip/Chest/RightArm/RightForearm"] position = Vector2(13, 94) rotation = 1.22745 -scale = Vector2(1, 1) rest = Transform2D(0.336639, 0.941634, -0.941634, 0.336639, 13, 94) auto_calculate_length_and_angle = false length = 16.0 diff --git a/2d/skeleton/project.godot b/2d/skeleton/project.godot index 265ee44d..7701b362 100644 --- a/2d/skeleton/project.godot +++ b/2d/skeleton/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://level.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1920 diff --git a/2d/sprite_shaders/project.godot b/2d/sprite_shaders/project.godot index 0a32a00d..1001e553 100644 --- a/2d/sprite_shaders/project.godot +++ b/2d/sprite_shaders/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://sprite_shaders.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/2d/tween/main.gd b/2d/tween/main.gd index eb4b0d91..622797ac 100644 --- a/2d/tween/main.gd +++ b/2d/tween/main.gd @@ -1,16 +1,23 @@ extends Node -@onready var icon: Sprite2D = %Icon -@onready var icon_start_position = icon.position - -@onready var countdown_label = %CountdownLabel -@onready var path: Path2D = $Path2D -@onready var progress = %Progress - var tween: Tween var sub_tween: Tween -func start_animation(): +@onready var icon: Sprite2D = %Icon +@onready var icon_start_position := icon.position + +@onready var countdown_label: Label = %CountdownLabel +@onready var path: Path2D = $Path2D +@onready var progress: TextureProgressBar = %Progress + +func _process(_delta: float) -> void: + if not tween or not tween.is_running(): + return + + progress.value = tween.get_total_elapsed_time() + + +func start_animation() -> void: # Reset the icon to original state. reset() # Create the Tween. Also sets the initial animation speed. @@ -29,7 +36,7 @@ func start_animation(): # tween_*() methods return a Tweener object. Its methods can also be chained, but # it's stored in a variable here for readability (chained lines tend to be long). # Note the usage of ^"NodePath". A regular "String" is accepted too, but it's very slightly slower. - var tweener = tween.tween_property(icon, ^"position", Vector2(400, 250), 1.0) + var tweener := tween.tween_property(icon, ^"position", Vector2(400, 250), 1.0) tweener.set_ease(%Ease1.selected) tweener.set_trans(%Trans1.selected) @@ -43,12 +50,12 @@ func start_animation(): if is_step_enabled("MoveRight", 1.0): # as_relative() makes the value relative, so in this case it moves the icon # 200 pixels from the previous position. - var tweener = tween.tween_property(icon, ^"position:x", 200.0, 1.0).as_relative() + var tweener := tween.tween_property(icon, ^"position:x", 200.0, 1.0).as_relative() tweener.set_ease(%Ease3.selected) tweener.set_trans(%Trans3.selected) if is_step_enabled("Roll", 0.0): # parallel() makes the Tweener run in parallel to the previous one. - var tweener = tween.parallel().tween_property(icon, ^"rotation", TAU, 1.0) + var tweener := tween.parallel().tween_property(icon, ^"rotation", TAU, 1.0) tweener.set_ease(%Ease3.selected) tweener.set_trans(%Trans3.selected) @@ -92,8 +99,10 @@ func start_animation(): # Method tweening is useful for animating values that can't be directly interpolated. # It can be used for remapping and some very advanced animations. # Here it's used for moving sprite along a path, using inline lambda function. - var tweener = tween.tween_method(func(v): icon.position = path.position + path.curve.sample_baked(v), - 0.0, path.curve.get_baked_length(), 3.0).set_delay(0.5) + var tweener := tween.tween_method( + func(v: float) -> void: + icon.position = path.position + path.curve.sample_baked(v), 0.0, path.curve.get_baked_length(), 3.0 + ).set_delay(0.5) tweener.set_ease(%Ease7.selected) tweener.set_trans(%Trans7.selected) @@ -126,10 +135,12 @@ func start_animation(): if %Reset.button_pressed: tween.tween_callback(reset.bind(true)) -func do_countdown(v): - countdown_label.text = str(v) -func reset(soft := false): +func do_countdown(number: int) -> void: + countdown_label.text = str(number) + + +func reset(soft: bool = false) -> void: icon.position = icon_start_position icon.self_modulate = Color.WHITE icon.rotation = 0 @@ -151,12 +162,15 @@ func reset(soft := false): progress.max_value = 0 -func is_step_enabled(step, expected_time): - var enabled = get_node("%" + step).button_pressed + +func is_step_enabled(step: String, expected_time: float) -> bool: + var enabled: bool = get_node("%" + step).button_pressed if enabled: progress.max_value += expected_time + return enabled + func pause_resume() -> void: if tween and tween.is_valid(): if tween.is_running(): @@ -170,24 +184,22 @@ func pause_resume() -> void: else: sub_tween.play() + func kill_tween() -> void: if tween: tween.kill() if sub_tween: sub_tween.kill() + func speed_changed(value: float) -> void: if tween: tween.set_speed_scale(value) if sub_tween: sub_tween.set_speed_scale(value) + %SpeedLabel.text = str("x", value) -func inifnite_toggled(button_pressed: bool) -> void: + +func infinite_toggled(button_pressed: bool) -> void: %Loops.editable = not button_pressed - -func _process(delta: float) -> void: - if not tween or not tween.is_running(): - return - - progress.value = tween.get_total_elapsed_time() diff --git a/2d/tween/main.tscn b/2d/tween/main.tscn index 3bdcc9a1..cdada367 100644 --- a/2d/tween/main.tscn +++ b/2d/tween/main.tscn @@ -451,7 +451,7 @@ vertical_alignment = 1 position = Vector2(473, 204) curve = SubResource("Curve2D_7nae7") -[connection signal="toggled" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer3/Infinite" to="." method="inifnite_toggled"] +[connection signal="toggled" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer3/Infinite" to="." method="infinite_toggled"] [connection signal="pressed" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer3/Button" to="." method="start_animation"] [connection signal="pressed" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer4/Button2" to="." method="pause_resume"] [connection signal="pressed" from="VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer4/Button3" to="." method="kill_tween"] diff --git a/2d/tween/project.godot b/2d/tween/project.godot index 2206b642..09d1eb4b 100644 --- a/2d/tween/project.godot +++ b/2d/tween/project.godot @@ -19,6 +19,10 @@ run/low_processor_mode=true config/icon="res://icon.webp" target_fps=60 +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/antialiasing/anti_aliasing.gd b/3d/antialiasing/anti_aliasing.gd index 8ef4b2b1..d55cad47 100644 --- a/3d/antialiasing/anti_aliasing.gd +++ b/3d/antialiasing/anti_aliasing.gd @@ -1,24 +1,22 @@ extends Node - const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = -TAU / 16 # This must be kept in sync with RotationX. -var rot_y = TAU / 8 # This must be kept in sync with CameraHolder. -var camera_distance = 2.0 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := -TAU / 16 # This must be kept in sync with RotationX. +var rot_y := TAU / 8 # This must be kept in sync with CameraHolder. +var camera_distance := 2.0 +var base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D -@onready var fps_label = $FPSLabel +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D +@onready var fps_label: Label = $FPSLabel - -func _ready(): +func _ready() -> void: # Disable V-Sync to uncap framerate on supported platforms. This makes performance comparison # easier on high-end machines that easily reach the monitor's refresh rate. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) @@ -28,10 +26,10 @@ func _ready(): get_viewport().size_changed.connect(_on_viewport_size_changed) -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -43,7 +41,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clamp(rot_x, -1.57, 0) @@ -51,11 +49,11 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, camera_distance, 10 * delta) fps_label.text = "%d FPS (%.2f mspf)" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()] @@ -66,37 +64,37 @@ func _process(delta): -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 -func _on_msaa_item_selected(index): +func _on_msaa_item_selected(index: int) -> void: # Multi-sample anti-aliasing. High quality, but slow. It also does not smooth out the edges of # transparent (alpha scissor) textures. - get_viewport().msaa_3d = index + get_viewport().msaa_3d = index as Viewport.MSAA -func _on_limit_fps_scale_value_changed(value): +func _on_limit_fps_scale_value_changed(value: float) -> void: # The rendering FPS affects the appearance of TAA, as higher framerates allow it to converge faster. # On high refresh rate monitors, TAA ghosting issues may appear less noticeable as a result # (if the GPU can keep up). $Antialiasing/LimitFPSContainer/Value.text = str(value) - Engine.max_fps = value + Engine.max_fps = roundi(value) -func _on_render_scale_value_changed(value): +func _on_render_scale_value_changed(value: float) -> void: get_viewport().scaling_3d_scale = value $Antialiasing/RenderScaleContainer/Value.text = "%d%%" % (value * 100) # Update viewport resolution text. @@ -106,13 +104,13 @@ func _on_render_scale_value_changed(value): $Antialiasing/FSRSharpness.visible = get_viewport().scaling_3d_mode == Viewport.SCALING_3D_MODE_FSR and value < 1.0 -func _on_amd_fidelityfx_fsr1_toggled(button_pressed): +func _on_amd_fidelityfx_fsr1_toggled(button_pressed: bool) -> void: get_viewport().scaling_3d_mode = Viewport.SCALING_3D_MODE_FSR if button_pressed else Viewport.SCALING_3D_MODE_BILINEAR # FSR 1.0 is only effective if render scale is below 100%, so hide the setting if at native resolution or higher. $Antialiasing/FSRSharpness.visible = button_pressed -func _on_fsr_sharpness_item_selected(index): +func _on_fsr_sharpness_item_selected(index: int) -> void: # *Lower* values of FSR sharpness are sharper. match index: 0: @@ -127,11 +125,14 @@ func _on_fsr_sharpness_item_selected(index): get_viewport().fsr_sharpness = 0.0 -func _on_viewport_size_changed(): - $ViewportResolution.text = "Viewport resolution: %d×%d" % [get_viewport().size.x * get_viewport().scaling_3d_scale, get_viewport().size.y * get_viewport().scaling_3d_scale] +func _on_viewport_size_changed() -> void: + $ViewportResolution.text = "Viewport resolution: %d×%d" % [ + get_viewport().size.x * get_viewport().scaling_3d_scale, + get_viewport().size.y * get_viewport().scaling_3d_scale, + ] -func _on_v_sync_item_selected(index): +func _on_v_sync_item_selected(index: int) -> void: # Vsync is enabled by default. # Vertical synchronization locks framerate and makes screen tearing not visible at the cost of # higher input latency and stuttering when the framerate target is not met. @@ -146,13 +147,13 @@ func _on_v_sync_item_selected(index): DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED) -func _on_taa_item_selected(index): +func _on_taa_item_selected(index: int) -> void: # Temporal antialiasing. Smooths out everything including specular aliasing, but can introduce # ghosting artifacts and blurring in motion. Moderate performance cost. get_viewport().use_taa = index == 1 -func _on_fxaa_item_selected(index): +func _on_fxaa_item_selected(index: int) -> void: # Fast approximate anti-aliasing. Much faster than MSAA (and works on alpha scissor edges), # but blurs the whole scene rendering slightly. get_viewport().screen_space_aa = int(index == 1) as Viewport.ScreenSpaceAA diff --git a/3d/antialiasing/project.godot b/3d/antialiasing/project.godot index c667f6fb..53c4513f 100644 --- a/3d/antialiasing/project.godot +++ b/3d/antialiasing/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://anti_aliasing.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/antialiasing/textures/checker.png.import b/3d/antialiasing/textures/checker.png.import index 85954ad8..cfc5488d 100644 --- a/3d/antialiasing/textures/checker.png.import +++ b/3d/antialiasing/textures/checker.png.import @@ -3,20 +3,19 @@ importer="texture" type="CompressedTexture2D" uid="uid://chjqieyps5n5r" -path.s3tc="res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.s3tc.ctex" +path="res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.ctex" metadata={ -"imported_formats": ["s3tc_bptc"], -"vram_texture": true +"vram_texture": false } [deps] source_file="res://textures/checker.png" -dest_files=["res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.s3tc.ctex"] +dest_files=["res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.ctex"] [params] -compress/mode=2 +compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 diff --git a/3d/csg/csg.gd b/3d/csg/csg.gd index 6d60ca5c..914a6dd9 100644 --- a/3d/csg/csg.gd +++ b/3d/csg/csg.gd @@ -4,28 +4,27 @@ const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = -TAU / 16 # This must be kept in sync with RotationX. -var rot_y = TAU / 8 # This must be kept in sync with CameraHolder. -var camera_distance = 4.0 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := -TAU / 16 # This must be kept in sync with RotationX. +var rot_y := TAU / 8 # This must be kept in sync with CameraHolder. +var camera_distance := 4.0 +var base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D - -func _ready(): +func _ready() -> void: camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -37,7 +36,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clamp(rot_x, -1.57, 0) @@ -45,26 +44,26 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, camera_distance, 10 * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 diff --git a/3d/csg/csg.tscn b/3d/csg/csg.tscn index e338fbea..fc8ba689 100644 --- a/3d/csg/csg.tscn +++ b/3d/csg/csg.tscn @@ -67,7 +67,7 @@ directional_shadow_fade_start = 1.0 directional_shadow_max_distance = 38.0 [node name="CameraHolder" type="Node3D" parent="."] -transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0.125, 0) +transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0.125, -12) [node name="RotationX" type="Node3D" parent="CameraHolder"] diff --git a/3d/csg/project.godot b/3d/csg/project.godot index 166f2f83..b59e83ac 100644 --- a/3d/csg/project.godot +++ b/3d/csg/project.godot @@ -19,6 +19,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/decals/project.godot b/3d/decals/project.godot index 03ddff6a..e52c7c84 100644 --- a/3d/decals/project.godot +++ b/3d/decals/project.godot @@ -16,6 +16,10 @@ run/main_scene="res://test.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/decals/test.tscn b/3d/decals/test.tscn index 6682d583..34af1d1f 100644 --- a/3d/decals/test.tscn +++ b/3d/decals/test.tscn @@ -193,10 +193,10 @@ environment = SubResource("11") script = ExtResource("18") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "move" libraries = { "": SubResource("AnimationLibrary_ecfcr") } +autoplay = "move" [node name="StaticBody3d" type="StaticBody3D" parent="."] @@ -229,12 +229,12 @@ fov = 70.0 [node name="PlasmaEmission" type="Decal" parent="."] transform = Transform3D(0.707107, 0, 0.707107, 0, 1, 0, -0.707107, 0, 0.707107, 0, 0, 12) -extents = Vector3(0.2, 0.1, 0.2) +size = Vector3(0.4, 0.2, 0.4) texture_emission = ExtResource("3_h6kom") [node name="PlasmaStain" type="Decal" parent="."] transform = Transform3D(0.707107, 0, 0.707107, 0, 1, 0, -0.707107, 0, 0.707107, 0, 0, 12) -extents = Vector3(0.2, 0.1, 0.2) +size = Vector3(0.4, 0.2, 0.4) texture_albedo = ExtResource("4_86yk0") normal_fade = 0.5 @@ -246,25 +246,25 @@ mesh = SubResource("15") [node name="PlasmaStain2" type="Decal" parent="Testers/BulletPlasmaDecals"] transform = Transform3D(0.818988, 0.544513, -0.181012, -0.544512, 0.637975, -0.544512, -0.181012, 0.544513, 0.818988, -0.343497, 0.0645585, 0.508513) -extents = Vector3(0.05, 0.1, 0.05) +size = Vector3(0.1, 0.2, 0.1) texture_albedo = ExtResource("4_86yk0") normal_fade = 0.5 [node name="PlasmaStain3" type="Decal" parent="Testers/BulletPlasmaDecals"] transform = Transform3D(0.322374, -0.258134, -0.910737, -0.372803, 0.849727, -0.372803, 0.870111, 0.459707, 0.177697, 0.0179672, 0.0645585, 0.457714) -extents = Vector3(0.05, 0.1, 0.05) +size = Vector3(0.1, 0.2, 0.1) texture_albedo = ExtResource("4_86yk0") normal_fade = 0.5 [node name="PlasmaStain4" type="Decal" parent="Testers/BulletPlasmaDecals"] transform = Transform3D(0.322374, -0.258134, -0.910737, -0.372803, 0.849727, -0.372803, 0.870111, 0.459707, 0.177697, -0.279583, 0.0645585, 0.135519) -extents = Vector3(0.05, 0.1, 0.05) +size = Vector3(0.1, 0.2, 0.1) texture_albedo = ExtResource("4_86yk0") normal_fade = 0.5 [node name="PlasmaStain5" type="Decal" parent="Testers/BulletPlasmaDecals"] transform = Transform3D(-0.781204, 0.439943, -0.442913, 0.177237, 0.836588, 0.51837, 0.598589, 0.326452, -0.731519, 0.147337, 0.0645586, 0.171896) -extents = Vector3(0.05, 0.1, 0.05) +size = Vector3(0.1, 0.2, 0.1) texture_albedo = ExtResource("4_86yk0") normal_fade = 0.5 @@ -278,56 +278,56 @@ modulate = Color(0.0235294, 0.121569, 1, 1) [node name="PurplePaint" type="Decal" parent="Testers/PaintDecals"] transform = Transform3D(0.866025, 0, -0.5, 0, 1, 0, 0.5, 0, 0.866025, 0.430567, -2.0597e-08, -0.314452) -extents = Vector3(0.5, 1, 0.5) +size = Vector3(1, 2, 1) texture_albedo = ExtResource("5_1d4vo") texture_normal = ExtResource("6_qfx85") modulate = Color(0.662745, 0.247059, 1, 1) [node name="CyanPaint" type="Decal" parent="Testers/PaintDecals"] transform = Transform3D(0.991172, 0, 0.132585, 0.0845414, 0.770335, -0.63201, -0.102135, 0.637639, 0.763534, -0.436872, 1.2699e-08, 0.06318) -extents = Vector3(0.5, 1, 0.5) +size = Vector3(1, 2, 1) texture_albedo = ExtResource("5_1d4vo") texture_normal = ExtResource("6_qfx85") modulate = Color(0.164706, 0.741176, 0.776471, 1) [node name="Arrow1" type="Decal" parent="Testers/PaintDecals"] transform = Transform3D(-0.707107, 0, 0.707107, 0.244151, 0.938499, 0.244151, -0.663619, 0.345282, -0.663619, 1.18236, 0, 1.04792) -extents = Vector3(0.4, 1, 0.25) +size = Vector3(0.8, 2, 0.5) texture_albedo = ExtResource("7_4xxma") texture_normal = ExtResource("8_40dxq") modulate = Color(1, 0.0705882, 0.0980392, 1) [node name="Arrow2" type="Decal" parent="Testers/PaintDecals"] transform = Transform3D(-0.783964, 0, -0.620806, 0, 1, 0, 0.620806, 0, -0.783964, 1.28394, 7.53473e-08, -1.18734) -extents = Vector3(0.4, 1, 0.18) +size = Vector3(0.8, 2, 0.36) texture_albedo = ExtResource("7_4xxma") texture_normal = ExtResource("8_40dxq") modulate = Color(1, 0.0705882, 0.0980392, 1) [node name="Arrow3" type="Decal" parent="Testers/PaintDecals"] transform = Transform3D(0.741555, 0, -0.670893, 0, 1, 0, 0.670893, 0, 0.741555, -1.15131, 2.10201e-07, -1.38808) -extents = Vector3(0.5, 1, 0.25) +size = Vector3(1, 2, 0.5) texture_albedo = ExtResource("7_4xxma") texture_normal = ExtResource("8_40dxq") modulate = Color(1, 0.0705882, 0.0980392, 1) [node name="Arrow4" type="Decal" parent="Testers/PaintDecals"] transform = Transform3D(0.79937, 0, 0.600839, 0, 1, 0, -0.600839, 0, 0.79937, -1.34612, 3.63008e-07, 1.11909) -extents = Vector3(0.4, 1, 0.25) +size = Vector3(0.8, 2, 0.5) texture_albedo = ExtResource("7_4xxma") texture_normal = ExtResource("8_40dxq") modulate = Color(1, 0.0705882, 0.0980392, 1) [node name="WaterPuddle" type="Decal" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 4) -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) texture_albedo = ExtResource("9_o80vp") texture_orm = ExtResource("10_rt6a0") albedo_mix = 0.0 [node name="ReflectionProbe" type="ReflectionProbe" parent="Testers/WaterPuddle"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) -extents = Vector3(8, 8, 8) +size = Vector3(16, 16, 16) box_projection = true [node name="CircleBlobShadow" type="MeshInstance3D" parent="Testers"] @@ -348,7 +348,7 @@ mesh = SubResource("18") [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_wbqnf") texture_normal = ExtResource("12_mlk6d") upper_fade = 0.0 @@ -356,7 +356,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot"] transform = Transform3D(-4.37114e-08, -1.62921e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.62921e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("13_p1ikw") texture_normal = ExtResource("14_yj8ff") upper_fade = 0.0 @@ -367,7 +367,7 @@ transform = Transform3D(0.866025, 0, -0.5, 0, 1, 0, 0.5, 0, 0.866025, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot2"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -375,7 +375,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot2"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -386,7 +386,7 @@ transform = Transform3D(0.5, 0, -0.866025, 0, 1, 0, 0.866025, 0, 0.5, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot3"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -394,7 +394,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot3"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -405,7 +405,7 @@ transform = Transform3D(0, 0, -1, 0, 1, 0, 1, 0, 0, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot4"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_wbqnf") texture_normal = ExtResource("12_mlk6d") upper_fade = 0.0 @@ -413,7 +413,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot4"] transform = Transform3D(-4.37114e-08, -1.62921e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.62921e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("13_p1ikw") texture_normal = ExtResource("14_yj8ff") upper_fade = 0.0 @@ -424,7 +424,7 @@ transform = Transform3D(-0.5, 0, -0.866025, 0, 1, 0, 0.866025, 0, -0.5, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot6"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -432,7 +432,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot6"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 2.38419e-07, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -443,7 +443,7 @@ transform = Transform3D(-0.866025, 0, -0.5, 0, 1, 0, 0.5, 0, -0.866025, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot7"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -451,7 +451,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot7"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 1.19209e-07, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -462,7 +462,7 @@ transform = Transform3D(-1, 0, 8.74228e-08, 0, 1, 0, -8.74228e-08, 0, -1, 0, 0, [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot8"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_wbqnf") texture_normal = ExtResource("12_mlk6d") upper_fade = 0.0 @@ -470,7 +470,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot8"] transform = Transform3D(-4.37114e-08, -1.62921e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.62921e-07, 8.146e-09, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("13_p1ikw") texture_normal = ExtResource("14_yj8ff") upper_fade = 0.0 @@ -481,7 +481,7 @@ transform = Transform3D(-0.866025, 0, 0.5, 0, 1, 0, -0.5, 0, -0.866025, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot9"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -489,7 +489,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot9"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 2.38419e-07, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -500,7 +500,7 @@ transform = Transform3D(-0.5, 0, 0.866025, 0, 1, 0, -0.866025, 0, -0.5, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot10"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -508,7 +508,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot10"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -519,7 +519,7 @@ transform = Transform3D(1.31134e-07, 0, 1, 0, 1, 0, -1, 0, 1.31134e-07, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot11"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_wbqnf") texture_normal = ExtResource("12_mlk6d") upper_fade = 0.0 @@ -527,7 +527,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot11"] transform = Transform3D(-4.37114e-08, -1.62921e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.62921e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("13_p1ikw") texture_normal = ExtResource("14_yj8ff") upper_fade = 0.0 @@ -538,7 +538,7 @@ transform = Transform3D(0.5, 0, 0.866025, 0, 1, 0, -0.866025, 0, 0.5, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot12"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -546,7 +546,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot12"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -557,7 +557,7 @@ transform = Transform3D(0.866025, 0, 0.5, 0, 1, 0, -0.5, 0, 0.866025, 0, 0, 0) [node name="Decal" type="Decal" parent="Testers/ScifiDecals/Pivot13"] transform = Transform3D(1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, -5.96046e-08, 0.888154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("15_ct5bp") texture_normal = ExtResource("16_0mhgx") upper_fade = 0.0 @@ -565,7 +565,7 @@ lower_fade = 0.0 [node name="Decal2" type="Decal" parent="Testers/ScifiDecals/Pivot13"] transform = Transform3D(-4.37114e-08, -1.19209e-07, -1, -1, 7.1215e-15, 4.37114e-08, 0, 1, -1.19209e-07, 0, 0.4, 0.838154) -extents = Vector3(0.2, 0.05, 0.2) +size = Vector3(0.4, 0.1, 0.4) texture_albedo = ExtResource("11_bbefl") texture_normal = ExtResource("12_tq8hn") upper_fade = 0.0 @@ -582,14 +582,14 @@ mesh = SubResource("20") [node name="Decal" type="Decal" parent="Testers/BuffEffect"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -extents = Vector3(1, 0.1, 1) +size = Vector3(2, 0.2, 2) texture_albedo = SubResource("GradientTexture1D_a7rt8") lower_fade = 2.0 cull_mask = 1048573 [node name="Noise" type="Decal" parent="Testers/BuffEffect"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.76837e-07, 0, 4.76837e-07) -extents = Vector3(1.2, 1.2, 1.2) +size = Vector3(2.4, 2.4, 2.4) texture_emission = SubResource("22") emission_energy = 0.25 upper_fade = 1.0 @@ -609,20 +609,20 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -12) [node name="AlbedoAndNormal" type="Decal" parent="Testers/NormalMapDecals"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.5, 0, 0.5) -extents = Vector3(0.45, 1, 0.45) +size = Vector3(0.9, 2, 0.9) texture_albedo = ExtResource("13_ef2mf") texture_normal = ExtResource("14_je5ga") [node name="NormalOnly" type="Decal" parent="Testers/NormalMapDecals"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -0.5, 0, -0.5) -extents = Vector3(0.45, 1, 0.45) +size = Vector3(0.9, 2, 0.9) texture_albedo = ExtResource("13_ef2mf") texture_normal = ExtResource("14_je5ga") albedo_mix = 0.0 [node name="Metallic" type="Decal" parent="Testers/NormalMapDecals"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0.5, 0, -0.5) -extents = Vector3(0.45, 1, 0.45) +size = Vector3(0.9, 2, 0.9) texture_albedo = ExtResource("13_ef2mf") texture_orm = ExtResource("14_je5ga") @@ -631,7 +631,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -16) [node name="FadeInstant" type="Decal" parent="Testers/DistanceFade"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 0, 1) -extents = Vector3(0.45, 1, 0.45) +size = Vector3(0.9, 2, 0.9) texture_albedo = ExtResource("13_ef2mf") texture_normal = ExtResource("14_je5ga") distance_fade_enabled = true @@ -640,7 +640,7 @@ distance_fade_length = 0.0 [node name="FadeShort" type="Decal" parent="Testers/DistanceFade"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -4.37114e-08, 0, 0) -extents = Vector3(0.45, 1, 0.45) +size = Vector3(0.9, 2, 0.9) texture_albedo = ExtResource("13_ef2mf") texture_normal = ExtResource("14_je5ga") distance_fade_enabled = true @@ -649,7 +649,7 @@ distance_fade_length = 4.0 [node name="FadeLong" type="Decal" parent="Testers/DistanceFade"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -8.74228e-08, 0, -1) -extents = Vector3(0.45, 1, 0.45) +size = Vector3(0.9, 2, 0.9) texture_albedo = ExtResource("13_ef2mf") texture_normal = ExtResource("14_je5ga") distance_fade_enabled = true @@ -752,18 +752,20 @@ text = "Decal Filter Mode:" [node name="OptionButton" type="OptionButton" parent="DecalFilterMode"] layout_mode = 2 -item_count = 5 +item_count = 6 selected = 4 popup/item_0/text = "Nearest" popup/item_0/id = 0 -popup/item_1/text = "Nearest + Mipmaps" +popup/item_1/text = "Linear" popup/item_1/id = 1 -popup/item_2/text = "Linear" +popup/item_2/text = "Nearest + Mipmaps" popup/item_2/id = 2 popup/item_3/text = "Linear + Mipmaps" popup/item_3/id = 3 -popup/item_4/text = "Linear + Mipmaps + 16× Anisotropic" +popup/item_4/text = "Nearest + Mipmaps + 16× Anisotropic" popup/item_4/id = 4 +popup/item_5/text = "Linear + Mipmaps + 16× Anisotropic" +popup/item_5/id = 5 [connection signal="pressed" from="Previous" to="." method="_on_previous_pressed"] [connection signal="pressed" from="Next" to="." method="_on_next_pressed"] diff --git a/3d/decals/tester.gd b/3d/decals/tester.gd index 2eba14f7..85022b54 100644 --- a/3d/decals/tester.gd +++ b/3d/decals/tester.gd @@ -4,38 +4,38 @@ const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = deg_to_rad(-22.5) # This must be kept in sync with RotationX. -var rot_y = deg_to_rad(90) # This must be kept in sync with CameraHolder. -var zoom = 1.5 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := deg_to_rad(-22.5) # This must be kept in sync with RotationX. +var rot_y := deg_to_rad(90) # This must be kept in sync with CameraHolder. +var zoom := 1.5 +var base_height: = int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D -func _ready(): +func _ready() -> void: camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() - if event.is_action_pressed("place_decal"): - var origin = camera.global_position - var target = camera.project_position(get_viewport().get_mouse_position(), 100) + if event.is_action_pressed(&"place_decal"): + var origin := camera.global_position + var target := camera.project_position(get_viewport().get_mouse_position(), 100) - var query = PhysicsRayQueryParameters3D.create(origin, target) - var result = camera.get_world_3d().direct_space_state.intersect_ray(query) + var query := PhysicsRayQueryParameters3D.create(origin, target) + var result := camera.get_world_3d().direct_space_state.intersect_ray(query) if not result.is_empty(): - var decal = preload("res://decal.tscn").instantiate() + var decal := preload("res://decal.tscn").instantiate() add_child(decal) decal.get_node("Decal").modulate = Color(1.0,0.0,0) decal.position = result["position"] @@ -50,7 +50,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clampf(rot_x, deg_to_rad(-90), 0) @@ -58,31 +58,31 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, zoom, 10 * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 -func _on_decal_filter_mode_item_selected(index): +func _on_decal_filter_mode_item_selected(index: int) -> void: # Indices in the OptionButton match RenderingServer decal filtering constants. RenderingServer.decals_set_filter(index) diff --git a/3d/decals/textures/checker.png.import b/3d/decals/textures/checker.png.import index 85954ad8..cfc5488d 100644 --- a/3d/decals/textures/checker.png.import +++ b/3d/decals/textures/checker.png.import @@ -3,20 +3,19 @@ importer="texture" type="CompressedTexture2D" uid="uid://chjqieyps5n5r" -path.s3tc="res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.s3tc.ctex" +path="res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.ctex" metadata={ -"imported_formats": ["s3tc_bptc"], -"vram_texture": true +"vram_texture": false } [deps] source_file="res://textures/checker.png" -dest_files=["res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.s3tc.ctex"] +dest_files=["res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.ctex"] [params] -compress/mode=2 +compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 diff --git a/3d/global_illumination/camera.gd b/3d/global_illumination/camera.gd index f9d393a2..f6ad1f4e 100644 --- a/3d/global_illumination/camera.gd +++ b/3d/global_illumination/camera.gd @@ -3,15 +3,14 @@ extends Camera3D const MOUSE_SENSITIVITY = 0.002 const MOVE_SPEED = 1.5 -var rot = Vector3() -var velocity = Vector3() +var rot := Vector3() +var velocity := Vector3() - -func _ready(): +func _ready() -> void: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) -func _input(event): +func _input(event: InputEvent) -> void: # Mouse look (only if the mouse is captured). if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: # Horizontal mouse look. @@ -27,8 +26,8 @@ func _input(event): Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) -func _process(delta): - var motion = Vector3( +func _process(delta: float) -> void: + var motion := Vector3( Input.get_axis(&"move_left", &"move_right"), 0, Input.get_axis(&"move_forward", &"move_back") diff --git a/3d/global_illumination/project.godot b/3d/global_illumination/project.godot index da4a9e7d..d905a2d1 100644 --- a/3d/global_illumination/project.godot +++ b/3d/global_illumination/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://test.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/global_illumination/test.gd b/3d/global_illumination/test.gd index 3ceb2633..4f230146 100644 --- a/3d/global_illumination/test.gd +++ b/3d/global_illumination/test.gd @@ -48,29 +48,29 @@ const SSIL_MODE_TEXTS = [ "SSAO + SSIL (Slow)", ] -var gi_mode = GIMode.NONE -var reflection_probe_mode = ReflectionProbeMode.NONE -var ssil_mode = SSILMode.NONE +var gi_mode := GIMode.NONE +var reflection_probe_mode := ReflectionProbeMode.NONE +var ssil_mode := SSILMode.NONE -@onready var environment = $WorldEnvironment.environment -@onready var gi_mode_label = $GIMode -@onready var reflection_probe_mode_label = $ReflectionProbeMode -@onready var reflection_probe = $Camera/ReflectiveSphere/ReflectionProbe -@onready var ssil_mode_label = $SSILMode +@onready var environment: Environment = $WorldEnvironment.environment +@onready var gi_mode_label: Label = $GIMode +@onready var reflection_probe_mode_label: Label = $ReflectionProbeMode +@onready var reflection_probe: ReflectionProbe = $Camera/ReflectiveSphere/ReflectionProbe +@onready var ssil_mode_label: Label = $SSILMode # Several copies of the level mesh are required to cycle between different GI modes. -@onready var zdm2_no_lightmap = $Zdm2NoLightmap -@onready var zdm2_lightmap_all = $Zdm2LightmapAll -@onready var zdm2_lightmap_indirect = $Zdm2LightmapIndirect +@onready var zdm2_no_lightmap: Node3D = $Zdm2NoLightmap +@onready var zdm2_lightmap_all: Node3D = $Zdm2LightmapAll +@onready var zdm2_lightmap_indirect: Node3D = $Zdm2LightmapIndirect -func _ready(): +func _ready() -> void: set_gi_mode(gi_mode) set_reflection_probe_mode(reflection_probe_mode) set_ssil_mode(ssil_mode) -func _input(event): +func _input(event: InputEvent) -> void: if event.is_action_pressed("cycle_gi_mode"): set_gi_mode(wrapi(gi_mode + 1, 0, GIMode.MAX)) @@ -81,7 +81,7 @@ func _input(event): set_ssil_mode(wrapi(ssil_mode + 1, 0, SSILMode.MAX)) -func set_gi_mode(p_gi_mode): +func set_gi_mode(p_gi_mode: GIMode) -> void: gi_mode = p_gi_mode gi_mode_label.text = "Global illumination: %s " % GI_MODE_TEXTS[gi_mode] @@ -179,7 +179,7 @@ func set_gi_mode(p_gi_mode): $CornerSpotLight.light_bake_mode = Light3D.BAKE_DYNAMIC -func set_reflection_probe_mode(p_reflection_probe_mode): +func set_reflection_probe_mode(p_reflection_probe_mode: ReflectionProbeMode) -> void: reflection_probe_mode = p_reflection_probe_mode reflection_probe_mode_label.text = "Reflection probe: %s " % REFLECTION_PROBE_MODE_TEXTS[reflection_probe_mode] @@ -195,7 +195,7 @@ func set_reflection_probe_mode(p_reflection_probe_mode): reflection_probe.update_mode = ReflectionProbe.UPDATE_ALWAYS -func set_ssil_mode(p_ssil_mode): +func set_ssil_mode(p_ssil_mode: SSILMode) -> void: ssil_mode = p_ssil_mode ssil_mode_label.text = "Screen-space lighting effects: %s " % SSIL_MODE_TEXTS[ssil_mode] diff --git a/3d/kinematic_character/cubelib.tres b/3d/kinematic_character/cubelib.tres index a26a25f9..0e41d4d9 100644 --- a/3d/kinematic_character/cubelib.tres +++ b/3d/kinematic_character/cubelib.tres @@ -2,7 +2,7 @@ [ext_resource type="ArrayMesh" uid="uid://ba7dqpj07mlsy" path="res://models/cube.mesh" id="1"] -[sub_resource type="Image" id="Image_tihji"] +[sub_resource type="Image" id="Image_56rhf"] data = { "data": PackedByteArray(76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 66, 41, 73, 255, 68, 42, 73, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 55, 32, 61, 255, 62, 36, 68, 255, 70, 43, 77, 255, 72, 45, 78, 255, 67, 43, 73, 255, 63, 41, 68, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 57, 33, 63, 255, 59, 34, 65, 255, 65, 38, 72, 255, 73, 45, 80, 255, 76, 47, 82, 255, 72, 47, 78, 255, 69, 46, 75, 255, 63, 41, 69, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 59, 34, 64, 255, 61, 35, 67, 255, 63, 36, 69, 255, 66, 38, 73, 255, 75, 44, 81, 255, 78, 47, 84, 255, 76, 49, 83, 255, 75, 51, 82, 255, 69, 46, 75, 255, 62, 41, 69, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 54, 32, 59, 255, 60, 35, 65, 255, 62, 36, 68, 255, 63, 37, 70, 255, 62, 36, 69, 255, 69, 40, 76, 255, 80, 48, 87, 255, 82, 50, 89, 255, 81, 52, 88, 255, 80, 54, 87, 255, 75, 51, 81, 255, 68, 46, 75, 255, 63, 42, 68, 255, 55, 35, 61, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 52, 31, 57, 255, 57, 34, 63, 255, 64, 37, 70, 255, 62, 36, 69, 255, 62, 36, 69, 255, 68, 39, 75, 255, 77, 45, 84, 255, 88, 52, 94, 255, 89, 54, 96, 255, 85, 55, 92, 255, 83, 55, 90, 255, 81, 55, 87, 255, 75, 51, 81, 255, 68, 46, 74, 255, 61, 40, 67, 255, 54, 34, 59, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 48, 30, 53, 255, 51, 31, 56, 255, 54, 32, 59, 255, 61, 36, 67, 255, 63, 36, 69, 255, 62, 36, 69, 255, 70, 40, 77, 255, 74, 43, 81, 255, 79, 46, 87, 255, 87, 53, 95, 255, 90, 56, 97, 255, 91, 59, 99, 255, 85, 55, 93, 255, 85, 58, 92, 255, 81, 56, 87, 255, 73, 50, 80, 255, 67, 45, 73, 255, 60, 39, 65, 255, 53, 34, 58, 255, 46, 29, 51, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 46, 28, 51, 255, 50, 30, 55, 255, 54, 32, 59, 255, 59, 36, 65, 255, 64, 37, 70, 255, 65, 37, 72, 255, 72, 42, 80, 255, 76, 44, 84, 255, 76, 44, 84, 255, 82, 49, 90, 255, 94, 58, 103, 255, 97, 61, 105, 255, 95, 61, 103, 255, 91, 59, 98, 255, 88, 60, 96, 255, 86, 60, 93, 255, 79, 54, 85, 255, 72, 48, 78, 255, 67, 45, 73, 255, 60, 39, 65, 255, 52, 33, 57, 255, 45, 29, 50, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 45, 28, 49, 255, 48, 29, 53, 255, 55, 33, 60, 255, 60, 36, 65, 255, 64, 39, 70, 255, 68, 40, 74, 255, 75, 44, 83, 255, 78, 46, 85, 255, 75, 44, 84, 255, 78, 46, 87, 255, 85, 51, 93, 255, 93, 58, 103, 255, 99, 62, 107, 255, 101, 66, 110, 255, 96, 63, 104, 255, 92, 61, 100, 255, 90, 61, 97, 255, 85, 59, 92, 255, 77, 52, 84, 255, 73, 49, 79, 255, 67, 45, 72, 255, 58, 38, 63, 255, 49, 31, 54, 255, 43, 27, 47, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 38, 24, 41, 255, 45, 29, 49, 255, 50, 31, 54, 255, 54, 33, 59, 255, 59, 36, 64, 255, 63, 38, 69, 255, 68, 41, 74, 255, 75, 44, 82, 255, 77, 45, 85, 255, 76, 44, 84, 255, 80, 47, 88, 255, 80, 47, 89, 255, 86, 51, 95, 255, 98, 60, 106, 255, 102, 64, 110, 255, 105, 69, 114, 255, 101, 67, 110, 255, 95, 62, 103, 255, 93, 62, 100, 255, 90, 61, 97, 255, 82, 56, 89, 255, 76, 50, 82, 255, 72, 49, 78, 255, 64, 42, 69, 255, 53, 33, 58, 255, 46, 28, 50, 255, 41, 26, 45, 255, 38, 24, 42, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 35, 22, 39, 255, 41, 26, 45, 255, 50, 32, 54, 255, 54, 33, 59, 255, 59, 36, 64, 255, 62, 37, 68, 255, 67, 40, 73, 255, 72, 44, 79, 255, 75, 45, 83, 255, 78, 46, 85, 255, 82, 48, 90, 255, 83, 49, 92, 255, 82, 47, 91, 255, 92, 54, 101, 255, 101, 61, 108, 255, 105, 64, 113, 255, 109, 70, 119, 255, 105, 69, 114, 255, 100, 66, 109, 255, 95, 62, 103, 255, 94, 63, 101, 255, 89, 59, 95, 255, 80, 52, 86, 255, 76, 51, 82, 255, 69, 45, 75, 255, 56, 34, 61, 255, 49, 29, 54, 255, 44, 26, 48, 255, 43, 27, 47, 255, 37, 23, 40, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 29, 18, 32, 255, 34, 21, 37, 255, 37, 22, 41, 255, 44, 27, 48, 255, 51, 32, 56, 255, 57, 35, 62, 255, 61, 38, 68, 255, 66, 40, 72, 255, 71, 43, 78, 255, 73, 45, 81, 255, 77, 46, 85, 255, 82, 49, 90, 255, 88, 53, 96, 255, 85, 50, 95, 255, 86, 49, 96, 255, 94, 55, 104, 255, 102, 60, 111, 255, 104, 63, 114, 255, 112, 71, 122, 255, 110, 72, 119, 255, 104, 69, 113, 255, 99, 64, 107, 255, 93, 60, 101, 255, 92, 60, 99, 255, 87, 55, 94, 255, 81, 53, 87, 255, 73, 48, 80, 255, 62, 38, 67, 255, 53, 32, 59, 255, 48, 28, 53, 255, 46, 28, 50, 255, 43, 27, 46, 255, 35, 21, 38, 255, 30, 19, 33, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 28, 17, 31, 255, 33, 21, 37, 255, 38, 23, 41, 255, 41, 24, 45, 255, 48, 28, 52, 255, 55, 33, 60, 255, 61, 38, 67, 255, 65, 40, 72, 255, 70, 43, 77, 255, 72, 44, 79, 255, 76, 46, 83, 255, 81, 49, 89, 255, 88, 52, 96, 255, 88, 52, 97, 255, 88, 51, 98, 255, 92, 53, 101, 255, 97, 57, 107, 255, 106, 63, 115, 255, 111, 68, 121, 255, 116, 74, 127, 255, 114, 75, 124, 255, 109, 72, 119, 255, 103, 67, 112, 255, 95, 60, 104, 255, 91, 58, 99, 255, 89, 57, 97, 255, 86, 55, 93, 255, 78, 51, 85, 255, 68, 43, 74, 255, 60, 37, 65, 255, 53, 31, 58, 255, 48, 29, 53, 255, 46, 29, 50, 255, 39, 24, 42, 255, 32, 20, 36, 255, 28, 17, 31, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 27, 17, 29, 255, 33, 21, 36, 255, 38, 25, 42, 255, 41, 24, 45, 255, 45, 26, 50, 255, 53, 32, 58, 255, 61, 38, 67, 255, 65, 40, 71, 255, 69, 41, 75, 255, 72, 43, 79, 255, 76, 46, 84, 255, 80, 49, 88, 255, 86, 52, 94, 255, 89, 53, 98, 255, 93, 55, 102, 255, 98, 58, 108, 255, 97, 57, 107, 255, 101, 59, 111, 255, 117, 72, 127, 255, 123, 77, 134, 255, 121, 77, 131, 255, 119, 77, 129, 255, 111, 72, 121, 255, 105, 68, 115, 255, 99, 63, 108, 255, 92, 58, 101, 255, 90, 57, 98, 255, 87, 55, 94, 255, 83, 53, 90, 255, 74, 47, 81, 255, 65, 41, 71, 255, 59, 36, 65, 255, 53, 33, 59, 255, 48, 29, 53, 255, 44, 27, 48, 255, 37, 23, 41, 255, 31, 18, 34, 255, 26, 16, 28, 255, 21, 12, 23, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 20, 13, 22, 255, 26, 17, 28, 255, 32, 21, 35, 255, 39, 26, 42, 255, 42, 27, 46, 255, 44, 26, 49, 255, 51, 31, 56, 255, 58, 36, 64, 255, 63, 39, 69, 255, 68, 41, 75, 255, 73, 44, 80, 255, 76, 47, 84, 255, 79, 48, 87, 255, 85, 52, 94, 255, 90, 55, 99, 255, 96, 58, 105, 255, 102, 62, 112, 255, 102, 61, 112, 255, 100, 59, 110, 255, 107, 64, 117, 255, 120, 74, 130, 255, 128, 81, 139, 255, 123, 78, 134, 255, 122, 78, 133, 255, 114, 73, 124, 255, 105, 66, 115, 255, 101, 64, 110, 255, 95, 60, 104, 255, 90, 56, 98, 255, 87, 55, 95, 255, 85, 54, 92, 255, 79, 49, 85, 255, 70, 44, 77, 255, 63, 39, 69, 255, 58, 36, 64, 255, 53, 33, 58, 255, 47, 29, 52, 255, 41, 25, 45, 255, 35, 21, 39, 255, 29, 17, 31, 255, 24, 14, 26, 255, 20, 11, 21, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 19, 12, 20, 255, 25, 16, 27, 255, 31, 20, 33, 255, 38, 25, 41, 255, 45, 30, 48, 255, 47, 30, 51, 255, 50, 31, 55, 255, 57, 35, 62, 255, 61, 37, 67, 255, 67, 40, 73, 255, 73, 44, 80, 255, 77, 46, 84, 255, 79, 48, 86, 255, 85, 52, 93, 255, 91, 55, 100, 255, 96, 58, 105, 255, 103, 63, 112, 255, 106, 64, 116, 255, 103, 62, 114, 255, 106, 63, 116, 255, 111, 65, 120, 255, 122, 75, 132, 255, 129, 80, 140, 255, 128, 81, 139, 255, 124, 79, 135, 255, 119, 76, 129, 255, 110, 69, 119, 255, 102, 63, 111, 255, 97, 60, 106, 255, 91, 57, 100, 255, 87, 55, 96, 255, 85, 53, 93, 255, 82, 51, 89, 255, 74, 46, 81, 255, 66, 40, 72, 255, 61, 37, 67, 255, 57, 35, 62, 255, 50, 31, 55, 255, 45, 27, 49, 255, 39, 24, 43, 255, 33, 20, 37, 255, 28, 16, 30, 255, 23, 14, 26, 255, 18, 10, 20, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 12, 7, 13, 255, 17, 11, 19, 255, 23, 16, 25, 255, 29, 19, 32, 255, 35, 24, 38, 255, 42, 29, 46, 255, 49, 33, 53, 255, 52, 33, 56, 255, 56, 35, 61, 255, 61, 38, 66, 255, 65, 40, 71, 255, 71, 43, 78, 255, 76, 46, 83, 255, 81, 49, 89, 255, 84, 51, 93, 255, 89, 54, 98, 255, 96, 58, 105, 255, 104, 63, 113, 255, 110, 66, 120, 255, 107, 64, 117, 255, 108, 64, 118, 255, 112, 67, 122, 255, 115, 68, 126, 255, 122, 73, 137, 255, 127, 76, 141, 255, 130, 81, 140, 255, 126, 79, 136, 255, 122, 76, 132, 255, 116, 73, 126, 255, 108, 66, 116, 255, 101, 62, 110, 255, 95, 59, 104, 255, 90, 56, 98, 255, 85, 53, 93, 255, 82, 51, 90, 255, 77, 48, 84, 255, 70, 44, 77, 255, 65, 40, 71, 255, 60, 36, 65, 255, 55, 33, 60, 255, 48, 29, 53, 255, 42, 25, 46, 255, 37, 22, 41, 255, 32, 19, 35, 255, 27, 16, 29, 255, 21, 13, 24, 255, 16, 9, 17, 255, 10, 6, 11, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 10, 6, 11, 255, 16, 10, 17, 255, 22, 15, 23, 255, 28, 19, 30, 255, 33, 23, 36, 255, 40, 27, 43, 255, 46, 30, 50, 255, 53, 35, 58, 255, 57, 36, 62, 255, 61, 38, 67, 255, 64, 40, 70, 255, 69, 42, 75, 255, 73, 44, 80, 255, 80, 49, 88, 255, 84, 51, 92, 255, 88, 53, 96, 255, 94, 57, 103, 255, 105, 64, 114, 255, 111, 68, 122, 255, 110, 66, 120, 255, 110, 65, 120, 255, 112, 67, 123, 255, 115, 69, 127, 255, 118, 70, 131, 255, 129, 78, 143, 255, 131, 79, 144, 255, 130, 80, 140, 255, 129, 80, 139, 255, 123, 77, 133, 255, 121, 75, 130, 255, 112, 68, 120, 255, 107, 65, 116, 255, 101, 62, 110, 255, 94, 58, 102, 255, 89, 55, 97, 255, 83, 52, 91, 255, 79, 49, 86, 255, 73, 45, 80, 255, 69, 42, 75, 255, 64, 39, 70, 255, 59, 35, 64, 255, 52, 32, 57, 255, 47, 28, 51, 255, 41, 24, 45, 255, 35, 21, 38, 255, 29, 17, 32, 255, 24, 14, 26, 255, 19, 11, 21, 255, 14, 8, 15, 255, 9, 5, 10, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 8, 5, 9, 255, 14, 9, 15, 255, 20, 14, 22, 255, 26, 18, 28, 255, 32, 22, 35, 255, 38, 26, 41, 255, 44, 29, 47, 255, 50, 33, 54, 255, 58, 37, 62, 255, 62, 39, 67, 255, 65, 41, 71, 255, 67, 42, 74, 255, 72, 44, 79, 255, 77, 47, 84, 255, 81, 50, 89, 255, 88, 54, 96, 255, 93, 56, 102, 255, 103, 64, 113, 255, 113, 70, 123, 255, 113, 69, 123, 255, 111, 67, 122, 255, 113, 67, 123, 255, 116, 68, 126, 255, 118, 71, 131, 255, 124, 75, 137, 255, 136, 82, 148, 255, 137, 83, 149, 255, 133, 80, 142, 255, 132, 82, 142, 255, 123, 76, 134, 255, 121, 74, 130, 255, 116, 71, 125, 255, 110, 66, 119, 255, 108, 65, 118, 255, 99, 61, 109, 255, 93, 58, 102, 255, 88, 55, 96, 255, 81, 50, 89, 255, 77, 48, 84, 255, 72, 44, 79, 255, 68, 41, 74, 255, 63, 38, 69, 255, 55, 33, 61, 255, 50, 30, 55, 255, 45, 27, 49, 255, 40, 24, 44, 255, 33, 19, 36, 255, 26, 15, 28, 255, 21, 12, 23, 255, 17, 10, 19, 255, 12, 7, 13, 255, 8, 5, 9, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 12, 7, 13, 255, 18, 12, 19, 255, 24, 16, 26, 255, 31, 21, 33, 255, 37, 26, 40, 255, 43, 30, 47, 255, 49, 32, 53, 255, 56, 35, 60, 255, 61, 39, 66, 255, 65, 41, 70, 255, 68, 42, 74, 255, 71, 44, 78, 255, 74, 46, 82, 255, 78, 48, 86, 255, 84, 52, 92, 255, 92, 56, 101, 255, 103, 63, 112, 255, 110, 68, 120, 255, 115, 71, 125, 255, 114, 69, 125, 255, 115, 69, 126, 255, 117, 69, 127, 255, 119, 71, 130, 255, 122, 73, 134, 255, 129, 78, 141, 255, 138, 83, 151, 255, 137, 82, 150, 255, 133, 81, 143, 255, 132, 80, 141, 255, 127, 77, 136, 255, 123, 75, 132, 255, 118, 72, 127, 255, 113, 69, 122, 255, 109, 66, 119, 255, 105, 63, 114, 255, 96, 58, 105, 255, 88, 54, 97, 255, 83, 52, 91, 255, 78, 49, 86, 255, 74, 45, 81, 255, 71, 43, 78, 255, 66, 39, 72, 255, 59, 36, 65, 255, 52, 32, 57, 255, 47, 28, 51, 255, 43, 26, 47, 255, 39, 23, 43, 255, 32, 18, 35, 255, 24, 14, 27, 255, 19, 11, 21, 255, 15, 9, 17, 255, 11, 7, 12, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 15, 10, 17, 255, 22, 14, 24, 255, 28, 19, 30, 255, 35, 24, 38, 255, 41, 28, 45, 255, 48, 32, 51, 255, 54, 35, 58, 255, 58, 37, 63, 255, 62, 39, 68, 255, 66, 41, 72, 255, 69, 43, 75, 255, 72, 45, 79, 255, 76, 48, 84, 255, 80, 49, 88, 255, 92, 56, 100, 255, 103, 63, 112, 255, 109, 67, 118, 255, 114, 71, 125, 255, 118, 73, 128, 255, 118, 72, 129, 255, 120, 72, 131, 255, 119, 70, 129, 255, 121, 72, 132, 255, 127, 76, 138, 255, 134, 81, 143, 255, 143, 86, 155, 255, 142, 86, 155, 255, 133, 81, 146, 255, 132, 80, 142, 255, 128, 77, 137, 255, 123, 74, 132, 255, 122, 74, 131, 255, 117, 71, 126, 255, 111, 67, 121, 255, 109, 66, 120, 255, 102, 61, 111, 255, 88, 53, 97, 255, 84, 51, 93, 255, 78, 48, 86, 255, 76, 47, 84, 255, 73, 45, 80, 255, 70, 43, 76, 255, 63, 38, 69, 255, 56, 34, 61, 255, 50, 31, 55, 255, 45, 27, 49, 255, 40, 24, 44, 255, 36, 21, 40, 255, 30, 17, 33, 255, 23, 13, 25, 255, 18, 10, 19, 255, 14, 8, 15, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 19, 12, 21, 255, 25, 16, 28, 255, 31, 21, 34, 255, 39, 26, 42, 255, 45, 31, 49, 255, 51, 34, 55, 255, 55, 35, 60, 255, 60, 37, 65, 255, 64, 40, 69, 255, 67, 42, 73, 255, 72, 45, 79, 255, 74, 46, 82, 255, 78, 48, 85, 255, 91, 55, 99, 255, 101, 62, 110, 255, 109, 67, 118, 255, 114, 71, 124, 255, 118, 73, 129, 255, 122, 75, 132, 255, 122, 74, 133, 255, 122, 73, 133, 255, 123, 73, 133, 255, 124, 75, 135, 255, 133, 81, 143, 255, 134, 82, 144, 255, 146, 90, 160, 255, 145, 90, 160, 255, 138, 84, 152, 255, 132, 81, 146, 255, 124, 76, 135, 255, 123, 74, 132, 255, 122, 73, 130, 255, 118, 71, 128, 255, 114, 69, 125, 255, 111, 67, 121, 255, 107, 65, 117, 255, 95, 57, 104, 255, 89, 53, 97, 255, 85, 51, 93, 255, 78, 48, 86, 255, 76, 47, 84, 255, 72, 44, 79, 255, 67, 41, 74, 255, 60, 37, 66, 255, 54, 33, 59, 255, 48, 29, 53, 255, 43, 26, 48, 255, 37, 22, 41, 255, 32, 19, 36, 255, 27, 16, 30, 255, 22, 13, 24, 255, 17, 10, 19, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 23, 15, 25, 255, 29, 19, 32, 255, 35, 23, 38, 255, 42, 28, 46, 255, 48, 31, 52, 255, 52, 33, 57, 255, 57, 36, 62, 255, 61, 38, 67, 255, 65, 40, 71, 255, 71, 44, 78, 255, 75, 46, 82, 255, 76, 46, 84, 255, 87, 52, 94, 255, 97, 60, 106, 255, 106, 65, 115, 255, 113, 70, 123, 255, 118, 73, 129, 255, 122, 75, 133, 255, 123, 76, 134, 255, 124, 75, 135, 255, 127, 76, 137, 255, 125, 75, 135, 255, 131, 80, 141, 255, 133, 81, 143, 255, 133, 81, 144, 255, 142, 84, 155, 255, 140, 84, 154, 255, 140, 85, 154, 255, 140, 85, 154, 255, 125, 77, 138, 255, 122, 74, 133, 255, 121, 73, 131, 255, 120, 72, 130, 255, 117, 71, 129, 255, 112, 68, 124, 255, 109, 66, 120, 255, 102, 61, 111, 255, 94, 56, 103, 255, 92, 55, 100, 255, 88, 54, 96, 255, 82, 50, 90, 255, 75, 46, 82, 255, 71, 43, 78, 255, 65, 39, 71, 255, 59, 36, 65, 255, 53, 32, 58, 255, 47, 28, 52, 255, 41, 25, 46, 255, 35, 20, 39, 255, 29, 17, 33, 255, 25, 15, 28, 255, 21, 13, 23, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 27, 18, 30, 255, 33, 22, 36, 255, 40, 26, 43, 255, 46, 30, 50, 255, 51, 33, 55, 255, 55, 35, 60, 255, 59, 37, 65, 255, 63, 39, 69, 255, 69, 43, 76, 255, 74, 46, 81, 255, 74, 45, 82, 255, 82, 49, 90, 255, 93, 56, 101, 255, 103, 63, 111, 255, 110, 68, 120, 255, 117, 72, 127, 255, 120, 74, 131, 255, 121, 73, 131, 255, 124, 76, 135, 255, 129, 79, 139, 255, 131, 80, 139, 255, 130, 80, 140, 255, 133, 81, 143, 255, 133, 80, 144, 255, 135, 83, 146, 255, 143, 90, 156, 255, 143, 89, 157, 255, 138, 84, 151, 255, 139, 85, 153, 255, 133, 81, 146, 255, 121, 75, 134, 255, 122, 75, 134, 255, 120, 73, 131, 255, 120, 72, 131, 255, 119, 72, 130, 255, 112, 68, 123, 255, 107, 65, 117, 255, 97, 58, 107, 255, 97, 59, 106, 255, 94, 57, 102, 255, 91, 56, 99, 255, 84, 51, 91, 255, 74, 45, 81, 255, 68, 41, 75, 255, 63, 38, 70, 255, 57, 35, 63, 255, 51, 31, 56, 255, 46, 28, 51, 255, 39, 23, 43, 255, 33, 19, 36, 255, 28, 17, 31, 255, 25, 15, 27, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 31, 20, 34, 255, 38, 25, 41, 255, 44, 29, 48, 255, 50, 33, 54, 255, 55, 35, 60, 255, 59, 37, 64, 255, 62, 39, 68, 255, 67, 42, 74, 255, 73, 45, 80, 255, 75, 45, 83, 255, 78, 47, 86, 255, 88, 53, 96, 255, 97, 59, 105, 255, 105, 64, 114, 255, 112, 69, 123, 255, 118, 72, 128, 255, 117, 71, 127, 255, 121, 74, 131, 255, 130, 81, 140, 255, 133, 82, 142, 255, 134, 82, 142, 255, 135, 82, 144, 255, 134, 82, 144, 255, 133, 82, 144, 255, 134, 83, 146, 255, 145, 91, 159, 255, 144, 90, 158, 255, 133, 82, 147, 255, 137, 84, 150, 255, 134, 81, 147, 255, 125, 77, 138, 255, 121, 75, 134, 255, 122, 75, 133, 255, 119, 74, 130, 255, 122, 74, 133, 255, 117, 70, 128, 255, 112, 68, 122, 255, 100, 60, 110, 255, 95, 57, 105, 255, 99, 60, 107, 255, 96, 59, 104, 255, 91, 56, 99, 255, 84, 52, 91, 255, 75, 46, 82, 255, 68, 41, 74, 255, 62, 37, 68, 255, 55, 33, 60, 255, 48, 29, 53, 255, 43, 26, 48, 255, 36, 21, 39, 255, 31, 18, 34, 255, 28, 17, 31, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 36, 23, 39, 255, 42, 28, 46, 255, 48, 32, 52, 255, 54, 36, 59, 255, 58, 37, 64, 255, 61, 38, 66, 255, 66, 41, 72, 255, 73, 45, 80, 255, 78, 47, 85, 255, 81, 48, 89, 255, 83, 50, 91, 255, 90, 54, 98, 255, 96, 58, 106, 255, 106, 65, 116, 255, 112, 68, 122, 255, 117, 71, 128, 255, 119, 73, 129, 255, 125, 79, 136, 255, 131, 83, 143, 255, 136, 84, 145, 255, 137, 83, 145, 255, 134, 82, 144, 255, 133, 82, 144, 255, 138, 85, 149, 255, 138, 85, 150, 255, 136, 87, 151, 255, 132, 84, 147, 255, 138, 85, 152, 255, 137, 84, 150, 255, 134, 82, 147, 255, 130, 80, 143, 255, 123, 76, 136, 255, 123, 76, 135, 255, 123, 77, 134, 255, 118, 74, 129, 255, 119, 73, 130, 255, 114, 69, 125, 255, 107, 65, 117, 255, 95, 57, 106, 255, 100, 61, 109, 255, 100, 61, 109, 255, 96, 60, 105, 255, 90, 55, 98, 255, 83, 51, 90, 255, 76, 47, 82, 255, 68, 41, 74, 255, 60, 36, 66, 255, 53, 32, 58, 255, 44, 26, 49, 255, 38, 22, 43, 255, 34, 20, 37, 255, 31, 19, 34, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 40, 26, 43, 255, 46, 30, 50, 255, 52, 34, 57, 255, 57, 37, 62, 255, 59, 37, 65, 255, 64, 40, 70, 255, 72, 44, 79, 255, 78, 47, 85, 255, 84, 51, 91, 255, 87, 52, 95, 255, 89, 53, 97, 255, 88, 53, 97, 255, 99, 60, 109, 255, 107, 64, 117, 255, 114, 70, 125, 255, 118, 74, 129, 255, 121, 76, 132, 255, 128, 81, 139, 255, 136, 86, 147, 255, 136, 84, 146, 255, 135, 83, 144, 255, 133, 82, 144, 255, 139, 86, 150, 255, 143, 87, 153, 255, 153, 98, 169, 255, 219, 159, 236, 255, 229, 167, 245, 255, 176, 115, 191, 255, 138, 85, 152, 255, 136, 83, 150, 255, 134, 82, 148, 255, 132, 80, 145, 255, 125, 78, 137, 255, 125, 78, 136, 255, 123, 77, 134, 255, 118, 74, 128, 255, 117, 72, 128, 255, 110, 67, 120, 255, 105, 63, 115, 255, 101, 61, 111, 255, 102, 63, 112, 255, 100, 62, 109, 255, 95, 59, 103, 255, 88, 54, 95, 255, 82, 51, 89, 255, 75, 46, 82, 255, 66, 40, 72, 255, 59, 36, 64, 255, 50, 30, 55, 255, 42, 24, 46, 255, 37, 22, 41, 255, 34, 20, 37, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 43, 27, 47, 255, 49, 32, 54, 255, 56, 37, 61, 255, 59, 38, 65, 255, 64, 40, 69, 255, 70, 42, 75, 255, 75, 45, 82, 255, 81, 49, 89, 255, 87, 53, 96, 255, 91, 55, 99, 255, 94, 57, 103, 255, 96, 58, 105, 255, 105, 64, 115, 255, 110, 68, 120, 255, 114, 72, 124, 255, 119, 76, 130, 255, 125, 79, 136, 255, 130, 82, 142, 255, 134, 85, 146, 255, 134, 84, 145, 255, 135, 83, 145, 255, 139, 85, 149, 255, 141, 86, 156, 255, 175, 117, 191, 255, 162, 105, 178, 255, 166, 106, 182, 255, 168, 108, 184, 255, 178, 117, 193, 255, 198, 136, 214, 255, 150, 92, 161, 255, 137, 83, 150, 255, 138, 84, 150, 255, 133, 81, 145, 255, 126, 78, 137, 255, 125, 79, 136, 255, 123, 77, 133, 255, 119, 74, 130, 255, 113, 70, 123, 255, 109, 67, 119, 255, 105, 64, 115, 255, 103, 62, 112, 255, 103, 63, 112, 255, 99, 61, 108, 255, 92, 57, 101, 255, 85, 53, 93, 255, 79, 48, 86, 255, 72, 44, 79, 255, 64, 38, 69, 255, 56, 34, 62, 255, 47, 27, 51, 255, 40, 23, 45, 255, 38, 23, 41, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 46, 29, 50, 255, 54, 35, 59, 255, 60, 39, 65, 255, 64, 40, 70, 255, 69, 43, 74, 255, 73, 44, 79, 255, 77, 46, 84, 255, 84, 50, 92, 255, 88, 53, 97, 255, 95, 57, 104, 255, 99, 60, 109, 255, 103, 63, 112, 255, 106, 66, 116, 255, 109, 69, 119, 255, 117, 74, 127, 255, 128, 82, 138, 255, 126, 79, 138, 255, 130, 83, 142, 255, 134, 85, 147, 255, 136, 84, 147, 255, 139, 85, 149, 255, 152, 93, 167, 255, 185, 122, 201, 255, 160, 98, 175, 255, 157, 98, 173, 255, 157, 98, 173, 255, 157, 98, 173, 255, 152, 94, 168, 255, 156, 96, 171, 255, 189, 124, 200, 255, 156, 95, 167, 255, 139, 84, 152, 255, 136, 83, 149, 255, 131, 81, 142, 255, 126, 78, 136, 255, 122, 76, 133, 255, 115, 71, 125, 255, 113, 70, 123, 255, 110, 68, 119, 255, 107, 66, 117, 255, 105, 64, 114, 255, 102, 63, 112, 255, 101, 62, 110, 255, 96, 59, 105, 255, 89, 55, 97, 255, 81, 50, 88, 255, 74, 45, 80, 255, 66, 40, 72, 255, 59, 35, 64, 255, 51, 30, 56, 255, 44, 26, 49, 255, 40, 24, 44, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 50, 32, 55, 255, 58, 37, 63, 255, 64, 41, 69, 255, 69, 43, 74, 255, 73, 45, 79, 255, 77, 47, 83, 255, 81, 49, 89, 255, 87, 52, 95, 255, 93, 56, 102, 255, 98, 60, 108, 255, 100, 61, 109, 255, 104, 64, 113, 255, 109, 68, 118, 255, 112, 71, 122, 255, 122, 78, 133, 255, 127, 81, 138, 255, 128, 81, 140, 255, 133, 84, 146, 255, 132, 84, 145, 255, 143, 88, 157, 255, 172, 106, 187, 255, 172, 107, 187, 255, 165, 100, 180, 255, 164, 99, 179, 255, 159, 96, 174, 255, 158, 98, 173, 255, 152, 94, 167, 255, 141, 84, 156, 255, 143, 85, 157, 255, 152, 91, 164, 255, 167, 103, 177, 255, 170, 105, 179, 255, 143, 89, 153, 255, 134, 84, 147, 255, 128, 79, 139, 255, 121, 73, 130, 255, 116, 71, 125, 255, 111, 68, 120, 255, 111, 68, 120, 255, 108, 68, 118, 255, 104, 66, 114, 255, 104, 64, 114, 255, 100, 61, 109, 255, 97, 59, 105, 255, 93, 57, 101, 255, 85, 52, 92, 255, 75, 46, 82, 255, 68, 41, 75, 255, 61, 36, 67, 255, 54, 32, 59, 255, 48, 28, 53, 255, 43, 25, 47, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 55, 34, 59, 255, 62, 39, 67, 255, 67, 42, 72, 255, 72, 45, 77, 255, 75, 46, 81, 255, 80, 49, 86, 255, 85, 51, 92, 255, 91, 55, 100, 255, 98, 59, 108, 255, 101, 62, 110, 255, 105, 65, 114, 255, 106, 65, 115, 255, 109, 68, 119, 255, 113, 71, 124, 255, 122, 78, 133, 255, 128, 82, 139, 255, 134, 85, 146, 255, 132, 84, 145, 255, 152, 94, 167, 255, 175, 109, 191, 255, 163, 98, 178, 255, 161, 97, 176, 255, 163, 98, 178, 255, 160, 97, 176, 255, 161, 97, 176, 255, 152, 91, 167, 255, 138, 81, 154, 255, 142, 83, 155, 255, 148, 88, 160, 255, 155, 93, 166, 255, 152, 91, 164, 255, 157, 94, 168, 255, 161, 103, 176, 255, 150, 95, 163, 255, 132, 83, 144, 255, 123, 75, 133, 255, 115, 69, 123, 255, 114, 69, 123, 255, 110, 68, 119, 255, 109, 69, 119, 255, 107, 68, 117, 255, 105, 66, 114, 255, 101, 63, 110, 255, 95, 58, 103, 255, 94, 57, 102, 255, 88, 54, 96, 255, 80, 48, 87, 255, 72, 43, 78, 255, 65, 39, 71, 255, 58, 34, 63, 255, 52, 31, 57, 255, 47, 28, 51, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 58, 36, 63, 255, 65, 41, 70, 255, 70, 43, 75, 255, 73, 45, 79, 255, 78, 48, 84, 255, 83, 50, 89, 255, 86, 52, 94, 255, 94, 57, 103, 255, 97, 60, 106, 255, 102, 64, 111, 255, 103, 64, 112, 255, 104, 64, 112, 255, 110, 68, 119, 255, 115, 73, 125, 255, 125, 80, 137, 255, 135, 87, 147, 255, 137, 87, 150, 255, 160, 98, 176, 255, 168, 103, 184, 255, 159, 96, 175, 255, 154, 91, 170, 255, 158, 94, 173, 255, 164, 98, 179, 255, 164, 99, 180, 255, 149, 88, 165, 255, 138, 80, 154, 255, 143, 84, 159, 255, 150, 89, 165, 255, 152, 91, 164, 255, 146, 86, 158, 255, 142, 85, 156, 255, 141, 86, 156, 255, 147, 91, 162, 255, 159, 101, 174, 255, 148, 93, 162, 255, 128, 79, 138, 255, 118, 71, 126, 255, 114, 68, 122, 255, 114, 69, 123, 255, 110, 69, 120, 255, 111, 71, 121, 255, 110, 70, 119, 255, 103, 65, 112, 255, 99, 62, 107, 255, 95, 58, 103, 255, 90, 55, 98, 255, 83, 50, 91, 255, 76, 45, 82, 255, 68, 40, 75, 255, 63, 38, 69, 255, 56, 33, 61, 255, 52, 31, 57, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 63, 40, 69, 255, 68, 43, 74, 255, 72, 45, 78, 255, 76, 46, 81, 255, 80, 48, 86, 255, 84, 50, 90, 255, 88, 54, 96, 255, 92, 58, 101, 255, 99, 62, 107, 255, 103, 64, 112, 255, 103, 63, 111, 255, 107, 65, 115, 255, 113, 69, 122, 255, 119, 76, 129, 255, 132, 85, 144, 255, 151, 97, 166, 255, 170, 107, 187, 255, 163, 100, 179, 255, 160, 97, 175, 255, 151, 89, 166, 255, 147, 86, 162, 255, 157, 95, 172, 255, 162, 97, 177, 255, 162, 97, 177, 255, 145, 85, 160, 255, 140, 81, 156, 255, 151, 89, 166, 255, 156, 93, 172, 255, 153, 91, 169, 255, 138, 82, 152, 255, 133, 81, 148, 255, 137, 84, 152, 255, 140, 86, 154, 255, 138, 85, 152, 255, 139, 87, 154, 255, 149, 93, 160, 255, 136, 84, 145, 255, 116, 70, 124, 255, 114, 69, 123, 255, 112, 71, 122, 255, 112, 71, 122, 255, 114, 73, 124, 255, 109, 69, 118, 255, 101, 64, 110, 255, 100, 63, 108, 255, 94, 58, 102, 255, 86, 52, 94, 255, 79, 47, 86, 255, 72, 43, 79, 255, 66, 39, 72, 255, 60, 36, 66, 255, 55, 32, 59, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 65, 41, 70, 255, 71, 44, 76, 255, 76, 47, 82, 255, 78, 47, 83, 255, 81, 48, 87, 255, 85, 52, 93, 255, 90, 56, 98, 255, 97, 61, 106, 255, 103, 65, 113, 255, 103, 64, 112, 255, 105, 63, 112, 255, 109, 66, 117, 255, 114, 70, 123, 255, 125, 79, 135, 255, 155, 99, 170, 255, 164, 104, 181, 255, 155, 96, 173, 255, 152, 91, 168, 255, 144, 85, 159, 255, 148, 88, 163, 255, 157, 95, 172, 255, 159, 96, 174, 255, 158, 95, 173, 255, 150, 87, 165, 255, 146, 85, 161, 255, 149, 88, 164, 255, 159, 95, 174, 255, 155, 92, 170, 255, 139, 81, 154, 255, 139, 81, 154, 255, 142, 84, 156, 255, 135, 82, 149, 255, 132, 80, 146, 255, 127, 77, 142, 255, 133, 80, 145, 255, 142, 86, 152, 255, 143, 87, 153, 255, 133, 80, 145, 255, 114, 68, 122, 255, 115, 72, 125, 255, 115, 73, 125, 255, 114, 73, 125, 255, 110, 70, 120, 255, 105, 67, 114, 255, 102, 65, 111, 255, 99, 62, 106, 255, 91, 55, 98, 255, 83, 49, 90, 255, 74, 44, 81, 255, 69, 41, 76, 255, 64, 38, 70, 255, 58, 35, 64, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 67, 40, 71, 255, 73, 45, 79, 255, 78, 47, 83, 255, 79, 48, 85, 255, 83, 50, 90, 255, 87, 54, 96, 255, 93, 58, 101, 255, 99, 62, 108, 255, 103, 64, 112, 255, 103, 62, 110, 255, 104, 62, 111, 255, 110, 66, 117, 255, 117, 73, 130, 255, 157, 100, 173, 255, 157, 99, 174, 255, 150, 91, 167, 255, 148, 89, 166, 255, 142, 84, 162, 255, 152, 93, 169, 255, 161, 99, 176, 255, 160, 98, 175, 255, 158, 95, 172, 255, 152, 89, 166, 255, 149, 87, 163, 255, 154, 91, 168, 255, 157, 94, 172, 255, 152, 90, 166, 255, 138, 80, 152, 255, 141, 83, 155, 255, 144, 85, 159, 255, 139, 81, 153, 255, 137, 80, 151, 255, 129, 77, 143, 255, 128, 75, 142, 255, 132, 77, 145, 255, 132, 77, 145, 255, 135, 80, 146, 255, 135, 80, 146, 255, 134, 79, 145, 255, 132, 84, 144, 255, 120, 77, 131, 255, 119, 76, 129, 255, 111, 71, 121, 255, 106, 67, 116, 255, 106, 67, 114, 255, 102, 64, 109, 255, 96, 58, 101, 255, 86, 52, 92, 255, 78, 46, 85, 255, 72, 43, 79, 255, 67, 40, 74, 255, 61, 37, 68, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 70, 42, 75, 255, 75, 45, 80, 255, 78, 47, 84, 255, 77, 47, 85, 255, 83, 51, 91, 255, 87, 54, 96, 255, 94, 59, 103, 255, 101, 62, 109, 255, 104, 63, 111, 255, 105, 64, 113, 255, 107, 64, 114, 255, 116, 70, 129, 255, 134, 83, 148, 255, 148, 94, 163, 255, 155, 98, 171, 255, 161, 103, 175, 255, 162, 104, 177, 255, 157, 99, 173, 255, 157, 98, 172, 255, 154, 95, 170, 255, 151, 91, 166, 255, 148, 86, 162, 255, 144, 83, 158, 255, 150, 89, 164, 255, 155, 94, 170, 255, 152, 91, 166, 255, 146, 86, 160, 255, 143, 84, 157, 255, 143, 84, 157, 255, 144, 85, 158, 255, 151, 90, 165, 255, 144, 86, 159, 255, 130, 75, 144, 255, 127, 73, 142, 255, 128, 74, 142, 255, 130, 76, 142, 255, 131, 77, 143, 255, 130, 76, 142, 255, 132, 79, 143, 255, 147, 93, 160, 255, 142, 91, 155, 255, 126, 81, 137, 255, 117, 75, 128, 255, 110, 70, 120, 255, 105, 67, 115, 255, 103, 65, 111, 255, 98, 60, 104, 255, 90, 55, 96, 255, 80, 49, 87, 255, 76, 46, 83, 255, 72, 43, 78, 255, 67, 40, 73, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 73, 44, 78, 255, 77, 47, 84, 255, 79, 49, 88, 255, 82, 50, 90, 255, 85, 52, 94, 255, 92, 57, 101, 255, 99, 61, 108, 255, 105, 65, 114, 255, 108, 67, 117, 255, 110, 67, 121, 255, 124, 76, 137, 255, 127, 78, 141, 255, 136, 87, 150, 255, 141, 91, 155, 255, 145, 94, 159, 255, 153, 98, 167, 255, 156, 99, 171, 255, 154, 97, 169, 255, 152, 94, 168, 255, 147, 90, 165, 255, 144, 89, 163, 255, 143, 86, 160, 255, 150, 89, 164, 255, 151, 91, 165, 255, 148, 89, 161, 255, 141, 83, 155, 255, 138, 80, 152, 255, 140, 82, 154, 255, 144, 85, 158, 255, 151, 91, 165, 255, 142, 84, 156, 255, 136, 81, 150, 255, 134, 79, 149, 255, 135, 80, 149, 255, 139, 84, 152, 255, 133, 80, 144, 255, 130, 77, 140, 255, 125, 72, 133, 255, 127, 75, 136, 255, 135, 82, 145, 255, 139, 87, 150, 255, 138, 87, 149, 255, 118, 73, 130, 255, 112, 71, 122, 255, 108, 68, 118, 255, 103, 65, 112, 255, 99, 61, 106, 255, 94, 57, 100, 255, 86, 53, 92, 255, 81, 50, 87, 255, 76, 46, 82, 255, 71, 43, 77, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 74, 45, 81, 255, 81, 49, 89, 255, 86, 52, 95, 255, 86, 53, 94, 255, 91, 55, 100, 255, 100, 61, 109, 255, 104, 64, 113, 255, 108, 68, 118, 255, 127, 79, 139, 255, 138, 84, 151, 255, 134, 85, 148, 255, 140, 91, 154, 255, 133, 83, 146, 255, 125, 76, 139, 255, 126, 76, 139, 255, 134, 81, 148, 255, 141, 84, 156, 255, 142, 87, 159, 255, 145, 89, 162, 255, 150, 92, 165, 255, 147, 90, 163, 255, 149, 92, 165, 255, 147, 87, 161, 255, 146, 87, 160, 255, 138, 81, 152, 255, 139, 82, 154, 255, 145, 87, 159, 255, 140, 82, 153, 255, 142, 84, 155, 255, 139, 83, 153, 255, 137, 82, 151, 255, 141, 86, 155, 255, 140, 85, 154, 255, 143, 87, 157, 255, 144, 89, 158, 255, 138, 84, 152, 255, 132, 79, 143, 255, 129, 77, 138, 255, 129, 77, 138, 255, 126, 74, 135, 255, 124, 73, 133, 255, 131, 80, 143, 255, 130, 78, 147, 255, 120, 73, 133, 255, 107, 68, 117, 255, 104, 65, 113, 255, 99, 61, 106, 255, 94, 58, 101, 255, 89, 54, 96, 255, 83, 51, 90, 255, 79, 48, 85, 255, 74, 45, 80, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 78, 47, 85, 255, 85, 51, 93, 255, 86, 53, 95, 255, 89, 54, 98, 255, 96, 58, 105, 255, 102, 62, 112, 255, 107, 67, 117, 255, 133, 83, 145, 255, 142, 89, 155, 255, 137, 85, 150, 255, 137, 84, 149, 255, 137, 88, 150, 255, 135, 87, 149, 255, 130, 81, 143, 255, 130, 77, 143, 255, 132, 75, 145, 255, 135, 78, 148, 255, 140, 84, 154, 255, 145, 90, 160, 255, 146, 90, 161, 255, 145, 88, 160, 255, 145, 86, 159, 255, 147, 87, 160, 255, 143, 83, 156, 255, 144, 85, 157, 255, 141, 84, 155, 255, 134, 79, 148, 255, 138, 82, 151, 255, 139, 83, 153, 255, 143, 86, 156, 255, 142, 85, 156, 255, 138, 83, 151, 255, 142, 88, 156, 255, 146, 91, 160, 255, 146, 90, 159, 255, 138, 84, 152, 255, 128, 77, 142, 255, 128, 77, 140, 255, 128, 77, 138, 255, 128, 78, 139, 255, 126, 75, 138, 255, 124, 74, 141, 255, 125, 75, 142, 255, 132, 80, 146, 255, 127, 77, 139, 255, 103, 65, 113, 255, 102, 63, 109, 255, 94, 58, 102, 255, 89, 55, 96, 255, 85, 51, 92, 255, 80, 48, 86, 255, 76, 47, 82, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 80, 49, 88, 255, 85, 52, 93, 255, 87, 53, 95, 255, 91, 55, 100, 255, 98, 60, 107, 255, 116, 74, 128, 255, 136, 86, 149, 255, 136, 85, 149, 255, 135, 85, 148, 255, 138, 88, 151, 255, 143, 93, 155, 255, 144, 94, 157, 255, 143, 93, 156, 255, 136, 84, 149, 255, 132, 77, 144, 255, 133, 78, 145, 255, 136, 81, 148, 255, 140, 86, 153, 255, 142, 88, 156, 255, 139, 83, 153, 255, 139, 81, 151, 255, 142, 84, 155, 255, 147, 88, 160, 255, 149, 89, 162, 255, 140, 82, 153, 255, 133, 77, 146, 255, 137, 82, 150, 255, 138, 83, 151, 255, 140, 84, 153, 255, 137, 82, 151, 255, 136, 81, 149, 255, 141, 84, 154, 255, 145, 90, 159, 255, 148, 91, 162, 255, 141, 86, 154, 255, 132, 80, 145, 255, 131, 79, 144, 255, 130, 78, 143, 255, 129, 78, 142, 255, 128, 77, 141, 255, 125, 75, 141, 255, 124, 74, 140, 255, 126, 76, 140, 255, 129, 78, 141, 255, 130, 79, 142, 255, 126, 75, 139, 255, 108, 65, 120, 255, 99, 61, 106, 255, 92, 57, 99, 255, 86, 53, 93, 255, 81, 50, 88, 255, 77, 47, 83, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 81, 49, 88, 255, 83, 51, 92, 255, 90, 55, 98, 255, 94, 57, 103, 255, 119, 76, 133, 255, 136, 88, 149, 255, 134, 87, 147, 255, 134, 86, 147, 255, 136, 88, 148, 255, 139, 90, 151, 255, 145, 98, 157, 255, 150, 103, 162, 255, 149, 102, 162, 255, 144, 94, 156, 255, 135, 82, 147, 255, 136, 84, 149, 255, 137, 85, 150, 255, 140, 87, 153, 255, 141, 87, 154, 255, 135, 82, 148, 255, 136, 81, 149, 255, 140, 83, 153, 255, 141, 84, 154, 255, 137, 80, 150, 255, 137, 82, 150, 255, 141, 87, 154, 255, 135, 84, 148, 255, 131, 79, 144, 255, 132, 79, 145, 255, 133, 79, 146, 255, 135, 81, 148, 255, 142, 88, 155, 255, 145, 92, 158, 255, 142, 89, 155, 255, 138, 85, 151, 255, 133, 81, 146, 255, 128, 77, 141, 255, 128, 77, 140, 255, 128, 75, 137, 255, 129, 75, 138, 255, 127, 76, 139, 255, 122, 73, 137, 255, 125, 75, 138, 255, 126, 76, 138, 255, 126, 77, 138, 255, 125, 75, 136, 255, 127, 77, 139, 255, 118, 73, 129, 255, 97, 60, 104, 255, 91, 56, 98, 255, 84, 52, 91, 255, 80, 49, 86, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 80, 49, 88, 255, 87, 54, 96, 255, 95, 59, 103, 255, 120, 77, 135, 255, 127, 82, 144, 255, 129, 84, 143, 255, 134, 88, 144, 255, 135, 89, 146, 255, 136, 90, 148, 255, 140, 93, 152, 255, 143, 96, 154, 255, 146, 101, 158, 255, 145, 99, 157, 255, 144, 96, 156, 255, 141, 91, 154, 255, 138, 88, 151, 255, 138, 86, 150, 255, 141, 87, 153, 255, 137, 84, 150, 255, 132, 80, 145, 255, 135, 83, 148, 255, 132, 80, 144, 255, 127, 74, 139, 255, 134, 81, 146, 255, 134, 83, 147, 255, 125, 77, 138, 255, 128, 79, 141, 255, 135, 84, 148, 255, 127, 77, 139, 255, 132, 80, 145, 255, 138, 86, 150, 255, 139, 87, 152, 255, 139, 87, 152, 255, 139, 87, 151, 255, 136, 85, 149, 255, 131, 80, 143, 255, 128, 77, 140, 255, 130, 77, 141, 255, 130, 77, 141, 255, 126, 74, 135, 255, 121, 69, 128, 255, 121, 70, 130, 255, 120, 72, 133, 255, 122, 73, 134, 255, 124, 76, 135, 255, 123, 75, 134, 255, 122, 75, 133, 255, 124, 76, 135, 255, 110, 63, 121, 255, 99, 62, 108, 255, 88, 54, 95, 255, 80, 49, 87, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 82, 51, 90, 255, 101, 63, 108, 255, 120, 75, 127, 255, 121, 77, 132, 255, 122, 79, 138, 255, 126, 82, 140, 255, 129, 85, 141, 255, 130, 85, 142, 255, 132, 88, 144, 255, 133, 86, 145, 255, 135, 88, 146, 255, 136, 89, 148, 255, 139, 92, 150, 255, 139, 92, 151, 255, 143, 98, 156, 255, 141, 92, 153, 255, 140, 89, 152, 255, 138, 86, 151, 255, 136, 84, 148, 255, 133, 82, 145, 255, 127, 77, 140, 255, 124, 75, 136, 255, 127, 80, 139, 255, 125, 78, 137, 255, 118, 72, 130, 255, 127, 79, 140, 255, 127, 79, 140, 255, 118, 72, 130, 255, 127, 78, 138, 255, 136, 84, 147, 255, 137, 85, 149, 255, 136, 85, 148, 255, 136, 85, 148, 255, 136, 85, 148, 255, 135, 84, 146, 255, 134, 82, 144, 255, 132, 80, 142, 255, 130, 78, 142, 255, 127, 76, 138, 255, 125, 74, 134, 255, 123, 73, 133, 255, 119, 71, 129, 255, 111, 66, 122, 255, 120, 73, 131, 255, 122, 76, 133, 255, 118, 70, 128, 255, 116, 69, 127, 255, 114, 67, 125, 255, 113, 69, 124, 255, 111, 70, 122, 255, 95, 60, 105, 255, 82, 51, 90, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 102, 62, 108, 255, 116, 73, 124, 255, 116, 73, 124, 255, 119, 76, 127, 255, 123, 80, 133, 255, 127, 83, 136, 255, 130, 86, 138, 255, 130, 88, 141, 255, 133, 92, 143, 255, 134, 93, 145, 255, 134, 92, 145, 255, 134, 91, 145, 255, 135, 89, 146, 255, 134, 87, 146, 255, 136, 88, 147, 255, 139, 90, 150, 255, 138, 89, 149, 255, 136, 88, 148, 255, 133, 84, 145, 255, 129, 79, 141, 255, 123, 76, 134, 255, 121, 76, 131, 255, 117, 72, 126, 255, 119, 74, 130, 255, 122, 77, 134, 255, 112, 69, 123, 255, 112, 68, 123, 255, 127, 78, 138, 255, 133, 82, 144, 255, 136, 84, 148, 255, 136, 84, 148, 255, 134, 84, 146, 255, 134, 84, 145, 255, 133, 83, 145, 255, 131, 80, 142, 255, 132, 81, 143, 255, 130, 80, 141, 255, 125, 75, 134, 255, 124, 74, 134, 255, 125, 75, 136, 255, 122, 74, 132, 255, 117, 71, 127, 255, 117, 72, 127, 255, 118, 73, 129, 255, 116, 71, 126, 255, 114, 68, 125, 255, 111, 66, 121, 255, 108, 67, 118, 255, 106, 67, 116, 255, 101, 63, 111, 255, 109, 69, 120, 255, 90, 57, 100, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 111, 69, 118, 255, 113, 71, 120, 255, 117, 75, 126, 255, 121, 79, 130, 255, 126, 83, 136, 255, 126, 85, 137, 255, 127, 87, 138, 255, 129, 90, 140, 255, 130, 91, 141, 255, 131, 92, 142, 255, 132, 92, 143, 255, 135, 91, 144, 255, 135, 89, 145, 255, 133, 87, 144, 255, 131, 85, 143, 255, 130, 83, 141, 255, 127, 80, 138, 255, 125, 78, 136, 255, 122, 76, 133, 255, 118, 74, 129, 255, 116, 72, 126, 255, 118, 74, 129, 255, 117, 73, 127, 255, 108, 66, 115, 255, 111, 67, 118, 255, 120, 73, 128, 255, 124, 76, 133, 255, 128, 78, 138, 255, 130, 80, 141, 255, 132, 82, 144, 255, 132, 81, 143, 255, 131, 81, 143, 255, 131, 81, 143, 255, 130, 80, 141, 255, 126, 77, 136, 255, 124, 75, 133, 255, 122, 74, 131, 255, 124, 76, 133, 255, 124, 77, 133, 255, 121, 75, 131, 255, 117, 72, 127, 255, 115, 71, 124, 255, 114, 70, 123, 255, 112, 69, 122, 255, 108, 68, 118, 255, 104, 66, 114, 255, 103, 65, 113, 255, 104, 66, 114, 255, 106, 67, 116, 255, 97, 61, 107, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 64, 40, 70, 255, 110, 69, 117, 255, 113, 73, 123, 255, 120, 79, 130, 255, 121, 80, 131, 255, 122, 81, 132, 255, 124, 86, 134, 255, 126, 86, 136, 255, 127, 86, 136, 255, 131, 89, 138, 255, 133, 89, 139, 255, 130, 85, 137, 255, 126, 81, 136, 255, 123, 78, 134, 255, 121, 76, 132, 255, 120, 75, 131, 255, 118, 73, 127, 255, 115, 71, 123, 255, 115, 71, 124, 255, 116, 73, 127, 255, 114, 71, 124, 255, 107, 65, 116, 255, 105, 63, 115, 255, 111, 66, 120, 255, 119, 72, 126, 255, 121, 73, 128, 255, 121, 74, 129, 255, 123, 76, 132, 255, 124, 76, 135, 255, 126, 78, 137, 255, 126, 78, 137, 255, 126, 78, 137, 255, 122, 74, 132, 255, 117, 70, 125, 255, 115, 68, 121, 255, 118, 72, 125, 255, 121, 75, 129, 255, 118, 73, 126, 255, 118, 73, 126, 255, 114, 71, 123, 255, 112, 69, 121, 255, 110, 68, 119, 255, 105, 66, 115, 255, 101, 64, 111, 255, 100, 64, 110, 255, 103, 65, 113, 255, 105, 65, 114, 255, 61, 36, 67, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 106, 67, 115, 255, 111, 72, 121, 255, 112, 72, 121, 255, 113, 73, 123, 255, 115, 75, 125, 255, 118, 78, 127, 255, 123, 81, 130, 255, 123, 81, 131, 255, 123, 80, 131, 255, 117, 74, 127, 255, 117, 73, 127, 255, 115, 72, 126, 255, 112, 70, 121, 255, 112, 70, 121, 255, 108, 67, 115, 255, 111, 68, 118, 255, 113, 70, 122, 255, 114, 70, 122, 255, 110, 67, 119, 255, 100, 60, 111, 255, 101, 61, 112, 255, 106, 63, 115, 255, 110, 66, 118, 255, 114, 68, 121, 255, 117, 71, 124, 255, 116, 71, 125, 255, 117, 72, 128, 255, 117, 72, 128, 255, 115, 70, 126, 255, 114, 68, 124, 255, 116, 71, 127, 255, 114, 70, 123, 255, 114, 70, 121, 255, 112, 69, 120, 255, 110, 68, 119, 255, 114, 71, 122, 255, 117, 73, 123, 255, 113, 70, 120, 255, 107, 67, 116, 255, 101, 64, 111, 255, 100, 63, 110, 255, 97, 62, 107, 255, 99, 63, 109, 255, 101, 63, 110, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 99, 62, 108, 255, 108, 69, 117, 255, 111, 73, 121, 255, 111, 73, 119, 255, 110, 72, 117, 255, 110, 71, 118, 255, 112, 72, 122, 255, 113, 72, 122, 255, 114, 72, 123, 255, 112, 71, 122, 255, 107, 70, 117, 255, 107, 70, 117, 255, 110, 70, 120, 255, 108, 67, 116, 255, 108, 67, 116, 255, 106, 65, 113, 255, 108, 66, 116, 255, 109, 66, 119, 255, 108, 65, 118, 255, 105, 63, 114, 255, 102, 61, 111, 255, 96, 58, 107, 255, 99, 60, 109, 255, 96, 58, 106, 255, 102, 63, 113, 255, 107, 65, 117, 255, 106, 63, 116, 255, 106, 63, 116, 255, 111, 68, 121, 255, 111, 69, 120, 255, 110, 70, 117, 255, 106, 67, 114, 255, 105, 65, 114, 255, 109, 68, 117, 255, 109, 68, 117, 255, 107, 66, 115, 255, 105, 66, 114, 255, 103, 65, 113, 255, 104, 65, 114, 255, 100, 63, 110, 255, 98, 62, 107, 255, 97, 61, 106, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 0, 0, 0, 255, 102, 65, 108, 255, 106, 70, 114, 255, 109, 72, 117, 255, 110, 74, 119, 255, 110, 73, 118, 255, 111, 72, 119, 255, 111, 72, 120, 255, 111, 73, 120, 255, 110, 72, 120, 255, 106, 69, 116, 255, 100, 65, 110, 255, 101, 64, 110, 255, 104, 64, 112, 255, 107, 66, 116, 255, 108, 66, 118, 255, 108, 66, 117, 255, 108, 66, 118, 255, 107, 65, 117, 255, 108, 65, 115, 255, 107, 65, 115, 255, 104, 64, 114, 255, 96, 59, 107, 255, 91, 56, 101, 255, 100, 62, 111, 255, 105, 64, 115, 255, 108, 66, 118, 255, 103, 64, 112, 255, 100, 63, 109, 255, 100, 63, 109, 255, 105, 67, 112, 255, 110, 70, 116, 255, 104, 65, 112, 255, 98, 61, 107, 255, 98, 62, 108, 255, 101, 64, 111, 255, 102, 64, 112, 255, 97, 62, 107, 255, 94, 59, 103, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 101, 66, 108, 255, 104, 69, 112, 255, 106, 71, 114, 255, 106, 70, 114, 255, 106, 68, 115, 255, 108, 70, 117, 255, 111, 73, 120, 255, 102, 67, 112, 255, 96, 63, 105, 255, 96, 63, 105, 255, 98, 62, 107, 255, 101, 62, 110, 255, 101, 61, 110, 255, 101, 61, 111, 255, 104, 64, 114, 255, 104, 64, 114, 255, 103, 63, 112, 255, 101, 62, 112, 255, 102, 62, 113, 255, 105, 65, 115, 255, 103, 64, 113, 255, 103, 64, 112, 255, 97, 60, 107, 255, 98, 61, 107, 255, 94, 59, 104, 255, 98, 62, 107, 255, 100, 63, 107, 255, 99, 63, 106, 255, 101, 64, 108, 255, 101, 64, 108, 255, 99, 64, 106, 255, 95, 62, 102, 255, 98, 62, 107, 255, 99, 62, 108, 255, 92, 59, 101, 255, 93, 59, 102, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 25, 16, 28, 255, 100, 65, 108, 255, 104, 66, 113, 255, 102, 65, 111, 255, 105, 67, 114, 255, 106, 68, 114, 255, 101, 66, 110, 255, 96, 62, 105, 255, 95, 60, 104, 255, 97, 60, 106, 255, 96, 59, 104, 255, 96, 59, 104, 255, 96, 58, 104, 255, 95, 57, 104, 255, 97, 59, 107, 255, 96, 58, 107, 255, 94, 57, 106, 255, 96, 58, 107, 255, 95, 58, 106, 255, 98, 60, 108, 255, 93, 57, 102, 255, 93, 57, 102, 255, 93, 58, 102, 255, 93, 58, 102, 255, 95, 58, 103, 255, 93, 58, 101, 255, 89, 55, 97, 255, 89, 56, 97, 255, 91, 59, 98, 255, 94, 61, 102, 255, 96, 62, 103, 255, 95, 62, 103, 255, 96, 61, 104, 255, 25, 15, 27, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 93, 59, 102, 255, 96, 61, 105, 255, 100, 64, 109, 255, 102, 65, 110, 255, 101, 65, 110, 255, 99, 64, 108, 255, 99, 63, 107, 255, 99, 63, 108, 255, 98, 62, 106, 255, 95, 59, 103, 255, 95, 59, 103, 255, 94, 59, 103, 255, 93, 57, 102, 255, 94, 57, 103, 255, 96, 58, 105, 255, 96, 58, 105, 255, 96, 58, 105, 255, 95, 58, 104, 255, 94, 58, 102, 255, 95, 58, 104, 255, 92, 57, 101, 255, 84, 53, 93, 255, 80, 52, 88, 255, 82, 52, 90, 255, 85, 53, 93, 255, 84, 53, 90, 255, 83, 54, 89, 255, 86, 56, 92, 255, 89, 58, 96, 255, 94, 61, 102, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 71, 45, 78, 255, 96, 60, 103, 255, 96, 61, 104, 255, 95, 61, 104, 255, 96, 61, 104, 255, 94, 59, 102, 255, 92, 58, 100, 255, 90, 57, 98, 255, 88, 55, 96, 255, 87, 54, 96, 255, 88, 55, 97, 255, 86, 53, 96, 255, 84, 52, 95, 255, 83, 51, 94, 255, 89, 54, 98, 255, 87, 54, 96, 255, 85, 54, 93, 255, 86, 54, 94, 255, 86, 54, 95, 255, 84, 53, 93, 255, 80, 51, 88, 255, 80, 51, 88, 255, 81, 50, 88, 255, 82, 50, 89, 255, 80, 49, 88, 255, 78, 49, 85, 255, 79, 51, 84, 255, 70, 43, 78, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 88, 55, 96, 255, 88, 54, 96, 255, 90, 56, 97, 255, 89, 55, 96, 255, 89, 55, 96, 255, 83, 51, 92, 255, 80, 50, 90, 255, 85, 54, 94, 255, 85, 54, 93, 255, 82, 50, 91, 255, 80, 49, 90, 255, 80, 49, 89, 255, 79, 50, 88, 255, 80, 51, 88, 255, 85, 53, 93, 255, 84, 53, 92, 255, 84, 53, 92, 255, 82, 52, 89, 255, 78, 49, 86, 255, 77, 47, 84, 255, 74, 45, 82, 255, 73, 44, 81, 255, 75, 46, 83, 255, 73, 44, 80, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 87, 56, 94, 255, 85, 54, 93, 255, 86, 54, 93, 255, 85, 53, 93, 255, 83, 51, 91, 255, 82, 50, 90, 255, 78, 49, 87, 255, 76, 47, 85, 255, 75, 46, 85, 255, 75, 46, 85, 255, 76, 47, 84, 255, 76, 47, 84, 255, 77, 48, 84, 255, 79, 49, 86, 255, 78, 49, 85, 255, 76, 48, 83, 255, 77, 48, 84, 255, 76, 46, 83, 255, 71, 43, 78, 255, 70, 42, 77, 255, 72, 43, 79, 255, 70, 42, 77, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 0, 0, 0, 255, 77, 47, 84, 255, 78, 48, 85, 255, 79, 48, 85, 255, 79, 48, 86, 255, 78, 48, 85, 255, 76, 47, 83, 255, 71, 44, 78, 255, 73, 45, 80, 255, 71, 44, 78, 255, 71, 44, 78, 255, 71, 44, 78, 255, 71, 44, 78, 255, 69, 44, 77, 255, 72, 44, 78, 255, 74, 45, 81, 255, 75, 46, 81, 255, 73, 45, 80, 255, 73, 45, 79, 255, 0, 0, 0, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 72, 44, 79, 255, 74, 45, 80, 255, 72, 44, 79, 255, 71, 43, 78, 255, 67, 41, 74, 255, 65, 41, 72, 255, 65, 40, 72, 255, 65, 41, 72, 255, 65, 40, 72, 255, 64, 40, 71, 255, 68, 41, 75, 255, 70, 42, 76, 255, 72, 44, 78, 255, 72, 45, 79, 255, 70, 44, 77, 255, 71, 44, 78, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 30, 18, 33, 255, 66, 41, 73, 255, 66, 41, 73, 255, 68, 42, 77, 255, 68, 42, 77, 255, 68, 42, 77, 255, 65, 40, 72, 255, 63, 39, 69, 255, 64, 39, 71, 255, 66, 40, 72, 255, 68, 42, 74, 255, 66, 40, 73, 255, 65, 39, 71, 255, 30, 19, 33, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 62, 39, 70, 255, 64, 40, 72, 255, 64, 40, 73, 255, 62, 38, 69, 255, 61, 37, 67, 255, 61, 37, 67, 255, 61, 36, 67, 255, 61, 37, 67, 255, 62, 37, 68, 255, 62, 38, 68, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 57, 36, 64, 255, 56, 35, 62, 255, 58, 36, 64, 255, 58, 36, 64, 255, 56, 35, 62, 255, 57, 35, 63, 255, 57, 34, 63, 255, 57, 34, 62, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 0, 0, 0, 255, 51, 32, 57, 255, 50, 30, 55, 255, 54, 33, 59, 255, 54, 33, 59, 255, 0, 0, 0, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 49, 31, 54, 255, 48, 30, 53, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0), "format": "RGBA8", @@ -12,7 +12,7 @@ data = { } [sub_resource type="ImageTexture" id="2"] -image = SubResource("Image_tihji") +image = SubResource("Image_56rhf") [sub_resource type="BoxShape3D" id="3"] diff --git a/3d/kinematic_character/level.tscn b/3d/kinematic_character/level.tscn index 73fd5f24..0fe827ae 100644 --- a/3d/kinematic_character/level.tscn +++ b/3d/kinematic_character/level.tscn @@ -104,7 +104,7 @@ data = { environment = SubResource("Environment_qep2e") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] -transform = Transform3D(-0.766045, 0.45452, -0.45452, 0, 0.707107, 0.707107, 0.642788, 0.541676, -0.541675, 0, 5, 0) +transform = Transform3D(-0.436154, 0.776648, -0.454519, 0.353553, 0.612372, 0.707107, 0.827508, 0.147711, -0.541675, 0, 5, 0) light_energy = 1.3 shadow_enabled = true shadow_bias = 0.032 diff --git a/3d/kinematic_character/player/cubio.gd b/3d/kinematic_character/player/cubio.gd index 6f391187..792414b4 100644 --- a/3d/kinematic_character/player/cubio.gd +++ b/3d/kinematic_character/player/cubio.gd @@ -5,11 +5,11 @@ const JUMP_SPEED = 6.5 const ACCELERATION = 4 const DECELERATION = 4 -@onready var camera = $Target/Camera3D -@onready var gravity = -ProjectSettings.get_setting("physics/3d/default_gravity") -@onready var start_position = position +@onready var camera: Camera3D = $Target/Camera3D +@onready var gravity := float(-ProjectSettings.get_setting("physics/3d/default_gravity")) +@onready var start_position := position -func _physics_process(delta): +func _physics_process(delta: float) -> void: if Input.is_action_just_pressed(&"exit"): get_tree().quit() if Input.is_action_just_pressed(&"reset_position") or global_position.y < - 6: @@ -17,17 +17,18 @@ func _physics_process(delta): position = start_position velocity = Vector3.ZERO - var dir = Vector3() + var dir := Vector3() dir.x = Input.get_axis(&"move_left", &"move_right") dir.z = Input.get_axis(&"move_forward", &"move_back") # Get the camera's transform basis, but remove the X rotation such # that the Y axis is up and Z is horizontal. - var cam_basis = camera.global_transform.basis + var cam_basis := camera.global_transform.basis cam_basis = cam_basis.rotated(cam_basis.x, -cam_basis.get_euler().x) dir = cam_basis * dir - # Limit the input to a length of 1. length_squared is faster to check. + # Limit the input to a length of 1. `length_squared()` is faster to check + # than `length()`. if dir.length_squared() > 1: dir /= dir.length() @@ -35,11 +36,11 @@ func _physics_process(delta): velocity.y += delta * gravity # Using only the horizontal velocity, interpolate towards the input. - var hvel = velocity + var hvel := velocity hvel.y = 0 - var target = dir * MAX_SPEED - var acceleration + var target := dir * MAX_SPEED + var acceleration := 0.0 if dir.dot(hvel) > 0: acceleration = ACCELERATION else: @@ -60,6 +61,6 @@ func _physics_process(delta): velocity.y = JUMP_SPEED -func _on_tcube_body_entered(body): +func _on_tcube_body_entered(body: PhysicsBody3D) -> void: if body == self: - get_node(^"WinText").show() + $WinText.show() diff --git a/3d/kinematic_character/player/follow_camera.gd b/3d/kinematic_character/player/follow_camera.gd index 8168ab6b..ca1e57bf 100644 --- a/3d/kinematic_character/player/follow_camera.gd +++ b/3d/kinematic_character/player/follow_camera.gd @@ -1,37 +1,36 @@ - extends Camera3D -# Member variables -var collision_exception = [] -@export var min_distance = 0.5 -@export var max_distance = 3.0 -@export var angle_v_adjust = 0.0 -var max_height = 2.0 -var min_height = 0 +@export var min_distance := 0.5 +@export var max_distance := 3.0 +@export var angle_v_adjust := 0.0 + +var collision_exception := [] +var max_height := 2.0 +var min_height := 0 + @onready var target_node: Node3D = get_parent() - -func _ready(): +func _ready() -> void: collision_exception.append(target_node.get_parent().get_rid()) - # Detaches the camera transform from the parent spatial node - set_as_top_level(true) + # Detaches the camera transform from the parent spatial node. + top_level = true -func _physics_process(_delta): - var target_pos: Vector3 = target_node.global_transform.origin - var camera_pos: Vector3 = global_transform.origin +func _physics_process(_delta: float) -> void: + var target_pos := target_node.global_transform.origin + var camera_pos := global_transform.origin - var delta_pos: Vector3 = camera_pos - target_pos + var delta_pos := camera_pos - target_pos - # Regular delta follow + # Regular delta follow. - # Check ranges + # Check ranges. if delta_pos.length() < min_distance: delta_pos = delta_pos.normalized() * min_distance elif delta_pos.length() > max_distance: delta_pos = delta_pos.normalized() * max_distance - # Check upper and lower height + # Check upper and lower height. if delta_pos.y > max_height: delta_pos.y = max_height if delta_pos.y < min_height: @@ -41,7 +40,7 @@ func _physics_process(_delta): look_at_from_position(camera_pos, target_pos, Vector3.UP) - # Turn a little up or down - var t = transform + # Turn a little up or down. + var t := transform t.basis = Basis(t.basis[0], deg_to_rad(angle_v_adjust)) * t.basis transform = t diff --git a/3d/kinematic_character/project.godot b/3d/kinematic_character/project.godot index 69b81970..f01224b9 100644 --- a/3d/kinematic_character/project.godot +++ b/3d/kinematic_character/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://level.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/labels_and_texts/3d_labels_and_texts.gd b/3d/labels_and_texts/3d_labels_and_texts.gd index a2ba610f..78ab269b 100644 --- a/3d/labels_and_texts/3d_labels_and_texts.gd +++ b/3d/labels_and_texts/3d_labels_and_texts.gd @@ -4,28 +4,28 @@ const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = -TAU / 16 # This must be kept in sync with RotationX. -var rot_y = TAU / 8 # This must be kept in sync with CameraHolder. -var camera_distance = 2.0 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := -TAU / 16 # This must be kept in sync with RotationX. +var rot_y := TAU / 8 # This must be kept in sync with CameraHolder. +var camera_distance := 2.0 +var base_height: = int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D -func _ready(): +func _ready() -> void: camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -37,7 +37,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clamp(rot_x, -1.57, 0) @@ -45,26 +45,26 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, camera_distance, 10 * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 @@ -74,5 +74,5 @@ func update_gui(): $Testers/Label3DHealthBar/LineEdit.visible = str(testers.get_child(tester_index).name) == "Label3DHealthBar" -func _on_line_edit_text_submitted(new_text): +func _on_line_edit_text_submitted(_new_text: String) -> void: $Testers/Label3DHealthBar/LineEdit.release_focus() diff --git a/3d/labels_and_texts/3d_labels_and_texts.tscn b/3d/labels_and_texts/3d_labels_and_texts.tscn index 6f9fc7b8..924125a3 100644 --- a/3d/labels_and_texts/3d_labels_and_texts.tscn +++ b/3d/labels_and_texts/3d_labels_and_texts.tscn @@ -146,10 +146,10 @@ environment = SubResource("11") script = ExtResource("18") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "move" libraries = { "": SubResource("AnimationLibrary_ecfcr") } +autoplay = "move" [node name="Plane" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -22) @@ -286,7 +286,7 @@ text = "Label3D (MSDF)" font = ExtResource("4_omdth") font_size = 40 -outline_size = 9 +outline_size = 4 [node name="RasterMipmaps" type="Label3D" parent="Testers/Label3DFontTypes/AnimationOrigin"] transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, 0, 1.8, 1) @@ -306,7 +306,7 @@ text = "Label3D mipmaps)" font = ExtResource("5_syv27") font_size = 40 -outline_size = 9 +outline_size = 4 [node name="Label3DBillboardModes" type="Node3D" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -16) diff --git a/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF-Mipmaps.ttf.import b/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF-Mipmaps.ttf.import index 6d7c3efb..1111959a 100644 --- a/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF-Mipmaps.ttf.import +++ b/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF-Mipmaps.ttf.import @@ -16,7 +16,7 @@ Rendering=null antialiasing=1 generate_mipmaps=true multichannel_signed_distance_field=true -msdf_pixel_range=8 +msdf_pixel_range=10 msdf_size=48 allow_system_fallback=true force_autohinter=false diff --git a/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF.ttf.import b/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF.ttf.import index 293c81a8..131bb95d 100644 --- a/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF.ttf.import +++ b/3d/labels_and_texts/fonts/Xolonium-Regular-MSDF.ttf.import @@ -16,7 +16,7 @@ Rendering=null antialiasing=1 generate_mipmaps=false multichannel_signed_distance_field=true -msdf_pixel_range=8 +msdf_pixel_range=10 msdf_size=48 allow_system_fallback=true force_autohinter=false diff --git a/3d/labels_and_texts/label_3d_layout.gd b/3d/labels_and_texts/label_3d_layout.gd index f0fa0bd3..736bab19 100644 --- a/3d/labels_and_texts/label_3d_layout.gd +++ b/3d/labels_and_texts/label_3d_layout.gd @@ -4,8 +4,8 @@ # must be adjusted instead of adjusting the `position` property. extends Node3D -var health = 0 -var counter = 0.0 +var health := 0: set = set_health +var counter := 0.0 # The margin to apply between the name and health percentage (in pixels). const HEALTH_MARGIN = 25 @@ -15,18 +15,26 @@ const HEALTH_MARGIN = 25 # (since more characters may need to be rendered at once). const BAR_WIDTH = 100 - -func _ready(): +func _ready() -> void: $LineEdit.text = $Name.text -func _process(delta): +func _process(delta: float) -> void: # Animate the health percentage. counter += delta - set_health(50 + sin(counter * 0.5) * 50) + health = roundi(50 + sin(counter * 0.5) * 50) -func set_health(p_health): +func _on_line_edit_text_changed(new_text: String) -> void: + $Name.text = new_text + + # Adjust name's font size to fit within the allowed width. + $Name.font_size = 32 + while $Name.font.get_string_size($Name.text, $Name.horizontal_alignment, -1, $Name.font_size).x > $Name.width: + $Name.font_size -= 1 + + +func set_health(p_health: int) -> void: health = p_health $Health.text = "%d%%" % round(health) @@ -48,21 +56,12 @@ func set_health(p_health): # Construct an health bar with `|` symbols brought very close to each other using # a custom FontVariation on the HealthBarForeground and HealthBarBackground nodes. - var bar_text = "" - var bar_text_bg = "" - for i in round((health / 100.0) * BAR_WIDTH): + var bar_text := "" + var bar_text_bg := "" + for i in roundi((health / 100.0) * BAR_WIDTH): bar_text += "|" for i in BAR_WIDTH: bar_text_bg += "|" $HealthBarForeground.text = str(bar_text) $HealthBarBackground.text = str(bar_text_bg) - - -func _on_line_edit_text_changed(new_text): - $Name.text = new_text - - # Adjust name's font size to fit within the allowed width. - $Name.font_size = 32 - while $Name.font.get_string_size($Name.text, $Name.horizontal_alignment, -1, $Name.font_size).x > $Name.width: - $Name.font_size -= 1 diff --git a/3d/labels_and_texts/project.godot b/3d/labels_and_texts/project.godot index 5b937350..89c47618 100644 --- a/3d/labels_and_texts/project.godot +++ b/3d/labels_and_texts/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://3d_labels_and_texts.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/labels_and_texts/textures/checker.png.import b/3d/labels_and_texts/textures/checker.png.import index 85954ad8..cfc5488d 100644 --- a/3d/labels_and_texts/textures/checker.png.import +++ b/3d/labels_and_texts/textures/checker.png.import @@ -3,20 +3,19 @@ importer="texture" type="CompressedTexture2D" uid="uid://chjqieyps5n5r" -path.s3tc="res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.s3tc.ctex" +path="res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.ctex" metadata={ -"imported_formats": ["s3tc_bptc"], -"vram_texture": true +"vram_texture": false } [deps] source_file="res://textures/checker.png" -dest_files=["res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.s3tc.ctex"] +dest_files=["res://.godot/imported/checker.png-d334a8ae07de292fd4162f184b9dd7bc.ctex"] [params] -compress/mode=2 +compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 diff --git a/3d/lights_and_shadows/checker.png.import b/3d/lights_and_shadows/checker.png.import index 4458677c..f04f3235 100644 --- a/3d/lights_and_shadows/checker.png.import +++ b/3d/lights_and_shadows/checker.png.import @@ -3,20 +3,19 @@ importer="texture" type="CompressedTexture2D" uid="uid://chjqieyps5n5r" -path.s3tc="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex" +path="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.ctex" metadata={ -"imported_formats": ["s3tc_bptc"], -"vram_texture": true +"vram_texture": false } [deps] source_file="res://checker.png" -dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex"] +dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.ctex"] [params] -compress/mode=2 +compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 diff --git a/3d/lights_and_shadows/day_night_cycle.gd b/3d/lights_and_shadows/day_night_cycle.gd index c2add263..deac7bef 100644 --- a/3d/lights_and_shadows/day_night_cycle.gd +++ b/3d/lights_and_shadows/day_night_cycle.gd @@ -1,6 +1,6 @@ extends DirectionalLight3D -func _process(delta): +func _process(delta: float) -> void: rotate_object_local(Vector3.RIGHT, 0.025 * delta) #rotate_object_local(Vector3.FORWARD, randf()) diff --git a/3d/lights_and_shadows/project.godot b/3d/lights_and_shadows/project.godot index c0265d80..fd2896c4 100644 --- a/3d/lights_and_shadows/project.godot +++ b/3d/lights_and_shadows/project.godot @@ -20,6 +20,10 @@ run/main_scene="res://test.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/lights_and_shadows/spin.gd b/3d/lights_and_shadows/spin.gd index 0b786f99..affdb279 100644 --- a/3d/lights_and_shadows/spin.gd +++ b/3d/lights_and_shadows/spin.gd @@ -1,10 +1,8 @@ extends Node3D +var increment := 0.0 -var increment = 0.0 - - -func _process(delta): +func _process(delta: float) -> void: position.x = sin(increment) position.z = cos(increment) # Avoid precision issues over time by rolling over every full turn. diff --git a/3d/lights_and_shadows/tester.gd b/3d/lights_and_shadows/tester.gd index f566e0a8..33da164e 100644 --- a/3d/lights_and_shadows/tester.gd +++ b/3d/lights_and_shadows/tester.gd @@ -4,28 +4,28 @@ const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = deg_to_rad(-22.5) # This must be kept in sync with RotationX. -var rot_y = deg_to_rad(90) # This must be kept in sync with CameraHolder. -var zoom = 2.5 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := deg_to_rad(-22.5) # This must be kept in sync with RotationX. +var rot_y := deg_to_rad(90) # This must be kept in sync with CameraHolder. +var zoom := 2.5 +var base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D -func _ready(): +func _ready() -> void: camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -37,7 +37,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clamp(rot_x, deg_to_rad(-90), 0) @@ -45,42 +45,42 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, zoom, 10 * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 -func _on_enable_sun_toggled(button_pressed): +func _on_enable_sun_toggled(button_pressed: bool) -> void: $DirectionalLight3D.visible = button_pressed -func _on_animate_lights_toggled(button_pressed): +func _on_animate_lights_toggled(button_pressed: bool) -> void: for animatable_node in get_tree().get_nodes_in_group("animatable"): animatable_node.set_process(button_pressed) -func _on_shadow_resolution_item_selected(index): - var size = 4096 +func _on_shadow_resolution_item_selected(index: int) -> void: + var size := 4096 match index: 0: size = 1024 @@ -97,12 +97,12 @@ func _on_shadow_resolution_item_selected(index): get_viewport().positional_shadow_atlas_size = size -func _on_shadow_filter_quality_item_selected(index): +func _on_shadow_filter_quality_item_selected(index: int) -> void: # Values are numbered in the OptionButton to match the RenderingServer.ShadowQuality enum. RenderingServer.directional_soft_shadow_filter_set_quality(index) RenderingServer.positional_soft_shadow_filter_set_quality(index) -func _on_projector_filter_mode_item_selected(index): +func _on_projector_filter_mode_item_selected(index: int) -> void: # Values are numbered in the OptionButton to match the RenderingServer.LightProjectorFilter enum. RenderingServer.light_projectors_set_filter(index) diff --git a/3d/material_testers/models/godot_ball.res b/3d/material_testers/models/godot_ball.res index 2e2a2d42..e592fb90 100644 Binary files a/3d/material_testers/models/godot_ball.res and b/3d/material_testers/models/godot_ball.res differ diff --git a/3d/material_testers/project.godot b/3d/material_testers/project.godot index 34559ae3..e5733d41 100644 --- a/3d/material_testers/project.godot +++ b/3d/material_testers/project.godot @@ -20,6 +20,10 @@ run/main_scene="res://material_tester.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/material_testers/tester.gd b/3d/material_testers/tester.gd index bc3c0025..1bc0ae84 100644 --- a/3d/material_testers/tester.gd +++ b/3d/material_testers/tester.gd @@ -6,13 +6,13 @@ const ZOOM_SPEED = 0.1 const ZOOM_MAX = 2.5 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_MIDDLE | MOUSE_BUTTON_MASK_RIGHT -var tester_index = 0 -var rot_x = -0.5 # This must be kept in sync with RotationX. -var rot_y = -0.5 # This must be kept in sync with CameraHolder. -var zoom = 5 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := -0.5 # This must be kept in sync with RotationX. +var rot_y := -0.5 # This must be kept in sync with CameraHolder. +var zoom := 5.0 +var base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -var backgrounds = [ +var backgrounds: Array[Dictionary] = [ { path = "res://backgrounds/schelde.hdr", name = "Riverside" }, { path = "res://backgrounds/lobby.hdr", name = "Lobby" }, { path = "res://backgrounds/park.hdr", name = "Park" }, @@ -23,21 +23,21 @@ var backgrounds = [ @onready var testers: Node3D = $Testers @onready var material_name: Label = $UI/MaterialName -@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. @onready var rotation_x: Node3D = $CameraHolder/RotationX @onready var camera: Camera3D = $CameraHolder/RotationX/Camera -func _ready(): +func _ready() -> void: for background in backgrounds: get_node(^"UI/Background").add_item(background.name) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -50,7 +50,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clamp(rot_x, -1.4, 0.45) @@ -58,40 +58,40 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's Y and Z coordinates are already correct. - var target_position = current_tester.transform.origin.x - var current_position = camera_holder.transform.origin.x + var target_position := current_tester.transform.origin.x + var current_position := camera_holder.transform.origin.x camera_holder.transform.origin.x = lerp(current_position, target_position, INTERP_SPEED * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: if tester_index > 0: tester_index -= 1 update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: if tester_index < testers.get_child_count() - 1: tester_index += 1 update_gui() -func update_gui(): - var current_tester = testers.get_child(tester_index) +func update_gui() -> void: + var current_tester := testers.get_child(tester_index) material_name.text = current_tester.get_name() $UI/Previous.disabled = tester_index == 0 $UI/Next.disabled = tester_index == testers.get_child_count() - 1 -func _on_bg_item_selected(index): +func _on_bg_item_selected(index: int) -> void: var sky_material: PanoramaSkyMaterial = $WorldEnvironment.environment.sky.sky_material sky_material.panorama = load(backgrounds[index].path) -func _on_quit_pressed(): +func _on_quit_pressed() -> void: get_tree().quit() diff --git a/3d/navigation/character.gd b/3d/navigation/character.gd index bc00fdd1..f05e75a4 100644 --- a/3d/navigation/character.gd +++ b/3d/navigation/character.gd @@ -1,36 +1,34 @@ extends Marker3D - -const Line3D = preload("res://line3d.gd") - @export var character_speed := 10.0 @export var show_path := true +var _nav_path_line: Line3D + @onready var _nav_agent := $NavigationAgent3D as NavigationAgent3D -var _nav_path_line : Line3D - - -func _ready(): +func _ready() -> void: _nav_path_line = Line3D.new() add_child(_nav_path_line) _nav_path_line.set_as_top_level(true) -func _physics_process(delta): +func _physics_process(delta: float) -> void: if _nav_agent.is_navigation_finished(): return + var next_position := _nav_agent.get_next_path_position() var offset := next_position - global_position global_position = global_position.move_toward(next_position, delta * character_speed) # Make the robot look at the direction we're traveling. - # Clamp y to 0 so the robot only looks left and right, not up/down. + # Clamp Y to 0 so the robot only looks left and right, not up/down. offset.y = 0 - look_at(global_position + offset, Vector3.UP) + if not offset.is_zero_approx(): + look_at(global_position + offset, Vector3.UP) -func set_target_position(target_position: Vector3): +func set_target_position(target_position: Vector3) -> void: _nav_agent.set_target_position(target_position) # Get a full navigation path with the NavigationServer API. if show_path: @@ -41,5 +39,6 @@ func set_target_position(target_position: Vector3): navigation_map, start_position, target_position, - optimize) + optimize + ) _nav_path_line.draw_path(path) diff --git a/3d/navigation/line3d.gd b/3d/navigation/line3d.gd index eb6193d4..138fa4e6 100644 --- a/3d/navigation/line3d.gd +++ b/3d/navigation/line3d.gd @@ -1,15 +1,14 @@ -extends MeshInstance3D +class_name MeshInstance3D +extends Line3D - -func _ready(): - set_mesh(ImmediateMesh.new()) +func _ready() -> void: + mesh = ImmediateMesh.new() var material := StandardMaterial3D.new() - material.flags_unshaded = true - material.albedo_color = Color.WHITE + material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED set_material_override(material) -func draw_path(path): +func draw_path(path: PackedVector3Array) -> void: var im: ImmediateMesh = mesh im.clear_surfaces() im.surface_begin(Mesh.PRIMITIVE_POINTS, null) diff --git a/3d/navigation/navmesh.gd b/3d/navigation/navmesh.gd index 437afe5b..0b293896 100644 --- a/3d/navigation/navmesh.gd +++ b/3d/navigation/navmesh.gd @@ -1,27 +1,25 @@ extends Node3D - const Character = preload("res://character.gd") +var _cam_rotation := 0.0 + @onready var _camera := $CameraBase/Camera3D as Camera3D @onready var _robot := $RobotBase as Character -var _cam_rotation := 0.0 - - -func _unhandled_input(event: InputEvent): +func _unhandled_input(event: InputEvent) -> void: if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed: # Get closest point on navmesh for the current mouse cursor position. - var mouse_cursor_position = event.position + var mouse_cursor_position: Vector2 = event.position var camera_ray_length := 1000.0 var camera_ray_start := _camera.project_ray_origin(mouse_cursor_position) var camera_ray_end := camera_ray_start + _camera.project_ray_normal(mouse_cursor_position) * camera_ray_length var closest_point_on_navmesh := NavigationServer3D.map_get_closest_point_to_segment( - get_world_3d().navigation_map, - camera_ray_start, - camera_ray_end - ) + get_world_3d().navigation_map, + camera_ray_start, + camera_ray_end + ) _robot.set_target_position(closest_point_on_navmesh) elif event is InputEventMouseMotion: diff --git a/3d/navigation/project.godot b/3d/navigation/project.godot index ebd0c791..5ea84ed9 100644 --- a/3d/navigation/project.godot +++ b/3d/navigation/project.godot @@ -20,6 +20,10 @@ run/main_scene="res://navmesh.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [physics] common/physics_ticks_per_second=120 diff --git a/3d/occlusion_culling_mesh_lod/camera.gd b/3d/occlusion_culling_mesh_lod/camera.gd index f9d393a2..65597931 100644 --- a/3d/occlusion_culling_mesh_lod/camera.gd +++ b/3d/occlusion_culling_mesh_lod/camera.gd @@ -3,15 +3,14 @@ extends Camera3D const MOUSE_SENSITIVITY = 0.002 const MOVE_SPEED = 1.5 -var rot = Vector3() -var velocity = Vector3() +var rot := Vector3() +var velocity := Vector3() + +func _ready() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED -func _ready(): - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - - -func _input(event): +func _input(event: InputEvent) -> void: # Mouse look (only if the mouse is captured). if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: # Horizontal mouse look. @@ -22,13 +21,13 @@ func _input(event): if event.is_action_pressed("toggle_mouse_capture"): if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE else: - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED -func _process(delta): - var motion = Vector3( +func _process(delta: float) -> void: + var motion := Vector3( Input.get_axis(&"move_left", &"move_right"), 0, Input.get_axis(&"move_forward", &"move_back") diff --git a/3d/occlusion_culling_mesh_lod/door.gd b/3d/occlusion_culling_mesh_lod/door.gd index ef04681b..60cff181 100644 --- a/3d/occlusion_culling_mesh_lod/door.gd +++ b/3d/occlusion_culling_mesh_lod/door.gd @@ -1,10 +1,8 @@ extends Node3D - var open := false - -func _input(event: InputEvent): +func _input(event: InputEvent) -> void: if event.is_action_pressed("toggle_doors"): if open: # Close the door. @@ -23,7 +21,7 @@ func _input(event: InputEvent): $OccluderInstance3D.visible = false -func _on_animation_player_animation_finished(_anim_name): +func _on_animation_player_animation_finished(_anim_name: StringName) -> void: if not open: # Re-enable the occluder when the door is done closing. # To prevent overocclusion, the door must be fully closed before the occluder can be re-enabled. diff --git a/3d/occlusion_culling_mesh_lod/node_3d.gd b/3d/occlusion_culling_mesh_lod/node_3d.gd index fe481a76..8b1cb10c 100644 --- a/3d/occlusion_culling_mesh_lod/node_3d.gd +++ b/3d/occlusion_culling_mesh_lod/node_3d.gd @@ -1,7 +1,6 @@ extends Node3D - -func _input(event): +func _input(event: InputEvent) -> void: if event.is_action_pressed("toggle_occlusion_culling"): get_viewport().use_occlusion_culling = not get_viewport().use_occlusion_culling update_labels() @@ -9,7 +8,7 @@ func _input(event): get_viewport().mesh_lod_threshold = 1.0 if is_zero_approx(get_viewport().mesh_lod_threshold) else 0.0 update_labels() if event.is_action_pressed("cycle_draw_mode"): - get_viewport().debug_draw = wrapi(get_viewport().debug_draw + 1, 0, 5) + get_viewport().debug_draw = wrapi(get_viewport().debug_draw + 1, 0, 5) as Viewport.DebugDraw update_labels() if event.is_action_pressed("toggle_vsync"): if DisplayServer.window_get_vsync_mode() == DisplayServer.VSYNC_DISABLED: @@ -18,7 +17,7 @@ func _input(event): DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) -func _process(_delta): +func _process(_delta: float) -> void: $Performance.text = """%d FPS (%.2f mspf) Currently rendering: @@ -29,18 +28,18 @@ Currently rendering: Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second(), RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME), - RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME) * 0.001, + roundi(RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME) * 0.001), RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME), ] -func update_labels(): +func update_labels() -> void: $OcclusionCulling.text = "Occlusion culling: %s" % ("Enabled" if get_viewport().use_occlusion_culling else "Disabled") $MeshLOD.text = "Mesh LOD: %s" % ("Enabled" if not is_zero_approx(get_viewport().mesh_lod_threshold) else "Disabled") $DrawMode.text = "Draw mode: %s" % get_draw_mode_string(get_viewport().debug_draw) -func get_draw_mode_string(draw_mode): +func get_draw_mode_string(draw_mode: int) -> String: match draw_mode: 0: return "Normal" @@ -52,3 +51,5 @@ func get_draw_mode_string(draw_mode): return "Overdraw" 4: return "Wireframe" + _: + return "(unknown)" diff --git a/3d/occlusion_culling_mesh_lod/project.godot b/3d/occlusion_culling_mesh_lod/project.godot index 6245cac1..f8c4dd9f 100644 --- a/3d/occlusion_culling_mesh_lod/project.godot +++ b/3d/occlusion_culling_mesh_lod/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://node_3d.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/particles/checker.png.import b/3d/particles/checker.png.import index 4458677c..f04f3235 100644 --- a/3d/particles/checker.png.import +++ b/3d/particles/checker.png.import @@ -3,20 +3,19 @@ importer="texture" type="CompressedTexture2D" uid="uid://chjqieyps5n5r" -path.s3tc="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex" +path="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.ctex" metadata={ -"imported_formats": ["s3tc_bptc"], -"vram_texture": true +"vram_texture": false } [deps] source_file="res://checker.png" -dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex"] +dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.ctex"] [params] -compress/mode=2 +compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 diff --git a/3d/particles/project.godot b/3d/particles/project.godot index 99fb9d5e..f3c11d48 100644 --- a/3d/particles/project.godot +++ b/3d/particles/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://test.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/particles/test.tscn b/3d/particles/test.tscn index e4c0c3d1..68fa45c6 100644 --- a/3d/particles/test.tscn +++ b/3d/particles/test.tscn @@ -230,10 +230,10 @@ emission_shape = 3 emission_box_extents = Vector3(0.5, 0, 0.5) direction = Vector3(0, 1, 0) spread = 3.5 -gravity = Vector3(0, 0, 0) initial_velocity_min = 1.0 initial_velocity_max = 4.0 angular_velocity_max = 360.0 +gravity = Vector3(0, 0, 0) damping_min = 2.0 damping_max = 2.0 scale_min = 0.1 @@ -266,10 +266,10 @@ gradient = SubResource("Gradient_lgkn4") [sub_resource type="ParticleProcessMaterial" id="ParticlesMaterial_a3ot6"] direction = Vector3(0, 1, 0) -gravity = Vector3(0, -2, 0) initial_velocity_min = 1.0 initial_velocity_max = 2.0 angular_velocity_max = 180.0 +gravity = Vector3(0, -2, 0) tangential_accel_min = 3.0 tangential_accel_max = 3.0 color = Color(0.55, 0.55, 0.55, 1) @@ -300,9 +300,9 @@ gradient = SubResource("Gradient_6585v") [sub_resource type="ParticleProcessMaterial" id="ParticlesMaterial_4noo4"] direction = Vector3(0, 1, 0) -gravity = Vector3(0, 0, 0) initial_velocity_min = 1.0 initial_velocity_max = 1.0 +gravity = Vector3(0, 0, 0) color_ramp = SubResource("GradientTexture1D_6ubl1") [sub_resource type="ParticleProcessMaterial" id="ParticlesMaterial_ft0gs"] @@ -417,9 +417,9 @@ gradient = SubResource("Gradient_kdfrx") emission_shape = 3 emission_box_extents = Vector3(1, 1, 1) direction = Vector3(0, 1, 0) -gravity = Vector3(0, 0, 0) initial_velocity_min = 1.0 initial_velocity_max = 1.0 +gravity = Vector3(0, 0, 0) color_ramp = SubResource("GradientTexture1D_3jc0t") sub_emitter_mode = 2 sub_emitter_amount_at_end = 1 @@ -474,10 +474,10 @@ initial_velocity_min = 1.0 initial_velocity_max = 1.0 color = Color(0.568627, 0.313726, 1, 1) color_ramp = SubResource("GradientTexture1D_ppbqr") +collision_mode = 2 sub_emitter_mode = 3 sub_emitter_amount_at_collision = 1 sub_emitter_keep_velocity = true -collision_mode = 2 [sub_resource type="Curve" id="Curve_7mapm"] _data = [Vector2(0.7, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] @@ -543,10 +543,10 @@ environment = SubResource("11") script = ExtResource("18") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "move" libraries = { "": SubResource("AnimationLibrary_ecfcr") } +autoplay = "move" [node name="Plane" type="MeshInstance3D" parent="."] layers = 2 @@ -612,19 +612,19 @@ color = Color(4, 4, 4, 1) color_ramp = SubResource("Gradient_or8rt") [node name="Decal4" type="Decal" parent="Testers/CPUParticlesExplosion"] -extents = Vector3(2.5, 0.01, 2.5) +size = Vector3(5, 0.02, 5) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) [node name="Decal5" type="Decal" parent="Testers/CPUParticlesExplosion"] transform = Transform3D(0.562646, 0, -0.826698, 0, 1, 0, 0.826698, 0, 0.562646, 0, 0, 0) -extents = Vector3(2.5, 0.01, 2.5) +size = Vector3(5, 0.02, 5) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) [node name="Decal6" type="Decal" parent="Testers/CPUParticlesExplosion"] transform = Transform3D(-0.481494, 0, -0.87645, 0, 1, 0, 0.87645, 0, -0.481494, 0, 0, 0) -extents = Vector3(2.5, 0.01, 2.5) +size = Vector3(5, 0.02, 5) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) @@ -639,19 +639,19 @@ process_material = SubResource("ParticlesMaterial_wcmum") draw_pass_1 = SubResource("QuadMesh_783ir") [node name="Decal" type="Decal" parent="Testers/GPUParticlesFire"] -extents = Vector3(1, 0.01, 1) +size = Vector3(2, 0.02, 2) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) [node name="Decal2" type="Decal" parent="Testers/GPUParticlesFire"] transform = Transform3D(0.562646, 0, -0.826698, 0, 1, 0, 0.826698, 0, 0.562646, 0, 0, 0) -extents = Vector3(1.5, 0.01, 1.1) +size = Vector3(3, 0.02, 2.2) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) [node name="Decal3" type="Decal" parent="Testers/GPUParticlesFire"] transform = Transform3D(-0.481494, 0, -0.87645, 0, 1, 0, 0.87645, 0, -0.481494, 0, 0, 0) -extents = Vector3(1.6, 0.01, 1.3) +size = Vector3(3.2, 0.02, 2.6) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) @@ -668,19 +668,19 @@ process_material = SubResource("ParticlesMaterial_a3ot6") draw_pass_1 = SubResource("QuadMesh_edvlt") [node name="Decal4" type="Decal" parent="Testers/GPUParticlesSmoke"] -extents = Vector3(1, 0.01, 1) +size = Vector3(2, 0.02, 2) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) [node name="Decal5" type="Decal" parent="Testers/GPUParticlesSmoke"] transform = Transform3D(0.562646, 0, -0.826698, 0, 1, 0, 0.826698, 0, 0.562646, 0, 0, 0) -extents = Vector3(1.5, 0.01, 1.1) +size = Vector3(3, 0.02, 2.2) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) [node name="Decal6" type="Decal" parent="Testers/GPUParticlesSmoke"] transform = Transform3D(-0.481494, 0, -0.87645, 0, 1, 0, 0.87645, 0, -0.481494, 0, 0, 0) -extents = Vector3(1.6, 0.01, 1.3) +size = Vector3(3.2, 0.02, 2.6) texture_albedo = ExtResource("3_pmhp8") modulate = Color(0, 0, 0, 1) @@ -716,7 +716,7 @@ draw_pass_1 = SubResource("BoxMesh_88317") [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesCollision"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) [node name="MovingBox" type="MeshInstance3D" parent="Testers/GPUParticlesCollision"] transform = Transform3D(0.707107, 0, -0.707107, 0, 1, 0, 0.707107, 0, 0.707107, 0, -0.45, -0.5) @@ -725,7 +725,7 @@ skeleton = NodePath("../../..") surface_material_override/0 = SubResource("StandardMaterial3D_3jlyg") [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesCollision/MovingBox"] -extents = Vector3(0.5, 0.5, 0.5) +size = Vector3(1, 1, 1) [node name="GPUParticlesCollisionGlobalCoords" type="Node3D" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2) @@ -744,7 +744,7 @@ draw_pass_1 = SubResource("BoxMesh_88317") [node name="GPUParticlesCollisionBox3D2" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesCollisionGlobalCoords"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) [node name="MovingBox" type="MeshInstance3D" parent="Testers/GPUParticlesCollisionGlobalCoords"] transform = Transform3D(0.707107, 0, -0.707107, 0, 1, 0, 0.707107, 0, 0.707107, 0, -0.45, -0.5) @@ -753,7 +753,7 @@ skeleton = NodePath("../../..") surface_material_override/0 = SubResource("StandardMaterial3D_3jlyg") [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesCollisionGlobalCoords/MovingBox"] -extents = Vector3(0.5, 0.5, 0.5) +size = Vector3(1, 1, 1) [node name="GPUParticles3DFoam" type="Node3D" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2) @@ -772,8 +772,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -6) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) amount = 50 lifetime = 2.0 -fixed_fps = 0 -interpolate = false +fixed_fps = 120 collision_base_size = 0.1 trail_enabled = true process_material = SubResource("ParticlesMaterial_bwh6l") @@ -783,7 +782,7 @@ draw_pass_2 = null [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesTrails"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) [node name="GPUParticlesSubemitterAtEnd" type="Node3D" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -10) @@ -809,7 +808,7 @@ draw_pass_1 = SubResource("SphereMesh_g7qur") [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesSubemitterAtEnd"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) [node name="GPUParticlesSubemitterOnCollision" type="Node3D" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -14) @@ -837,7 +836,7 @@ draw_pass_1 = SubResource("SphereMesh_g7qur") [node name="GPUParticlesCollisionBox3D" type="GPUParticlesCollisionBox3D" parent="Testers/GPUParticlesSubemitterOnCollision"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) [node name="GPUParticlesCollisionSDF" type="Node3D" parent="Testers"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -18) @@ -855,7 +854,7 @@ draw_pass_1 = SubResource("SphereMesh_whk10") [node name="GPUParticlesCollisionSDF3D" type="GPUParticlesCollisionSDF3D" parent="Testers/GPUParticlesCollisionSDF"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) -extents = Vector3(2, 0.5, 2) +size = Vector3(4, 1, 4) texture = ExtResource("4_wcrow") [node name="Tube" type="MeshInstance3D" parent="Testers/GPUParticlesCollisionSDF"] @@ -897,7 +896,7 @@ process_material = SubResource("ParticleProcessMaterial_4f0te") draw_pass_1 = SubResource("SphereMesh_8xbmh") [node name="GPUParticlesCollisionHeightField3D" type="GPUParticlesCollisionHeightField3D" parent="Testers/GPUParticlesCollisionHeightfield"] -extents = Vector3(2, 1, 2) +size = Vector3(4, 2, 4) [node name="CSGBox3D" type="CSGBox3D" parent="Testers/GPUParticlesCollisionHeightfield"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) diff --git a/3d/particles/tester.gd b/3d/particles/tester.gd index 842cc061..913bdc3b 100644 --- a/3d/particles/tester.gd +++ b/3d/particles/tester.gd @@ -4,28 +4,27 @@ const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = deg_to_rad(-22.5) # This must be kept in sync with RotationX. -var rot_y = deg_to_rad(90) # This must be kept in sync with CameraHolder. -var zoom = 2.5 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := deg_to_rad(-22.5) # This must be kept in sync with RotationX. +var rot_y := deg_to_rad(90) # This must be kept in sync with CameraHolder. +var zoom := 2.5 +var base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D - -func _ready(): +func _ready() -> void: camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -37,7 +36,7 @@ func _unhandled_input(event): if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED rot_x = clamp(rot_x, deg_to_rad(-90), 0) @@ -45,26 +44,26 @@ func _unhandled_input(event): rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, zoom, 10 * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 diff --git a/3d/physical_light_camera_units/project.godot b/3d/physical_light_camera_units/project.godot index 24166eef..b817d223 100644 --- a/3d/physical_light_camera_units/project.godot +++ b/3d/physical_light_camera_units/project.godot @@ -14,10 +14,14 @@ config/name="Physical Light and Camera Units" config/description="This demo showcases a physical light and camera units setup. This allows you to use real world units for lights (lumen, lux, Kelvin) and cameras (shutter speed, aperture, ISO sensitivity)." +config/tags=PackedStringArray("3d", "demo", "official", "rendering") run/main_scene="res://test.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" -config/tags=PackedStringArray("3d", "demo", "official", "rendering") + +[debug] + +gdscript/warnings/untyped_declaration=1 [display] diff --git a/3d/physics_tests/main.tscn b/3d/physics_tests/main.tscn index 4d7e6a87..d7de5575 100644 --- a/3d/physics_tests/main.tscn +++ b/3d/physics_tests/main.tscn @@ -47,10 +47,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -19.0 -offset_right = 50.0 -offset_bottom = -5.0 +offset_top = -36.0 +offset_right = 55.0 +offset_bottom = -13.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "FPS: 0" script = ExtResource("1") @@ -60,10 +62,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -39.0 -offset_right = 50.0 -offset_bottom = -25.0 +offset_top = -64.0 +offset_right = 128.0 +offset_bottom = -41.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "Physics engine:" script = ExtResource("3") @@ -73,10 +77,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -59.0 -offset_right = 50.0 -offset_bottom = -45.0 +offset_top = -92.0 +offset_right = 125.0 +offset_bottom = -69.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "Godot Version:" script = ExtResource("2") @@ -86,10 +92,12 @@ anchors_preset = 2 anchor_top = 1.0 anchor_bottom = 1.0 offset_left = 10.0 -offset_top = -79.0 +offset_top = -120.0 offset_right = 50.0 -offset_bottom = -65.0 +offset_bottom = -97.0 grow_vertical = 0 +theme_override_colors/font_outline_color = Color(0, 0, 0, 1) +theme_override_constants/outline_size = 4 text = "Test:" script = ExtResource("5") diff --git a/3d/physics_tests/project.godot b/3d/physics_tests/project.godot index 15b50b2d..4ba52ed0 100644 --- a/3d/physics_tests/project.godot +++ b/3d/physics_tests/project.godot @@ -21,6 +21,10 @@ config/icon="res://icon.webp" Log="*res://utils/system_log.gd" System="*res://utils/system.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" @@ -51,7 +55,7 @@ toggle_full_screen={ } exit={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777217,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"echo":false,"script":null) ] } toggle_debug_collision={ @@ -71,19 +75,20 @@ toggle_pause={ } character_right={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777233,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":68,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194321,"key_label":0,"unicode":0,"echo":false,"script":null) ] } character_left={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777231,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":113,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194319,"key_label":0,"unicode":0,"echo":false,"script":null) ] } character_jump={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":122,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null) ] } diff --git a/3d/physics_tests/test.gd b/3d/physics_tests/test.gd index f89ad2fe..bb0300d6 100644 --- a/3d/physics_tests/test.gd +++ b/3d/physics_tests/test.gd @@ -1,41 +1,39 @@ class_name Test extends Node - signal wait_done() -@export var _enable_debug_collision = true +@export var _enable_debug_collision := true -var _timer -var _timer_started = false +var _timer: Timer +var _timer_started := false -var _wait_physics_ticks_counter = 0 +var _wait_physics_ticks_counter := 0 -var _drawn_nodes = [] +var _drawn_nodes: Array[Node3D] = [] - -func _enter_tree(): +func _enter_tree() -> void: if not _enable_debug_collision: get_tree().debug_collisions_hint = false -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if _wait_physics_ticks_counter > 0: _wait_physics_ticks_counter -= 1 if _wait_physics_ticks_counter == 0: wait_done.emit() -func add_sphere(pos, radius, color): - var sphere = MeshInstance3D.new() +func add_sphere(pos: Vector3, radius: float, color: Color) -> void: + var sphere := MeshInstance3D.new() - var sphere_mesh = SphereMesh.new() + var sphere_mesh := SphereMesh.new() sphere_mesh.radius = radius sphere_mesh.height = radius * 2.0 sphere.mesh = sphere_mesh - var material = StandardMaterial3D.new() - material.flags_unshaded = true + var material := StandardMaterial3D.new() + material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED material.albedo_color = color sphere.set_surface_override_material(0, material) @@ -45,14 +43,14 @@ func add_sphere(pos, radius, color): sphere.global_transform.origin = pos -func add_shape(shape, transform, color): - var debug_mesh = shape.get_debug_mesh() +func add_shape(shape: Shape3D, transform: Transform3D, color: Color) -> void: + var debug_mesh := shape.get_debug_mesh() - var mesh_instance = MeshInstance3D.new() + var mesh_instance := MeshInstance3D.new() mesh_instance.transform = transform mesh_instance.mesh = debug_mesh - var material = StandardMaterial3D.new() + var material := StandardMaterial3D.new() material.flags_unshaded = true material.albedo_color = color mesh_instance.set_surface_override_material(0, material) @@ -61,36 +59,37 @@ func add_shape(shape, transform, color): _drawn_nodes.push_back(mesh_instance) -func clear_drawn_nodes(): +func clear_drawn_nodes() -> void: for node in _drawn_nodes: remove_child(node) node.queue_free() + _drawn_nodes.clear() -func create_rigidbody(shape, pickable = false, transform = Transform3D.IDENTITY): - var collision = CollisionShape3D.new() +func create_rigidbody(shape: Shape3D, pickable: bool = false, transform: Transform3D = Transform3D.IDENTITY) -> RigidBody3D: + var collision := CollisionShape3D.new() collision.shape = shape collision.transform = transform - var body = RigidBody3D.new() + var body := RigidBody3D.new() body.add_child(collision) if pickable: - var script = load("res://utils/rigidbody_pick.gd") + var script := load("res://utils/rigidbody_pick.gd") body.set_script(script) return body -func create_rigidbody_box(size, pickable = false, transform = Transform3D.IDENTITY): - var shape = BoxShape3D.new() +func create_rigidbody_box(size: Vector3, pickable: bool = false, transform: Transform3D = Transform3D.IDENTITY) -> RigidBody3D: + var shape := BoxShape3D.new() shape.size = size return create_rigidbody(shape, pickable, transform) -func start_timer(timeout): +func start_timer(timeout: float) -> Timer: if _timer == null: _timer = Timer.new() _timer.one_shot = true @@ -105,21 +104,21 @@ func start_timer(timeout): return _timer -func cancel_timer(): +func cancel_timer() -> void: if _timer_started: _timer.paused = true _timer.timeout.emit() _timer.paused = false -func is_timer_canceled(): +func is_timer_canceled() -> bool: return _timer.paused -func wait_for_physics_ticks(tick_count): +func wait_for_physics_ticks(tick_count: int) -> Test: _wait_physics_ticks_counter = tick_count return self -func _on_timer_done(): +func _on_timer_done() -> void: _timer_started = false diff --git a/3d/physics_tests/tests.gd b/3d/physics_tests/tests.gd index 3b485dc1..f92b6abe 100644 --- a/3d/physics_tests/tests.gd +++ b/3d/physics_tests/tests.gd @@ -1,7 +1,6 @@ extends Node - -var _tests = [ +var _tests: Array[Dictionary] = [ { "id": "Functional Tests/Shapes", "path": "res://tests/functional/test_shapes.tscn", @@ -61,7 +60,7 @@ var _tests = [ ] -func _ready(): - var test_menu = $TestsMenu +func _ready() -> void: + var test_menu: OptionMenu = $TestsMenu for test in _tests: test_menu.add_test(test.id, test.path) diff --git a/3d/physics_tests/tests/functional/test_collision_pairs.gd b/3d/physics_tests/tests/functional/test_collision_pairs.gd index 3da46a6c..c2edc724 100644 --- a/3d/physics_tests/tests/functional/test_collision_pairs.gd +++ b/3d/physics_tests/tests/functional/test_collision_pairs.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_TYPE_BOX = "Collision type/Box (1)" const OPTION_TYPE_SPHERE = "Collision type/Sphere (2)" const OPTION_TYPE_CAPSULE = "Collision type/Capsule (3)" @@ -16,15 +15,13 @@ const OPTION_SHAPE_CONCAVE_POLYGON = "Shape type/Concave Polygon" const OFFSET_RANGE = 3.0 -@export var offset = Vector3.ZERO +@export var offset := Vector3.ZERO -var _update_collision = false -var _collision_test_index = 0 -var _current_offset = Vector3.ZERO -var _collision_shapes = [] +var _update_collision := false +var _collision_test_index := 0 +var _collision_shapes: Array[Shape3D] = [] - -func _ready(): +func _ready() -> void: _initialize_collision_shapes() $Options.add_menu_item(OPTION_TYPE_BOX) @@ -50,22 +47,21 @@ func _ready(): _update_collision = true -func _input(event): - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - if key_event.keycode == KEY_1: +func _input(event: InputEvent) -> void: + if event is InputEventKey and event.pressed: + if event.keycode == KEY_1: _on_option_selected(OPTION_TYPE_BOX) - elif key_event.keycode == KEY_2: + elif event.keycode == KEY_2: _on_option_selected(OPTION_TYPE_SPHERE) - elif key_event.keycode == KEY_3: + elif event.keycode == KEY_3: _on_option_selected(OPTION_TYPE_CAPSULE) - elif key_event.keycode == KEY_4: + elif event.keycode == KEY_4: _on_option_selected(OPTION_TYPE_CYLINDER) - elif key_event.keycode == KEY_5: + elif event.keycode == KEY_5: _on_option_selected(OPTION_TYPE_CONVEX_POLYGON) -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if not _update_collision: @@ -76,71 +72,69 @@ func _physics_process(delta): _do_collision_test() -func set_x_offset(value): +func set_x_offset(value: float) -> void: offset.x = value * OFFSET_RANGE _update_collision = true -func set_y_offset(value): +func set_y_offset(value: float) -> void: offset.y = value * OFFSET_RANGE _update_collision = true -func set_z_offset(value): +func set_z_offset(value: float) -> void: offset.z = value * OFFSET_RANGE _update_collision = true -func _initialize_collision_shapes(): +func _initialize_collision_shapes() -> void: _collision_shapes.clear() for node in $Shapes.get_children(): - var body = node as PhysicsBody3D - var shape = body.shape_owner_get_shape(0, 0) + var body: PhysicsBody3D = node + var shape: Shape3D = body.shape_owner_get_shape(0, 0) shape.resource_name = String(node.name).substr("RigidBody".length()) _collision_shapes.push_back(shape) -func _do_collision_test(): +func _do_collision_test() -> void: clear_drawn_nodes() - var shape = _collision_shapes[_collision_test_index] + var shape: Shape3D = _collision_shapes[_collision_test_index] Log.print_log("* Start %s collision tests..." % shape.resource_name) - var shape_query = PhysicsShapeQueryParameters3D.new() + var shape_query := PhysicsShapeQueryParameters3D.new() shape_query.set_shape(shape) - var shape_scale = Vector3(0.5, 0.5, 0.5) + var shape_scale := Vector3(0.5, 0.5, 0.5) shape_query.transform = Transform3D.IDENTITY.scaled(shape_scale) for node in $Shapes.get_children(): if not node.visible: continue - var body = node as PhysicsBody3D - var space_state = body.get_world_3d().direct_space_state + var body: PhysicsBody3D = node + var space_state := body.get_world_3d().direct_space_state Log.print_log("* Testing: %s" % body.name) - var center = body.global_transform.origin + var center := body.global_transform.origin # Collision at the center inside. - var res = _add_collision(space_state, center, shape, shape_query) + var res := _add_collision(space_state, center, shape, shape_query) Log.print_log("Collision center inside: %s" % ("NO HIT" if res.is_empty() else "HIT")) Log.print_log("* Done.") -func _add_collision(space_state, pos, shape, shape_query): +func _add_collision(space_state: PhysicsDirectSpaceState3D, pos: Vector3, shape: Shape3D, shape_query: PhysicsShapeQueryParameters3D) -> Array[Vector3]: shape_query.transform.origin = pos + offset - var results = space_state.collide_shape(shape_query) + var results := space_state.collide_shape(shape_query) - var color + var color := Color.GREEN if results.is_empty(): color = Color.WHITE.darkened(0.5) - else: - color = Color.GREEN # Draw collision query shape. add_shape(shape, shape_query.transform, color) @@ -152,7 +146,7 @@ func _add_collision(space_state, pos, shape, shape_query): return results -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_TYPE_BOX: _collision_test_index = _find_type_index("Box") @@ -171,9 +165,9 @@ func _on_option_selected(option): _update_collision = true -func _find_type_index(type_name): - for type_index in range(_collision_shapes.size()): - var type_shape = _collision_shapes[type_index] +func _find_type_index(type_name: String) -> int: + for type_index in _collision_shapes.size(): + var type_shape := _collision_shapes[type_index] if type_shape.resource_name.find(type_name) > -1: return type_index @@ -181,8 +175,8 @@ func _find_type_index(type_name): return -1 -func _on_option_changed(option, checked): - var node +func _on_option_changed(option: String, checked: bool) -> void: + var node: RigidBody3D match option: OPTION_SHAPE_BOX: @@ -204,8 +198,8 @@ func _on_option_changed(option, checked): _update_collision = true -func _find_shape_node(type_name): - var node = $Shapes.find_node("RigidBody%s" % type_name) +func _find_shape_node(type_name: String) -> RigidBody3D: + var node: RigidBody3D = $Shapes.find_child("RigidBody%s" % type_name) if not node: Log.print_error("Invalid shape type: " + type_name) diff --git a/3d/physics_tests/tests/functional/test_joints.gd b/3d/physics_tests/tests/functional/test_joints.gd index 5ca04cb7..1dfdf884 100644 --- a/3d/physics_tests/tests/functional/test_joints.gd +++ b/3d/physics_tests/tests/functional/test_joints.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_JOINT_TYPE = "Joint Type/%s Joint (%d)" const OPTION_TEST_CASE_BODIES_COLLIDE = "Test case/Attached bodies collide" @@ -11,28 +10,27 @@ const OPTION_TEST_CASE_CHANGE_POSITIONS = "Test case/Set body positions after ad const BOX_SIZE = Vector3(1.0, 1.0, 1.0) -var _update_joint = false -var _selected_joint = null +var _update_joint := false +var _selected_joint: Joint3D -var _bodies_collide = false -var _world_attachement = false -var _dynamic_attachement = false -var _destroy_body = false -var _change_positions = false +var _bodies_collide := false +var _world_attachement := false +var _dynamic_attachement := false +var _destroy_body := false +var _change_positions := false -var _joint_types = {} +var _joint_types := {} +func _ready() -> void: + var options: OptionMenu = $Options -func _ready(): - var options = $Options - - var joints = $Joints + var joints: Node3D = $Joints for joint_index in joints.get_child_count(): - var joint_node = joints.get_child(joint_index) + var joint_node := joints.get_child(joint_index) joint_node.visible = false - var joint_name = String(joint_node.name) - var joint_short = joint_name.substr(0, joint_name.length() - 5) - var option_name = OPTION_JOINT_TYPE % [joint_short, joint_index + 1] + var joint_name := String(joint_node.name) + var joint_short := joint_name.substr(0, joint_name.length() - 5) + var option_name := OPTION_JOINT_TYPE % [joint_short, joint_index + 1] options.add_menu_item(option_name) _joint_types[option_name] = joint_node @@ -49,29 +47,28 @@ func _ready(): _update_joint = true -func _process(_delta): +func _process(_delta: float) -> void: if _update_joint: _update_joint = false await _create_joint() $LabelJointType.text = "Joint Type: " + String(_selected_joint.name) -func _input(event): - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - var joint_index = key_event.keycode - KEY_1 +func _input(event: InputEvent) -> void: + if event is InputEventKey and event.pressed: + var joint_index: int = event.keycode - KEY_1 if joint_index >= 0 and joint_index < _joint_types.size(): _selected_joint = _joint_types.values()[joint_index] _update_joint = true -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: if _joint_types.has(option): _selected_joint = _joint_types[option] _update_joint = true -func _on_option_changed(option, checked): +func _on_option_changed(option: String, checked: bool) -> void: match option: OPTION_TEST_CASE_BODIES_COLLIDE: _bodies_collide = checked @@ -90,18 +87,18 @@ func _on_option_changed(option, checked): _update_joint = true -func _create_joint(): +func _create_joint() -> void: cancel_timer() - var root = $Objects + var root: Node3D = $Objects while root.get_child_count(): - var last_child_index = root.get_child_count() - 1 - var last_child = root.get_child(last_child_index) + var last_child_index := root.get_child_count() - 1 + var last_child := root.get_child(last_child_index) root.remove_child(last_child) last_child.queue_free() - var child_body = create_rigidbody_box(BOX_SIZE, true) + var child_body := create_rigidbody_box(BOX_SIZE, true) if _change_positions: root.add_child(child_body) child_body.transform.origin = Vector3(0.0, -1.5, 0.0) @@ -109,7 +106,7 @@ func _create_joint(): child_body.transform.origin = Vector3(0.0, -1.5, 0.0) root.add_child(child_body) - var parent_body = null + var parent_body: RigidBody3D if not _world_attachement: parent_body = create_rigidbody_box(BOX_SIZE, true) if _dynamic_attachement: @@ -124,7 +121,7 @@ func _create_joint(): parent_body.transform.origin = Vector3(0.0, 1.5, 0.0) root.add_child(parent_body) - var joint = _selected_joint.duplicate() + var joint := _selected_joint.duplicate() joint.visible = true joint.set_exclude_nodes_from_collision(not _bodies_collide) root.add_child(joint) diff --git a/3d/physics_tests/tests/functional/test_moving_platform.gd b/3d/physics_tests/tests/functional/test_moving_platform.gd index bbbb57ad..e2ac0a13 100644 --- a/3d/physics_tests/tests/functional/test_moving_platform.gd +++ b/3d/physics_tests/tests/functional/test_moving_platform.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_BODY_TYPE = "Body Type/%s (%d)" const OPTION_SLOPE = "Physics options/Stop on slope (Character only)" @@ -15,29 +14,28 @@ const SHAPE_CYLINDER = "Collision shapes/Cylinder" const SHAPE_SPHERE = "Collision shapes/Sphere" const SHAPE_CONVEX = "Collision shapes/Convex" -var _slope = false -var _snap = false -var _friction = false -var _rough = false -var _animation_physics = false +var _slope := false +var _snap := false +var _friction := false +var _rough := false +var _animation_physics := false -var _body_scene = {} -var _key_list = [] -var _current_body_index = 0 -var _current_body_key = "" +var _body_scene := {} +var _key_list := [] +var _current_body_index := 0 +var _current_body_key := "" var _current_body: PhysicsBody3D = null -var _body_type = ["CharacterBody3D", "RigidBody"] +var _body_type := ["CharacterBody3D", "RigidBody"] -var _shapes = {} -var _current_shape = "" +var _shapes := {} +var _current_shape := "" - -func _ready(): - var options = $Options - var bodies = $Bodies.get_children() +func _ready() -> void: + var options: OptionMenu = $Options + var bodies := $Bodies.get_children() for i in bodies.size(): - var body = bodies[i] - var option_name = OPTION_BODY_TYPE % [body.name, i + 1] + var body := bodies[i] + var option_name := OPTION_BODY_TYPE % [body.name, i + 1] options.add_menu_item(option_name) _key_list.append(option_name) _body_scene[option_name] = get_packed_scene(body) @@ -68,15 +66,14 @@ func _ready(): spawn_body_index(_current_body_index) -func _input(event): - var key_event = event as InputEventKey - if key_event and not key_event.pressed: - var _index = key_event.keycode - KEY_1 +func _input(event: InputEvent) -> void: + if event is InputEventKey and not event.pressed: + var _index: int = event.keycode - KEY_1 if _index >= 0 and _index < _key_list.size(): spawn_body_index(_index) -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: if _body_scene.has(option): spawn_body_key(option) else: @@ -98,7 +95,7 @@ func _on_option_selected(option): spawn_body_index(_current_body_index) -func _on_option_changed(option, checked): +func _on_option_changed(option: String, checked: bool) -> void: match option: OPTION_SLOPE: _slope = checked @@ -117,33 +114,33 @@ func _on_option_changed(option, checked): spawn_body_index(_current_body_index) -func spawn_body_index(body_index): +func spawn_body_index(body_index: int) -> void: if _current_body: _current_body.queue_free() _current_body_index = body_index _current_body_key = _key_list[body_index] - var body_parent = $Bodies - var body = _body_scene[_key_list[body_index]].instantiate() + var body_parent := $Bodies + var body: PhysicsBody3D = _body_scene[_key_list[body_index]].instantiate() _current_body = body init_body() body_parent.add_child(body) start_test() -func spawn_body_key(body_key): +func spawn_body_key(body_key: String) -> void: if _current_body: _current_body.queue_free() _current_body_key = body_key _current_body_index = _key_list.find(body_key) - var body_parent = $Bodies - var body = _body_scene[body_key].instantiate() + var body_parent := $Bodies + var body: PhysicsBody3D = _body_scene[body_key].instantiate() _current_body = body init_body() body_parent.add_child(body) start_test() -func init_body(): +func init_body() -> void: if _current_body is CharacterBody3D: _current_body._stop_on_slopes = _slope _current_body.use_snap = _snap @@ -156,8 +153,8 @@ func init_body(): shape.queue_free() -func start_test(): - var animation_player = $Platforms/MovingPlatform/AnimationPlayer +func start_test() -> void: + var animation_player: AnimationPlayer = $Platforms/MovingPlatform/AnimationPlayer animation_player.stop() if _animation_physics: animation_player.playback_process_mode = AnimationPlayer.ANIMATION_PROCESS_PHYSICS @@ -168,9 +165,10 @@ func start_test(): $LabelBodyType.text = "Body Type: " + _body_type[_current_body_index] + " \nCollision Shape: " + _current_shape -func get_packed_scene(node): +func get_packed_scene(node: Node) -> PackedScene: for child in node.get_children(): child.owner = node - var packed_scene = PackedScene.new() + + var packed_scene := PackedScene.new() packed_scene.pack(node) return packed_scene diff --git a/3d/physics_tests/tests/functional/test_pyramid.gd b/3d/physics_tests/tests/functional/test_pyramid.gd index 63e624bc..fcb8d267 100644 --- a/3d/physics_tests/tests/functional/test_pyramid.gd +++ b/3d/physics_tests/tests/functional/test_pyramid.gd @@ -1,43 +1,41 @@ extends Test +@export_range(1, 100) var height := 10 +@export_range(1, 100) var width_max := 100 +@export_range(1, 100) var depth_max := 1 +@export var box_size := Vector3(1.0, 1.0, 1.0) +@export var box_spacing := Vector3(0.0, 0.0, 0.0) -@export_range(1, 100) var height = 10 -@export_range(1, 100) var width_max = 100 -@export_range(1, 100) var depth_max = 1 -@export var box_size = Vector3(1.0, 1.0, 1.0) -@export var box_spacing = Vector3(0.0, 0.0, 0.0) - - -func _ready(): +func _ready() -> void: _create_pyramid() -func _create_pyramid(): - var root_node = $Pyramid +func _create_pyramid() -> void: + var root_node: Node3D = $Pyramid - var template_body = create_rigidbody_box(box_size, true) + var template_body := create_rigidbody_box(box_size, true) - var pos_y = 0.5 * box_size.y + box_spacing.y + var pos_y := 0.5 * box_size.y + box_spacing.y for level in height: - var level_index = height - level - 1 - var num_boxes = 2 * level_index + 1 - var num_boxes_width = min(num_boxes, width_max) - var num_boxes_depth = min(num_boxes, depth_max) + var level_index := height - level - 1 + var num_boxes := 2 * level_index + 1 + var num_boxes_width := mini(num_boxes, width_max) + var num_boxes_depth := mini(num_boxes, depth_max) - var row_node = Node3D.new() + var row_node := Node3D.new() row_node.transform.origin = Vector3(0.0, pos_y, 0.0) row_node.name = "Row%02d" % (level + 1) root_node.add_child(row_node) - var pos_x = -0.5 * (num_boxes_width - 1) * (box_size.x + box_spacing.x) + var pos_x := -0.5 * (num_boxes_width - 1) * (box_size.x + box_spacing.x) for box_index_x in num_boxes_width: - var pos_z = -0.5 * (num_boxes_depth - 1) * (box_size.z + box_spacing.z) + var pos_z := -0.5 * (num_boxes_depth - 1) * (box_size.z + box_spacing.z) for box_index_z in num_boxes_depth: - var box_index = box_index_x * box_index_z - var box = template_body.duplicate() + var box_index := box_index_x * box_index_z + var box := template_body.duplicate() box.transform.origin = Vector3(pos_x, 0.0, pos_z) box.name = "Box%02d" % (box_index + 1) row_node.add_child(box) diff --git a/3d/physics_tests/tests/functional/test_raycasting.gd b/3d/physics_tests/tests/functional/test_raycasting.gd index 95243a41..75fd83c5 100644 --- a/3d/physics_tests/tests/functional/test_raycasting.gd +++ b/3d/physics_tests/tests/functional/test_raycasting.gd @@ -1,26 +1,25 @@ extends Test - const OPTION_TEST_CASE_HIT_FROM_INSIDE = "Test case/Hit from inside" -var _hit_from_inside = false -var _do_raycasts = false +var _hit_from_inside := false +var _do_raycasts := false -@onready var _raycast_visuals = ImmediateMesh.new() -@onready var _material = StandardMaterial3D.new() +@onready var _raycast_visuals := ImmediateMesh.new() +@onready var _material := StandardMaterial3D.new() -func _ready(): - var options = $Options +func _ready() -> void: + var options: OptionMenu = $Options options.add_menu_item(OPTION_TEST_CASE_HIT_FROM_INSIDE, true, false) options.option_changed.connect(_on_option_changed) - _material.flags_unshaded = true + _material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED _material.vertex_color_use_as_albedo = true - var raycast_mesh_instance = MeshInstance3D.new() + var raycast_mesh_instance := MeshInstance3D.new() raycast_mesh_instance.mesh = _raycast_visuals add_child(raycast_mesh_instance) move_child(raycast_mesh_instance, get_child_count()) @@ -32,7 +31,7 @@ func _ready(): _do_raycasts = true -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if not _do_raycasts: @@ -46,15 +45,15 @@ func _physics_process(delta): _raycast_visuals.surface_begin(Mesh.PRIMITIVE_LINES) for shape in $Shapes.get_children(): - var body = shape as PhysicsBody3D - var space_state = body.get_world_3d().direct_space_state + var body: PhysicsBody3D = shape + var space_state := body.get_world_3d().direct_space_state Log.print_log("* Testing: %s" % body.name) - var center = body.global_transform.origin + var center := body.global_transform.origin # Raycast entering from the top. - var res = _add_raycast(space_state, center + Vector3(0.0, 2.0, 0.0), center) + var res := _add_raycast(space_state, center + Vector3(0.0, 2.0, 0.0), center) Log.print_log("Raycast in: %s" % ("HIT" if res else "NO HIT")) # Raycast exiting from inside. @@ -72,20 +71,20 @@ func _physics_process(delta): _raycast_visuals.surface_set_material(0, _material) -func _on_option_changed(option, checked): +func _on_option_changed(option: String, checked: bool) -> void: match option: OPTION_TEST_CASE_HIT_FROM_INSIDE: _hit_from_inside = checked _do_raycasts = true -func _add_raycast(space_state, pos_start, pos_end): - var params = PhysicsRayQueryParameters3D.new() +func _add_raycast(space_state: PhysicsDirectSpaceState3D, pos_start: Vector3, pos_end: Vector3) -> Dictionary: + var params := PhysicsRayQueryParameters3D.new() params.from = pos_start params.to = pos_end params.hit_from_inside = _hit_from_inside - var result = space_state.intersect_ray(params) + var result := space_state.intersect_ray(params) if result: _raycast_visuals.surface_set_color(Color.GREEN) else: diff --git a/3d/physics_tests/tests/functional/test_rigidbody_ground_check.gd b/3d/physics_tests/tests/functional/test_rigidbody_ground_check.gd index 73c8ed1f..3bc2485d 100644 --- a/3d/physics_tests/tests/functional/test_rigidbody_ground_check.gd +++ b/3d/physics_tests/tests/functional/test_rigidbody_ground_check.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_BIG = "Floor options/Big" const OPTION_SMALL = "Floor options/Small" @@ -8,17 +7,16 @@ const SHAPE_CONCAVE = "Collision shapes/Concave" const SHAPE_CONVEX = "Collision shapes/Convex" const SHAPE_BOX = "Collision shapes/Box" -var _dynamic_shapes_scene -var _floor_shapes = {} -var _floor_size = "Small" +var _dynamic_shapes_scene: PackedScene +var _floor_shapes := {} +var _floor_size := "Small" -var _current_floor_name = SHAPE_CONCAVE -var _current_bodies -var _current_floor +var _current_floor_name := SHAPE_CONCAVE +var _current_bodies: Node3D +var _current_floor: Node3D - -func _ready(): - var options = $Options +func _ready() -> void: + var options: OptionMenu = $Options _dynamic_shapes_scene = get_packed_scene($DynamicShapes/Bodies) _floor_shapes[SHAPE_CONVEX + "Small"] = get_packed_scene($"Floors/ConvexSmall") _floor_shapes[SHAPE_CONVEX + "Big"] = get_packed_scene($"Floors/ConvexBig") @@ -40,7 +38,7 @@ func _ready(): restart_scene() -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: match option: OPTION_BIG: _floor_size = "Big" @@ -51,30 +49,31 @@ func _on_option_selected(option): restart_scene() -func restart_scene(): +func restart_scene() -> void: if _current_bodies: _current_bodies.queue_free() if _current_floor: _current_floor.queue_free() - var dynamic_bodies = _dynamic_shapes_scene.instantiate() + var dynamic_bodies := _dynamic_shapes_scene.instantiate() _current_bodies = dynamic_bodies add_child(dynamic_bodies) - var floor_inst = _floor_shapes[_current_floor_name + _floor_size].instantiate() + var floor_inst: Node3D = _floor_shapes[_current_floor_name + _floor_size].instantiate() _current_floor = floor_inst $Floors.add_child(floor_inst) $LabelBodyType.text = "Floor Type: " + _current_floor_name.rsplit("/", true, 1)[1] + "\nSize: " + _floor_size -func get_packed_scene(node): +func get_packed_scene(node: Node) -> PackedScene: for child in node.get_children(): child.owner = node for child1 in child.get_children(): child1.owner = node for child2 in child1.get_children(): child2.owner = node - var packed_scene = PackedScene.new() + + var packed_scene := PackedScene.new() packed_scene.pack(node) return packed_scene diff --git a/3d/physics_tests/tests/functional/test_rigidbody_ground_check.tscn b/3d/physics_tests/tests/functional/test_rigidbody_ground_check.tscn index 47e66f77..45db90e0 100644 --- a/3d/physics_tests/tests/functional/test_rigidbody_ground_check.tscn +++ b/3d/physics_tests/tests/functional/test_rigidbody_ground_check.tscn @@ -35,12 +35,13 @@ points = PackedVector3Array(-0.7, 0, -0.7, -0.3, 0, 0.8, 0.8, 0, -0.3, 0, -1, 0) [sub_resource type="ArrayMesh" id="15"] _surfaces = [{ "aabb": AABB(-0.7, -1, -0.7, 1.5, 1.00001, 1.5), -"format": 4099, +"format": 34359742467, "index_count": 12, "index_data": PackedByteArray(0, 0, 1, 0, 3, 0, 1, 0, 2, 0, 3, 0, 2, 0, 0, 0, 3, 0, 2, 0, 1, 0, 0, 0), "primitive": 3, +"uv_scale": Vector4(0, 0, 0, 0), "vertex_count": 4, -"vertex_data": PackedByteArray(51, 51, 51, 191, 0, 0, 0, 0, 51, 51, 51, 191, 0, 0, 0, 0, 154, 153, 153, 190, 0, 0, 0, 0, 205, 204, 76, 63, 0, 0, 96, 59, 205, 204, 76, 63, 0, 0, 0, 0, 154, 153, 153, 190, 182, 3, 0, 0, 0, 0, 0, 0, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0) +"vertex_data": PackedByteArray(51, 51, 51, 191, 0, 0, 0, 0, 51, 51, 51, 191, 154, 153, 153, 190, 0, 0, 0, 0, 205, 204, 76, 63, 205, 204, 76, 63, 0, 0, 0, 0, 154, 153, 153, 190, 0, 0, 0, 0, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 59, 182, 3, 0, 0, 0, 0, 0, 0) }] [sub_resource type="PhysicsMaterial" id="17"] @@ -75,19 +76,16 @@ size = Vector3(100, 2, 40) size = Vector3(200, 2, 200) [node name="Test" type="Node3D"] -script = ExtResource( "3" ) +script = ExtResource("3") [node name="LabelBodyType" type="Label" parent="."] offset_left = 14.0 -offset_top = 78.0 +offset_top = 62.0 offset_right = 171.0 -offset_bottom = 92.0 +offset_bottom = 85.0 text = "Floor Type: " -__meta__ = { -"_edit_use_anchors_": false -} -[node name="Options" parent="." instance=ExtResource( "2" )] +[node name="Options" parent="." instance=ExtResource("2")] offset_top = 120.0 offset_bottom = 140.0 focus_mode = 2 @@ -97,79 +95,79 @@ focus_mode = 2 [node name="Bodies" type="Node3D" parent="DynamicShapes"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 5.2912, 0) -[node name="RigidBodyBox" type="RigidDynamicBody3D" parent="DynamicShapes/Bodies"] +[node name="RigidBodyBox" type="RigidBody3D" parent="DynamicShapes/Bodies"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -6, 0, 0) axis_lock_angular_x = true axis_lock_angular_y = true axis_lock_angular_z = true -physics_material_override = SubResource( "1" ) -script = ExtResource( "1" ) +physics_material_override = SubResource("1") +script = ExtResource("1") [node name="CollisionShape" type="CollisionShape3D" parent="DynamicShapes/Bodies/RigidBodyBox"] transform = Transform3D(0.6, 0, 0, 0, 1, 0, 0, 0, 0.6, 0, 0, 0) -shape = SubResource( "2" ) +shape = SubResource("2") [node name="MeshInstance3D" type="MeshInstance3D" parent="DynamicShapes/Bodies/RigidBodyBox/CollisionShape"] -mesh = SubResource( "3" ) +mesh = SubResource("3") -[node name="RigidBodyCapsule" type="RigidDynamicBody3D" parent="DynamicShapes/Bodies"] +[node name="RigidBodyCapsule" type="RigidBody3D" parent="DynamicShapes/Bodies"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 0) axis_lock_angular_x = true axis_lock_angular_y = true axis_lock_angular_z = true -physics_material_override = SubResource( "5" ) -script = ExtResource( "1" ) +physics_material_override = SubResource("5") +script = ExtResource("1") [node name="CollisionShape" type="CollisionShape3D" parent="DynamicShapes/Bodies/RigidBodyCapsule"] transform = Transform3D(0.8, 0, 0, 0, 0.8, 0, 0, 0, 0.8, 0, 0, 0) -shape = SubResource( "6" ) +shape = SubResource("6") [node name="MeshInstance3D" type="MeshInstance3D" parent="DynamicShapes/Bodies/RigidBodyCapsule/CollisionShape"] -mesh = SubResource( "7" ) +mesh = SubResource("7") -[node name="RigidBodyCylinder" type="RigidDynamicBody3D" parent="DynamicShapes/Bodies"] +[node name="RigidBodyCylinder" type="RigidBody3D" parent="DynamicShapes/Bodies"] axis_lock_angular_x = true axis_lock_angular_y = true axis_lock_angular_z = true -physics_material_override = SubResource( "9" ) -script = ExtResource( "1" ) +physics_material_override = SubResource("9") +script = ExtResource("1") [node name="CollisionShape" type="CollisionShape3D" parent="DynamicShapes/Bodies/RigidBodyCylinder"] transform = Transform3D(0.8, 0, 0, 0, 1, 0, 0, 0, 0.8, 0, 0, 0) -shape = SubResource( "10" ) +shape = SubResource("10") [node name="MeshInstance3D" type="MeshInstance3D" parent="DynamicShapes/Bodies/RigidBodyCylinder/CollisionShape"] -mesh = SubResource( "11" ) +mesh = SubResource("11") -[node name="RigidBodyConvex" type="RigidDynamicBody3D" parent="DynamicShapes/Bodies"] +[node name="RigidBodyConvex" type="RigidBody3D" parent="DynamicShapes/Bodies"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.974548, 0) axis_lock_angular_x = true axis_lock_angular_y = true axis_lock_angular_z = true -physics_material_override = SubResource( "13" ) -script = ExtResource( "1" ) +physics_material_override = SubResource("13") +script = ExtResource("1") [node name="CollisionShape" type="CollisionShape3D" parent="DynamicShapes/Bodies/RigidBodyConvex"] transform = Transform3D(1.5, 0, 0, 0, 2, 0, 0, 0, 1.5, 0, 0, 0) -shape = SubResource( "14" ) +shape = SubResource("14") [node name="MeshInstance3D" type="MeshInstance3D" parent="DynamicShapes/Bodies/RigidBodyConvex/CollisionShape"] -mesh = SubResource( "15" ) +mesh = SubResource("15") -[node name="RigidBodySphere" type="RigidDynamicBody3D" parent="DynamicShapes/Bodies"] +[node name="RigidBodySphere" type="RigidBody3D" parent="DynamicShapes/Bodies"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6, 0, 0) axis_lock_angular_x = true axis_lock_angular_y = true axis_lock_angular_z = true -physics_material_override = SubResource( "17" ) -script = ExtResource( "1" ) +physics_material_override = SubResource("17") +script = ExtResource("1") [node name="CollisionShape" type="CollisionShape3D" parent="DynamicShapes/Bodies/RigidBodySphere"] transform = Transform3D(0.8, 0, 0, 0, 0.8, 0, 0, 0, 0.8, 0, 0, 0) -shape = SubResource( "18" ) +shape = SubResource("18") [node name="MeshInstance3D" type="MeshInstance3D" parent="DynamicShapes/Bodies/RigidBodySphere/CollisionShape"] -mesh = SubResource( "19" ) +mesh = SubResource("19") [node name="Floors" type="Node3D" parent="."] @@ -180,20 +178,20 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -10) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/ConvexSmall/ConvexFloor"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/ConvexSmall/ConvexFloor"] -shape = SubResource( "24" ) +shape = SubResource("24") [node name="ConvexFloor2" type="StaticBody3D" parent="Floors/ConvexSmall"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/ConvexSmall/ConvexFloor2"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/ConvexSmall/ConvexFloor2"] -shape = SubResource( "25" ) +shape = SubResource("25") [node name="ConvexBig" type="Node3D" parent="Floors"] @@ -201,10 +199,10 @@ shape = SubResource( "25" ) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/ConvexBig/ConvexFloor"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/ConvexBig/ConvexFloor"] -shape = SubResource( "26" ) +shape = SubResource("26") [node name="ConcaveSmall" type="Node3D" parent="Floors"] @@ -213,22 +211,22 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -10) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/ConcaveSmall/ConcaveFloor"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/ConcaveSmall/ConcaveFloor"] transform = Transform3D(25, 0, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0) -shape = SubResource( "27" ) +shape = SubResource("27") [node name="ConcaveFloor2" type="StaticBody3D" parent="Floors/ConcaveSmall"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/ConcaveSmall/ConcaveFloor2"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/ConcaveSmall/ConcaveFloor2"] transform = Transform3D(25, 0, 0, 0, 1, 0, 0, 0, 10, 0, 0, 0) -shape = SubResource( "27" ) +shape = SubResource("27") [node name="ConcaveBig" type="Node3D" parent="Floors"] @@ -236,10 +234,10 @@ shape = SubResource( "27" ) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/ConcaveBig/ConcaveFloor"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/ConcaveBig/ConcaveFloor"] -shape = SubResource( "28" ) +shape = SubResource("28") [node name="BoxSmall" type="Node3D" parent="Floors"] @@ -248,22 +246,22 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -10) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/BoxSmall/BoxFloor"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/BoxSmall/BoxFloor"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -shape = SubResource( "29" ) +shape = SubResource("29") [node name="BoxFloor2" type="StaticBody3D" parent="Floors/BoxSmall"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/BoxSmall/BoxFloor2"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/BoxSmall/BoxFloor2"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -shape = SubResource( "29" ) +shape = SubResource("29") [node name="BoxBig" type="Node3D" parent="Floors"] @@ -271,16 +269,16 @@ shape = SubResource( "29" ) [node name="MeshInstance3D" type="MeshInstance3D" parent="Floors/BoxBig/BoxFloor"] visible = false -mesh = SubResource( "23" ) +mesh = SubResource("23") [node name="CollisionShape" type="CollisionShape3D" parent="Floors/BoxBig/BoxFloor"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1, 0) -shape = SubResource( "30" ) +shape = SubResource("30") [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.604, 22.124) far = 1000.0 -script = ExtResource( "4" ) +script = ExtResource("4") [node name="OmniLight" type="OmniLight3D" parent="Camera3D"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 14.6965, -5.95932) diff --git a/3d/physics_tests/tests/functional/test_stack.gd b/3d/physics_tests/tests/functional/test_stack.gd index e860be8c..9ca71802 100644 --- a/3d/physics_tests/tests/functional/test_stack.gd +++ b/3d/physics_tests/tests/functional/test_stack.gd @@ -1,38 +1,36 @@ extends Test +@export_range(1, 100) var height := 10 +@export_range(1, 100) var width := 1 +@export_range(1, 100) var depth := 1 +@export var box_size := Vector3(1.0, 1.0, 1.0) +@export var box_spacing := Vector3(0.0, 0.0, 0.0) -@export_range(1, 100) var height = 10 -@export_range(1, 100) var width = 1 -@export_range(1, 100) var depth = 1 -@export var box_size = Vector3(1.0, 1.0, 1.0) -@export var box_spacing = Vector3(0.0, 0.0, 0.0) - - -func _ready(): +func _ready() -> void: _create_stack() -func _create_stack(): - var root_node = $Stack +func _create_stack() -> void: + var root_node: Node3D = $Stack - var template_body = create_rigidbody_box(box_size, true) + var template_body := create_rigidbody_box(box_size, true) - var pos_y = 0.5 * box_size.y + box_spacing.y + var pos_y := 0.5 * box_size.y + box_spacing.y for level in height: - var row_node = Node3D.new() + var row_node := Node3D.new() row_node.transform.origin = Vector3(0.0, pos_y, 0.0) row_node.name = "Row%02d" % (level + 1) root_node.add_child(row_node) - var pos_x = -0.5 * (width - 1) * (box_size.x + box_spacing.x) + var pos_x := -0.5 * (width - 1) * (box_size.x + box_spacing.x) for box_index_x in width: - var pos_z = -0.5 * (depth - 1) * (box_size.z + box_spacing.z) + var pos_z := -0.5 * (depth - 1) * (box_size.z + box_spacing.z) for box_index_z in depth: - var box_index = box_index_x * box_index_z - var box = template_body.duplicate() + var box_index := box_index_x * box_index_z + var box := template_body.duplicate() box.transform.origin = Vector3(pos_x, 0.0, pos_z) box.name = "Box%02d" % (box_index + 1) row_node.add_child(box) diff --git a/3d/physics_tests/tests/functional/test_stack.tscn b/3d/physics_tests/tests/functional/test_stack.tscn index 73adb9a4..9e00bddb 100644 --- a/3d/physics_tests/tests/functional/test_stack.tscn +++ b/3d/physics_tests/tests/functional/test_stack.tscn @@ -5,13 +5,13 @@ [ext_resource type="Script" path="res://utils/camera_orbit.gd" id="4"] [node name="Test" type="Node3D"] -script = ExtResource( "1" ) +script = ExtResource("1") [node name="Stack" type="Node3D" parent="."] -[node name="StaticBodyPlane" parent="." instance=ExtResource( "2" )] +[node name="StaticBodyPlane" parent="." instance=ExtResource("2")] [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4.53602, 12.2684) current = true -script = ExtResource( "4" ) +script = ExtResource("4") diff --git a/3d/physics_tests/tests/performance/test_perf_broadphase.gd b/3d/physics_tests/tests/performance/test_perf_broadphase.gd index e55da407..a50b496e 100644 --- a/3d/physics_tests/tests/performance/test_perf_broadphase.gd +++ b/3d/physics_tests/tests/performance/test_perf_broadphase.gd @@ -1,21 +1,19 @@ extends Test - const BOX_SIZE = Vector3(0.8, 0.8, 0.8) const BOX_SPACE = Vector3(1.0, 1.0, 1.0) -@export_range(1, 1000) var row_size = 20 -@export_range(1, 1000) var column_size = 20 -@export_range(1, 1000) var depth_size = 20 +@export_range(1, 1000) var row_size := 20 +@export_range(1, 1000) var column_size := 20 +@export_range(1, 1000) var depth_size := 20 -var _objects = [] +var _objects: Array[Node3D] = [] -var _log_physics = false -var _log_physics_time = 0 -var _log_physics_time_start = 0 +var _log_physics := false +var _log_physics_time := 0 +var _log_physics_time_start := 0 - -func _ready(): +func _ready() -> void: await start_timer(1.0).timeout if is_timer_canceled(): return @@ -67,49 +65,49 @@ func _ready(): Log.print_log("* Done.") -func _exit_tree(): +func _exit_tree() -> void: for object in _objects: object.free() -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if _log_physics: - var time = Time.get_ticks_usec() - var time_delta = time - _log_physics_time - var time_total = time - _log_physics_time_start + var time := Time.get_ticks_usec() + var time_delta := time - _log_physics_time + var time_total := time - _log_physics_time_start _log_physics_time = time Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total]) -func _log_physics_start(): +func _log_physics_start() -> void: _log_physics = true _log_physics_time_start = Time.get_ticks_usec() _log_physics_time = _log_physics_time_start -func _log_physics_stop(): +func _log_physics_stop() -> void: _log_physics = false -func _create_objects(): +func _create_objects() -> void: _objects.clear() Log.print_log("* Creating objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() - var pos_x = -0.5 * (row_size - 1) * BOX_SPACE.x + var pos_x := -0.5 * (row_size - 1) * BOX_SPACE.x for row in row_size: - var pos_y = -0.5 * (column_size - 1) * BOX_SPACE.y + var pos_y := -0.5 * (column_size - 1) * BOX_SPACE.y for column in column_size: - var pos_z = -0.5 * (depth_size - 1) * BOX_SPACE.z + var pos_z := -0.5 * (depth_size - 1) * BOX_SPACE.z for depth in depth_size: # Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape. - var box = create_rigidbody_box(BOX_SIZE) + var box: RigidBody3D = create_rigidbody_box(BOX_SIZE) box.gravity_scale = 0.0 box.transform.origin = Vector3(pos_x, pos_y, pos_z) _objects.push_back(box) @@ -124,11 +122,11 @@ func _create_objects(): Log.print_log(" Create Time: %.3f ms" % (0.001 * timer)) -func _add_objects(): - var root_node = $Objects +func _add_objects() -> void: + var root_node: Node3D = $Objects Log.print_log("* Adding objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() for object in _objects: root_node.add_child(object) @@ -137,9 +135,9 @@ func _add_objects(): Log.print_log(" Add Time: %.3f ms" % (0.001 * timer)) -func _move_objects(): +func _move_objects() -> void: Log.print_log("* Moving objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() for object in _objects: object.transform.origin += BOX_SPACE @@ -148,15 +146,15 @@ func _move_objects(): Log.print_log(" Move Time: %.3f ms" % (0.001 * timer)) -func _remove_objects(): - var root_node = $Objects +func _remove_objects() -> void: + var root_node: Node3D = $Objects Log.print_log("* Removing objects...") - var timer = Time.get_ticks_usec() + var timer := Time.get_ticks_usec() # Remove objects in reversed order to avoid the overhead of changing children index in parent. - var object_count = _objects.size() - for object_index in range(object_count): + var object_count := _objects.size() + for object_index in object_count: root_node.remove_child(_objects[object_count - object_index - 1]) timer = Time.get_ticks_usec() - timer diff --git a/3d/physics_tests/tests/performance/test_perf_contacts.gd b/3d/physics_tests/tests/performance/test_perf_contacts.gd index 90bb6b2e..63a4d89a 100644 --- a/3d/physics_tests/tests/performance/test_perf_contacts.gd +++ b/3d/physics_tests/tests/performance/test_perf_contacts.gd @@ -1,6 +1,5 @@ extends Test - const OPTION_TYPE_ALL = "Shape type/All" const OPTION_TYPE_BOX = "Shape type/Box" const OPTION_TYPE_SPHERE = "Shape type/Sphere" @@ -8,24 +7,23 @@ const OPTION_TYPE_CAPSULE = "Shape type/Capsule" const OPTION_TYPE_CYLINDER = "Shape type/Cylinder" const OPTION_TYPE_CONVEX = "Shape type/Convex" -@export var spawns = [] -@export var spawn_count = 100 -@export var spawn_randomize = Vector3.ZERO +@export var spawns: Array[NodePath] = [] +@export var spawn_count := 100 +@export var spawn_randomize := Vector3.ZERO -var _object_templates = [] +var _object_templates: Array[Node3D] = [] -var _log_physics = false -var _log_physics_time = 0 -var _log_physics_time_start = 0 +var _log_physics := false +var _log_physics_time := 0 +var _log_physics_time_start := 0 - -func _ready(): +func _ready() -> void: await start_timer(0.5).timeout if is_timer_canceled(): return while $DynamicShapes.get_child_count(): - var type_node = $DynamicShapes.get_child(0) + var type_node: Node3D = $DynamicShapes.get_child(0) _object_templates.push_back(type_node) $DynamicShapes.remove_child(type_node) @@ -40,33 +38,33 @@ func _ready(): await _start_all_types() -func _exit_tree(): +func _exit_tree() -> void: for object_template in _object_templates: object_template.free() -func _physics_process(delta): +func _physics_process(delta: float) -> void: super._physics_process(delta) if _log_physics: - var time = Time.get_ticks_usec() - var time_delta = time - _log_physics_time - var time_total = time - _log_physics_time_start + var time := Time.get_ticks_usec() + var time_delta := time - _log_physics_time + var time_total := time - _log_physics_time_start _log_physics_time = time Log.print_log(" Physics Tick: %.3f ms (total = %.3f ms)" % [0.001 * time_delta, 0.001 * time_total]) -func _log_physics_start(): +func _log_physics_start() -> void: _log_physics = true _log_physics_time_start = Time.get_ticks_usec() _log_physics_time = _log_physics_time_start -func _log_physics_stop(): +func _log_physics_stop() -> void: _log_physics = false -func _on_option_selected(option): +func _on_option_selected(option: String) -> void: cancel_timer() _despawn_objects() @@ -86,9 +84,9 @@ func _on_option_selected(option): await _start_type(_find_type_index("Convex")) -func _find_type_index(type_name): +func _find_type_index(type_name: String) -> int: for type_index in range(_object_templates.size()): - var type_node = _object_templates[type_index] + var type_node := _object_templates[type_index] if String(type_node.name).find(type_name) > -1: return type_index @@ -96,7 +94,7 @@ func _find_type_index(type_name): return -1 -func _start_type(type_index): +func _start_type(type_index: int) -> void: if type_index < 0: return if type_index >= _object_templates.size(): @@ -138,10 +136,10 @@ func _start_type(type_index): await start_timer(1.0).timeout -func _start_all_types(): +func _start_all_types() -> void: Log.print_log("* Start all types.") - for type_index in range(_object_templates.size()): + for type_index in _object_templates.size(): await _start_type(type_index) if is_timer_canceled(): return @@ -149,25 +147,25 @@ func _start_all_types(): Log.print_log("* Done all types.") -func _spawn_objects(type_index): - var template_node = _object_templates[type_index] +func _spawn_objects(type_index: int) -> void: + var template_node := _object_templates[type_index] Log.print_log("* Spawning: " + String(template_node.name)) for spawn in spawns: - var spawn_parent = get_node(spawn) + var spawn_parent := get_node(spawn) for _node_index in range(spawn_count): # Create a new object and shape every time to avoid the overhead of connecting many bodies to the same shape. - var collision = template_node.get_child(0).duplicate() + var collision := template_node.get_child(0).duplicate() collision.shape = collision.shape.duplicate() - var body = template_node.duplicate() + var body := template_node.duplicate() body.transform = Transform3D.IDENTITY if spawn_randomize != Vector3.ZERO: body.transform.origin.x = randf() * spawn_randomize.x body.transform.origin.y = randf() * spawn_randomize.y body.transform.origin.z = randf() * spawn_randomize.z - var prev_collision = body.get_child(0) + var prev_collision := body.get_child(0) body.remove_child(prev_collision) prev_collision.queue_free() body.add_child(collision) @@ -175,26 +173,26 @@ func _spawn_objects(type_index): spawn_parent.add_child(body) -func _activate_objects(): +func _activate_objects() -> void: Log.print_log("* Activating") for spawn in spawns: - var spawn_parent = get_node(spawn) + var spawn_parent := get_node(spawn) - for node_index in range(spawn_parent.get_child_count()): - var node = spawn_parent.get_child(node_index) as RigidBody3D + for node_index in spawn_parent.get_child_count(): + var node: RigidBody3D = spawn_parent.get_child(node_index) node.set_sleeping(false) -func _despawn_objects(): +func _despawn_objects() -> void: Log.print_log("* Despawning") for spawn in spawns: - var spawn_parent = get_node(spawn) + var spawn_parent := get_node(spawn) # Remove objects in reversed order to avoid the overhead of changing children index in parent. - var object_count = spawn_parent.get_child_count() - for object_index in range(object_count): - var node = spawn_parent.get_child(object_count - object_index - 1) + var object_count := spawn_parent.get_child_count() + for object_index in object_count: + var node := spawn_parent.get_child(object_count - object_index - 1) spawn_parent.remove_child(node) node.queue_free() diff --git a/3d/physics_tests/tests_menu.gd b/3d/physics_tests/tests_menu.gd index 7770fbaa..e4bffee4 100644 --- a/3d/physics_tests/tests_menu.gd +++ b/3d/physics_tests/tests_menu.gd @@ -2,28 +2,28 @@ extends OptionMenu class TestData: - var id - var scene_path + var id := "" + var scene_path := "" -var _test_list = [] +var _test_list: Array[TestData] = [] -var _current_test = null +var _current_test: TestData = null var _current_test_scene: Node = null -func _ready(): +func _ready() -> void: option_selected.connect(_on_option_selected) -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"restart_test"): if _current_test: _start_test(_current_test) -func add_test(id, scene_path): - var test_data = TestData.new() +func add_test(id: String, scene_path: String) -> void: + var test_data := TestData.new() test_data.id = id test_data.scene_path = scene_path _test_list.append(test_data) @@ -31,13 +31,13 @@ func add_test(id, scene_path): add_menu_item(id) -func _on_option_selected(item_path): +func _on_option_selected(item_path: String) -> void: for test in _test_list: if test.id == item_path: _start_test(test) -func _start_test(test): +func _start_test(test: TestData) -> void: _current_test = test if _current_test_scene: @@ -45,9 +45,9 @@ func _start_test(test): _current_test_scene = null Log.print_log("*** STARTING TEST: " + test.id) - var scene = load(test.scene_path) + var scene := load(test.scene_path) _current_test_scene = scene.instantiate() get_tree().root.add_child(_current_test_scene) - var label_test = get_node(^"../LabelTest") + var label_test: Label = $"../LabelTest" label_test.test_name = test.id diff --git a/3d/physics_tests/utils/camera_orbit.gd b/3d/physics_tests/utils/camera_orbit.gd index 329b81be..899504eb 100644 --- a/3d/physics_tests/utils/camera_orbit.gd +++ b/3d/physics_tests/utils/camera_orbit.gd @@ -1,35 +1,32 @@ extends Camera3D - const ROTATION_COEFF = 0.02 -var _rotation_enabled = false -var _rotation_pivot +var _rotation_enabled := false +var _rotation_pivot: Node3D - -func _ready(): +func _ready() -> void: _initialize_pivot.call_deferred() -func _unhandled_input(event): - var mouse_button_event = event as InputEventMouseButton - if mouse_button_event: - if mouse_button_event.button_index == MOUSE_BUTTON_RIGHT: - _rotation_enabled = mouse_button_event.pressed +func _unhandled_input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_RIGHT: + _rotation_enabled = event.pressed + return if not _rotation_enabled: return - var mouse_motion_event = event as InputEventMouseMotion - if mouse_motion_event: - var rotation_delta = mouse_motion_event.relative.x + if event is InputEventMouseMotion: + var rotation_delta: float = event.relative.x _rotation_pivot.rotate(Vector3.UP, -rotation_delta * ROTATION_COEFF) -func _initialize_pivot(): +func _initialize_pivot() -> void: _rotation_pivot = Node3D.new() - var camera_parent = get_parent() + var camera_parent := get_parent() camera_parent.add_child(_rotation_pivot) camera_parent.remove_child(self) _rotation_pivot.add_child(self) diff --git a/3d/physics_tests/utils/characterbody_physics.gd b/3d/physics_tests/utils/characterbody_physics.gd index 6a211738..02a48c05 100644 --- a/3d/physics_tests/utils/characterbody_physics.gd +++ b/3d/physics_tests/utils/characterbody_physics.gd @@ -1,12 +1,11 @@ extends CharacterBody3D +@export var _stop_on_slopes := false +@export var use_snap := false -@export var _stop_on_slopes = false -@export var use_snap = false +var _gravity := 20.0 -var _gravity = 20.0 - -func _physics_process(delta): +func _physics_process(delta: float) -> void: if is_on_floor(): floor_snap_length = 0.2 else: diff --git a/3d/physics_tests/utils/container_log.gd b/3d/physics_tests/utils/container_log.gd index 3ccf84a6..0e43fc7e 100644 --- a/3d/physics_tests/utils/container_log.gd +++ b/3d/physics_tests/utils/container_log.gd @@ -1,40 +1,39 @@ extends Control - const MAX_ENTRIES = 100 -var _entry_template +var _entry_template: Label -func _enter_tree(): +func _enter_tree() -> void: Log.entry_logged.connect(_on_log_entry) - _entry_template = get_child(0) as Label + _entry_template = get_child(0) remove_child(_entry_template) -func _exit_tree(): +func _exit_tree() -> void: _entry_template.free() -func clear(): +func clear() -> void: while get_child_count(): - var entry = get_child(get_child_count() - 1) + var entry: Label = get_child(get_child_count() - 1) remove_child(entry) entry.queue_free() -func _on_log_entry(message, type): - var new_entry = _entry_template.duplicate() as Label +func _on_log_entry(message: String, type: Log.LogType) -> void: + var new_entry: Label = _entry_template.duplicate() - new_entry.set_text(message) + new_entry.text = message if type == Log.LogType.ERROR: new_entry.modulate = Color.RED else: new_entry.modulate = Color.WHITE if get_child_count() >= MAX_ENTRIES: - var first_entry = get_child(0) as Label + var first_entry: Label = get_child(0) remove_child(first_entry) first_entry.queue_free() diff --git a/3d/physics_tests/utils/control3d.gd b/3d/physics_tests/utils/control3d.gd index bcea6796..dffe1713 100644 --- a/3d/physics_tests/utils/control3d.gd +++ b/3d/physics_tests/utils/control3d.gd @@ -1,30 +1,28 @@ extends Control +@export var world_offset := Vector3.ZERO -@export var world_offset = Vector3.ZERO +var _pos_offset: Vector2 +var _attachment: Node3D -var _pos_offset -var _attachment - - -func _ready(): +func _ready() -> void: _pos_offset = position - _attachment = get_parent() as Node3D + _attachment = get_parent() -func _process(_delta): +func _process(_delta: float) -> void: if _attachment == null: return - var viewport = get_viewport() + var viewport := get_viewport() if viewport == null: return - var camera = viewport.get_camera_3d() + var camera := viewport.get_camera_3d() if camera == null: return - var world_pos = world_offset + _attachment.global_transform.origin - var screen_pos = camera.unproject_position(world_pos) + var world_pos := world_offset + _attachment.global_transform.origin + var screen_pos := camera.unproject_position(world_pos) position = _pos_offset + screen_pos - 0.5 * size diff --git a/3d/physics_tests/utils/label_engine.gd b/3d/physics_tests/utils/label_engine.gd index 6f0cbe80..87ec5dc6 100644 --- a/3d/physics_tests/utils/label_engine.gd +++ b/3d/physics_tests/utils/label_engine.gd @@ -1,12 +1,12 @@ extends Label - -func _process(_delta): - var engine_name = "" +func _ready() -> void: + var engine_name := "" match System.get_physics_engine(): System.PhysicsEngine.GODOT_PHYSICS: engine_name = "GodotPhysics 3D" System.PhysicsEngine.OTHER: - var engine_setting = ProjectSettings.get_setting("physics/3d/physics_engine") + var engine_setting := str(ProjectSettings.get_setting("physics/3d/physics_engine")) engine_name = "Other (%s)" % engine_setting - set_text("Physics engine: %s" % engine_name) + + text = "Physics engine: %s" % engine_name diff --git a/3d/physics_tests/utils/label_fps.gd b/3d/physics_tests/utils/label_fps.gd index 6f2c6f30..8165e7f2 100644 --- a/3d/physics_tests/utils/label_fps.gd +++ b/3d/physics_tests/utils/label_fps.gd @@ -1,5 +1,4 @@ extends Label - -func _process(_delta): - set_text("FPS: %d" % Engine.get_frames_per_second()) +func _process(_delta: float) -> void: + text = "%d FPS (%.2f mspf)" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()] diff --git a/3d/physics_tests/utils/label_pause.gd b/3d/physics_tests/utils/label_pause.gd index d0b9a060..0171cdaa 100644 --- a/3d/physics_tests/utils/label_pause.gd +++ b/3d/physics_tests/utils/label_pause.gd @@ -1,5 +1,4 @@ extends Label - -func _process(_delta): +func _process(_delta: float) -> void: visible = get_tree().paused diff --git a/3d/physics_tests/utils/label_test.gd b/3d/physics_tests/utils/label_test.gd index 01e0c1bc..91bfe870 100644 --- a/3d/physics_tests/utils/label_test.gd +++ b/3d/physics_tests/utils/label_test.gd @@ -1,13 +1,12 @@ extends Label - -var test_name = "": +var test_name := "": set(value): if (test_name != value): return test_name = value - set_text("Test: %s" % test_name) + text = "Test: %s" % test_name -func _ready(): - set_text("Select a test from the menu to start it") +func _ready() -> void: + text = "Select a test from the menu to start it" diff --git a/3d/physics_tests/utils/label_version.gd b/3d/physics_tests/utils/label_version.gd index b2185fb9..944e135a 100644 --- a/3d/physics_tests/utils/label_version.gd +++ b/3d/physics_tests/utils/label_version.gd @@ -1,5 +1,4 @@ extends Label - -func _process(_delta): +func _process(_delta: float) -> void: set_text("Godot Version: %s" % Engine.get_version_info().string) diff --git a/3d/physics_tests/utils/option_menu.gd b/3d/physics_tests/utils/option_menu.gd index a8088267..5933cb93 100644 --- a/3d/physics_tests/utils/option_menu.gd +++ b/3d/physics_tests/utils/option_menu.gd @@ -1,24 +1,22 @@ class_name OptionMenu extends MenuButton +signal option_selected(item_path: String) +signal option_changed(item_path: String, checked: bool) -signal option_selected(item_path) -signal option_changed(item_path, checked) - - -func add_menu_item(item_path, checkbox = false, checked = false): - var path_elements = item_path.split("/", false) - var path_element_count = path_elements.size() +func add_menu_item(item_path: String, checkbox: bool = false, checked: bool = false) -> void: + var path_elements := item_path.split("/", false) + var path_element_count := path_elements.size() assert(path_element_count > 0) - var path = "" - var popup = get_popup() - for element_index in range(path_element_count - 1): - var popup_label = path_elements[element_index] + var path := "" + var popup := get_popup() + for element_index in path_element_count - 1: + var popup_label := path_elements[element_index] path += popup_label + "/" popup = _add_popup(popup, path, popup_label) - var label = path_elements[path_element_count - 1] + var label := path_elements[path_element_count - 1] if checkbox: popup.add_check_item(label) popup.set_item_checked(popup.get_item_count() - 1, checked) @@ -26,18 +24,18 @@ func add_menu_item(item_path, checkbox = false, checked = false): popup.add_item(label) -func _add_item(parent_popup, label): +func _add_item(parent_popup: PopupMenu, label: String) -> void: parent_popup.add_item(label) -func _add_popup(parent_popup, path, label): +func _add_popup(parent_popup: PopupMenu, path: String, label: String) -> PopupMenu: if parent_popup.has_node(label): - var popup_node = parent_popup.get_node(label) - var popup_menu = popup_node as PopupMenu - assert(popup_menu) - return popup_menu + var popup_node := parent_popup.get_node(label) + var new_popup_menu: PopupMenu = popup_node + assert(new_popup_menu) + return new_popup_menu - var popup_menu = PopupMenu.new() + var popup_menu := PopupMenu.new() popup_menu.name = label popup_menu.hide_on_checkable_item_selection = false @@ -49,11 +47,11 @@ func _add_popup(parent_popup, path, label): return popup_menu -func _on_item_pressed(item_index, popup_menu, path): - var item_path = path + popup_menu.get_item_text(item_index) +func _on_item_pressed(item_index: int, popup_menu: PopupMenu, path: String) -> void: + var item_path := path + popup_menu.get_item_text(item_index) if popup_menu.is_item_checkable(item_index): - var checked = not popup_menu.is_item_checked(item_index) + var checked := not popup_menu.is_item_checked(item_index) popup_menu.set_item_checked(item_index, checked) option_changed.emit(item_path, checked) else: diff --git a/3d/physics_tests/utils/rigidbody_ground_check.gd b/3d/physics_tests/utils/rigidbody_ground_check.gd index d4c7f441..f8ea8934 100644 --- a/3d/physics_tests/utils/rigidbody_ground_check.gd +++ b/3d/physics_tests/utils/rigidbody_ground_check.gd @@ -1,33 +1,31 @@ extends RigidBody3D +var _dir := 1.0 +var _distance := 10.0 +var _walk_spd := 100.0 +var _acceleration := 22.0 +var _is_on_floor := false -@onready var _forward = -transform.basis.z -@onready var _collision_shape = $CollisionShape -@onready var _material = $CollisionShape/MeshInstance3D.get_active_material(0) +@onready var _forward := -transform.basis.z +@onready var _collision_shape := $CollisionShape +@onready var _material: StandardMaterial3D = $CollisionShape/MeshInstance3D.get_active_material(0) -var _dir = 1.0 -var _distance = 10.0 -var _walk_spd = 100.0 -var _acceleration = 22.0 -var _is_on_floor = false - - -func _ready(): +func _ready() -> void: if not _material: _material = StandardMaterial3D.new() $CollisionShape/MeshInstance3D.set_surface_override_material(0, _material) -func _process(_delta): +func _process(_delta: float) -> void: if _is_on_floor: _material.albedo_color = Color.WHITE else: _material.albedo_color = Color.RED -func _integrate_forces(state): - var delta = state.step - var velocity = (_forward * _dir * _walk_spd * delta) + (state.linear_velocity * Vector3.UP) +func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: + var delta := state.step + var velocity := (_forward * _dir * _walk_spd * delta) + (state.linear_velocity * Vector3.UP) state.linear_velocity = state.linear_velocity.move_toward(velocity, _acceleration * delta) if state.transform.origin.z < -_distance: @@ -38,13 +36,13 @@ func _integrate_forces(state): ground_check() -func ground_check(): - var space_state = get_world_3d().direct_space_state - var shape = PhysicsShapeQueryParameters3D.new() +func ground_check() -> void: + var space_state := get_world_3d().direct_space_state + var shape := PhysicsShapeQueryParameters3D.new() shape.transform = _collision_shape.global_transform shape.shape_rid = _collision_shape.shape.get_rid() shape.collision_mask = 2 - var result = space_state.get_rest_info(shape) + var result := space_state.get_rest_info(shape) if result: _is_on_floor = true else: diff --git a/3d/physics_tests/utils/rigidbody_pick.gd b/3d/physics_tests/utils/rigidbody_pick.gd index 5bfd38cf..57559461 100644 --- a/3d/physics_tests/utils/rigidbody_pick.gd +++ b/3d/physics_tests/utils/rigidbody_pick.gd @@ -1,53 +1,49 @@ extends RigidBody3D - const MOUSE_DELTA_COEFFICIENT = 0.01 const CAMERA_DISTANCE_COEFFICIENT = 0.2 -var _picked = false -var _last_mouse_pos = Vector2.ZERO -var _mouse_pos = Vector2.ZERO +var _picked := false +var _last_mouse_pos := Vector2.ZERO +var _mouse_pos := Vector2.ZERO - -func _ready(): +func _ready() -> void: input_ray_pickable = true -func _input(event): - var mouse_event = event as InputEventMouseButton - if mouse_event and not mouse_event.pressed: - if mouse_event.button_index == MOUSE_BUTTON_LEFT: +func _input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if not event.pressed and event.button_index == MOUSE_BUTTON_LEFT: _picked = false - var mouse_motion = event as InputEventMouseMotion - if mouse_motion: - _mouse_pos = mouse_motion.position + if event is InputEventMouseMotion: + _mouse_pos = event.position -func _input_event(_viewport, event, _click_pos, _click_normal, _shape_idx): - var mouse_event = event as InputEventMouseButton - if mouse_event and mouse_event.pressed: - if mouse_event.button_index == MOUSE_BUTTON_LEFT: +func _input_event(_camera: Camera3D, event: InputEvent, _position: Vector3, _normal: Vector3, _shape_idx: int) -> void: + if event is InputEventMouseButton: + if event.pressed and event.button_index == MOUSE_BUTTON_LEFT: _picked = true - _mouse_pos = mouse_event.position + _mouse_pos = event.position _last_mouse_pos = _mouse_pos -func _physics_process(delta): +func _physics_process(delta: float) -> void: if _picked: - var mouse_delta = _mouse_pos - _last_mouse_pos + var mouse_delta := _mouse_pos - _last_mouse_pos var world_delta := Vector3.ZERO world_delta.x = mouse_delta.x * MOUSE_DELTA_COEFFICIENT world_delta.y = -mouse_delta.y * MOUSE_DELTA_COEFFICIENT - var camera = get_viewport().get_camera_3d() + var camera := get_viewport().get_camera_3d() if camera: - var camera_basis = camera.global_transform.basis + var camera_basis := camera.global_transform.basis world_delta = camera_basis * world_delta - var camera_dist = camera.global_transform.origin.distance_to(global_transform.origin) - var fov_coefficient = camera.fov / 70.0 + var camera_dist := camera.global_transform.origin.distance_to(global_transform.origin) + const DEFAULT_CAMERA_FOV = 75.0 + var fov_coefficient := camera.fov / DEFAULT_CAMERA_FOV world_delta *= CAMERA_DISTANCE_COEFFICIENT * camera_dist * fov_coefficient if freeze: diff --git a/3d/physics_tests/utils/scroll_log.gd b/3d/physics_tests/utils/scroll_log.gd index 7c12c10d..497738f0 100644 --- a/3d/physics_tests/utils/scroll_log.gd +++ b/3d/physics_tests/utils/scroll_log.gd @@ -1,14 +1,12 @@ extends ScrollContainer +@export var auto_scroll := false -@export var auto_scroll: bool = false - - -func _process(_delta): +func _process(_delta: float) -> void: if auto_scroll: - var scrollbar = get_v_scroll_bar() + var scrollbar := get_v_scroll_bar() scrollbar.value = scrollbar.max_value -func _on_check_box_scroll_toggled(button_pressed): +func _on_check_box_scroll_toggled(button_pressed: bool) -> void: auto_scroll = button_pressed diff --git a/3d/physics_tests/utils/system.gd b/3d/physics_tests/utils/system.gd index 7c37c29d..af0a233c 100644 --- a/3d/physics_tests/utils/system.gd +++ b/3d/physics_tests/utils/system.gd @@ -1,20 +1,20 @@ extends Node - enum PhysicsEngine { GODOT_PHYSICS, OTHER, } -var _engine = PhysicsEngine.OTHER +var _engine := PhysicsEngine.OTHER - -func _enter_tree(): +func _enter_tree() -> void: process_mode = Node.PROCESS_MODE_ALWAYS + # Always enable visible collision shapes on startup + # (same as the Debug > Visible Collision Shapes option). get_tree().debug_collisions_hint = true - var engine_string = ProjectSettings.get_setting("physics/3d/physics_engine") + var engine_string: String = ProjectSettings.get_setting("physics/3d/physics_engine") match engine_string: "DEFAULT": _engine = PhysicsEngine.GODOT_PHYSICS @@ -24,7 +24,7 @@ func _enter_tree(): _engine = PhysicsEngine.OTHER -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"toggle_full_screen"): if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) @@ -32,7 +32,7 @@ func _process(_delta): DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) if Input.is_action_just_pressed(&"toggle_debug_collision"): - var debug_collision_enabled = not _is_debug_collision_enabled() + var debug_collision_enabled := not _is_debug_collision_enabled() _set_debug_collision_enabled(debug_collision_enabled) if debug_collision_enabled: Log.print_log("Debug Collision ON") @@ -46,13 +46,13 @@ func _process(_delta): get_tree().quit() -func get_physics_engine(): +func get_physics_engine() -> PhysicsEngine: return _engine -func _set_debug_collision_enabled(enabled): +func _set_debug_collision_enabled(enabled: bool) -> void: get_tree().debug_collisions_hint = enabled -func _is_debug_collision_enabled(): +func _is_debug_collision_enabled() -> bool: return get_tree().debug_collisions_hint diff --git a/3d/physics_tests/utils/system_log.gd b/3d/physics_tests/utils/system_log.gd index 8abfa804..749e9089 100644 --- a/3d/physics_tests/utils/system_log.gd +++ b/3d/physics_tests/utils/system_log.gd @@ -1,20 +1,18 @@ extends Node - enum LogType { LOG, ERROR, } -signal entry_logged(message, type) +signal entry_logged(message: String, type: LogType) - -func print_log(message): +func print_log(message: String) -> void: print(message) entry_logged.emit(message, LogType.LOG) -func print_error(message): +func print_error(message: String) -> void: push_error(message) printerr(message) entry_logged.emit(message, LogType.ERROR) diff --git a/3d/platformer/coin/coin.gd b/3d/platformer/coin/coin.gd index 94c7f44f..3dbce1bd 100644 --- a/3d/platformer/coin/coin.gd +++ b/3d/platformer/coin/coin.gd @@ -1,10 +1,8 @@ extends Area3D +var taken := false -var taken = false - - -func _on_coin_body_enter(body): +func _on_coin_body_enter(body: Node) -> void: if not taken and body is Player: $Animation.play(&"take") taken = true diff --git a/3d/platformer/enemy/enemy.gd b/3d/platformer/enemy/enemy.gd index 304b9985..bc5e4e91 100644 --- a/3d/platformer/enemy/enemy.gd +++ b/3d/platformer/enemy/enemy.gd @@ -1,6 +1,5 @@ extends RigidBody3D - const ACCEL = 5.0 const DEACCEL = 20.0 const MAX_SPEED = 2.0 @@ -8,17 +7,17 @@ const ROT_SPEED = 1.0 var prev_advance := false var dying := false -var rot_dir = 4 +var rot_dir := 4 -@onready var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") \ - * ProjectSettings.get_setting("physics/3d/default_gravity_vector") +@onready var gravity := Vector3( + ProjectSettings.get_setting("physics/3d/default_gravity") * ProjectSettings.get_setting("physics/3d/default_gravity_vector") +) @onready var _animation_player := $Enemy/AnimationPlayer as AnimationPlayer @onready var _ray_floor := $Enemy/Skeleton/RayFloor as RayCast3D @onready var _ray_wall := $Enemy/Skeleton/RayWall as RayCast3D - -func _integrate_forces(state: PhysicsDirectBodyState3D): +func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: var delta := state.get_step() var lin_velocity := state.get_linear_velocity() var grav := state.get_total_gravity() @@ -80,5 +79,5 @@ func _integrate_forces(state: PhysicsDirectBodyState3D): prev_advance = advance -func _die(): +func _die() -> void: queue_free() diff --git a/3d/platformer/player/bullet/bullet.gd b/3d/platformer/player/bullet/bullet.gd index b9b0bde6..ff794395 100644 --- a/3d/platformer/player/bullet/bullet.gd +++ b/3d/platformer/player/bullet/bullet.gd @@ -1,4 +1,6 @@ -class_name Bullet extends RigidBody3D +class_name Bullet +extends RigidBody3D - -var enabled = true +## If `true`, the bullet can hit enemies. This is set to `false` when the bullet +## hits an enemy so it can't hit an enemy multiple times while the bullet is fading out. +var enabled := true diff --git a/3d/platformer/player/bullet/bullet.tscn b/3d/platformer/player/bullet/bullet.tscn index 3a322024..841208ee 100644 --- a/3d/platformer/player/bullet/bullet.tscn +++ b/3d/platformer/player/bullet/bullet.tscn @@ -144,20 +144,18 @@ script = ExtResource("1") [node name="Sphere" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00159812, 0.0110106, 0.0045104) -visible = false cast_shadow = 0 mesh = SubResource("SphereMesh_gjrxu") surface_material_override/0 = SubResource("StandardMaterial3D_aw6a5") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "life" libraries = { "": SubResource("AnimationLibrary_pyoek") } +autoplay = "life" [node name="CPUParticles3D" type="CPUParticles3D" parent="."] cast_shadow = 0 -emitting = false amount = 16 lifetime = 0.4 mesh = SubResource("SphereMesh_hnt4a") diff --git a/3d/platformer/player/follow_camera.gd b/3d/platformer/player/follow_camera.gd index 2cb10a12..8d47d310 100644 --- a/3d/platformer/player/follow_camera.gd +++ b/3d/platformer/player/follow_camera.gd @@ -1,19 +1,17 @@ extends Camera3D - const MAX_HEIGHT = 2.0 const MIN_HEIGHT = 0.0 +var collision_exception: Array[RID] = [] + @export var min_distance := 0.5 @export var max_distance := 3.5 @export var angle_v_adjust := 0.0 @export var autoturn_ray_aperture := 25.0 @export var autoturn_speed := 50.0 -var collision_exception: Array[RID] = [] - - -func _ready(): +func _ready() -> void: # Find collision exceptions for ray. var node: Node = self while is_instance_valid(node): @@ -27,7 +25,7 @@ func _ready(): set_as_top_level(true) -func _physics_process(delta: float): +func _physics_process(delta: float) -> void: var target := (get_parent() as Node3D).get_global_transform().origin var pos := get_global_transform().origin @@ -47,22 +45,22 @@ func _physics_process(delta: float): # Check autoturn. var ds := PhysicsServer3D.space_get_direct_state(get_world_3d().get_space()) - var col_left = ds.intersect_ray(PhysicsRayQueryParameters3D.create( + var col_left := ds.intersect_ray(PhysicsRayQueryParameters3D.create( target, target + Basis(Vector3.UP, deg_to_rad(autoturn_ray_aperture)) * (difference), - 0xFFFFFFFF, + 0xffffffff, collision_exception )) - var col = ds.intersect_ray(PhysicsRayQueryParameters3D.create( + var col := ds.intersect_ray(PhysicsRayQueryParameters3D.create( target, target + difference, - 0xFFFFFFFF, + 0xffffffff, collision_exception )) - var col_right = ds.intersect_ray(PhysicsRayQueryParameters3D.create( + var col_right := ds.intersect_ray(PhysicsRayQueryParameters3D.create( target, target + Basis(Vector3.UP, deg_to_rad(-autoturn_ray_aperture)) * (difference), - 0xFFFFFFFF, + 0xffffffff, collision_exception )) diff --git a/3d/platformer/player/player.gd b/3d/platformer/player/player.gd index 5625517c..dd3e9784 100644 --- a/3d/platformer/player/player.gd +++ b/3d/platformer/player/player.gd @@ -1,5 +1,5 @@ -class_name Player extends CharacterBody3D - +class_name Player +extends CharacterBody3D enum _Anim { FLOOR, @@ -35,7 +35,7 @@ var coins := 0 @onready var _animation_tree := $AnimationTree as AnimationTree -func _physics_process(delta): +func _physics_process(delta: float) -> void: if Input.is_action_pressed("reset_position") or global_position.y < -12: # Player hit the reset button or fell off the map. position = initial_position diff --git a/3d/platformer/player/player.tscn b/3d/platformer/player/player.tscn index 0e96dcd3..e058c553 100644 --- a/3d/platformer/player/player.tscn +++ b/3d/platformer/player/player.tscn @@ -118,7 +118,15 @@ script = ExtResource("2") [node name="Player" parent="." instance=ExtResource("3_uccbe")] [node name="Skeleton3D" parent="Player/Skeleton" index="0"] +bones/5/rotation = Quaternion(0.501129, -0.498869, -0.501128, 0.498869) +bones/9/rotation = Quaternion(-0.264667, 0.951702, -0.15503, -0.013433) +bones/10/rotation = Quaternion(0.744208, -0.433567, 0.504614, 0.0594899) +bones/11/rotation = Quaternion(0.264667, 0.951702, -0.15503, 0.013433) bones/13/rotation = Quaternion(-0.000357303, 0.998602, 0.0504822, -0.0156872) +bones/14/rotation = Quaternion(0.720784, -0.0117194, -0.041935, 0.691791) +bones/15/rotation = Quaternion(0.998503, -0.0419896, 0.0282027, 0.0208377) +bones/16/rotation = Quaternion(0.000357169, 0.998602, 0.050483, 0.0156871) +bones/17/rotation = Quaternion(0.720784, 0.0117189, 0.0419352, 0.691791) [node name="Robot" parent="Player/Skeleton/Skeleton3D" index="0"] layers = 2 @@ -168,9 +176,9 @@ text = "123" font_size = 48 [node name="AnimationTree" type="AnimationTree" parent="."] +root_node = NodePath("../Player") tree_root = SubResource("23") anim_player = NodePath("../Player/AnimationPlayer") -active = true parameters/air_dir/blend_amount = 0.0 parameters/gun/blend_amount = 0.0 parameters/run/blend_amount = 0.0 diff --git a/3d/platformer/player/player_gray.tres b/3d/platformer/player/player_gray.tres index b29691dd..f1afb30e 100644 --- a/3d/platformer/player/player_gray.tres +++ b/3d/platformer/player/player_gray.tres @@ -3,9 +3,9 @@ [resource] resource_name = "player_gray" vertex_color_use_as_albedo = true -albedo_color = Color(0.665185, 0.665185, 0.665185, 1) +albedo_color = Color(0.8, 0.8, 0.8, 1) metallic = 1.0 -roughness = 0.8 +roughness = 0.4 distance_fade_mode = 2 distance_fade_min_distance = 1.0 distance_fade_max_distance = 2.0 diff --git a/3d/platformer/project.godot b/3d/platformer/project.godot index 32f62b2a..a0cbbbfd 100644 --- a/3d/platformer/project.godot +++ b/3d/platformer/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://game.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [input] ui_accept={ diff --git a/3d/platformer/stage/stage.tscn b/3d/platformer/stage/stage.tscn index f74ff466..22af6186 100644 --- a/3d/platformer/stage/stage.tscn +++ b/3d/platformer/stage/stage.tscn @@ -49,7 +49,6 @@ max_distance = 60.0 size = Vector3(35.9516, 20, 52.5818) origin_offset = Vector3(0, -1.5, 0) box_projection = true -cull_mask = 1048573 [node name="Reflection2" type="ReflectionProbe" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 15, 0, 0) @@ -57,7 +56,6 @@ intensity = 0.5 size = Vector3(16, 5, 6) origin_offset = Vector3(0, -0.22168, 0) box_projection = true -cull_mask = 1048573 [node name="Reflection3" type="ReflectionProbe" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20, 0, 4) @@ -66,7 +64,6 @@ max_distance = 18.7 size = Vector3(6, 6, 12) origin_offset = Vector3(0, -0.22168, 0) box_projection = true -cull_mask = 1048573 [node name="Reflection7" type="ReflectionProbe" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 17.0391, 6.19519, 1.14534) @@ -75,7 +72,6 @@ max_distance = 18.7 size = Vector3(8, 6, 14) origin_offset = Vector3(0, -0.22168, 0) box_projection = true -cull_mask = 1048573 [node name="Reflection4" type="ReflectionProbe" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 21, 1, 15) @@ -84,7 +80,6 @@ max_distance = 60.0 size = Vector3(24, 20, 16) origin_offset = Vector3(-4.6, -1.4, 0) box_projection = true -cull_mask = 1048573 [node name="Reflection5" type="ReflectionProbe" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 47.5486, 1, 8) @@ -92,7 +87,6 @@ intensity = 0.5 max_distance = 60.0 size = Vector3(36.9944, 20, 44.786) origin_offset = Vector3(0, -6.5, 0) -cull_mask = 1048573 [node name="Reflection6" type="ReflectionProbe" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 25.0962, 0.999998, -15.4268) @@ -100,7 +94,6 @@ intensity = 0.5 max_distance = 60.0 size = Vector3(24, 20, 24) origin_offset = Vector3(0, -6.5, 0) -cull_mask = 1048573 [node name="ExtraFloor1" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 19, -3, 17) diff --git a/3d/procedural_materials/checker.png.import b/3d/procedural_materials/checker.png.import index 4458677c..f04f3235 100644 --- a/3d/procedural_materials/checker.png.import +++ b/3d/procedural_materials/checker.png.import @@ -3,20 +3,19 @@ importer="texture" type="CompressedTexture2D" uid="uid://chjqieyps5n5r" -path.s3tc="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex" +path="res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.ctex" metadata={ -"imported_formats": ["s3tc_bptc"], -"vram_texture": true +"vram_texture": false } [deps] source_file="res://checker.png" -dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.s3tc.ctex"] +dest_files=["res://.godot/imported/checker.png-6bb199bedbd039461e4248c1d0b9691d.ctex"] [params] -compress/mode=2 +compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 compress/hdr_compression=1 diff --git a/3d/procedural_materials/loading.gd b/3d/procedural_materials/loading.gd index 9f4c7921..3884c42b 100644 --- a/3d/procedural_materials/loading.gd +++ b/3d/procedural_materials/loading.gd @@ -1,8 +1,7 @@ # This acts as a staging scene shown until the main scene is fully loaded. extends Control - -func _ready(): +func _ready() -> void: for i in 2: # Wait 2 frames before starting to change to the main scene, # so that the loading text can be shown instead of the splash screen. diff --git a/3d/procedural_materials/project.godot b/3d/procedural_materials/project.godot index ca26c21a..7fdc735b 100644 --- a/3d/procedural_materials/project.godot +++ b/3d/procedural_materials/project.godot @@ -11,10 +11,15 @@ config_version=5 [application] config/name="Procedural Materials" +config/tags=PackedStringArray("3d", "demo", "official", "procedural", "rendering") run/main_scene="res://loading.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" -config/tags=PackedStringArray("3d", "demo", "official", "procedural", "rendering") + +[debug] + +gdscript/warnings/untyped_declaration=1 +gdscript/warnings/integer_division=0 [display] diff --git a/3d/procedural_materials/tester.gd b/3d/procedural_materials/tester.gd index 842cc061..22107740 100644 --- a/3d/procedural_materials/tester.gd +++ b/3d/procedural_materials/tester.gd @@ -4,28 +4,27 @@ const ROT_SPEED = 0.003 const ZOOM_SPEED = 0.125 const MAIN_BUTTONS = MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT | MOUSE_BUTTON_MASK_MIDDLE -var tester_index = 0 -var rot_x = deg_to_rad(-22.5) # This must be kept in sync with RotationX. -var rot_y = deg_to_rad(90) # This must be kept in sync with CameraHolder. -var zoom = 2.5 -var base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var tester_index := 0 +var rot_x := deg_to_rad(-22.5) # This must be kept in sync with RotationX. +var rot_y := deg_to_rad(90) # This must be kept in sync with CameraHolder. +var zoom := 2.5 +var base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var testers = $Testers -@onready var camera_holder = $CameraHolder # Has a position and rotates on Y. -@onready var rotation_x = $CameraHolder/RotationX -@onready var camera = $CameraHolder/RotationX/Camera3D +@onready var testers: Node3D = $Testers +@onready var camera_holder: Node3D = $CameraHolder # Has a position and rotates on Y. +@onready var rotation_x: Node3D = $CameraHolder/RotationX +@onready var camera: Camera3D = $CameraHolder/RotationX/Camera3D - -func _ready(): +func _ready() -> void: camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) update_gui() -func _unhandled_input(event): - if event.is_action_pressed("ui_left"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"ui_left"): _on_previous_pressed() - if event.is_action_pressed("ui_right"): + if event.is_action_pressed(&"ui_right"): _on_next_pressed() if event is InputEventMouseButton: @@ -33,38 +32,38 @@ func _unhandled_input(event): zoom -= ZOOM_SPEED if event.button_index == MOUSE_BUTTON_WHEEL_DOWN: zoom += ZOOM_SPEED - zoom = clamp(zoom, 1.5, 4) + zoom = clampf(zoom, 1.5, 4) if event is InputEventMouseMotion and event.button_mask & MAIN_BUTTONS: # Compensate motion speed to be resolution-independent (based on the window height). - var relative_motion = event.relative * DisplayServer.window_get_size().y / base_height + var relative_motion: Vector2 = event.relative * DisplayServer.window_get_size().y / base_height rot_y -= relative_motion.x * ROT_SPEED rot_x -= relative_motion.y * ROT_SPEED - rot_x = clamp(rot_x, deg_to_rad(-90), 0) + rot_x = clampf(rot_x, deg_to_rad(-90), 0) camera_holder.transform.basis = Basis.from_euler(Vector3(0, rot_y, 0)) rotation_x.transform.basis = Basis.from_euler(Vector3(rot_x, 0, 0)) -func _process(delta): - var current_tester = testers.get_child(tester_index) +func _process(delta: float) -> void: + var current_tester: Node3D = testers.get_child(tester_index) # This code assumes CameraHolder's X and Y coordinates are already correct. - var current_position = camera_holder.global_transform.origin.z - var target_position = current_tester.global_transform.origin.z + var current_position := camera_holder.global_transform.origin.z + var target_position := current_tester.global_transform.origin.z camera_holder.global_transform.origin.z = lerpf(current_position, target_position, 3 * delta) camera.position.z = lerpf(camera.position.z, zoom, 10 * delta) -func _on_previous_pressed(): +func _on_previous_pressed() -> void: tester_index = max(0, tester_index - 1) update_gui() -func _on_next_pressed(): +func _on_next_pressed() -> void: tester_index = min(tester_index + 1, testers.get_child_count() - 1) update_gui() -func update_gui(): +func update_gui() -> void: $TestName.text = str(testers.get_child(tester_index).name).capitalize() $Previous.disabled = tester_index == 0 $Next.disabled = tester_index == testers.get_child_count() - 1 diff --git a/3d/rigidbody_character/cubelib.tres b/3d/rigidbody_character/cubelib.tres index c47067ea..dee83012 100644 --- a/3d/rigidbody_character/cubelib.tres +++ b/3d/rigidbody_character/cubelib.tres @@ -2,7 +2,7 @@ [ext_resource type="ArrayMesh" uid="uid://h65pkfq5sgmy" path="res://models/cube.mesh" id="1"] -[sub_resource type="Image" id="Image_rixji"] +[sub_resource type="Image" id="Image_5paxl"] data = { "data": PackedByteArray(76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 66, 41, 73, 255, 68, 42, 73, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 55, 32, 61, 255, 62, 36, 68, 255, 70, 43, 77, 255, 72, 45, 78, 255, 67, 43, 73, 255, 63, 41, 68, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 57, 33, 63, 255, 59, 34, 65, 255, 65, 38, 72, 255, 73, 45, 80, 255, 76, 47, 82, 255, 72, 47, 78, 255, 69, 46, 75, 255, 63, 41, 69, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 59, 34, 64, 255, 61, 35, 67, 255, 63, 36, 69, 255, 66, 38, 73, 255, 75, 44, 81, 255, 78, 47, 84, 255, 76, 49, 83, 255, 75, 51, 82, 255, 69, 46, 75, 255, 62, 41, 69, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 54, 32, 59, 255, 60, 35, 65, 255, 62, 36, 68, 255, 63, 37, 70, 255, 62, 36, 69, 255, 69, 40, 76, 255, 80, 48, 87, 255, 82, 50, 89, 255, 81, 52, 88, 255, 80, 54, 87, 255, 75, 51, 81, 255, 68, 46, 75, 255, 63, 42, 68, 255, 55, 35, 61, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 52, 31, 57, 255, 57, 34, 63, 255, 64, 37, 70, 255, 62, 36, 69, 255, 62, 36, 69, 255, 68, 39, 75, 255, 77, 45, 84, 255, 88, 52, 94, 255, 89, 54, 96, 255, 85, 55, 92, 255, 83, 55, 90, 255, 81, 55, 87, 255, 75, 51, 81, 255, 68, 46, 74, 255, 61, 40, 67, 255, 54, 34, 59, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 48, 30, 53, 255, 51, 31, 56, 255, 54, 32, 59, 255, 61, 36, 67, 255, 63, 36, 69, 255, 62, 36, 69, 255, 70, 40, 77, 255, 74, 43, 81, 255, 79, 46, 87, 255, 87, 53, 95, 255, 90, 56, 97, 255, 91, 59, 99, 255, 85, 55, 93, 255, 85, 58, 92, 255, 81, 56, 87, 255, 73, 50, 80, 255, 67, 45, 73, 255, 60, 39, 65, 255, 53, 34, 58, 255, 46, 29, 51, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 46, 28, 51, 255, 50, 30, 55, 255, 54, 32, 59, 255, 59, 36, 65, 255, 64, 37, 70, 255, 65, 37, 72, 255, 72, 42, 80, 255, 76, 44, 84, 255, 76, 44, 84, 255, 82, 49, 90, 255, 94, 58, 103, 255, 97, 61, 105, 255, 95, 61, 103, 255, 91, 59, 98, 255, 88, 60, 96, 255, 86, 60, 93, 255, 79, 54, 85, 255, 72, 48, 78, 255, 67, 45, 73, 255, 60, 39, 65, 255, 52, 33, 57, 255, 45, 29, 50, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 45, 28, 49, 255, 48, 29, 53, 255, 55, 33, 60, 255, 60, 36, 65, 255, 64, 39, 70, 255, 68, 40, 74, 255, 75, 44, 83, 255, 78, 46, 85, 255, 75, 44, 84, 255, 78, 46, 87, 255, 85, 51, 93, 255, 93, 58, 103, 255, 99, 62, 107, 255, 101, 66, 110, 255, 96, 63, 104, 255, 92, 61, 100, 255, 90, 61, 97, 255, 85, 59, 92, 255, 77, 52, 84, 255, 73, 49, 79, 255, 67, 45, 72, 255, 58, 38, 63, 255, 49, 31, 54, 255, 43, 27, 47, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 38, 24, 41, 255, 45, 29, 49, 255, 50, 31, 54, 255, 54, 33, 59, 255, 59, 36, 64, 255, 63, 38, 69, 255, 68, 41, 74, 255, 75, 44, 82, 255, 77, 45, 85, 255, 76, 44, 84, 255, 80, 47, 88, 255, 80, 47, 89, 255, 86, 51, 95, 255, 98, 60, 106, 255, 102, 64, 110, 255, 105, 69, 114, 255, 101, 67, 110, 255, 95, 62, 103, 255, 93, 62, 100, 255, 90, 61, 97, 255, 82, 56, 89, 255, 76, 50, 82, 255, 72, 49, 78, 255, 64, 42, 69, 255, 53, 33, 58, 255, 46, 28, 50, 255, 41, 26, 45, 255, 38, 24, 42, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 35, 22, 39, 255, 41, 26, 45, 255, 50, 32, 54, 255, 54, 33, 59, 255, 59, 36, 64, 255, 62, 37, 68, 255, 67, 40, 73, 255, 72, 44, 79, 255, 75, 45, 83, 255, 78, 46, 85, 255, 82, 48, 90, 255, 83, 49, 92, 255, 82, 47, 91, 255, 92, 54, 101, 255, 101, 61, 108, 255, 105, 64, 113, 255, 109, 70, 119, 255, 105, 69, 114, 255, 100, 66, 109, 255, 95, 62, 103, 255, 94, 63, 101, 255, 89, 59, 95, 255, 80, 52, 86, 255, 76, 51, 82, 255, 69, 45, 75, 255, 56, 34, 61, 255, 49, 29, 54, 255, 44, 26, 48, 255, 43, 27, 47, 255, 37, 23, 40, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 29, 18, 32, 255, 34, 21, 37, 255, 37, 22, 41, 255, 44, 27, 48, 255, 51, 32, 56, 255, 57, 35, 62, 255, 61, 38, 68, 255, 66, 40, 72, 255, 71, 43, 78, 255, 73, 45, 81, 255, 77, 46, 85, 255, 82, 49, 90, 255, 88, 53, 96, 255, 85, 50, 95, 255, 86, 49, 96, 255, 94, 55, 104, 255, 102, 60, 111, 255, 104, 63, 114, 255, 112, 71, 122, 255, 110, 72, 119, 255, 104, 69, 113, 255, 99, 64, 107, 255, 93, 60, 101, 255, 92, 60, 99, 255, 87, 55, 94, 255, 81, 53, 87, 255, 73, 48, 80, 255, 62, 38, 67, 255, 53, 32, 59, 255, 48, 28, 53, 255, 46, 28, 50, 255, 43, 27, 46, 255, 35, 21, 38, 255, 30, 19, 33, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 28, 17, 31, 255, 33, 21, 37, 255, 38, 23, 41, 255, 41, 24, 45, 255, 48, 28, 52, 255, 55, 33, 60, 255, 61, 38, 67, 255, 65, 40, 72, 255, 70, 43, 77, 255, 72, 44, 79, 255, 76, 46, 83, 255, 81, 49, 89, 255, 88, 52, 96, 255, 88, 52, 97, 255, 88, 51, 98, 255, 92, 53, 101, 255, 97, 57, 107, 255, 106, 63, 115, 255, 111, 68, 121, 255, 116, 74, 127, 255, 114, 75, 124, 255, 109, 72, 119, 255, 103, 67, 112, 255, 95, 60, 104, 255, 91, 58, 99, 255, 89, 57, 97, 255, 86, 55, 93, 255, 78, 51, 85, 255, 68, 43, 74, 255, 60, 37, 65, 255, 53, 31, 58, 255, 48, 29, 53, 255, 46, 29, 50, 255, 39, 24, 42, 255, 32, 20, 36, 255, 28, 17, 31, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 27, 17, 29, 255, 33, 21, 36, 255, 38, 25, 42, 255, 41, 24, 45, 255, 45, 26, 50, 255, 53, 32, 58, 255, 61, 38, 67, 255, 65, 40, 71, 255, 69, 41, 75, 255, 72, 43, 79, 255, 76, 46, 84, 255, 80, 49, 88, 255, 86, 52, 94, 255, 89, 53, 98, 255, 93, 55, 102, 255, 98, 58, 108, 255, 97, 57, 107, 255, 101, 59, 111, 255, 117, 72, 127, 255, 123, 77, 134, 255, 121, 77, 131, 255, 119, 77, 129, 255, 111, 72, 121, 255, 105, 68, 115, 255, 99, 63, 108, 255, 92, 58, 101, 255, 90, 57, 98, 255, 87, 55, 94, 255, 83, 53, 90, 255, 74, 47, 81, 255, 65, 41, 71, 255, 59, 36, 65, 255, 53, 33, 59, 255, 48, 29, 53, 255, 44, 27, 48, 255, 37, 23, 41, 255, 31, 18, 34, 255, 26, 16, 28, 255, 21, 12, 23, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 20, 13, 22, 255, 26, 17, 28, 255, 32, 21, 35, 255, 39, 26, 42, 255, 42, 27, 46, 255, 44, 26, 49, 255, 51, 31, 56, 255, 58, 36, 64, 255, 63, 39, 69, 255, 68, 41, 75, 255, 73, 44, 80, 255, 76, 47, 84, 255, 79, 48, 87, 255, 85, 52, 94, 255, 90, 55, 99, 255, 96, 58, 105, 255, 102, 62, 112, 255, 102, 61, 112, 255, 100, 59, 110, 255, 107, 64, 117, 255, 120, 74, 130, 255, 128, 81, 139, 255, 123, 78, 134, 255, 122, 78, 133, 255, 114, 73, 124, 255, 105, 66, 115, 255, 101, 64, 110, 255, 95, 60, 104, 255, 90, 56, 98, 255, 87, 55, 95, 255, 85, 54, 92, 255, 79, 49, 85, 255, 70, 44, 77, 255, 63, 39, 69, 255, 58, 36, 64, 255, 53, 33, 58, 255, 47, 29, 52, 255, 41, 25, 45, 255, 35, 21, 39, 255, 29, 17, 31, 255, 24, 14, 26, 255, 20, 11, 21, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 19, 12, 20, 255, 25, 16, 27, 255, 31, 20, 33, 255, 38, 25, 41, 255, 45, 30, 48, 255, 47, 30, 51, 255, 50, 31, 55, 255, 57, 35, 62, 255, 61, 37, 67, 255, 67, 40, 73, 255, 73, 44, 80, 255, 77, 46, 84, 255, 79, 48, 86, 255, 85, 52, 93, 255, 91, 55, 100, 255, 96, 58, 105, 255, 103, 63, 112, 255, 106, 64, 116, 255, 103, 62, 114, 255, 106, 63, 116, 255, 111, 65, 120, 255, 122, 75, 132, 255, 129, 80, 140, 255, 128, 81, 139, 255, 124, 79, 135, 255, 119, 76, 129, 255, 110, 69, 119, 255, 102, 63, 111, 255, 97, 60, 106, 255, 91, 57, 100, 255, 87, 55, 96, 255, 85, 53, 93, 255, 82, 51, 89, 255, 74, 46, 81, 255, 66, 40, 72, 255, 61, 37, 67, 255, 57, 35, 62, 255, 50, 31, 55, 255, 45, 27, 49, 255, 39, 24, 43, 255, 33, 20, 37, 255, 28, 16, 30, 255, 23, 14, 26, 255, 18, 10, 20, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 12, 7, 13, 255, 17, 11, 19, 255, 23, 16, 25, 255, 29, 19, 32, 255, 35, 24, 38, 255, 42, 29, 46, 255, 49, 33, 53, 255, 52, 33, 56, 255, 56, 35, 61, 255, 61, 38, 66, 255, 65, 40, 71, 255, 71, 43, 78, 255, 76, 46, 83, 255, 81, 49, 89, 255, 84, 51, 93, 255, 89, 54, 98, 255, 96, 58, 105, 255, 104, 63, 113, 255, 110, 66, 120, 255, 107, 64, 117, 255, 108, 64, 118, 255, 112, 67, 122, 255, 115, 68, 126, 255, 122, 73, 137, 255, 127, 76, 141, 255, 130, 81, 140, 255, 126, 79, 136, 255, 122, 76, 132, 255, 116, 73, 126, 255, 108, 66, 116, 255, 101, 62, 110, 255, 95, 59, 104, 255, 90, 56, 98, 255, 85, 53, 93, 255, 82, 51, 90, 255, 77, 48, 84, 255, 70, 44, 77, 255, 65, 40, 71, 255, 60, 36, 65, 255, 55, 33, 60, 255, 48, 29, 53, 255, 42, 25, 46, 255, 37, 22, 41, 255, 32, 19, 35, 255, 27, 16, 29, 255, 21, 13, 24, 255, 16, 9, 17, 255, 10, 6, 11, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 10, 6, 11, 255, 16, 10, 17, 255, 22, 15, 23, 255, 28, 19, 30, 255, 33, 23, 36, 255, 40, 27, 43, 255, 46, 30, 50, 255, 53, 35, 58, 255, 57, 36, 62, 255, 61, 38, 67, 255, 64, 40, 70, 255, 69, 42, 75, 255, 73, 44, 80, 255, 80, 49, 88, 255, 84, 51, 92, 255, 88, 53, 96, 255, 94, 57, 103, 255, 105, 64, 114, 255, 111, 68, 122, 255, 110, 66, 120, 255, 110, 65, 120, 255, 112, 67, 123, 255, 115, 69, 127, 255, 118, 70, 131, 255, 129, 78, 143, 255, 131, 79, 144, 255, 130, 80, 140, 255, 129, 80, 139, 255, 123, 77, 133, 255, 121, 75, 130, 255, 112, 68, 120, 255, 107, 65, 116, 255, 101, 62, 110, 255, 94, 58, 102, 255, 89, 55, 97, 255, 83, 52, 91, 255, 79, 49, 86, 255, 73, 45, 80, 255, 69, 42, 75, 255, 64, 39, 70, 255, 59, 35, 64, 255, 52, 32, 57, 255, 47, 28, 51, 255, 41, 24, 45, 255, 35, 21, 38, 255, 29, 17, 32, 255, 24, 14, 26, 255, 19, 11, 21, 255, 14, 8, 15, 255, 9, 5, 10, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 8, 5, 9, 255, 14, 9, 15, 255, 20, 14, 22, 255, 26, 18, 28, 255, 32, 22, 35, 255, 38, 26, 41, 255, 44, 29, 47, 255, 50, 33, 54, 255, 58, 37, 62, 255, 62, 39, 67, 255, 65, 41, 71, 255, 67, 42, 74, 255, 72, 44, 79, 255, 77, 47, 84, 255, 81, 50, 89, 255, 88, 54, 96, 255, 93, 56, 102, 255, 103, 64, 113, 255, 113, 70, 123, 255, 113, 69, 123, 255, 111, 67, 122, 255, 113, 67, 123, 255, 116, 68, 126, 255, 118, 71, 131, 255, 124, 75, 137, 255, 136, 82, 148, 255, 137, 83, 149, 255, 133, 80, 142, 255, 132, 82, 142, 255, 123, 76, 134, 255, 121, 74, 130, 255, 116, 71, 125, 255, 110, 66, 119, 255, 108, 65, 118, 255, 99, 61, 109, 255, 93, 58, 102, 255, 88, 55, 96, 255, 81, 50, 89, 255, 77, 48, 84, 255, 72, 44, 79, 255, 68, 41, 74, 255, 63, 38, 69, 255, 55, 33, 61, 255, 50, 30, 55, 255, 45, 27, 49, 255, 40, 24, 44, 255, 33, 19, 36, 255, 26, 15, 28, 255, 21, 12, 23, 255, 17, 10, 19, 255, 12, 7, 13, 255, 8, 5, 9, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 12, 7, 13, 255, 18, 12, 19, 255, 24, 16, 26, 255, 31, 21, 33, 255, 37, 26, 40, 255, 43, 30, 47, 255, 49, 32, 53, 255, 56, 35, 60, 255, 61, 39, 66, 255, 65, 41, 70, 255, 68, 42, 74, 255, 71, 44, 78, 255, 74, 46, 82, 255, 78, 48, 86, 255, 84, 52, 92, 255, 92, 56, 101, 255, 103, 63, 112, 255, 110, 68, 120, 255, 115, 71, 125, 255, 114, 69, 125, 255, 115, 69, 126, 255, 117, 69, 127, 255, 119, 71, 130, 255, 122, 73, 134, 255, 129, 78, 141, 255, 138, 83, 151, 255, 137, 82, 150, 255, 133, 81, 143, 255, 132, 80, 141, 255, 127, 77, 136, 255, 123, 75, 132, 255, 118, 72, 127, 255, 113, 69, 122, 255, 109, 66, 119, 255, 105, 63, 114, 255, 96, 58, 105, 255, 88, 54, 97, 255, 83, 52, 91, 255, 78, 49, 86, 255, 74, 45, 81, 255, 71, 43, 78, 255, 66, 39, 72, 255, 59, 36, 65, 255, 52, 32, 57, 255, 47, 28, 51, 255, 43, 26, 47, 255, 39, 23, 43, 255, 32, 18, 35, 255, 24, 14, 27, 255, 19, 11, 21, 255, 15, 9, 17, 255, 11, 7, 12, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 15, 10, 17, 255, 22, 14, 24, 255, 28, 19, 30, 255, 35, 24, 38, 255, 41, 28, 45, 255, 48, 32, 51, 255, 54, 35, 58, 255, 58, 37, 63, 255, 62, 39, 68, 255, 66, 41, 72, 255, 69, 43, 75, 255, 72, 45, 79, 255, 76, 48, 84, 255, 80, 49, 88, 255, 92, 56, 100, 255, 103, 63, 112, 255, 109, 67, 118, 255, 114, 71, 125, 255, 118, 73, 128, 255, 118, 72, 129, 255, 120, 72, 131, 255, 119, 70, 129, 255, 121, 72, 132, 255, 127, 76, 138, 255, 134, 81, 143, 255, 143, 86, 155, 255, 142, 86, 155, 255, 133, 81, 146, 255, 132, 80, 142, 255, 128, 77, 137, 255, 123, 74, 132, 255, 122, 74, 131, 255, 117, 71, 126, 255, 111, 67, 121, 255, 109, 66, 120, 255, 102, 61, 111, 255, 88, 53, 97, 255, 84, 51, 93, 255, 78, 48, 86, 255, 76, 47, 84, 255, 73, 45, 80, 255, 70, 43, 76, 255, 63, 38, 69, 255, 56, 34, 61, 255, 50, 31, 55, 255, 45, 27, 49, 255, 40, 24, 44, 255, 36, 21, 40, 255, 30, 17, 33, 255, 23, 13, 25, 255, 18, 10, 19, 255, 14, 8, 15, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 19, 12, 21, 255, 25, 16, 28, 255, 31, 21, 34, 255, 39, 26, 42, 255, 45, 31, 49, 255, 51, 34, 55, 255, 55, 35, 60, 255, 60, 37, 65, 255, 64, 40, 69, 255, 67, 42, 73, 255, 72, 45, 79, 255, 74, 46, 82, 255, 78, 48, 85, 255, 91, 55, 99, 255, 101, 62, 110, 255, 109, 67, 118, 255, 114, 71, 124, 255, 118, 73, 129, 255, 122, 75, 132, 255, 122, 74, 133, 255, 122, 73, 133, 255, 123, 73, 133, 255, 124, 75, 135, 255, 133, 81, 143, 255, 134, 82, 144, 255, 146, 90, 160, 255, 145, 90, 160, 255, 138, 84, 152, 255, 132, 81, 146, 255, 124, 76, 135, 255, 123, 74, 132, 255, 122, 73, 130, 255, 118, 71, 128, 255, 114, 69, 125, 255, 111, 67, 121, 255, 107, 65, 117, 255, 95, 57, 104, 255, 89, 53, 97, 255, 85, 51, 93, 255, 78, 48, 86, 255, 76, 47, 84, 255, 72, 44, 79, 255, 67, 41, 74, 255, 60, 37, 66, 255, 54, 33, 59, 255, 48, 29, 53, 255, 43, 26, 48, 255, 37, 22, 41, 255, 32, 19, 36, 255, 27, 16, 30, 255, 22, 13, 24, 255, 17, 10, 19, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 23, 15, 25, 255, 29, 19, 32, 255, 35, 23, 38, 255, 42, 28, 46, 255, 48, 31, 52, 255, 52, 33, 57, 255, 57, 36, 62, 255, 61, 38, 67, 255, 65, 40, 71, 255, 71, 44, 78, 255, 75, 46, 82, 255, 76, 46, 84, 255, 87, 52, 94, 255, 97, 60, 106, 255, 106, 65, 115, 255, 113, 70, 123, 255, 118, 73, 129, 255, 122, 75, 133, 255, 123, 76, 134, 255, 124, 75, 135, 255, 127, 76, 137, 255, 125, 75, 135, 255, 131, 80, 141, 255, 133, 81, 143, 255, 133, 81, 144, 255, 142, 84, 155, 255, 140, 84, 154, 255, 140, 85, 154, 255, 140, 85, 154, 255, 125, 77, 138, 255, 122, 74, 133, 255, 121, 73, 131, 255, 120, 72, 130, 255, 117, 71, 129, 255, 112, 68, 124, 255, 109, 66, 120, 255, 102, 61, 111, 255, 94, 56, 103, 255, 92, 55, 100, 255, 88, 54, 96, 255, 82, 50, 90, 255, 75, 46, 82, 255, 71, 43, 78, 255, 65, 39, 71, 255, 59, 36, 65, 255, 53, 32, 58, 255, 47, 28, 52, 255, 41, 25, 46, 255, 35, 20, 39, 255, 29, 17, 33, 255, 25, 15, 28, 255, 21, 13, 23, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 27, 18, 30, 255, 33, 22, 36, 255, 40, 26, 43, 255, 46, 30, 50, 255, 51, 33, 55, 255, 55, 35, 60, 255, 59, 37, 65, 255, 63, 39, 69, 255, 69, 43, 76, 255, 74, 46, 81, 255, 74, 45, 82, 255, 82, 49, 90, 255, 93, 56, 101, 255, 103, 63, 111, 255, 110, 68, 120, 255, 117, 72, 127, 255, 120, 74, 131, 255, 121, 73, 131, 255, 124, 76, 135, 255, 129, 79, 139, 255, 131, 80, 139, 255, 130, 80, 140, 255, 133, 81, 143, 255, 133, 80, 144, 255, 135, 83, 146, 255, 143, 90, 156, 255, 143, 89, 157, 255, 138, 84, 151, 255, 139, 85, 153, 255, 133, 81, 146, 255, 121, 75, 134, 255, 122, 75, 134, 255, 120, 73, 131, 255, 120, 72, 131, 255, 119, 72, 130, 255, 112, 68, 123, 255, 107, 65, 117, 255, 97, 58, 107, 255, 97, 59, 106, 255, 94, 57, 102, 255, 91, 56, 99, 255, 84, 51, 91, 255, 74, 45, 81, 255, 68, 41, 75, 255, 63, 38, 70, 255, 57, 35, 63, 255, 51, 31, 56, 255, 46, 28, 51, 255, 39, 23, 43, 255, 33, 19, 36, 255, 28, 17, 31, 255, 25, 15, 27, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 31, 20, 34, 255, 38, 25, 41, 255, 44, 29, 48, 255, 50, 33, 54, 255, 55, 35, 60, 255, 59, 37, 64, 255, 62, 39, 68, 255, 67, 42, 74, 255, 73, 45, 80, 255, 75, 45, 83, 255, 78, 47, 86, 255, 88, 53, 96, 255, 97, 59, 105, 255, 105, 64, 114, 255, 112, 69, 123, 255, 118, 72, 128, 255, 117, 71, 127, 255, 121, 74, 131, 255, 130, 81, 140, 255, 133, 82, 142, 255, 134, 82, 142, 255, 135, 82, 144, 255, 134, 82, 144, 255, 133, 82, 144, 255, 134, 83, 146, 255, 145, 91, 159, 255, 144, 90, 158, 255, 133, 82, 147, 255, 137, 84, 150, 255, 134, 81, 147, 255, 125, 77, 138, 255, 121, 75, 134, 255, 122, 75, 133, 255, 119, 74, 130, 255, 122, 74, 133, 255, 117, 70, 128, 255, 112, 68, 122, 255, 100, 60, 110, 255, 95, 57, 105, 255, 99, 60, 107, 255, 96, 59, 104, 255, 91, 56, 99, 255, 84, 52, 91, 255, 75, 46, 82, 255, 68, 41, 74, 255, 62, 37, 68, 255, 55, 33, 60, 255, 48, 29, 53, 255, 43, 26, 48, 255, 36, 21, 39, 255, 31, 18, 34, 255, 28, 17, 31, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 36, 23, 39, 255, 42, 28, 46, 255, 48, 32, 52, 255, 54, 36, 59, 255, 58, 37, 64, 255, 61, 38, 66, 255, 66, 41, 72, 255, 73, 45, 80, 255, 78, 47, 85, 255, 81, 48, 89, 255, 83, 50, 91, 255, 90, 54, 98, 255, 96, 58, 106, 255, 106, 65, 116, 255, 112, 68, 122, 255, 117, 71, 128, 255, 119, 73, 129, 255, 125, 79, 136, 255, 131, 83, 143, 255, 136, 84, 145, 255, 137, 83, 145, 255, 134, 82, 144, 255, 133, 82, 144, 255, 138, 85, 149, 255, 138, 85, 150, 255, 136, 87, 151, 255, 132, 84, 147, 255, 138, 85, 152, 255, 137, 84, 150, 255, 134, 82, 147, 255, 130, 80, 143, 255, 123, 76, 136, 255, 123, 76, 135, 255, 123, 77, 134, 255, 118, 74, 129, 255, 119, 73, 130, 255, 114, 69, 125, 255, 107, 65, 117, 255, 95, 57, 106, 255, 100, 61, 109, 255, 100, 61, 109, 255, 96, 60, 105, 255, 90, 55, 98, 255, 83, 51, 90, 255, 76, 47, 82, 255, 68, 41, 74, 255, 60, 36, 66, 255, 53, 32, 58, 255, 44, 26, 49, 255, 38, 22, 43, 255, 34, 20, 37, 255, 31, 19, 34, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 40, 26, 43, 255, 46, 30, 50, 255, 52, 34, 57, 255, 57, 37, 62, 255, 59, 37, 65, 255, 64, 40, 70, 255, 72, 44, 79, 255, 78, 47, 85, 255, 84, 51, 91, 255, 87, 52, 95, 255, 89, 53, 97, 255, 88, 53, 97, 255, 99, 60, 109, 255, 107, 64, 117, 255, 114, 70, 125, 255, 118, 74, 129, 255, 121, 76, 132, 255, 128, 81, 139, 255, 136, 86, 147, 255, 136, 84, 146, 255, 135, 83, 144, 255, 133, 82, 144, 255, 139, 86, 150, 255, 143, 87, 153, 255, 153, 98, 169, 255, 219, 159, 236, 255, 229, 167, 245, 255, 176, 115, 191, 255, 138, 85, 152, 255, 136, 83, 150, 255, 134, 82, 148, 255, 132, 80, 145, 255, 125, 78, 137, 255, 125, 78, 136, 255, 123, 77, 134, 255, 118, 74, 128, 255, 117, 72, 128, 255, 110, 67, 120, 255, 105, 63, 115, 255, 101, 61, 111, 255, 102, 63, 112, 255, 100, 62, 109, 255, 95, 59, 103, 255, 88, 54, 95, 255, 82, 51, 89, 255, 75, 46, 82, 255, 66, 40, 72, 255, 59, 36, 64, 255, 50, 30, 55, 255, 42, 24, 46, 255, 37, 22, 41, 255, 34, 20, 37, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 43, 27, 47, 255, 49, 32, 54, 255, 56, 37, 61, 255, 59, 38, 65, 255, 64, 40, 69, 255, 70, 42, 75, 255, 75, 45, 82, 255, 81, 49, 89, 255, 87, 53, 96, 255, 91, 55, 99, 255, 94, 57, 103, 255, 96, 58, 105, 255, 105, 64, 115, 255, 110, 68, 120, 255, 114, 72, 124, 255, 119, 76, 130, 255, 125, 79, 136, 255, 130, 82, 142, 255, 134, 85, 146, 255, 134, 84, 145, 255, 135, 83, 145, 255, 139, 85, 149, 255, 141, 86, 156, 255, 175, 117, 191, 255, 162, 105, 178, 255, 166, 106, 182, 255, 168, 108, 184, 255, 178, 117, 193, 255, 198, 136, 214, 255, 150, 92, 161, 255, 137, 83, 150, 255, 138, 84, 150, 255, 133, 81, 145, 255, 126, 78, 137, 255, 125, 79, 136, 255, 123, 77, 133, 255, 119, 74, 130, 255, 113, 70, 123, 255, 109, 67, 119, 255, 105, 64, 115, 255, 103, 62, 112, 255, 103, 63, 112, 255, 99, 61, 108, 255, 92, 57, 101, 255, 85, 53, 93, 255, 79, 48, 86, 255, 72, 44, 79, 255, 64, 38, 69, 255, 56, 34, 62, 255, 47, 27, 51, 255, 40, 23, 45, 255, 38, 23, 41, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 46, 29, 50, 255, 54, 35, 59, 255, 60, 39, 65, 255, 64, 40, 70, 255, 69, 43, 74, 255, 73, 44, 79, 255, 77, 46, 84, 255, 84, 50, 92, 255, 88, 53, 97, 255, 95, 57, 104, 255, 99, 60, 109, 255, 103, 63, 112, 255, 106, 66, 116, 255, 109, 69, 119, 255, 117, 74, 127, 255, 128, 82, 138, 255, 126, 79, 138, 255, 130, 83, 142, 255, 134, 85, 147, 255, 136, 84, 147, 255, 139, 85, 149, 255, 152, 93, 167, 255, 185, 122, 201, 255, 160, 98, 175, 255, 157, 98, 173, 255, 157, 98, 173, 255, 157, 98, 173, 255, 152, 94, 168, 255, 156, 96, 171, 255, 189, 124, 200, 255, 156, 95, 167, 255, 139, 84, 152, 255, 136, 83, 149, 255, 131, 81, 142, 255, 126, 78, 136, 255, 122, 76, 133, 255, 115, 71, 125, 255, 113, 70, 123, 255, 110, 68, 119, 255, 107, 66, 117, 255, 105, 64, 114, 255, 102, 63, 112, 255, 101, 62, 110, 255, 96, 59, 105, 255, 89, 55, 97, 255, 81, 50, 88, 255, 74, 45, 80, 255, 66, 40, 72, 255, 59, 35, 64, 255, 51, 30, 56, 255, 44, 26, 49, 255, 40, 24, 44, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 50, 32, 55, 255, 58, 37, 63, 255, 64, 41, 69, 255, 69, 43, 74, 255, 73, 45, 79, 255, 77, 47, 83, 255, 81, 49, 89, 255, 87, 52, 95, 255, 93, 56, 102, 255, 98, 60, 108, 255, 100, 61, 109, 255, 104, 64, 113, 255, 109, 68, 118, 255, 112, 71, 122, 255, 122, 78, 133, 255, 127, 81, 138, 255, 128, 81, 140, 255, 133, 84, 146, 255, 132, 84, 145, 255, 143, 88, 157, 255, 172, 106, 187, 255, 172, 107, 187, 255, 165, 100, 180, 255, 164, 99, 179, 255, 159, 96, 174, 255, 158, 98, 173, 255, 152, 94, 167, 255, 141, 84, 156, 255, 143, 85, 157, 255, 152, 91, 164, 255, 167, 103, 177, 255, 170, 105, 179, 255, 143, 89, 153, 255, 134, 84, 147, 255, 128, 79, 139, 255, 121, 73, 130, 255, 116, 71, 125, 255, 111, 68, 120, 255, 111, 68, 120, 255, 108, 68, 118, 255, 104, 66, 114, 255, 104, 64, 114, 255, 100, 61, 109, 255, 97, 59, 105, 255, 93, 57, 101, 255, 85, 52, 92, 255, 75, 46, 82, 255, 68, 41, 75, 255, 61, 36, 67, 255, 54, 32, 59, 255, 48, 28, 53, 255, 43, 25, 47, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 55, 34, 59, 255, 62, 39, 67, 255, 67, 42, 72, 255, 72, 45, 77, 255, 75, 46, 81, 255, 80, 49, 86, 255, 85, 51, 92, 255, 91, 55, 100, 255, 98, 59, 108, 255, 101, 62, 110, 255, 105, 65, 114, 255, 106, 65, 115, 255, 109, 68, 119, 255, 113, 71, 124, 255, 122, 78, 133, 255, 128, 82, 139, 255, 134, 85, 146, 255, 132, 84, 145, 255, 152, 94, 167, 255, 175, 109, 191, 255, 163, 98, 178, 255, 161, 97, 176, 255, 163, 98, 178, 255, 160, 97, 176, 255, 161, 97, 176, 255, 152, 91, 167, 255, 138, 81, 154, 255, 142, 83, 155, 255, 148, 88, 160, 255, 155, 93, 166, 255, 152, 91, 164, 255, 157, 94, 168, 255, 161, 103, 176, 255, 150, 95, 163, 255, 132, 83, 144, 255, 123, 75, 133, 255, 115, 69, 123, 255, 114, 69, 123, 255, 110, 68, 119, 255, 109, 69, 119, 255, 107, 68, 117, 255, 105, 66, 114, 255, 101, 63, 110, 255, 95, 58, 103, 255, 94, 57, 102, 255, 88, 54, 96, 255, 80, 48, 87, 255, 72, 43, 78, 255, 65, 39, 71, 255, 58, 34, 63, 255, 52, 31, 57, 255, 47, 28, 51, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 58, 36, 63, 255, 65, 41, 70, 255, 70, 43, 75, 255, 73, 45, 79, 255, 78, 48, 84, 255, 83, 50, 89, 255, 86, 52, 94, 255, 94, 57, 103, 255, 97, 60, 106, 255, 102, 64, 111, 255, 103, 64, 112, 255, 104, 64, 112, 255, 110, 68, 119, 255, 115, 73, 125, 255, 125, 80, 137, 255, 135, 87, 147, 255, 137, 87, 150, 255, 160, 98, 176, 255, 168, 103, 184, 255, 159, 96, 175, 255, 154, 91, 170, 255, 158, 94, 173, 255, 164, 98, 179, 255, 164, 99, 180, 255, 149, 88, 165, 255, 138, 80, 154, 255, 143, 84, 159, 255, 150, 89, 165, 255, 152, 91, 164, 255, 146, 86, 158, 255, 142, 85, 156, 255, 141, 86, 156, 255, 147, 91, 162, 255, 159, 101, 174, 255, 148, 93, 162, 255, 128, 79, 138, 255, 118, 71, 126, 255, 114, 68, 122, 255, 114, 69, 123, 255, 110, 69, 120, 255, 111, 71, 121, 255, 110, 70, 119, 255, 103, 65, 112, 255, 99, 62, 107, 255, 95, 58, 103, 255, 90, 55, 98, 255, 83, 50, 91, 255, 76, 45, 82, 255, 68, 40, 75, 255, 63, 38, 69, 255, 56, 33, 61, 255, 52, 31, 57, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 63, 40, 69, 255, 68, 43, 74, 255, 72, 45, 78, 255, 76, 46, 81, 255, 80, 48, 86, 255, 84, 50, 90, 255, 88, 54, 96, 255, 92, 58, 101, 255, 99, 62, 107, 255, 103, 64, 112, 255, 103, 63, 111, 255, 107, 65, 115, 255, 113, 69, 122, 255, 119, 76, 129, 255, 132, 85, 144, 255, 151, 97, 166, 255, 170, 107, 187, 255, 163, 100, 179, 255, 160, 97, 175, 255, 151, 89, 166, 255, 147, 86, 162, 255, 157, 95, 172, 255, 162, 97, 177, 255, 162, 97, 177, 255, 145, 85, 160, 255, 140, 81, 156, 255, 151, 89, 166, 255, 156, 93, 172, 255, 153, 91, 169, 255, 138, 82, 152, 255, 133, 81, 148, 255, 137, 84, 152, 255, 140, 86, 154, 255, 138, 85, 152, 255, 139, 87, 154, 255, 149, 93, 160, 255, 136, 84, 145, 255, 116, 70, 124, 255, 114, 69, 123, 255, 112, 71, 122, 255, 112, 71, 122, 255, 114, 73, 124, 255, 109, 69, 118, 255, 101, 64, 110, 255, 100, 63, 108, 255, 94, 58, 102, 255, 86, 52, 94, 255, 79, 47, 86, 255, 72, 43, 79, 255, 66, 39, 72, 255, 60, 36, 66, 255, 55, 32, 59, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 65, 41, 70, 255, 71, 44, 76, 255, 76, 47, 82, 255, 78, 47, 83, 255, 81, 48, 87, 255, 85, 52, 93, 255, 90, 56, 98, 255, 97, 61, 106, 255, 103, 65, 113, 255, 103, 64, 112, 255, 105, 63, 112, 255, 109, 66, 117, 255, 114, 70, 123, 255, 125, 79, 135, 255, 155, 99, 170, 255, 164, 104, 181, 255, 155, 96, 173, 255, 152, 91, 168, 255, 144, 85, 159, 255, 148, 88, 163, 255, 157, 95, 172, 255, 159, 96, 174, 255, 158, 95, 173, 255, 150, 87, 165, 255, 146, 85, 161, 255, 149, 88, 164, 255, 159, 95, 174, 255, 155, 92, 170, 255, 139, 81, 154, 255, 139, 81, 154, 255, 142, 84, 156, 255, 135, 82, 149, 255, 132, 80, 146, 255, 127, 77, 142, 255, 133, 80, 145, 255, 142, 86, 152, 255, 143, 87, 153, 255, 133, 80, 145, 255, 114, 68, 122, 255, 115, 72, 125, 255, 115, 73, 125, 255, 114, 73, 125, 255, 110, 70, 120, 255, 105, 67, 114, 255, 102, 65, 111, 255, 99, 62, 106, 255, 91, 55, 98, 255, 83, 49, 90, 255, 74, 44, 81, 255, 69, 41, 76, 255, 64, 38, 70, 255, 58, 35, 64, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 67, 40, 71, 255, 73, 45, 79, 255, 78, 47, 83, 255, 79, 48, 85, 255, 83, 50, 90, 255, 87, 54, 96, 255, 93, 58, 101, 255, 99, 62, 108, 255, 103, 64, 112, 255, 103, 62, 110, 255, 104, 62, 111, 255, 110, 66, 117, 255, 117, 73, 130, 255, 157, 100, 173, 255, 157, 99, 174, 255, 150, 91, 167, 255, 148, 89, 166, 255, 142, 84, 162, 255, 152, 93, 169, 255, 161, 99, 176, 255, 160, 98, 175, 255, 158, 95, 172, 255, 152, 89, 166, 255, 149, 87, 163, 255, 154, 91, 168, 255, 157, 94, 172, 255, 152, 90, 166, 255, 138, 80, 152, 255, 141, 83, 155, 255, 144, 85, 159, 255, 139, 81, 153, 255, 137, 80, 151, 255, 129, 77, 143, 255, 128, 75, 142, 255, 132, 77, 145, 255, 132, 77, 145, 255, 135, 80, 146, 255, 135, 80, 146, 255, 134, 79, 145, 255, 132, 84, 144, 255, 120, 77, 131, 255, 119, 76, 129, 255, 111, 71, 121, 255, 106, 67, 116, 255, 106, 67, 114, 255, 102, 64, 109, 255, 96, 58, 101, 255, 86, 52, 92, 255, 78, 46, 85, 255, 72, 43, 79, 255, 67, 40, 74, 255, 61, 37, 68, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 70, 42, 75, 255, 75, 45, 80, 255, 78, 47, 84, 255, 77, 47, 85, 255, 83, 51, 91, 255, 87, 54, 96, 255, 94, 59, 103, 255, 101, 62, 109, 255, 104, 63, 111, 255, 105, 64, 113, 255, 107, 64, 114, 255, 116, 70, 129, 255, 134, 83, 148, 255, 148, 94, 163, 255, 155, 98, 171, 255, 161, 103, 175, 255, 162, 104, 177, 255, 157, 99, 173, 255, 157, 98, 172, 255, 154, 95, 170, 255, 151, 91, 166, 255, 148, 86, 162, 255, 144, 83, 158, 255, 150, 89, 164, 255, 155, 94, 170, 255, 152, 91, 166, 255, 146, 86, 160, 255, 143, 84, 157, 255, 143, 84, 157, 255, 144, 85, 158, 255, 151, 90, 165, 255, 144, 86, 159, 255, 130, 75, 144, 255, 127, 73, 142, 255, 128, 74, 142, 255, 130, 76, 142, 255, 131, 77, 143, 255, 130, 76, 142, 255, 132, 79, 143, 255, 147, 93, 160, 255, 142, 91, 155, 255, 126, 81, 137, 255, 117, 75, 128, 255, 110, 70, 120, 255, 105, 67, 115, 255, 103, 65, 111, 255, 98, 60, 104, 255, 90, 55, 96, 255, 80, 49, 87, 255, 76, 46, 83, 255, 72, 43, 78, 255, 67, 40, 73, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 73, 44, 78, 255, 77, 47, 84, 255, 79, 49, 88, 255, 82, 50, 90, 255, 85, 52, 94, 255, 92, 57, 101, 255, 99, 61, 108, 255, 105, 65, 114, 255, 108, 67, 117, 255, 110, 67, 121, 255, 124, 76, 137, 255, 127, 78, 141, 255, 136, 87, 150, 255, 141, 91, 155, 255, 145, 94, 159, 255, 153, 98, 167, 255, 156, 99, 171, 255, 154, 97, 169, 255, 152, 94, 168, 255, 147, 90, 165, 255, 144, 89, 163, 255, 143, 86, 160, 255, 150, 89, 164, 255, 151, 91, 165, 255, 148, 89, 161, 255, 141, 83, 155, 255, 138, 80, 152, 255, 140, 82, 154, 255, 144, 85, 158, 255, 151, 91, 165, 255, 142, 84, 156, 255, 136, 81, 150, 255, 134, 79, 149, 255, 135, 80, 149, 255, 139, 84, 152, 255, 133, 80, 144, 255, 130, 77, 140, 255, 125, 72, 133, 255, 127, 75, 136, 255, 135, 82, 145, 255, 139, 87, 150, 255, 138, 87, 149, 255, 118, 73, 130, 255, 112, 71, 122, 255, 108, 68, 118, 255, 103, 65, 112, 255, 99, 61, 106, 255, 94, 57, 100, 255, 86, 53, 92, 255, 81, 50, 87, 255, 76, 46, 82, 255, 71, 43, 77, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 74, 45, 81, 255, 81, 49, 89, 255, 86, 52, 95, 255, 86, 53, 94, 255, 91, 55, 100, 255, 100, 61, 109, 255, 104, 64, 113, 255, 108, 68, 118, 255, 127, 79, 139, 255, 138, 84, 151, 255, 134, 85, 148, 255, 140, 91, 154, 255, 133, 83, 146, 255, 125, 76, 139, 255, 126, 76, 139, 255, 134, 81, 148, 255, 141, 84, 156, 255, 142, 87, 159, 255, 145, 89, 162, 255, 150, 92, 165, 255, 147, 90, 163, 255, 149, 92, 165, 255, 147, 87, 161, 255, 146, 87, 160, 255, 138, 81, 152, 255, 139, 82, 154, 255, 145, 87, 159, 255, 140, 82, 153, 255, 142, 84, 155, 255, 139, 83, 153, 255, 137, 82, 151, 255, 141, 86, 155, 255, 140, 85, 154, 255, 143, 87, 157, 255, 144, 89, 158, 255, 138, 84, 152, 255, 132, 79, 143, 255, 129, 77, 138, 255, 129, 77, 138, 255, 126, 74, 135, 255, 124, 73, 133, 255, 131, 80, 143, 255, 130, 78, 147, 255, 120, 73, 133, 255, 107, 68, 117, 255, 104, 65, 113, 255, 99, 61, 106, 255, 94, 58, 101, 255, 89, 54, 96, 255, 83, 51, 90, 255, 79, 48, 85, 255, 74, 45, 80, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 78, 47, 85, 255, 85, 51, 93, 255, 86, 53, 95, 255, 89, 54, 98, 255, 96, 58, 105, 255, 102, 62, 112, 255, 107, 67, 117, 255, 133, 83, 145, 255, 142, 89, 155, 255, 137, 85, 150, 255, 137, 84, 149, 255, 137, 88, 150, 255, 135, 87, 149, 255, 130, 81, 143, 255, 130, 77, 143, 255, 132, 75, 145, 255, 135, 78, 148, 255, 140, 84, 154, 255, 145, 90, 160, 255, 146, 90, 161, 255, 145, 88, 160, 255, 145, 86, 159, 255, 147, 87, 160, 255, 143, 83, 156, 255, 144, 85, 157, 255, 141, 84, 155, 255, 134, 79, 148, 255, 138, 82, 151, 255, 139, 83, 153, 255, 143, 86, 156, 255, 142, 85, 156, 255, 138, 83, 151, 255, 142, 88, 156, 255, 146, 91, 160, 255, 146, 90, 159, 255, 138, 84, 152, 255, 128, 77, 142, 255, 128, 77, 140, 255, 128, 77, 138, 255, 128, 78, 139, 255, 126, 75, 138, 255, 124, 74, 141, 255, 125, 75, 142, 255, 132, 80, 146, 255, 127, 77, 139, 255, 103, 65, 113, 255, 102, 63, 109, 255, 94, 58, 102, 255, 89, 55, 96, 255, 85, 51, 92, 255, 80, 48, 86, 255, 76, 47, 82, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 80, 49, 88, 255, 85, 52, 93, 255, 87, 53, 95, 255, 91, 55, 100, 255, 98, 60, 107, 255, 116, 74, 128, 255, 136, 86, 149, 255, 136, 85, 149, 255, 135, 85, 148, 255, 138, 88, 151, 255, 143, 93, 155, 255, 144, 94, 157, 255, 143, 93, 156, 255, 136, 84, 149, 255, 132, 77, 144, 255, 133, 78, 145, 255, 136, 81, 148, 255, 140, 86, 153, 255, 142, 88, 156, 255, 139, 83, 153, 255, 139, 81, 151, 255, 142, 84, 155, 255, 147, 88, 160, 255, 149, 89, 162, 255, 140, 82, 153, 255, 133, 77, 146, 255, 137, 82, 150, 255, 138, 83, 151, 255, 140, 84, 153, 255, 137, 82, 151, 255, 136, 81, 149, 255, 141, 84, 154, 255, 145, 90, 159, 255, 148, 91, 162, 255, 141, 86, 154, 255, 132, 80, 145, 255, 131, 79, 144, 255, 130, 78, 143, 255, 129, 78, 142, 255, 128, 77, 141, 255, 125, 75, 141, 255, 124, 74, 140, 255, 126, 76, 140, 255, 129, 78, 141, 255, 130, 79, 142, 255, 126, 75, 139, 255, 108, 65, 120, 255, 99, 61, 106, 255, 92, 57, 99, 255, 86, 53, 93, 255, 81, 50, 88, 255, 77, 47, 83, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 81, 49, 88, 255, 83, 51, 92, 255, 90, 55, 98, 255, 94, 57, 103, 255, 119, 76, 133, 255, 136, 88, 149, 255, 134, 87, 147, 255, 134, 86, 147, 255, 136, 88, 148, 255, 139, 90, 151, 255, 145, 98, 157, 255, 150, 103, 162, 255, 149, 102, 162, 255, 144, 94, 156, 255, 135, 82, 147, 255, 136, 84, 149, 255, 137, 85, 150, 255, 140, 87, 153, 255, 141, 87, 154, 255, 135, 82, 148, 255, 136, 81, 149, 255, 140, 83, 153, 255, 141, 84, 154, 255, 137, 80, 150, 255, 137, 82, 150, 255, 141, 87, 154, 255, 135, 84, 148, 255, 131, 79, 144, 255, 132, 79, 145, 255, 133, 79, 146, 255, 135, 81, 148, 255, 142, 88, 155, 255, 145, 92, 158, 255, 142, 89, 155, 255, 138, 85, 151, 255, 133, 81, 146, 255, 128, 77, 141, 255, 128, 77, 140, 255, 128, 75, 137, 255, 129, 75, 138, 255, 127, 76, 139, 255, 122, 73, 137, 255, 125, 75, 138, 255, 126, 76, 138, 255, 126, 77, 138, 255, 125, 75, 136, 255, 127, 77, 139, 255, 118, 73, 129, 255, 97, 60, 104, 255, 91, 56, 98, 255, 84, 52, 91, 255, 80, 49, 86, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 80, 49, 88, 255, 87, 54, 96, 255, 95, 59, 103, 255, 120, 77, 135, 255, 127, 82, 144, 255, 129, 84, 143, 255, 134, 88, 144, 255, 135, 89, 146, 255, 136, 90, 148, 255, 140, 93, 152, 255, 143, 96, 154, 255, 146, 101, 158, 255, 145, 99, 157, 255, 144, 96, 156, 255, 141, 91, 154, 255, 138, 88, 151, 255, 138, 86, 150, 255, 141, 87, 153, 255, 137, 84, 150, 255, 132, 80, 145, 255, 135, 83, 148, 255, 132, 80, 144, 255, 127, 74, 139, 255, 134, 81, 146, 255, 134, 83, 147, 255, 125, 77, 138, 255, 128, 79, 141, 255, 135, 84, 148, 255, 127, 77, 139, 255, 132, 80, 145, 255, 138, 86, 150, 255, 139, 87, 152, 255, 139, 87, 152, 255, 139, 87, 151, 255, 136, 85, 149, 255, 131, 80, 143, 255, 128, 77, 140, 255, 130, 77, 141, 255, 130, 77, 141, 255, 126, 74, 135, 255, 121, 69, 128, 255, 121, 70, 130, 255, 120, 72, 133, 255, 122, 73, 134, 255, 124, 76, 135, 255, 123, 75, 134, 255, 122, 75, 133, 255, 124, 76, 135, 255, 110, 63, 121, 255, 99, 62, 108, 255, 88, 54, 95, 255, 80, 49, 87, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 82, 51, 90, 255, 101, 63, 108, 255, 120, 75, 127, 255, 121, 77, 132, 255, 122, 79, 138, 255, 126, 82, 140, 255, 129, 85, 141, 255, 130, 85, 142, 255, 132, 88, 144, 255, 133, 86, 145, 255, 135, 88, 146, 255, 136, 89, 148, 255, 139, 92, 150, 255, 139, 92, 151, 255, 143, 98, 156, 255, 141, 92, 153, 255, 140, 89, 152, 255, 138, 86, 151, 255, 136, 84, 148, 255, 133, 82, 145, 255, 127, 77, 140, 255, 124, 75, 136, 255, 127, 80, 139, 255, 125, 78, 137, 255, 118, 72, 130, 255, 127, 79, 140, 255, 127, 79, 140, 255, 118, 72, 130, 255, 127, 78, 138, 255, 136, 84, 147, 255, 137, 85, 149, 255, 136, 85, 148, 255, 136, 85, 148, 255, 136, 85, 148, 255, 135, 84, 146, 255, 134, 82, 144, 255, 132, 80, 142, 255, 130, 78, 142, 255, 127, 76, 138, 255, 125, 74, 134, 255, 123, 73, 133, 255, 119, 71, 129, 255, 111, 66, 122, 255, 120, 73, 131, 255, 122, 76, 133, 255, 118, 70, 128, 255, 116, 69, 127, 255, 114, 67, 125, 255, 113, 69, 124, 255, 111, 70, 122, 255, 95, 60, 105, 255, 82, 51, 90, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 102, 62, 108, 255, 116, 73, 124, 255, 116, 73, 124, 255, 119, 76, 127, 255, 123, 80, 133, 255, 127, 83, 136, 255, 130, 86, 138, 255, 130, 88, 141, 255, 133, 92, 143, 255, 134, 93, 145, 255, 134, 92, 145, 255, 134, 91, 145, 255, 135, 89, 146, 255, 134, 87, 146, 255, 136, 88, 147, 255, 139, 90, 150, 255, 138, 89, 149, 255, 136, 88, 148, 255, 133, 84, 145, 255, 129, 79, 141, 255, 123, 76, 134, 255, 121, 76, 131, 255, 117, 72, 126, 255, 119, 74, 130, 255, 122, 77, 134, 255, 112, 69, 123, 255, 112, 68, 123, 255, 127, 78, 138, 255, 133, 82, 144, 255, 136, 84, 148, 255, 136, 84, 148, 255, 134, 84, 146, 255, 134, 84, 145, 255, 133, 83, 145, 255, 131, 80, 142, 255, 132, 81, 143, 255, 130, 80, 141, 255, 125, 75, 134, 255, 124, 74, 134, 255, 125, 75, 136, 255, 122, 74, 132, 255, 117, 71, 127, 255, 117, 72, 127, 255, 118, 73, 129, 255, 116, 71, 126, 255, 114, 68, 125, 255, 111, 66, 121, 255, 108, 67, 118, 255, 106, 67, 116, 255, 101, 63, 111, 255, 109, 69, 120, 255, 90, 57, 100, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 111, 69, 118, 255, 113, 71, 120, 255, 117, 75, 126, 255, 121, 79, 130, 255, 126, 83, 136, 255, 126, 85, 137, 255, 127, 87, 138, 255, 129, 90, 140, 255, 130, 91, 141, 255, 131, 92, 142, 255, 132, 92, 143, 255, 135, 91, 144, 255, 135, 89, 145, 255, 133, 87, 144, 255, 131, 85, 143, 255, 130, 83, 141, 255, 127, 80, 138, 255, 125, 78, 136, 255, 122, 76, 133, 255, 118, 74, 129, 255, 116, 72, 126, 255, 118, 74, 129, 255, 117, 73, 127, 255, 108, 66, 115, 255, 111, 67, 118, 255, 120, 73, 128, 255, 124, 76, 133, 255, 128, 78, 138, 255, 130, 80, 141, 255, 132, 82, 144, 255, 132, 81, 143, 255, 131, 81, 143, 255, 131, 81, 143, 255, 130, 80, 141, 255, 126, 77, 136, 255, 124, 75, 133, 255, 122, 74, 131, 255, 124, 76, 133, 255, 124, 77, 133, 255, 121, 75, 131, 255, 117, 72, 127, 255, 115, 71, 124, 255, 114, 70, 123, 255, 112, 69, 122, 255, 108, 68, 118, 255, 104, 66, 114, 255, 103, 65, 113, 255, 104, 66, 114, 255, 106, 67, 116, 255, 97, 61, 107, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 64, 40, 70, 255, 110, 69, 117, 255, 113, 73, 123, 255, 120, 79, 130, 255, 121, 80, 131, 255, 122, 81, 132, 255, 124, 86, 134, 255, 126, 86, 136, 255, 127, 86, 136, 255, 131, 89, 138, 255, 133, 89, 139, 255, 130, 85, 137, 255, 126, 81, 136, 255, 123, 78, 134, 255, 121, 76, 132, 255, 120, 75, 131, 255, 118, 73, 127, 255, 115, 71, 123, 255, 115, 71, 124, 255, 116, 73, 127, 255, 114, 71, 124, 255, 107, 65, 116, 255, 105, 63, 115, 255, 111, 66, 120, 255, 119, 72, 126, 255, 121, 73, 128, 255, 121, 74, 129, 255, 123, 76, 132, 255, 124, 76, 135, 255, 126, 78, 137, 255, 126, 78, 137, 255, 126, 78, 137, 255, 122, 74, 132, 255, 117, 70, 125, 255, 115, 68, 121, 255, 118, 72, 125, 255, 121, 75, 129, 255, 118, 73, 126, 255, 118, 73, 126, 255, 114, 71, 123, 255, 112, 69, 121, 255, 110, 68, 119, 255, 105, 66, 115, 255, 101, 64, 111, 255, 100, 64, 110, 255, 103, 65, 113, 255, 105, 65, 114, 255, 61, 36, 67, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 106, 67, 115, 255, 111, 72, 121, 255, 112, 72, 121, 255, 113, 73, 123, 255, 115, 75, 125, 255, 118, 78, 127, 255, 123, 81, 130, 255, 123, 81, 131, 255, 123, 80, 131, 255, 117, 74, 127, 255, 117, 73, 127, 255, 115, 72, 126, 255, 112, 70, 121, 255, 112, 70, 121, 255, 108, 67, 115, 255, 111, 68, 118, 255, 113, 70, 122, 255, 114, 70, 122, 255, 110, 67, 119, 255, 100, 60, 111, 255, 101, 61, 112, 255, 106, 63, 115, 255, 110, 66, 118, 255, 114, 68, 121, 255, 117, 71, 124, 255, 116, 71, 125, 255, 117, 72, 128, 255, 117, 72, 128, 255, 115, 70, 126, 255, 114, 68, 124, 255, 116, 71, 127, 255, 114, 70, 123, 255, 114, 70, 121, 255, 112, 69, 120, 255, 110, 68, 119, 255, 114, 71, 122, 255, 117, 73, 123, 255, 113, 70, 120, 255, 107, 67, 116, 255, 101, 64, 111, 255, 100, 63, 110, 255, 97, 62, 107, 255, 99, 63, 109, 255, 101, 63, 110, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 99, 62, 108, 255, 108, 69, 117, 255, 111, 73, 121, 255, 111, 73, 119, 255, 110, 72, 117, 255, 110, 71, 118, 255, 112, 72, 122, 255, 113, 72, 122, 255, 114, 72, 123, 255, 112, 71, 122, 255, 107, 70, 117, 255, 107, 70, 117, 255, 110, 70, 120, 255, 108, 67, 116, 255, 108, 67, 116, 255, 106, 65, 113, 255, 108, 66, 116, 255, 109, 66, 119, 255, 108, 65, 118, 255, 105, 63, 114, 255, 102, 61, 111, 255, 96, 58, 107, 255, 99, 60, 109, 255, 96, 58, 106, 255, 102, 63, 113, 255, 107, 65, 117, 255, 106, 63, 116, 255, 106, 63, 116, 255, 111, 68, 121, 255, 111, 69, 120, 255, 110, 70, 117, 255, 106, 67, 114, 255, 105, 65, 114, 255, 109, 68, 117, 255, 109, 68, 117, 255, 107, 66, 115, 255, 105, 66, 114, 255, 103, 65, 113, 255, 104, 65, 114, 255, 100, 63, 110, 255, 98, 62, 107, 255, 97, 61, 106, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 0, 0, 0, 255, 102, 65, 108, 255, 106, 70, 114, 255, 109, 72, 117, 255, 110, 74, 119, 255, 110, 73, 118, 255, 111, 72, 119, 255, 111, 72, 120, 255, 111, 73, 120, 255, 110, 72, 120, 255, 106, 69, 116, 255, 100, 65, 110, 255, 101, 64, 110, 255, 104, 64, 112, 255, 107, 66, 116, 255, 108, 66, 118, 255, 108, 66, 117, 255, 108, 66, 118, 255, 107, 65, 117, 255, 108, 65, 115, 255, 107, 65, 115, 255, 104, 64, 114, 255, 96, 59, 107, 255, 91, 56, 101, 255, 100, 62, 111, 255, 105, 64, 115, 255, 108, 66, 118, 255, 103, 64, 112, 255, 100, 63, 109, 255, 100, 63, 109, 255, 105, 67, 112, 255, 110, 70, 116, 255, 104, 65, 112, 255, 98, 61, 107, 255, 98, 62, 108, 255, 101, 64, 111, 255, 102, 64, 112, 255, 97, 62, 107, 255, 94, 59, 103, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 101, 66, 108, 255, 104, 69, 112, 255, 106, 71, 114, 255, 106, 70, 114, 255, 106, 68, 115, 255, 108, 70, 117, 255, 111, 73, 120, 255, 102, 67, 112, 255, 96, 63, 105, 255, 96, 63, 105, 255, 98, 62, 107, 255, 101, 62, 110, 255, 101, 61, 110, 255, 101, 61, 111, 255, 104, 64, 114, 255, 104, 64, 114, 255, 103, 63, 112, 255, 101, 62, 112, 255, 102, 62, 113, 255, 105, 65, 115, 255, 103, 64, 113, 255, 103, 64, 112, 255, 97, 60, 107, 255, 98, 61, 107, 255, 94, 59, 104, 255, 98, 62, 107, 255, 100, 63, 107, 255, 99, 63, 106, 255, 101, 64, 108, 255, 101, 64, 108, 255, 99, 64, 106, 255, 95, 62, 102, 255, 98, 62, 107, 255, 99, 62, 108, 255, 92, 59, 101, 255, 93, 59, 102, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 25, 16, 28, 255, 100, 65, 108, 255, 104, 66, 113, 255, 102, 65, 111, 255, 105, 67, 114, 255, 106, 68, 114, 255, 101, 66, 110, 255, 96, 62, 105, 255, 95, 60, 104, 255, 97, 60, 106, 255, 96, 59, 104, 255, 96, 59, 104, 255, 96, 58, 104, 255, 95, 57, 104, 255, 97, 59, 107, 255, 96, 58, 107, 255, 94, 57, 106, 255, 96, 58, 107, 255, 95, 58, 106, 255, 98, 60, 108, 255, 93, 57, 102, 255, 93, 57, 102, 255, 93, 58, 102, 255, 93, 58, 102, 255, 95, 58, 103, 255, 93, 58, 101, 255, 89, 55, 97, 255, 89, 56, 97, 255, 91, 59, 98, 255, 94, 61, 102, 255, 96, 62, 103, 255, 95, 62, 103, 255, 96, 61, 104, 255, 25, 15, 27, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 93, 59, 102, 255, 96, 61, 105, 255, 100, 64, 109, 255, 102, 65, 110, 255, 101, 65, 110, 255, 99, 64, 108, 255, 99, 63, 107, 255, 99, 63, 108, 255, 98, 62, 106, 255, 95, 59, 103, 255, 95, 59, 103, 255, 94, 59, 103, 255, 93, 57, 102, 255, 94, 57, 103, 255, 96, 58, 105, 255, 96, 58, 105, 255, 96, 58, 105, 255, 95, 58, 104, 255, 94, 58, 102, 255, 95, 58, 104, 255, 92, 57, 101, 255, 84, 53, 93, 255, 80, 52, 88, 255, 82, 52, 90, 255, 85, 53, 93, 255, 84, 53, 90, 255, 83, 54, 89, 255, 86, 56, 92, 255, 89, 58, 96, 255, 94, 61, 102, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 71, 45, 78, 255, 96, 60, 103, 255, 96, 61, 104, 255, 95, 61, 104, 255, 96, 61, 104, 255, 94, 59, 102, 255, 92, 58, 100, 255, 90, 57, 98, 255, 88, 55, 96, 255, 87, 54, 96, 255, 88, 55, 97, 255, 86, 53, 96, 255, 84, 52, 95, 255, 83, 51, 94, 255, 89, 54, 98, 255, 87, 54, 96, 255, 85, 54, 93, 255, 86, 54, 94, 255, 86, 54, 95, 255, 84, 53, 93, 255, 80, 51, 88, 255, 80, 51, 88, 255, 81, 50, 88, 255, 82, 50, 89, 255, 80, 49, 88, 255, 78, 49, 85, 255, 79, 51, 84, 255, 70, 43, 78, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 88, 55, 96, 255, 88, 54, 96, 255, 90, 56, 97, 255, 89, 55, 96, 255, 89, 55, 96, 255, 83, 51, 92, 255, 80, 50, 90, 255, 85, 54, 94, 255, 85, 54, 93, 255, 82, 50, 91, 255, 80, 49, 90, 255, 80, 49, 89, 255, 79, 50, 88, 255, 80, 51, 88, 255, 85, 53, 93, 255, 84, 53, 92, 255, 84, 53, 92, 255, 82, 52, 89, 255, 78, 49, 86, 255, 77, 47, 84, 255, 74, 45, 82, 255, 73, 44, 81, 255, 75, 46, 83, 255, 73, 44, 80, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 87, 56, 94, 255, 85, 54, 93, 255, 86, 54, 93, 255, 85, 53, 93, 255, 83, 51, 91, 255, 82, 50, 90, 255, 78, 49, 87, 255, 76, 47, 85, 255, 75, 46, 85, 255, 75, 46, 85, 255, 76, 47, 84, 255, 76, 47, 84, 255, 77, 48, 84, 255, 79, 49, 86, 255, 78, 49, 85, 255, 76, 48, 83, 255, 77, 48, 84, 255, 76, 46, 83, 255, 71, 43, 78, 255, 70, 42, 77, 255, 72, 43, 79, 255, 70, 42, 77, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 0, 0, 0, 255, 77, 47, 84, 255, 78, 48, 85, 255, 79, 48, 85, 255, 79, 48, 86, 255, 78, 48, 85, 255, 76, 47, 83, 255, 71, 44, 78, 255, 73, 45, 80, 255, 71, 44, 78, 255, 71, 44, 78, 255, 71, 44, 78, 255, 71, 44, 78, 255, 69, 44, 77, 255, 72, 44, 78, 255, 74, 45, 81, 255, 75, 46, 81, 255, 73, 45, 80, 255, 73, 45, 79, 255, 0, 0, 0, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 72, 44, 79, 255, 74, 45, 80, 255, 72, 44, 79, 255, 71, 43, 78, 255, 67, 41, 74, 255, 65, 41, 72, 255, 65, 40, 72, 255, 65, 41, 72, 255, 65, 40, 72, 255, 64, 40, 71, 255, 68, 41, 75, 255, 70, 42, 76, 255, 72, 44, 78, 255, 72, 45, 79, 255, 70, 44, 77, 255, 71, 44, 78, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 30, 18, 33, 255, 66, 41, 73, 255, 66, 41, 73, 255, 68, 42, 77, 255, 68, 42, 77, 255, 68, 42, 77, 255, 65, 40, 72, 255, 63, 39, 69, 255, 64, 39, 71, 255, 66, 40, 72, 255, 68, 42, 74, 255, 66, 40, 73, 255, 65, 39, 71, 255, 30, 19, 33, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 62, 39, 70, 255, 64, 40, 72, 255, 64, 40, 73, 255, 62, 38, 69, 255, 61, 37, 67, 255, 61, 37, 67, 255, 61, 36, 67, 255, 61, 37, 67, 255, 62, 37, 68, 255, 62, 38, 68, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 57, 36, 64, 255, 56, 35, 62, 255, 58, 36, 64, 255, 58, 36, 64, 255, 56, 35, 62, 255, 57, 35, 63, 255, 57, 34, 63, 255, 57, 34, 62, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 0, 0, 0, 255, 51, 32, 57, 255, 50, 30, 55, 255, 54, 33, 59, 255, 54, 33, 59, 255, 0, 0, 0, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 49, 31, 54, 255, 48, 30, 53, 255, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0, 76, 76, 76, 0), "format": "RGBA8", @@ -12,7 +12,7 @@ data = { } [sub_resource type="ImageTexture" id="2"] -image = SubResource("Image_rixji") +image = SubResource("Image_5paxl") [sub_resource type="BoxShape3D" id="3"] diff --git a/3d/rigidbody_character/level.gd b/3d/rigidbody_character/level.gd index 7974aef0..1e8af7b7 100644 --- a/3d/rigidbody_character/level.gd +++ b/3d/rigidbody_character/level.gd @@ -1,8 +1,8 @@ extends Node3D # Random spawn of Rigidbody cubes. -func _on_SpawnTimer_timeout(): - var new_rb = preload("res://cube_rigidbody.tscn").instantiate() +func _on_SpawnTimer_timeout() -> void: + var new_rb: RigidBody3D = preload("res://cube_rigidbody.tscn").instantiate() new_rb.position.y = 15 new_rb.position.x = randf_range(-5, 5) new_rb.position.z = randf_range(-5, 5) diff --git a/3d/rigidbody_character/level.tscn b/3d/rigidbody_character/level.tscn index 1ae25145..94ae4863 100644 --- a/3d/rigidbody_character/level.tscn +++ b/3d/rigidbody_character/level.tscn @@ -107,7 +107,7 @@ data = { environment = SubResource("Environment_jpjfl") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] -transform = Transform3D(-0.766044, 0.45452, -0.454519, 0, 0.707107, 0.707107, 0.642788, 0.541675, -0.541675, 0, 5, 1) +transform = Transform3D(-0.436154, 0.776648, -0.45452, 0.353553, 0.612372, 0.707107, 0.827508, 0.14771, -0.541675, 0, 5, 1) light_energy = 1.3 shadow_enabled = true shadow_bias = 0.032 diff --git a/3d/rigidbody_character/player/cubio.gd b/3d/rigidbody_character/player/cubio.gd index 279a359e..a4d4811c 100644 --- a/3d/rigidbody_character/player/cubio.gd +++ b/3d/rigidbody_character/player/cubio.gd @@ -1,10 +1,10 @@ extends RigidBody3D -@onready var shape_cast = $ShapeCast3D -@onready var camera = $Target/Camera3D -@onready var start_position = position +@onready var shape_cast: ShapeCast3D = $ShapeCast3D +@onready var camera: Camera3D = $Target/Camera3D +@onready var start_position := position -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if Input.is_action_just_pressed(&"exit"): get_tree().quit() if Input.is_action_just_pressed(&"reset_position") or global_position.y < - 6: @@ -12,13 +12,13 @@ func _physics_process(_delta): position = start_position linear_velocity = Vector3.ZERO - var dir = Vector3() + var dir := Vector3() dir.x = Input.get_axis(&"move_left", &"move_right") dir.z = Input.get_axis(&"move_forward", &"move_back") # Get the camera's transform basis, but remove the X rotation such # that the Y axis is up and Z is horizontal. - var cam_basis = camera.global_transform.basis + var cam_basis := camera.global_transform.basis cam_basis = cam_basis.rotated(cam_basis.x, -cam_basis.get_euler().x) dir = cam_basis * dir @@ -38,11 +38,10 @@ func _physics_process(_delta): # Test if there is a body below the player. -func on_ground(): - if shape_cast.is_colliding(): - return true +func on_ground() -> bool: + return shape_cast.is_colliding() -func _on_tcube_body_entered(body): +func _on_tcube_body_entered(body: Node) -> void: if body == self: - get_node(^"WinText").show() + $WinText.visible = true diff --git a/3d/rigidbody_character/player/follow_camera.gd b/3d/rigidbody_character/player/follow_camera.gd index 9d24c51e..246f4fa1 100644 --- a/3d/rigidbody_character/player/follow_camera.gd +++ b/3d/rigidbody_character/player/follow_camera.gd @@ -1,41 +1,41 @@ extends Camera3D -var collision_exception = [] -@export var min_distance = 0.5 -@export var max_distance = 3.0 -@export var angle_v_adjust = 0.0 -var max_height = 2.0 -var min_height = 0 +var collision_exception := [] +var max_height := 2.0 +var min_height := 0 + +@export var min_distance := 0.5 +@export var max_distance := 3.0 +@export var angle_v_adjust := 0.0 @onready var target_node: Node3D = get_parent() - -func _ready(): +func _ready() -> void: collision_exception.append(target_node.get_parent().get_rid()) - # Detaches the camera transform from the parent spatial node - set_as_top_level(true) + # Detach the camera transform from the parent spatial node. + top_level = true -func _physics_process(_delta): - var target_pos: Vector3 = target_node.global_transform.origin - var camera_pos: Vector3 = global_transform.origin +func _physics_process(_delta: float) -> void: + var target_pos := target_node.global_transform.origin + var camera_pos := global_transform.origin - var delta_pos: Vector3 = camera_pos - target_pos + var delta_pos := camera_pos - target_pos - # Regular delta follow + # Regular delta follow. - # Check ranges + # Check ranges. if delta_pos.length() < min_distance: delta_pos = delta_pos.normalized() * min_distance elif delta_pos.length() > max_distance: delta_pos = delta_pos.normalized() * max_distance - # Check upper and lower height + # Check upper and lower height. delta_pos.y = clamp(delta_pos.y, min_height, max_height) camera_pos = target_pos + delta_pos look_at_from_position(camera_pos, target_pos, Vector3.UP) - # Turn a little up or down - var t = transform + # Turn a little up or down. + var t := transform t.basis = Basis(t.basis[0], deg_to_rad(angle_v_adjust)) * t.basis transform = t diff --git a/3d/rigidbody_character/project.godot b/3d/rigidbody_character/project.godot index e60f04cd..4974d333 100644 --- a/3d/rigidbody_character/project.godot +++ b/3d/rigidbody_character/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://level.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/truck_town/car_select/car_select.gd b/3d/truck_town/car_select/car_select.gd index c399d809..10d0e810 100644 --- a/3d/truck_town/car_select/car_select.gd +++ b/3d/truck_town/car_select/car_select.gd @@ -2,16 +2,17 @@ extends Control var town: Node3D = null -func _ready(): +func _ready() -> void: # Automatically focus the first item for gamepad accessibility. $HBoxContainer/MiniVan.grab_focus.call_deferred() -func _process(_delta: float): + +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"back"): _on_back_pressed() -func _load_scene(car_scene: PackedScene): +func _load_scene(car_scene: PackedScene) -> void: var car: Node3D = car_scene.instantiate() car.name = "car" town = preload("res://town/town_scene.tscn").instantiate() @@ -23,7 +24,7 @@ func _load_scene(car_scene: PackedScene): hide() -func _on_back_pressed(): +func _on_back_pressed() -> void: if is_instance_valid(town): # Currently in the town, go back to main menu. town.queue_free() @@ -35,13 +36,13 @@ func _on_back_pressed(): get_tree().quit() -func _on_mini_van_pressed(): +func _on_mini_van_pressed() -> void: _load_scene(preload("res://vehicles/car_base.tscn")) -func _on_trailer_truck_pressed(): +func _on_trailer_truck_pressed() -> void: _load_scene(preload("res://vehicles/trailer_truck.tscn")) -func _on_tow_truck_pressed(): +func _on_tow_truck_pressed() -> void: _load_scene(preload("res://vehicles/tow_truck.tscn")) diff --git a/3d/truck_town/project.godot b/3d/truck_town/project.godot index e1c7494d..92746083 100644 --- a/3d/truck_town/project.godot +++ b/3d/truck_town/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://car_select/car_select.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/truck_town/spedometer.gd b/3d/truck_town/spedometer.gd index 7b77e845..a10f6afa 100644 --- a/3d/truck_town/spedometer.gd +++ b/3d/truck_town/spedometer.gd @@ -6,13 +6,12 @@ enum SpeedUnit { MILES_PER_HOUR, } -@export var speed_unit: SpeedUnit = SpeedUnit.METERS_PER_SECOND - var gradient := Gradient.new() var car_body: VehicleBody3D +@export var speed_unit: SpeedUnit = SpeedUnit.METERS_PER_SECOND -func _ready(): +func _ready() -> void: # The start and end points (offset 0.0 and 1.0) are already defined in a Gradient # resource on creation. Override their colors and only create one new point. gradient.set_color(0, Color(0.7, 0.9, 1.0)) @@ -20,7 +19,7 @@ func _ready(): gradient.add_point(0.2, Color(1.0, 1.0, 1.0)) -func _process(_delta): +func _process(_delta: float) -> void: var speed := car_body.linear_velocity.length() if speed_unit == SpeedUnit.METERS_PER_SECOND: text = "Speed: " + ("%.1f" % speed) + " m/s" @@ -35,5 +34,5 @@ func _process(_delta): add_theme_color_override("font_color", gradient.sample(remap(car_body.linear_velocity.length(), 0.0, 30.0, 0.0, 1.0))) -func _on_spedometer_pressed(): +func _on_spedometer_pressed() -> void: speed_unit = ((speed_unit + 1) % SpeedUnit.size()) as SpeedUnit diff --git a/3d/truck_town/vehicles/car_base.tscn b/3d/truck_town/vehicles/car_base.tscn index 507031a2..99b2d41b 100644 --- a/3d/truck_town/vehicles/car_base.tscn +++ b/3d/truck_town/vehicles/car_base.tscn @@ -59,8 +59,8 @@ colors = PackedColorArray(1, 1, 1, 1, 1, 1, 1, 0) [node name="Body" type="VehicleBody3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00169557, 0.222867, -0.0955184) -center_of_mass_mode = 1 physics_material_override = SubResource("PhysicsMaterial_l7i2k") +center_of_mass_mode = 1 script = ExtResource("1_r806m") [node name="Wheel1" type="VehicleWheel3D" parent="Body"] @@ -154,7 +154,7 @@ attenuation_filter_cutoff_hz = 20500.0 [node name="ImpactSound" type="AudioStreamPlayer3D" parent="Body"] stream = SubResource("AudioStreamRandomizer_bpr2q") -volume_db = -9.0 +volume_db = -10.0 max_polyphony = 3 attenuation_filter_cutoff_hz = 20500.0 diff --git a/3d/truck_town/vehicles/follow_camera.gd b/3d/truck_town/vehicles/follow_camera.gd index 8fcf749d..09088569 100644 --- a/3d/truck_town/vehicles/follow_camera.gd +++ b/3d/truck_town/vehicles/follow_camera.gd @@ -33,17 +33,17 @@ enum CameraType { MAX, # Represents the size of the CameraType enum. } -func _ready(): +func _ready() -> void: update_camera() -func _input(event): +func _input(event: InputEvent) -> void: if event.is_action_pressed(&"cycle_camera"): camera_type = wrapi(camera_type + 1, 0, CameraType.MAX) as CameraType update_camera() -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if camera_type == CameraType.EXTERIOR: var target: Vector3 = get_parent().global_transform.origin var pos := global_transform.origin @@ -77,7 +77,7 @@ func _physics_process(_delta): previous_position = global_position -func update_camera(): +func update_camera() -> void: match camera_type: CameraType.EXTERIOR: transform = initial_transform diff --git a/3d/truck_town/vehicles/meshes/minivan.res b/3d/truck_town/vehicles/meshes/minivan.res index 7b989a40..f94e96cf 100644 Binary files a/3d/truck_town/vehicles/meshes/minivan.res and b/3d/truck_town/vehicles/meshes/minivan.res differ diff --git a/3d/truck_town/vehicles/meshes/tow_truck.res b/3d/truck_town/vehicles/meshes/tow_truck.res index 3790ed80..3159e1ca 100644 Binary files a/3d/truck_town/vehicles/meshes/tow_truck.res and b/3d/truck_town/vehicles/meshes/tow_truck.res differ diff --git a/3d/truck_town/vehicles/meshes/truck_cab.res b/3d/truck_town/vehicles/meshes/truck_cab.res index 91de2222..282ae6f9 100644 Binary files a/3d/truck_town/vehicles/meshes/truck_cab.res and b/3d/truck_town/vehicles/meshes/truck_cab.res differ diff --git a/3d/truck_town/vehicles/meshes/truck_trailer.res b/3d/truck_town/vehicles/meshes/truck_trailer.res index dccc0bd1..0a6a1300 100644 Binary files a/3d/truck_town/vehicles/meshes/truck_trailer.res and b/3d/truck_town/vehicles/meshes/truck_trailer.res differ diff --git a/3d/truck_town/vehicles/meshes/wheel.res b/3d/truck_town/vehicles/meshes/wheel.res index c648ff01..736cc341 100644 Binary files a/3d/truck_town/vehicles/meshes/wheel.res and b/3d/truck_town/vehicles/meshes/wheel.res differ diff --git a/3d/truck_town/vehicles/tow_truck.tscn b/3d/truck_town/vehicles/tow_truck.tscn index 7b986248..cffc105a 100644 --- a/3d/truck_town/vehicles/tow_truck.tscn +++ b/3d/truck_town/vehicles/tow_truck.tscn @@ -190,7 +190,7 @@ attenuation_filter_cutoff_hz = 20500.0 [node name="ImpactSound" type="AudioStreamPlayer3D" parent="Body"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.391365, 0.158069) stream = SubResource("AudioStreamRandomizer_aad58") -volume_db = -9.0 +volume_db = -10.0 max_polyphony = 3 attenuation_filter_cutoff_hz = 20500.0 @@ -317,8 +317,8 @@ params/bias = 0.5 [node name="Body2" type="VehicleBody3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.00169557, 0.222867, -3.97518) mass = 10.0 -center_of_mass_mode = 1 physics_material_override = SubResource("PhysicsMaterial_hvgqm") +center_of_mass_mode = 1 [node name="Wheel1" type="VehicleWheel3D" parent="Body2"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.573678, 0.115169, 1.10416) diff --git a/3d/truck_town/vehicles/trailer_truck.tscn b/3d/truck_town/vehicles/trailer_truck.tscn index 3ded4e41..f5fa9fe3 100644 --- a/3d/truck_town/vehicles/trailer_truck.tscn +++ b/3d/truck_town/vehicles/trailer_truck.tscn @@ -242,7 +242,7 @@ attenuation_filter_cutoff_hz = 20500.0 [node name="ImpactSound" type="AudioStreamPlayer3D" parent="Body"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.00169557, -0.222867, 0.0955184) stream = SubResource("AudioStreamRandomizer_xu0em") -volume_db = -9.0 +volume_db = -10.0 max_polyphony = 3 attenuation_filter_cutoff_hz = 20500.0 diff --git a/3d/truck_town/vehicles/vehicle.gd b/3d/truck_town/vehicles/vehicle.gd index b74c2418..ef32d360 100644 --- a/3d/truck_town/vehicles/vehicle.gd +++ b/3d/truck_town/vehicles/vehicle.gd @@ -11,9 +11,7 @@ var _steer_target := 0.0 @onready var desired_engine_pitch: float = $EngineSound.pitch_scale -func _physics_process(delta: float): - var fwd_mps := (linear_velocity * transform.basis).x - +func _physics_process(delta: float) -> void: _steer_target = Input.get_axis(&"turn_right", &"turn_left") _steer_target *= STEER_LIMIT diff --git a/3d/variable_rate_shading/project.godot b/3d/variable_rate_shading/project.godot index 6b94b713..b11397c7 100644 --- a/3d/variable_rate_shading/project.godot +++ b/3d/variable_rate_shading/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://vrs.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/variable_rate_shading/vrs.gd b/3d/variable_rate_shading/vrs.gd index 86918b41..4c116442 100644 --- a/3d/variable_rate_shading/vrs.gd +++ b/3d/variable_rate_shading/vrs.gd @@ -10,7 +10,7 @@ extends Node3D var xr_interface: MobileVRInterface func _set_xr_mode() -> void: - var vrs_mode = get_viewport().vrs_mode + var vrs_mode := get_viewport().vrs_mode if vrs_mode == Viewport.VRS_XR: xr_interface = XRServer.find_interface("Native mobile") if xr_interface and xr_interface.initialize(): @@ -34,7 +34,7 @@ func _set_xr_mode() -> void: func _update_texture() -> void: - var vrs_mode = get_viewport().vrs_mode + var vrs_mode := get_viewport().vrs_mode if vrs_mode == Viewport.VRS_DISABLED: texture_rect.visible = false elif vrs_mode == Viewport.VRS_TEXTURE: @@ -52,7 +52,7 @@ func _update_texture() -> void: func _ready() -> void: - var vrs_mode = get_viewport().vrs_mode + var vrs_mode := get_viewport().vrs_mode option_button.selected = vrs_mode _update_texture() diff --git a/3d/variable_rate_shading/vrs.tscn b/3d/variable_rate_shading/vrs.tscn index 349fb608..ab62ec1c 100644 --- a/3d/variable_rate_shading/vrs.tscn +++ b/3d/variable_rate_shading/vrs.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=15 format=3 uid="uid://byr2ixl00dqdl"] +[gd_scene load_steps=16 format=3 uid="uid://byr2ixl00dqdl"] [ext_resource type="Script" path="res://vrs.gd" id="1_5k5b8"] [ext_resource type="Texture2D" uid="uid://dsdx5gplyr6or" path="res://vrs_texture.png" id="2_44sk1"] @@ -19,6 +19,9 @@ tonemap_mode = 3 tonemap_white = 6.0 glow_enabled = true +[sub_resource type="BoxMesh" id="BoxMesh_t8cmv"] +size = Vector3(1024, 1, 1024) + [sub_resource type="BoxMesh" id="BoxMesh_ocds8"] [sub_resource type="Gradient" id="Gradient_f30sk"] @@ -72,6 +75,10 @@ fov = 50.0 [node name="XRCamera3D" type="XRCamera3D" parent="XROrigin3D"] transform = Transform3D(0.92086, -0.232944, 0.312657, 0, 0.801902, 0.597456, -0.389894, -0.550173, 0.738439, 1.02558, 2.09094, 2.36376) +[node name="Ground" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -4.65, 0) +mesh = SubResource("BoxMesh_t8cmv") + [node name="Boxes" type="Node3D" parent="."] [node name="MeshInstance3D" type="MeshInstance3D" parent="Boxes"] @@ -908,6 +915,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1, 1, 0) light_color = Color(1, 0.952941, 0.392157, 1) shadow_enabled = true shadow_bias = 0.03 +omni_range = 20.0 [node name="CanvasLayer" type="CanvasLayer" parent="."] diff --git a/3d/volumetric_fog/camera.gd b/3d/volumetric_fog/camera.gd index eaea4886..73de870f 100644 --- a/3d/volumetric_fog/camera.gd +++ b/3d/volumetric_fog/camera.gd @@ -3,22 +3,21 @@ extends Camera3D const MOUSE_SENSITIVITY = 0.002 const MOVE_SPEED = 0.6 -var volumetric_fog_volume_size = ProjectSettings.get_setting("rendering/environment/volumetric_fog/volume_size") -var volumetric_fog_volume_depth = ProjectSettings.get_setting("rendering/environment/volumetric_fog/volume_depth") +var volumetric_fog_volume_size := int(ProjectSettings.get_setting("rendering/environment/volumetric_fog/volume_size")) +var volumetric_fog_volume_depth := int(ProjectSettings.get_setting("rendering/environment/volumetric_fog/volume_depth")) -var rot = Vector3() -var velocity = Vector3() +var rot := Vector3() +var velocity := Vector3() -@onready var label = $Label +@onready var label: Label = $Label - -func _ready(): - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) +func _ready() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED update_label() -func _process(delta): - var motion = Vector3( +func _process(delta: float) -> void: + var motion := Vector3( Input.get_action_strength("move_right") - Input.get_action_strength("move_left"), 0, Input.get_action_strength("move_back") - Input.get_action_strength("move_forward") @@ -33,7 +32,7 @@ func _process(delta): position += velocity -func _input(event): +func _input(event: InputEvent) -> void: # Mouse look (only if the mouse is captured). if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: # Horizontal mouse look. @@ -75,7 +74,7 @@ func _input(event): update_label() -func update_label(): +func update_label() -> void: if get_world_3d().environment.volumetric_fog_temporal_reprojection_enabled: label.text = "Fog density: %.2f\nTemporal reprojection: Enabled\nTemporal reprojection strength: %.2f\nVolumetric fog quality: %d×%d×%d" % [ get_world_3d().environment.volumetric_fog_density, diff --git a/3d/volumetric_fog/project.godot b/3d/volumetric_fog/project.godot index 95061225..d749626d 100644 --- a/3d/volumetric_fog/project.godot +++ b/3d/volumetric_fog/project.godot @@ -16,6 +16,10 @@ run/main_scene="res://volumetric_fog.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/3d/voxel/menu/debug.gd b/3d/voxel/menu/debug.gd index 22cb6a0f..b1cd138c 100644 --- a/3d/voxel/menu/debug.gd +++ b/3d/voxel/menu/debug.gd @@ -1,11 +1,10 @@ extends Label # Displays some useful debug information in a Label. -@onready var player = $"../Player" -@onready var voxel_world = $"../VoxelWorld" +@onready var player := $"../Player" +@onready var voxel_world := $"../VoxelWorld" - -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"debug"): visible = not visible @@ -17,14 +16,17 @@ func _process(_delta): # Avoids the problem of showing more digits than needed or available. -func _vector_to_string_appropriate_digits(vector): - var factors = [1000, 1000, 1000] - for i in range(3): +func _vector_to_string_appropriate_digits(vector: Vector3) -> String: + var factors: Array[int] = [1000, 1000, 1000] + for i in 3: if abs(vector[i]) > 4096: + @warning_ignore("integer_division") factors[i] = factors[i] / 10 if abs(vector[i]) > 65536: + @warning_ignore("integer_division") factors[i] = factors[i] / 10 if abs(vector[i]) > 524288: + @warning_ignore("integer_division") factors[i] = factors[i] / 10 return "(" + \ @@ -34,7 +36,7 @@ func _vector_to_string_appropriate_digits(vector): # Expects a rotation where 0 is North, on the range -PI to PI. -func _cardinal_string_from_radians(angle): +func _cardinal_string_from_radians(angle: float) -> String: if angle > TAU * 3 / 8: return "South" if angle < -TAU * 3 / 8: diff --git a/3d/voxel/menu/ingame/pause_menu.gd b/3d/voxel/menu/ingame/pause_menu.gd index 2746d9bf..93d8eb99 100644 --- a/3d/voxel/menu/ingame/pause_menu.gd +++ b/3d/voxel/menu/ingame/pause_menu.gd @@ -1,14 +1,11 @@ extends Control -@onready var tree = get_tree() +@onready var crosshair: CenterContainer = $Crosshair +@onready var pause: VBoxContainer = $Pause +@onready var options: HBoxContainer = $Options +@onready var voxel_world: Node = $"../VoxelWorld" -@onready var crosshair = $Crosshair -@onready var pause = $Pause -@onready var options = $Options -@onready var voxel_world = $"../VoxelWorld" - - -func _process(_delta): +func _process(_delta: float) -> void: if Input.is_action_just_pressed(&"pause"): pause.visible = crosshair.visible crosshair.visible = not crosshair.visible @@ -19,23 +16,23 @@ func _process(_delta): Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) -func _on_Resume_pressed(): +func _on_Resume_pressed() -> void: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) crosshair.visible = true pause.visible = false -func _on_Options_pressed(): +func _on_Options_pressed() -> void: options.prev_menu = pause options.visible = true pause.visible = false -func _on_MainMenu_pressed(): +func _on_MainMenu_pressed() -> void: voxel_world.clean_up() - tree.change_scene_to_packed(load("res://menu/main/main_menu.tscn")) + get_tree().change_scene_to_packed(load("res://menu/main/main_menu.tscn")) -func _on_Exit_pressed(): +func _on_Exit_pressed() -> void: voxel_world.clean_up() - tree.quit() + get_tree().quit() diff --git a/3d/voxel/menu/ingame/pause_menu.tscn b/3d/voxel/menu/ingame/pause_menu.tscn index db94d314..f134d476 100644 --- a/3d/voxel/menu/ingame/pause_menu.tscn +++ b/3d/voxel/menu/ingame/pause_menu.tscn @@ -20,7 +20,7 @@ theme = ExtResource("2") script = ExtResource("4") [node name="Crosshair" type="CenterContainer" parent="."] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 @@ -28,44 +28,36 @@ grow_vertical = 2 [node name="TextureRect" type="TextureRect" parent="Crosshair"] modulate = Color(1, 1, 1, 0.501961) -offset_left = 784.0 -offset_top = 434.0 -offset_right = 816.0 -offset_bottom = 466.0 +layout_mode = 2 texture = ExtResource("1") [node name="Pause" type="VBoxContainer" parent="."] visible = false -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 [node name="ButtonHolder" type="HBoxContainer" parent="Pause"] -offset_right = 1024.0 -offset_bottom = 600.0 +layout_mode = 2 size_flags_vertical = 3 alignment = 1 [node name="MainButtons" type="VBoxContainer" parent="Pause/ButtonHolder"] -offset_left = 320.0 -offset_right = 704.0 -offset_bottom = 600.0 +layout_mode = 2 theme_override_constants/separation = 20 alignment = 1 [node name="Resume" type="TextureButton" parent="Pause/ButtonHolder/MainButtons"] -offset_top = 142.0 -offset_right = 384.0 -offset_bottom = 206.0 +layout_mode = 2 texture_normal = ExtResource("5") texture_pressed = ExtResource("5_sc8eq") texture_hover = ExtResource("6_xrlxa") texture_focused = ExtResource("7_elacb") [node name="Label" type="Label" parent="Pause/ButtonHolder/MainButtons/Resume"] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 offset_top = -1.0 @@ -78,16 +70,14 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="Options" type="TextureButton" parent="Pause/ButtonHolder/MainButtons"] -offset_top = 226.0 -offset_right = 384.0 -offset_bottom = 290.0 +layout_mode = 2 texture_normal = ExtResource("5") texture_pressed = ExtResource("5_sc8eq") texture_hover = ExtResource("6_xrlxa") texture_focused = ExtResource("7_elacb") [node name="Label" type="Label" parent="Pause/ButtonHolder/MainButtons/Options"] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 offset_top = -1.0 @@ -100,16 +90,14 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="MainMenu" type="TextureButton" parent="Pause/ButtonHolder/MainButtons"] -offset_top = 310.0 -offset_right = 384.0 -offset_bottom = 374.0 +layout_mode = 2 texture_normal = ExtResource("5") texture_pressed = ExtResource("5_sc8eq") texture_hover = ExtResource("6_xrlxa") texture_focused = ExtResource("7_elacb") [node name="Label" type="Label" parent="Pause/ButtonHolder/MainButtons/MainMenu"] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 offset_top = -1.0 @@ -122,16 +110,14 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="Exit" type="TextureButton" parent="Pause/ButtonHolder/MainButtons"] -offset_top = 394.0 -offset_right = 384.0 -offset_bottom = 458.0 +layout_mode = 2 texture_normal = ExtResource("5") texture_pressed = ExtResource("5_sc8eq") texture_hover = ExtResource("6_xrlxa") texture_focused = ExtResource("7_elacb") [node name="Label" type="Label" parent="Pause/ButtonHolder/MainButtons/Exit"] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 offset_top = -1.0 @@ -144,6 +130,8 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="Options" parent="." instance=ExtResource("3")] +layout_mode = 0 +anchors_preset = 0 [connection signal="pressed" from="Pause/ButtonHolder/MainButtons/Resume" to="." method="_on_Resume_pressed"] [connection signal="pressed" from="Pause/ButtonHolder/MainButtons/Options" to="." method="_on_Options_pressed"] diff --git a/3d/voxel/menu/main/main_menu.gd b/3d/voxel/menu/main/main_menu.gd index c35bccb5..a9227a34 100644 --- a/3d/voxel/menu/main/main_menu.gd +++ b/3d/voxel/menu/main/main_menu.gd @@ -1,37 +1,35 @@ extends Control -@onready var tree = get_tree() - -@onready var title = $TitleScreen -@onready var start = $StartGame -@onready var options = $Options +@onready var title: VBoxContainer = $TitleScreen +@onready var start: HBoxContainer = $StartGame +@onready var options: HBoxContainer = $Options -func _on_Start_pressed(): +func _on_Start_pressed() -> void: start.visible = true title.visible = false -func _on_Options_pressed(): +func _on_Options_pressed() -> void: options.prev_menu = title options.visible = true title.visible = false -func _on_Exit_pressed(): - tree.quit() +func _on_Exit_pressed() -> void: + get_tree().quit() -func _on_RandomBlocks_pressed(): +func _on_RandomBlocks_pressed() -> void: Settings.world_type = 0 - tree.change_scene_to_packed(preload("res://world/world.tscn")) + get_tree().change_scene_to_packed(preload("res://world/world.tscn")) -func _on_FlatGrass_pressed(): +func _on_FlatGrass_pressed() -> void: Settings.world_type = 1 - tree.change_scene_to_packed(preload("res://world/world.tscn")) + get_tree().change_scene_to_packed(preload("res://world/world.tscn")) -func _on_BackToTitle_pressed(): +func _on_BackToTitle_pressed() -> void: title.visible = true start.visible = false diff --git a/3d/voxel/menu/main/splash_text.gd b/3d/voxel/menu/main/splash_text.gd index ab1beb7b..f65832ad 100644 --- a/3d/voxel/menu/main/splash_text.gd +++ b/3d/voxel/menu/main/splash_text.gd @@ -2,7 +2,6 @@ extends Control var time := 0.0 - -func _process(delta): +func _process(delta: float) -> void: time += delta scale = Vector2.ONE * (1 - abs(sin(time * 4)) / 4) diff --git a/3d/voxel/menu/options/option_buttons.gd b/3d/voxel/menu/options/option_buttons.gd index 14332c32..df391596 100644 --- a/3d/voxel/menu/options/option_buttons.gd +++ b/3d/voxel/menu/options/option_buttons.gd @@ -1,22 +1,22 @@ extends Control -@onready var render_distance_label = $RenderDistanceLabel -@onready var render_distance_slider = $RenderDistanceSlider +@onready var render_distance_label: Label = $RenderDistanceLabel +@onready var render_distance_slider: Slider = $RenderDistanceSlider @onready var fog_checkbox: CheckBox = $FogCheckBox -func _ready(): +func _ready() -> void: render_distance_slider.value = Settings.render_distance render_distance_label.text = "Render distance: " + str(Settings.render_distance) fog_checkbox.button_pressed = Settings.fog_enabled -func _on_RenderDistanceSlider_value_changed(value): - Settings.render_distance = value +func _on_RenderDistanceSlider_value_changed(value: float) -> void: + Settings.render_distance = int(value) render_distance_label.text = "Render distance: " + str(value) Settings.save_settings() -func _on_FogCheckBox_pressed(): +func _on_FogCheckBox_pressed() -> void: Settings.fog_enabled = fog_checkbox.button_pressed Settings.save_settings() diff --git a/3d/voxel/menu/options/options.gd b/3d/voxel/menu/options/options.gd index bbf75b31..81477d4e 100644 --- a/3d/voxel/menu/options/options.gd +++ b/3d/voxel/menu/options/options.gd @@ -1,8 +1,7 @@ extends HBoxContainer -var prev_menu +var prev_menu: Control - -func _on_Back_pressed(): +func _on_Back_pressed() -> void: prev_menu.visible = true visible = false diff --git a/3d/voxel/player/player.gd b/3d/voxel/player/player.gd index e37b666e..6438ed1b 100644 --- a/3d/voxel/player/player.gd +++ b/3d/voxel/player/player.gd @@ -9,35 +9,35 @@ const MOVEMENT_SPEED_CROUCH_MODIFIER = 0.5 const MOVEMENT_FRICTION_GROUND = 0.9 const MOVEMENT_FRICTION_AIR = 0.98 -var _mouse_motion = Vector2() -var _selected_block = 6 +var _mouse_motion := Vector2() +var _selected_block := 6 -@onready var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") +@onready var gravity := float(ProjectSettings.get_setting("physics/3d/default_gravity")) -@onready var head = $Head -@onready var raycast = $Head/RayCast3D -@onready var camera_attributes = $Head/Camera3D.attributes -@onready var selected_block_texture = $SelectedBlock -@onready var voxel_world = $"../VoxelWorld" -@onready var crosshair = $"../PauseMenu/Crosshair" +@onready var head: Node3D = $Head +@onready var raycast: RayCast3D = $Head/RayCast3D +@onready var camera_attributes: CameraAttributes = $Head/Camera3D.attributes +@onready var selected_block_texture: TextureRect = $SelectedBlock +@onready var voxel_world: Node = $"../VoxelWorld" +@onready var crosshair: CenterContainer = $"../PauseMenu/Crosshair" -func _ready(): - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) +func _ready() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED -func _process(_delta): +func _process(_delta: float) -> void: # Mouse movement. - _mouse_motion.y = clamp(_mouse_motion.y, -1560, 1560) + _mouse_motion.y = clampf(_mouse_motion.y, -1560, 1560) transform.basis = Basis.from_euler(Vector3(0, _mouse_motion.x * -0.001, 0)) head.transform.basis = Basis.from_euler(Vector3(_mouse_motion.y * -0.001, 0, 0)) # Block selection. - var ray_position = raycast.get_collision_point() - var ray_normal = raycast.get_collision_normal() + var ray_position := raycast.get_collision_point() + var ray_normal := raycast.get_collision_normal() if Input.is_action_just_pressed(&"pick_block"): # Block picking. - var block_global_position = Vector3i((ray_position - ray_normal / 2).floor()) + var block_global_position := Vector3i((ray_position - ray_normal / 2).floor()) _selected_block = voxel_world.get_block_global_position(block_global_position) else: # Block prev/next keys. @@ -47,36 +47,36 @@ func _process(_delta): _selected_block += 1 _selected_block = wrapi(_selected_block, 1, 30) # Set the appropriate texture. - var uv = Chunk.calculate_block_uvs(_selected_block) + var uv := Chunk.calculate_block_uvs(_selected_block) selected_block_texture.texture.region = Rect2(uv[0] * 512, Vector2.ONE * 64) # Block breaking/placing. if crosshair.visible and raycast.is_colliding(): - var breaking = Input.is_action_just_pressed(&"break") - var placing = Input.is_action_just_pressed(&"place") + var breaking := Input.is_action_just_pressed(&"break") + var placing := Input.is_action_just_pressed(&"place") # Either both buttons were pressed or neither are, so stop. if breaking == placing: return if breaking: - var block_global_position = Vector3i((ray_position - ray_normal / 2).floor()) + var block_global_position := Vector3i((ray_position - ray_normal / 2).floor()) voxel_world.set_block_global_position(block_global_position, 0) elif placing: - var block_global_position = Vector3i((ray_position + ray_normal / 2).floor()) + var block_global_position := Vector3i((ray_position + ray_normal / 2).floor()) voxel_world.set_block_global_position(block_global_position, _selected_block) -func _physics_process(delta): +func _physics_process(delta: float) -> void: camera_attributes.dof_blur_far_enabled = Settings.fog_enabled camera_attributes.dof_blur_far_distance = Settings.fog_distance * 1.5 camera_attributes.dof_blur_far_transition = Settings.fog_distance * 0.125 # Crouching. - var crouching = Input.is_action_pressed(&"crouch") + var crouching := Input.is_action_pressed(&"crouch") head.transform.origin.y = lerpf(head.transform.origin.y, EYE_HEIGHT_CROUCH if crouching else EYE_HEIGHT_STAND, 16 * delta) # Keyboard movement. - var movement_vec2 = Input.get_vector("move_left", "move_right", "move_forward", "move_back") - var movement = transform.basis * (Vector3(movement_vec2.x, 0, movement_vec2.y)) + var movement_vec2 := Input.get_vector("move_left", "move_right", "move_forward", "move_back") + var movement := transform.basis * (Vector3(movement_vec2.x, 0, movement_vec2.y)) if is_on_floor(): movement *= MOVEMENT_SPEED_GROUND @@ -100,11 +100,11 @@ func _physics_process(delta): velocity.y = 7.5 -func _input(event): +func _input(event: InputEvent) -> void: if event is InputEventMouseMotion: if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: _mouse_motion += event.relative -func chunk_pos(): +func chunk_pos() -> Vector3i: return Vector3i((transform.origin / Chunk.CHUNK_SIZE).floor()) diff --git a/3d/voxel/player/player.tscn b/3d/voxel/player/player.tscn index 7b865c99..3a0d0f42 100644 --- a/3d/voxel/player/player.tscn +++ b/3d/voxel/player/player.tscn @@ -47,4 +47,4 @@ offset_bottom = 1.0 grow_horizontal = 0 grow_vertical = 0 texture = SubResource("2") -ignore_texture_size = true +expand_mode = 1 diff --git a/3d/voxel/project.godot b/3d/voxel/project.godot index 9e683df0..d21becce 100644 --- a/3d/voxel/project.godot +++ b/3d/voxel/project.godot @@ -25,6 +25,10 @@ config/icon="res://icon.webp" Settings="*res://settings.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1600 diff --git a/3d/voxel/settings.gd b/3d/voxel/settings.gd index eb7a4aef..263e68b1 100644 --- a/3d/voxel/settings.gd +++ b/3d/voxel/settings.gd @@ -1,39 +1,30 @@ extends Node -var render_distance = 7 -var fog_enabled = true +var render_distance := 7 +var fog_enabled := true -var fog_distance = 32.0 # Not saved, only used during runtime. -var world_type = 0 # Not saved, only used during runtime. +var fog_distance := 32.0 # Not saved, only used during runtime. +var world_type := 0 # Not saved, only used during runtime. -var _save_path = "user://settings.json" -@warning_ignore("unused_private_class_variable") -var _loaded = false - - -func _enter_tree(): - if Settings._loaded: - printerr("Error: Settings is an AutoLoad singleton and it shouldn't be instanced elsewhere.") - printerr("Please delete the instance at: " + String(get_path())) - else: - Settings._loaded = true +var _save_path := "user://settings.json" +func _enter_tree() -> void: if FileAccess.file_exists(_save_path): - var file = FileAccess.open(_save_path, FileAccess.READ) + var file := FileAccess.open(_save_path, FileAccess.READ) while file.get_position() < file.get_length(): # Get the saved dictionary from the next line in the save file - var json = JSON.new() + var json := JSON.new() json.parse(file.get_line()) - var data = json.get_data() + var data: Dictionary = json.get_data() render_distance = data["render_distance"] fog_enabled = data["fog_enabled"] else: save_settings() -func save_settings(): - var file = FileAccess.open(_save_path, FileAccess.WRITE) - var data = { +func save_settings() -> void: + var file := FileAccess.open(_save_path, FileAccess.WRITE) + var data := { "render_distance": render_distance, "fog_enabled": fog_enabled, } diff --git a/3d/voxel/world/chunk.gd b/3d/voxel/world/chunk.gd index 6d6b67df..ce94e519 100644 --- a/3d/voxel/world/chunk.gd +++ b/3d/voxel/world/chunk.gd @@ -10,15 +10,14 @@ const TEXTURE_SHEET_WIDTH = 8 const CHUNK_LAST_INDEX = CHUNK_SIZE - 1 const TEXTURE_TILE_SIZE = 1.0 / TEXTURE_SHEET_WIDTH -var data = {} -var chunk_position = Vector3i() +var data := {} +var chunk_position := Vector3i() -var _thread +var _thread: Thread -@onready var voxel_world = get_parent() +@onready var voxel_world := get_parent() - -func _ready(): +func _ready() -> void: transform.origin = Vector3(chunk_position * CHUNK_SIZE) name = str(chunk_position) if Settings.world_type == 0: @@ -33,7 +32,7 @@ func _ready(): _thread.start(_generate_chunk_mesh) -func regenerate(): +func regenerate() -> void: # Clear out all old nodes first. for c in get_children(): remove_child(c) @@ -44,7 +43,7 @@ func regenerate(): _generate_chunk_mesh() -func _generate_chunk_collider(): +func _generate_chunk_collider() -> void: if data.is_empty(): # Avoid errors caused by StaticBody3D not having colliders. _create_block_collider(Vector3.ZERO) @@ -55,40 +54,40 @@ func _generate_chunk_collider(): # For each block, generate a collider. Ensure collision layers are enabled. collision_layer = 0xFFFFF collision_mask = 0xFFFFF - for block_position in data.keys(): - var block_id = data[block_position] + for block_position: Vector3i in data.keys(): + var block_id: int = data[block_position] if block_id != 27 and block_id != 28: _create_block_collider(block_position) -func _generate_chunk_mesh(): +func _generate_chunk_mesh() -> void: if data.is_empty(): return - var surface_tool = SurfaceTool.new() + var surface_tool := SurfaceTool.new() surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES) # For each block, add data to the SurfaceTool and generate a collider. - for block_position in data.keys(): - var block_id = data[block_position] + for block_position: Vector3i in data.keys(): + var block_id: int = data[block_position] _draw_block_mesh(surface_tool, block_position, block_id) # Create the chunk's mesh from the SurfaceTool data. surface_tool.generate_normals() surface_tool.generate_tangents() surface_tool.index() - var array_mesh = surface_tool.commit() - var mi = MeshInstance3D.new() + var array_mesh := surface_tool.commit() + var mi := MeshInstance3D.new() mi.mesh = array_mesh mi.material_override = preload("res://world/textures/material.tres") add_child.call_deferred(mi) -func _draw_block_mesh(surface_tool, block_sub_position, block_id): - var verts = calculate_block_verts(block_sub_position) - var uvs = calculate_block_uvs(block_id) - var top_uvs = uvs - var bottom_uvs = uvs +func _draw_block_mesh(surface_tool: SurfaceTool, block_sub_position: Vector3i, block_id: int) -> void: + var verts := Chunk.calculate_block_verts(block_sub_position) + var uvs := Chunk.calculate_block_uvs(block_id) + var top_uvs := uvs + var bottom_uvs := uvs # Bush blocks get drawn in their own special way. if block_id == 27 or block_id == 28: @@ -100,26 +99,26 @@ func _draw_block_mesh(surface_tool, block_sub_position, block_id): # Allow some blocks to have different top/bottom textures. if block_id == 3: # Grass. - top_uvs = calculate_block_uvs(0) - bottom_uvs = calculate_block_uvs(2) + top_uvs = Chunk.calculate_block_uvs(0) + bottom_uvs = Chunk.calculate_block_uvs(2) elif block_id == 5: # Furnace. - top_uvs = calculate_block_uvs(31) + top_uvs = Chunk.calculate_block_uvs(31) bottom_uvs = top_uvs elif block_id == 12: # Log. - top_uvs = calculate_block_uvs(30) + top_uvs = Chunk.calculate_block_uvs(30) bottom_uvs = top_uvs elif block_id == 19: # Bookshelf. - top_uvs = calculate_block_uvs(4) + top_uvs = Chunk.calculate_block_uvs(4) bottom_uvs = top_uvs # Main rendering code for normal blocks. - var other_block_position = block_sub_position + Vector3i.LEFT - var other_block_id = 0 + var other_block_position := block_sub_position + Vector3i.LEFT + var other_block_id := 0 if other_block_position.x == -1: other_block_id = voxel_world.get_block_global_position(other_block_position + chunk_position * CHUNK_SIZE) elif data.has(other_block_position): other_block_id = data[other_block_position] - if block_id != other_block_id and is_block_transparent(other_block_id): + if block_id != other_block_id and Chunk.is_block_transparent(other_block_id): _draw_block_face(surface_tool, [verts[2], verts[0], verts[3], verts[1]], uvs) other_block_position = block_sub_position + Vector3i.RIGHT @@ -128,7 +127,7 @@ func _draw_block_mesh(surface_tool, block_sub_position, block_id): other_block_id = voxel_world.get_block_global_position(other_block_position + chunk_position * CHUNK_SIZE) elif data.has(other_block_position): other_block_id = data[other_block_position] - if block_id != other_block_id and is_block_transparent(other_block_id): + if block_id != other_block_id and Chunk.is_block_transparent(other_block_id): _draw_block_face(surface_tool, [verts[7], verts[5], verts[6], verts[4]], uvs) other_block_position = block_sub_position + Vector3i.FORWARD @@ -137,7 +136,7 @@ func _draw_block_mesh(surface_tool, block_sub_position, block_id): other_block_id = voxel_world.get_block_global_position(other_block_position + chunk_position * CHUNK_SIZE) elif data.has(other_block_position): other_block_id = data[other_block_position] - if block_id != other_block_id and is_block_transparent(other_block_id): + if block_id != other_block_id and Chunk.is_block_transparent(other_block_id): _draw_block_face(surface_tool, [verts[6], verts[4], verts[2], verts[0]], uvs) other_block_position = block_sub_position + Vector3i.BACK @@ -146,7 +145,7 @@ func _draw_block_mesh(surface_tool, block_sub_position, block_id): other_block_id = voxel_world.get_block_global_position(other_block_position + chunk_position * CHUNK_SIZE) elif data.has(other_block_position): other_block_id = data[other_block_position] - if block_id != other_block_id and is_block_transparent(other_block_id): + if block_id != other_block_id and Chunk.is_block_transparent(other_block_id): _draw_block_face(surface_tool, [verts[3], verts[1], verts[7], verts[5]], uvs) other_block_position = block_sub_position + Vector3i.DOWN @@ -155,7 +154,7 @@ func _draw_block_mesh(surface_tool, block_sub_position, block_id): other_block_id = voxel_world.get_block_global_position(other_block_position + chunk_position * CHUNK_SIZE) elif data.has(other_block_position): other_block_id = data[other_block_position] - if block_id != other_block_id and is_block_transparent(other_block_id): + if block_id != other_block_id and Chunk.is_block_transparent(other_block_id): _draw_block_face(surface_tool, [verts[4], verts[5], verts[0], verts[1]], bottom_uvs) other_block_position = block_sub_position + Vector3i.UP @@ -164,11 +163,11 @@ func _draw_block_mesh(surface_tool, block_sub_position, block_id): other_block_id = voxel_world.get_block_global_position(other_block_position + chunk_position * CHUNK_SIZE) elif data.has(other_block_position): other_block_id = data[other_block_position] - if block_id != other_block_id and is_block_transparent(other_block_id): + if block_id != other_block_id and Chunk.is_block_transparent(other_block_id): _draw_block_face(surface_tool, [verts[2], verts[3], verts[6], verts[7]], top_uvs) -func _draw_block_face(surface_tool: SurfaceTool, verts, uvs): +func _draw_block_face(surface_tool: SurfaceTool, verts: Array[Vector3], uvs: Array[Vector2]) -> void: surface_tool.set_uv(uvs[1]); surface_tool.add_vertex(verts[1]) surface_tool.set_uv(uvs[2]); surface_tool.add_vertex(verts[2]) surface_tool.set_uv(uvs[3]); surface_tool.add_vertex(verts[3]) @@ -178,18 +177,19 @@ func _draw_block_face(surface_tool: SurfaceTool, verts, uvs): surface_tool.set_uv(uvs[0]); surface_tool.add_vertex(verts[0]) -func _create_block_collider(block_sub_position): - var collider = CollisionShape3D.new() +func _create_block_collider(block_sub_position: Vector3) -> void: + var collider := CollisionShape3D.new() collider.shape = BoxShape3D.new() collider.shape.extents = Vector3.ONE / 2 collider.transform.origin = Vector3(block_sub_position) + Vector3.ONE / 2 add_child(collider) -static func calculate_block_uvs(block_id): +static func calculate_block_uvs(block_id: int) -> Array[Vector2]: # This method only supports square texture sheets. - var row = block_id / TEXTURE_SHEET_WIDTH - var col = block_id % TEXTURE_SHEET_WIDTH + @warning_ignore("integer_division") + var row := block_id / TEXTURE_SHEET_WIDTH + var col := block_id % TEXTURE_SHEET_WIDTH return [ # Godot 4 has a weird bug where there are seams at the edge @@ -201,7 +201,7 @@ static func calculate_block_uvs(block_id): ] -static func calculate_block_verts(block_position): +static func calculate_block_verts(block_position: Vector3) -> Array[Vector3]: return [ Vector3(block_position.x, block_position.y, block_position.z), Vector3(block_position.x, block_position.y, block_position.z + 1), @@ -214,5 +214,5 @@ static func calculate_block_verts(block_position): ] -static func is_block_transparent(block_id): +static func is_block_transparent(block_id: int) -> int: return block_id == 0 or (block_id > 25 and block_id < 30) diff --git a/3d/voxel/world/environment.gd b/3d/voxel/world/environment.gd index 8b369713..f58d6043 100644 --- a/3d/voxel/world/environment.gd +++ b/3d/voxel/world/environment.gd @@ -1,13 +1,12 @@ extends WorldEnvironment # This script controls fog based on the VoxelWorld's effective render distance. -@onready var voxel_world = $"../VoxelWorld" +@onready var voxel_world: Node = $"../VoxelWorld" - -func _process(delta): +func _process(delta: float) -> void: environment.fog_enabled = Settings.fog_enabled - var target_distance = clamp(voxel_world.effective_render_distance, 2, voxel_world.render_distance - 1) * Chunk.CHUNK_SIZE - var rate = delta * 4 + var target_distance := clampi(voxel_world.effective_render_distance, 2, voxel_world.render_distance - 1) * Chunk.CHUNK_SIZE + var rate := delta * 4 Settings.fog_distance = move_toward(Settings.fog_distance, target_distance, rate) environment.fog_density = 0.5 / Settings.fog_distance diff --git a/3d/voxel/world/terrain_generator.gd b/3d/voxel/world/terrain_generator.gd index 7c9c2b01..547502eb 100644 --- a/3d/voxel/world/terrain_generator.gd +++ b/3d/voxel/world/terrain_generator.gd @@ -1,44 +1,40 @@ class_name TerrainGenerator extends Resource -# Can't be "Chunk.CHUNK_SIZE" due to cyclic dependency issues. -# https://github.com/godotengine/godot/issues/21461 -const CHUNK_SIZE = 16 - const RANDOM_BLOCK_PROBABILITY = 0.015 - -static func empty(): +static func empty() -> Dictionary: return {} -static func random_blocks(): - var random_data = {} - for x in range(CHUNK_SIZE): - for y in range(CHUNK_SIZE): - for z in range(CHUNK_SIZE): - var vec = Vector3i(x, y, z) +static func random_blocks() -> Dictionary: + var random_data := {} + for x in Chunk.CHUNK_SIZE: + for y in Chunk.CHUNK_SIZE: + for z in Chunk.CHUNK_SIZE: + var vec := Vector3i(x, y, z) if randf() < RANDOM_BLOCK_PROBABILITY: random_data[vec] = randi() % 29 + 1 + return random_data -static func flat(chunk_position): - var data = {} +static func flat(chunk_position: Vector3i) -> Dictionary: + var data := {} if chunk_position.y != -1: return data - for x in range(CHUNK_SIZE): - for z in range(CHUNK_SIZE): + for x in Chunk.CHUNK_SIZE: + for z in Chunk.CHUNK_SIZE: data[Vector3i(x, 0, z)] = 3 return data # Used to create the project icon. -static func origin_grass(chunk_position): +static func origin_grass(chunk_position: Vector3i) -> Dictionary: if chunk_position == Vector3i.ZERO: - return {Vector3i.ZERO: 3} + return { Vector3i.ZERO: 3 } return {} diff --git a/3d/voxel/world/voxel_world.gd b/3d/voxel/world/voxel_world.gd index 5a837985..4e817602 100644 --- a/3d/voxel/world/voxel_world.gd +++ b/3d/voxel/world/voxel_world.gd @@ -4,26 +4,25 @@ extends Node const CHUNK_MIDPOINT = Vector3(0.5, 0.5, 0.5) * Chunk.CHUNK_SIZE const CHUNK_END_SIZE = Chunk.CHUNK_SIZE - 1 -var render_distance: +var render_distance: int: set(value): render_distance = value _delete_distance = value + 2 -var _delete_distance = 0 -var effective_render_distance = 0 -var _old_player_chunk = Vector3i() +var _delete_distance := 0 +var effective_render_distance := 0 +var _old_player_chunk := Vector3i() -var _generating = true -var _deleting = false +var _generating := true +var _deleting := false -var _chunks = {} +var _chunks := {} -@onready var player = $"../Player" +@onready var player: CharacterBody3D = $"../Player" - -func _process(_delta): +func _process(_delta: float) -> void: render_distance = Settings.render_distance - var player_chunk = Vector3i((player.transform.origin / Chunk.CHUNK_SIZE).round()) + var player_chunk := Vector3i((player.transform.origin / Chunk.CHUNK_SIZE).round()) if _deleting or player_chunk != _old_player_chunk: _delete_far_away_chunks(player_chunk) @@ -33,20 +32,21 @@ func _process(_delta): return # Try to generate chunks ahead of time based on where the player is moving. - player_chunk.y += round(clamp(player.velocity.y, -render_distance / 4, render_distance / 4)) + @warning_ignore("integer_division") + player_chunk.y += roundi(clampf(player.velocity.y, -render_distance / 4, render_distance / 4)) # Check existing chunks within range. If it doesn't exist, create it. for x in range(player_chunk.x - effective_render_distance, player_chunk.x + effective_render_distance): for y in range(player_chunk.y - effective_render_distance, player_chunk.y + effective_render_distance): for z in range(player_chunk.z - effective_render_distance, player_chunk.z + effective_render_distance): - var chunk_position = Vector3i(x, y, z) + var chunk_position := Vector3i(x, y, z) if Vector3(player_chunk).distance_to(Vector3(chunk_position)) > render_distance: continue if _chunks.has(chunk_position): continue - var chunk = Chunk.new() + var chunk := Chunk.new() chunk.chunk_position = chunk_position _chunks[chunk_position] = chunk add_child(chunk) @@ -61,20 +61,21 @@ func _process(_delta): _generating = false -func get_block_global_position(block_global_position: Vector3i): - var chunk_position = Vector3i((block_global_position / Chunk.CHUNK_SIZE)) +func get_block_global_position(block_global_position: Vector3i) -> int: + var chunk_position := Vector3i((block_global_position / Chunk.CHUNK_SIZE)) if _chunks.has(chunk_position): - var chunk = _chunks[chunk_position] - var sub_position = Vector3i(Vector3(block_global_position).posmod(Chunk.CHUNK_SIZE)) + var chunk: Chunk = _chunks[chunk_position] + var sub_position := Vector3i(Vector3(block_global_position).posmod(Chunk.CHUNK_SIZE)) if chunk.data.has(sub_position): return chunk.data[sub_position] + return 0 -func set_block_global_position(block_global_position: Vector3i, block_id): - var chunk_position = Vector3i((Vector3(block_global_position) / Chunk.CHUNK_SIZE).floor()) - var chunk = _chunks[chunk_position] - var sub_position = Vector3i(Vector3(block_global_position).posmod(Chunk.CHUNK_SIZE)) +func set_block_global_position(block_global_position: Vector3i, block_id: int) -> void: + var chunk_position := Vector3i((Vector3(block_global_position) / Chunk.CHUNK_SIZE).floor()) + var chunk: Chunk = _chunks[chunk_position] + var sub_position := Vector3i(Vector3(block_global_position).posmod(Chunk.CHUNK_SIZE)) if block_id == 0: chunk.data.erase(sub_position) else: @@ -97,31 +98,33 @@ func set_block_global_position(block_global_position: Vector3i, block_id): _chunks[chunk_position + Vector3i.UP].regenerate() -func clean_up(): - for chunk_position_key in _chunks.keys(): - var thread = _chunks[chunk_position_key]._thread +func clean_up() -> void: + for chunk_position_key: Vector3i in _chunks.keys(): + var thread: Thread = _chunks[chunk_position_key]._thread if thread: thread.wait_to_finish() + _chunks = {} set_process(false) + for c in get_children(): c.free() -func _delete_far_away_chunks(player_chunk): +func _delete_far_away_chunks(player_chunk: Vector3i) -> void: _old_player_chunk = player_chunk # If we need to delete chunks, give the new chunk system a chance to catch up. - effective_render_distance = max(1, effective_render_distance - 1) + effective_render_distance = maxi(1, effective_render_distance - 1) - var deleted_this_frame = 0 + var deleted_this_frame := 0 # We should delete old chunks more aggressively if moving fast. # An easy way to calculate this is by using the effective render distance. # The specific values in this formula are arbitrary and from experimentation. - var max_deletions = clamp(2 * (render_distance - effective_render_distance), 2, 8) + var max_deletions := clampi(2 * (render_distance - effective_render_distance), 2, 8) # Also take the opportunity to delete far away chunks. - for chunk_position_key in _chunks.keys(): + for chunk_position_key: Vector3i in _chunks.keys(): if Vector3(player_chunk).distance_to(Vector3(chunk_position_key)) > _delete_distance: - var thread = _chunks[chunk_position_key]._thread + var thread: Thread = _chunks[chunk_position_key]._thread if thread: thread.wait_to_finish() _chunks[chunk_position_key].queue_free() diff --git a/3d/waypoints/camera.gd b/3d/waypoints/camera.gd index 9a74b23e..4c4d5d59 100644 --- a/3d/waypoints/camera.gd +++ b/3d/waypoints/camera.gd @@ -1,17 +1,16 @@ extends Camera3D const MOUSE_SENSITIVITY = 0.002 -const MOVE_SPEED = 0.6 +const MOVE_SPEED = 0.65 -var rot = Vector3() -var velocity = Vector3() +var rot := Vector3() +var velocity := Vector3() + +func _ready() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED -func _ready(): - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - - -func _input(event): +func _input(event: InputEvent) -> void: # Mouse look (only if the mouse is captured). if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: # Horizontal mouse look. @@ -20,15 +19,15 @@ func _input(event): rot.x = clamp(rot.x - event.relative.y * MOUSE_SENSITIVITY, -1.57, 1.57) transform.basis = Basis.from_euler(rot) - if event.is_action_pressed("toggle_mouse_capture"): + if event.is_action_pressed(&"toggle_mouse_capture"): if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED: Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) else: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) -func _process(delta): - var motion = Vector3( +func _process(delta: float) -> void: + var motion := Vector3( Input.get_axis(&"move_left", &"move_right"), 0, Input.get_axis(&"move_forward", &"move_back") diff --git a/3d/waypoints/main.tscn b/3d/waypoints/main.tscn index 2cbdff32..88bfafdf 100644 --- a/3d/waypoints/main.tscn +++ b/3d/waypoints/main.tscn @@ -111,7 +111,7 @@ offset_top = 10.0 offset_right = 325.0 offset_bottom = 36.0 theme_override_colors/font_outline_color = Color(0, 0, 0, 1) -theme_override_constants/outline_size = 3 +theme_override_constants/outline_size = 4 theme_override_font_sizes/font_size = 18 text = "Press Esc or F10 to toggle mouse capture" diff --git a/3d/waypoints/project.godot b/3d/waypoints/project.godot index 60cc5538..1e58fe67 100644 --- a/3d/waypoints/project.godot +++ b/3d/waypoints/project.godot @@ -17,6 +17,11 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 +gdscript/warnings/integer_division=0 + [display] window/stretch/mode="canvas_items" diff --git a/3d/waypoints/waypoint.gd b/3d/waypoints/waypoint.gd index ca579be5..804ba27e 100644 --- a/3d/waypoints/waypoint.gd +++ b/3d/waypoints/waypoint.gd @@ -1,52 +1,50 @@ extends Control -# Some margin to keep the marker away from the screen's corners. +## Some margin to keep the marker away from the screen's corners. const MARGIN = 8 -@onready var camera = get_viewport().get_camera_3d() -@onready var parent = get_parent() -@onready var label = $Label -@onready var marker = $Marker - -# The waypoint's text. -@export var text = "Waypoint": +## The waypoint's text. +@export var text := "Waypoint": set(value): text = value # The label's text can only be set once the node is ready. if is_inside_tree(): label.text = value -# If `true`, the waypoint sticks to the viewport's edges when moving off-screen. -@export var sticky = true +## If `true`, the waypoint sticks to the viewport's edges when moving off-screen. +@export var sticky := true +@onready var camera := get_viewport().get_camera_3d() +@onready var parent := get_parent() +@onready var label: Label = $Label +@onready var marker: TextureRect = $Marker func _ready() -> void: self.text = text - - if not parent is Node3D: - push_error("The waypoint's parent node must inherit from Node3D.") + assert(parent is Node3D, "The waypoint's parent node must inherit from Node3D.") -func _process(_delta): +func _process(_delta: float) -> void: if not camera.current: # If the camera we have isn't the current one, get the current camera. camera = get_viewport().get_camera_3d() - var parent_position = parent.global_transform.origin - var camera_transform = camera.global_transform - var camera_position = camera_transform.origin + + var parent_position: Vector3 = parent.global_transform.origin + var camera_transform := camera.global_transform + var camera_position := camera_transform.origin # We would use "camera.is_position_behind(parent_position)", except # that it also accounts for the near clip plane, which we don't want. - var is_behind = camera_transform.basis.z.dot(parent_position - camera_position) > 0 + var is_behind := camera_transform.basis.z.dot(parent_position - camera_position) > 0 # Fade the waypoint when the camera gets close. - var distance = camera_position.distance_to(parent_position) + var distance := camera_position.distance_to(parent_position) modulate.a = clamp(remap(distance, 0, 2, 0, 1), 0, 1 ) - var unprojected_position = camera.unproject_position(parent_position) + var unprojected_position := camera.unproject_position(parent_position) # `get_size_override()` will return a valid size only if the stretch mode is `2d`. # Otherwise, the viewport size is used directly. - var viewport_base_size = ( + var viewport_base_size: Vector2i = ( get_viewport().content_scale_size if get_viewport().content_scale_size > Vector2i(0, 0) else get_viewport().size ) @@ -75,8 +73,8 @@ func _process(_delta): # This will be slightly off from the theoretical "ideal" position. if is_behind or unprojected_position.x < MARGIN or \ unprojected_position.x > viewport_base_size.x - MARGIN: - var look = camera_transform.looking_at(parent_position, Vector3.UP) - var diff = angle_diff(look.basis.get_euler().x, camera_transform.basis.get_euler().x) + var look := camera_transform.looking_at(parent_position, Vector3.UP) + var diff := angle_difference(look.basis.get_euler().x, camera_transform.basis.get_euler().x) unprojected_position.y = viewport_base_size.y * (0.5 + (diff / deg_to_rad(camera.fov))) position = Vector2( @@ -88,16 +86,16 @@ func _process(_delta): rotation = 0 # Used to display a diagonal arrow when the waypoint is displayed in # one of the screen corners. - var overflow = 0 + var overflow := 0 if position.x <= MARGIN: # Left overflow. - overflow = -TAU / 8.0 + overflow = int(-TAU / 8.0) label.visible = false rotation = TAU / 4.0 elif position.x >= viewport_base_size.x - MARGIN: # Right overflow. - overflow = TAU / 8.0 + overflow = int(TAU / 8.0) label.visible = false rotation = TAU * 3.0 / 4.0 @@ -109,8 +107,3 @@ func _process(_delta): # Bottom overflow. label.visible = false rotation = -overflow - - -static func angle_diff(from, to): - var diff = fmod(to - from, TAU) - return fmod(2.0 * diff, TAU) - diff diff --git a/3d/waypoints/waypoint.svg.import b/3d/waypoints/waypoint.svg.import index c0becd98..5968696b 100644 --- a/3d/waypoints/waypoint.svg.import +++ b/3d/waypoints/waypoint.svg.import @@ -21,7 +21,7 @@ compress/lossy_quality=0.7 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 -mipmaps/generate=false +mipmaps/generate=true mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" diff --git a/3d/waypoints/waypoint.tscn b/3d/waypoints/waypoint.tscn index dc11fff0..9f346f47 100644 --- a/3d/waypoints/waypoint.tscn +++ b/3d/waypoints/waypoint.tscn @@ -9,20 +9,22 @@ anchors_preset = 0 script = ExtResource("1") [node name="Label" type="Label" parent="."] +layout_mode = 0 offset_left = -200.0 offset_top = -44.0 offset_right = 200.0 offset_bottom = -15.0 theme_override_colors/font_outline_color = Color(0, 0, 0, 1) -theme_override_constants/outline_size = 3 +theme_override_constants/outline_size = 4 theme_override_font_sizes/font_size = 18 text = "Waypoint" horizontal_alignment = 1 vertical_alignment = 1 [node name="Marker" type="TextureRect" parent="."] +layout_mode = 0 offset_left = -8.0 offset_top = -16.0 offset_right = 8.0 texture = ExtResource("2") -ignore_texture_size = true +expand_mode = 1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1201ee23..f3df1576 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,10 +11,10 @@ Please follow these guidelines for submitting new demos or improving existing de - The demo must follow all of the Godot style guides: - [Project organization](https://docs.godotengine.org/en/stable/tutorials/best_practices/project_organization.html) - [GDScript style guide](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_styleguide.html) - - In GDScript, type hints should be used to improve runtime performance - and ease code maintenance. Do not use type inference syntax - (`var some_integer := 123`) if the resulting type is not obvious from - reading the righthand side of the assignment. + - In GDScript, type hints should be used whenever possible to improve runtime performance + and ease code maintenance. The **Debug > GDScript > Warnings > Untyped Declaration** + project setting is set to **Warn** on most existing demos to enforce this. + This setting should also be configured to **Warn** on new demos. - [C# style guide](https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/c_sharp_style_guide.html) - [Shaders style guide](https://docs.godotengine.org/en/stable/tutorials/shaders/shaders_style_guide.html) diff --git a/audio/bpm_sync/bpm_sync.gd b/audio/bpm_sync/bpm_sync.gd index f9e5044c..f8efa653 100644 --- a/audio/bpm_sync/bpm_sync.gd +++ b/audio/bpm_sync/bpm_sync.gd @@ -1,36 +1,29 @@ extends Panel -const BPM = 116 -const BARS = 4 - -var playing = false -const COMPENSATE_FRAMES = 2 -const COMPENSATE_HZ = 60.0 - enum SyncSource { SYSTEM_CLOCK, SOUND_CLOCK, } -var sync_source = SyncSource.SYSTEM_CLOCK +const BPM = 116 +const BARS = 4 + +const COMPENSATE_FRAMES = 2 +const COMPENSATE_HZ = 60.0 + +var playing := false +var sync_source := SyncSource.SYSTEM_CLOCK # Used by system clock. -var time_begin -var time_delay +var time_begin: float +var time_delay: float -func strsec(secs): - var s = str(secs) - if (secs < 10): - s = "0" + s - return s - - -func _process(_delta): +func _process(_delta: float) -> void: if not playing or not $Player.playing: return - var time = 0.0 + var time := 0.0 if sync_source == SyncSource.SYSTEM_CLOCK: # Obtain from ticks. time = (Time.get_ticks_usec() - time_begin) / 1000000.0 @@ -39,14 +32,14 @@ func _process(_delta): elif sync_source == SyncSource.SOUND_CLOCK: time = $Player.get_playback_position() + AudioServer.get_time_since_last_mix() - AudioServer.get_output_latency() + (1 / COMPENSATE_HZ) * COMPENSATE_FRAMES - var beat = int(time * BPM / 60.0) - var seconds = int(time) - var seconds_total = int($Player.stream.get_length()) + var beat := int(time * BPM / 60.0) + var seconds := int(time) + var seconds_total := int($Player.stream.get_length()) @warning_ignore("integer_division") - $Label.text = str("BEAT: ", beat % BARS + 1, "/", BARS, " TIME: ", seconds / 60, ":", strsec(seconds % 60), " / ", seconds_total / 60, ":", strsec(seconds_total % 60)) + $Label.text = str("BEAT: ", beat % BARS + 1, "/", BARS, " TIME: ", seconds / 60, ":", str(seconds % 60).pad_zeros(2), " / ", seconds_total / 60, ":", str(seconds_total % 60).pad_zeros(2)) -func _on_PlaySystem_pressed(): +func _on_PlaySystem_pressed() -> void: sync_source = SyncSource.SYSTEM_CLOCK time_begin = Time.get_ticks_usec() time_delay = AudioServer.get_time_to_next_mix() + AudioServer.get_output_latency() @@ -54,7 +47,7 @@ func _on_PlaySystem_pressed(): $Player.play() -func _on_PlaySound_pressed(): +func _on_PlaySound_pressed() -> void: sync_source = SyncSource.SOUND_CLOCK playing = true $Player.play() diff --git a/audio/bpm_sync/bpm_sync.tscn b/audio/bpm_sync/bpm_sync.tscn index aa8265a7..dcd9301f 100644 --- a/audio/bpm_sync/bpm_sync.tscn +++ b/audio/bpm_sync/bpm_sync.tscn @@ -19,32 +19,62 @@ size_flags_vertical = 4 script = ExtResource("7") [node name="Label" type="Label" parent="."] -layout_mode = 0 -offset_left = 106.895 -offset_top = 427.158 -offset_right = 914.895 -offset_bottom = 488.158 +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -404.0 +offset_top = 55.0 +offset_right = 404.0 +offset_bottom = 121.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_colors/font_color = Color(0.654902, 1, 0.67451, 1) +theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) +theme_override_constants/shadow_offset_x = 4 +theme_override_constants/shadow_offset_y = 4 theme_override_fonts/font = ExtResource("2_wyi3x") +theme_override_font_sizes/font_size = 48 +text = "Press one of the buttons." +horizontal_alignment = 1 +vertical_alignment = 1 [node name="Player" type="AudioStreamPlayer" parent="."] stream = ExtResource("3") +volume_db = -6.0 [node name="PlaySystem" type="TextureButton" parent="."] -layout_mode = 0 -offset_left = 214.737 -offset_top = 187.368 -offset_right = 342.737 -offset_bottom = 315.368 +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -288.0 +offset_top = -136.0 +offset_right = -160.0 +offset_bottom = -7.99997 +grow_horizontal = 2 +grow_vertical = 2 texture_normal = ExtResource("5") texture_pressed = ExtResource("5") texture_hover = ExtResource("1") [node name="PlaySound" type="TextureButton" parent="."] -layout_mode = 0 -offset_left = 622.105 -offset_top = 183.158 -offset_right = 750.105 -offset_bottom = 311.158 +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = 160.0 +offset_top = -136.0 +offset_right = 288.0 +offset_bottom = -8.0 +grow_horizontal = 2 +grow_vertical = 2 texture_normal = ExtResource("2") texture_pressed = ExtResource("2") texture_hover = ExtResource("4") diff --git a/audio/bpm_sync/project.godot b/audio/bpm_sync/project.godot index eb1a08d2..40b34271 100644 --- a/audio/bpm_sync/project.godot +++ b/audio/bpm_sync/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://bpm_sync.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/audio/device_changer/Changer.gd b/audio/device_changer/Changer.gd index 5f0bafc7..68b4ae21 100644 --- a/audio/device_changer/Changer.gd +++ b/audio/device_changer/Changer.gd @@ -1,22 +1,21 @@ extends Control -@onready var item_list = get_node(^"ItemList") +@onready var item_list: ItemList = $ItemList - -func _ready(): +func _ready() -> void: for item in AudioServer.get_output_device_list(): item_list.add_item(item) - var device = AudioServer.get_output_device() - for i in range(item_list.get_item_count()): + var device := AudioServer.get_output_device() + for i in item_list.get_item_count(): if device == item_list.get_item_text(i): item_list.select(i) break -func _process(_delta): - var speaker_mode_text = "Stereo" - var speaker_mode = AudioServer.get_speaker_mode() +func _process(_delta: float) -> void: + var speaker_mode_text := "Stereo" + var speaker_mode := AudioServer.get_speaker_mode() if speaker_mode == AudioServer.SPEAKER_SURROUND_31: speaker_mode_text = "Surround 3.1" @@ -29,13 +28,13 @@ func _process(_delta): $DeviceInfo.text += "Speaker Mode: " + speaker_mode_text -func _on_Button_button_down(): +func _on_Button_button_down() -> void: for item in item_list.get_selected_items(): - var device = item_list.get_item_text(item) + var device := item_list.get_item_text(item) AudioServer.set_output_device(device) -func _on_Play_Audio_button_down(): +func _on_Play_Audio_button_down() -> void: if $AudioStreamPlayer.playing: $AudioStreamPlayer.stop() $PlayAudio.text = "Play Audio" diff --git a/audio/device_changer/Changer.tscn b/audio/device_changer/Changer.tscn index be235568..b70a53a8 100644 --- a/audio/device_changer/Changer.tscn +++ b/audio/device_changer/Changer.tscn @@ -27,10 +27,11 @@ offset_bottom = 228.0 [node name="DeviceInfo" type="Label" parent="."] layout_mode = 0 -offset_left = 321.0 +offset_left = -64.0 offset_top = 248.0 -offset_right = 660.0 +offset_right = 1046.0 offset_bottom = 284.0 +horizontal_alignment = 1 [node name="SetDevice" type="Button" parent="."] layout_mode = 0 diff --git a/audio/device_changer/project.godot b/audio/device_changer/project.godot index 65dd98ea..91da7a82 100644 --- a/audio/device_changer/project.godot +++ b/audio/device_changer/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/audio/generator/generator_demo.gd b/audio/generator/generator_demo.gd index 0d7f9e72..d557d207 100644 --- a/audio/generator/generator_demo.gd +++ b/audio/generator/generator_demo.gd @@ -1,26 +1,28 @@ extends Node -var sample_hz = 22050.0 # Keep the number of samples to mix low, GDScript is not super fast. -var pulse_hz = 440.0 -var phase = 0.0 +# Keep the number of samples per second to mix low, as GDScript is not super fast. +var sample_hz := 22050.0 +var pulse_hz := 440.0 +var phase := 0.0 -var playback: AudioStreamPlayback = null # Actual playback stream, assigned in _ready(). +# Actual playback stream, assigned in _ready(). +var playback: AudioStreamPlayback -func _fill_buffer(): - var increment = pulse_hz / sample_hz +func _fill_buffer() -> void: + var increment := pulse_hz / sample_hz - var to_fill = playback.get_frames_available() + var to_fill: int = playback.get_frames_available() while to_fill > 0: playback.push_frame(Vector2.ONE * sin(phase * TAU)) # Audio frames are stereo. phase = fmod(phase + increment, 1.0) to_fill -= 1 -func _process(_delta): +func _process(_delta: float) -> void: _fill_buffer() -func _ready(): +func _ready() -> void: # Setting mix rate is only possible before play(). $Player.stream.mix_rate = sample_hz $Player.play() @@ -30,12 +32,12 @@ func _ready(): _fill_buffer() -func _on_frequency_h_slider_value_changed(value): +func _on_frequency_h_slider_value_changed(value: float) -> void: %FrequencyLabel.text = "%d Hz" % value pulse_hz = value -func _on_volume_h_slider_value_changed(value): +func _on_volume_h_slider_value_changed(value: float) -> void: # Use `linear_to_db()` to get a volume slider that matches perceptual human hearing. %VolumeLabel.text = "%.2f dB" % linear_to_db(value) $Player.volume_db = linear_to_db(value) diff --git a/audio/generator/project.godot b/audio/generator/project.godot index 40e32adf..141cdb5b 100644 --- a/audio/generator/project.godot +++ b/audio/generator/project.godot @@ -20,6 +20,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/audio/mic_record/MicRecord.gd b/audio/mic_record/MicRecord.gd index 69be97f4..184ab313 100644 --- a/audio/mic_record/MicRecord.gd +++ b/audio/mic_record/MicRecord.gd @@ -1,19 +1,19 @@ extends Control -var effect # See AudioEffect in docs -var recording # See AudioStreamSample in docs +var effect: AudioEffect +var recording: AudioStreamWAV var stereo := true -var mix_rate := 44100 # This is the default mix rate on recordings -var format := 1 # This equals to the default format: 16 bits +var mix_rate := 44100 # This is the default mix rate on recordings. +var format := AudioStreamWAV.FORMAT_16_BITS # This is the default format on recordings. -func _ready(): - var idx = AudioServer.get_bus_index("Record") +func _ready() -> void: + var idx := AudioServer.get_bus_index("Record") effect = AudioServer.get_bus_effect(idx, 0) -func _on_RecordButton_pressed(): +func _on_record_button_pressed() -> void: if effect.is_recording_active(): recording = effect.get_recording() $PlayButton.disabled = false @@ -32,18 +32,18 @@ func _on_RecordButton_pressed(): $Status.text = "Status: Recording..." -func _on_PlayButton_pressed(): +func _on_play_button_pressed() -> void: print_rich("\n[b]Playing recording:[/b] %s" % recording) print_rich("[b]Format:[/b] %s" % ("8-bit uncompressed" if recording.format == 0 else "16-bit uncompressed" if recording.format == 1 else "IMA ADPCM compressed")) print_rich("[b]Mix rate:[/b] %s Hz" % recording.mix_rate) print_rich("[b]Stereo:[/b] %s" % ("Yes" if recording.stereo else "No")) - var data = recording.get_data() + var data := recording.get_data() print_rich("[b]Size:[/b] %s bytes" % data.size()) $AudioStreamPlayer.stream = recording $AudioStreamPlayer.play() -func _on_Play_Music_pressed(): +func _on_play_music_pressed() -> void: if $AudioStreamPlayer2.playing: $AudioStreamPlayer2.stop() $PlayMusic.text = "Play Music" @@ -52,13 +52,13 @@ func _on_Play_Music_pressed(): $PlayMusic.text = "Stop Music" -func _on_SaveButton_pressed(): - var save_path = $SaveButton/Filename.text +func _on_save_button_pressed() -> void: + var save_path: String = $SaveButton/Filename.text recording.save_to_wav(save_path) $Status.text = "Status: Saved WAV file to: %s\n(%s)" % [save_path, ProjectSettings.globalize_path(save_path)] -func _on_MixRateOptionButton_item_selected(index: int) -> void: +func _on_mix_rate_option_button_item_selected(index: int) -> void: match index: 0: mix_rate = 11025 @@ -76,7 +76,7 @@ func _on_MixRateOptionButton_item_selected(index: int) -> void: recording.set_mix_rate(mix_rate) -func _on_FormatOptionButton_item_selected(index: int) -> void: +func _on_format_option_button_item_selected(index: int) -> void: match index: 0: format = AudioStreamWAV.FORMAT_8_BITS @@ -88,11 +88,12 @@ func _on_FormatOptionButton_item_selected(index: int) -> void: recording.set_format(format) -func _on_StereoCheckButton_toggled(button_pressed: bool) -> void: +func _on_stereo_check_button_toggled(button_pressed: bool) -> void: stereo = button_pressed if recording != null: recording.set_stereo(stereo) -func _on_open_user_folder_button_pressed(): +func _on_open_user_folder_button_pressed() -> void: OS.shell_open(ProjectSettings.globalize_path("user://")) + diff --git a/audio/mic_record/MicRecord.tscn b/audio/mic_record/MicRecord.tscn index c83240a2..88bf2233 100644 --- a/audio/mic_record/MicRecord.tscn +++ b/audio/mic_record/MicRecord.tscn @@ -159,11 +159,11 @@ offset_right = 372.0 offset_bottom = 374.0 text = "Open User Folder" -[connection signal="pressed" from="RecordButton" to="." method="_on_RecordButton_pressed"] -[connection signal="pressed" from="PlayButton" to="." method="_on_PlayButton_pressed"] -[connection signal="pressed" from="PlayMusic" to="." method="_on_Play_Music_pressed"] -[connection signal="item_selected" from="FormatOptionButton" to="." method="_on_FormatOptionButton_item_selected"] -[connection signal="item_selected" from="MixRateOptionButton" to="." method="_on_MixRateOptionButton_item_selected"] -[connection signal="toggled" from="StereoCheckButton" to="." method="_on_StereoCheckButton_toggled"] -[connection signal="pressed" from="SaveButton" to="." method="_on_SaveButton_pressed"] +[connection signal="pressed" from="RecordButton" to="." method="_on_record_button_pressed"] +[connection signal="pressed" from="PlayButton" to="." method="_on_play_button_pressed"] +[connection signal="pressed" from="PlayMusic" to="." method="_on_play_music_pressed"] +[connection signal="item_selected" from="FormatOptionButton" to="." method="_on_format_option_button_item_selected"] +[connection signal="item_selected" from="MixRateOptionButton" to="." method="_on_mix_rate_option_button_item_selected"] +[connection signal="toggled" from="StereoCheckButton" to="." method="_on_stereo_check_button_toggled"] +[connection signal="pressed" from="SaveButton" to="." method="_on_save_button_pressed"] [connection signal="pressed" from="OpenUserFolderButton" to="." method="_on_open_user_folder_button_pressed"] diff --git a/audio/mic_record/project.godot b/audio/mic_record/project.godot index 8974e148..22e5069c 100644 --- a/audio/mic_record/project.godot +++ b/audio/mic_record/project.godot @@ -24,6 +24,10 @@ config/icon="res://icon.webp" driver/enable_input=true enable_audio_input=true +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=640 diff --git a/audio/midi_piano/piano.gd b/audio/midi_piano/piano.gd index c8bce698..5c51327c 100644 --- a/audio/midi_piano/piano.gd +++ b/audio/midi_piano/piano.gd @@ -9,37 +9,38 @@ extends Control const START_KEY = 21 const END_KEY = 108 -const WhiteKeyScene = preload("res://piano_keys/white_piano_key.tscn") -const BlackKeyScene = preload("res://piano_keys/black_piano_key.tscn") +const WhiteKeyScene := preload("res://piano_keys/white_piano_key.tscn") +const BlackKeyScene := preload("res://piano_keys/black_piano_key.tscn") var piano_key_dict := Dictionary() -@onready var white_keys = $WhiteKeys -@onready var black_keys = $BlackKeys +@onready var white_keys: HBoxContainer = $WhiteKeys +@onready var black_keys: HBoxContainer = $BlackKeys -func _ready(): - # Sanity checks. - if _is_note_index_sharp(_pitch_index_to_note_index(START_KEY)): - printerr("The start key can't be a sharp note (limitation of this piano-generating algorithm). Try 21.") - return +func _ready() -> void: + assert(not _is_note_index_sharp(_pitch_index_to_note_index(START_KEY)), "The start key can't be a sharp note (limitation of this piano-generating algorithm). Try 21.") for i in range(START_KEY, END_KEY + 1): piano_key_dict[i] = _create_piano_key(i) if white_keys.get_child_count() != black_keys.get_child_count(): _add_placeholder_key(black_keys) + OS.open_midi_inputs() - if len(OS.get_connected_midi_inputs()) > 0: + + if not OS.get_connected_midi_inputs().is_empty(): print(OS.get_connected_midi_inputs()) -func _input(input_event): - if not (input_event is InputEventMIDI): +func _input(input_event: InputEvent) -> void: + if not input_event is InputEventMIDI: return + var midi_event: InputEventMIDI = input_event if midi_event.pitch < START_KEY or midi_event.pitch > END_KEY: # The given pitch isn't on the on-screen keyboard, so return. return + _print_midi_info(midi_event) var key: PianoKey = piano_key_dict[midi_event.pitch] if midi_event.message == MIDI_MESSAGE_NOTE_ON: @@ -48,16 +49,16 @@ func _input(input_event): key.deactivate() -func _add_placeholder_key(container): - var placeholder = Control.new() +func _add_placeholder_key(container: HBoxContainer) -> void: + var placeholder := Control.new() placeholder.size_flags_horizontal = SIZE_EXPAND_FILL placeholder.mouse_filter = Control.MOUSE_FILTER_IGNORE placeholder.name = &"Placeholder" container.add_child(placeholder) -func _create_piano_key(pitch_index): - var note_index = _pitch_index_to_note_index(pitch_index) +func _create_piano_key(pitch_index: int) -> PianoKey: + var note_index := _pitch_index_to_note_index(pitch_index) var piano_key: PianoKey if _is_note_index_sharp(note_index): piano_key = BlackKeyScene.instantiate() @@ -71,22 +72,22 @@ func _create_piano_key(pitch_index): return piano_key -func _is_note_index_lacking_sharp(note_index: int): +func _is_note_index_lacking_sharp(note_index: int) -> bool: # B and E, because no B# or E# return note_index in [2, 7] -func _is_note_index_sharp(note_index: int): +func _is_note_index_sharp(note_index: int) -> bool: # A#, C#, D#, F#, and G# return note_index in [1, 4, 6, 9, 11] -func _pitch_index_to_note_index(pitch: int): +func _pitch_index_to_note_index(pitch: int) -> int: pitch += 3 return pitch % 12 -func _print_midi_info(midi_event: InputEventMIDI): +func _print_midi_info(midi_event: InputEventMIDI) -> void: print(midi_event) print("Channel: " + str(midi_event.channel)) print("Message: " + str(midi_event.message)) diff --git a/audio/midi_piano/piano_keys/piano_key.gd b/audio/midi_piano/piano_keys/piano_key.gd index 71396ae5..ef813361 100644 --- a/audio/midi_piano/piano_keys/piano_key.gd +++ b/audio/midi_piano/piano_keys/piano_key.gd @@ -7,14 +7,13 @@ var pitch_scale: float @onready var start_color: Color = key.color @onready var color_timer: Timer = $ColorTimer - -func setup(pitch_index: int): +func setup(pitch_index: int) -> void: name = "PianoKey" + str(pitch_index) var exponent := (pitch_index - 69.0) / 12.0 pitch_scale = pow(2, exponent) -func activate(): +func activate() -> void: key.color = (Color.YELLOW + start_color) / 2 var audio := AudioStreamPlayer.new() add_child(audio) @@ -26,5 +25,5 @@ func activate(): audio.queue_free() -func deactivate(): +func deactivate() -> void: key.color = start_color diff --git a/audio/midi_piano/piano_keys/piano_key_color.gd b/audio/midi_piano/piano_keys/piano_key_color.gd index 2e8069bf..527a468e 100644 --- a/audio/midi_piano/piano_keys/piano_key_color.gd +++ b/audio/midi_piano/piano_keys/piano_key_color.gd @@ -1,8 +1,8 @@ extends ColorRect -@onready var parent = get_parent() +@onready var parent: PianoKey = get_parent() # Yes, this script exists just for this one method. -func _gui_input(input_event): +func _gui_input(input_event: InputEvent) -> void: if input_event is InputEventMouseButton and input_event.pressed: parent.activate() diff --git a/audio/midi_piano/project.godot b/audio/midi_piano/project.godot index 8a957415..85529962 100644 --- a/audio/midi_piano/project.godot +++ b/audio/midi_piano/project.godot @@ -16,6 +16,10 @@ run/main_scene="res://piano.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1280 diff --git a/audio/spectrum/show_spectrum.gd b/audio/spectrum/show_spectrum.gd index 3283a716..4ec46f1b 100644 --- a/audio/spectrum/show_spectrum.gd +++ b/audio/spectrum/show_spectrum.gd @@ -1,6 +1,5 @@ extends Node2D - const VU_COUNT = 16 const FREQ_MAX = 11050.0 @@ -10,14 +9,14 @@ const HEIGHT_SCALE = 8.0 const MIN_DB = 60 const ANIMATION_SPEED = 0.1 -var spectrum -var min_values = [] -var max_values = [] +var spectrum: AudioEffectSpectrumAnalyzerInstance +var min_values: Array[float] = [] +var max_values: Array[float] = [] - -func _draw(): - var w = WIDTH / VU_COUNT - for i in range(VU_COUNT): +func _draw() -> void: + @warning_ignore("integer_division") + var w := WIDTH / VU_COUNT + for i in VU_COUNT: var min_height = min_values[i] var max_height = max_values[i] var height = lerp(min_height, max_height, ANIMATION_SPEED) @@ -48,32 +47,32 @@ func _draw(): ) -func _process(_delta): - var data = [] - var prev_hz = 0 +func _process(_delta: float) -> void: + var data: Array[float] = [] + var prev_hz := 0.0 for i in range(1, VU_COUNT + 1): - var hz = i * FREQ_MAX / VU_COUNT - var magnitude = spectrum.get_magnitude_for_frequency_range(prev_hz, hz).length() - var energy = clampf((MIN_DB + linear_to_db(magnitude)) / MIN_DB, 0, 1) - var height = energy * HEIGHT * HEIGHT_SCALE + var hz := i * FREQ_MAX / VU_COUNT + var magnitude := spectrum.get_magnitude_for_frequency_range(prev_hz, hz).length() + var energy := clampf((MIN_DB + linear_to_db(magnitude)) / MIN_DB, 0, 1) + var height := energy * HEIGHT * HEIGHT_SCALE data.append(height) prev_hz = hz - for i in range(VU_COUNT): + for i in VU_COUNT: if data[i] > max_values[i]: max_values[i] = data[i] else: - max_values[i] = lerp(max_values[i], data[i], ANIMATION_SPEED) + max_values[i] = lerpf(max_values[i], data[i], ANIMATION_SPEED) if data[i] <= 0.0: - min_values[i] = lerp(min_values[i], 0.0, ANIMATION_SPEED) + min_values[i] = lerpf(min_values[i], 0.0, ANIMATION_SPEED) # Sound plays back continuously, so the graph needs to be updated every frame. queue_redraw() -func _ready(): +func _ready() -> void: spectrum = AudioServer.get_bus_effect_instance(0, 0) min_values.resize(VU_COUNT) max_values.resize(VU_COUNT) diff --git a/audio/text_to_speech/control.tscn b/audio/text_to_speech/control.tscn index 08b1df71..29e3712c 100644 --- a/audio/text_to_speech/control.tscn +++ b/audio/text_to_speech/control.tscn @@ -52,6 +52,7 @@ offset_top = 56.0 offset_right = 704.0 offset_bottom = 296.0 columns = 2 +select_mode = 1 [node name="Utterance" type="TextEdit" parent="."] layout_mode = 0 @@ -187,7 +188,6 @@ offset_bottom = 40.0 layout_mode = 0 offset_right = 128.0 offset_bottom = 32.0 -theme_override_font_sizes/font_size = 16 text = "Speaking..." [node name="Log" type="TextEdit" parent="."] @@ -232,13 +232,12 @@ text = "Demo" [connection signal="text_changed" from="LineEditFilterLang" to="." method="_on_LineEditFilterName_text_changed"] [connection signal="text_changed" from="LineEditFilterName" to="." method="_on_LineEditFilterName_text_changed"] -[connection signal="item_activated" from="Tree" to="." method="_on_ItemList_item_activated"] -[connection signal="pressed" from="ButtonSpeak" to="." method="_on_ButtonSpeak_pressed"] -[connection signal="pressed" from="ButtonIntSpeak" to="." method="_on_ButtonIntSpeak_pressed"] -[connection signal="pressed" from="ButtonStop" to="." method="_on_ButtonStop_pressed"] -[connection signal="pressed" from="ButtonPause" to="." method="_on_ButtonPause_pressed"] +[connection signal="pressed" from="ButtonSpeak" to="." method="_on_button_speak_pressed"] +[connection signal="pressed" from="ButtonIntSpeak" to="." method="_on_button_int_speak_pressed"] +[connection signal="pressed" from="ButtonStop" to="." method="_on_button_stop_pressed"] +[connection signal="pressed" from="ButtonPause" to="." method="_on_button_pause_pressed"] [connection signal="value_changed" from="HSliderRate" to="." method="_on_HSliderRate_value_changed"] [connection signal="value_changed" from="HSliderPitch" to="." method="_on_HSliderPitch_value_changed"] [connection signal="value_changed" from="HSliderVolume" to="." method="_on_HSliderVolume_value_changed"] -[connection signal="pressed" from="Log/ButtonClearLog" to="." method="_on_ButtonClearLog_pressed"] +[connection signal="pressed" from="Log/ButtonClearLog" to="." method="_on_button_clear_log_pressed"] [connection signal="pressed" from="ButtonDemo" to="." method="_on_Button_pressed"] diff --git a/audio/text_to_speech/project.godot b/audio/text_to_speech/project.godot index 42f9fdcc..cacb368d 100644 --- a/audio/text_to_speech/project.godot +++ b/audio/text_to_speech/project.godot @@ -21,6 +21,10 @@ config/icon="res://icon.webp" general/text_to_speech=true +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/audio/text_to_speech/voice_list.gd b/audio/text_to_speech/voice_list.gd index 89597ed2..7ddffabc 100644 --- a/audio/text_to_speech/voice_list.gd +++ b/audio/text_to_speech/voice_list.gd @@ -1,127 +1,150 @@ extends Control -var id = 0 #utterance id -var ut_map = {} -var vs +## The utterance ID to use for text to speech. +var id := 0 -func _ready(): - # get voice data +var ut_map := {} +var vs: Array[Dictionary] + +func _ready() -> void: + # Get voice data. vs = DisplayServer.tts_get_voices() - var root = $Tree.create_item() + var root: TreeItem = $Tree.create_item() $Tree.set_hide_root(true) $Tree.set_column_title(0, "Name") $Tree.set_column_title(1, "Language") $Tree.set_column_titles_visible(true) for v in vs: - var child = $Tree.create_item(root) + var child: TreeItem = $Tree.create_item(root) child.set_text(0, v["name"]) child.set_metadata(0, v["id"]) child.set_text(1, v["language"]) - $Log.text += "%d voices available\n" % [vs.size()] + $Log.text += "%d voices available.\n" % [vs.size()] $Log.text += "=======\n" - # add callbacks - DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_STARTED, Callable(self, "_on_utterance_start")) - DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_ENDED, Callable(self, "_on_utterance_end")) - DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_CANCELED, Callable(self, "_on_utterance_error")) - DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_BOUNDARY, Callable(self, "_on_utterance_boundary")) - set_process(true) + # Ensure the first voice added to the list is preselected. + $Tree.get_root().get_child(0).select(0) -func _process(_delta): + # Add callbacks. + DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_STARTED, _on_utterance_start) + DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_ENDED, _on_utterance_end) + DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_CANCELED, _on_utterance_error) + DisplayServer.tts_set_utterance_callback(DisplayServer.TTS_UTTERANCE_BOUNDARY, _on_utterance_boundary) + + +func _process(_delta: float) -> void: $ButtonPause.button_pressed = DisplayServer.tts_is_paused() if DisplayServer.tts_is_speaking(): - $ColorRect.color = Color(1, 0, 0) + $ColorRect.color = Color(0.9, 0.3, 0.1) else: $ColorRect.color = Color(1, 1, 1) -func _on_utterance_boundary(pos, ut_id): + +func _on_utterance_boundary(pos: int, ut_id: int) -> void: $RichTextLabel.text = "[bgcolor=yellow][color=black]" + ut_map[ut_id].substr(0, pos) + "[/color][/bgcolor]" + ut_map[ut_id].substr(pos, -1) -func _on_utterance_start(ut_id): - $Log.text += "utterance %d started\n" % [ut_id] -func _on_utterance_end(ut_id): +func _on_utterance_start(ut_id: int) -> void: + $Log.text += "Utterance %d started.\n" % [ut_id] + + +func _on_utterance_end(ut_id: int) -> void: $RichTextLabel.text = "[bgcolor=yellow][color=black]" + ut_map[ut_id] + "[/color][/bgcolor]" - $Log.text += "utterance %d ended\n" % [ut_id] + $Log.text += "Utterance %d ended.\n" % [ut_id] ut_map.erase(ut_id) -func _on_utterance_error(ut_id): + +func _on_utterance_error(ut_id: int) -> void: $RichTextLabel.text = "" - $Log.text += "utterance %d canceled/failed\n" % [ut_id] + $Log.text += "Utterance %d canceled/failed.\n" % [ut_id] ut_map.erase(ut_id) -func _on_ButtonStop_pressed(): + +func _on_button_stop_pressed() -> void: DisplayServer.tts_stop() -func _on_ButtonPause_pressed(): + +func _on_button_pause_pressed() -> void: if $ButtonPause.pressed: DisplayServer.tts_pause() else: DisplayServer.tts_resume() -func _on_ButtonSpeak_pressed(): + +func _on_button_speak_pressed() -> void: if $Tree.get_selected(): - $Log.text += "utterance %d queried\n" % [id] + $Log.text += "Utterance %d queried.\n" % [id] ut_map[id] = $Utterance.text DisplayServer.tts_speak($Utterance.text, $Tree.get_selected().get_metadata(0), $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id, false) id += 1 else: OS.alert("No voice selected.\nSelect a voice in the list, then try using Speak again.") -func _on_ButtonIntSpeak_pressed(): + +func _on_button_int_speak_pressed() -> void: if $Tree.get_selected(): - $Log.text += "utterance %d interrupt\n" % [id] + $Log.text += "Utterance %d interrupted.\n" % [id] ut_map[id] = $Utterance.text DisplayServer.tts_speak($Utterance.text, $Tree.get_selected().get_metadata(0), $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id, true) id += 1 else: OS.alert("No voice selected.\nSelect a voice in the list, then try using Interrupt again.") -func _on_ButtonClearLog_pressed(): + +func _on_button_clear_log_pressed() -> void: $Log.text = "" -func _on_HSliderRate_value_changed(value): - $HSliderRate/Value.text = "%.2fx" % [value] -func _on_HSliderPitch_value_changed(value): - $HSliderPitch/Value.text = "%.2fx" % [value] +func _on_HSliderRate_value_changed(value: float) -> void: + $HSliderRate/Value.text = "%.2fx" % value -func _on_HSliderVolume_value_changed(value): - $HSliderVolume/Value.text = "%d%%" % [value] -func _on_Button_pressed(): - var vc +func _on_HSliderPitch_value_changed(value: float) -> void: + $HSliderPitch/Value.text = "%.2fx" % value + + +func _on_HSliderVolume_value_changed(value: float) -> void: + $HSliderVolume/Value.text = "%d%%" % value + + +func _on_Button_pressed() -> void: + var vc: PackedStringArray #demo - en vc = DisplayServer.tts_get_voices_for_language("en") - if !vc.is_empty(): + if not vc.is_empty(): ut_map[id] = "Beware the Jabberwock, my son!" ut_map[id + 1] = "The jaws that bite, the claws that catch!" - DisplayServer.tts_speak("Beware the Jabberwock, my son!", vc[0], 50, 1, 1, id) - DisplayServer.tts_speak("The jaws that bite, the claws that catch!", vc[0], 50, 1, 1, id + 1) + DisplayServer.tts_speak("Beware the Jabberwock, my son!", vc[0], $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id) + DisplayServer.tts_speak("The jaws that bite, the claws that catch!", vc[0], $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id + 1) id += 2 #demo - es vc = DisplayServer.tts_get_voices_for_language("es") - if !vc.is_empty(): + if not vc.is_empty(): ut_map[id] = "¡Cuidado, hijo, con el Fablistanón!" ut_map[id + 1] = "¡Con sus dientes y garras, muerde, apresa!" - DisplayServer.tts_speak("¡Cuidado, hijo, con el Fablistanón!", vc[0], 50, 1, 1, id) - DisplayServer.tts_speak("¡Con sus dientes y garras, muerde, apresa!", vc[0], 50, 1, 1, id + 1) + DisplayServer.tts_speak("¡Cuidado, hijo, con el Fablistanón!", vc[0], $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id) + DisplayServer.tts_speak("¡Con sus dientes y garras, muerde, apresa!", vc[0], $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id + 1) id += 2 #demo - ru vc = DisplayServer.tts_get_voices_for_language("ru") - if !vc.is_empty(): + if not vc.is_empty(): ut_map[id] = "О, бойся Бармаглота, сын!" ut_map[id + 1] = "Он так свирлеп и дик!" - DisplayServer.tts_speak("О, бойся Бармаглота, сын!", vc[0], 50, 1, 1, id) - DisplayServer.tts_speak("Он так свирлеп и дик!", vc[0], 50, 1, 1, id + 1) + DisplayServer.tts_speak("О, бойся Бармаглота, сын!", vc[0], $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id) + DisplayServer.tts_speak("Он так свирлеп и дик!", vc[0], $HSliderVolume.value, $HSliderPitch.value, $HSliderRate.value, id + 1) id += 2 -func _on_LineEditFilterName_text_changed(_new_text): + +func _on_LineEditFilterName_text_changed(_new_text: String) -> void: $Tree.clear() - var root = $Tree.create_item() + var root: TreeItem = $Tree.create_item() for v in vs: - if ($LineEditFilterName.text.is_empty() || $LineEditFilterName.text.to_lower() in v["name"].to_lower()) && ($LineEditFilterLang.text.is_empty() || $LineEditFilterLang.text.to_lower() in v["language"].to_lower()): - var child = $Tree.create_item(root) + if ( + $LineEditFilterName.text.is_empty() or $LineEditFilterName.text.to_lower() in v["name"].to_lower() + ) and ( + $LineEditFilterLang.text.is_empty() or $LineEditFilterLang.text.to_lower() in v["language"].to_lower() + ): + var child: TreeItem = $Tree.create_item(root) child.set_text(0, v["name"]) child.set_metadata(0, v["id"]) child.set_text(1, v["language"]) diff --git a/compute/texture/README.md b/compute/texture/README.md index a14f3b50..19f0d3e0 100644 --- a/compute/texture/README.md +++ b/compute/texture/README.md @@ -1,4 +1,4 @@ -# Compute texture +# Compute Texture This demo shows how to use compute shaders to populate a texture that is used as an input for a material shader. diff --git a/compute/texture/main.gd b/compute/texture/main.gd index 62a18057..ac77261f 100644 --- a/compute/texture/main.gd +++ b/compute/texture/main.gd @@ -1,27 +1,26 @@ extends Node3D -# Note, the code here just adds some control to our effects. -# Check res://water_plane/water_plane.gd for the real implementation. +# NOTE: The code here just adds some control to our effects. +# Check `res://water_plane/water_plane.gd` for the real implementation. -var y = 0.0 +var y := 0.0 -@onready var water_plane = $WaterPlane +@onready var water_plane: Area3D = $WaterPlane -func _ready(): +func _ready() -> void: $Container/RainSize/HSlider.value = $WaterPlane.rain_size $Container/MouseSize/HSlider.value = $WaterPlane.mouse_size -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): +func _process(delta: float) -> void: if $Container/Rotate.button_pressed: y += delta water_plane.basis = Basis(Vector3.UP, y) -func _on_rain_size_changed(value): +func _on_rain_size_changed(value: float) -> void: $WaterPlane.rain_size = value -func _on_mouse_size_changed(value): +func _on_mouse_size_changed(value: float) -> void: $WaterPlane.mouse_size = value diff --git a/compute/texture/main.tscn b/compute/texture/main.tscn index b6e3ee67..2d33e65b 100644 --- a/compute/texture/main.tscn +++ b/compute/texture/main.tscn @@ -32,8 +32,10 @@ environment = SubResource("Environment_5dv8s") transform = Transform3D(0.900266, -0.142464, 0.41137, -0.113954, 0.834877, 0.538512, -0.420162, -0.531681, 0.735377, 1.55343, 1.1434, 2.431) [node name="Container" type="VBoxContainer" parent="."] -offset_right = 40.0 -offset_bottom = 40.0 +offset_left = 24.0 +offset_top = 24.0 +offset_right = 364.0 +offset_bottom = 109.0 [node name="Rotate" type="CheckBox" parent="Container"] layout_mode = 2 diff --git a/compute/texture/project.godot b/compute/texture/project.godot index 808ad1b6..b4121a26 100644 --- a/compute/texture/project.godot +++ b/compute/texture/project.godot @@ -10,8 +10,17 @@ config_version=5 [application] -config/name="TestCustomTextures" +config/name="Compute Texture" +config/tags=PackedStringArray("3d", "demo", "official", "rendering") run/main_scene="res://main.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.svg" -config/tags=PackedStringArray("3d", "demo", "official", "rendering") + +[debug] + +gdscript/warnings/untyped_declaration=1 + +[display] + +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" diff --git a/compute/texture/water_plane/water_plane.gd b/compute/texture/water_plane/water_plane.gd index cbab26e8..9bcb925f 100644 --- a/compute/texture/water_plane/water_plane.gd +++ b/compute/texture/water_plane/water_plane.gd @@ -8,38 +8,38 @@ extends Area3D # in Godot and making use of the new Custom Texture RD API added to # the RenderingServer. # -# If thread model is set to Multi-Threaded the code related to compute will +# If thread model is set to Multi-Threaded, the code related to compute will # run on the render thread. This is needed as we want to add our logic to # the normal rendering pipeline for this thread. # # The effect itself is an implementation of the classic ripple effect -# that has been around since the 90ies but in a compute shader. +# that has been around since the 90s, but in a compute shader. # If someone knows if the original author ever published a paper I could # quote, please let me know :) -@export var rain_size : float = 3.0 -@export var mouse_size : float = 5.0 -@export var texture_size : Vector2i = Vector2i(512, 512) -@export_range(1.0, 10.0, 0.1) var damp : float = 1.0 +@export var rain_size: float = 3.0 +@export var mouse_size: float = 5.0 +@export var texture_size: Vector2i = Vector2i(512, 512) +@export_range(1.0, 10.0, 0.1) var damp: float = 1.0 -var t = 0.0 -var max_t = 0.1 +var t := 0.0 +var max_t := 0.1 -var texture : Texture2DRD -var next_texture : int = 0 +var texture: Texture2DRD +var next_texture: int = 0 -var add_wave_point : Vector4 -var mouse_pos : Vector2 -var mouse_pressed : bool = false +var add_wave_point: Vector4 +var mouse_pos: Vector2 +var mouse_pressed: bool = false # Called when the node enters the scene tree for the first time. -func _ready(): +func _ready() -> void: # In case we're running stuff on the rendering thread # we need to do our initialisation on that thread. RenderingServer.call_on_render_thread(_initialize_compute_code.bind(texture_size)) # Get our texture from our material so we set our RID. - var material : ShaderMaterial = $MeshInstance3D.material_override + var material: ShaderMaterial = $MeshInstance3D.material_override if material: material.set_shader_parameter("effect_texture_size", texture_size) @@ -47,7 +47,7 @@ func _ready(): texture = material.get_shader_parameter("effect_texture") -func _exit_tree(): +func _exit_tree() -> void: # Make sure we clean up! if texture: texture.texture_rd_rid = RID() @@ -55,7 +55,7 @@ func _exit_tree(): RenderingServer.call_on_render_thread(_free_compute_resources) -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: # If tool enabled, we don't want to handle our input in the editor. if Engine.is_editor_hint(): return @@ -67,32 +67,32 @@ func _unhandled_input(event): mouse_pressed = event.pressed -func _check_mouse_pos(): +func _check_mouse_pos() -> void: # This is a mouse event, do a raycast. - var camera = get_viewport().get_camera_3d() + var camera := get_viewport().get_camera_3d() - var parameters = PhysicsRayQueryParameters3D.new() + var parameters := PhysicsRayQueryParameters3D.new() parameters.from = camera.project_ray_origin(mouse_pos) parameters.to = parameters.from + camera.project_ray_normal(mouse_pos) * 100.0 parameters.collision_mask = 1 parameters.collide_with_bodies = false parameters.collide_with_areas = true - var result = get_world_3d().direct_space_state.intersect_ray(parameters) - if result.size() > 0: + var result := get_world_3d().direct_space_state.intersect_ray(parameters) + if not result.is_empty(): # Transform our intersection point. - var pos = global_transform.affine_inverse() * result.position + var pos: Vector3 = global_transform.affine_inverse() * result.position add_wave_point.x = clamp(pos.x / 5.0, -0.5, 0.5) * texture_size.x + 0.5 * texture_size.x add_wave_point.y = clamp(pos.z / 5.0, -0.5, 0.5) * texture_size.y + 0.5 * texture_size.y - add_wave_point.w = 1.0 # We have w left over so we use it to indicate mouse is over our water plane. + # We have w left over so we use it to indicate mouse is over our water plane. + add_wave_point.w = 1.0 else: add_wave_point.x = 0.0 add_wave_point.y = 0.0 add_wave_point.w = 0.0 -# Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta): +func _process(delta: float) -> void: # If tool is enabled, ignore mouse input. if Engine.is_editor_hint(): add_wave_point.w = 0.0 @@ -131,19 +131,19 @@ func _process(delta): ############################################################################### # Everything after this point is designed to run on our rendering thread. -var rd : RenderingDevice +var rd: RenderingDevice -var shader : RID -var pipeline : RID +var shader: RID +var pipeline: RID # We use 3 textures: # - One to render into # - One that contains the last frame rendered # - One for the frame before that -var texture_rds : Array = [ RID(), RID(), RID() ] -var texture_sets : Array = [ RID(), RID(), RID() ] +var texture_rds: Array[RID] = [RID(), RID(), RID()] +var texture_sets: Array[RID] = [RID(), RID(), RID()] -func _create_uniform_set(texture_rd : RID) -> RID: +func _create_uniform_set(texture_rd: RID) -> RID: var uniform := RDUniform.new() uniform.uniform_type = RenderingDevice.UNIFORM_TYPE_IMAGE uniform.binding = 0 @@ -152,19 +152,19 @@ func _create_uniform_set(texture_rd : RID) -> RID: return rd.uniform_set_create([uniform], shader, 0) -func _initialize_compute_code(init_with_texture_size): +func _initialize_compute_code(init_with_texture_size: Vector2i) -> void: # As this becomes part of our normal frame rendering, # we use our main rendering device here. rd = RenderingServer.get_rendering_device() # Create our shader. - var shader_file = load("res://water_plane/water_compute.glsl") + var shader_file := load("res://water_plane/water_compute.glsl") var shader_spirv: RDShaderSPIRV = shader_file.get_spirv() shader = rd.shader_create_from_spirv(shader_spirv) pipeline = rd.compute_pipeline_create(shader) # Create our textures to manage our wave. - var tf : RDTextureFormat = RDTextureFormat.new() + var tf: RDTextureFormat = RDTextureFormat.new() tf.format = RenderingDevice.DATA_FORMAT_R32_SFLOAT tf.texture_type = RenderingDevice.TEXTURE_TYPE_2D tf.width = init_with_texture_size.x @@ -172,9 +172,15 @@ func _initialize_compute_code(init_with_texture_size): tf.depth = 1 tf.array_layers = 1 tf.mipmaps = 1 - tf.usage_bits = RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT + RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT + RenderingDevice.TEXTURE_USAGE_STORAGE_BIT + RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT + RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT + tf.usage_bits = ( + RenderingDevice.TEXTURE_USAGE_SAMPLING_BIT | + RenderingDevice.TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | + RenderingDevice.TEXTURE_USAGE_STORAGE_BIT | + RenderingDevice.TEXTURE_USAGE_CAN_UPDATE_BIT | + RenderingDevice.TEXTURE_USAGE_CAN_COPY_TO_BIT + ) - for i in range(3): + for i in 3: # Create our texture. texture_rds[i] = rd.texture_create(tf, RDTextureView.new(), []) @@ -185,10 +191,10 @@ func _initialize_compute_code(init_with_texture_size): texture_sets[i] = _create_uniform_set(texture_rds[i]) -func _render_process(with_next_texture, wave_point, tex_size, damp): +func _render_process(with_next_texture: int, wave_point: Vector4, tex_size: Vector2i, p_damp: float) -> void: # We don't have structures (yet) so we need to build our push constant # "the hard way"... - var push_constant : PackedFloat32Array = PackedFloat32Array() + var push_constant := PackedFloat32Array() push_constant.push_back(wave_point.x) push_constant.push_back(wave_point.y) push_constant.push_back(wave_point.z) @@ -196,7 +202,7 @@ func _render_process(with_next_texture, wave_point, tex_size, damp): push_constant.push_back(tex_size.x) push_constant.push_back(tex_size.y) - push_constant.push_back(damp) + push_constant.push_back(p_damp) push_constant.push_back(0.0) # Calculate our dispatch group size. @@ -204,12 +210,14 @@ func _render_process(with_next_texture, wave_point, tex_size, damp): # divisible by 8. # In combination with a discard check in the shader this ensures # we cover the entire texture. - var x_groups = (tex_size.x - 1) / 8 + 1 - var y_groups = (tex_size.y - 1) / 8 + 1 + @warning_ignore("integer_division") + var x_groups := (tex_size.x - 1) / 8 + 1 + @warning_ignore("integer_division") + var y_groups := (tex_size.y - 1) / 8 + 1 - var next_set = texture_sets[with_next_texture] - var current_set = texture_sets[(with_next_texture - 1) % 3] - var previous_set = texture_sets[(with_next_texture - 2) % 3] + var next_set := texture_sets[with_next_texture] + var current_set := texture_sets[(with_next_texture - 1) % 3] + var previous_set := texture_sets[(with_next_texture - 2) % 3] # Run our compute shader. var compute_list := rd.compute_list_begin() @@ -227,9 +235,9 @@ func _render_process(with_next_texture, wave_point, tex_size, damp): #rd.barrier(RenderingDevice.BARRIER_MASK_COMPUTE) -func _free_compute_resources(): +func _free_compute_resources() -> void: # Note that our sets and pipeline are cleaned up automatically as they are dependencies :P - for i in range(3): + for i in 3: if texture_rds[i]: rd.free_rid(texture_rds[i]) diff --git a/gui/bidi_and_font_features/bidi.gd b/gui/bidi_and_font_features/bidi.gd index ea2f64d4..27ac3104 100644 --- a/gui/bidi_and_font_features/bidi.gd +++ b/gui/bidi_and_font_features/bidi.gd @@ -45,7 +45,7 @@ func _on_variable_size_value_changed(value: float) -> void: func _on_variable_weight_value_changed(value: float) -> void: $"TabContainer/Variable fonts/Variables/Weight/Value".text = str(value) # Workaround to make the variable font axis value effective. This requires duplicating the dictionary. - var dict = variable_font_variation.variation_opentype.duplicate() + var dict := variable_font_variation.variation_opentype.duplicate() dict["weight"] = value variable_font_variation.variation_opentype = dict @@ -53,7 +53,7 @@ func _on_variable_weight_value_changed(value: float) -> void: func _on_variable_slant_value_changed(value: float) -> void: $"TabContainer/Variable fonts/Variables/Slant/Value".text = str(value) # Workaround to make the variable font axis value effective. This requires duplicating the dictionary. - var dict = variable_font_variation.variation_opentype.duplicate() + var dict := variable_font_variation.variation_opentype.duplicate() dict["slant"] = value variable_font_variation.variation_opentype = dict @@ -61,7 +61,7 @@ func _on_variable_slant_value_changed(value: float) -> void: func _on_variable_cursive_toggled(button_pressed: bool) -> void: $"TabContainer/Variable fonts/Variables/Cursive".button_pressed = button_pressed # Workaround to make the variable font axis value effective. This requires duplicating the dictionary. - var dict = variable_font_variation.variation_opentype.duplicate() + var dict := variable_font_variation.variation_opentype.duplicate() dict["custom_CRSV"] = int(button_pressed) variable_font_variation.variation_opentype = dict @@ -69,7 +69,7 @@ func _on_variable_cursive_toggled(button_pressed: bool) -> void: func _on_variable_casual_toggled(button_pressed: bool) -> void: $"TabContainer/Variable fonts/Variables/Casual".button_pressed = button_pressed # Workaround to make the variable font axis value effective. This requires duplicating the dictionary. - var dict = variable_font_variation.variation_opentype.duplicate() + var dict := variable_font_variation.variation_opentype.duplicate() dict["custom_CASL"] = int(button_pressed) variable_font_variation.variation_opentype = dict @@ -77,13 +77,13 @@ func _on_variable_casual_toggled(button_pressed: bool) -> void: func _on_variable_monospace_toggled(button_pressed: bool) -> void: $"TabContainer/Variable fonts/Variables/Monospace".button_pressed = button_pressed # Workaround to make the variable font axis value effective. This requires duplicating the dictionary. - var dict = variable_font_variation.variation_opentype.duplicate() + var dict := variable_font_variation.variation_opentype.duplicate() dict["custom_MONO"] = int(button_pressed) variable_font_variation.variation_opentype = dict func _on_system_font_value_text_changed(new_text: String) -> void: - for label in [ + for label: Label in [ $"TabContainer/System fonts/VBoxContainer/SansSerif/Value", $"TabContainer/System fonts/VBoxContainer/Serif/Value", $"TabContainer/System fonts/VBoxContainer/Monospace/Value", @@ -96,7 +96,7 @@ func _on_system_font_value_text_changed(new_text: String) -> void: func _on_system_font_weight_value_changed(value: float) -> void: $"TabContainer/System fonts/Weight/Value".text = str(value) - for label in [ + for label: Label in [ $"TabContainer/System fonts/VBoxContainer/SansSerif/Value", $"TabContainer/System fonts/VBoxContainer/Serif/Value", $"TabContainer/System fonts/VBoxContainer/Monospace/Value", @@ -105,10 +105,10 @@ func _on_system_font_weight_value_changed(value: float) -> void: $"TabContainer/System fonts/VBoxContainer/Custom/Value" ]: var system_font: SystemFont = label.get_theme_font("font") - system_font.font_weight = value + system_font.font_weight = int(value) func _on_system_font_italic_toggled(button_pressed: bool) -> void: - for label in [ + for label: Label in [ $"TabContainer/System fonts/VBoxContainer/SansSerif/Value", $"TabContainer/System fonts/VBoxContainer/Serif/Value", $"TabContainer/System fonts/VBoxContainer/Monospace/Value", diff --git a/gui/bidi_and_font_features/custom_st_parser.gd b/gui/bidi_and_font_features/custom_st_parser.gd index 6e0fd034..d4eb592b 100644 --- a/gui/bidi_and_font_features/custom_st_parser.gd +++ b/gui/bidi_and_font_features/custom_st_parser.gd @@ -1,15 +1,17 @@ extends LineEdit -func _structured_text_parser(args, p_text): - var output = [] - var tags = p_text.split(":") - var prev = 0 - var count = int(tags.size()) +func _structured_text_parser(_args: Variant, p_text: String) -> Array: + var output: Array[Vector3i] = [] + var tags := p_text.split(":") + var prev := 0 + var count := tags.size() output.clear() - for i in range(count): - var range1 = Vector3i(prev, prev + tags[i].length(), TextServer.DIRECTION_AUTO) - var range2 = Vector3i(prev + tags[i].length(), prev + tags[i].length() + 1, TextServer.DIRECTION_AUTO) + + for i in count: + var range1 := Vector3i(prev, prev + tags[i].length(), TextServer.DIRECTION_AUTO) + var range2 := Vector3i(prev + tags[i].length(), prev + tags[i].length() + 1, TextServer.DIRECTION_AUTO) output.push_front(range1) output.push_front(range2) prev = prev + tags[i].length() + 1 + return output diff --git a/gui/bidi_and_font_features/project.godot b/gui/bidi_and_font_features/project.godot index 99a57ea6..3df645a2 100644 --- a/gui/bidi_and_font_features/project.godot +++ b/gui/bidi_and_font_features/project.godot @@ -17,6 +17,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/control_gallery/project.godot b/gui/control_gallery/project.godot index 5c682c3a..a6a944c4 100644 --- a/gui/control_gallery/project.godot +++ b/gui/control_gallery/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/drag_and_drop/drag_drop_script.gd b/gui/drag_and_drop/drag_drop_script.gd index 9865746b..2b057b30 100644 --- a/gui/drag_and_drop/drag_drop_script.gd +++ b/gui/drag_and_drop/drag_drop_script.gd @@ -1,20 +1,20 @@ extends ColorPickerButton # Returns the data to pass from an object when you click and drag away from -# this object. Also calls set_drag_preview() to show the mouse dragging +# this object. Also calls `set_drag_preview()` to show the mouse dragging # something so the user knows that the operation is working. -func _get_drag_data(_pos): +func _get_drag_data(_at_position: Vector2) -> Color: # Use another colorpicker as drag preview. - var cpb = ColorPickerButton.new() + var cpb := ColorPickerButton.new() cpb.color = color cpb.size = Vector2(80.0, 50.0) - # Allows us to center the color picker on the mouse - var preview = Control.new() + # Allows us to center the color picker on the mouse. + var preview := Control.new() preview.add_child(cpb) cpb.position = -0.5 * cpb.size - # Sets what the user will see they are dragging + # Sets what the user will see they are dragging. set_drag_preview(preview) # Return color as drag data. @@ -23,10 +23,11 @@ func _get_drag_data(_pos): # Returns a boolean by examining the data being dragged to see if it's valid # to drop here. -func _can_drop_data(_pos, data): +func _can_drop_data(_at_position: Vector2, data: Variant) -> bool: return typeof(data) == TYPE_COLOR + # Takes the data being dragged and processes it. In this case, we are # assigning a new color to the target color picker button. -func _drop_data(_pos, data): +func _drop_data(_at_position: Vector2, data: Variant) -> void: color = data diff --git a/gui/drag_and_drop/project.godot b/gui/drag_and_drop/project.godot index 8c72e080..bc9d1f2e 100644 --- a/gui/drag_and_drop/project.godot +++ b/gui/drag_and_drop/project.godot @@ -21,6 +21,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/gd_paint/paint_control.gd b/gui/gd_paint/paint_control.gd index 7bf7d79b..d6c25658 100644 --- a/gui/gd_paint/paint_control.gd +++ b/gui/gd_paint/paint_control.gd @@ -1,53 +1,52 @@ extends Control -# A constant for whether or not we're needing to undo a shape. -const UNDO_MODE_SHAPE = -2 -# A constant for whether or not we can undo. -const UNDO_NONE = -1 - # Enums for the various modes and brush shapes that can be applied. -enum BrushModes { +enum BrushMode { PENCIL, ERASER, CIRCLE_SHAPE, RECTANGLE_SHAPE, } -enum BrushShapes { +enum BrushShape { RECTANGLE, CIRCLE, } +# A constant for whether or not we're needing to undo a shape. +const UNDO_MODE_SHAPE = -2 +# A constant for whether or not we can undo. +const UNDO_NONE = -1 + # A list to hold all of the dictionaries that make up each brush. -var brush_data_list = [] +var brush_data_list: Array[Dictionary] = [] # A boolean to hold whether or not the mouse is inside the drawing area, the mouse position last _process call # and the position of the mouse when the left mouse button was pressed. -var is_mouse_in_drawing_area = false -var last_mouse_pos = Vector2() -var mouse_click_start_pos = null +var is_mouse_in_drawing_area := false +var last_mouse_pos := Vector2() +var mouse_click_start_pos := Vector2.INF # A boolean to tell whether we've set undo_elements_list_num, which holds the size of draw_elements_list # before a new stroke is added (unless the current brush mode is 'rectangle shape' or 'circle shape', in # which case we do things a litte differently. See the undo_stroke function for more details). -var undo_set = false -var undo_element_list_num = -1 +var undo_set := false +var undo_element_list_num := -1 # The current brush settings: The mode, size, color, and shape we have currently selected. -var brush_mode = BrushModes.PENCIL -var brush_size = 32 -var brush_color = Color.BLACK -var brush_shape = BrushShapes.CIRCLE; +var brush_mode := BrushMode.PENCIL +var brush_size := 32 +var brush_color := Color.BLACK +var brush_shape := BrushShape.CIRCLE # The color of the background. We need this for the eraser (see the how we handle the eraser # in the _draw function for more details). -var bg_color = Color.WHITE +var bg_color := Color.WHITE -@onready var drawing_area = $"../DrawingAreaBG" +@onready var drawing_area: Panel = $"../DrawingAreaBG" - -func _process(_delta): - var mouse_pos = get_viewport().get_mouse_position() +func _process(_delta: float) -> void: + var mouse_pos := get_viewport().get_mouse_position() # Check if the mouse is currently inside the canvas/drawing-area. var drawing_area_rect := Rect2(drawing_area.position, drawing_area.size) @@ -57,14 +56,14 @@ func _process(_delta): # If we do not have a position for when the mouse was first clicked, then this must # be the first time is_mouse_button_pressed has been called since the mouse button was # released, so we need to store the position. - if mouse_click_start_pos == null: + if mouse_click_start_pos.is_equal_approx(Vector2.INF): mouse_click_start_pos = mouse_pos # If the mouse is inside the canvas and the mouse is 1px away from the position of the mouse last _process call. if check_if_mouse_is_inside_canvas(): if mouse_pos.distance_to(last_mouse_pos) >= 1: # If we are in pencil or eraser mode, then we need to draw. - if brush_mode == BrushModes.PENCIL or brush_mode == BrushModes.ERASER: + if brush_mode == BrushMode.PENCIL or brush_mode == BrushMode.ERASER: # If undo has not been set, meaning we've started a new stroke, then store the size of the # draw_elements_list so we can undo from this point in time. if undo_set == false: @@ -81,20 +80,20 @@ func _process(_delta): if check_if_mouse_is_inside_canvas(): # If we're using either the circle shape mode, or the rectangle shape mode, then # add the brush object to draw_elements_array. - if brush_mode == BrushModes.CIRCLE_SHAPE or brush_mode == BrushModes.RECTANGLE_SHAPE: + if brush_mode == BrushMode.CIRCLE_SHAPE or brush_mode == BrushMode.RECTANGLE_SHAPE: add_brush(mouse_pos, brush_mode) # We handle undo's differently than either pencil or eraser mode, so we need to set undo # element_list_num to -2 so we can tell if we need to undo a shape. See undo_stroke for details. undo_element_list_num = UNDO_MODE_SHAPE # Since we've released the left mouse, we need to get a new mouse_click_start_pos next time - #is_mouse_button_pressed is true. - mouse_click_start_pos = null + # is_mouse_button_pressed is true. + mouse_click_start_pos = Vector2.INF # Store mouse_pos as last_mouse_pos now that we're done with _process. last_mouse_pos = mouse_pos -func check_if_mouse_is_inside_canvas(): +func check_if_mouse_is_inside_canvas() -> bool: # Make sure we have a mouse click starting position. if mouse_click_start_pos != null: # Make sure the mouse click starting position is inside the canvas. @@ -107,7 +106,7 @@ func check_if_mouse_is_inside_canvas(): return false -func undo_stroke(): +func undo_stroke() -> void: # Only undo a stroke if we have one. if undo_element_list_num == UNDO_NONE: return @@ -125,22 +124,22 @@ func undo_stroke(): # Otherwise we're removing a either a pencil stroke or a eraser stroke. else: # Figure out how many elements/brushes we've added in the last stroke. - var elements_to_remove = brush_data_list.size() - undo_element_list_num + var elements_to_remove := brush_data_list.size() - undo_element_list_num # Remove all of the elements we've added this in the last stroke. #warning-ignore:unused_variable - for elment_num in range(0, elements_to_remove): + for elment_num in elements_to_remove: brush_data_list.pop_back() # Now that we've undone a stoke, we cannot undo again until another stoke is added. undo_element_list_num = UNDO_NONE - # Redraw the brushes + # Redraw the brushes. queue_redraw() -func add_brush(mouse_pos, type): +func add_brush(mouse_pos: Vector2, type: BrushMode) -> void: # Make new brush dictionary that will hold all of the data we need for the brush. - var new_brush = {} + var new_brush := {} # Populate the dictionary with values based on the global brush variables. # We will override these as needed if the brush is a rectange or circle. @@ -152,9 +151,9 @@ func add_brush(mouse_pos, type): # If the new bursh is a rectangle shape, we need to calculate the top left corner of the rectangle and the # bottom right corner of the rectangle. - if type == BrushModes.RECTANGLE_SHAPE: - var TL_pos = Vector2() - var BR_pos = Vector2() + if type == BrushMode.RECTANGLE_SHAPE: + var TL_pos := Vector2() + var BR_pos := Vector2() # Figure out the left and right positions of the corners and assign them to the proper variable. if mouse_pos.x < mouse_click_start_pos.x: @@ -177,9 +176,9 @@ func add_brush(mouse_pos, type): new_brush.brush_shape_rect_pos_BR = BR_pos # If the brush isa circle shape, then we need to calculate the radius of the circle. - if type == BrushModes.CIRCLE_SHAPE: + if type == BrushMode.CIRCLE_SHAPE: # Get the center point inbetween the mouse position and the position of the mouse when we clicked. - var center_pos = Vector2((mouse_pos.x + mouse_click_start_pos.x) / 2, (mouse_pos.y + mouse_click_start_pos.y) / 2) + var center_pos := Vector2((mouse_pos.x + mouse_click_start_pos.x) / 2, (mouse_pos.y + mouse_click_start_pos.y) / 2) # Assign the brush position to the center point, and calculate the radius of the circle using the distance from # the center to the top/bottom positon of the mouse. new_brush.brush_pos = center_pos @@ -190,50 +189,56 @@ func add_brush(mouse_pos, type): queue_redraw() -func _draw(): - # Go through all of the brushes in brush_data_list. +func _draw() -> void: for brush in brush_data_list: match brush.brush_type: - BrushModes.PENCIL: + BrushMode.PENCIL: # If the brush shape is a rectangle, then we need to make a Rect2 so we can use draw_rect. # Draw_rect draws a rectagle at the top left corner, using the scale for the size. # So we offset the position by half of the brush size so the rectangle's center is at mouse position. - if brush.brush_shape == BrushShapes.RECTANGLE: - var rect = Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) + if brush.brush_shape == BrushShape.RECTANGLE: + var rect := Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) draw_rect(rect, brush.brush_color) # If the brush shape is a circle, then we draw a circle at the mouse position, # making the radius half of brush size (so the circle is brush size pixels in diameter). - elif brush.brush_shape == BrushShapes.CIRCLE: + elif brush.brush_shape == BrushShape.CIRCLE: draw_circle(brush.brush_pos, brush.brush_size / 2, brush.brush_color) - BrushModes.ERASER: + BrushMode.ERASER: # NOTE: this is a really cheap way of erasing that isn't really erasing! # However, this gives similar results in a fairy simple way! # Erasing works exactly the same was as pencil does for both the rectangle shape and the circle shape, # but instead of using brush.brush_color, we instead use bg_color instead. - if brush.brush_shape == BrushShapes.RECTANGLE: - var rect = Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) + if brush.brush_shape == BrushShape.RECTANGLE: + var rect := Rect2(brush.brush_pos - Vector2(brush.brush_size / 2, brush.brush_size / 2), Vector2(brush.brush_size, brush.brush_size)) draw_rect(rect, bg_color) - elif brush.brush_shape == BrushShapes.CIRCLE: + elif brush.brush_shape == BrushShape.CIRCLE: draw_circle(brush.brush_pos, brush.brush_size / 2, bg_color) - BrushModes.RECTANGLE_SHAPE: + BrushMode.RECTANGLE_SHAPE: # We make a Rect2 with the postion at the top left. To get the size we take the bottom right position # and subtract the top left corner's position. - var rect = Rect2(brush.brush_pos, brush.brush_shape_rect_pos_BR - brush.brush_pos) + var rect := Rect2(brush.brush_pos, brush.brush_shape_rect_pos_BR - brush.brush_pos) draw_rect(rect, brush.brush_color) - BrushModes.CIRCLE_SHAPE: + BrushMode.CIRCLE_SHAPE: # We simply draw a circle using stored in brush. draw_circle(brush.brush_pos, brush.brush_shape_circle_radius, brush.brush_color) -func save_picture(path): +func save_picture(path: String) -> void: # Wait until the frame has finished before getting the texture. await RenderingServer.frame_post_draw - # Get the viewport image. - var img = get_viewport().get_texture().get_image() + var img := get_viewport().get_texture().get_image() # Crop the image so we only have canvas area. - var cropped_image = img.get_region(Rect2(drawing_area.position, drawing_area.size)) + var cropped_image := img.get_region(Rect2(drawing_area.position, drawing_area.size)) # Save the image with the passed in path we got from the save dialog. - cropped_image.save_png(path) + # File format is based on the extension given by the user in the save dialog. + if path.to_lower().ends_with(".png"): + cropped_image.save_png(path) + elif path.to_lower().ends_with(".webp"): + # `save_webp()` is lossless by default. + cropped_image.save_webp(path) + elif path.to_lower().ends_with(".jpg") or path.to_lower().ends_with(".jpeg"): + # JPEG is always a lossy format, so use the highest possible quality. + cropped_image.save_jpg(path, 1.0) diff --git a/gui/gd_paint/paint_root.tscn b/gui/gd_paint/paint_root.tscn index ec79f965..b31b04d4 100644 --- a/gui/gd_paint/paint_root.tscn +++ b/gui/gd_paint/paint_root.tscn @@ -335,5 +335,5 @@ metadata/_edit_use_custom_anchors = false size = Vector2i(800, 300) min_size = Vector2i(800, 300) access = 2 -filters = PackedStringArray("*.png") +filters = PackedStringArray("*.png ; PNG Image", "*.webp ; WebP Image", "*.jpeg, *.jpg ; JPEG Image") show_hidden_files = true diff --git a/gui/gd_paint/project.godot b/gui/gd_paint/project.godot index fc924717..228b520b 100644 --- a/gui/gd_paint/project.godot +++ b/gui/gd_paint/project.godot @@ -21,6 +21,7 @@ config/icon="res://icon.webp" [debug] +gdscript/warnings/untyped_declaration=1 gdscript/warnings/redundant_await=false [display] diff --git a/gui/gd_paint/tools_panel.gd b/gui/gd_paint/tools_panel.gd index ea6d526e..f58874ae 100644 --- a/gui/gd_paint/tools_panel.gd +++ b/gui/gd_paint/tools_panel.gd @@ -1,17 +1,17 @@ extends Panel -@onready var brush_settings = $BrushSettings -@onready var label_brush_size = brush_settings.get_node(^"LabelBrushSize") -@onready var label_brush_shape = brush_settings.get_node(^"LabelBrushShape") -@onready var label_stats = $LabelStats -@onready var label_tools = $LabelTools +@onready var brush_settings: Control = $BrushSettings +@onready var label_brush_size: Label = brush_settings.get_node(^"LabelBrushSize") +@onready var label_brush_shape: Label = brush_settings.get_node(^"LabelBrushShape") +@onready var label_stats: Label = $LabelStats +@onready var label_tools: Label = $LabelTools -@onready var _parent = get_parent() -@onready var save_dialog = _parent.get_node(^"SaveFileDialog") -@onready var paint_control = _parent.get_node(^"PaintControl") +@onready var _parent: Control = get_parent() +@onready var save_dialog: FileDialog = _parent.get_node(^"SaveFileDialog") +@onready var paint_control: Control = _parent.get_node(^"PaintControl") -func _ready(): - # Assign all of the needed signals for the oppersation buttons. +func _ready() -> void: + # Assign all of the needed signals for the option buttons. $ButtonUndo.pressed.connect(button_pressed.bind("undo_stroke")) $ButtonSave.pressed.connect(button_pressed.bind("save_picture")) $ButtonClear.pressed.connect(button_pressed.bind("clear_picture")) @@ -32,48 +32,45 @@ func _ready(): # Assign the "file_selected" signal in SaveFileDialog. save_dialog.file_selected.connect(save_file_selected) - # Set physics process so we can update the status label. - set_physics_process(true) - -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: # Update the status label with the newest brush element count. - label_stats.text = "Brush objects: " + str(paint_control.brush_data_list.size()) + label_stats.text = "Brush objects: %d" % paint_control.brush_data_list.size() -func button_pressed(button_name): +func button_pressed(button_name: String) -> void: # If a brush mode button is pressed. - var tool_name = null - var shape_name = null + var tool_name := "" + var shape_name := "" if button_name == "mode_pencil": - paint_control.brush_mode = paint_control.BrushModes.PENCIL - brush_settings.modulate = Color(1, 1, 1, 1) + paint_control.brush_mode = paint_control.BrushMode.PENCIL + brush_settings.modulate = Color(1, 1, 1) tool_name = "Pencil" elif button_name == "mode_eraser": - paint_control.brush_mode = paint_control.BrushModes.ERASER - brush_settings.modulate = Color(1, 1, 1, 1) + paint_control.brush_mode = paint_control.BrushMode.ERASER + brush_settings.modulate = Color(1, 1, 1) tool_name = "Eraser" elif button_name == "mode_rectangle": - paint_control.brush_mode = paint_control.BrushModes.RECTANGLE_SHAPE + paint_control.brush_mode = paint_control.BrushMode.RECTANGLE_SHAPE brush_settings.modulate = Color(1, 1, 1, 0.5) tool_name = "Rectangle shape" elif button_name == "mode_circle": - paint_control.brush_mode = paint_control.BrushModes.CIRCLE_SHAPE + paint_control.brush_mode = paint_control.BrushMode.CIRCLE_SHAPE brush_settings.modulate = Color(1, 1, 1, 0.5) tool_name = "Circle shape" # If a brush shape button is pressed elif button_name == "shape_rectangle": - paint_control.brush_shape = paint_control.BrushShapes.RECTANGLE + paint_control.brush_shape = paint_control.BrushShape.RECTANGLE shape_name = "Rectangle" elif button_name == "shape_circle": - paint_control.brush_shape = paint_control.BrushShapes.CIRCLE - shape_name = "Circle"; + paint_control.brush_shape = paint_control.BrushShape.CIRCLE + shape_name = "Circle" # If a opperation button is pressed elif button_name == "clear_picture": - paint_control.brush_data_list = [] + paint_control.brush_data_list.clear() paint_control.queue_redraw() elif button_name == "save_picture": save_dialog.popup_centered() @@ -81,18 +78,18 @@ func button_pressed(button_name): paint_control.undo_stroke() # Update the labels (in case the brush mode or brush shape has changed). - if tool_name != null: - label_tools.text = "Selected tool: " + tool_name - if shape_name != null: - label_brush_shape.text = "Brush shape: " + shape_name + if not tool_name.is_empty(): + label_tools.text = "Selected tool: %s" % tool_name + if not shape_name.is_empty(): + label_brush_shape.text = "Brush shape: %s" % shape_name -func brush_color_changed(color): +func brush_color_changed(color: Color) -> void: # Change the brush color to whatever color the color picker is. paint_control.brush_color = color -func background_color_changed(color): +func background_color_changed(color: Color) -> void: # Change the background color to whatever colorthe background color picker is. get_parent().get_node(^"DrawingAreaBG").modulate = color paint_control.bg_color = color @@ -100,12 +97,12 @@ func background_color_changed(color): paint_control.queue_redraw() -func brush_size_changed(value): +func brush_size_changed(value: float) -> void: # Change the size of the brush, and update the label to reflect the new value. - paint_control.brush_size = ceil(value) + paint_control.brush_size = ceilf(value) label_brush_size.text = "Brush size: " + str(ceil(value)) + "px" -func save_file_selected(path): +func save_file_selected(path: String) -> void: # Call save_picture in paint_control, passing in the path we recieved from SaveFileDialog. paint_control.save_picture(path) diff --git a/gui/input_mapping/ActionRemapButton.gd b/gui/input_mapping/ActionRemapButton.gd index 83890dd0..e8fb7124 100644 --- a/gui/input_mapping/ActionRemapButton.gd +++ b/gui/input_mapping/ActionRemapButton.gd @@ -1,39 +1,48 @@ extends Button -@export var action: String = "ui_up" +@export var action := "ui_up" -func _ready(): +func _ready() -> void: assert(InputMap.has_action(action)) set_process_unhandled_key_input(false) display_current_key() -func _toggled(is_button_pressed): +func _toggled(is_button_pressed: bool) -> void: set_process_unhandled_key_input(is_button_pressed) if is_button_pressed: text = "" + modulate = Color.YELLOW release_focus() else: display_current_key() + modulate = Color.WHITE + # Grab focus after assigning a key, so that you can go to the next + # key using the keyboard. + grab_focus() -func _unhandled_key_input(event): - # Note that you can use the _input callback instead, especially if - # you want to work with gamepads. - remap_action_to(event) - button_pressed = false +# NOTE: You can use the `_input()` callback instead, especially if +# you want to work with gamepads. +func _unhandled_key_input(event: InputEvent) -> void: + # Skip if pressing Enter, so that the input mapping GUI can be navigated + # with the keyboard. The downside of this approach is that the Enter + # key can't be bound to actions. + if event is InputEventKey and event.keycode != KEY_ENTER: + remap_action_to(event) + button_pressed = false -func remap_action_to(event): +func remap_action_to(event: InputEvent) -> void: # We first change the event in this game instance. InputMap.action_erase_events(action) InputMap.action_add_event(action, event) - # And then save it to the keymaps file + # And then save it to the keymaps file. KeyPersistence.keymaps[action] = event KeyPersistence.save_keymap() text = event.as_text() -func display_current_key(): - var current_key = InputMap.action_get_events(action)[0].as_text() +func display_current_key() -> void: + var current_key := InputMap.action_get_events(action)[0].as_text() text = current_key diff --git a/gui/input_mapping/KeyPersistence.gd b/gui/input_mapping/KeyPersistence.gd index 355d04e3..45b79ad1 100644 --- a/gui/input_mapping/KeyPersistence.gd +++ b/gui/input_mapping/KeyPersistence.gd @@ -2,7 +2,7 @@ # the key maps in a simple way through a dictionary. extends Node -const keymaps_path = "user://keymaps.dat" +const keymaps_path := "user://keymaps.dat" var keymaps: Dictionary @@ -10,27 +10,30 @@ func _ready() -> void: # First we create the keymap dictionary on startup with all # the keymap actions we have. for action in InputMap.get_actions(): - if InputMap.action_get_events(action).size() != 0: + if not InputMap.action_get_events(action).is_empty(): keymaps[action] = InputMap.action_get_events(action)[0] + load_keymap() func load_keymap() -> void: if not FileAccess.file_exists(keymaps_path): - save_keymap() # There is no save file yet, so let's create one. + # There is no save file yet, so let's create one. + save_keymap() return - var file = FileAccess.open(keymaps_path, FileAccess.READ) - var temp_keymap = file.get_var(true) as Dictionary + + var file := FileAccess.open(keymaps_path, FileAccess.READ) + var temp_keymap: Dictionary = file.get_var(true) file.close() # We don't just replace the keymaps dictionary, because if you # updated your game and removed/added keymaps, the data of this # save file may have invalid actions. So we check one by one to # make sure that the keymap dictionary really has all current actions. - for action in keymaps.keys(): + for action: StringName in keymaps.keys(): if temp_keymap.has(action): keymaps[action] = temp_keymap[action] # Whilst setting the keymap dictionary, we also set the - # correct InputMap event + # correct InputMap event. InputMap.action_erase_events(action) InputMap.action_add_event(action, keymaps[action]) diff --git a/gui/input_mapping/project.godot b/gui/input_mapping/project.godot index b3b0b9de..a98c661b 100644 --- a/gui/input_mapping/project.godot +++ b/gui/input_mapping/project.godot @@ -25,6 +25,10 @@ config/icon="res://icon.webp" KeyPersistence="*res://KeyPersistence.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=640 diff --git a/gui/msdf_font/project.godot b/gui/msdf_font/project.godot index 0f15d581..72ce2ef4 100644 --- a/gui/msdf_font/project.godot +++ b/gui/msdf_font/project.godot @@ -22,6 +22,10 @@ run/main_scene="res://sdf_font_demo.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/msdf_font/sdf_font_demo.gd b/gui/msdf_font/sdf_font_demo.gd index 3da88d46..10c48f31 100644 --- a/gui/msdf_font/sdf_font_demo.gd +++ b/gui/msdf_font/sdf_font_demo.gd @@ -1,9 +1,7 @@ extends Control - - -func _input(event): - if event.is_action_pressed("toggle_msdf_font"): +func _input(event: InputEvent) -> void: + if event.is_action_pressed(&"toggle_msdf_font"): if %FontLabel.get_theme_font("font").multichannel_signed_distance_field: %FontLabel.add_theme_font_override("font", preload("res://montserrat_semibold.ttf")) else: @@ -12,10 +10,12 @@ func _input(event): update_label() -func update_label(): - %FontMode.text = "Font rendering: %s" % ("MSDF" if %FontLabel.get_theme_font("font").multichannel_signed_distance_field else "Traditional") +func update_label() -> void: + %FontMode.text = "Font rendering: %s" % ( + "MSDF" if %FontLabel.get_theme_font("font").multichannel_signed_distance_field else "Traditional" + ) -func _on_outline_size_value_changed(value): +func _on_outline_size_value_changed(value: float) -> void: %FontLabel.add_theme_constant_override("outline_size", int(value)) %Value.text = str(value) diff --git a/gui/multiple_resolutions/main.gd b/gui/multiple_resolutions/main.gd index 47a90fb0..5d633f93 100644 --- a/gui/multiple_resolutions/main.gd +++ b/gui/multiple_resolutions/main.gd @@ -4,25 +4,24 @@ # (with their rect spread across the whole viewport, and Anchor set to Full Rect). extends Control -var base_window_size = Vector2( +var base_window_size := Vector2( ProjectSettings.get_setting("display/window/size/viewport_width"), ProjectSettings.get_setting("display/window/size/viewport_height") ) # These defaults match this demo's project settings. Adjust as needed if adapting this # in your own project. -var stretch_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS -var stretch_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND +var stretch_mode := Window.CONTENT_SCALE_MODE_CANVAS_ITEMS +var stretch_aspect := Window.CONTENT_SCALE_ASPECT_EXPAND -var scale_factor = 1.0 -var gui_aspect_ratio = -1.0 -var gui_margin = 0.0 +var scale_factor := 1.0 +var gui_aspect_ratio := -1.0 +var gui_margin := 0.0 -@onready var panel = $Panel -@onready var arc = $Panel/AspectRatioContainer +@onready var panel: Panel = $Panel +@onready var arc: AspectRatioContainer = $Panel/AspectRatioContainer - -func _ready(): +func _ready() -> void: # The `resized` signal will be emitted when the window size changes, as the root Control node # is resized whenever the window size changes. This is because the root Control node # uses a Full Rect anchor, so its size will always be equal to the window size. @@ -30,7 +29,7 @@ func _ready(): update_container.call_deferred() -func update_container(): +func update_container() -> void: # The code within this function needs to be run deferred to work around an issue with containers # having a 1-frame delay with updates. # Otherwise, `panel.size` returns a value of the previous frame, which results in incorrect @@ -58,7 +57,7 @@ func update_container(): panel.offset_right = -gui_margin -func _on_gui_aspect_ratio_item_selected(index): +func _on_gui_aspect_ratio_item_selected(index: int) -> void: match index: 0: # Fit to Window gui_aspect_ratio = -1.0 @@ -78,17 +77,17 @@ func _on_gui_aspect_ratio_item_selected(index): update_container.call_deferred() -func _on_resized(): +func _on_resized() -> void: update_container.call_deferred() -func _on_gui_margin_drag_ended(_value_changed): +func _on_gui_margin_drag_ended(_value_changed: bool) -> void: gui_margin = $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/GUIMargin/HSlider".value $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/GUIMargin/Value".text = str(gui_margin) update_container.call_deferred() -func _on_window_base_size_item_selected(index): +func _on_window_base_size_item_selected(index: int) -> void: match index: 0: # 648×648 (1:1) base_window_size = Vector2(648, 648) @@ -111,8 +110,8 @@ func _on_window_base_size_item_selected(index): update_container.call_deferred() -func _on_window_stretch_mode_item_selected(index): - stretch_mode = index +func _on_window_stretch_mode_item_selected(index: int) -> void: + stretch_mode = index as Window.ContentScaleMode get_viewport().content_scale_mode = stretch_mode # Disable irrelevant options when the stretch mode is Disabled. @@ -120,12 +119,12 @@ func _on_window_stretch_mode_item_selected(index): $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowStretchAspect/OptionButton".disabled = stretch_mode == Window.CONTENT_SCALE_MODE_DISABLED -func _on_window_stretch_aspect_item_selected(index): - stretch_aspect = index +func _on_window_stretch_aspect_item_selected(index: int) -> void: + stretch_aspect = index as Window.ContentScaleAspect get_viewport().content_scale_aspect = stretch_aspect -func _on_window_scale_factor_drag_ended(_value_changed): +func _on_window_scale_factor_drag_ended(_value_changed: bool) -> void: scale_factor = $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowScaleFactor/HSlider".value $"Panel/AspectRatioContainer/Panel/CenterContainer/Options/WindowScaleFactor/Value".text = "%d%%" % (scale_factor * 100) get_viewport().content_scale_factor = scale_factor diff --git a/gui/multiple_resolutions/project.godot b/gui/multiple_resolutions/project.godot index 685fba7f..e836cca7 100644 --- a/gui/multiple_resolutions/project.godot +++ b/gui/multiple_resolutions/project.godot @@ -33,6 +33,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=648 diff --git a/gui/pseudolocalization/Pseudolocalization.gd b/gui/pseudolocalization/Pseudolocalization.gd index c53aa9b2..60564dc8 100644 --- a/gui/pseudolocalization/Pseudolocalization.gd +++ b/gui/pseudolocalization/Pseudolocalization.gd @@ -1,67 +1,60 @@ extends Control -func _ready(): - $Main/Pseudolocalization_options/accents.button_pressed = ProjectSettings.get("internationalization/pseudolocalization/replace_with_accents") +func _ready() -> void: + $Main/Pseudolocalization_options/accents.button_pressed = ProjectSettings.get_setting("internationalization/pseudolocalization/replace_with_accents") $Main/Pseudolocalization_options/toggle.button_pressed = TranslationServer.pseudolocalization_enabled - $Main/Pseudolocalization_options/fakebidi.button_pressed = ProjectSettings.get("internationalization/pseudolocalization/fake_bidi") - $Main/Pseudolocalization_options/doublevowels.button_pressed = ProjectSettings.get("internationalization/pseudolocalization/double_vowels") - $Main/Pseudolocalization_options/override.button_pressed = ProjectSettings.get("internationalization/pseudolocalization/override") - $Main/Pseudolocalization_options/skipplaceholders.button_pressed = ProjectSettings.get("internationalization/pseudolocalization/skip_placeholders") - $Main/Pseudolocalization_options/prefix/TextEdit.text = ProjectSettings.get("internationalization/pseudolocalization/prefix") - $Main/Pseudolocalization_options/suffix/TextEdit.text = ProjectSettings.get("internationalization/pseudolocalization/suffix") - $Main/Pseudolocalization_options/exp_ratio/TextEdit.text = str(ProjectSettings.get("internationalization/pseudolocalization/expansion_ratio")) + $Main/Pseudolocalization_options/fakebidi.button_pressed = ProjectSettings.get_setting("internationalization/pseudolocalization/fake_bidi") + $Main/Pseudolocalization_options/doublevowels.button_pressed = ProjectSettings.get_setting("internationalization/pseudolocalization/double_vowels") + $Main/Pseudolocalization_options/override.button_pressed = ProjectSettings.get_setting("internationalization/pseudolocalization/override") + $Main/Pseudolocalization_options/skipplaceholders.button_pressed = ProjectSettings.get_setting("internationalization/pseudolocalization/skip_placeholders") + $Main/Pseudolocalization_options/prefix/TextEdit.text = ProjectSettings.get_setting("internationalization/pseudolocalization/prefix") + $Main/Pseudolocalization_options/suffix/TextEdit.text = ProjectSettings.get_setting("internationalization/pseudolocalization/suffix") + $Main/Pseudolocalization_options/exp_ratio/SpinBox.value = float(ProjectSettings.get_setting("internationalization/pseudolocalization/expansion_ratio")) -func _on_accents_toggled(button_pressed): - ProjectSettings.set("internationalization/pseudolocalization/replace_with_accents", button_pressed) +func _on_accents_toggled(button_pressed: bool) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/replace_with_accents", button_pressed) TranslationServer.reload_pseudolocalization() -func _on_toggle_toggled(button_pressed): +func _on_toggle_toggled(button_pressed: bool) -> void: TranslationServer.pseudolocalization_enabled = button_pressed -func _on_fakebidi_toggled(button_pressed): - ProjectSettings.set("internationalization/pseudolocalization/fake_bidi", button_pressed) +func _on_fake_bidi_toggled(button_pressed: bool) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/fake_bidi", button_pressed) TranslationServer.reload_pseudolocalization() -func _on_prefix_changed(): - ProjectSettings.set("internationalization/pseudolocalization/prefix", $Main/Pseudolocalization_options/prefix/TextEdit.text) +func _on_prefix_changed(new_text: String) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/prefix", new_text) TranslationServer.reload_pseudolocalization() -func _on_suffix_changed(): - ProjectSettings.set("internationalization/pseudolocalization/suffix", $Main/Pseudolocalization_options/suffix/TextEdit.text) +func _on_suffix_changed(new_text: String) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/suffix", new_text) TranslationServer.reload_pseudolocalization() -func _on_Pseudolocalize_pressed(): +func _on_pseudolocalize_pressed() -> void: $Main/Pseudolocalizer/Result.text = TranslationServer.pseudolocalize($Main/Pseudolocalizer/Key.text) -func _on_doublevowels_toggled(button_pressed): - ProjectSettings.set("internationalization/pseudolocalization/double_vowels", button_pressed) +func _on_double_vowels_toggled(button_pressed: bool) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/double_vowels", button_pressed) TranslationServer.reload_pseudolocalization() -func _on_expansion_ratio_text_changed(): - var ratio = ($Main/Pseudolocalization_options/exp_ratio/TextEdit.text).to_float() - if ratio > 1: - ratio = 1 - $Main/Pseudolocalization_options/exp_ratio/TextEdit.text = str(ratio) - if ratio < 0: - ratio = 0 - $Main/Pseudolocalization_options/exp_ratio/TextEdit.text = str(ratio) - ProjectSettings.set("internationalization/pseudolocalization/expansion_ratio", ratio) +func _on_expansion_ratio_value_changed(value: float) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/expansion_ratio", value) TranslationServer.reload_pseudolocalization() -func _on_override_toggled(button_pressed): - ProjectSettings.set("internationalization/pseudolocalization/override", button_pressed) +func _on_override_toggled(button_pressed: bool) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/override", button_pressed) TranslationServer.reload_pseudolocalization() -func _on_skipplaceholders_toggled(button_pressed): - ProjectSettings.set("internationalization/pseudolocalization/skip_placeholders", button_pressed) +func _on_skip_placeholders_toggled(button_pressed: bool) -> void: + ProjectSettings.set_setting("internationalization/pseudolocalization/skip_placeholders", button_pressed) TranslationServer.reload_pseudolocalization() diff --git a/gui/pseudolocalization/Pseudolocalization.tscn b/gui/pseudolocalization/Pseudolocalization.tscn index 6fe6444a..6097f056 100644 --- a/gui/pseudolocalization/Pseudolocalization.tscn +++ b/gui/pseudolocalization/Pseudolocalization.tscn @@ -101,10 +101,11 @@ size_flags_vertical = 1 size_flags_stretch_ratio = 4.0 text = "Expansion Ratio : " -[node name="TextEdit" type="LineEdit" parent="Main/Pseudolocalization_options/exp_ratio"] +[node name="SpinBox" type="SpinBox" parent="Main/Pseudolocalization_options/exp_ratio"] layout_mode = 2 size_flags_horizontal = 3 -caret_blink = true +max_value = 1.0 +step = 0.05 [node name="prefix" type="Control" parent="Main/Pseudolocalization_options"] layout_mode = 2 @@ -200,11 +201,11 @@ layout_mode = 2 [connection signal="toggled" from="Main/Pseudolocalization_options/toggle" to="." method="_on_toggle_toggled"] [connection signal="toggled" from="Main/Pseudolocalization_options/accents" to="." method="_on_accents_toggled"] -[connection signal="toggled" from="Main/Pseudolocalization_options/doublevowels" to="." method="_on_doublevowels_toggled"] -[connection signal="toggled" from="Main/Pseudolocalization_options/fakebidi" to="." method="_on_fakebidi_toggled"] +[connection signal="toggled" from="Main/Pseudolocalization_options/doublevowels" to="." method="_on_double_vowels_toggled"] +[connection signal="toggled" from="Main/Pseudolocalization_options/fakebidi" to="." method="_on_fake_bidi_toggled"] [connection signal="toggled" from="Main/Pseudolocalization_options/override" to="." method="_on_override_toggled"] -[connection signal="toggled" from="Main/Pseudolocalization_options/skipplaceholders" to="." method="_on_skipplaceholders_toggled"] -[connection signal="text_changed" from="Main/Pseudolocalization_options/exp_ratio/TextEdit" to="." method="_on_expansion_ratio_text_changed"] +[connection signal="toggled" from="Main/Pseudolocalization_options/skipplaceholders" to="." method="_on_skip_placeholders_toggled"] +[connection signal="value_changed" from="Main/Pseudolocalization_options/exp_ratio/SpinBox" to="." method="_on_expansion_ratio_value_changed"] [connection signal="text_changed" from="Main/Pseudolocalization_options/prefix/TextEdit" to="." method="_on_prefix_changed"] [connection signal="text_changed" from="Main/Pseudolocalization_options/suffix/TextEdit" to="." method="_on_suffix_changed"] -[connection signal="pressed" from="Main/Pseudolocalizer/Pseudolocalize" to="." method="_on_Pseudolocalize_pressed"] +[connection signal="pressed" from="Main/Pseudolocalizer/Pseudolocalize" to="." method="_on_pseudolocalize_pressed"] diff --git a/gui/pseudolocalization/project.godot b/gui/pseudolocalization/project.godot index 8adf521f..30f45124 100644 --- a/gui/pseudolocalization/project.godot +++ b/gui/pseudolocalization/project.godot @@ -16,6 +16,15 @@ run/main_scene="res://Pseudolocalization.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + +[display] + +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + [internationalization] pseudolocalization/use_pseudolocalization=true diff --git a/gui/regex/project.godot b/gui/regex/project.godot index d6fb52aa..e8a78c93 100644 --- a/gui/regex/project.godot +++ b/gui/regex/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://regex.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/regex/regex.gd b/gui/regex/regex.gd index d25fbdd5..f1e44f29 100644 --- a/gui/regex/regex.gd +++ b/gui/regex/regex.gd @@ -1,47 +1,48 @@ extends VBoxContainer -var regex = RegEx.new() +var regex := RegEx.new() -func _ready(): +func _ready() -> void: %Text.set_text("They asked me \"What's going on \\\"in the manor\\\"?\"") update_expression(%Expression.text) -func update_expression(text): +func update_expression(text: String) -> void: regex.compile(text) update_text() -func update_text(): +func update_text() -> void: for child in %List.get_children(): child.queue_free() + if regex.is_valid(): $HBoxContainer.modulate = Color.WHITE - var matches = regex.search_all(%Text.get_text()) + var matches := regex.search_all(%Text.get_text()) if matches.size() >= 1: # List all matches and their respective captures. - var match_number = 0 + var match_number := 0 for regex_match in matches: match_number += 1 # `match` is a reserved GDScript keyword. - var match_label = Label.new() + var match_label := Label.new() match_label.text = "RegEx match #%d:" % match_number match_label.modulate = Color(0.6, 0.9, 1.0) %List.add_child(match_label) - var capture_number = 0 + var capture_number := 0 for result in regex_match.get_strings(): capture_number += 1 - var capture_label = Label.new() + var capture_label := Label.new() capture_label.text = " Capture group #%d: %s" % [capture_number, result] %List.add_child(capture_label) else: $HBoxContainer.modulate = Color(1, 0.2, 0.1) - var label = Label.new() + var label := Label.new() label.text = "Error: Invalid regular expression. Check if the expression is correctly escaped and terminated." %List.add_child(label) -func _on_help_meta_clicked(_meta): +func _on_help_meta_clicked(_meta: Variant) -> void: # Workaround for clickable link doing nothing when clicked. OS.shell_open("https://regexr.com") diff --git a/gui/rich_text_bbcode/project.godot b/gui/rich_text_bbcode/project.godot index b8788512..e79d15bc 100644 --- a/gui/rich_text_bbcode/project.godot +++ b/gui/rich_text_bbcode/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/rich_text_bbcode/rich_text_bbcode.gd b/gui/rich_text_bbcode/rich_text_bbcode.gd index 3fef0ec7..65eef2cf 100644 --- a/gui/rich_text_bbcode/rich_text_bbcode.gd +++ b/gui/rich_text_bbcode/rich_text_bbcode.gd @@ -1,12 +1,12 @@ extends Control -func _on_RichTextLabel_meta_clicked(meta): - var err = OS.shell_open(meta) +func _on_RichTextLabel_meta_clicked(meta: Variant) -> void: + var err := OS.shell_open(str(meta)) if err == OK: - print("Opened link '%s' successfully!" % meta) + print("Opened link '%s' successfully!" % str(meta)) else: - print("Failed opening the link '%s'!" % meta) + print("Failed opening the link '%s'!" % str(meta)) -func _on_pause_toggled(button_pressed): +func _on_pause_toggled(button_pressed: bool) -> void: get_tree().paused = button_pressed diff --git a/gui/theming_override/project.godot b/gui/theming_override/project.godot index 92224b85..08e70675 100644 --- a/gui/theming_override/project.godot +++ b/gui/theming_override/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_height=576 diff --git a/gui/theming_override/test.gd b/gui/theming_override/test.gd index f2fa71e4..3ba2181d 100644 --- a/gui/theming_override/test.gd +++ b/gui/theming_override/test.gd @@ -5,51 +5,51 @@ extends Control # This means that you should use `add_theme_stylebox_override("normal", ...)` # instead of `set("custom_styles/normal", ...)`. -@onready var label = $Panel/MarginContainer/VBoxContainer/Label -@onready var button = $Panel/MarginContainer/VBoxContainer/Button -@onready var button2 = $Panel/MarginContainer/VBoxContainer/Button2 -@onready var reset_all_button = $Panel/MarginContainer/VBoxContainer/ResetAllButton +@onready var label: Label = $Panel/MarginContainer/VBoxContainer/Label +@onready var button: Button = $Panel/MarginContainer/VBoxContainer/Button +@onready var button2: Button = $Panel/MarginContainer/VBoxContainer/Button2 +@onready var reset_all_button: Button = $Panel/MarginContainer/VBoxContainer/ResetAllButton -func _ready(): +func _ready() -> void: # Focus the first button automatically for keyboard/controller-friendly navigation. button.grab_focus() -func _on_button_pressed(): +func _on_button_pressed() -> void: # We have to modify the normal, hover and pressed styleboxes all at once # to get a correct appearance when the button is hovered or pressed. # We can't use a single StyleBox for all of them as these have different # background colors. - var new_stylebox_normal = button.get_theme_stylebox("normal").duplicate() + var new_stylebox_normal: StyleBoxFlat = button.get_theme_stylebox("normal").duplicate() new_stylebox_normal.border_color = Color(1, 1, 0) - var new_stylebox_hover = button.get_theme_stylebox("hover").duplicate() + var new_stylebox_hover: StyleBoxFlat = button.get_theme_stylebox("hover").duplicate() new_stylebox_hover.border_color = Color(1, 1, 0) - var new_stylebox_pressed = button.get_theme_stylebox("pressed").duplicate() + var new_stylebox_pressed: StyleBoxFlat = button.get_theme_stylebox("pressed").duplicate() new_stylebox_pressed.border_color = Color(1, 1, 0) button.add_theme_stylebox_override("normal", new_stylebox_normal) button.add_theme_stylebox_override("hover", new_stylebox_hover) button.add_theme_stylebox_override("pressed", new_stylebox_pressed) - label.add_theme_color_override("font_color", Color(1, 1, 0.5)) + label.add_theme_color_override("font_color", Color(1, 1, 0.375)) -func _on_button2_pressed(): - var new_stylebox_normal = button2.get_theme_stylebox("normal").duplicate() +func _on_button2_pressed() -> void: + var new_stylebox_normal: StyleBoxFlat = button2.get_theme_stylebox("normal").duplicate() new_stylebox_normal.border_color = Color(0, 1, 0.5) - var new_stylebox_hover = button2.get_theme_stylebox("hover").duplicate() + var new_stylebox_hover: StyleBoxFlat = button2.get_theme_stylebox("hover").duplicate() new_stylebox_hover.border_color = Color(0, 1, 0.5) - var new_stylebox_pressed = button2.get_theme_stylebox("pressed").duplicate() + var new_stylebox_pressed: StyleBoxFlat = button2.get_theme_stylebox("pressed").duplicate() new_stylebox_pressed.border_color = Color(0, 1, 0.5) button2.add_theme_stylebox_override("normal", new_stylebox_normal) button2.add_theme_stylebox_override("hover", new_stylebox_hover) button2.add_theme_stylebox_override("pressed", new_stylebox_pressed) - label.add_theme_color_override("font_color", Color(0.5, 1, 0.75)) + label.add_theme_color_override("font_color", Color(0.375, 1, 0.75)) -func _on_reset_all_button_pressed(): +func _on_reset_all_button_pressed() -> void: button.remove_theme_stylebox_override("normal") button.remove_theme_stylebox_override("hover") button.remove_theme_stylebox_override("pressed") diff --git a/gui/translation/fonts/DroidSans.ttf.import b/gui/translation/fonts/DroidSans.ttf.import index 1b45a53a..948fbe82 100644 --- a/gui/translation/fonts/DroidSans.ttf.import +++ b/gui/translation/fonts/DroidSans.ttf.import @@ -15,7 +15,6 @@ dest_files=["res://.godot/imported/DroidSans.ttf-f4f3e617929333a8a3b131725141d72 Rendering=null antialiasing=1 generate_mipmaps=false -disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/gui/translation/fonts/DroidSansArabic.ttf.import b/gui/translation/fonts/DroidSansArabic.ttf.import index f3d4ff1f..21263a2b 100644 --- a/gui/translation/fonts/DroidSansArabic.ttf.import +++ b/gui/translation/fonts/DroidSansArabic.ttf.import @@ -15,7 +15,6 @@ dest_files=["res://.godot/imported/DroidSansArabic.ttf-e3dcbe0c4bc0f3f609a01ac9b Rendering=null antialiasing=1 generate_mipmaps=false -disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/gui/translation/fonts/DroidSansFallback.ttf.import b/gui/translation/fonts/DroidSansFallback.ttf.import index 3796ff52..0f289db2 100644 --- a/gui/translation/fonts/DroidSansFallback.ttf.import +++ b/gui/translation/fonts/DroidSansFallback.ttf.import @@ -15,7 +15,6 @@ dest_files=["res://.godot/imported/DroidSansFallback.ttf-fefd6276707493f1293e2a6 Rendering=null antialiasing=1 generate_mipmaps=false -disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/gui/translation/fonts/DroidSansHebrew.ttf.import b/gui/translation/fonts/DroidSansHebrew.ttf.import index 28349ccb..4ee792bb 100644 --- a/gui/translation/fonts/DroidSansHebrew.ttf.import +++ b/gui/translation/fonts/DroidSansHebrew.ttf.import @@ -15,7 +15,6 @@ dest_files=["res://.godot/imported/DroidSansHebrew.ttf-12677dba89ba8356d90dbb456 Rendering=null antialiasing=1 generate_mipmaps=false -disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/gui/translation/fonts/DroidSansJapanese.ttf.import b/gui/translation/fonts/DroidSansJapanese.ttf.import index 92417ea9..02f63f0a 100644 --- a/gui/translation/fonts/DroidSansJapanese.ttf.import +++ b/gui/translation/fonts/DroidSansJapanese.ttf.import @@ -15,7 +15,6 @@ dest_files=["res://.godot/imported/DroidSansJapanese.ttf-70e19a56601aacaaf5d6d30 Rendering=null antialiasing=1 generate_mipmaps=false -disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/gui/translation/fonts/DroidSansThai.ttf.import b/gui/translation/fonts/DroidSansThai.ttf.import index adc3edef..acda4b4d 100644 --- a/gui/translation/fonts/DroidSansThai.ttf.import +++ b/gui/translation/fonts/DroidSansThai.ttf.import @@ -15,7 +15,6 @@ dest_files=["res://.godot/imported/DroidSansThai.ttf-136cea21d69e1da7eb0a603f8d9 Rendering=null antialiasing=1 generate_mipmaps=false -disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 msdf_size=48 diff --git a/gui/translation/project.godot b/gui/translation/project.godot index 475f4c12..87a8b4fd 100644 --- a/gui/translation/project.godot +++ b/gui/translation/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://translation_demo_csv.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/translation/translation_demo_csv.tscn b/gui/translation/translation_demo_csv.tscn index d440a4d9..001446ef 100644 --- a/gui/translation/translation_demo_csv.tscn +++ b/gui/translation/translation_demo_csv.tscn @@ -1,10 +1,10 @@ [gd_scene load_steps=6 format=3 uid="uid://du3apufm66p3x"] [ext_resource type="Script" path="res://translation_csv.gd" id="1_o1a7r"] -[ext_resource type="Texture2D" uid="uid://bk44e7bkr4w4l" path="res://images/speaker.webp" id="3_d0i3f"] +[ext_resource type="Texture2D" uid="uid://bk44e7bkr4w4l" path="res://images/speaker.webp" id="3_usrmd"] [ext_resource type="FontFile" uid="uid://b0887xnwnkgju" path="res://fonts/droid_sans.tres" id="3_wf1ar"] -[ext_resource type="Texture2D" uid="uid://cy06u7558clgu" path="res://images/flag_uk.webp" id="4_xn1dg"] -[ext_resource type="AudioStream" uid="uid://ciept8j0x21to" path="res://audio/hello_en.wav" id="6_a303u"] +[ext_resource type="Texture2D" uid="uid://cy06u7558clgu" path="res://images/flag_uk.webp" id="4_j5852"] +[ext_resource type="AudioStream" uid="uid://ciept8j0x21to" path="res://audio/hello_en.wav" id="5_6qqpb"] [node name="TranslationDemoCSV" type="Panel"] anchors_preset = 8 @@ -115,7 +115,7 @@ offset_right = 475.0 offset_bottom = 498.0 theme_override_fonts/font = ExtResource("3_wf1ar") text = "KEY_PUSH" -icon = ExtResource("3_d0i3f") +icon = ExtResource("3_usrmd") [node name="Flag" type="TextureRect" parent="."] layout_mode = 0 @@ -123,10 +123,10 @@ offset_left = 85.0 offset_top = 406.0 offset_right = 213.0 offset_bottom = 491.0 -texture = ExtResource("4_xn1dg") +texture = ExtResource("4_j5852") [node name="Audio" type="AudioStreamPlayer2D" parent="."] -stream = ExtResource("6_a303u") +stream = ExtResource("5_6qqpb") [node name="GoToPOTranslationDemo" type="Button" parent="."] layout_mode = 0 diff --git a/gui/translation/translation_demo_po.tscn b/gui/translation/translation_demo_po.tscn index f3aa9812..217f6a1e 100644 --- a/gui/translation/translation_demo_po.tscn +++ b/gui/translation/translation_demo_po.tscn @@ -74,7 +74,7 @@ The resouce remapping process is the same with CSV. The in-game text translation process is also the same – use keys to fetch the appropriate translation. The main difference between PO files and CSV files is the way both of them store -the translated data in their files. Have a look at the \"translations/po\" +the translated data in their files. Have a look at the \"translations/po\" and \"translations/csv\" folders to see the files involved." [node name="HSeparator" type="HSeparator" parent="."] diff --git a/gui/translation/translation_po.gd b/gui/translation/translation_po.gd index 56254832..921cbf5f 100644 --- a/gui/translation/translation_po.gd +++ b/gui/translation/translation_po.gd @@ -7,6 +7,7 @@ extends Panel func _ready() -> void: _print_intro() + func _on_english_pressed() -> void: TranslationServer.set_locale("en") _print_intro() diff --git a/gui/ui_mirroring/project.godot b/gui/ui_mirroring/project.godot index 5afb9ae0..62ef068e 100644 --- a/gui/ui_mirroring/project.godot +++ b/gui/ui_mirroring/project.godot @@ -16,6 +16,10 @@ run/main_scene="res://ui_mirroring.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/gui/ui_mirroring/ui_mirroring.gd b/gui/ui_mirroring/ui_mirroring.gd index 481a9e1a..3fe1f2a5 100644 --- a/gui/ui_mirroring/ui_mirroring.gd +++ b/gui/ui_mirroring/ui_mirroring.gd @@ -1,11 +1,13 @@ extends Control -func _ready(): +func _ready() -> void: $Label.text = TranslationServer.get_locale() -func _on_Button_pressed(): + +func _on_Button_pressed() -> void: if TranslationServer.get_locale() != "ar": TranslationServer.set_locale("ar") else: TranslationServer.set_locale("en") + $Label.text = TranslationServer.get_locale() diff --git a/gui/ui_mirroring/ui_mirroring.tscn b/gui/ui_mirroring/ui_mirroring.tscn index 3ef3aa51..e326f86e 100644 --- a/gui/ui_mirroring/ui_mirroring.tscn +++ b/gui/ui_mirroring/ui_mirroring.tscn @@ -83,9 +83,9 @@ self_modulate = Color(0.819608, 0.254902, 0.254902, 1) layout_direction = 1 layout_mode = 0 offset_left = 20.0 -offset_top = 90.0 +offset_top = 101.0 offset_right = 170.0 -offset_bottom = 130.0 +offset_bottom = 141.0 [node name="HBoxContainer" type="HBoxContainer" parent="PanelLTR/PanelLocale"] layout_mode = 0 diff --git a/loading/autoload/global.gd b/loading/autoload/global.gd index a2b6b8be..aa8dd4f7 100644 --- a/loading/autoload/global.gd +++ b/loading/autoload/global.gd @@ -1,10 +1,10 @@ extends Node -# Changing scenes is most easily done using the functions change_scene_to_file -# and change_scene_to_packed of the SceneTree. This script demonstrates how to -# change scenes without those helpers. +# Changing scenes is most easily done using the `change_scene_to_file()` and +# `change_scene_to_packed()` methods of SceneTree. This script demonstrates +# how to change scenes without those helpers. -func goto_scene(path: String): +func goto_scene(path: String) -> void: # This function will usually be called from a signal callback, # or some other function from the running scene. # Deleting the current scene at this point might be @@ -16,12 +16,12 @@ func goto_scene(path: String): _deferred_goto_scene.call_deferred(path) -func _deferred_goto_scene(path: String): +func _deferred_goto_scene(path: String) -> void: # Immediately free the current scene. There is no risk here because the # call to this method is already deferred. get_tree().current_scene.free() - var packed_scene := ResourceLoader.load(path) as PackedScene + var packed_scene: PackedScene = ResourceLoader.load(path) var instanced_scene := packed_scene.instantiate() diff --git a/loading/autoload/project.godot b/loading/autoload/project.godot index 00a57ebc..18327419 100644 --- a/loading/autoload/project.godot +++ b/loading/autoload/project.godot @@ -22,6 +22,10 @@ config/icon="res://icon.webp" global="*res://global.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/loading/autoload/scene_a.gd b/loading/autoload/scene_a.gd index 233ff509..d5fe6860 100644 --- a/loading/autoload/scene_a.gd +++ b/loading/autoload/scene_a.gd @@ -1,5 +1,4 @@ extends Panel - -func _on_goto_scene_pressed(): +func _on_goto_scene_pressed() -> void: global.goto_scene("res://scene_b.tscn") diff --git a/loading/autoload/scene_b.gd b/loading/autoload/scene_b.gd index 62f33d35..b8787bb7 100644 --- a/loading/autoload/scene_b.gd +++ b/loading/autoload/scene_b.gd @@ -1,5 +1,4 @@ extends Panel - -func _on_goto_scene_pressed(): +func _on_goto_scene_pressed() -> void: global.goto_scene("res://scene_a.tscn") diff --git a/loading/load_threaded/load_threaded.gd b/loading/load_threaded/load_threaded.gd index fdc4fa39..f3a900fe 100644 --- a/loading/load_threaded/load_threaded.gd +++ b/loading/load_threaded/load_threaded.gd @@ -1,42 +1,41 @@ extends VBoxContainer - -func _on_start_loading_pressed(): +func _on_start_loading_pressed() -> void: ResourceLoader.load_threaded_request("res://paintings/painting_babel.jpg") ResourceLoader.load_threaded_request("res://paintings/painting_las_meninas.png") ResourceLoader.load_threaded_request("res://paintings/painting_mona_lisa.jpg") ResourceLoader.load_threaded_request("res://paintings/painting_old_guitarist.jpg") ResourceLoader.load_threaded_request("res://paintings/painting_parasol.jpg") ResourceLoader.load_threaded_request("res://paintings/painting_the_swing.jpg") - for current_button in $GetLoaded.get_children(): + for current_button: Button in $GetLoaded.get_children(): current_button.disabled = false -func _on_babel_pressed(): +func _on_babel_pressed() -> void: $Paintings/Babel.texture = ResourceLoader.load_threaded_get("res://paintings/painting_babel.jpg") $GetLoaded/Babel.disabled = true -func _on_las_meninas_pressed(): +func _on_las_meninas_pressed() -> void: $Paintings/LasMeninas.texture = ResourceLoader.load_threaded_get("res://paintings/painting_las_meninas.png") $GetLoaded/LasMeninas.disabled = true -func _on_mona_lisa_pressed(): +func _on_mona_lisa_pressed() -> void: $Paintings/MonaLisa.texture = ResourceLoader.load_threaded_get("res://paintings/painting_mona_lisa.jpg") $GetLoaded/MonaLisa.disabled = true -func _on_old_guitarist_pressed(): +func _on_old_guitarist_pressed() -> void: $Paintings/OldGuitarist.texture = ResourceLoader.load_threaded_get("res://paintings/painting_old_guitarist.jpg") $GetLoaded/OldGuitarist.disabled = true -func _on_parasol_pressed(): +func _on_parasol_pressed() -> void: $Paintings/Parasol.texture = ResourceLoader.load_threaded_get("res://paintings/painting_parasol.jpg") $GetLoaded/Parasol.disabled = true -func _on_swing_pressed(): +func _on_swing_pressed() -> void: $Paintings/Swing.texture = ResourceLoader.load_threaded_get("res://paintings/painting_the_swing.jpg") $GetLoaded/Swing.disabled = true diff --git a/loading/load_threaded/project.godot b/loading/load_threaded/project.godot index fcbd1778..96efd427 100644 --- a/loading/load_threaded/project.godot +++ b/loading/load_threaded/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/vsync/vsync_mode=0 diff --git a/loading/runtime_save_load/project.godot b/loading/runtime_save_load/project.godot index f5ea1bcd..27b219b1 100644 --- a/loading/runtime_save_load/project.godot +++ b/loading/runtime_save_load/project.godot @@ -23,6 +23,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.svg" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/loading/scene_changer/project.godot b/loading/scene_changer/project.godot index a93d179b..0e9d71a2 100644 --- a/loading/scene_changer/project.godot +++ b/loading/scene_changer/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.svg" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/loading/scene_changer/scene_a.gd b/loading/scene_changer/scene_a.gd index 14a2fdc9..b28286f3 100644 --- a/loading/scene_changer/scene_a.gd +++ b/loading/scene_changer/scene_a.gd @@ -1,6 +1,5 @@ extends Panel - -func _on_goto_scene_pressed(): +func _on_goto_scene_pressed() -> void: # Change the scene to the one located at the given path. get_tree().change_scene_to_file("res://scene_b.tscn") diff --git a/loading/scene_changer/scene_b.gd b/loading/scene_changer/scene_b.gd index 6c5a372b..804e7335 100644 --- a/loading/scene_changer/scene_b.gd +++ b/loading/scene_changer/scene_b.gd @@ -1,9 +1,8 @@ extends Panel - -func _on_goto_scene_pressed(): +func _on_goto_scene_pressed() -> void: # Change the scene to the given PackedScene. # Though it usually takes more code, this can have advantages, such as letting you load the # scene in another thread, or use a scene that isn't saved to a file. - var scene := load("res://scene_a.tscn") as PackedScene + var scene: PackedScene = load("res://scene_a.tscn") get_tree().change_scene_to_packed(scene) diff --git a/loading/serialization/enemy.gd b/loading/serialization/enemy.gd index fab68791..20f678df 100644 --- a/loading/serialization/enemy.gd +++ b/loading/serialization/enemy.gd @@ -1,5 +1,5 @@ -class_name Enemy extends Node2D - +class_name Enemy +extends Node2D ## Movement speed in pixels per second. const MOVEMENT_SPEED = 75.0 @@ -9,8 +9,7 @@ const DAMAGE_PER_SECOND = 15.0 ## If [code]null[/code], nobody is in range to attack. var attacking: Player = null - -func _process(delta: float): +func _process(delta: float) -> void: if is_instance_valid(attacking): attacking.health -= delta * DAMAGE_PER_SECOND @@ -21,10 +20,10 @@ func _process(delta: float): position.x = -32 -func _on_attack_area_body_entered(body: PhysicsBody2D): +func _on_attack_area_body_entered(body: PhysicsBody2D) -> void: if body is Player: attacking = body -func _on_attack_area_body_exited(_body: PhysicsBody2D): +func _on_attack_area_body_exited(_body: PhysicsBody2D) -> void: attacking = null diff --git a/loading/serialization/gui.gd b/loading/serialization/gui.gd index e4236ea0..21c39d74 100644 --- a/loading/serialization/gui.gd +++ b/loading/serialization/gui.gd @@ -1,11 +1,11 @@ extends VBoxContainer -func _ready(): +func _ready() -> void: # Don't allow loading files that don't exist yet. ($SaveLoad/LoadConfigFile as Button).disabled = not FileAccess.file_exists("user://save_config_file.ini") ($SaveLoad/LoadJSON as Button).disabled = not FileAccess.file_exists("user://save_json.json") -func _on_open_user_data_folder_pressed(): +func _on_open_user_data_folder_pressed() -> void: OS.shell_open(ProjectSettings.globalize_path("user://")) diff --git a/loading/serialization/player.gd b/loading/serialization/player.gd index b2989c88..c1c0020f 100644 --- a/loading/serialization/player.gd +++ b/loading/serialization/player.gd @@ -1,5 +1,5 @@ -class_name Player extends CharacterBody2D - +class_name Player +extends CharacterBody2D ## Movement speed in pixels per second. const MOVEMENT_SPEED = 240.0 @@ -18,8 +18,7 @@ var motion := Vector2() @onready var progress_bar := $ProgressBar as ProgressBar @onready var sprite := $Sprite2D as Sprite2D - -func _process(_delta: float): +func _process(_delta: float) -> void: velocity = Input.get_vector(&"move_left", &"move_right", &"move_up", &"move_down") if velocity.length_squared() > 1.0: velocity = velocity.normalized() @@ -27,7 +26,7 @@ func _process(_delta: float): move_and_slide() -func _input(event: InputEvent): +func _input(event: InputEvent) -> void: if event.is_action_pressed(&"move_left"): sprite.rotation = PI / 2 elif event.is_action_pressed(&"move_right"): diff --git a/loading/serialization/project.godot b/loading/serialization/project.godot index 21d35f06..eafea322 100644 --- a/loading/serialization/project.godot +++ b/loading/serialization/project.godot @@ -21,6 +21,10 @@ run/main_scene="res://save_load.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/loading/serialization/save_load.tscn b/loading/serialization/save_load.tscn index 5ae3b955..afdd00e2 100644 --- a/loading/serialization/save_load.tscn +++ b/loading/serialization/save_load.tscn @@ -44,12 +44,12 @@ texture = ExtResource("2_g2wd8") [node name="ProgressBar" type="ProgressBar" parent="Game/Player"] offset_left = -32.0 -offset_top = -50.0 +offset_top = -52.0 offset_right = 32.0 -offset_bottom = -33.0 +offset_bottom = -32.0 theme_override_colors/font_outline_color = Color(0.152941, 0.152941, 0.152941, 1) -theme_override_constants/outline_size = 6 -theme_override_font_sizes/font_size = 13 +theme_override_constants/outline_size = 8 +theme_override_font_sizes/font_size = 14 theme_override_styles/background = SubResource("StyleBoxFlat_lkphp") theme_override_styles/fill = SubResource("StyleBoxFlat_smouc") value = 100.0 diff --git a/loading/serialization/save_load_config_file.gd b/loading/serialization/save_load_config_file.gd index 9774ca20..a2cf93ec 100644 --- a/loading/serialization/save_load_config_file.gd +++ b/loading/serialization/save_load_config_file.gd @@ -4,7 +4,6 @@ extends Button # It can even store Objects, but be extra careful where you deserialize them # from, because they can include (potentially malicious) scripts. - const SAVE_PATH = "user://save_config_file.ini" ## The root game node (so we can get and instance enemies). @@ -13,7 +12,7 @@ const SAVE_PATH = "user://save_config_file.ini" @export var player_node: NodePath -func save_game(): +func save_game() -> void: var config := ConfigFile.new() var player := get_node(player_node) as Player @@ -30,10 +29,10 @@ func save_game(): config.save(SAVE_PATH) - (get_node(^"../LoadConfigFile") as Button).disabled = false + ($"../LoadConfigFile" as Button).disabled = false -func load_game(): +func load_game() -> void: var config := ConfigFile.new() config.load(SAVE_PATH) @@ -45,10 +44,10 @@ func load_game(): # Remove existing enemies before adding new ones. get_tree().call_group("enemy", "queue_free") - var enemies = config.get_value("enemies", "enemies") - var game = get_node(game_node) + var enemies: Array = config.get_value("enemies", "enemies") + var game := get_node(game_node) - for enemy_config in enemies: + for enemy_config: Dictionary in enemies: var enemy := preload("res://enemy.tscn").instantiate() as Enemy enemy.position = enemy_config.position game.add_child(enemy) diff --git a/loading/serialization/save_load_json.gd b/loading/serialization/save_load_json.gd index 76f82f8d..13adb829 100644 --- a/loading/serialization/save_load_json.gd +++ b/loading/serialization/save_load_json.gd @@ -5,7 +5,6 @@ extends Button # and to store Vector2 and other non-JSON types you need to convert # them, such as to a String using var_to_str. - ## The root game node (so we can get and instance enemies). @export var game_node: NodePath ## The player node (so we can set/get its health and position). @@ -13,20 +12,19 @@ extends Button const SAVE_PATH = "user://save_json.json" - -func save_game(): +func save_game() -> void: var file := FileAccess.open(SAVE_PATH, FileAccess.WRITE) - var player = get_node(player_node) + var player := get_node(player_node) # JSON doesn't support many of Godot's types such as Vector2. # var_to_str can be used to convert any Variant to a String. - var save_dict = { + var save_dict := { player = { position = var_to_str(player.position), health = var_to_str(player.health), - rotation = var_to_str(player.sprite.rotation) + rotation = var_to_str(player.sprite.rotation), }, - enemies = [] + enemies = [], } for enemy in get_tree().get_nodes_in_group(&"enemy"): @@ -39,7 +37,7 @@ func save_game(): get_node(^"../LoadJSON").disabled = false -func load_game(): +func load_game() -> void: var file := FileAccess.open(SAVE_PATH, FileAccess.READ) var json := JSON.new() json.parse(file.get_line()) @@ -58,7 +56,7 @@ func load_game(): # Ensure the node structure is the same when loading. var game := get_node(game_node) - for enemy_config in save_dict.enemies: - var enemy = preload("res://enemy.tscn").instantiate() + for enemy_config: Dictionary in save_dict.enemies: + var enemy: Enemy = preload("res://enemy.tscn").instantiate() enemy.position = str_to_var(enemy_config.position) game.add_child(enemy) diff --git a/loading/threads/project.godot b/loading/threads/project.godot index e84f45e2..515f504f 100644 --- a/loading/threads/project.godot +++ b/loading/threads/project.godot @@ -20,6 +20,10 @@ config/icon="res://icon.webp" run/stretch/aspect="expand" run/stretch/mode="canvas_items" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/loading/threads/thread.gd b/loading/threads/thread.gd index c4be98a1..0dac8724 100644 --- a/loading/threads/thread.gd +++ b/loading/threads/thread.gd @@ -1,22 +1,20 @@ extends Control - var thread: Thread - -func _on_load_pressed(): +func _on_load_pressed() -> void: if is_instance_valid(thread) and thread.is_started(): # If a thread is already running, let it finish before we start another. thread.wait_to_finish() thread = Thread.new() - print("START THREAD!") + print_rich("[b]Starting thread.") # Our method needs an argument, so we pass it using bind(). thread.start(_bg_load.bind("res://mona.png")) -func _bg_load(path: String): - print("THREAD FUNC!") - var tex = load(path) +func _bg_load(path: String) -> Texture2D: + print("Calling thread function.") + var tex := load(path) # call_deferred() tells the main thread to call a method during idle time. # Our method operates on nodes currently in the tree, so it isn't safe to # call directly from another thread. @@ -24,16 +22,17 @@ func _bg_load(path: String): return tex -func _bg_load_done(): +func _bg_load_done() -> void: # Wait for the thread to complete, and get the returned value. - var tex = thread.wait_to_finish() - print("THREAD FINISHED!") + var tex: Texture2D = thread.wait_to_finish() + print_rich("[b][i]Thread finished.\n") $TextureRect.texture = tex # We're done with the thread now, so we can free it. - thread = null # Threads are reference counted, so this is how we free them. + # Threads are reference counted, so this is how we free them. + thread = null -func _exit_tree(): +func _exit_tree() -> void: # You should always wait for a thread to finish before letting it get freed! # It might not clean up correctly if you don't. if is_instance_valid(thread) and thread.is_started(): diff --git a/loading/threads/thread.tscn b/loading/threads/thread.tscn index 689eefc5..c93cac09 100644 --- a/loading/threads/thread.tscn +++ b/loading/threads/thread.tscn @@ -13,25 +13,35 @@ script = ExtResource("1") [node name="Load" type="Button" parent="."] layout_mode = 1 -anchors_preset = 5 +anchors_preset = 8 anchor_left = 0.5 +anchor_top = 0.5 anchor_right = 0.5 +anchor_bottom = 0.5 offset_left = -115.0 -offset_top = 96.0 +offset_top = -227.5 offset_right = 115.0 -offset_bottom = 151.0 +offset_bottom = -172.5 grow_horizontal = 2 +grow_vertical = 2 size_flags_horizontal = 2 size_flags_vertical = 2 theme_override_font_sizes/font_size = 24 text = "Load in Thread" [node name="ColorRect" type="Panel" parent="."] -layout_mode = 0 -offset_left = 461.0 -offset_top = 160.0 -offset_right = 692.0 -offset_bottom = 489.0 +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -115.5 +offset_top = -164.5 +offset_right = 115.5 +offset_bottom = 164.5 +grow_horizontal = 2 +grow_vertical = 2 [node name="TextureRect" type="TextureRect" parent="."] layout_mode = 1 diff --git a/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd b/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd index 94037413..dfb46299 100644 --- a/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd +++ b/misc/2.5d/addons/node25d/main_screen/gizmo_25d.gd @@ -1,17 +1,16 @@ @tool extends Node2D - # If the mouse is farther than this many pixels, it won't grab anything. -const DEADZONE_RADIUS: float = 20 -const DEADZONE_RADIUS_SQ: float = DEADZONE_RADIUS * DEADZONE_RADIUS +const DEADZONE_RADIUS = 20.0 +const DEADZONE_RADIUS_SQ = DEADZONE_RADIUS * DEADZONE_RADIUS # Not pixel perfect for all axes in all modes, but works well enough. # Rounding is not done until after the movement is finished. const ROUGHLY_ROUND_TO_PIXELS = true # Set when the node is created. var node_25d: Node25D -var _spatial_node +var _spatial_node: Node3D # Input from Viewport25D, represents if the mouse is clicked. var wants_to_move = false diff --git a/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd b/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd index 08039dad..ec73e89b 100644 --- a/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd +++ b/misc/2.5d/addons/node25d/main_screen/viewport_25d.gd @@ -17,10 +17,11 @@ var moving = false @onready var gizmo_25d_scene = preload("res://addons/node25d/main_screen/gizmo_25d.tscn") -func _ready(): +func _ready() -> void: # Give Godot a chance to fully load the scene. Should take two frames. - await get_tree().process_frame - await get_tree().process_frame + for i in 2: + await get_tree().process_frame + var edited_scene_root = get_tree().edited_scene_root if not edited_scene_root: # Godot hasn't finished loading yet, so try loading the plugin again. @@ -34,13 +35,13 @@ func _ready(): viewport_2d.world_2d = world_2d -func _process(_delta): +func _process(_delta: float) -> void: if not editor_interface: # Something's not right... bail! return # View mode polling. - var view_mode_changed_this_frame = false - var new_view_mode = -1 + var view_mode_changed_this_frame := false + var new_view_mode := -1 if view_mode_button_group.get_pressed_button(): new_view_mode = view_mode_button_group.get_pressed_button().get_index() if view_mode_index != new_view_mode: @@ -53,15 +54,15 @@ func _process(_delta): zoom_level += 1 elif Input.is_mouse_button_pressed(MOUSE_BUTTON_WHEEL_DOWN): zoom_level -= 1 - var zoom = _get_zoom_amount() + var zoom := _get_zoom_amount() # SubViewport size. - var vp_size = get_global_rect().size + var vp_size := get_global_rect().size viewport_2d.size = vp_size viewport_overlay.size = vp_size # SubViewport transform. - var viewport_trans = Transform2D.IDENTITY + var viewport_trans := Transform2D.IDENTITY viewport_trans.x *= zoom viewport_trans.y *= zoom viewport_trans.origin = viewport_trans.basis_xform(viewport_center) + size / 2 @@ -69,10 +70,10 @@ func _process(_delta): viewport_overlay.canvas_transform = viewport_trans # Delete unused gizmos. - var selection = editor_interface.get_selection().get_selected_nodes() - var gizmos = viewport_overlay.get_children() + var selection := editor_interface.get_selection().get_selected_nodes() + var gizmos := viewport_overlay.get_children() for gizmo in gizmos: - var contains = false + var contains := false for selected in selection: if selected == gizmo.node_25d and not view_mode_changed_this_frame: contains = true @@ -98,7 +99,7 @@ func _ensure_node25d_has_gizmo(node: Node25D, gizmos: Array[Node]) -> void: # This only accepts input when the mouse is inside of the 2.5D viewport. -func _gui_input(event): +func _gui_input(event: InputEvent) -> void: if event is InputEventMouseButton: if event.is_pressed(): if event.button_index == MOUSE_BUTTON_WHEEL_UP: @@ -112,7 +113,7 @@ func _gui_input(event): pan_center = viewport_center - event.position / _get_zoom_amount() accept_event() elif event.button_index == MOUSE_BUTTON_LEFT: - var overlay_children = viewport_overlay.get_children() + var overlay_children := viewport_overlay.get_children() for overlay_child in overlay_children: overlay_child.wants_to_move = true accept_event() @@ -120,7 +121,7 @@ func _gui_input(event): is_panning = false accept_event() elif event.button_index == MOUSE_BUTTON_LEFT: - var overlay_children = viewport_overlay.get_children() + var overlay_children := viewport_overlay.get_children() for overlay_child in overlay_children: overlay_child.wants_to_move = false accept_event() @@ -130,28 +131,31 @@ func _gui_input(event): accept_event() -func _recursive_change_view_mode(current_node): +func _recursive_change_view_mode(current_node: Node) -> void: if not current_node: return + if current_node.has_method("set_view_mode"): current_node.set_view_mode(view_mode_index) + for child in current_node.get_children(): _recursive_change_view_mode(child) -func _get_zoom_amount(): - var zoom_amount = pow(1.05476607648, zoom_level) # 13th root of 2 +func _get_zoom_amount() -> float: + const THIRTEENTH_ROOT_OF_2 = 1.05476607648 + var zoom_amount = pow(THIRTEENTH_ROOT_OF_2, zoom_level) zoom_label.text = str(round(zoom_amount * 1000) / 10) + "%" return zoom_amount -func _on_ZoomOut_pressed(): +func _on_ZoomOut_pressed() -> void: zoom_level -= 1 -func _on_ZoomIn_pressed(): +func _on_ZoomIn_pressed() -> void: zoom_level += 1 -func _on_ZoomReset_pressed(): +func _on_ZoomReset_pressed() -> void: zoom_level = 0 diff --git a/misc/2.5d/addons/node25d/node25d_plugin.gd b/misc/2.5d/addons/node25d/node25d_plugin.gd index 15e1cdd8..db052a32 100644 --- a/misc/2.5d/addons/node25d/node25d_plugin.gd +++ b/misc/2.5d/addons/node25d/node25d_plugin.gd @@ -3,10 +3,10 @@ extends EditorPlugin const MainPanel = preload("res://addons/node25d/main_screen/main_screen_25d.tscn") -var main_panel_instance +var main_panel_instance: Panel -func _enter_tree(): +func _enter_tree() -> void: main_panel_instance = MainPanel.instantiate() main_panel_instance.get_child(1).editor_interface = get_editor_interface() @@ -21,7 +21,7 @@ func _enter_tree(): add_custom_type("ShadowMath25D", "CharacterBody3D", preload("shadow_math_25d.gd"), preload("icons/shadow_math_25d_icon.png")) -func _exit_tree(): +func _exit_tree() -> void: if main_panel_instance: main_panel_instance.queue_free() # When the plugin node exits the tree, remove the custom types. @@ -30,11 +30,11 @@ func _exit_tree(): remove_custom_type("Node25D") -func _has_main_screen(): +func _has_main_screen() -> bool: return true -func _make_visible(visible): +func _make_visible(visible: bool) -> void: if main_panel_instance: if visible: main_panel_instance.show() @@ -42,11 +42,11 @@ func _make_visible(visible): main_panel_instance.hide() -func _get_plugin_name(): +func _get_plugin_name() -> String: return "2.5D" -func _get_plugin_icon(): +func _get_plugin_icon() -> Texture2D: return preload("res://addons/node25d/icons/viewport_25d.svg") diff --git a/misc/2.5d/addons/node25d/node_25d.gd b/misc/2.5d/addons/node25d/node_25d.gd index 7e11fd24..2046f299 100644 --- a/misc/2.5d/addons/node25d/node_25d.gd +++ b/misc/2.5d/addons/node25d/node_25d.gd @@ -85,27 +85,27 @@ func set_spatial_position(value): # This can be changed or removed in actual games where you only need one view mode. func set_view_mode(view_mode_index): match view_mode_index: - 0: # 45 Degrees + 0: # 45 Degrees _basisX = SCALE * Vector2(1, 0) _basisY = SCALE * Vector2(0, -0.70710678118) _basisZ = SCALE * Vector2(0, 0.70710678118) - 1: # Isometric + 1: # Isometric _basisX = SCALE * Vector2(0.86602540378, 0.5) _basisY = SCALE * Vector2(0, -1) _basisZ = SCALE * Vector2(-0.86602540378, 0.5) - 2: # Top Down + 2: # Top Down _basisX = SCALE * Vector2(1, 0) _basisY = SCALE * Vector2(0, 0) _basisZ = SCALE * Vector2(0, 1) - 3: # Front Side + 3: # Front Side _basisX = SCALE * Vector2(1, 0) _basisY = SCALE * Vector2(0, -1) _basisZ = SCALE * Vector2(0, 0) - 4: # Oblique Y + 4: # Oblique Y _basisX = SCALE * Vector2(1, 0) _basisY = SCALE * Vector2(-0.70710678118, -0.70710678118) _basisZ = SCALE * Vector2(0, 1) - 5: # Oblique Z + 5: # Oblique Z _basisX = SCALE * Vector2(1, 0) _basisY = SCALE * Vector2(0, -1) _basisZ = SCALE * Vector2(-0.70710678118, 0.70710678118) diff --git a/misc/2.5d/addons/node25d/shadow_math_25d.gd b/misc/2.5d/addons/node25d/shadow_math_25d.gd index cf3a6eba..e0047d43 100644 --- a/misc/2.5d/addons/node25d/shadow_math_25d.gd +++ b/misc/2.5d/addons/node25d/shadow_math_25d.gd @@ -6,31 +6,34 @@ class_name ShadowMath25D extends ShapeCast3D - var _shadow_root: Node25D var _target_math: Node3D -func _ready(): +func _ready() -> void: _shadow_root = get_parent() - var index = _shadow_root.get_index() - if index > 0: # Else, Shadow is not in a valid place. + + var index := _shadow_root.get_index() + if index > 0: # Else, shadow is not in a valid place. var sibling_25d: Node = _shadow_root.get_parent().get_child(index - 1) if sibling_25d.get_child_count() > 0: var target = sibling_25d.get_child(0) if target is Node3D: _target_math = target return - printerr("Shadow is not in the correct place, expected a previous sibling node with a 3D first child.") + + push_error("Shadow is not in the correct place, expected a previous sibling node with a 3D first child.") -func _physics_process(_delta): +func _physics_process(_delta: float) -> void: if _target_math == null: if _shadow_root != null: _shadow_root.visible = false - return # Shadow is not in a valid place or you're viewing the Shadow25D scene. + return # Shadow is not in a valid place or you're viewing the Shadow25D scene. + position = _target_math.position force_shapecast_update() + if is_colliding(): global_position = get_collision_point(0) _shadow_root.visible = true diff --git a/misc/2.5d/addons/node25d/y_sort_25d.gd b/misc/2.5d/addons/node25d/y_sort_25d.gd index 9ca6b767..fded97fc 100644 --- a/misc/2.5d/addons/node25d/y_sort_25d.gd +++ b/misc/2.5d/addons/node25d/y_sort_25d.gd @@ -4,8 +4,8 @@ # sorting is delayed by one frame. @tool @icon("res://addons/node25d/icons/y_sort_25d_icon.png") -extends Node # Note: NOT Node2D, Node25D, or Node2D -class_name YSort25D +class_name Node # Note: NOT Node2D, Node25D, or Node2D +extends YSort25D # Whether or not to automatically call sort() in _process(). diff --git a/misc/2.5d/assets/cube/cube_math.gd b/misc/2.5d/assets/cube/cube_math.gd index 3ab40c6f..1c564cbe 100644 --- a/misc/2.5d/assets/cube/cube_math.gd +++ b/misc/2.5d/assets/cube/cube_math.gd @@ -1,16 +1,17 @@ extends Node3D -@onready var _cube_point_scene: PackedScene = preload("res://assets/cube/cube_point.tscn") - -@onready var _parent = get_parent() var _is_parent_ready := false -var _cube_points_math = [] -var _cube_math_spatials = [] +var _cube_points_math: Array[Node3D] = [] +var _cube_math_spatials: Array[Node3D] = [] -func _ready(): +@onready var _cube_point_scene: PackedScene = preload("res://assets/cube/cube_point.tscn") +@onready var _parent: Node = get_parent() + + +func _ready() -> void: _parent = get_parent() - for i in range(27): + for i in 27: @warning_ignore("integer_division") var a: int = (i / 9) - 1 @warning_ignore("integer_division") @@ -23,7 +24,7 @@ func _ready(): add_child(_cube_math_spatials[i]) -func _process(delta): +func _process(delta: float) -> void: if Input.is_action_pressed(&"exit"): get_tree().quit() @@ -38,13 +39,13 @@ func _process(delta): rotate_x(delta * (Input.get_axis(&"move_forward", &"move_back"))) rotate_y(delta * (Input.get_axis(&"move_left", &"move_right"))) rotate_z(delta * (Input.get_axis(&"move_clockwise", &"move_counterclockwise"))) - for i in range(27): + for i in 27: _cube_points_math[i].global_transform = _cube_math_spatials[i].global_transform else: - # This code block will be run only once. It's not in _ready() because the parent isn't set up there. - for i in range(27): - var my_cube_point_scene = _cube_point_scene.duplicate(true) - var cube_point = my_cube_point_scene.instantiate() + # This code block will be run only once. It's not in `_ready()` because the parent isn't set up there. + for i in 27: + var my_cube_point_scene := _cube_point_scene.duplicate(true) + var cube_point: Node = my_cube_point_scene.instantiate() cube_point.name = "CubePoint #" + str(i) _cube_points_math.append(cube_point.get_child(0)) _parent.add_child(cube_point) diff --git a/misc/2.5d/assets/cube/cube_point.tscn b/misc/2.5d/assets/cube/cube_point.tscn index ae68f64a..6ff8e711 100644 --- a/misc/2.5d/assets/cube/cube_point.tscn +++ b/misc/2.5d/assets/cube/cube_point.tscn @@ -1,16 +1,12 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=3 format=3 uid="uid://dpm3nweqk8ws0"] -[ext_resource path="res://addons/node25d/node_25d.gd" type="Script" id=1] -[ext_resource path="res://addons/node25d/icons/node_25d_icon.png" type="Texture2D" id=2] -[ext_resource path="res://assets/cube/godot.png" type="Texture2D" id=3] +[ext_resource type="Script" path="res://addons/node25d/node_25d.gd" id="1"] +[ext_resource type="Texture2D" uid="uid://c5d2c7nxf1wbo" path="res://assets/cube/godot.png" id="3"] [node name="CubePoint" type="Node2D"] -script = ExtResource( 1 ) -__meta__ = { -"_editor_icon": ExtResource( 2 ) -} +script = ExtResource("1") [node name="CubePointMath" type="Node3D" parent="."] [node name="CubePointSprite" type="Sprite2D" parent="."] -texture = ExtResource( 3 ) +texture = ExtResource("3") diff --git a/misc/2.5d/assets/demo_scene.tscn b/misc/2.5d/assets/demo_scene.tscn index 2e9cac50..31125d21 100644 --- a/misc/2.5d/assets/demo_scene.tscn +++ b/misc/2.5d/assets/demo_scene.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=4 uid="uid://bc8akj25hcmiy"] +[gd_scene load_steps=12 format=3 uid="uid://bc8akj25hcmiy"] [ext_resource type="PackedScene" uid="uid://6o8sm5bti8d1" path="res://assets/ui/overlay.tscn" id="1"] [ext_resource type="PackedScene" uid="uid://bg27d8sfehmr4" path="res://assets/player/player_25d.tscn" id="2"] diff --git a/misc/2.5d/assets/platform/platform_sprite.gd b/misc/2.5d/assets/platform/platform_sprite.gd index a722eaa4..51b3566c 100644 --- a/misc/2.5d/assets/platform/platform_sprite.gd +++ b/misc/2.5d/assets/platform/platform_sprite.gd @@ -1,14 +1,14 @@ @tool extends Sprite2D -@onready var _forty_five = preload("res://assets/platform/textures/forty_five.png") -@onready var _isometric = preload("res://assets/platform/textures/isometric.png") -@onready var _top_down = preload("res://assets/platform/textures/top_down.png") -@onready var _front_side = preload("res://assets/platform/textures/front_side.png") -@onready var _oblique_y = preload("res://assets/platform/textures/oblique_y.png") -@onready var _oblique_z = preload("res://assets/platform/textures/oblique_z.png") +@onready var _forty_five: Texture2D = preload("res://assets/platform/textures/forty_five.png") +@onready var _isometric: Texture2D = preload("res://assets/platform/textures/isometric.png") +@onready var _top_down: Texture2D = preload("res://assets/platform/textures/top_down.png") +@onready var _front_side: Texture2D = preload("res://assets/platform/textures/front_side.png") +@onready var _oblique_y: Texture2D = preload("res://assets/platform/textures/oblique_y.png") +@onready var _oblique_z: Texture2D = preload("res://assets/platform/textures/oblique_z.png") -func _process(_delta): +func _process(_delta: float) -> void: if not Engine.is_editor_hint(): if Input.is_action_pressed(&"forty_five_mode"): set_view_mode(0) @@ -24,17 +24,17 @@ func _process(_delta): set_view_mode(5) -func set_view_mode(view_mode_index): +func set_view_mode(view_mode_index: int) -> void: match view_mode_index: - 0: # 45 Degrees + 0: # 45 Degrees texture = _forty_five - 1: # Isometric + 1: # Isometric texture = _isometric - 2: # Top Down + 2: # Top Down texture = _top_down - 3: # Front Side + 3: # Front Side texture = _front_side - 4: # Oblique Y + 4: # Oblique Y texture = _oblique_y - 5: # Oblique Z + 5: # Oblique Z texture = _oblique_z diff --git a/misc/2.5d/assets/player/player_math_25d.gd b/misc/2.5d/assets/player/player_math_25d.gd index 67a8d030..36eded2f 100644 --- a/misc/2.5d/assets/player/player_math_25d.gd +++ b/misc/2.5d/assets/player/player_math_25d.gd @@ -4,9 +4,11 @@ extends CharacterBody3D var vertical_speed := 0.0 var isometric_controls := true + @onready var _parent_node25d: Node25D = get_parent() -func _physics_process(delta): + +func _physics_process(delta: float) -> void: if Input.is_action_pressed(&"exit"): get_tree().quit() @@ -26,17 +28,17 @@ func _physics_process(delta): # Checks WASD and Shift for horizontal movement via move_and_slide. -func _horizontal_movement(delta): - var localX = Vector3.RIGHT - var localZ = Vector3.BACK +func _horizontal_movement(_delta: float) -> void: + var local_x := Vector3.RIGHT + var local_z := Vector3.BACK if isometric_controls and is_equal_approx(Node25D.SCALE * 0.86602540378, _parent_node25d.get_basis()[0].x): - localX = Vector3(0.70710678118, 0, -0.70710678118) - localZ = Vector3(0.70710678118, 0, 0.70710678118) + local_x = Vector3(0.70710678118, 0, -0.70710678118) + local_z = Vector3(0.70710678118, 0, 0.70710678118) # Gather player input and add directional movement to a Vector3 variable. - var movement_vec2 = Input.get_vector(&"move_left", &"move_right", &"move_forward", &"move_back") - var move_dir = localX * movement_vec2.x + localZ * movement_vec2.y + var movement_vec2 := Input.get_vector(&"move_left", &"move_right", &"move_forward", &"move_back") + var move_dir: Vector3 = local_x * movement_vec2.x + local_z * movement_vec2.y velocity = move_dir * 10 if Input.is_action_pressed(&"movement_modifier"): @@ -46,10 +48,12 @@ func _horizontal_movement(delta): # Checks Jump and applies gravity and vertical speed via move_and_collide. -func _vertical_movement(delta): +func _vertical_movement(delta: float) -> void: if Input.is_action_just_pressed(&"jump"): vertical_speed = 60 + vertical_speed -= delta * 240 # Gravity - var k = move_and_collide(Vector3.UP * vertical_speed * delta) + var k := move_and_collide(Vector3.UP * vertical_speed * delta) + if k != null: vertical_speed = 0 diff --git a/misc/2.5d/assets/player/player_sprite.gd b/misc/2.5d/assets/player/player_sprite.gd index bbbd8dab..724ded25 100644 --- a/misc/2.5d/assets/player/player_sprite.gd +++ b/misc/2.5d/assets/player/player_sprite.gd @@ -1,38 +1,38 @@ @tool extends Sprite2D -@onready var _stand = preload("res://assets/player/textures/stand.png") -@onready var _jump = preload("res://assets/player/textures/jump.png") -@onready var _run = preload("res://assets/player/textures/run.png") - -const FRAMERATE = 15 +const ANIMATION_FRAMERATE = 15 var _direction := 0 var _progress := 0.0 var _parent_node25d: Node25D var _parent_math: PlayerMath25D -func _ready(): +@onready var _stand: Texture2D = preload("res://assets/player/textures/stand.png") +@onready var _jump: Texture2D = preload("res://assets/player/textures/jump.png") +@onready var _run: Texture2D = preload("res://assets/player/textures/run.png") + +func _ready() -> void: _parent_node25d = get_parent() _parent_math = _parent_node25d.get_child(0) -func _process(delta): +func _process(delta: float) -> void: if Engine.is_editor_hint(): - return # Don't run this in the editor. + return # Don't run this in the editor. _sprite_basis() - var movement = _check_movement() # Always run to get direction, but don't always use return bool. + var movement := _check_movement() # Always run to get direction, but don't always use return bool. # Test-only move and collide, check if the player is on the ground. - var k = _parent_math.move_and_collide(Vector3.DOWN * 10 * delta, true, true, true) + var k := _parent_math.move_and_collide(Vector3.DOWN * 10 * delta, true, true, true) if k != null: if movement: hframes = 6 texture = _run if Input.is_action_pressed(&"movement_modifier"): delta /= 2 - _progress = fmod((_progress + FRAMERATE * delta), 6) + _progress = fmod((_progress + ANIMATION_FRAMERATE * delta), 6) frame = _direction * 6 + int(_progress) else: hframes = 1 @@ -43,34 +43,34 @@ func _process(delta): hframes = 2 texture = _jump _progress = 0 - var jumping = 1 if _parent_math.vertical_speed < 0 else 0 + var jumping := 1 if _parent_math.vertical_speed < 0 else 0 frame = _direction * 2 + jumping -func set_view_mode(view_mode_index): +func set_view_mode(view_mode_index: int) -> void: match view_mode_index: - 0: # 45 Degrees + 0: # 45 Degrees transform.x = Vector2(1, 0) transform.y = Vector2(0, 0.75) - 1: # Isometric + 1: # Isometric transform.x = Vector2(1, 0) transform.y = Vector2(0, 1) - 2: # Top Down + 2: # Top Down transform.x = Vector2(1, 0) transform.y = Vector2(0, 0.5) - 3: # Front Side + 3: # Front Side transform.x = Vector2(1, 0) transform.y = Vector2(0, 1) - 4: # Oblique Y + 4: # Oblique Y transform.x = Vector2(1, 0) transform.y = Vector2(0.75, 0.75) - 5: # Oblique Z + 5: # Oblique Z transform.x = Vector2(1, 0.25) transform.y = Vector2(0, 1) # Change the 2D basis of the sprite to try and make it "fit" multiple view modes. -func _sprite_basis(): +func _sprite_basis() -> void: if not Engine.is_editor_hint(): if Input.is_action_pressed(&"forty_five_mode"): set_view_mode(0) @@ -116,7 +116,7 @@ func _check_movement() -> bool: # Set the direction based on which inputs were pressed. if x == 0: if z == 0: - return false # No movement. + return false # No movement. elif z > 0: _direction = 0 else: @@ -141,4 +141,5 @@ func _check_movement() -> bool: else: _direction = 3 flip_h = false - return true # There is movement. + + return true # There is movement. diff --git a/misc/2.5d/assets/shadow/shadow_sprite.gd b/misc/2.5d/assets/shadow/shadow_sprite.gd index c7c37873..4f5298c8 100644 --- a/misc/2.5d/assets/shadow/shadow_sprite.gd +++ b/misc/2.5d/assets/shadow/shadow_sprite.gd @@ -1,14 +1,15 @@ @tool extends Sprite2D -@onready var _forty_five = preload("res://assets/shadow/textures/forty_five.png") -@onready var _isometric = preload("res://assets/shadow/textures/isometric.png") -@onready var _top_down = preload("res://assets/shadow/textures/top_down.png") -@onready var _front_side = preload("res://assets/shadow/textures/front_side.png") -@onready var _oblique_y = preload("res://assets/shadow/textures/oblique_y.png") -@onready var _oblique_z = preload("res://assets/shadow/textures/oblique_z.png") +@onready var _forty_five: Texture2D = preload("res://assets/shadow/textures/forty_five.png") +@onready var _isometric: Texture2D = preload("res://assets/shadow/textures/isometric.png") +@onready var _top_down: Texture2D = preload("res://assets/shadow/textures/top_down.png") +@onready var _front_side: Texture2D = preload("res://assets/shadow/textures/front_side.png") +@onready var _oblique_y: Texture2D = preload("res://assets/shadow/textures/oblique_y.png") +@onready var _oblique_z: Texture2D = preload("res://assets/shadow/textures/oblique_z.png") -func _process(_delta): + +func _process(_delta: float) -> void: if not Engine.is_editor_hint(): if Input.is_action_pressed(&"forty_five_mode"): set_view_mode(0) @@ -24,17 +25,17 @@ func _process(_delta): set_view_mode(5) -func set_view_mode(view_mode_index): +func set_view_mode(view_mode_index: int) -> void: match view_mode_index: - 0: # 45 Degrees + 0: # 45 Degrees texture = _forty_five - 1: # Isometric + 1: # Isometric texture = _isometric - 2: # Top Down + 2: # Top Down texture = _top_down - 3: # Front Side + 3: # Front Side texture = _front_side - 4: # Oblique Y + 4: # Oblique Y texture = _oblique_y - 5: # Oblique Z + 5: # Oblique Z texture = _oblique_z diff --git a/misc/2.5d/assets/ui/control_hints.gd b/misc/2.5d/assets/ui/control_hints.gd index 33579030..bf87ba15 100644 --- a/misc/2.5d/assets/ui/control_hints.gd +++ b/misc/2.5d/assets/ui/control_hints.gd @@ -1,5 +1,6 @@ extends Control + func _input(event: InputEvent) -> void: if event.is_action_pressed(&"toggle_control_hints"): visible = not visible diff --git a/misc/2.5d/project.godot b/misc/2.5d/project.godot index 61690e83..d671b1d0 100644 --- a/misc/2.5d/project.godot +++ b/misc/2.5d/project.godot @@ -19,6 +19,10 @@ run/main_scene="res://assets/demo_scene.tscn" config/features=PackedStringArray("4.3") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=1600 diff --git a/misc/compute_shader_heightmap/main.gd b/misc/compute_shader_heightmap/main.gd index 69bf1fc8..c9a4781b 100644 --- a/misc/compute_shader_heightmap/main.gd +++ b/misc/compute_shader_heightmap/main.gd @@ -1,6 +1,6 @@ extends Control -@export_file("*.glsl") var shader_file +@export_file("*.glsl") var shader_file: String @export_range(128, 4096, 1, "exp") var dimension: int = 512 @onready var seed_input: SpinBox = $CenterContainer/VBoxContainer/PanelContainer/VBoxContainer/GridContainer/SeedInput @@ -53,7 +53,7 @@ func _ready() -> void: $CenterContainer/VBoxContainer/PanelContainer/VBoxContainer/HBoxContainer/CreateButtonCPU.text += "\n" + OS.get_processor_name() -func _notification(what): +func _notification(what: int) -> void: # Object destructor, triggered before the engine deletes this Node. if what == NOTIFICATION_PREDELETE: cleanup_gpu() @@ -66,13 +66,12 @@ func randomize_seed() -> void: func prepare_image() -> Image: start_time = Time.get_ticks_usec() - # Use the to_int() method on the String to convert to a valid seed. - noise.seed = seed_input.value + noise.seed = int(seed_input.value) # Create image from noise. var heightmap := noise.get_image(po2_dimensions, po2_dimensions, false, false) # Create ImageTexture to display original on screen. - var clone = Image.new() + var clone := Image.new() clone.copy_from(heightmap) clone.resize(512, 512, Image.INTERPOLATE_NEAREST) var clone_tex := ImageTexture.create_from_image(clone) @@ -164,6 +163,7 @@ func compute_island_gpu(heightmap: Image) -> void: rd.compute_list_bind_uniform_set(compute_list, uniform_set, 0) # This is where the magic happens! As our shader has a work group size of 8x8x1, we dispatch # one for every 8x8 block of pixels here. This ratio is highly tunable, and performance may vary. + @warning_ignore("integer_division") rd.compute_list_dispatch(compute_list, po2_dimensions / 8, po2_dimensions / 8, 1) rd.compute_list_end() @@ -207,10 +207,10 @@ func cleanup_gpu() -> void: # Import, compile and load shader, return reference. -func load_shader(rd: RenderingDevice, path: String) -> RID: +func load_shader(p_rd: RenderingDevice, path: String) -> RID: var shader_file_data: RDShaderFile = load(path) var shader_spirv: RDShaderSPIRV = shader_file_data.get_spirv() - return rd.shader_create_from_spirv(shader_spirv) + return p_rd.shader_create_from_spirv(shader_spirv) func compute_island_cpu(heightmap: Image) -> void: @@ -251,10 +251,10 @@ func _on_random_button_pressed() -> void: func _on_create_button_gpu_pressed() -> void: - var heightmap = prepare_image() + var heightmap := prepare_image() compute_island_gpu.call_deferred(heightmap) func _on_create_button_cpu_pressed() -> void: - var heightmap = prepare_image() + var heightmap := prepare_image() compute_island_cpu.call_deferred(heightmap) diff --git a/misc/compute_shader_heightmap/project.godot b/misc/compute_shader_heightmap/project.godot index 26d03515..08bd68cf 100644 --- a/misc/compute_shader_heightmap/project.godot +++ b/misc/compute_shader_heightmap/project.godot @@ -17,6 +17,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/misc/joypads/joypads.gd b/misc/joypads/joypads.gd index a0efb65f..cd07511a 100644 --- a/misc/joypads/joypads.gd +++ b/misc/joypads/joypads.gd @@ -11,26 +11,26 @@ const DEADZONE = 0.2 const FONT_COLOR_DEFAULT = Color(1.0, 1.0, 1.0, 0.5) const FONT_COLOR_ACTIVE = Color(0.2, 1.0, 0.2, 1.0) -var joy_num -var cur_joy = -1 -var axis_value +var joy_num := 0 +var cur_joy := -1 +var axis_value := 0.0 -@onready var axes = $Axes -@onready var button_grid = $Buttons/ButtonGrid -@onready var joypad_axes = $JoypadDiagram/Axes -@onready var joypad_buttons = $JoypadDiagram/Buttons -@onready var joypad_name = $DeviceInfo/JoyName -@onready var joypad_number = $DeviceInfo/JoyNumber +@onready var axes: VBoxContainer = $Axes +@onready var button_grid: GridContainer = $Buttons/ButtonGrid +@onready var joypad_axes: Node2D = $JoypadDiagram/Axes +@onready var joypad_buttons: Node2D = $JoypadDiagram/Buttons +@onready var joypad_name: RichTextLabel = $DeviceInfo/JoyName +@onready var joypad_number: SpinBox = $DeviceInfo/JoyNumber -func _ready(): +func _ready() -> void: Input.joy_connection_changed.connect(_on_joy_connection_changed) for joypad in Input.get_connected_joypads(): print_rich("Found joypad #%d: [b]%s[/b] - %s" % [joypad, Input.get_joy_name(joypad), Input.get_joy_guid(joypad)]) -func _process(_delta): +func _process(_delta: float) -> void: # Get the joypad device number from the spinbox. - joy_num = joypad_number.value + joy_num = int(joypad_number.value) # Display the name of the joypad if we haven't already. if joy_num != cur_joy: @@ -47,7 +47,7 @@ func _process(_delta): axes.get_node("Axis" + str(axis) + "/ProgressBar").set_value(100 * axis_value) axes.get_node("Axis" + str(axis) + "/ProgressBar/Value").set_text("[center][fade start=2 length=16]%s[/fade][/center]" % axis_value) # Scaled value used for alpha channel using valid range rather than including unusable deadzone values. - var scaled_alpha_value = (abs(axis_value) - DEADZONE) / (1.0 - DEADZONE) + var scaled_alpha_value: float = (abs(axis_value) - DEADZONE) / (1.0 - DEADZONE) # Show joypad direction indicators if axis <= JOY_AXIS_RIGHT_Y: if abs(axis_value) < DEADZONE: @@ -89,11 +89,11 @@ func _process(_delta): # Called whenever a joypad has been connected or disconnected. -func _on_joy_connection_changed(device_id, connected): +func _on_joy_connection_changed(device_id: int, connected: bool) -> void: if connected: - print_rich("[color=green]Found newly connected joypad #%d: [b]%s[/b] - %s[/color]" % [device_id, Input.get_joy_name(device_id), Input.get_joy_guid(device_id)]) + print_rich("[color=green][b]+[/b] Found newly connected joypad #%d: [b]%s[/b] - %s[/color]" % [device_id, Input.get_joy_name(device_id), Input.get_joy_guid(device_id)]) else: - print_rich("[color=red]Disconnected joypad #%d.[/color]" % device_id) + print_rich("[color=red][b]-[/b] Disconnected joypad #%d.[/color]" % device_id) if device_id == cur_joy: # Update current joypad label. @@ -103,48 +103,49 @@ func _on_joy_connection_changed(device_id, connected): clear_joypad_name() -func _on_start_vibration_pressed(): - var weak = $Vibration/Weak/Value.get_value() - var strong = $Vibration/Strong/Value.get_value() - var duration = $Vibration/Duration/Value.get_value() +func _on_start_vibration_pressed() -> void: + var weak: float = $Vibration/Weak/Value.get_value() + var strong: float = $Vibration/Strong/Value.get_value() + var duration: float = $Vibration/Duration/Value.get_value() Input.start_joy_vibration(cur_joy, weak, strong, duration) -func _on_stop_vibration_pressed(): +func _on_stop_vibration_pressed() -> void: Input.stop_joy_vibration(cur_joy) -func _on_Remap_pressed(): +func _on_Remap_pressed() -> void: $RemapWizard.start(cur_joy) -func _on_Clear_pressed(): - var guid = Input.get_joy_guid(cur_joy) +func _on_Clear_pressed() -> void: + var guid := Input.get_joy_guid(cur_joy) if guid.is_empty(): push_error("No gamepad selected.") return + Input.remove_joy_mapping(guid) -func _on_Show_pressed(): +func _on_Show_pressed() -> void: $RemapWizard.show_map() -func _on_joy_name_meta_clicked(meta): - OS.shell_open(meta) +func _on_joy_name_meta_clicked(meta: Variant) -> void: + OS.shell_open(str(meta)) -func set_joypad_name(joy_name, joy_guid): +func set_joypad_name(joy_name: String, joy_guid: String) -> void: # Make the GUID clickable (and point to Godot's game controller database for easier lookup). joypad_name.set_text("%s\n[color=#fff9][url=https://github.com/godotengine/godot/blob/master/core/input/gamecontrollerdb.txt]%s[/url][/color]" % [joy_name, joy_guid]) # Make the rest of the UI appear as enabled. - for node in [$JoypadDiagram, $Axes, $Buttons, $Vibration, $VBoxContainer]: + for node: CanvasItem in [$JoypadDiagram, $Axes, $Buttons, $Vibration, $VBoxContainer]: node.modulate.a = 1.0 -func clear_joypad_name(): +func clear_joypad_name() -> void: joypad_name.set_text("[i]No controller detected at ID %d.[/i]" % joypad_number.value) # Make the rest of the UI appear as disabled. - for node in [$JoypadDiagram, $Axes, $Buttons, $Vibration, $VBoxContainer]: + for node: CanvasItem in [$JoypadDiagram, $Axes, $Buttons, $Vibration, $VBoxContainer]: node.modulate.a = 0.5 diff --git a/misc/joypads/project.godot b/misc/joypads/project.godot index f376541a..b01a70a4 100644 --- a/misc/joypads/project.godot +++ b/misc/joypads/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=600 diff --git a/misc/joypads/remap/joy_mapping.gd b/misc/joypads/remap/joy_mapping.gd index 51739209..f3177cdc 100644 --- a/misc/joypads/remap/joy_mapping.gd +++ b/misc/joypads/remap/joy_mapping.gd @@ -1,9 +1,17 @@ -extends RefCounted -class_name JoyMapping +class_name RefCounted +extends JoyMapping +enum Type { + NONE, + BTN, + AXIS, +} -enum TYPE {NONE, BTN, AXIS} -enum AXIS {FULL, HALF_PLUS, HALF_MINUS} +enum Axis { + FULL, + HALF_PLUS, + HALF_MINUS, +} const PLATFORMS = { # From gamecontrollerdb @@ -96,42 +104,46 @@ const XBOX_OSX = { "righttrigger":"a5", } -var type = TYPE.NONE -var idx = -1 -var axis = AXIS.FULL -var inverted = false +var type := Type.NONE +var idx := -1 +var axis := Axis.FULL +var inverted := false - -func _init(p_type = TYPE.NONE, p_idx = -1, p_axis = AXIS.FULL): +func _init(p_type: Type = Type.NONE, p_idx: int = -1, p_axis: Axis = Axis.FULL) -> void: type = p_type idx = p_idx axis = p_axis -func _to_string(): - if type == TYPE.NONE: +func _to_string() -> String: + if type == Type.NONE: return "" - var ts = "b" if type == TYPE.BTN else "a" - var prefix = "" - var suffix = "~" if inverted else "" + + var ts := "b" if type == Type.BTN else "a" + var prefix := "" + var suffix := "~" if inverted else "" + match axis: - AXIS.HALF_PLUS: + Axis.HALF_PLUS: prefix = "+" - AXIS.HALF_MINUS: + Axis.HALF_MINUS: prefix = "-" + return "%s%s%d%s" % [prefix, ts, idx, suffix] -func to_human_string(): - if type == TYPE.BTN: +func to_human_string() -> String: + if type == Type.BTN: return "Button %d" % idx - if type == TYPE.AXIS: - var prefix = "" + + if type == Type.AXIS: + var prefix := "" match axis: - AXIS.HALF_PLUS: + Axis.HALF_PLUS: prefix = "(+) " - AXIS.HALF_MINUS: + Axis.HALF_MINUS: prefix = "(-) " - var suffix = " (inverted)" if inverted else "" + var suffix := " (inverted)" if inverted else "" return "Axis %s%d%s" % [prefix, idx, suffix] + return "" diff --git a/misc/joypads/remap/remap_wizard.gd b/misc/joypads/remap/remap_wizard.gd index 6450584a..4626a8ca 100644 --- a/misc/joypads/remap/remap_wizard.gd +++ b/misc/joypads/remap/remap_wizard.gd @@ -1,6 +1,5 @@ extends Node - const DEADZONE = 0.3 var joy_index: int = -1 @@ -12,69 +11,74 @@ var cur_step: int = -1 var cur_mapping: Dictionary = {} var last_mapping: String = "" -@onready var joy_buttons = $Mapping/Margin/VBox/SubViewportContainer/SubViewport/JoypadDiagram/Buttons -@onready var joy_axes = $Mapping/Margin/VBox/SubViewportContainer/SubViewport/JoypadDiagram/Axes -@onready var joy_mapping_text = $Mapping/Margin/VBox/Info/Text/Value -@onready var joy_mapping_full_axis = $Mapping/Margin/VBox/Info/Extra/FullAxis -@onready var joy_mapping_axis_invert = $Mapping/Margin/VBox/Info/Extra/InvertAxis - +@onready var joy_buttons: Node2D = $Mapping/Margin/VBox/SubViewportContainer/SubViewport/JoypadDiagram/Buttons +@onready var joy_axes: Node2D = $Mapping/Margin/VBox/SubViewportContainer/SubViewport/JoypadDiagram/Axes +@onready var joy_mapping_text: Label = $Mapping/Margin/VBox/Info/Text/Value +@onready var joy_mapping_full_axis: CheckBox = $Mapping/Margin/VBox/Info/Extra/FullAxis +@onready var joy_mapping_axis_invert: CheckBox = $Mapping/Margin/VBox/Info/Extra/InvertAxis # Connected to Mapping.window_input, otherwise no gamepad events # will be received when the subwindow is focused. -func _input(event): +func _input(event: InputEvent) -> void: if cur_step == -1: return + # Ignore events not related to gamepads. if not (event is InputEventJoypadButton or event is InputEventJoypadMotion): return + # Ignore devices other than the one being remapped. Handles accidental input and analog drift. if event.device != joy_index: return + if event is InputEventJoypadMotion: get_viewport().set_input_as_handled() - var motion = event as InputEventJoypadMotion + var motion := event as InputEventJoypadMotion if abs(motion.axis_value) > DEADZONE: - var idx = motion.axis - var map = JoyMapping.new(JoyMapping.TYPE.AXIS, idx) + var idx := motion.axis + var map := JoyMapping.new(JoyMapping.Type.AXIS, idx) map.inverted = joy_mapping_axis_invert.button_pressed if joy_mapping_full_axis.button_pressed: - map.axis = JoyMapping.AXIS.FULL + map.axis = JoyMapping.Axis.FULL elif motion.axis_value > 0: - map.axis = JoyMapping.AXIS.HALF_PLUS + map.axis = JoyMapping.Axis.HALF_PLUS else: - map.axis = JoyMapping.AXIS.HALF_MINUS + map.axis = JoyMapping.Axis.HALF_MINUS joy_mapping_text.text = map.to_human_string() cur_mapping[steps[cur_step]] = map elif event is InputEventJoypadButton and event.pressed: get_viewport().set_input_as_handled() - var btn = event as InputEventJoypadButton - var map = JoyMapping.new(JoyMapping.TYPE.BTN, btn.button_index) + var btn := event as InputEventJoypadButton + var map := JoyMapping.new(JoyMapping.Type.BTN, btn.button_index) joy_mapping_text.text = map.to_human_string() cur_mapping[steps[cur_step]] = map func create_mapping_string(mapping: Dictionary) -> String: - var string = "%s,%s," % [joy_guid, joy_name] - for k in mapping: - var m = mapping[k] - if typeof(m) == TYPE_OBJECT and m.type == JoyMapping.TYPE.NONE: + var string := "%s,%s," % [joy_guid, joy_name] + + for k: String in mapping: + var m: Variant = mapping[k] + if typeof(m) == TYPE_OBJECT and m.type == JoyMapping.Type.NONE: continue string += "%s:%s," % [k, str(m)] - var platform = "Unknown" + + var platform := "Unknown" if JoyMapping.PLATFORMS.keys().has(OS.get_name()): platform = JoyMapping.PLATFORMS[OS.get_name()] + return string + "platform:" + platform -func start(idx: int): +func start(idx: int) -> void: joy_index = idx joy_guid = Input.get_joy_guid(idx) joy_name = Input.get_joy_name(idx) if joy_guid.is_empty(): - printerr("Unable to find controller") + push_error("Unable to find controller") return - if OS.get_name() == "HTML5": - # Propose trying known mapping on HTML5. + if OS.has_feature("web"): + # Propose trying known mapping on Web. $Start.window_title = "%s - %s" % [joy_guid, joy_name] $Start.popup_centered() else: @@ -89,7 +93,7 @@ func remap_and_close(mapping: Dictionary) -> void: show_map() -func reset(): +func reset() -> void: $Start.hide() $Mapping.hide() joy_guid = "" @@ -98,7 +102,7 @@ func reset(): cur_step = -1 -func step_next(): +func step_next() -> void: $Mapping.title = "Step: %d/%d" % [cur_step + 1, steps.size()] joy_mapping_text.text = "" if cur_step >= steps.size(): @@ -107,22 +111,22 @@ func step_next(): _update_step() -func show_map(): - if OS.get_name() == "Web": +func show_map() -> void: + if OS.has_feature("web"): JavaScriptBridge.eval("window.prompt('This is the resulting remap string', '%s')" % last_mapping) else: $MapWindow/Margin/VBoxContainer/TextEdit.text = last_mapping $MapWindow.popup_centered() -func _update_step(): +func _update_step() -> void: $Mapping/Margin/VBox/Info/Buttons/Next.grab_focus() for btn in joy_buttons.get_children(): btn.hide() for axis in joy_axes.get_children(): axis.hide() - var key = steps[cur_step] - var idx = JoyMapping.BASE[key] + var key: String = steps[cur_step] + var idx: int = JoyMapping.BASE[key] if key in ["leftx", "lefty", "rightx", "righty"]: joy_axes.get_node(str(idx) + "+").show() joy_axes.get_node(str(idx) + "-").show() @@ -134,14 +138,14 @@ func _update_step(): joy_mapping_full_axis.button_pressed = key in ["leftx", "lefty", "rightx", "righty", "righttrigger", "lefttrigger"] joy_mapping_axis_invert.button_pressed = false if cur_mapping.has(key): - var cur = cur_mapping[steps[cur_step]] + var cur: JoyMapping = cur_mapping[steps[cur_step]] joy_mapping_text.text = cur.to_human_string() - if cur.type == JoyMapping.TYPE.AXIS: - joy_mapping_full_axis.button_pressed = cur.axis == JoyMapping.AXIS.FULL + if cur.type == JoyMapping.Type.AXIS: + joy_mapping_full_axis.button_pressed = cur.axis == JoyMapping.Axis.FULL joy_mapping_axis_invert.button_pressed = cur.inverted -func _on_Wizard_pressed(): +func _on_Wizard_pressed() -> void: Input.remove_joy_mapping(joy_guid) $Start.hide() $Mapping.popup_centered() @@ -149,66 +153,69 @@ func _on_Wizard_pressed(): step_next() -func _on_Cancel_pressed(): +func _on_Cancel_pressed() -> void: reset() -func _on_xbox_pressed(): +func _on_xbox_pressed() -> void: remap_and_close(JoyMapping.XBOX) -func _on_xboxosx_pressed(): +func _on_xboxosx_pressed() -> void: remap_and_close(JoyMapping.XBOX_OSX) -func _on_Mapping_popup_hide(): +func _on_Mapping_popup_hide() -> void: reset() -func _on_Next_pressed(): +func _on_Next_pressed() -> void: cur_step += 1 step_next() -func _on_Prev_pressed(): +func _on_Prev_pressed() -> void: if cur_step > 0: cur_step -= 1 step_next() -func _on_Skip_pressed(): - var key = steps[cur_step] +func _on_Skip_pressed() -> void: + var key: String = steps[cur_step] if cur_mapping.has(key): cur_mapping.erase(key) + cur_step += 1 step_next() -func _on_FullAxis_toggled(button_pressed): +func _on_FullAxis_toggled(button_pressed: bool) -> void: if cur_step == -1 or not button_pressed: return - var key = steps[cur_step] - if cur_mapping.has(key) and cur_mapping[key].type == JoyMapping.TYPE.AXIS: - cur_mapping[key].axis = JoyMapping.AXIS.FULL + + var key: String = steps[cur_step] + if cur_mapping.has(key) and cur_mapping[key].type == JoyMapping.Type.AXIS: + cur_mapping[key].axis = JoyMapping.Axis.FULL joy_mapping_text.text = cur_mapping[key].to_human_string() -func _on_InvertAxis_toggled(button_pressed): +func _on_InvertAxis_toggled(button_pressed: bool) -> void: if cur_step == -1: return - var key = steps[cur_step] - if cur_mapping.has(key) and cur_mapping[key].type == JoyMapping.TYPE.AXIS: + + var key: String = steps[cur_step] + if cur_mapping.has(key) and cur_mapping[key].type == JoyMapping.Type.AXIS: cur_mapping[key].inverted = button_pressed joy_mapping_text.text = cur_mapping[key].to_human_string() -func _on_start_close_requested(): +func _on_start_close_requested() -> void: $Start.hide() -func _on_mapping_close_requested(): +func _on_mapping_close_requested() -> void: $Mapping.hide() -func _on_map_window_close_requested(): +func _on_map_window_close_requested() -> void: $MapWindow.hide() diff --git a/misc/joypads/remap/remap_wizard.tscn b/misc/joypads/remap/remap_wizard.tscn index 1d29a9d3..ee1fcb9f 100644 --- a/misc/joypads/remap/remap_wizard.tscn +++ b/misc/joypads/remap/remap_wizard.tscn @@ -21,75 +21,44 @@ grow_vertical = 2 [node name="Layout" type="VBoxContainer" parent="Start/Margin"] layout_mode = 2 -offset_right = 600.0 -offset_bottom = 540.0 alignment = 1 [node name="HTML5" type="VBoxContainer" parent="Start/Margin/Layout"] layout_mode = 2 -offset_top = 207.0 -offset_right = 600.0 -offset_bottom = 268.0 [node name="Label" type="Label" parent="Start/Margin/Layout/HTML5"] layout_mode = 2 -offset_right = 600.0 -offset_bottom = 26.0 text = "Try a common mapping:" [node name="known" type="HBoxContainer" parent="Start/Margin/Layout/HTML5"] layout_mode = 2 -offset_top = 30.0 -offset_right = 600.0 -offset_bottom = 61.0 alignment = 1 [node name="Xbox" type="Button" parent="Start/Margin/Layout/HTML5/known"] layout_mode = 2 -offset_left = 228.0 -offset_right = 275.0 -offset_bottom = 31.0 text = "Xbox" [node name="XboxOSX" type="Button" parent="Start/Margin/Layout/HTML5/known"] layout_mode = 2 -offset_left = 279.0 -offset_right = 372.0 -offset_bottom = 31.0 text = "Xbox (OSX)" [node name="Label" type="Label" parent="Start/Margin/Layout"] layout_mode = 2 -offset_top = 272.0 -offset_right = 600.0 -offset_bottom = 298.0 text = "Or start the wizard" [node name="Buttons" type="HBoxContainer" parent="Start/Margin/Layout"] layout_mode = 2 -offset_top = 302.0 -offset_right = 600.0 -offset_bottom = 333.0 [node name="Cancel" type="Button" parent="Start/Margin/Layout/Buttons"] layout_mode = 2 -offset_right = 60.0 -offset_bottom = 31.0 text = "Cancel" [node name="Control" type="Control" parent="Start/Margin/Layout/Buttons"] layout_mode = 2 -anchors_preset = 0 -offset_left = 64.0 -offset_right = 534.0 -offset_bottom = 31.0 size_flags_horizontal = 3 [node name="Wizard" type="Button" parent="Start/Margin/Layout/Buttons"] layout_mode = 2 -offset_left = 538.0 -offset_right = 600.0 -offset_bottom = 31.0 text = "Wizard" [node name="Mapping" type="Window" parent="."] @@ -111,13 +80,10 @@ theme_override_constants/margin_bottom = 30 [node name="VBox" type="VBoxContainer" parent="Mapping/Margin"] layout_mode = 2 -offset_right = 600.0 -offset_bottom = 540.0 [node name="SubViewportContainer" type="SubViewportContainer" parent="Mapping/Margin/VBox"] custom_minimum_size = Vector2(0, 260) layout_mode = 2 -offset_right = 600.0 stretch = true [node name="SubViewport" type="SubViewport" parent="Mapping/Margin/VBox/SubViewportContainer"] @@ -129,91 +95,52 @@ render_target_update_mode = 0 position = Vector2(0, 0) [node name="Camera2D" type="Camera2D" parent="Mapping/Margin/VBox/SubViewportContainer/SubViewport"] -current = true [node name="Info" type="VBoxContainer" parent="Mapping/Margin/VBox"] layout_mode = 2 -offset_top = 4.0 -offset_right = 600.0 -offset_bottom = 100.0 [node name="Text" type="HBoxContainer" parent="Mapping/Margin/VBox/Info"] layout_mode = 2 -offset_right = 600.0 -offset_bottom = 26.0 [node name="Text" type="Label" parent="Mapping/Margin/VBox/Info/Text"] layout_mode = 2 -offset_right = 150.0 -offset_bottom = 26.0 text = "Currently selected: " [node name="Value" type="Label" parent="Mapping/Margin/VBox/Info/Text"] layout_mode = 2 -offset_left = 154.0 -offset_top = 1.0 -offset_right = 155.0 -offset_bottom = 24.0 [node name="Extra" type="HBoxContainer" parent="Mapping/Margin/VBox/Info"] layout_mode = 2 -offset_top = 30.0 -offset_right = 600.0 -offset_bottom = 61.0 [node name="FullAxis" type="CheckBox" parent="Mapping/Margin/VBox/Info/Extra"] layout_mode = 2 -offset_right = 91.0 -offset_bottom = 31.0 text = "Full axis" [node name="InvertAxis" type="CheckBox" parent="Mapping/Margin/VBox/Info/Extra"] layout_mode = 2 -offset_left = 95.0 -offset_right = 205.0 -offset_bottom = 31.0 text = "Invert Axis" [node name="Buttons" type="HBoxContainer" parent="Mapping/Margin/VBox/Info"] layout_mode = 2 -offset_top = 65.0 -offset_right = 600.0 -offset_bottom = 96.0 [node name="Prev" type="Button" parent="Mapping/Margin/VBox/Info/Buttons"] layout_mode = 2 -offset_right = 75.0 -offset_bottom = 31.0 text = "Previous" [node name="Control" type="Control" parent="Mapping/Margin/VBox/Info/Buttons"] layout_mode = 2 -anchors_preset = 0 -offset_left = 79.0 -offset_right = 290.0 -offset_bottom = 31.0 size_flags_horizontal = 3 [node name="Skip" type="Button" parent="Mapping/Margin/VBox/Info/Buttons"] layout_mode = 2 -offset_left = 294.0 -offset_right = 335.0 -offset_bottom = 31.0 text = "Skip" [node name="Control2" type="Control" parent="Mapping/Margin/VBox/Info/Buttons"] layout_mode = 2 -anchors_preset = 0 -offset_left = 339.0 -offset_right = 551.0 -offset_bottom = 31.0 size_flags_horizontal = 3 [node name="Next" type="Button" parent="Mapping/Margin/VBox/Info/Buttons"] layout_mode = 2 -offset_left = 555.0 -offset_right = 600.0 -offset_bottom = 31.0 text = "Next" [node name="MapWindow" type="Window" parent="."] @@ -231,20 +158,13 @@ grow_vertical = 2 [node name="VBoxContainer" type="VBoxContainer" parent="MapWindow/Margin"] layout_mode = 2 -offset_right = 600.0 -offset_bottom = 540.0 [node name="Label" type="Label" parent="MapWindow/Margin/VBoxContainer"] layout_mode = 2 -offset_right = 600.0 -offset_bottom = 26.0 text = "This is the resulting remap string:" [node name="TextEdit" type="TextEdit" parent="MapWindow/Margin/VBoxContainer"] layout_mode = 2 -offset_top = 30.0 -offset_right = 600.0 -offset_bottom = 540.0 size_flags_vertical = 3 [connection signal="close_requested" from="Start" to="." method="_on_start_close_requested"] diff --git a/misc/large_world_coordinates/controls.gd b/misc/large_world_coordinates/controls.gd index e568c254..0956ee47 100644 --- a/misc/large_world_coordinates/controls.gd +++ b/misc/large_world_coordinates/controls.gd @@ -21,6 +21,7 @@ func _ready() -> void: %HelpLabel.text = "Double precision is enabled in this engine build.\nNo shaking should occur at high coordinate levels\n(±65,536 or more on any axis)." %HelpLabel.add_theme_color_override("font_color", Color(0.667, 1, 0.667)) + func _process(delta: float) -> void: %Coordinates.text = "X: [color=#fb9]%f[/color]\nY: [color=#bfa]%f[/color]\nZ: [color=#9cf]%f[/color]" % [node_to_move.position.x, node_to_move.position.y, node_to_move.position.z] if %IncrementX.button_pressed: diff --git a/misc/large_world_coordinates/project.godot b/misc/large_world_coordinates/project.godot index ea3e39d1..000e4f9a 100644 --- a/misc/large_world_coordinates/project.godot +++ b/misc/large_world_coordinates/project.godot @@ -19,6 +19,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/misc/large_world_coordinates/test.tscn b/misc/large_world_coordinates/test.tscn index ae4b8b4f..243cd6af 100644 --- a/misc/large_world_coordinates/test.tscn +++ b/misc/large_world_coordinates/test.tscn @@ -76,11 +76,11 @@ albedo_color = Color(0.0666667, 0.313726, 0.768627, 1) [sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_r08do"] emission_shape = 3 emission_box_extents = Vector3(8, 0, 8) -sub_emitter_mode = 3 -sub_emitter_amount_at_collision = 1 collision_mode = 1 collision_friction = 0.0 collision_bounce = 0.2 +sub_emitter_mode = 3 +sub_emitter_amount_at_collision = 1 [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jmbue"] shading_mode = 0 @@ -89,8 +89,8 @@ shading_mode = 0 material = SubResource("StandardMaterial3D_jmbue") radius = 0.05 height = 0.1 -radial_segments = 4 -rings = 1 +radial_segments = 8 +rings = 4 [sub_resource type="Animation" id="Animation_c3rry"] length = 0.001 @@ -249,7 +249,7 @@ local_coords = true process_material = SubResource("ParticleProcessMaterial_r08do") draw_pass_1 = SubResource("SphereMesh_f1qcl") -[node name="Controls" type="VBoxContainer" parent="." node_paths=PackedStringArray("camera", "camera_holder", "rotation_x", "node_to_move", "rigid_body")] +[node name="Controls" type="VBoxContainer" parent="." node_paths=PackedStringArray("camera", "camera_holder", "rotation_x", "node_to_move")] offset_left = 16.0 offset_top = 16.0 offset_right = 350.0 @@ -260,7 +260,6 @@ camera = NodePath("../Move/CameraHolder/RotationX/Camera3D") camera_holder = NodePath("../Move/CameraHolder") rotation_x = NodePath("../Move/CameraHolder/RotationX") node_to_move = NodePath("../Move") -rigid_body = NodePath("") [node name="HelpLabel" type="Label" parent="Controls"] unique_name_in_owner = true @@ -362,10 +361,10 @@ layout_mode = 2 text = "10,000,000,000,000" [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "move_text_around" libraries = { "": SubResource("AnimationLibrary_2gye4") } +autoplay = "move_text_around" [connection signal="pressed" from="Controls/Button" to="Controls" method="_on_open_documentation_pressed"] [connection signal="pressed" from="Controls/HFlowContainer/Button" to="Controls" method="_on_go_to_button_pressed" binds= [0]] diff --git a/misc/matrix_transform/marker/AxisMarker2D.gd b/misc/matrix_transform/marker/AxisMarker2D.gd index 35ec5f48..895127fb 100644 --- a/misc/matrix_transform/marker/AxisMarker2D.gd +++ b/misc/matrix_transform/marker/AxisMarker2D.gd @@ -4,9 +4,9 @@ class_name AxisMarker2D extends Node2D -func _process(_delta): +func _process(_delta: float) -> void: var line: Line2D = get_child(0).get_child(0) - var marker_parent = get_parent() + var marker_parent: Node = get_parent() line.points[1] = transform.origin if marker_parent as Node2D != null: diff --git a/misc/matrix_transform/marker/AxisMarker3D.gd b/misc/matrix_transform/marker/AxisMarker3D.gd index 0f044150..10a41368 100644 --- a/misc/matrix_transform/marker/AxisMarker3D.gd +++ b/misc/matrix_transform/marker/AxisMarker3D.gd @@ -4,7 +4,7 @@ class_name AxisMarker3D extends Node3D -func _process(_delta): +func _process(_delta: float) -> void: var holder: Node3D = get_child(0).get_child(0) var cube: Node3D = holder.get_child(0) # "Hide" the origin vector if the AxisMarker is at (0, 0, 0) diff --git a/misc/matrix_transform/project.godot b/misc/matrix_transform/project.godot index b9484539..a12666fa 100644 --- a/misc/matrix_transform/project.godot +++ b/misc/matrix_transform/project.godot @@ -21,6 +21,10 @@ run/main_scene="res://3D.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [rendering] renderer/rendering_method="gl_compatibility" diff --git a/misc/noise_viewer/noise_viewer.gd b/misc/noise_viewer/noise_viewer.gd index de61c70f..c150780e 100644 --- a/misc/noise_viewer/noise_viewer.gd +++ b/misc/noise_viewer/noise_viewer.gd @@ -4,12 +4,10 @@ extends Control @onready var noise: FastNoiseLite = $SeamlessNoiseTexture.texture.noise # Various noise parameters. -var min_noise = -1 -var max_noise = 1 +var min_noise := -1.0 +var max_noise := 1.0 - -# Called when the node enters the scene tree for the first time. -func _ready(): +func _ready() -> void: # Set up noise with basic info. $ParameterContainer/SeedSpinBox.value = noise.seed $ParameterContainer/FrequencySpinBox.value = noise.frequency @@ -21,48 +19,50 @@ func _ready(): _refresh_shader_params() -func _refresh_shader_params(): +func _refresh_shader_params() -> void: # Adjust min/max for shader. - var _min = (min_noise + 1) / 2 - var _max = (max_noise + 1) / 2 - var _material = $SeamlessNoiseTexture.material + @warning_ignore("integer_division") + var _min := (min_noise + 1) / 2 + @warning_ignore("integer_division") + var _max := (max_noise + 1) / 2 + var _material: ShaderMaterial = $SeamlessNoiseTexture.material _material.set_shader_parameter("min_value", _min) _material.set_shader_parameter("max_value", _max) -func _on_documentation_button_pressed(): +func _on_documentation_button_pressed() -> void: OS.shell_open("https://docs.godotengine.org/en/latest/classes/class_fastnoiselite.html") -func _on_random_seed_button_pressed(): +func _on_random_seed_button_pressed() -> void: $ParameterContainer/SeedSpinBox.value = floor(randf_range(-2147483648, 2147483648)) -func _on_seed_spin_box_value_changed(value): - noise.seed = value +func _on_seed_spin_box_value_changed(value: float) -> void: + noise.seed = int(value) -func _on_frequency_spin_box_value_changed(value): +func _on_frequency_spin_box_value_changed(value: float) -> void: noise.frequency = value -func _on_fractal_octaves_spin_box_value_changed(value): - noise.fractal_octaves = value +func _on_fractal_octaves_spin_box_value_changed(value: float) -> void: + noise.fractal_octaves = int(value) -func _on_fractal_gain_spin_box_value_changed(value): +func _on_fractal_gain_spin_box_value_changed(value: float) -> void: noise.fractal_gain = value -func _on_fractal_lacunarity_spin_box_value_changed(value): +func _on_fractal_lacunarity_spin_box_value_changed(value: float) -> void: noise.fractal_lacunarity = value -func _on_min_clip_spin_box_value_changed(value): +func _on_min_clip_spin_box_value_changed(value: float) -> void: min_noise = value _refresh_shader_params() -func _on_max_clip_spin_box_value_changed(value): +func _on_max_clip_spin_box_value_changed(value: float) -> void: max_noise = value _refresh_shader_params() diff --git a/misc/noise_viewer/project.godot b/misc/noise_viewer/project.godot index b6b075a3..ddccc061 100644 --- a/misc/noise_viewer/project.godot +++ b/misc/noise_viewer/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/misc/os_test/actions.gd b/misc/os_test/actions.gd index 17f56686..91483e10 100644 --- a/misc/os_test/actions.gd +++ b/misc/os_test/actions.gd @@ -1,12 +1,11 @@ extends Node - -func _on_OpenShellWeb_pressed(): +func _on_open_shell_web_pressed() -> void: OS.shell_open("https://example.com") -func _on_OpenShellFolder_pressed(): - var path = OS.get_environment("HOME") +func _on_open_shell_folder_pressed() -> void: + var path := OS.get_environment("HOME") if path == "": # Windows-specific. path = OS.get_environment("USERPROFILE") @@ -18,17 +17,21 @@ func _on_OpenShellFolder_pressed(): OS.shell_open(path) -func _on_ChangeWindowTitle_pressed(): +func _on_change_window_title_pressed() -> void: DisplayServer.window_set_title("Modified window title. Unicode characters for testing: é € × Ù ¨") -func _on_ChangeWindowIcon_pressed(): - var image = Image.create(128, 128, false, Image.FORMAT_RGB8) +func _on_change_window_icon_pressed() -> void: + if not DisplayServer.has_feature(DisplayServer.FEATURE_ICON): + OS.alert("Changing the window icon is not supported by the current display server (%s)." % DisplayServer.get_name()) + return + + var image := Image.create(128, 128, false, Image.FORMAT_RGB8) image.fill(Color(1, 0.6, 0.3)) DisplayServer.set_icon(image) -func _on_MoveWindowToForeground_pressed(): +func _on_move_window_to_foreground_pressed() -> void: DisplayServer.window_set_title("Will move window to foreground in 5 seconds, try unfocusing the window...") await get_tree().create_timer(5).timeout DisplayServer.window_move_to_foreground() @@ -36,7 +39,7 @@ func _on_MoveWindowToForeground_pressed(): DisplayServer.window_set_title(ProjectSettings.get_setting("application/config/name")) -func _on_RequestAttention_pressed(): +func _on_request_attention_pressed() -> void: DisplayServer.window_set_title("Will request attention in 5 seconds, try unfocusing the window...") await get_tree().create_timer(5).timeout DisplayServer.window_request_attention() @@ -44,36 +47,44 @@ func _on_RequestAttention_pressed(): DisplayServer.window_set_title(ProjectSettings.get_setting("application/config/name")) -func _on_VibrateDeviceShort_pressed(): +func _on_vibrate_device_short_pressed() -> void: Input.vibrate_handheld(200) -func _on_VibrateDeviceLong_pressed(): +func _on_vibrate_device_long_pressed() -> void: Input.vibrate_handheld(1000) -func _on_AddGlobalMenuItems_pressed(): +func _on_add_global_menu_items_pressed() -> void: + if not DisplayServer.has_feature(DisplayServer.FEATURE_GLOBAL_MENU): + OS.alert("Global menus are not supported by the current display server (%s)." % DisplayServer.get_name()) + return + # Add a menu to the main menu bar. DisplayServer.global_menu_add_submenu_item("_main", "Hello", "_main/Hello") DisplayServer.global_menu_add_item( "_main/Hello", "World", - func(tag): print("Clicked main 1 " + str(tag)), - func(tag): print("Key main 1 " + str(tag)), + func(tag: String) -> void: print("Clicked main 1 " + str(tag)), + func(tag: String) -> void: print("Key main 1 " + str(tag)), null, (KEY_MASK_META | KEY_1) as Key ) DisplayServer.global_menu_add_separator("_main/Hello") - DisplayServer.global_menu_add_item("_main/Hello", "World2", func(tag): print("Clicked main 2 " + str(tag))) + DisplayServer.global_menu_add_item("_main/Hello", "World2", func(tag: String) -> void: print("Clicked main 2 " + str(tag))) # Add a menu to the Dock context menu. DisplayServer.global_menu_add_submenu_item("_dock", "Hello", "_dock/Hello") - DisplayServer.global_menu_add_item("_dock/Hello", "World", func(tag): print("Clicked dock 1 " + str(tag))) + DisplayServer.global_menu_add_item("_dock/Hello", "World", func(tag: String) -> void: print("Clicked dock 1 " + str(tag))) DisplayServer.global_menu_add_separator("_dock/Hello") - DisplayServer.global_menu_add_item("_dock/Hello", "World2", func(tag): print("Clicked dock 2 " + str(tag))) + DisplayServer.global_menu_add_item("_dock/Hello", "World2", func(tag: String) -> void: print("Clicked dock 2 " + str(tag))) -func _on_RemoveGlobalMenuItem_pressed(): +func _on_remove_global_menu_item_pressed() -> void: + if not DisplayServer.has_feature(DisplayServer.FEATURE_GLOBAL_MENU): + OS.alert("Global menus are not supported by the current display server (%s)." % DisplayServer.get_name()) + return + DisplayServer.global_menu_remove_item("_main/Hello", 2) DisplayServer.global_menu_remove_item("_main/Hello", 1) DisplayServer.global_menu_remove_item("_main/Hello", 0) @@ -85,17 +96,25 @@ func _on_RemoveGlobalMenuItem_pressed(): DisplayServer.global_menu_remove_item("_dock", 0) -func _on_GetClipboard_pressed(): +func _on_get_clipboard_pressed() -> void: + if not DisplayServer.has_feature(DisplayServer.FEATURE_CLIPBOARD): + OS.alert("Clipboard I/O is not supported by the current display server (%s)." % DisplayServer.get_name()) + return + OS.alert("Clipboard contents:\n\n%s" % DisplayServer.clipboard_get()) -func _on_SetClipboard_pressed(): +func _on_set_clipboard_pressed() -> void: + if not DisplayServer.has_feature(DisplayServer.FEATURE_CLIPBOARD): + OS.alert("Clipboard I/O is not supported by the current display server (%s)." % DisplayServer.get_name()) + return + DisplayServer.clipboard_set("Modified clipboard contents. Unicode characters for testing: é € × Ù ¨") -func _on_DisplayAlert_pressed(): +func _on_display_alert_pressed() -> void: OS.alert("Hello from Godot! Close this dialog to resume the main window.") -func _on_KillCurrentProcess_pressed(): +func _on_kill_current_process_pressed() -> void: OS.kill(OS.get_process_id()) diff --git a/misc/os_test/os_test.gd b/misc/os_test/os_test.gd index 7c2ecd77..625268ec 100644 --- a/misc/os_test/os_test.gd +++ b/misc/os_test/os_test.gd @@ -1,11 +1,10 @@ extends Node -@onready var rtl = $HBoxContainer/Features -@onready var csharp_test = $CSharpTest - +@onready var rtl: RichTextLabel = $HBoxContainer/Features +@onready var csharp_test: Node = $CSharpTest # Returns a human-readable string from a date and time, date, or time dictionary. -func datetime_to_string(date): +func datetime_to_string(date: Dictionary) -> void: if ( date.has("year") and date.has("month") @@ -39,27 +38,34 @@ func datetime_to_string(date): }) -func scan_midi_devices(): +func scan_midi_devices() -> String: OS.open_midi_inputs() - var devices = ", ".join(OS.get_connected_midi_inputs()) + var devices := ", ".join(OS.get_connected_midi_inputs()) OS.close_midi_inputs() return devices -func add_header(header): +func add_header(header: String) -> void: rtl.append_text("\n[font_size=24][color=#6df]{header}[/color][/font_size]\n\n".format({ header = header, })) -func add_line(key, value): +func add_line(key: String, value: Variant) -> void: + if typeof(value) == TYPE_BOOL: + # Colorize boolean values. + value = "[color=8f8]true[/color]" if value else "[color=#f88]false[/color]" + rtl.append_text("[color=#adf]{key}:[/color] {value}\n".format({ key = key, value = value if str(value) != "" else "[color=#fff8](empty)[/color]", })) -func _ready(): +func _ready() -> void: + # Grab focus so that the list can be scrolled (for keyboard/controller-friendly navigation). + rtl.grab_focus() + add_header("Audio") add_line("Mix rate", "%d Hz" % AudioServer.get_mix_rate()) add_line("Output latency", "%f ms" % (AudioServer.get_output_latency() * 1000)) @@ -115,7 +121,7 @@ func _ready(): add_header("Input") add_line("Device has touch screen", DisplayServer.is_touchscreen_available()) - var has_virtual_keyboard = DisplayServer.has_feature(DisplayServer.FEATURE_VIRTUAL_KEYBOARD) + var has_virtual_keyboard := DisplayServer.has_feature(DisplayServer.FEATURE_VIRTUAL_KEYBOARD) add_line("Device has virtual keyboard", has_virtual_keyboard) if has_virtual_keyboard: add_line("Virtual keyboard height", DisplayServer.virtual_keyboard_get_height()) @@ -127,7 +133,7 @@ func _ready(): add_line("Granted permissions", OS.get_granted_permissions()) add_header(".NET (C#)") - var csharp_enabled = ResourceLoader.exists("res://CSharpTest.cs") + var csharp_enabled := ResourceLoader.exists("res://CSharpTest.cs") add_line("Mono module enabled", "Yes" if csharp_enabled else "No") if csharp_enabled: csharp_test.set_script(load("res://CSharpTest.cs")) @@ -163,7 +169,7 @@ func _ready(): ][RenderingServer.get_video_adapter_type()]) add_line("Adapter graphics API version", RenderingServer.get_video_adapter_api_version()) - var video_adapter_driver_info = OS.get_video_adapter_driver_info() + var video_adapter_driver_info := OS.get_video_adapter_driver_info() if video_adapter_driver_info.size() > 0: add_line("Adapter driver name", video_adapter_driver_info[0]) if video_adapter_driver_info.size() > 1: diff --git a/misc/os_test/os_test.tscn b/misc/os_test/os_test.tscn index 2c69dba7..16050dc8 100644 --- a/misc/os_test/os_test.tscn +++ b/misc/os_test/os_test.tscn @@ -1,8 +1,10 @@ -[gd_scene load_steps=3 format=3 uid="uid://ds1y65r8ld026"] +[gd_scene load_steps=4 format=3 uid="uid://ds1y65r8ld026"] [ext_resource type="Script" path="res://os_test.gd" id="1"] [ext_resource type="Script" path="res://actions.gd" id="4"] +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_dl4cr"] + [node name="OSTest" type="Panel"] anchors_preset = 15 anchor_right = 1.0 @@ -28,6 +30,8 @@ theme_override_constants/separation = 10 layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 +focus_mode = 2 +theme_override_styles/focus = SubResource("StyleBoxEmpty_dl4cr") bbcode_enabled = true [node name="Actions" type="VBoxContainer" parent="HBoxContainer"] @@ -134,17 +138,17 @@ text = "Kill Current Process" [node name="CSharpTest" type="Node" parent="."] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/OpenShellWeb" to="HBoxContainer/Actions" method="_on_OpenShellWeb_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/OpenShellFolder" to="HBoxContainer/Actions" method="_on_OpenShellFolder_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/ChangeWindowTitle" to="HBoxContainer/Actions" method="_on_ChangeWindowTitle_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/ChangeWindowIcon" to="HBoxContainer/Actions" method="_on_ChangeWindowIcon_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/MoveWindowToForeground" to="HBoxContainer/Actions" method="_on_MoveWindowToForeground_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/RequestAttention" to="HBoxContainer/Actions" method="_on_RequestAttention_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/VibrateDeviceShort" to="HBoxContainer/Actions" method="_on_VibrateDeviceShort_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/VibrateDeviceLong" to="HBoxContainer/Actions" method="_on_VibrateDeviceLong_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/AddGlobalMenuItems" to="HBoxContainer/Actions" method="_on_AddGlobalMenuItems_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/RemoveGlobalMenuItem" to="HBoxContainer/Actions" method="_on_RemoveGlobalMenuItem_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/GetClipboard" to="HBoxContainer/Actions" method="_on_GetClipboard_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/SetClipboard" to="HBoxContainer/Actions" method="_on_SetClipboard_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/DisplayAlert" to="HBoxContainer/Actions" method="_on_DisplayAlert_pressed"] -[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/KillCurrentProcess" to="HBoxContainer/Actions" method="_on_KillCurrentProcess_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/OpenShellWeb" to="HBoxContainer/Actions" method="_on_open_shell_web_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/OpenShellFolder" to="HBoxContainer/Actions" method="_on_open_shell_folder_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/ChangeWindowTitle" to="HBoxContainer/Actions" method="_on_change_window_title_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/ChangeWindowIcon" to="HBoxContainer/Actions" method="_on_change_window_icon_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/MoveWindowToForeground" to="HBoxContainer/Actions" method="_on_move_window_to_foreground_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/RequestAttention" to="HBoxContainer/Actions" method="_on_request_attention_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/VibrateDeviceShort" to="HBoxContainer/Actions" method="_on_vibrate_device_short_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/VibrateDeviceLong" to="HBoxContainer/Actions" method="_on_vibrate_device_long_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/AddGlobalMenuItems" to="HBoxContainer/Actions" method="_on_add_global_menu_items_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/RemoveGlobalMenuItem" to="HBoxContainer/Actions" method="_on_remove_global_menu_item_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/GetClipboard" to="HBoxContainer/Actions" method="_on_get_clipboard_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/SetClipboard" to="HBoxContainer/Actions" method="_on_set_clipboard_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/DisplayAlert" to="HBoxContainer/Actions" method="_on_display_alert_pressed"] +[connection signal="pressed" from="HBoxContainer/Actions/GridContainer/KillCurrentProcess" to="HBoxContainer/Actions" method="_on_kill_current_process_pressed"] diff --git a/misc/os_test/project.godot b/misc/os_test/project.godot index 39266203..c414aca6 100644 --- a/misc/os_test/project.godot +++ b/misc/os_test/project.godot @@ -23,6 +23,11 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 +gdscript/warnings/int_as_enum_without_match=0 + [display] window/stretch/mode="canvas_items" diff --git a/misc/pause/pause_button.gd b/misc/pause/pause_button.gd index 58972ffb..3a7ff93f 100644 --- a/misc/pause/pause_button.gd +++ b/misc/pause/pause_button.gd @@ -1,6 +1,6 @@ extends Button -func _ready(): +func _ready() -> void: # This ensures that this Node won't be paused, allowing it to # process even when the SceneTree is paused. Without that it would # not be able to unpause the game. Note that you can set this through @@ -8,7 +8,7 @@ func _ready(): process_mode = Node.PROCESS_MODE_ALWAYS -func _toggled(is_button_pressed): +func _toggled(is_button_pressed: bool) -> void: # Pause or unpause the SceneTree based on whether the button is # toggled on or off. get_tree().paused = is_button_pressed diff --git a/misc/pause/process_mode.gd b/misc/pause/process_mode.gd index 033165c5..86ec777f 100644 --- a/misc/pause/process_mode.gd +++ b/misc/pause/process_mode.gd @@ -1,7 +1,7 @@ extends OptionButton -@onready var cube_animation = $"../../AnimationPlayer" +@onready var cube_animation: AnimationPlayer = $"../../AnimationPlayer" -func _on_option_button_item_selected(index): - cube_animation.process_mode = index +func _on_option_button_item_selected(index: int) -> void: + cube_animation.process_mode = index as ProcessMode diff --git a/misc/pause/project.godot b/misc/pause/project.godot index 97aeb68f..03cb8f4d 100644 --- a/misc/pause/project.godot +++ b/misc/pause/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://spinpause.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/misc/window_management/control.gd b/misc/window_management/control.gd index 9568b17b..96ce748b 100644 --- a/misc/window_management/control.gd +++ b/misc/window_management/control.gd @@ -1,10 +1,10 @@ extends Control -var mouse_position = Vector2() +var mouse_position := Vector2() -@onready var observer = $"../Observer" +@onready var observer: CharacterBody3D = $"../Observer" -func _ready(): +func _ready() -> void: if not check_wm_api(): set_physics_process(false) set_process_input(false) @@ -14,8 +14,8 @@ func _ready(): if DisplayServer.get_screen_count() > 1: $Labels/Label_Screen1_RefreshRate.text = "Screen1 Refresh Rate: %.2f Hz" % DisplayServer.screen_get_refresh_rate(1) -func _physics_process(_delta): - var modetext = "Mode: " +func _physics_process(_delta: float) -> void: + var modetext := "Mode: " if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN: modetext += "Fullscreen\n" else: @@ -68,33 +68,33 @@ func _physics_process(_delta): $Buttons/Button_MouseModeCaptured.set_pressed(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED) -func _input(event): +func _input(event: InputEvent) -> void: if event is InputEventMouseMotion: mouse_position = event.position if event is InputEventKey: if Input.is_action_pressed(&"mouse_mode_visible"): - observer.state = observer.STATE_MENU - _on_Button_MouseModeVisible_pressed() + observer.state = observer.State.MENU + _on_button_mouse_mode_visible_pressed() if Input.is_action_pressed(&"mouse_mode_hidden"): - observer.state = observer.STATE_MENU - _on_Button_MouseModeHidden_pressed() + observer.state = observer.State.MENU + _on_button_mouse_mode_hidden_pressed() if Input.is_action_pressed(&"mouse_mode_captured"): - _on_Button_MouseModeCaptured_pressed() + _on_button_mouse_mode_captured_pressed() if Input.is_action_pressed(&"mouse_mode_confined"): - observer.state = observer.STATE_MENU - _on_Button_MouseModeConfined_pressed() + observer.state = observer.State.MENU + _on_button_mouse_mode_confined_pressed() if Input.is_action_pressed(&"mouse_mode_confined_hidden"): - observer.state = observer.STATE_MENU - _on_Button_MouseModeConfinedHidden_pressed() + observer.state = observer.State.MENU + _on_button_mouse_mode_confined_hidden_pressed() -func check_wm_api(): - var s = "" +func check_wm_api() -> bool: + var s := "" if not DisplayServer.has_method("get_screen_count"): s += " - get_screen_count()\n" if not DisplayServer.has_method("window_get_current_screen"): @@ -139,65 +139,65 @@ func check_wm_api(): return false -func _on_Button_MoveTo_pressed(): +func _on_button_move_to_pressed() -> void: DisplayServer.window_set_position(Vector2(100, 100)) -func _on_Button_Resize_pressed(): +func _on_button_resize_pressed() -> void: DisplayServer.window_set_size(Vector2(1280, 720)) -func _on_Button_Screen0_pressed(): +func _on_button_screen_0_pressed() -> void: DisplayServer.window_set_current_screen(0) -func _on_Button_Screen1_pressed(): +func _on_button_screen_1_pressed() -> void: DisplayServer.window_set_current_screen(1) -func _on_Button_Fullscreen_pressed(): +func _on_button_fullscreen_pressed() -> void: if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_FULLSCREEN: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) else: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN) -func _on_Button_FixedSize_pressed(): +func _on_button_fixed_size_pressed() -> void: if DisplayServer.window_get_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED): DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED, false) else: DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_RESIZE_DISABLED, true) -func _on_Button_Minimized_pressed(): +func _on_button_minimized_pressed() -> void: if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_MINIMIZED: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED) else: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED) -func _on_Button_Maximized_pressed(): +func _on_button_maximized_pressed() -> void: if DisplayServer.window_get_mode() == DisplayServer.WINDOW_MODE_MAXIMIZED: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED) else: DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MAXIMIZED) -func _on_Button_MouseModeVisible_pressed(): - Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) +func _on_button_mouse_mode_visible_pressed() -> void: + Input.mouse_mode = Input.MOUSE_MODE_VISIBLE -func _on_Button_MouseModeHidden_pressed(): - Input.set_mouse_mode(Input.MOUSE_MODE_HIDDEN) +func _on_button_mouse_mode_hidden_pressed() -> void: + Input.mouse_mode = Input.MOUSE_MODE_HIDDEN -func _on_Button_MouseModeCaptured_pressed(): - Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - observer.state = observer.STATE_GRAB +func _on_button_mouse_mode_captured_pressed() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED + observer.state = observer.State.GRAB -func _on_Button_MouseModeConfined_pressed(): - Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED) +func _on_button_mouse_mode_confined_pressed() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CONFINED -func _on_Button_MouseModeConfinedHidden_pressed(): - Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED_HIDDEN) +func _on_button_mouse_mode_confined_hidden_pressed() -> void: + Input.mouse_mode = Input.MOUSE_MODE_CONFINED_HIDDEN diff --git a/misc/window_management/observer/observer.gd b/misc/window_management/observer/observer.gd index 314f4071..548d428b 100644 --- a/misc/window_management/observer/observer.gd +++ b/misc/window_management/observer/observer.gd @@ -1,51 +1,59 @@ extends CharacterBody3D -const STATE_MENU = 0 -const STATE_GRAB = 1 +enum State { + MENU, + GRAB, +} -var r_pos = Vector2() -var state = STATE_MENU +var r_pos := Vector2() +var state := State.MENU -var initial_viewport_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var initial_viewport_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -@onready var camera = $Camera3D +@onready var camera: Camera3D = $Camera3D -func _process(delta): - if state != STATE_GRAB: +func _process(delta: float) -> void: + if state != State.GRAB: return - var x_movement = Input.get_axis(&"move_left", &"move_right") - var z_movement = Input.get_axis(&"move_forward", &"move_backwards") - var dir = direction(Vector3(x_movement, 0, z_movement)) + var x_movement := Input.get_axis(&"move_left", &"move_right") + var z_movement := Input.get_axis(&"move_forward", &"move_backwards") + var dir := direction(Vector3(x_movement, 0, z_movement)) transform.origin += dir * 10 * delta - var d = delta * 0.1 # Scale the input, easiest to do by scaling the delta. - rotate(Vector3.UP, d * r_pos.x) # Yaw - camera.transform = camera.transform.rotated(Vector3.RIGHT, d * r_pos.y) # Pitch + # Scale the input, easiest to do by scaling the delta. + var d := delta * 0.1 + rotate(Vector3.UP, d * r_pos.x) # Yaw + camera.transform = camera.transform.rotated(Vector3.RIGHT, d * r_pos.y) # Pitch - r_pos = Vector2.ZERO # We've dealt with all the input, so set it to zero. + # We've dealt with all the input, so set it to zero. + r_pos = Vector2.ZERO -func _input(event): +func _input(event: InputEvent) -> void: if event is InputEventMouseMotion: # Scale mouse sensitivity according to resolution, so that effective mouse sensitivity # doesn't change depending on the viewport size. r_pos = -event.relative * (get_viewport().size.y / initial_viewport_height) if event.is_action("ui_cancel") and event.is_pressed() and not event.is_echo(): - if state == STATE_GRAB: + if state == State.GRAB: Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) - state = STATE_MENU + state = State.MENU else: Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) - state = STATE_GRAB + state = State.GRAB -func direction(vector): - var v = camera.get_global_transform().basis * vector +func direction(vector: Vector3) -> Vector3: + var v := camera.get_global_transform().basis * vector return v.normalized() -func _on_transparent_check_button_toggled(button_pressed): +func _on_transparent_check_button_toggled(button_pressed: bool) -> void: + if not DisplayServer.has_feature(DisplayServer.FEATURE_WINDOW_TRANSPARENCY): + OS.alert("Window transparency is not supported by the current display server (%s)." % DisplayServer.get_name()) + return + get_viewport().transparent_bg = button_pressed DisplayServer.window_set_flag(DisplayServer.WINDOW_FLAG_TRANSPARENT, button_pressed) diff --git a/misc/window_management/project.godot b/misc/window_management/project.godot index 83f4e919..80048079 100644 --- a/misc/window_management/project.godot +++ b/misc/window_management/project.godot @@ -18,6 +18,10 @@ config/features=PackedStringArray("4.2") run/low_processor_mode=true config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/misc/window_management/window_management.tscn b/misc/window_management/window_management.tscn index c949d917..229485fc 100644 --- a/misc/window_management/window_management.tscn +++ b/misc/window_management/window_management.tscn @@ -355,17 +355,17 @@ grow_horizontal = 0 grow_vertical = 0 text = "Transparent" -[connection signal="pressed" from="Control/Buttons/Button_Fullscreen" to="Control" method="_on_Button_Fullscreen_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_FixedSize" to="Control" method="_on_Button_FixedSize_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_Minimized" to="Control" method="_on_Button_Minimized_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_Maximized" to="Control" method="_on_Button_Maximized_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_MoveTo" to="Control" method="_on_Button_MoveTo_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_Resize" to="Control" method="_on_Button_Resize_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_Screen0" to="Control" method="_on_Button_Screen0_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_Screen1" to="Control" method="_on_Button_Screen1_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_MouseModeVisible" to="Control" method="_on_Button_MouseModeVisible_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_MouseModeHidden" to="Control" method="_on_Button_MouseModeHidden_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_MouseModeCaptured" to="Control" method="_on_Button_MouseModeCaptured_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_MouseModeConfined" to="Control" method="_on_Button_MouseModeConfined_pressed"] -[connection signal="pressed" from="Control/Buttons/Button_MouseModeConfinedHidden" to="Control" method="_on_Button_MouseModeConfinedHidden_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_Fullscreen" to="Control" method="_on_button_fullscreen_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_FixedSize" to="Control" method="_on_button_fixed_size_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_Minimized" to="Control" method="_on_button_minimized_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_Maximized" to="Control" method="_on_button_maximized_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_MoveTo" to="Control" method="_on_button_move_to_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_Resize" to="Control" method="_on_button_resize_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_Screen0" to="Control" method="_on_button_screen_0_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_Screen1" to="Control" method="_on_button_screen_1_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_MouseModeVisible" to="Control" method="_on_button_mouse_mode_visible_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_MouseModeHidden" to="Control" method="_on_button_mouse_mode_hidden_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_MouseModeCaptured" to="Control" method="_on_button_mouse_mode_captured_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_MouseModeConfined" to="Control" method="_on_button_mouse_mode_confined_pressed"] +[connection signal="pressed" from="Control/Buttons/Button_MouseModeConfinedHidden" to="Control" method="_on_button_mouse_mode_confined_hidden_pressed"] [connection signal="toggled" from="Control/CheckButton" to="Observer" method="_on_transparent_check_button_toggled"] diff --git a/mobile/android_iap/iap_demo.gd b/mobile/android_iap/iap_demo.gd index 14875da1..22454512 100644 --- a/mobile/android_iap/iap_demo.gd +++ b/mobile/android_iap/iap_demo.gd @@ -2,13 +2,14 @@ extends Control const TEST_ITEM_SKU = "my_in_app_purchase_sku" -@onready var alert_dialog = $AlertDialog -@onready var label = $Label +@onready var alert_dialog: AcceptDialog = $AlertDialog +@onready var label: Label = $Label -var payment = null -var test_item_purchase_token = null +var payment: Object = null +var test_item_purchase_token := "" -func _ready(): + +func _ready() -> void: if Engine.has_singleton("GodotGooglePlayBilling"): label.text += "\n\n\nTest item SKU: %s" % TEST_ITEM_SKU @@ -42,21 +43,23 @@ func _ready(): show_alert('Android IAP support is not enabled.\n\nMake sure you have enabled "Custom Build" and installed and enabled the GodotGooglePlayBilling plugin in your Android export settings!\nThis application will not work otherwise.') -func show_alert(text): +func show_alert(text: String) -> void: alert_dialog.dialog_text = text alert_dialog.popup_centered_clamped(Vector2i(600, 0)) $QuerySkuDetailsButton.disabled = true $PurchaseButton.disabled = true $ConsumeButton.disabled = true -func _on_connected(): + +func _on_connected() -> void: print("PurchaseManager connected") - payment.queryPurchases("inapp") # Use "subs" for subscriptions. + # Use "subs" for subscriptions. + payment.queryPurchases("inapp") -func _on_query_purchases_response(query_result): +func _on_query_purchases_response(query_result: Dictionary) -> void: if query_result.status == OK: - for purchase in query_result.purchases: + for purchase: Dictionary in query_result.purchases: # We must acknowledge all puchases. # See https://developer.android.com/google/play/billing/integrate#process for more information if not purchase.is_acknowledged: @@ -68,70 +71,71 @@ func _on_query_purchases_response(query_result): " debug message: ", query_result.debug_message) -func _on_sku_details_query_completed(sku_details): - for available_sku in sku_details: - show_alert(JSON.new().stringify(available_sku)) +func _on_sku_details_query_completed(sku_details: Array) -> void: + for available_sku: Dictionary in sku_details: + show_alert(JSON.stringify(available_sku)) -func _on_purchases_updated(purchases): - print("Purchases updated: %s" % JSON.new().stringify(purchases)) +func _on_purchases_updated(purchases: Array) -> void: + print("Purchases updated: %s" % JSON.stringify(purchases)) - # See _on_connected - for purchase in purchases: + # See `_on_connected()`. + for purchase: Dictionary in purchases: if not purchase.is_acknowledged: print("Purchase " + str(purchase.sku) + " has not been acknowledged. Acknowledging...") payment.acknowledgePurchase(purchase.purchase_token) - if purchases.size() > 0: + if not purchases.is_empty(): test_item_purchase_token = purchases[purchases.size() - 1].purchase_token -func _on_purchase_acknowledged(purchase_token): +func _on_purchase_acknowledged(purchase_token: String) -> void: print("Purchase acknowledged: %s" % purchase_token) -func _on_purchase_consumed(purchase_token): +func _on_purchase_consumed(purchase_token: String) -> void: show_alert("Purchase consumed successfully: %s" % purchase_token) -func _on_connect_error(code, message): +func _on_connect_error(code: int, message: String) -> void: show_alert("Connect error %d: %s" % [code, message]) -func _on_purchase_error(code, message): +func _on_purchase_error(code: int, message: String) -> void: show_alert("Purchase error %d: %s" % [code, message]) -func _on_purchase_acknowledgement_error(code, message): +func _on_purchase_acknowledgement_error(code: int, message: String) -> void: show_alert("Purchase acknowledgement error %d: %s" % [code, message]) -func _on_purchase_consumption_error(code, message, purchase_token): +func _on_purchase_consumption_error(code: int, message: String, purchase_token: String) -> void: show_alert("Purchase consumption error %d: %s, purchase token: %s" % [code, message, purchase_token]) -func _on_sku_details_query_error(code, message): +func _on_sku_details_query_error(code: int, message: String) -> void: show_alert("SKU details query error %d: %s" % [code, message]) -func _on_disconnected(): +func _on_disconnected() -> void: show_alert("GodotGooglePlayBilling disconnected. Will try to reconnect in 10s...") await get_tree().create_timer(10).timeout payment.startConnection() # GUI -func _on_QuerySkuDetailsButton_pressed(): - payment.querySkuDetails([TEST_ITEM_SKU], "inapp") # Use "subs" for subscriptions. +func _on_QuerySkuDetailsButton_pressed() -> void: + # Use "subs" for subscriptions. + payment.querySkuDetails([TEST_ITEM_SKU], "inapp") -func _on_PurchaseButton_pressed(): - var response = payment.purchase(TEST_ITEM_SKU) +func _on_PurchaseButton_pressed() -> void: + var response: Dictionary = payment.purchase(TEST_ITEM_SKU) if response.status != OK: show_alert("Purchase error %s: %s" % [response.response_code, response.debug_message]) -func _on_ConsumeButton_pressed(): +func _on_ConsumeButton_pressed() -> void: if test_item_purchase_token == null: show_alert("You need to set 'test_item_purchase_token' first! (either by hand or in code)") return diff --git a/mobile/android_iap/project.godot b/mobile/android_iap/project.godot index f6497a58..02e40400 100644 --- a/mobile/android_iap/project.godot +++ b/mobile/android_iap/project.godot @@ -23,6 +23,10 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/mobile/multitouch_cubes/GestureArea.gd b/mobile/multitouch_cubes/GestureArea.gd index ab957697..73acad23 100644 --- a/mobile/multitouch_cubes/GestureArea.gd +++ b/mobile/multitouch_cubes/GestureArea.gd @@ -1,34 +1,28 @@ extends Control @export var target: NodePath -@export var min_scale = 0.1 -@export var max_scale = 3.0 -@export var one_finger_rot_x = true -@export var one_finger_rot_y = true -@export var two_fingers_rot_z = true -@export var two_fingers_zoom = true +@export var min_scale := 0.1 +@export var max_scale := 3.0 +@export var one_finger_rot_x := true +@export var one_finger_rot_y := true +@export var two_fingers_rot_z := true +@export var two_fingers_zoom := true -var base_state -var curr_state - -var target_node +var base_state := {} +var curr_state := {} # We keep here a copy of the state before the number of fingers changed to avoid accumulation errors. -var base_xform +var base_xform: Transform3D -func _ready(): - base_state = {} - curr_state = {} - target_node = get_node(target) +@onready var target_node: Node = get_node(target) - -func _gui_input(event): +func _gui_input(event: InputEvent) -> void: # We must start touching inside, but we can drag or unpress outside. # if not (event is InputEventScreenDrag or # (event is InputEventScreenTouch and (not event.pressed or get_global_rect().has_point(event.position)))): # return - var finger_count = base_state.size() + var finger_count := base_state.size() if finger_count == 0: # No fingers => Accept press. @@ -61,7 +55,7 @@ func _gui_input(event): elif event is InputEventScreenDrag: if curr_state.has(event.index): # Touching finger dragged. - var unit_drag = _px2unit(base_state[base_state.keys()[0]] - event.position) + var unit_drag := _px2unit(base_state[base_state.keys()[0]] - event.position) if one_finger_rot_x: target_node.global_rotate(Vector3.UP, deg_to_rad(180.0 * unit_drag.x)) if one_finger_rot_y: @@ -87,29 +81,29 @@ func _gui_input(event): curr_state[event.index] = event.position # Compute base and current inter-finger vectors. - var base_segment = base_state[base_state.keys()[0]] - base_state[base_state.keys()[1]] - var new_segment = curr_state[curr_state.keys()[0]] - curr_state[curr_state.keys()[1]] + var base_segment: Vector3 = base_state[base_state.keys()[0]] - base_state[base_state.keys()[1]] + var new_segment: Vector3 = curr_state[curr_state.keys()[0]] - curr_state[curr_state.keys()[1]] # Get the base scale from the base matrix. - var base_scale = Vector3(base_xform.basis.x.x, base_xform.basis.y.y, base_xform.basis.z.z).length() + var base_scale := Vector3(base_xform.basis.x.x, base_xform.basis.y.y, base_xform.basis.z.z).length() if two_fingers_zoom: # Compute the new scale limiting it and taking into account the base scale. - var new_scale = clamp(base_scale * (new_segment.length() / base_segment.length()), min_scale, max_scale) / base_scale + var new_scale := clampf(base_scale * (new_segment.length() / base_segment.length()), min_scale, max_scale) / base_scale target_node.set_transform(base_xform.scaled(new_scale * Vector3.ONE)) else: target_node.set_transform(base_xform) if two_fingers_rot_z: # Apply rotation between base inter-finger vector and the current one. - var rot = new_segment.angle_to(base_segment) + var rot := new_segment.angle_to(base_segment) target_node.global_rotate(Vector3.BACK, rot) # Finger count changed? if base_state.size() != finger_count: # Copy new base state to the current state. curr_state = {} - for idx in base_state.keys(): + for idx: int in base_state.keys(): curr_state[idx] = base_state[idx] # Remember the base transform. base_xform = target_node.get_transform() @@ -117,6 +111,6 @@ func _gui_input(event): # Converts a vector in pixels to a unitary magnitude, # considering the number of pixels of the shorter axis is the unit. -func _px2unit(v): - var shortest = min(get_size().x, get_size().y) +func _px2unit(v: Vector2) -> Vector2: + var shortest := minf(get_size().x, get_size().y) return v * (1.0 / shortest) diff --git a/mobile/multitouch_cubes/project.godot b/mobile/multitouch_cubes/project.godot index 3c83bca3..1ae86dac 100644 --- a/mobile/multitouch_cubes/project.godot +++ b/mobile/multitouch_cubes/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://Main.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/mobile/multitouch_view/Main.gd b/mobile/multitouch_view/Main.gd index 852c37c2..32979b96 100644 --- a/mobile/multitouch_view/Main.gd +++ b/mobile/multitouch_view/Main.gd @@ -1,22 +1,22 @@ extends Node2D -func _process(_delta): +func _process(_delta: float) -> void: # Keep redrawing on every frame. queue_redraw() -func _draw(): +func _draw() -> void: # Get the touch helper singleton. - var touch_helper = get_node(^"/root/TouchHelper") + var touch_helper: Node = $"/root/TouchHelper" # Draw every pointer as a circle. - for ptr_index in touch_helper.state.keys(): - var pos = touch_helper.state[ptr_index] - var color = _get_color_for_ptr_index(ptr_index) + for ptr_index: int in touch_helper.state.keys(): + var pos: Vector2 = touch_helper.state[ptr_index] + var color := _get_color_for_ptr_index(ptr_index) color.a = 0.75 draw_circle(pos, 40.0, color) -# Just a way of getting different colors. -func _get_color_for_ptr_index(index): - var x = (index % 7) + 1 +## Returns a unique-looking color for the specified index. +func _get_color_for_ptr_index(index: int) -> Color: + var x := (index % 7) + 1 return Color(float(bool(x & 1)), float(bool(x & 2)), float(bool(x & 4))) diff --git a/mobile/multitouch_view/TouchHelper.gd b/mobile/multitouch_view/TouchHelper.gd index 171e2113..933fa763 100644 --- a/mobile/multitouch_view/TouchHelper.gd +++ b/mobile/multitouch_view/TouchHelper.gd @@ -5,16 +5,19 @@ extends Node # It also remaps the pointer indices coming from the OS to the lowest available to be friendlier. # It can be conveniently setup as a singleton. -var state = {} +var state := {} -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: if event is InputEventScreenTouch: - if event.pressed: # Down. + if event.pressed: + # Down. state[event.index] = event.position - else: # Up. + else: + # Up. state.erase(event.index) get_viewport().set_input_as_handled() - elif event is InputEventScreenDrag: # Movement. + elif event is InputEventScreenDrag: + # Movement. state[event.index] = event.position get_viewport().set_input_as_handled() diff --git a/mobile/multitouch_view/project.godot b/mobile/multitouch_view/project.godot index fde08aa3..8933c1fd 100644 --- a/mobile/multitouch_view/project.godot +++ b/mobile/multitouch_view/project.godot @@ -21,6 +21,10 @@ config/icon="res://icon.webp" TouchHelper="*res://TouchHelper.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/mobile/sensors/main.gd b/mobile/sensors/main.gd index 47d56d77..e4edc90a 100644 --- a/mobile/sensors/main.gd +++ b/mobile/sensors/main.gd @@ -1,6 +1,5 @@ extends Node - # Below are a number of helper functions that show how you can use the raw sensor data to determine the orientation # of your phone/device. The cheapest phones only have an accelerometer only the most expensive phones have all three. # Note that none of this logic filters data. Filters introduce lag but also provide stability. There are plenty @@ -10,66 +9,66 @@ extends Node # these cubes to our phones orientation. # This is a 3D example however reading the phones orientation is also invaluable for 2D -# This function calculates a rotation matrix based on a direction vector. As our arrows are cylindrical we don't -# care about the rotation around this axis. -func get_basis_for_arrow(p_vector): - var rotate = Basis() +## Returns a rotation matrix based on a direction vector. As our arrows are cylindrical, we don't +## care about the rotation around this axis. +func get_basis_for_arrow(p_vector: Vector3) -> Basis: + var rotate := Basis() - # as our arrow points up, Y = our direction vector + # As our arrow points up, Y = our direction vector. rotate.y = p_vector.normalized() - # get an arbitrary vector we can use to calculate our other two vectors - var v = Vector3(1.0, 0.0, 0.0) + # Get an arbitrary vector we can use to calculate our other two vectors. + var v := Vector3(1.0, 0.0, 0.0) if abs(v.dot(rotate.y)) > 0.9: v = Vector3(0.0, 1.0, 0.0) - # use our vector to get a vector perpendicular to our two vectors + # Use our vector to get a vector perpendicular to our two vectors. rotate.x = rotate.y.cross(v).normalized() - # and the cross product again gives us our final vector perpendicular to our previous two vectors + # And the cross product again gives us our final vector perpendicular to our previous two vectors. rotate.z = rotate.x.cross(rotate.y).normalized() return rotate -# This function combines the magnetometer reading with the gravity vector to get a vector that points due north -func calc_north(p_grav, p_mag): +## Combines the magnetometer reading with the gravity vector to get a vector that points due north. +func calc_north(p_grav: Vector3, p_mag: Vector3) -> Vector3: # Always use normalized vectors! p_grav = p_grav.normalized() # Calculate east (or is it west) by getting our cross product. # The cross product of two normalized vectors returns a vector that - # is perpendicular to our two vectors - var east = p_grav.cross(p_mag.normalized()).normalized() + # is perpendicular to our two vectors. + var east := p_grav.cross(p_mag.normalized()).normalized() - # Cross again to get our horizon aligned north + # Cross again to get our horizon-aligned north. return east.cross(p_grav).normalized() -# This function creates an orientation matrix using the magnetometer and gravity vector as inputs. -func orientate_by_mag_and_grav(p_mag, p_grav): - var rotate = Basis() +## Returns an orientation matrix using the magnetometer and gravity vector as inputs. +func orientate_by_mag_and_grav(p_mag: Vector3, p_grav: Vector3) -> Basis: + var rotate := Basis() - # as always, normalize! + # As always, normalize! p_mag = p_mag.normalized() - # gravity points down, so - gravity points up! + # Gravity points down, so - gravity points up! rotate.y = -p_grav.normalized() - # Cross products with our magnetic north gives an aligned east (or west, I always forget) + # Cross products with our magnetic north gives an aligned east (or west, I always forget). rotate.x = rotate.y.cross(p_mag) - # And cross product again and we get our aligned north completing our matrix + # And cross product again and we get our aligned north completing our matrix. rotate.z = rotate.x.cross(rotate.y) return rotate -# This function takes our gyro input and update an orientation matrix accordingly -# The gyro is special as this vector does not contain a direction but rather a -# rotational velocity. This is why we multiply our values with delta. -func rotate_by_gyro(p_gyro, p_basis, p_delta): - var rotate = Basis() +## Takes our gyro input and updates an orientation matrix accordingly. +## The gyro is special as this vector does not contain a direction but rather a +## rotational velocity. This is why we multiply our values with delta. +func rotate_by_gyro(p_gyro: Vector3, p_basis: Basis, p_delta: float) -> Basis: + var rotate := Basis() rotate = rotate.rotated(p_basis.x, -p_gyro.x * p_delta) rotate = rotate.rotated(p_basis.y, -p_gyro.y * p_delta) @@ -78,33 +77,33 @@ func rotate_by_gyro(p_gyro, p_basis, p_delta): return rotate * p_basis -# This function corrects the drift in our matrix by our gravity vector -func drift_correction(p_basis, p_grav): - # as always, make sure our vector is normalized but also invert as our gravity points down - var real_up = -p_grav.normalized() +## Returns the basis corrected for drift by our gravity vector. +func drift_correction(p_basis: Basis, p_grav: Vector3) -> Basis: + # As always, make sure our vector is normalized but also invert as our gravity points down. + var real_up := -p_grav.normalized() - # start by calculating the dot product, this gives us the cosine angle between our two vectors - var dot = p_basis.y.dot(real_up) + # Start by calculating the dot product. This gives us the cosine angle between our two vectors. + var dot := p_basis.y.dot(real_up) - # if our dot is 1.0 we're good + # If our dot is 1.0, we're good. if dot < 1.0: - # the cross between our two vectors gives us a vector perpendicular to our two vectors - var axis = p_basis.y.cross(real_up).normalized() - var correction = Basis(axis, acos(dot)) + # The cross between our two vectors gives us a vector perpendicular to our two vectors. + var axis := p_basis.y.cross(real_up).normalized() + var correction := Basis(axis, acos(dot)) p_basis = correction * p_basis return p_basis -func _process(delta): - # Get our data - var acc = Input.get_accelerometer() - var grav = Input.get_gravity() - var mag = Input.get_magnetometer() - var gyro = Input.get_gyroscope() +func _process(delta: float) -> void: + # Get our data from the engine's sensor readings. + var acc := Input.get_accelerometer() + var grav := Input.get_gravity() + var mag := Input.get_magnetometer() + var gyro := Input.get_gyroscope() - # Show our base values - var format = "%.05f" + # Show our base values. + var format := "%.05f" %AccX.text = format % acc.x %AccY.text = format % acc.y @@ -122,37 +121,38 @@ func _process(delta): %GyroY.text = format % gyro.y %GyroZ.text = format % gyro.z - # Check if we have all needed data + # Check if we have all needed data. if grav.length() < 0.1: if acc.length() < 0.1: - # we don't have either... + # We don't have either... grav = Vector3(0.0, -1.0, 0.0) else: # The gravity vector is calculated by the OS by combining the other sensor inputs. - # If we don't have a gravity vector, from now on, use accelerometer... + # If we don't have a gravity vector, from now on, use the accelerometer... grav = acc if mag.length() < 0.1: mag = Vector3(1.0, 0.0, 0.0) - # Update our arrow showing gravity + # Update our arrow showing gravity. $Arrows/AccelerometerArrow.transform.basis = get_basis_for_arrow(grav) - # Update our arrow showing our magnetometer - # Note that in absence of other strong magnetic forces this will point to magnetic north, which is not horizontal thanks to the earth being, uhm, round + # Update our arrow showing our magnetometer. + # Note that in absence of other strong magnetic forces this will point to magnetic north, + # which is not horizontal thanks to the earth being round. $Arrows/MagnetoArrow.transform.basis = get_basis_for_arrow(mag) - # Calculate our north vector and show that - var north = calc_north(grav, mag) + # Calculate our north vector and show that. + var north := calc_north(grav, mag) $Arrows/NorthArrow.transform.basis = get_basis_for_arrow(north) # Combine our magnetometer and gravity vector to position our box. This will be fairly accurate # but our magnetometer can be easily influenced by magnets. Cheaper phones often don't have gyros # so it is a good backup. - var mag_and_grav = $Boxes/MagAndGrav + var mag_and_grav: MeshInstance3D = $Boxes/MagAndGrav mag_and_grav.transform.basis = orientate_by_mag_and_grav(mag, grav).orthonormalized() - # Using our gyro and do a drift correction using our gravity vector gives the best result - var gyro_and_grav = $Boxes/GyroAndGrav - var new_basis = rotate_by_gyro(gyro, gyro_and_grav.transform.basis, delta).orthonormalized() + # Using our gyro and do a drift correction using our gravity vector gives the best result. + var gyro_and_grav: MeshInstance3D = $Boxes/GyroAndGrav + var new_basis := rotate_by_gyro(gyro, gyro_and_grav.transform.basis, delta).orthonormalized() gyro_and_grav.transform.basis = drift_correction(new_basis, grav) diff --git a/mobile/sensors/main.tscn b/mobile/sensors/main.tscn index 6440d29f..bca58095 100644 --- a/mobile/sensors/main.tscn +++ b/mobile/sensors/main.tscn @@ -50,8 +50,10 @@ environment = SubResource("1") [node name="Control" type="Control" parent="."] layout_mode = 3 anchors_preset = 0 -offset_right = 1025.0 -offset_bottom = 602.0 +offset_left = 24.0 +offset_top = 24.0 +offset_right = 1049.0 +offset_bottom = 626.0 size_flags_horizontal = 3 size_flags_vertical = 3 diff --git a/mobile/sensors/project.godot b/mobile/sensors/project.godot index a5a6bbe5..2c814f19 100644 --- a/mobile/sensors/project.godot +++ b/mobile/sensors/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://main.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/networking/multiplayer_bomber/bomb.gd b/networking/multiplayer_bomber/bomb.gd index c4d928bb..276b4cf8 100644 --- a/networking/multiplayer_bomber/bomb.gd +++ b/networking/multiplayer_bomber/bomb.gd @@ -4,13 +4,14 @@ var in_area: Array = [] var from_player: int # Called from the animation. -func explode(): +func explode() -> void: if not is_multiplayer_authority(): # Explode only on authority. return - for p in in_area: + + for p: Object in in_area: if p.has_method("exploded"): - # Checks if there is wall in between bomb and the object + # Checks if there is wall in between bomb and the object. var world_state: PhysicsDirectSpaceState2D = get_world_2d().direct_space_state var query := PhysicsRayQueryParameters2D.create(position, p.position) query.hit_from_inside = true @@ -20,15 +21,15 @@ func explode(): p.exploded.rpc(from_player) -func done(): +func done() -> void: if is_multiplayer_authority(): queue_free() -func _on_bomb_body_enter(body): +func _on_bomb_body_enter(body: Node2D) -> void: if not body in in_area: in_area.append(body) -func _on_bomb_body_exit(body): +func _on_bomb_body_exit(body: Node2D) -> void: in_area.erase(body) diff --git a/networking/multiplayer_bomber/bomb.tscn b/networking/multiplayer_bomber/bomb.tscn index c4f81eb5..febc01b2 100644 --- a/networking/multiplayer_bomber/bomb.tscn +++ b/networking/multiplayer_bomber/bomb.tscn @@ -125,10 +125,10 @@ angular_velocity_max = 188.35 scale_amount_curve = SubResource("Curve_4yges") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] -autoplay = "anim" libraries = { "": SubResource("AnimationLibrary_h2w7m") } +autoplay = "anim" [connection signal="body_entered" from="." to="." method="_on_bomb_body_enter"] [connection signal="body_exited" from="." to="." method="_on_bomb_body_exit"] diff --git a/networking/multiplayer_bomber/bomb_spawner.gd b/networking/multiplayer_bomber/bomb_spawner.gd index 62006408..9201f1c7 100644 --- a/networking/multiplayer_bomber/bomb_spawner.gd +++ b/networking/multiplayer_bomber/bomb_spawner.gd @@ -1,13 +1,14 @@ extends MultiplayerSpawner -func _init(): +func _init() -> void: spawn_function = _spawn_bomb -func _spawn_bomb(data): +func _spawn_bomb(data: Array) -> Area2D: if data.size() != 2 or typeof(data[0]) != TYPE_VECTOR2 or typeof(data[1]) != TYPE_INT: return null - var bomb = preload("res://bomb.tscn").instantiate() + + var bomb: Area2D = preload("res://bomb.tscn").instantiate() bomb.position = data[0] bomb.from_player = data[1] return bomb diff --git a/networking/multiplayer_bomber/gamestate.gd b/networking/multiplayer_bomber/gamestate.gd index 299eca44..a89c54b9 100644 --- a/networking/multiplayer_bomber/gamestate.gd +++ b/networking/multiplayer_bomber/gamestate.gd @@ -1,149 +1,156 @@ extends Node # Default game server port. Can be any number between 1024 and 49151. -# Not on the list of registered or common ports as of November 2020: +# Not on the list of registered or common ports as of May 2024: # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers const DEFAULT_PORT = 10567 -# Max number of players. +## The maximum number of players. const MAX_PEERS = 12 -var peer = null +var peer: ENetMultiplayerPeer -# Name for my player. -var player_name = "The Warrior" +## Our local player's name. +var player_name := "The Warrior" # Names for remote players in id:name format. -var players = {} -var players_ready = [] +var players := {} +var players_ready: Array[int] = [] # Signals to let lobby GUI know what's going on. signal player_list_changed() signal connection_failed() signal connection_succeeded() signal game_ended() -signal game_error(what) +signal game_error(what: int) # Callback from SceneTree. -func _player_connected(id): +func _player_connected(id: int) -> void: # Registration of a client beings here, tell the connected player that we are here. register_player.rpc_id(id, player_name) # Callback from SceneTree. -func _player_disconnected(id): - if has_node("/root/World"): # Game is in progress. +func _player_disconnected(id: int) -> void: + if has_node("/root/World"): + # Game is in progress. if multiplayer.is_server(): game_error.emit("Player " + players[id] + " disconnected") end_game() - else: # Game is not in progress. + else: + # Game is not in progress. # Unregister this player. unregister_player(id) # Callback from SceneTree, only for clients (not server). -func _connected_ok(): +func _connected_ok() -> void: # We just connected to a server connection_succeeded.emit() # Callback from SceneTree, only for clients (not server). -func _server_disconnected(): +func _server_disconnected() -> void: game_error.emit("Server disconnected") end_game() # Callback from SceneTree, only for clients (not server). -func _connected_fail(): +func _connected_fail() -> void: multiplayer.set_network_peer(null) # Remove peer connection_failed.emit() # Lobby management functions. @rpc("any_peer") -func register_player(new_player_name): - var id = multiplayer.get_remote_sender_id() +func register_player(new_player_name: String) -> void: + var id := multiplayer.get_remote_sender_id() players[id] = new_player_name player_list_changed.emit() -func unregister_player(id): +func unregister_player(id: int) -> void: players.erase(id) player_list_changed.emit() @rpc("call_local") -func load_world(): +func load_world() -> void: # Change scene. - var world = load("res://world.tscn").instantiate() + var world: Node2D = load("res://world.tscn").instantiate() get_tree().get_root().add_child(world) get_tree().get_root().get_node("Lobby").hide() # Set up score. world.get_node("Score").add_player(multiplayer.get_unique_id(), player_name) - for pn in players: + for pn: int in players: world.get_node("Score").add_player(pn, players[pn]) - get_tree().set_pause(false) # Unpause and unleash the game! + + # Unpause and unleash the game! + get_tree().paused = false -func host_game(new_player_name): +func host_game(new_player_name: String) -> void: player_name = new_player_name peer = ENetMultiplayerPeer.new() peer.create_server(DEFAULT_PORT, MAX_PEERS) multiplayer.set_multiplayer_peer(peer) -func join_game(ip, new_player_name): +func join_game(ip: String, new_player_name: String) -> void: player_name = new_player_name peer = ENetMultiplayerPeer.new() peer.create_client(ip, DEFAULT_PORT) multiplayer.set_multiplayer_peer(peer) -func get_player_list(): +func get_player_list() -> Array: return players.values() -func get_player_name(): - return player_name - - -func begin_game(): +func begin_game() -> void: assert(multiplayer.is_server()) load_world.rpc() - var world = get_tree().get_root().get_node("World") - var player_scene = load("res://player.tscn") + var world: Node2D = get_tree().get_root().get_node("World") + var player_scene: PackedScene = load("res://player.tscn") - # Create a dictionary with peer id and respective spawn points, could be improved by randomizing. - var spawn_points = {} - spawn_points[1] = 0 # Server in spawn point 0. - var spawn_point_idx = 1 - for p in players: + # Create a dictionary with peer ID. and respective spawn points. + # TODO: This could be improved by randomizing spawn points for players. + var spawn_points := {} + spawn_points[1] = 0 # Server in spawn point 0. + var spawn_point_idx := 1 + for p: int in players: spawn_points[p] = spawn_point_idx spawn_point_idx += 1 - for p_id in spawn_points: - var spawn_pos = world.get_node("SpawnPoints/" + str(spawn_points[p_id])).position - var player = player_scene.instantiate() + for p_id: int in spawn_points: + var spawn_pos: Vector2 = world.get_node("SpawnPoints/" + str(spawn_points[p_id])).position + var player := player_scene.instantiate() player.synced_position = spawn_pos player.name = str(p_id) - player.set_player_name(player_name if p_id == multiplayer.get_unique_id() else players[p_id]) world.get_node("Players").add_child(player) + # The RPC must be called after the player is added to the scene tree. + player.set_player_name.rpc(player_name if p_id == multiplayer.get_unique_id() else players[p_id]) -func end_game(): - if has_node("/root/World"): # Game is in progress. - # End it +func end_game() -> void: + if has_node("/root/World"): + # If the game is in progress, end it. get_node("/root/World").queue_free() game_ended.emit() players.clear() -func _ready(): +func _ready() -> void: multiplayer.peer_connected.connect(_player_connected) multiplayer.peer_disconnected.connect(_player_disconnected) multiplayer.connected_to_server.connect(_connected_ok) multiplayer.connection_failed.connect(_connected_fail) multiplayer.server_disconnected.connect(_server_disconnected) + + +## Returns an unique-looking player color based on the name's hash. +func get_player_color(p_name: String) -> Color: + return Color.from_hsv(wrapf(p_name.hash() * 0.001, 0.0, 1.0), 0.6, 1.0) diff --git a/networking/multiplayer_bomber/lobby.gd b/networking/multiplayer_bomber/lobby.gd index 90ed898f..a31c94f8 100644 --- a/networking/multiplayer_bomber/lobby.gd +++ b/networking/multiplayer_bomber/lobby.gd @@ -1,6 +1,6 @@ extends Control -func _ready(): +func _ready() -> void: # Called every time the node is added to the scene. gamestate.connection_failed.connect(_on_connection_failed) gamestate.connection_succeeded.connect(_on_connection_success) @@ -11,11 +11,11 @@ func _ready(): if OS.has_environment("USERNAME"): $Connect/Name.text = OS.get_environment("USERNAME") else: - var desktop_path = OS.get_system_dir(0).replace("\\", "/").split("/") + var desktop_path := OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP).replace("\\", "/").split("/") $Connect/Name.text = desktop_path[desktop_path.size() - 2] -func _on_host_pressed(): +func _on_host_pressed() -> void: if $Connect/Name.text == "": $Connect/ErrorLabel.text = "Invalid name!" return @@ -24,17 +24,18 @@ func _on_host_pressed(): $Players.show() $Connect/ErrorLabel.text = "" - var player_name = $Connect/Name.text + var player_name: String = $Connect/Name.text gamestate.host_game(player_name) + get_window().title = ProjectSettings.get_setting("application/config/name") + ": Server (%s)" % $Connect/Name.text refresh_lobby() -func _on_join_pressed(): +func _on_join_pressed() -> void: if $Connect/Name.text == "": $Connect/ErrorLabel.text = "Invalid name!" return - var ip = $Connect/IPAddress.text + var ip: String = $Connect/IPAddress.text if not ip.is_valid_ip_address(): $Connect/ErrorLabel.text = "Invalid IP address!" return @@ -43,22 +44,23 @@ func _on_join_pressed(): $Connect/Host.disabled = true $Connect/Join.disabled = true - var player_name = $Connect/Name.text + var player_name: String = $Connect/Name.text gamestate.join_game(ip, player_name) + get_window().title = ProjectSettings.get_setting("application/config/name") + ": Client (%s)" % $Connect/Name.text -func _on_connection_success(): +func _on_connection_success() -> void: $Connect.hide() $Players.show() -func _on_connection_failed(): +func _on_connection_failed() -> void: $Connect/Host.disabled = false $Connect/Join.disabled = false $Connect/ErrorLabel.set_text("Connection failed.") -func _on_game_ended(): +func _on_game_ended() -> void: show() $Connect.show() $Players.hide() @@ -66,27 +68,27 @@ func _on_game_ended(): $Connect/Join.disabled = false -func _on_game_error(errtxt): +func _on_game_error(errtxt: String) -> void: $ErrorDialog.dialog_text = errtxt $ErrorDialog.popup_centered() $Connect/Host.disabled = false $Connect/Join.disabled = false -func refresh_lobby(): - var players = gamestate.get_player_list() +func refresh_lobby() -> void: + var players := gamestate.get_player_list() players.sort() $Players/List.clear() - $Players/List.add_item(gamestate.get_player_name() + " (You)") - for p in players: + $Players/List.add_item(gamestate.player_name + " (you)") + for p: String in players: $Players/List.add_item(p) $Players/Start.disabled = not multiplayer.is_server() -func _on_start_pressed(): +func _on_start_pressed() -> void: gamestate.begin_game() -func _on_find_public_ip_pressed(): +func _on_find_public_ip_pressed() -> void: OS.shell_open("https://icanhazip.com/") diff --git a/networking/multiplayer_bomber/player.gd b/networking/multiplayer_bomber/player.gd index b332fc76..cd4e3fae 100644 --- a/networking/multiplayer_bomber/player.gd +++ b/networking/multiplayer_bomber/player.gd @@ -1,27 +1,28 @@ extends CharacterBody2D +## The player's movement speed (in pixels per second). const MOTION_SPEED = 90.0 + +## The delay before which you can place a new bomb (in seconds). const BOMB_RATE = 0.5 -@export -var synced_position := Vector2() +@export var synced_position := Vector2() -@export -var stunned = false +@export var stunned := false -@onready -var inputs = $Inputs -var last_bomb_time = BOMB_RATE -var current_anim = "" +var last_bomb_time := BOMB_RATE +var current_anim := "" -func _ready(): +@onready var inputs: Node = $Inputs + +func _ready() -> void: stunned = false position = synced_position if str(name).is_valid_int(): - get_node("Inputs/InputsSync").set_multiplayer_authority(str(name).to_int()) + $"Inputs/InputsSync".set_multiplayer_authority(str(name).to_int()) -func _physics_process(delta): +func _physics_process(delta: float) -> void: if multiplayer.multiplayer_peer == null or str(multiplayer.get_unique_id()) == str(name): # The client which this player represent will update the controls state, and notify it to everyone. inputs.update() @@ -33,43 +34,48 @@ func _physics_process(delta): last_bomb_time += delta if not stunned and is_multiplayer_authority() and inputs.bombing and last_bomb_time >= BOMB_RATE: last_bomb_time = 0.0 - get_node("../../BombSpawner").spawn([position, str(name).to_int()]) + $"../../BombSpawner".spawn([position, str(name).to_int()]) else: # The client simply updates the position to the last known one. position = synced_position if not stunned: - # Everybody runs physics. I.e. clients tries to predict where they will be during the next frame. + # Everybody runs physics. i.e. clients try to predict where they will be during the next frame. velocity = inputs.motion * MOTION_SPEED move_and_slide() - # Also update the animation based on the last known player input state - var new_anim = "standing" + # Also update the animation based on the last known player input state. + var new_anim := &"standing" if inputs.motion.y < 0: - new_anim = "walk_up" + new_anim = &"walk_up" elif inputs.motion.y > 0: - new_anim = "walk_down" + new_anim = &"walk_down" elif inputs.motion.x < 0: - new_anim = "walk_left" + new_anim = &"walk_left" elif inputs.motion.x > 0: - new_anim = "walk_right" + new_anim = &"walk_right" if stunned: - new_anim = "stunned" + new_anim = &"stunned" if new_anim != current_anim: current_anim = new_anim - get_node("anim").play(current_anim) - - -func set_player_name(value): - get_node("label").text = value + $anim.play(current_anim) @rpc("call_local") -func exploded(_by_who): +func set_player_name(value: String) -> void: + $label.text = value + # Assign a random color to the player based on its name. + $label.modulate = gamestate.get_player_color(value) + $sprite.modulate = Color(0.5, 0.5, 0.5) + gamestate.get_player_color(value) + + +@rpc("call_local") +func exploded(_by_who: int) -> void: if stunned: return + stunned = true - get_node("anim").play("stunned") + $anim.play("stunned") diff --git a/networking/multiplayer_bomber/player.tscn b/networking/multiplayer_bomber/player.tscn index be336f0a..ab541cc2 100644 --- a/networking/multiplayer_bomber/player.tscn +++ b/networking/multiplayer_bomber/player.tscn @@ -6,7 +6,7 @@ [ext_resource type="Script" path="res://player_controls.gd" id="4_k1vfr"] [sub_resource type="CircleShape2D" id="1"] -radius = 20.0 +radius = 16.0 [sub_resource type="Animation" id="2"] resource_name = "standing" @@ -149,22 +149,18 @@ outline_color = Color(0, 0, 0, 1) [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_sh64w"] properties/0/path = NodePath(".:synced_position") properties/0/spawn = true -properties/0/sync = true -properties/0/watch = false +properties/0/replication_mode = 1 properties/1/path = NodePath("label:text") properties/1/spawn = true -properties/1/sync = false -properties/1/watch = false +properties/1/replication_mode = 0 [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_w53uu"] properties/0/path = NodePath(".:motion") properties/0/spawn = true -properties/0/sync = true -properties/0/watch = false +properties/0/replication_mode = 1 properties/1/path = NodePath(".:bombing") properties/1/spawn = true -properties/1/sync = true -properties/1/watch = false +properties/1/replication_mode = 1 [node name="player" type="CharacterBody2D"] z_index = 10 diff --git a/networking/multiplayer_bomber/player_controls.gd b/networking/multiplayer_bomber/player_controls.gd index e232af36..f5724d14 100644 --- a/networking/multiplayer_bomber/player_controls.gd +++ b/networking/multiplayer_bomber/player_controls.gd @@ -1,24 +1,22 @@ extends Node -@export -var motion = Vector2(): +@export var motion := Vector2(): set(value): # This will be sent by players, make sure values are within limits. motion = clamp(value, Vector2(-1, -1), Vector2(1, 1)) -@export -var bombing = false +@export var bombing := false -func update(): - var m = Vector2() - if Input.is_action_pressed("move_left"): +func update() -> void: + var m := Vector2() + if Input.is_action_pressed(&"move_left"): m += Vector2(-1, 0) - if Input.is_action_pressed("move_right"): + if Input.is_action_pressed(&"move_right"): m += Vector2(1, 0) - if Input.is_action_pressed("move_up"): + if Input.is_action_pressed(&"move_up"): m += Vector2(0, -1) - if Input.is_action_pressed("move_down"): + if Input.is_action_pressed(&"move_down"): m += Vector2(0, 1) motion = m - bombing = Input.is_action_pressed("set_bomb") + bombing = Input.is_action_pressed(&"set_bomb") diff --git a/networking/multiplayer_bomber/project.godot b/networking/multiplayer_bomber/project.godot index 759adb14..3fc15b9a 100644 --- a/networking/multiplayer_bomber/project.godot +++ b/networking/multiplayer_bomber/project.godot @@ -23,6 +23,10 @@ config/icon="res://icon.webp" gamestate="*res://gamestate.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" @@ -75,6 +79,8 @@ set_bomb={ renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" +2d/snap/snap_2d_transforms_to_pixel=true +2d/snap/snap_2d_vertices_to_pixel=true [replication] diff --git a/networking/multiplayer_bomber/rock.gd b/networking/multiplayer_bomber/rock.gd index b2a86c03..9dad5efc 100644 --- a/networking/multiplayer_bomber/rock.gd +++ b/networking/multiplayer_bomber/rock.gd @@ -1,6 +1,6 @@ extends CharacterBody2D @rpc("call_local") -func exploded(by_who): +func exploded(by_who: int) -> void: $"../../Score".increase_score(by_who) $"AnimationPlayer".play("explode") diff --git a/networking/multiplayer_bomber/score.gd b/networking/multiplayer_bomber/score.gd index 13584278..348389ea 100644 --- a/networking/multiplayer_bomber/score.gd +++ b/networking/multiplayer_bomber/score.gd @@ -1,13 +1,13 @@ extends HBoxContainer -var player_labels = {} +var player_labels := {} -func _process(_delta): - var rocks_left = $"../Rocks".get_child_count() +func _process(_delta: float) -> void: + var rocks_left := $"../Rocks".get_child_count() if rocks_left == 0: - var winner_name = "" - var winner_score = 0 - for p in player_labels: + var winner_name := "" + var winner_score := 0 + for p: int in player_labels: if player_labels[p].score > winner_score: winner_score = player_labels[p].score winner_name = player_labels[p].name @@ -16,30 +16,36 @@ func _process(_delta): $"../Winner".show() -func increase_score(for_who): +func increase_score(for_who: int) -> void: assert(for_who in player_labels) - var pl = player_labels[for_who] + + var pl: Dictionary = player_labels[for_who] pl.score += 1 pl.label.set_text(pl.name + "\n" + str(pl.score)) -func add_player(id, new_player_name): - var l = Label.new() - l.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER - l.set_text(new_player_name + "\n" + "0") - l.set_h_size_flags(SIZE_EXPAND_FILL) - var font = preload("res://montserrat.otf") - l.set("custom_fonts/font", font) - l.set("custom_font_size/font_size", 18) - add_child(l) +func add_player(id: int, new_player_name: String) -> void: + var label := Label.new() + label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + label.text = new_player_name + "\n" + "0" + label.modulate = gamestate.get_player_color(new_player_name) + label.size_flags_horizontal = SIZE_EXPAND_FILL + label.add_theme_font_override("font", preload("res://montserrat.otf")) + label.add_theme_color_override("font_outline_color", Color.BLACK) + label.add_theme_constant_override("outline_size", 9) + label.add_theme_font_size_override("font_size", 18) + add_child(label) - player_labels[id] = { name = new_player_name, label = l, score = 0 } + player_labels[id] = { + name = new_player_name, + label = label, + score = 0, + } -func _ready(): +func _ready() -> void: $"../Winner".hide() - set_process(true) -func _on_exit_game_pressed(): +func _on_exit_game_pressed() -> void: gamestate.end_game() diff --git a/networking/multiplayer_bomber/world.tscn b/networking/multiplayer_bomber/world.tscn index 6a867c5b..f5063b64 100644 --- a/networking/multiplayer_bomber/world.tscn +++ b/networking/multiplayer_bomber/world.tscn @@ -10,7 +10,7 @@ [node name="TileMap" type="TileMap" parent="."] tile_set = ExtResource("1") -cell_quadrant_size = 48 +rendering_quadrant_size = 48 format = 2 layer_0/tile_data = PackedInt32Array(0, 0, 0, 65536, 0, 0, 131072, 0, 0, 196608, 0, 0, 262144, 0, 0, 327680, 0, 0, 393216, 0, 0, 458752, 0, 0, 524288, 0, 0, 589824, 0, 0, 655360, 0, 0, 720896, 0, 0, 786432, 0, 0, 1, 0, 0, 65537, 65536, 0, 131073, 65536, 0, 196609, 65536, 0, 262145, 65536, 0, 327681, 65536, 0, 393217, 65536, 0, 458753, 65536, 0, 524289, 65536, 0, 589825, 65536, 0, 655361, 65536, 0, 720897, 65536, 0, 786433, 0, 0, 2, 0, 0, 65538, 65536, 0, 131074, 0, 0, 196610, 65536, 0, 262146, 0, 0, 327682, 65536, 0, 393218, 0, 0, 458754, 65536, 0, 524290, 0, 0, 589826, 65536, 0, 655362, 0, 0, 720898, 65536, 0, 786434, 0, 0, 3, 0, 0, 65539, 65536, 0, 131075, 65536, 0, 196611, 65536, 0, 262147, 65536, 0, 327683, 65536, 0, 393219, 65536, 0, 458755, 65536, 0, 524291, 0, 0, 589827, 65536, 0, 655363, 65536, 0, 720899, 65536, 0, 786435, 0, 0, 4, 0, 0, 65540, 65536, 0, 131076, 0, 0, 196612, 0, 0, 262148, 0, 0, 327684, 65536, 0, 393220, 0, 0, 458756, 65536, 0, 524292, 0, 0, 589828, 65536, 0, 655364, 0, 0, 720900, 65536, 0, 786436, 0, 0, 5, 0, 0, 65541, 65536, 0, 131077, 65536, 0, 196613, 65536, 0, 262149, 65536, 0, 327685, 65536, 0, 393221, 65536, 0, 458757, 65536, 0, 524293, 65536, 0, 589829, 65536, 0, 655365, 65536, 0, 720901, 65536, 0, 786437, 0, 0, 6, 0, 0, 65542, 65536, 0, 131078, 0, 0, 196614, 65536, 0, 262150, 0, 0, 327686, 0, 0, 393222, 0, 0, 458758, 65536, 0, 524294, 0, 0, 589830, 65536, 0, 655366, 0, 0, 720902, 65536, 0, 786438, 0, 0, 7, 0, 0, 65543, 65536, 0, 131079, 65536, 0, 196615, 65536, 0, 262151, 65536, 0, 327687, 65536, 0, 393223, 65536, 0, 458759, 65536, 0, 524295, 65536, 0, 589831, 65536, 0, 655367, 65536, 0, 720903, 65536, 0, 786439, 0, 0, 8, 0, 0, 65544, 65536, 0, 131080, 0, 0, 196616, 65536, 0, 262152, 0, 0, 327688, 65536, 0, 393224, 0, 0, 458760, 65536, 0, 524296, 0, 0, 589832, 65536, 0, 655368, 0, 0, 720904, 65536, 0, 786440, 0, 0, 9, 0, 0, 65545, 65536, 0, 131081, 65536, 0, 196617, 65536, 0, 262153, 65536, 0, 327689, 65536, 0, 393225, 65536, 0, 458761, 65536, 0, 524297, 65536, 0, 589833, 65536, 0, 655369, 65536, 0, 720905, 65536, 0, 786441, 0, 0, 10, 0, 0, 65546, 65536, 0, 131082, 0, 0, 196618, 0, 0, 262154, 0, 0, 327690, 65536, 0, 393226, 0, 0, 458762, 65536, 0, 524298, 0, 0, 589834, 65536, 0, 655370, 0, 0, 720906, 65536, 0, 786442, 0, 0, 11, 0, 0, 65547, 65536, 0, 131083, 0, 0, 196619, 65536, 0, 262155, 65536, 0, 327691, 65536, 0, 393227, 65536, 0, 458763, 65536, 0, 524299, 65536, 0, 589835, 65536, 0, 655371, 65536, 0, 720907, 65536, 0, 786443, 0, 0, 12, 0, 0, 65548, 65536, 0, 131084, 0, 0, 196620, 65536, 0, 262156, 0, 0, 327692, 65536, 0, 393228, 0, 0, 458764, 65536, 0, 524300, 0, 0, 589836, 65536, 0, 655372, 0, 0, 720908, 65536, 0, 786444, 0, 0, 13, 0, 0, 65549, 65536, 0, 131085, 0, 0, 196621, 65536, 0, 262157, 65536, 0, 327693, 65536, 0, 393229, 0, 0, 458765, 65536, 0, 524301, 0, 0, 589837, 65536, 0, 655373, 65536, 0, 720909, 65536, 0, 786445, 0, 0, 14, 0, 0, 65550, 65536, 0, 131086, 0, 0, 196622, 65536, 0, 262158, 0, 0, 327694, 65536, 0, 393230, 0, 0, 458766, 65536, 0, 524302, 0, 0, 589838, 65536, 0, 655374, 0, 0, 720910, 65536, 0, 786446, 0, 0, 15, 0, 0, 65551, 65536, 0, 131087, 65536, 0, 196623, 65536, 0, 262159, 65536, 0, 327695, 65536, 0, 393231, 0, 0, 458767, 65536, 0, 524303, 65536, 0, 589839, 65536, 0, 655375, 65536, 0, 720911, 65536, 0, 786447, 0, 0, 16, 0, 0, 65552, 65536, 0, 131088, 0, 0, 196624, 65536, 0, 262160, 0, 0, 327696, 65536, 0, 393232, 0, 0, 458768, 65536, 0, 524304, 0, 0, 589840, 65536, 0, 655376, 0, 0, 720912, 65536, 0, 786448, 0, 0, 17, 0, 0, 65553, 65536, 0, 131089, 65536, 0, 196625, 65536, 0, 262161, 65536, 0, 327697, 65536, 0, 393233, 65536, 0, 458769, 65536, 0, 524305, 65536, 0, 589841, 65536, 0, 655377, 65536, 0, 720913, 65536, 0, 786449, 0, 0, 18, 0, 0, 65554, 65536, 0, 131090, 0, 0, 196626, 65536, 0, 262162, 0, 0, 327698, 0, 0, 393234, 0, 0, 458770, 65536, 0, 524306, 0, 0, 589842, 65536, 0, 655378, 0, 0, 720914, 65536, 0, 786450, 0, 0, 19, 0, 0, 65555, 65536, 0, 131091, 65536, 0, 196627, 65536, 0, 262163, 65536, 0, 327699, 65536, 0, 393235, 65536, 0, 458771, 65536, 0, 524307, 65536, 0, 589843, 65536, 0, 655379, 65536, 0, 720915, 65536, 0, 786451, 0, 0, 20, 0, 0, 65556, 0, 0, 131092, 0, 0, 196628, 0, 0, 262164, 0, 0, 327700, 0, 0, 393236, 0, 0, 458772, 0, 0, 524308, 0, 0, 589844, 0, 0, 655380, 0, 0, 720916, 0, 0, 786452, 0, 0, 21, 0, 0, 65557, 0, 0, 131093, 0, 0, 196629, 0, 0, 262165, 0, 0, 327701, 0, 0, 393237, 0, 0, 458773, 0, 0, 524309, 0, 0, 589845, 0, 0, 655381, 0, 0, 720917, 0, 0, 786453, 0, 0) @@ -266,6 +266,11 @@ position = Vector2(840, 456) [node name="Players" type="Node2D" parent="."] +[node name="ColorRect" type="ColorRect" parent="."] +offset_right = 1056.0 +offset_bottom = 48.0 +color = Color(0, 0, 0, 0.501961) + [node name="Score" type="HBoxContainer" parent="."] offset_right = 1024.0 offset_bottom = 40.0 @@ -298,7 +303,6 @@ text = "EXIT GAME" [node name="Camera2D" type="Camera2D" parent="."] offset = Vector2(512, 300) -current = true [node name="PlayerSpawner" type="MultiplayerSpawner" parent="."] _spawnable_scenes = PackedStringArray("res://player.tscn") diff --git a/networking/multiplayer_pong/logic/ball.gd b/networking/multiplayer_pong/logic/ball.gd index 5e025a4e..714c2a28 100644 --- a/networking/multiplayer_pong/logic/ball.gd +++ b/networking/multiplayer_pong/logic/ball.gd @@ -1,14 +1,14 @@ extends Area2D -const DEFAULT_SPEED = 100 +const DEFAULT_SPEED = 100.0 -var direction = Vector2.LEFT -var stopped = false -var _speed = DEFAULT_SPEED +var direction := Vector2.LEFT +var stopped := false +var _speed := DEFAULT_SPEED -@onready var _screen_size = get_viewport_rect().size +@onready var _screen_size := get_viewport_rect().size -func _process(delta): +func _process(delta: float) -> void: _speed += delta # Ball will move normally for both players, # even if it's sightly out of sync between them, @@ -17,24 +17,24 @@ func _process(delta): translate(_speed * delta * direction) # Check screen bounds to make ball bounce. - var ball_pos = position + var ball_pos := position if (ball_pos.y < 0 and direction.y < 0) or (ball_pos.y > _screen_size.y and direction.y > 0): direction.y = -direction.y if is_multiplayer_authority(): # Only the master will decide when the ball is out in - # the left side (it's own side). This makes the game + # the left side (its own side). This makes the game # playable even if latency is high and ball is going - # fast. Otherwise ball might be out in the other + # fast. Otherwise, the ball might be out in the other # player's screen but not this one. if ball_pos.x < 0: get_parent().update_score.rpc(false) _reset_ball.rpc(false) else: # Only the puppet will decide when the ball is out in - # the right side, which is it's own side. This makes + # the right side, which is its own side. This makes # the game playable even if latency is high and ball - # is going fast. Otherwise ball might be out in the + # is going fast. Otherwise, the ball might be out in the # other player's screen but not this one. if ball_pos.x > _screen_size.x: get_parent().update_score.rpc(true) @@ -42,7 +42,7 @@ func _process(delta): @rpc("any_peer", "call_local") -func bounce(left, random): +func bounce(left: bool, random: float) -> void: # Using sync because both players can make it bounce. if left: direction.x = abs(direction.x) @@ -55,12 +55,12 @@ func bounce(left, random): @rpc("any_peer", "call_local") -func stop(): +func stop() -> void: stopped = true @rpc("any_peer", "call_local") -func _reset_ball(for_left): +func _reset_ball(for_left: float) -> void: position = _screen_size / 2 if for_left: direction = Vector2.LEFT diff --git a/networking/multiplayer_pong/logic/lobby.gd b/networking/multiplayer_pong/logic/lobby.gd index ba984386..4957bb09 100644 --- a/networking/multiplayer_pong/logic/lobby.gd +++ b/networking/multiplayer_pong/logic/lobby.gd @@ -1,21 +1,21 @@ extends Control # Default game server port. Can be any number between 1024 and 49151. -# Not present on the list of registered or common ports as of December 2022: +# Not present on the list of registered or common ports as of May 2024: # https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers const DEFAULT_PORT = 8910 -@onready var address = $Address -@onready var host_button = $HostButton -@onready var join_button = $JoinButton -@onready var status_ok = $StatusOk -@onready var status_fail = $StatusFail -@onready var port_forward_label = $PortForward -@onready var find_public_ip_button = $FindPublicIP +@onready var address: LineEdit = $Address +@onready var host_button: Button = $HostButton +@onready var join_button: Button = $JoinButton +@onready var status_ok: Label = $StatusOk +@onready var status_fail: Label = $StatusFail +@onready var port_forward_label: Label = $PortForward +@onready var find_public_ip_button: LinkButton = $FindPublicIP -var peer = null +var peer: ENetMultiplayerPeer -func _ready(): +func _ready() -> void: # Connect all the callbacks related to networking. multiplayer.peer_connected.connect(_player_connected) multiplayer.peer_disconnected.connect(_player_disconnected) @@ -23,12 +23,11 @@ func _ready(): multiplayer.connection_failed.connect(_connected_fail) multiplayer.server_disconnected.connect(_server_disconnected) -#### Network callbacks from SceneTree #### - +#region Network callbacks from SceneTree # Callback from SceneTree. -func _player_connected(_id): +func _player_connected(_id: int) -> void: # Someone connected, start the game! - var pong = load("res://pong.tscn").instantiate() + var pong: Node2D = load("res://pong.tscn").instantiate() # Connect deferred so we can safely erase it from the callback. pong.game_finished.connect(_end_game, CONNECT_DEFERRED) @@ -36,49 +35,49 @@ func _player_connected(_id): hide() -func _player_disconnected(_id): +func _player_disconnected(_id: int) -> void: if multiplayer.is_server(): - _end_game("Client disconnected") + _end_game("Client disconnected.") else: - _end_game("Server disconnected") + _end_game("Server disconnected.") # Callback from SceneTree, only for clients (not server). -func _connected_ok(): +func _connected_ok() -> void: pass # This function is not needed for this project. # Callback from SceneTree, only for clients (not server). -func _connected_fail(): +func _connected_fail() -> void: _set_status("Couldn't connect.", false) - multiplayer.set_multiplayer_peer(null) # Remove peer. + multiplayer.set_multiplayer_peer(null) # Remove peer. host_button.set_disabled(false) join_button.set_disabled(false) -func _server_disconnected(): +func _server_disconnected() -> void: _end_game("Server disconnected.") +#endregion -##### Game creation functions ###### - -func _end_game(with_error = ""): +#region Game creation methods +func _end_game(with_error: String = "") -> void: if has_node("/root/Pong"): # Erase immediately, otherwise network might show # errors (this is why we connected deferred above). get_node(^"/root/Pong").free() show() - multiplayer.set_multiplayer_peer(null) # Remove peer. + multiplayer.set_multiplayer_peer(null) # Remove peer. host_button.set_disabled(false) join_button.set_disabled(false) _set_status(with_error, false) -func _set_status(text, isok): +func _set_status(text: String, is_ok: bool) -> void: # Simple way to show status. - if isok: + if is_ok: status_ok.set_text(text) status_fail.set_text("") else: @@ -86,9 +85,10 @@ func _set_status(text, isok): status_fail.set_text(text) -func _on_host_pressed(): +func _on_host_pressed() -> void: peer = ENetMultiplayerPeer.new() - var err = peer.create_server(DEFAULT_PORT, 1) # Maximum of 1 peer, since it's a 2-player game. + # Set a maximum of 1 peer, since Pong is a 2-player game. + var err := peer.create_server(DEFAULT_PORT, 1) if err != OK: # Is another server running? _set_status("Can't host, address in use.",false) @@ -99,14 +99,15 @@ func _on_host_pressed(): host_button.set_disabled(true) join_button.set_disabled(true) _set_status("Waiting for player...", true) + get_window().title = ProjectSettings.get_setting("application/config/name") + ": Server" # Only show hosting instructions when relevant. port_forward_label.visible = true find_public_ip_button.visible = true -func _on_join_pressed(): - var ip = address.get_text() +func _on_join_pressed() -> void: + var ip := address.get_text() if not ip.is_valid_ip_address(): _set_status("IP address is invalid.", false) return @@ -117,7 +118,8 @@ func _on_join_pressed(): multiplayer.set_multiplayer_peer(peer) _set_status("Connecting...", true) + get_window().title = ProjectSettings.get_setting("application/config/name") + ": Client" +#endregion - -func _on_find_public_ip_pressed(): +func _on_find_public_ip_pressed() -> void: OS.shell_open("https://icanhazip.com/") diff --git a/networking/multiplayer_pong/logic/paddle.gd b/networking/multiplayer_pong/logic/paddle.gd index a98916e3..622ad781 100644 --- a/networking/multiplayer_pong/logic/paddle.gd +++ b/networking/multiplayer_pong/logic/paddle.gd @@ -2,14 +2,14 @@ extends Area2D const MOTION_SPEED = 150 -@export var left = false +@export var left := false -var _motion = 0 -var _you_hidden = false +var _motion := 0.0 +var _you_hidden := false -@onready var _screen_size_y = get_viewport_rect().size.y +@onready var _screen_size_y := get_viewport_rect().size.y -func _process(delta): +func _process(delta: float) -> void: # Is the master of the paddle. if is_multiplayer_authority(): _motion = Input.get_axis(&"move_up", &"move_down") @@ -26,25 +26,25 @@ func _process(delta): if not _you_hidden: _hide_you_label() - translate(Vector2(0, _motion * delta)) + translate(Vector2(0.0, _motion * delta)) # Set screen limits. - position.y = clamp(position.y, 16, _screen_size_y - 16) + position.y = clampf(position.y, 16, _screen_size_y - 16) # Synchronize position and speed to the other peers. @rpc("unreliable") -func set_pos_and_motion(pos, motion): +func set_pos_and_motion(pos: Vector2, motion: float) -> void: position = pos _motion = motion -func _hide_you_label(): +func _hide_you_label() -> void: _you_hidden = true - get_node(^"You").hide() + $You.hide() -func _on_paddle_area_enter(area): +func _on_paddle_area_enter(area: Area2D) -> void: if is_multiplayer_authority(): # Random for new direction generated checked each peer. area.bounce.rpc(left, randf()) diff --git a/networking/multiplayer_pong/logic/pong.gd b/networking/multiplayer_pong/logic/pong.gd index 5f2c7298..988fac91 100644 --- a/networking/multiplayer_pong/logic/pong.gd +++ b/networking/multiplayer_pong/logic/pong.gd @@ -4,16 +4,16 @@ signal game_finished() const SCORE_TO_WIN = 10 -var score_left = 0 -var score_right = 0 +var score_left := 0 +var score_right := 0 -@onready var player2 = $Player2 -@onready var score_left_node = $ScoreLeft -@onready var score_right_node = $ScoreRight -@onready var winner_left = $WinnerLeft -@onready var winner_right = $WinnerRight +@onready var player2: Area2D = $Player2 +@onready var score_left_node: Label = $ScoreLeft +@onready var score_right_node: Label = $ScoreRight +@onready var winner_left: Label = $WinnerLeft +@onready var winner_right: Label = $WinnerRight -func _ready(): +func _ready() -> void: # By default, all nodes in server inherit from master, # while all nodes in clients inherit from puppet. # set_multiplayer_authority is tree-recursive by default. @@ -28,7 +28,7 @@ func _ready(): @rpc("any_peer", "call_local") -func update_score(add_to_left): +func update_score(add_to_left: int) -> void: if add_to_left: score_left += 1 score_left_node.set_text(str(score_left)) @@ -36,7 +36,7 @@ func update_score(add_to_left): score_right += 1 score_right_node.set_text(str(score_right)) - var game_ended = false + var game_ended := false if score_left == SCORE_TO_WIN: winner_left.show() game_ended = true @@ -49,5 +49,5 @@ func update_score(add_to_left): $Ball.stop.rpc() -func _on_exit_game_pressed(): +func _on_exit_game_pressed() -> void: game_finished.emit() diff --git a/networking/multiplayer_pong/pong.tscn b/networking/multiplayer_pong/pong.tscn index 89c147bc..510404b3 100644 --- a/networking/multiplayer_pong/pong.tscn +++ b/networking/multiplayer_pong/pong.tscn @@ -81,7 +81,6 @@ text = "Exit Game" [node name="Camera2D" type="Camera2D" parent="."] offset = Vector2(320, 200) -current = true [connection signal="pressed" from="ExitGame" to="." method="_on_exit_game_pressed"] diff --git a/networking/multiplayer_pong/project.godot b/networking/multiplayer_pong/project.godot index f9a7f42b..336574ea 100644 --- a/networking/multiplayer_pong/project.godot +++ b/networking/multiplayer_pong/project.godot @@ -19,35 +19,38 @@ run/main_scene="res://lobby.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=640 window/size/viewport_height=400 window/stretch/mode="canvas_items" -window/stretch/aspect="expand" +window/stretch/scale_mode="integer" [input] -move_down={ -"deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777234,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":90,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -] -} move_up={ "deadzone": 0.2, -"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":16777232,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) -, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":65,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) -, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":87,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194320,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":122,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":11,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null) +] +} +move_down={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194322,"key_label":0,"unicode":0,"echo":false,"script":null) +, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null) +, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"button_index":12,"pressure":0.0,"pressed":false,"script":null) +, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":1.0,"script":null) ] } [rendering] +textures/canvas_textures/default_texture_filter=0 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" diff --git a/networking/webrtc_minimal/Signaling.gd b/networking/webrtc_minimal/Signaling.gd index 8cfe7a73..3dff924d 100644 --- a/networking/webrtc_minimal/Signaling.gd +++ b/networking/webrtc_minimal/Signaling.gd @@ -1,31 +1,32 @@ # A local signaling server. Add this to autoloads with name "Signaling" (/root/Signaling) extends Node -# We will store the two peers here -var peers = [] +# We will store the two peers here. +var peers: Array[String] = [] -func register(path): +func register(path: String) -> void: assert(peers.size() < 2) - peers.append(path) + peers.push_back(path) if peers.size() == 2: get_node(peers[0]).peer.create_offer() -func _find_other(path): +func _find_other(path: String) -> String: # Find the other registered peer. for p in peers: if p != path: return p + return "" -func send_session(path, type, sdp): - var other = _find_other(path) - assert(other != "") +func send_session(path: String, type: String, sdp: String) -> void: + var other := _find_other(path) + assert(not other.is_empty()) get_node(other).peer.set_remote_description(type, sdp) -func send_candidate(path, mid, index, sdp): - var other = _find_other(path) - assert(other != "") - get_node(other).peer.add_ice_candidate(mid, index, sdp) +func send_candidate(path: String, media: String, index: int, sdp: String) -> void: + var other := _find_other(path) + assert(not other.is_empty()) + get_node(other).peer.add_ice_candidate(media, index, sdp) diff --git a/networking/webrtc_minimal/chat.gd b/networking/webrtc_minimal/chat.gd index 032f8dae..fa975c9c 100644 --- a/networking/webrtc_minimal/chat.gd +++ b/networking/webrtc_minimal/chat.gd @@ -1,12 +1,12 @@ extends Node -# An example p2p chat client. +# An example peer-to-peer chat client. -var peer = WebRTCPeerConnection.new() +var peer := WebRTCPeerConnection.new() # Create negotiated data channel. var channel = peer.create_data_channel("chat", {"negotiated": true, "id": 1}) -func _ready(): +func _ready() -> void: # Connect all functions. peer.ice_candidate_created.connect(_on_ice_candidate) peer.session_description_created.connect(_on_session) @@ -15,19 +15,19 @@ func _ready(): Signaling.register(String(get_path())) -func _on_ice_candidate(mid, index, sdp): - # Send the ICE candidate to the other peer via signaling server. - Signaling.send_candidate(String(get_path()), mid, index, sdp) +func _on_ice_candidate(media: String, index: int, sdp: String) -> void: + # Send the ICE candidate to the other peer via the signaling server. + Signaling.send_candidate(String(get_path()), media, index, sdp) -func _on_session(type, sdp): - # Send the session to other peer via signaling server. +func _on_session(type: String, sdp: String) -> void: + # Send the session to other peer via the signaling server. Signaling.send_session(String(get_path()), type, sdp) # Set generated description as local. peer.set_local_description(type, sdp) -func _process(delta): +func _process(delta: float) -> void: # Always poll the connection frequently. peer.poll() if channel.get_ready_state() == WebRTCDataChannel.STATE_OPEN: @@ -35,5 +35,5 @@ func _process(delta): print(String(get_path()), " received: ", channel.get_packet().get_string_from_utf8()) -func send_message(message): +func send_message(message: String) -> void: channel.put_packet(message.to_utf8_buffer()) diff --git a/networking/webrtc_minimal/link_button.gd b/networking/webrtc_minimal/link_button.gd index be300b95..bef662d5 100644 --- a/networking/webrtc_minimal/link_button.gd +++ b/networking/webrtc_minimal/link_button.gd @@ -1,4 +1,4 @@ extends LinkButton -func _on_LinkButton_pressed(): +func _on_LinkButton_pressed() -> void: OS.shell_open("https://github.com/godotengine/webrtc-native/releases") diff --git a/networking/webrtc_minimal/main.gd b/networking/webrtc_minimal/main.gd index 9f1dde39..6b0b9490 100644 --- a/networking/webrtc_minimal/main.gd +++ b/networking/webrtc_minimal/main.gd @@ -2,16 +2,16 @@ extends Node const Chat = preload("res://chat.gd") -func _ready(): - var p1 = Chat.new() - var p2 = Chat.new() +func _ready() -> void: + var p1 := Chat.new() + var p2 := Chat.new() add_child(p1) add_child(p2) - # Wait a second and send message from P1 - await get_tree().create_timer(1).timeout + # Wait a second and send message from P1. + await get_tree().create_timer(1.0).timeout p1.send_message("Hi from %s" % String(p1.get_path())) - # Wait a second and send message from P2 - await get_tree().create_timer(1).timeout + # Wait a second and send message from P2. + await get_tree().create_timer(1.0).timeout p2.send_message("Hi from %s" % String(p2.get_path())) diff --git a/networking/webrtc_minimal/minimal.gd b/networking/webrtc_minimal/minimal.gd index 5311ad83..e573d44b 100644 --- a/networking/webrtc_minimal/minimal.gd +++ b/networking/webrtc_minimal/minimal.gd @@ -2,13 +2,13 @@ extends Node # Main scene. # Create the two peers. -var p1 = WebRTCPeerConnection.new() -var p2 = WebRTCPeerConnection.new() -var ch1 = p1.create_data_channel("chat", {"id": 1, "negotiated": true}) -var ch2 = p2.create_data_channel("chat", {"id": 1, "negotiated": true}) +var p1 := WebRTCPeerConnection.new() +var p2 := WebRTCPeerConnection.new() +var ch1 := p1.create_data_channel("chat", { "id": 1, "negotiated": true }) +var ch2 := p2.create_data_channel("chat", { "id": 1, "negotiated": true }) -func _ready(): - print(p1.create_data_channel("chat", {"id": 1, "negotiated": true})) +func _ready() -> void: + print(p1.create_data_channel("chat", { "id": 1, "negotiated": true })) # Connect P1 session created to itself to set local description. p1.session_description_created.connect(p1.set_local_description) # Connect P1 session and ICE created to p2 set remote description and candidates. @@ -32,7 +32,7 @@ func _ready(): ch2.put_packet("Hi from P2".to_utf8_buffer()) -func _process(delta): +func _process(delta: float) -> void: p1.poll() p2.poll() if ch1.get_ready_state() == ch1.STATE_OPEN and ch1.get_available_packet_count() > 0: diff --git a/networking/webrtc_minimal/project.godot b/networking/webrtc_minimal/project.godot index 1e687e3d..0aaaab82 100644 --- a/networking/webrtc_minimal/project.godot +++ b/networking/webrtc_minimal/project.godot @@ -20,6 +20,10 @@ config/features=PackedStringArray("4.2") Signaling="*res://Signaling.gd" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/networking/webrtc_signaling/client/multiplayer_client.gd b/networking/webrtc_signaling/client/multiplayer_client.gd index 854d987a..b22a99bb 100644 --- a/networking/webrtc_signaling/client/multiplayer_client.gd +++ b/networking/webrtc_signaling/client/multiplayer_client.gd @@ -1,9 +1,9 @@ extends "ws_webrtc_client.gd" -var rtc_mp: WebRTCMultiplayerPeer = WebRTCMultiplayerPeer.new() +var rtc_mp := WebRTCMultiplayerPeer.new() var sealed := false -func _init(): +func _init() -> void: connected.connect(_connected) disconnected.connect(_disconnected) @@ -17,7 +17,7 @@ func _init(): peer_disconnected.connect(_peer_disconnected) -func start(url, _lobby = "", _mesh := true): +func start(url: String, _lobby: String = "", _mesh: bool = true) -> void: stop() sealed = false mesh = _mesh @@ -25,30 +25,35 @@ func start(url, _lobby = "", _mesh := true): connect_to_url(url) -func stop(): +func stop() -> void: multiplayer.multiplayer_peer = null rtc_mp.close() close() -func _create_peer(id): +func _create_peer(id: int) -> WebRTCPeerConnection: var peer: WebRTCPeerConnection = WebRTCPeerConnection.new() + # Use a public STUN server for moderate NAT traversal. + # Note that STUN cannot punch through strict NATs (such as most mobile connections), + # in which case TURN is required. TURN generally does not have public servers available, + # as it requires much greater resources to host (all traffic goes through + # the TURN server, instead of only performing the initial connection). peer.initialize({ "iceServers": [ { "urls": ["stun:stun.l.google.com:19302"] } ] }) peer.session_description_created.connect(_offer_created.bind(id)) peer.ice_candidate_created.connect(_new_ice_candidate.bind(id)) rtc_mp.add_peer(peer, id) - if id < rtc_mp.get_unique_id(): # So lobby creator never creates offers. + if id < rtc_mp.get_unique_id(): # So lobby creator never creates offers. peer.create_offer() return peer -func _new_ice_candidate(mid_name, index_name, sdp_name, id): +func _new_ice_candidate(mid_name: String, index_name: int, sdp_name: String, id: int) -> void: send_candidate(id, mid_name, index_name, sdp_name) -func _offer_created(type, data, id): +func _offer_created(type: String, data: String, id: int) -> void: if not rtc_mp.has_peer(id): return print("created", type) @@ -57,7 +62,7 @@ func _offer_created(type, data, id): else: send_answer(id, data) -func _connected(id, use_mesh): +func _connected(id: int, use_mesh: bool) -> void: print("Connected %d, mesh: %s" % [id, use_mesh]) if use_mesh: rtc_mp.create_mesh(id) @@ -68,41 +73,42 @@ func _connected(id, use_mesh): multiplayer.multiplayer_peer = rtc_mp -func _lobby_joined(_lobby): +func _lobby_joined(_lobby: String) -> void: lobby = _lobby -func _lobby_sealed(): +func _lobby_sealed() -> void: sealed = true -func _disconnected(): +func _disconnected() -> void: print("Disconnected: %d: %s" % [code, reason]) if not sealed: stop() # Unexpected disconnect -func _peer_connected(id): - print("Peer connected %d" % id) +func _peer_connected(id: int) -> void: + print("Peer connected: %d" % id) _create_peer(id) -func _peer_disconnected(id): - if rtc_mp.has_peer(id): rtc_mp.remove_peer(id) +func _peer_disconnected(id: int) -> void: + if rtc_mp.has_peer(id): + rtc_mp.remove_peer(id) -func _offer_received(id, offer): +func _offer_received(id: int, offer: int) -> void: print("Got offer: %d" % id) if rtc_mp.has_peer(id): rtc_mp.get_peer(id).connection.set_remote_description("offer", offer) -func _answer_received(id, answer): +func _answer_received(id: int, answer: int) -> void: print("Got answer: %d" % id) if rtc_mp.has_peer(id): rtc_mp.get_peer(id).connection.set_remote_description("answer", answer) -func _candidate_received(id, mid, index, sdp): +func _candidate_received(id: int, mid: String, index: int, sdp: String) -> void: if rtc_mp.has_peer(id): rtc_mp.get_peer(id).connection.add_ice_candidate(mid, index, sdp) diff --git a/networking/webrtc_signaling/client/ws_webrtc_client.gd b/networking/webrtc_signaling/client/ws_webrtc_client.gd index e0e8dbf6..98fe1297 100644 --- a/networking/webrtc_signaling/client/ws_webrtc_client.gd +++ b/networking/webrtc_signaling/client/ws_webrtc_client.gd @@ -1,41 +1,50 @@ extends Node -enum Message {JOIN, ID, PEER_CONNECT, PEER_DISCONNECT, OFFER, ANSWER, CANDIDATE, SEAL} +enum Message { + JOIN, + ID, + PEER_CONNECT, + PEER_DISCONNECT, + OFFER, + ANSWER, + CANDIDATE, + SEAL, +} @export var autojoin := true -@export var lobby := "" # Will create a new lobby if empty. -@export var mesh := true # Will use the lobby host as relay otherwise. +@export var lobby := "" # Will create a new lobby if empty. +@export var mesh := true # Will use the lobby host as relay otherwise. -var ws: WebSocketPeer = WebSocketPeer.new() -var code = 1000 -var reason = "Unknown" -var old_state = WebSocketPeer.STATE_CLOSED +var ws := WebSocketPeer.new() +var code := 1000 +var reason := "Unknown" +var old_state := WebSocketPeer.STATE_CLOSED -signal lobby_joined(lobby) -signal connected(id, use_mesh) +signal lobby_joined(lobby: String) +signal connected(id: int, use_mesh: bool) signal disconnected() -signal peer_connected(id) -signal peer_disconnected(id) -signal offer_received(id, offer) -signal answer_received(id, answer) -signal candidate_received(id, mid, index, sdp) +signal peer_connected(id: int) +signal peer_disconnected(id: int) +signal offer_received(id: int, offer: int) +signal answer_received(id: int, answer: int) +signal candidate_received(id: int, mid: String, index: int, sdp: String) signal lobby_sealed() -func connect_to_url(url): +func connect_to_url(url: String) -> void: close() code = 1000 reason = "Unknown" ws.connect_to_url(url) -func close(): +func close() -> void: ws.close() -func _process(delta): +func _process(_delta: float) -> void: ws.poll() - var state = ws.get_ready_state() + var state := ws.get_ready_state() if state != old_state and state == WebSocketPeer.STATE_OPEN and autojoin: join_lobby(lobby) while state == WebSocketPeer.STATE_OPEN and ws.get_available_packet_count(): @@ -48,8 +57,8 @@ func _process(delta): old_state = state -func _parse_msg(): - var parsed = JSON.parse_string(ws.get_packet().get_string_from_utf8()) +func _parse_msg() -> bool: + var parsed: Dictionary = JSON.parse_string(ws.get_packet().get_string_from_utf8()) if typeof(parsed) != TYPE_DICTIONARY or not parsed.has("type") or not parsed.has("id") or \ typeof(parsed.get("data")) != TYPE_STRING: return false @@ -68,19 +77,19 @@ func _parse_msg(): elif type == Message.SEAL: lobby_sealed.emit() elif type == Message.PEER_CONNECT: - # Client connected + # Client connected. peer_connected.emit(src_id) elif type == Message.PEER_DISCONNECT: - # Client connected + # Client connected. peer_disconnected.emit(src_id) elif type == Message.OFFER: - # Offer received + # Offer received. offer_received.emit(src_id, msg.data) elif type == Message.ANSWER: - # Answer received + # Answer received. answer_received.emit(src_id, msg.data) elif type == Message.CANDIDATE: - # Candidate received + # Candidate received. var candidate: PackedStringArray = msg.data.split("\n", false) if candidate.size() != 3: return false @@ -89,32 +98,33 @@ func _parse_msg(): candidate_received.emit(src_id, candidate[0], candidate[1].to_int(), candidate[2]) else: return false - return true # Parsed + + return true # Parsed. -func join_lobby(lobby: String): +func join_lobby(lobby: String) -> Error: return _send_msg(Message.JOIN, 0 if mesh else 1, lobby) -func seal_lobby(): +func seal_lobby() -> Error: return _send_msg(Message.SEAL, 0) -func send_candidate(id, mid, index, sdp) -> int: +func send_candidate(id: int, mid: String, index: int, sdp: String) -> Error: return _send_msg(Message.CANDIDATE, id, "\n%s\n%d\n%s" % [mid, index, sdp]) -func send_offer(id, offer) -> int: +func send_offer(id: int, offer: String) -> Error: return _send_msg(Message.OFFER, id, offer) -func send_answer(id, answer) -> int: +func send_answer(id: int, answer: String) -> Error: return _send_msg(Message.ANSWER, id, answer) -func _send_msg(type: int, id: int, data:="") -> int: +func _send_msg(type: int, id: int, data: String = "") -> Error: return ws.send_text(JSON.stringify({ "type": type, "id": id, - "data": data + "data": data, })) diff --git a/networking/webrtc_signaling/demo/client_ui.gd b/networking/webrtc_signaling/demo/client_ui.gd index 89a5309e..0731db31 100644 --- a/networking/webrtc_signaling/demo/client_ui.gd +++ b/networking/webrtc_signaling/demo/client_ui.gd @@ -1,11 +1,11 @@ extends Control -@onready var client = $Client -@onready var host = $VBoxContainer/Connect/Host -@onready var room = $VBoxContainer/Connect/RoomSecret -@onready var mesh = $VBoxContainer/Connect/Mesh +@onready var client: Node = $Client +@onready var host: LineEdit = $VBoxContainer/Connect/Host +@onready var room: LineEdit = $VBoxContainer/Connect/RoomSecret +@onready var mesh: CheckBox = $VBoxContainer/Connect/Mesh -func _ready(): +func _ready() -> void: client.lobby_joined.connect(_lobby_joined) client.lobby_sealed.connect(_lobby_sealed) client.connected.connect(_connected) @@ -19,62 +19,62 @@ func _ready(): @rpc("any_peer", "call_local") -func ping(argument): +func ping(argument: String) -> void: _log("[Multiplayer] Ping from peer %d: arg: %s" % [multiplayer.get_remote_sender_id(), argument]) -func _mp_server_connected(): +func _mp_server_connected() -> void: _log("[Multiplayer] Server connected (I am %d)" % client.rtc_mp.get_unique_id()) -func _mp_server_disconnect(): +func _mp_server_disconnect() -> void: _log("[Multiplayer] Server disconnected (I am %d)" % client.rtc_mp.get_unique_id()) -func _mp_peer_connected(id: int): +func _mp_peer_connected(id: int) -> void: _log("[Multiplayer] Peer %d connected" % id) -func _mp_peer_disconnected(id: int): +func _mp_peer_disconnected(id: int) -> void: _log("[Multiplayer] Peer %d disconnected" % id) -func _connected(id, use_mesh): +func _connected(id: int, use_mesh: bool) -> void: _log("[Signaling] Server connected with ID: %d. Mesh: %s" % [id, use_mesh]) -func _disconnected(): +func _disconnected() -> void: _log("[Signaling] Server disconnected: %d - %s" % [client.code, client.reason]) -func _lobby_joined(lobby): +func _lobby_joined(lobby: String) -> void: _log("[Signaling] Joined lobby %s" % lobby) -func _lobby_sealed(): +func _lobby_sealed() -> void: _log("[Signaling] Lobby has been sealed") -func _log(msg): +func _log(msg: String) -> void: print(msg) $VBoxContainer/TextEdit.text += str(msg) + "\n" -func _on_peers_pressed(): - _log(multiplayer.get_peers()) +func _on_peers_pressed() -> void: + _log(str(multiplayer.get_peers())) -func _on_ping_pressed(): +func _on_ping_pressed() -> void: ping.rpc(randf()) -func _on_seal_pressed(): +func _on_seal_pressed() -> void: client.seal_lobby() -func _on_start_pressed(): +func _on_start_pressed() -> void: client.start(host.text, room.text, mesh.button_pressed) -func _on_stop_pressed(): +func _on_stop_pressed() -> void: client.stop() diff --git a/networking/webrtc_signaling/demo/client_ui.tscn b/networking/webrtc_signaling/demo/client_ui.tscn index b1757570..623da91f 100644 --- a/networking/webrtc_signaling/demo/client_ui.tscn +++ b/networking/webrtc_signaling/demo/client_ui.tscn @@ -25,92 +25,55 @@ grow_vertical = 2 [node name="Connect" type="HBoxContainer" parent="VBoxContainer"] layout_mode = 2 -offset_right = 1024.0 -offset_bottom = 31.0 [node name="Label" type="Label" parent="VBoxContainer/Connect"] layout_mode = 2 -offset_top = 2.0 -offset_right = 89.0 -offset_bottom = 28.0 text = "Connect to:" [node name="Host" type="LineEdit" parent="VBoxContainer/Connect"] layout_mode = 2 -offset_left = 93.0 -offset_right = 829.0 -offset_bottom = 31.0 size_flags_horizontal = 3 text = "ws://localhost:9080" [node name="Room" type="Label" parent="VBoxContainer/Connect"] layout_mode = 2 -offset_left = 833.0 -offset_right = 879.0 -offset_bottom = 31.0 size_flags_vertical = 5 text = "Room" [node name="RoomSecret" type="LineEdit" parent="VBoxContainer/Connect"] layout_mode = 2 -offset_left = 883.0 -offset_right = 950.0 -offset_bottom = 31.0 placeholder_text = "secret" [node name="Mesh" type="CheckBox" parent="VBoxContainer/Connect"] layout_mode = 2 -offset_left = 954.0 -offset_right = 1024.0 -offset_bottom = 31.0 button_pressed = true text = "Mesh" [node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] layout_mode = 2 -offset_top = 35.0 -offset_right = 1024.0 -offset_bottom = 66.0 [node name="Start" type="Button" parent="VBoxContainer/HBoxContainer"] layout_mode = 2 -offset_right = 46.0 -offset_bottom = 31.0 text = "Start" [node name="Stop" type="Button" parent="VBoxContainer/HBoxContainer"] layout_mode = 2 -offset_left = 50.0 -offset_right = 93.0 -offset_bottom = 31.0 text = "Stop" [node name="Seal" type="Button" parent="VBoxContainer/HBoxContainer"] layout_mode = 2 -offset_left = 97.0 -offset_right = 137.0 -offset_bottom = 31.0 text = "Seal" [node name="Ping" type="Button" parent="VBoxContainer/HBoxContainer"] layout_mode = 2 -offset_left = 141.0 -offset_right = 183.0 -offset_bottom = 31.0 text = "Ping" [node name="Peers" type="Button" parent="VBoxContainer/HBoxContainer"] layout_mode = 2 -offset_left = 187.0 -offset_right = 280.0 -offset_bottom = 31.0 text = "Print peers" [node name="TextEdit" type="TextEdit" parent="VBoxContainer"] layout_mode = 2 -offset_top = 70.0 -offset_right = 1024.0 -offset_bottom = 600.0 size_flags_vertical = 3 [connection signal="pressed" from="VBoxContainer/HBoxContainer/Start" to="." method="_on_start_pressed"] diff --git a/networking/webrtc_signaling/demo/main.gd b/networking/webrtc_signaling/demo/main.gd index df332e66..6727d8e5 100644 --- a/networking/webrtc_signaling/demo/main.gd +++ b/networking/webrtc_signaling/demo/main.gd @@ -1,24 +1,25 @@ extends Control -func _enter_tree(): +func _enter_tree() -> void: for c in $VBoxContainer/Clients.get_children(): # So each child gets its own separate MultiplayerAPI. get_tree().set_multiplayer( - MultiplayerAPI.create_default_interface(), - NodePath("%s/VBoxContainer/Clients/%s" % [get_path(), c.name]) + MultiplayerAPI.create_default_interface(), + NodePath("%s/VBoxContainer/Clients/%s" % [get_path(), c.name]) ) -func _ready(): + +func _ready() -> void: if OS.get_name() == "Web": $VBoxContainer/Signaling.hide() -func _on_listen_toggled(button_pressed): +func _on_listen_toggled(button_pressed: bool) -> void: if button_pressed: $Server.listen(int($VBoxContainer/Signaling/Port.value)) else: $Server.stop() -func _on_LinkButton_pressed(): +func _on_LinkButton_pressed() -> void: OS.shell_open("https://github.com/godotengine/webrtc-native/releases") diff --git a/networking/webrtc_signaling/project.godot b/networking/webrtc_signaling/project.godot index 85ce91af..78c8e472 100644 --- a/networking/webrtc_signaling/project.godot +++ b/networking/webrtc_signaling/project.godot @@ -22,6 +22,7 @@ config/features=PackedStringArray("4.2") [debug] gdscript/warnings/shadowed_variable=false +gdscript/warnings/untyped_declaration=1 gdscript/warnings/unused_argument=false [display] diff --git a/networking/webrtc_signaling/server/ws_webrtc_server.gd b/networking/webrtc_signaling/server/ws_webrtc_server.gd index 811cee27..c9c4bf44 100644 --- a/networking/webrtc_signaling/server/ws_webrtc_server.gd +++ b/networking/webrtc_signaling/server/ws_webrtc_server.gd @@ -1,12 +1,26 @@ extends Node -enum Message {JOIN, ID, PEER_CONNECT, PEER_DISCONNECT, OFFER, ANSWER, CANDIDATE, SEAL} +enum Message { + JOIN, + ID, + PEER_CONNECT, + PEER_DISCONNECT, + OFFER, + ANSWER, + CANDIDATE, + SEAL, +} -const TIMEOUT = 1000 # Unresponsive clients times out after 1 sec -const SEAL_TIME = 10000 # A sealed room will be closed after this time +## Unresponsive clients time out after this time (in milliseconds). +const TIMEOUT = 1000 + +## A sealed room will be closed after this time (in milliseconds). +const SEAL_TIME = 10000 + +## All alphanumeric characters. const ALFNUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" -var _alfnum = ALFNUM.to_ascii_buffer() +var _alfnum := ALFNUM.to_ascii_buffer() var rand: RandomNumberGenerator = RandomNumberGenerator.new() var lobbies: Dictionary = {} @@ -14,13 +28,13 @@ var tcp_server := TCPServer.new() var peers: Dictionary = {} class Peer extends RefCounted: - var id = -1 - var lobby = "" - var time = Time.get_ticks_msec() - var ws = WebSocketPeer.new() + var id := -1 + var lobby := "" + var time := Time.get_ticks_msec() + var ws := WebSocketPeer.new() - func _init(peer_id, tcp): + func _init(peer_id: int, tcp: StreamPeer) -> void: id = peer_id ws.accept_stream(tcp) @@ -29,7 +43,7 @@ class Peer extends RefCounted: return ws.get_ready_state() == WebSocketPeer.STATE_OPEN - func send(type: int, id: int, data:=""): + func send(type: int, id: int, data: String = "") -> void: return ws.send_text(JSON.stringify({ "type": type, "id": id, @@ -38,13 +52,13 @@ class Peer extends RefCounted: class Lobby extends RefCounted: - var peers: = {} - var host: int = -1 - var sealed: bool = false - var time = 0 + var peers := {} + var host := -1 + var sealed := false + var time := 0 # Value is in milliseconds. var mesh := true - func _init(host_id: int, use_mesh: bool): + func _init(host_id: int, use_mesh: bool) -> void: host = host_id mesh = use_mesh @@ -52,7 +66,7 @@ class Lobby extends RefCounted: if sealed: return false if not peer.is_ws_open(): return false peer.send(Message.ID, (1 if peer.id == host else peer.id), "true" if mesh else "") - for p in peers.values(): + for p: Peer in peers.values(): if not p.is_ws_open(): continue if not mesh and p.id != host: @@ -65,15 +79,19 @@ class Lobby extends RefCounted: func leave(peer: Peer) -> bool: - if not peers.has(peer.id): return false + if not peers.has(peer.id): + return false + peers.erase(peer.id) - var close = false + var close := false if peer.id == host: # The room host disconnected, will disconnect all peers. close = true - if sealed: return close + if sealed: + return close + # Notify other peers. - for p in peers.values(): + for p: Peer in peers.values(): if not p.is_ws_open(): continue if close: @@ -82,53 +100,59 @@ class Lobby extends RefCounted: else: # Notify disconnection. p.send(Message.PEER_DISCONNECT, peer.id) + return close func seal(peer_id: int) -> bool: # Only host can seal the room. - if host != peer_id: return false + if host != peer_id: + return false + sealed = true - for p in peers.values(): + + for p: Peer in peers.values(): if not p.is_ws_open(): continue p.send(Message.SEAL, 0) + time = Time.get_ticks_msec() peers.clear() + return true -func _process(delta): +func _process(_delta: float) -> void: poll() -func listen(port): - if OS.get_name() == "Web": +func listen(port: int) -> void: + if OS.has_feature("web"): OS.alert("Cannot create WebSocket servers in Web exports due to browsers' limitations.") return stop() - rand.seed = Time.get_unix_time_from_system() + rand.seed = int(Time.get_unix_time_from_system()) tcp_server.listen(port) -func stop(): +func stop() -> void: tcp_server.stop() peers.clear() -func poll(): +func poll() -> void: if not tcp_server.is_listening(): return if tcp_server.is_connection_available(): - var id = randi() % (1 << 31) + var id := randi() % (1 << 31) peers[id] = Peer.new(id, tcp_server.take_connection()) # Poll peers. var to_remove := [] - for p in peers.values(): + for p: Peer in peers.values(): # Peers timeout. - if p.lobby == "" and Time.get_ticks_msec() - p.time > TIMEOUT: + if p.lobby.is_empty() and Time.get_ticks_msec() - p.time > TIMEOUT: p.ws.close() p.ws.poll() while p.is_ws_open() and p.ws.get_available_packet_count(): @@ -137,7 +161,7 @@ func poll(): to_remove.push_back(p.id) p.ws.close() break - var state = p.ws.get_ready_state() + var state := p.ws.get_ready_state() if state == WebSocketPeer.STATE_CLOSED: print("Peer %d disconnected from lobby: '%s'" % [p.id, p.lobby]) # Remove from lobby (and lobby itself if host). @@ -148,24 +172,24 @@ func poll(): to_remove.push_back(p.id) # Lobby seal. - for k in lobbies: + for k: String in lobbies: if not lobbies[k].sealed: continue if lobbies[k].time + SEAL_TIME < Time.get_ticks_msec(): # Close lobby. - for p in lobbies[k].peers: + for p: Peer in lobbies[k].peers: p.ws.close() to_remove.push_back(p.id) # Remove stale peers - for id in to_remove: + for id: int in to_remove: peers.erase(id) func _join_lobby(peer: Peer, lobby: String, mesh: bool) -> bool: - if lobby == "": - for _i in range(0, 32): - lobby += char(_alfnum[rand.randi_range(0, ALFNUM.length()-1)]) + if lobby.is_empty(): + for _i in 32: + lobby += char(_alfnum[rand.randi_range(0, ALFNUM.length() - 1)]) lobbies[lobby] = Lobby.new(peer.id, mesh) elif not lobbies.has(lobby): return false @@ -179,7 +203,7 @@ func _join_lobby(peer: Peer, lobby: String, mesh: bool) -> bool: func _parse_msg(peer: Peer) -> bool: var pkt_str: String = peer.ws.get_packet().get_string_from_utf8() - var parsed = JSON.parse_string(pkt_str) + var parsed: Dictionary = JSON.parse_string(pkt_str) if typeof(parsed) != TYPE_DICTIONARY or not parsed.has("type") or not parsed.has("id") or \ typeof(parsed.get("data")) != TYPE_STRING: return false @@ -189,36 +213,37 @@ func _parse_msg(peer: Peer) -> bool: var msg := { "type": str(parsed.type).to_int(), "id": str(parsed.id).to_int(), - "data": parsed.data + "data": parsed.data, } if msg.type == Message.JOIN: - if peer.lobby: # Peer must not have joined a lobby already! + if peer.lobby: # Peer must not have joined a lobby already! return false + return _join_lobby(peer, msg.data, msg.id == 0) - if not lobbies.has(peer.lobby): # Lobby not found? + if not lobbies.has(peer.lobby): # Lobby not found? return false - var lobby = lobbies[peer.lobby] + var lobby: Peer = lobbies[peer.lobby] if msg.type == Message.SEAL: - # Client is sealing the room + # Client is sealing the room. return lobby.seal(peer.id) var dest_id: int = msg.id if dest_id == MultiplayerPeer.TARGET_PEER_SERVER: dest_id = lobby.host - if not peers.has(dest_id): # Destination ID not connected + if not peers.has(dest_id): # Destination ID not connected. return false - if peers[dest_id].lobby != peer.lobby: # Trying to contact someone not in same lobby + if peers[dest_id].lobby != peer.lobby: # Trying to contact someone not in same lobby. return false if msg.type in [Message.OFFER, Message.ANSWER, Message.CANDIDATE]: - var source = MultiplayerPeer.TARGET_PEER_SERVER if peer.id == lobby.host else peer.id + var source := MultiplayerPeer.TARGET_PEER_SERVER if peer.id == lobby.host else peer.id peers[dest_id].send(msg.type, source, msg.data) return true - return false # Unknown message + return false # Unknown message. diff --git a/networking/websocket_chat/client.gd b/networking/websocket_chat/client.gd index 4026c971..88102269 100644 --- a/networking/websocket_chat/client.gd +++ b/networking/websocket_chat/client.gd @@ -1,32 +1,32 @@ extends Control @onready var _client: WebSocketClient = $WebSocketClient -@onready var _log_dest = $Panel/VBoxContainer/RichTextLabel -@onready var _line_edit = $Panel/VBoxContainer/Send/LineEdit -@onready var _host = $Panel/VBoxContainer/Connect/Host +@onready var _log_dest: RichTextLabel = $Panel/VBoxContainer/RichTextLabel +@onready var _line_edit: LineEdit = $Panel/VBoxContainer/Send/LineEdit +@onready var _host: LineEdit = $Panel/VBoxContainer/Connect/Host -func info(msg): +func info(msg: String) -> void: print(msg) _log_dest.add_text(str(msg) + "\n") -# Client signals -func _on_web_socket_client_connection_closed(): - var ws = _client.get_socket() +#region Client signals +func _on_web_socket_client_connection_closed() -> void: + var ws := _client.get_socket() info("Client just disconnected with code: %s, reson: %s" % [ws.get_close_code(), ws.get_close_reason()]) -func _on_web_socket_client_connected_to_server(): +func _on_web_socket_client_connected_to_server() -> void: info("Client just connected with protocol: %s" % _client.get_socket().get_selected_protocol()) -func _on_web_socket_client_message_received(message): +func _on_web_socket_client_message_received(message: String) -> void: info("%s" % message) +#endregion - -# UI signals. -func _on_send_pressed(): - if _line_edit.text == "": +#region UI signals +func _on_send_pressed() -> void: + if _line_edit.text.is_empty(): return info("Sending message: %s" % [_line_edit.text]) @@ -34,14 +34,17 @@ func _on_send_pressed(): _line_edit.text = "" -func _on_connect_toggled(pressed): +func _on_connect_toggled(pressed: bool) -> void: if not pressed: _client.close() return - if _host.text == "": + + if _host.text.is_empty(): return + info("Connecting to host: %s." % [_host.text]) - var err = _client.connect_to_url(_host.text) + var err := _client.connect_to_url(_host.text) if err != OK: info("Error connecting to host: %s" % [_host.text]) return +#endregion diff --git a/networking/websocket_chat/project.godot b/networking/websocket_chat/project.godot index ada9058b..7168d683 100644 --- a/networking/websocket_chat/project.godot +++ b/networking/websocket_chat/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://combo.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/networking/websocket_chat/server.gd b/networking/websocket_chat/server.gd index 2589903a..cb39617b 100644 --- a/networking/websocket_chat/server.gd +++ b/networking/websocket_chat/server.gd @@ -1,35 +1,35 @@ extends Control @onready var _server: WebSocketServer = $WebSocketServer -@onready var _log_dest = $Panel/VBoxContainer/RichTextLabel -@onready var _line_edit = $Panel/VBoxContainer/Send/LineEdit -@onready var _listen_port = $Panel/VBoxContainer/Connect/Port +@onready var _log_dest: RichTextLabel = $Panel/VBoxContainer/RichTextLabel +@onready var _line_edit: LineEdit = $Panel/VBoxContainer/Send/LineEdit +@onready var _listen_port: SpinBox = $Panel/VBoxContainer/Connect/Port -func info(msg): +func info(msg: String) -> void: print(msg) _log_dest.add_text(str(msg) + "\n") -# Server signals -func _on_web_socket_server_client_connected(peer_id): +#region Server signals +func _on_web_socket_server_client_connected(peer_id: int) -> void: var peer: WebSocketPeer = _server.peers[peer_id] info("Remote client connected: %d. Protocol: %s" % [peer_id, peer.get_selected_protocol()]) _server.send(-peer_id, "[%d] connected" % peer_id) -func _on_web_socket_server_client_disconnected(peer_id): +func _on_web_socket_server_client_disconnected(peer_id: int) -> void: var peer: WebSocketPeer = _server.peers[peer_id] info("Remote client disconnected: %d. Code: %d, Reason: %s" % [peer_id, peer.get_close_code(), peer.get_close_reason()]) _server.send(-peer_id, "[%d] disconnected" % peer_id) -func _on_web_socket_server_message_received(peer_id, message): +func _on_web_socket_server_message_received(peer_id: int, message: String) -> void: info("Server received data from peer %d: %s" % [peer_id, message]) _server.send(-peer_id, "[%d] Says: %s" % [peer_id, message]) +#endregion - -# UI signals. -func _on_send_pressed(): +#region UI signals +func _on_send_pressed() -> void: if _line_edit.text == "": return @@ -38,14 +38,17 @@ func _on_send_pressed(): _line_edit.text = "" -func _on_listen_toggled(pressed): +func _on_listen_toggled(pressed: bool) -> void: if not pressed: _server.stop() info("Server stopped") return - var port = int(_listen_port.value) - var err = _server.listen(port) + + var port := int(_listen_port.value) + var err := _server.listen(port) + if err != OK: info("Error listing on port %s" % port) return info("Listing on port %s, supported protocols: %s" % [port, _server.supported_protocols]) +#endregion diff --git a/networking/websocket_chat/websocket/WebSocketClient.gd b/networking/websocket_chat/websocket/WebSocketClient.gd index 17fda900..e51da5b9 100644 --- a/networking/websocket_chat/websocket/WebSocketClient.gd +++ b/networking/websocket_chat/websocket/WebSocketClient.gd @@ -1,31 +1,30 @@ -extends Node -class_name WebSocketClient +class_name Node +extends WebSocketClient @export var handshake_headers: PackedStringArray @export var supported_protocols: PackedStringArray var tls_options: TLSOptions = null - -var socket = WebSocketPeer.new() -var last_state = WebSocketPeer.STATE_CLOSED - +var socket := WebSocketPeer.new() +var last_state := WebSocketPeer.STATE_CLOSED signal connected_to_server() signal connection_closed() signal message_received(message: Variant) - -func connect_to_url(url) -> int: +func connect_to_url(url: String) -> int: socket.supported_protocols = supported_protocols socket.handshake_headers = handshake_headers - var err = socket.connect_to_url(url, tls_options) + + var err := socket.connect_to_url(url, tls_options) if err != OK: return err + last_state = socket.get_ready_state() return OK -func send(message) -> int: +func send(message: String) -> int: if typeof(message) == TYPE_STRING: return socket.send_text(message) return socket.send(var_to_bytes(message)) @@ -34,13 +33,13 @@ func send(message) -> int: func get_message() -> Variant: if socket.get_available_packet_count() < 1: return null - var pkt = socket.get_packet() + var pkt := socket.get_packet() if socket.was_string_packet(): return pkt.get_string_from_utf8() return bytes_to_var(pkt) -func close(code := 1000, reason := "") -> void: +func close(code: int = 1000, reason: String = "") -> void: socket.close(code, reason) last_state = socket.get_ready_state() @@ -57,7 +56,9 @@ func get_socket() -> WebSocketPeer: func poll() -> void: if socket.get_ready_state() != socket.STATE_CLOSED: socket.poll() - var state = socket.get_ready_state() + + var state := socket.get_ready_state() + if last_state != state: last_state = state if state == socket.STATE_OPEN: @@ -68,5 +69,5 @@ func poll() -> void: message_received.emit(get_message()) -func _process(delta): +func _process(_delta: float) -> void: poll() diff --git a/networking/websocket_chat/websocket/WebSocketServer.gd b/networking/websocket_chat/websocket/WebSocketServer.gd index 5cc0daf6..eff7305a 100644 --- a/networking/websocket_chat/websocket/WebSocketServer.gd +++ b/networking/websocket_chat/websocket/WebSocketServer.gd @@ -1,12 +1,12 @@ -extends Node -class_name WebSocketServer +class_name Node +extends WebSocketServer -signal message_received(peer_id: int, message) +signal message_received(peer_id: int, message: String) signal client_connected(peer_id: int) signal client_disconnected(peer_id: int) @export var handshake_headers := PackedStringArray() -@export var supported_protocols: PackedStringArray +@export var supported_protocols := PackedStringArray() @export var handshake_timout := 3000 @export var use_tls := false @export var tls_cert: X509Certificate @@ -23,7 +23,7 @@ class PendingPeer: var connection: StreamPeer var ws: WebSocketPeer - func _init(p_tcp: StreamPeerTCP): + func _init(p_tcp: StreamPeerTCP) -> void: tcp = p_tcp connection = p_tcp connect_time = Time.get_ticks_msec() @@ -39,17 +39,17 @@ func listen(port: int) -> int: return tcp_server.listen(port) -func stop(): +func stop() -> void: tcp_server.stop() pending_peers.clear() peers.clear() -func send(peer_id, message) -> int: - var type = typeof(message) +func send(peer_id: int, message: String) -> int: + var type := typeof(message) if peer_id <= 0: - # Send to multiple peers, (zero = brodcast, negative = exclude one) - for id in peers: + # Send to multiple peers, (zero = broadcast, negative = exclude one). + for id: int in peers: if id == -peer_id: continue if type == TYPE_STRING: @@ -59,30 +59,30 @@ func send(peer_id, message) -> int: return OK assert(peers.has(peer_id)) - var socket = peers[peer_id] + var socket: WebSocketPeer = peers[peer_id] if type == TYPE_STRING: return socket.send_text(message) return socket.send(var_to_bytes(message)) -func get_message(peer_id) -> Variant: +func get_message(peer_id: int) -> Variant: assert(peers.has(peer_id)) - var socket = peers[peer_id] + var socket: WebSocketPeer = peers[peer_id] if socket.get_available_packet_count() < 1: return null - var pkt = socket.get_packet() + var pkt: PackedByteArray = socket.get_packet() if socket.was_string_packet(): return pkt.get_string_from_utf8() return bytes_to_var(pkt) -func has_message(peer_id) -> bool: +func has_message(peer_id: int) -> bool: assert(peers.has(peer_id)) return peers[peer_id].get_available_packet_count() > 0 func _create_peer() -> WebSocketPeer: - var ws = WebSocketPeer.new() + var ws := WebSocketPeer.new() ws.supported_protocols = supported_protocols ws.handshake_headers = handshake_headers return ws @@ -91,72 +91,83 @@ func _create_peer() -> WebSocketPeer: func poll() -> void: if not tcp_server.is_listening(): return + while not refuse_new_connections and tcp_server.is_connection_available(): - var conn = tcp_server.take_connection() + var conn: StreamPeerTCP = tcp_server.take_connection() assert(conn != null) pending_peers.append(PendingPeer.new(conn)) + var to_remove := [] + for p in pending_peers: if not _connect_pending(p): if p.connect_time + handshake_timout < Time.get_ticks_msec(): - # Timeout + # Timeout. to_remove.append(p) - continue # Still pending + continue # Still pending. + to_remove.append(p) - for r in to_remove: + + for r: RefCounted in to_remove: pending_peers.erase(r) + to_remove.clear() - for id in peers: + + for id: int in peers: var p: WebSocketPeer = peers[id] - var packets = p.get_available_packet_count() p.poll() + if p.get_ready_state() != WebSocketPeer.STATE_OPEN: client_disconnected.emit(id) to_remove.append(id) continue + while p.get_available_packet_count(): message_received.emit(id, get_message(id)) - for r in to_remove: + + for r: int in to_remove: peers.erase(r) to_remove.clear() func _connect_pending(p: PendingPeer) -> bool: if p.ws != null: - # Poll websocket client if doing handshake + # Poll websocket client if doing handshake. p.ws.poll() - var state = p.ws.get_ready_state() + var state := p.ws.get_ready_state() if state == WebSocketPeer.STATE_OPEN: - var id = randi_range(2, 1 << 30) + var id := randi_range(2, 1 << 30) peers[id] = p.ws client_connected.emit(id) - return true # Success. + return true # Success. elif state != WebSocketPeer.STATE_CONNECTING: - return true # Failure. - return false # Still connecting. + return true # Failure. + return false # Still connecting. elif p.tcp.get_status() != StreamPeerTCP.STATUS_CONNECTED: - return true # TCP disconnected. + return true # TCP disconnected. elif not use_tls: - # TCP is ready, create WS peer + # TCP is ready, create WS peer. p.ws = _create_peer() p.ws.accept_stream(p.tcp) - return false # WebSocketPeer connection is pending. + return false # WebSocketPeer connection is pending. + else: if p.connection == p.tcp: assert(tls_key != null and tls_cert != null) - var tls = StreamPeerTLS.new() + var tls := StreamPeerTLS.new() tls.accept_stream(p.tcp, TLSOptions.server(tls_key, tls_cert)) p.connection = tls p.connection.poll() - var status = p.connection.get_status() + var status: StreamPeerTLS.Status = p.connection.get_status() if status == StreamPeerTLS.STATUS_CONNECTED: p.ws = _create_peer() p.ws.accept_stream(p.connection) - return false # WebSocketPeer connection is pending. + return false # WebSocketPeer connection is pending. if status != StreamPeerTLS.STATUS_HANDSHAKING: - return true # Failure. + return true # Failure. + return false -func _process(delta): +func _process(_delta: float) -> void: poll() diff --git a/networking/websocket_minimal/client.gd b/networking/websocket_minimal/client.gd index 12bbe0f4..5f67ebf7 100644 --- a/networking/websocket_minimal/client.gd +++ b/networking/websocket_minimal/client.gd @@ -1,22 +1,22 @@ extends Node -# The URL we will connect to. -var websocket_url = "ws://localhost:9080" +## The URL we will connect to. +var websocket_url := "ws://localhost:9080" + var socket := WebSocketPeer.new() - -func log_message(message): - var time = "[color=#aaaaaa] %s [/color]" % Time.get_time_string_from_system() +func log_message(message: String) -> void: + var time := "[color=#aaaaaa] %s |[/color] " % Time.get_time_string_from_system() %TextClient.text += time + message + "\n" -func _ready(): +func _ready() -> void: if socket.connect_to_url(websocket_url) != OK: log_message("Unable to connect.") set_process(false) -func _process(_delta): +func _process(_delta: float) -> void: socket.poll() if socket.get_ready_state() == WebSocketPeer.STATE_OPEN: @@ -24,9 +24,9 @@ func _process(_delta): log_message(socket.get_packet().get_string_from_ascii()) -func _exit_tree(): +func _exit_tree() -> void: socket.close() -func _on_button_ping_pressed(): +func _on_button_ping_pressed() -> void: socket.send_text("Ping") diff --git a/networking/websocket_minimal/project.godot b/networking/websocket_minimal/project.godot index e974b77b..75fc64b3 100644 --- a/networking/websocket_minimal/project.godot +++ b/networking/websocket_minimal/project.godot @@ -16,6 +16,10 @@ config/tags=PackedStringArray("demo", "network", "official") run/main_scene="res://Main.tscn" config/features=PackedStringArray("4.2") +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/size/viewport_width=600 diff --git a/networking/websocket_minimal/server.gd b/networking/websocket_minimal/server.gd index 33380821..9f019df0 100644 --- a/networking/websocket_minimal/server.gd +++ b/networking/websocket_minimal/server.gd @@ -1,23 +1,23 @@ extends Node -# The port we will listen to. +## The port the server will listen on. const PORT = 9080 + var tcp_server := TCPServer.new() var socket := WebSocketPeer.new() - -func log_message(message): - var time = "[color=#aaaaaa] %s [/color]" % Time.get_time_string_from_system() +func log_message(message: String) -> void: + var time := "[color=#aaaaaa] %s |[/color] " % Time.get_time_string_from_system() %TextServer.text += time + message + "\n" -func _ready(): +func _ready() -> void: if tcp_server.listen(PORT) != OK: log_message("Unable to start server.") set_process(false) -func _process(_delta): +func _process(_delta: float) -> void: while tcp_server.is_connection_available(): var conn: StreamPeerTCP = tcp_server.take_connection() assert(conn != null) @@ -30,10 +30,10 @@ func _process(_delta): log_message(socket.get_packet().get_string_from_ascii()) -func _exit_tree(): +func _exit_tree() -> void: socket.close() tcp_server.stop() -func _on_button_pong_pressed(): +func _on_button_pong_pressed() -> void: socket.send_text("Pong") diff --git a/networking/websocket_multiplayer/project.godot b/networking/websocket_multiplayer/project.godot index 9c714567..130e4ed8 100644 --- a/networking/websocket_multiplayer/project.godot +++ b/networking/websocket_multiplayer/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://scene/combo.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/networking/websocket_multiplayer/scene/game.tscn b/networking/websocket_multiplayer/scene/game.tscn index bf102bf8..84b51485 100644 --- a/networking/websocket_multiplayer/scene/game.tscn +++ b/networking/websocket_multiplayer/scene/game.tscn @@ -1,50 +1,42 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=2 format=3 uid="uid://dqxum77awcw6u"] -[ext_resource path="res://script/game.gd" type="Script" id=1] +[ext_resource type="Script" path="res://script/game.gd" id="1"] [node name="Game" type="Control"] +layout_mode = 3 +anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 -mouse_filter = 1 size_flags_horizontal = 3 size_flags_vertical = 3 -script = ExtResource( 1 ) -__meta__ = { -"_edit_use_anchors_": false -} +mouse_filter = 1 +script = ExtResource("1") [node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 [node name="RichTextLabel" type="RichTextLabel" parent="HBoxContainer"] -offset_right = 510.0 -offset_bottom = 600.0 +layout_mode = 2 size_flags_horizontal = 3 [node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"] -offset_left = 514.0 -offset_right = 1024.0 -offset_bottom = 600.0 +layout_mode = 2 size_flags_horizontal = 3 [node name="Label" type="Label" parent="HBoxContainer/VBoxContainer"] -offset_right = 510.0 -offset_bottom = 14.0 +layout_mode = 2 text = "Players:" [node name="ItemList" type="ItemList" parent="HBoxContainer/VBoxContainer"] -offset_top = 18.0 -offset_right = 510.0 -offset_bottom = 576.0 +layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 same_column_width = true [node name="Action" type="Button" parent="HBoxContainer/VBoxContainer"] -offset_top = 580.0 -offset_right = 510.0 -offset_bottom = 600.0 +layout_mode = 2 disabled = true text = "Do Action!" diff --git a/networking/websocket_multiplayer/scene/main.tscn b/networking/websocket_multiplayer/scene/main.tscn index 3871f234..ad2ca7a6 100644 --- a/networking/websocket_multiplayer/scene/main.tscn +++ b/networking/websocket_multiplayer/scene/main.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=3 format=3 uid="uid://c240icwf4uov8"] [ext_resource type="Script" path="res://script/main.gd" id="1"] -[ext_resource type="PackedScene" path="res://scene/game.tscn" id="2"] +[ext_resource type="PackedScene" uid="uid://dqxum77awcw6u" path="res://scene/game.tscn" id="2"] [node name="Main" type="Control"] layout_mode = 3 @@ -15,14 +15,14 @@ size_flags_vertical = 3 script = ExtResource("1") [node name="Panel" type="Panel" parent="."] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 [node name="VBoxContainer" type="VBoxContainer" parent="Panel"] -anchors_preset = 15 +layout_mode = 0 anchor_right = 1.0 anchor_bottom = 1.0 offset_left = 20.0 @@ -33,84 +33,55 @@ grow_horizontal = 2 grow_vertical = 2 [node name="HBoxContainer" type="HBoxContainer" parent="Panel/VBoxContainer"] -offset_right = 1112.0 -offset_bottom = 31.0 +layout_mode = 2 [node name="Label" type="Label" parent="Panel/VBoxContainer/HBoxContainer"] -offset_top = 2.0 -offset_right = 369.0 -offset_bottom = 28.0 +layout_mode = 2 size_flags_horizontal = 3 text = "Name" [node name="NameEdit" type="LineEdit" parent="Panel/VBoxContainer/HBoxContainer"] -offset_left = 373.0 -offset_right = 1112.0 -offset_bottom = 31.0 +layout_mode = 2 size_flags_horizontal = 3 size_flags_stretch_ratio = 2.0 text = "A Godot User" [node name="HBoxContainer2" type="HBoxContainer" parent="Panel/VBoxContainer"] -offset_top = 35.0 -offset_right = 1112.0 -offset_bottom = 66.0 +layout_mode = 2 [node name="HBoxContainer" type="HBoxContainer" parent="Panel/VBoxContainer/HBoxContainer2"] -offset_right = 369.0 -offset_bottom = 31.0 +layout_mode = 2 size_flags_horizontal = 3 [node name="Host" type="Button" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"] -offset_right = 44.0 -offset_bottom = 31.0 +layout_mode = 2 text = "Host" [node name="Control" type="Control" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"] -layout_mode = 3 -anchors_preset = 0 -offset_left = 48.0 -offset_right = 273.0 -offset_bottom = 31.0 +layout_mode = 2 size_flags_horizontal = 3 [node name="Connect" type="Button" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"] -offset_left = 277.0 -offset_right = 369.0 -offset_bottom = 31.0 +layout_mode = 2 text = "Connect to" [node name="Disconnect" type="Button" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"] visible = false -offset_left = 68.0 -offset_right = 152.0 -offset_bottom = 24.0 +layout_mode = 2 text = "Disconnect" [node name="Hostname" type="LineEdit" parent="Panel/VBoxContainer/HBoxContainer2"] -offset_left = 373.0 -offset_right = 1112.0 -offset_bottom = 31.0 +layout_mode = 2 size_flags_horizontal = 3 size_flags_stretch_ratio = 2.0 text = "localhost" placeholder_text = "localhost" [node name="Control" type="Control" parent="Panel/VBoxContainer"] -layout_mode = 3 -anchors_preset = 0 -offset_top = 70.0 -offset_right = 1112.0 -offset_bottom = 70.0 +layout_mode = 2 [node name="Game" parent="Panel/VBoxContainer" instance=ExtResource("2")] -layout_mode = 3 -anchors_preset = 0 -anchor_right = 0.0 -anchor_bottom = 0.0 -offset_top = 74.0 -offset_right = 1112.0 -offset_bottom = 608.0 +layout_mode = 2 [node name="AcceptDialog" type="AcceptDialog" parent="."] dialog_text = "Connection closed" diff --git a/networking/websocket_multiplayer/script/combo.gd b/networking/websocket_multiplayer/script/combo.gd index 04f46034..251520c9 100644 --- a/networking/websocket_multiplayer/script/combo.gd +++ b/networking/websocket_multiplayer/script/combo.gd @@ -1,8 +1,9 @@ extends Control -var paths := [] +var paths: Array[NodePath] = [] -func _enter_tree(): + +func _enter_tree() -> void: for ch in $GridContainer.get_children(): paths.append(NodePath(str(get_path()) + "/GridContainer/" + str(ch.name))) # Sets a dedicated Multiplayer API for each branch. @@ -10,7 +11,7 @@ func _enter_tree(): get_tree().set_multiplayer(MultiplayerAPI.create_default_interface(), path) -func _exit_tree(): +func _exit_tree() -> void: # Clear the branch-specific Multiplayer API. for path in paths: get_tree().set_multiplayer(null, path) diff --git a/networking/websocket_multiplayer/script/game.gd b/networking/websocket_multiplayer/script/game.gd index 859f6152..1b28ff5f 100644 --- a/networking/websocket_multiplayer/script/game.gd +++ b/networking/websocket_multiplayer/script/game.gd @@ -2,39 +2,40 @@ extends Control const _crown = preload("res://img/crown.png") -@onready var _list = $HBoxContainer/VBoxContainer/ItemList -@onready var _action = $HBoxContainer/VBoxContainer/Action +@onready var _list: ItemList = $HBoxContainer/VBoxContainer/ItemList +@onready var _action: Button = $HBoxContainer/VBoxContainer/Action const ACTIONS = ["roll", "pass"] -var _players = [] -var _turn = -1 +var _players: Array[int] = [] +var _turn := -1 + @rpc -func _log(what): - $HBoxContainer/RichTextLabel.add_text(what + "\n") +func _log(message: String) -> void: + $HBoxContainer/RichTextLabel.add_text(message + "\n") @rpc("any_peer") -func set_player_name(p_name): +func set_player_name(p_name: String) -> void: if not is_multiplayer_authority(): return - var sender = multiplayer.get_remote_sender_id() + var sender := multiplayer.get_remote_sender_id() update_player_name.rpc(sender, p_name) @rpc("call_local") -func update_player_name(player, p_name): - var pos = _players.find(player) +func update_player_name(player: int, p_name: String) -> void: + var pos := _players.find(player) if pos != -1: _list.set_item_text(pos, p_name) @rpc("any_peer") -func request_action(action): +func request_action(action: String) -> void: if not is_multiplayer_authority(): return - var sender = multiplayer.get_remote_sender_id() + var sender := multiplayer.get_remote_sender_id() if _players[_turn] != sender: _log.rpc("Someone is trying to cheat! %s" % str(sender)) return @@ -46,88 +47,97 @@ func request_action(action): next_turn() -func do_action(action): - var player_name = _list.get_item_text(_turn) - var val = randi() % 100 +func do_action(action: String) -> void: + var player_name := _list.get_item_text(_turn) + var val := randi() % 100 _log.rpc("%s: %ss %d" % [player_name, action, val]) @rpc("call_local") -func set_turn(turn): +func set_turn(turn: int) -> void: _turn = turn if turn >= _players.size(): return - for i in range(0, _players.size()): + + for i in _players.size(): if i == turn: _list.set_item_icon(i, _crown) else: _list.set_item_icon(i, null) + _action.disabled = _players[turn] != multiplayer.get_unique_id() @rpc("call_local") -func del_player(id): - var pos = _players.find(id) +func del_player(id: int) -> void: + var pos := _players.find(id) + if pos == -1: return + _players.remove_at(pos) _list.remove_item(pos) + if _turn > pos: _turn -= 1 + if multiplayer.is_server(): set_turn.rpc(_turn) @rpc("call_local") -func add_player(id, pname=""): +func add_player(id: int, p_name: String = "") -> void: _players.append(id) - if pname == "": + if p_name == "": _list.add_item("... connecting ...", null, false) else: - _list.add_item(pname, null, false) + _list.add_item(p_name, null, false) -func get_player_name(pos): +func get_player_name(pos: int) -> String: if pos < _list.get_item_count(): return _list.get_item_text(pos) else: return "Error!" -func next_turn(): +func next_turn() -> void: _turn += 1 if _turn >= _players.size(): _turn = 0 set_turn.rpc(_turn) -func start(): +func start() -> void: set_turn(0) -func stop(): +func stop() -> void: _players.clear() _list.clear() _turn = 0 _action.disabled = true -func on_peer_add(id): +func on_peer_add(id: int) -> void: if not multiplayer.is_server(): return - for i in range(0, _players.size()): + + for i in _players.size(): add_player.rpc_id(id, _players[i], get_player_name(i)) + add_player.rpc(id) set_turn.rpc_id(id, _turn) -func on_peer_del(id): +func on_peer_del(id: int) -> void: if not multiplayer.is_server(): return + del_player.rpc(id) -func _on_Action_pressed(): +func _on_Action_pressed() -> void: if multiplayer.is_server(): if _turn != 0: return diff --git a/networking/websocket_multiplayer/script/main.gd b/networking/websocket_multiplayer/script/main.gd index f890e9b3..5ae3818f 100644 --- a/networking/websocket_multiplayer/script/main.gd +++ b/networking/websocket_multiplayer/script/main.gd @@ -3,21 +3,21 @@ extends Control const DEF_PORT = 8080 const PROTO_NAME = "ludus" -@onready var _host_btn = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Host -@onready var _connect_btn = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Connect -@onready var _disconnect_btn = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Disconnect -@onready var _name_edit = $Panel/VBoxContainer/HBoxContainer/NameEdit -@onready var _host_edit = $Panel/VBoxContainer/HBoxContainer2/Hostname -@onready var _game = $Panel/VBoxContainer/Game +@onready var _host_btn: Button = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Host +@onready var _connect_btn: Button = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Connect +@onready var _disconnect_btn: Button = $Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Disconnect +@onready var _name_edit: LineEdit = $Panel/VBoxContainer/HBoxContainer/NameEdit +@onready var _host_edit: LineEdit = $Panel/VBoxContainer/HBoxContainer2/Hostname +@onready var _game: Control = $Panel/VBoxContainer/Game -var peer = WebSocketMultiplayerPeer.new() +var peer := WebSocketMultiplayerPeer.new() -func _init(): +func _init() -> void: peer.supported_protocols = ["ludus"] -func _ready(): +func _ready() -> void: multiplayer.peer_connected.connect(_peer_connected) multiplayer.peer_disconnected.connect(_peer_disconnected) multiplayer.server_disconnected.connect(_close_network) @@ -30,11 +30,11 @@ func _ready(): if OS.has_environment("USERNAME"): _name_edit.text = OS.get_environment("USERNAME") else: - var desktop_path = OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP).replace("\\", "/").split("/") + var desktop_path := OS.get_system_dir(OS.SYSTEM_DIR_DESKTOP).replace("\\", "/").split("/") _name_edit.text = desktop_path[desktop_path.size() - 2] -func start_game(): +func start_game() -> void: _host_btn.disabled = true _name_edit.editable = false _host_edit.editable = false @@ -43,7 +43,7 @@ func start_game(): _game.start() -func stop_game(): +func stop_game() -> void: _host_btn.disabled = false _name_edit.editable = true _host_edit.editable = true @@ -52,7 +52,7 @@ func stop_game(): _game.stop() -func _close_network(): +func _close_network() -> void: stop_game() $AcceptDialog.popup_centered() $AcceptDialog.get_ok_button().grab_focus() @@ -60,20 +60,20 @@ func _close_network(): peer.close() -func _connected(): +func _connected() -> void: _game.set_player_name.rpc(_name_edit.text) -func _peer_connected(id): +func _peer_connected(id: int) -> void: _game.on_peer_add(id) -func _peer_disconnected(id): +func _peer_disconnected(id: int) -> void: print("Disconnected %d" % id) _game.on_peer_del(id) -func _on_Host_pressed(): +func _on_Host_pressed() -> void: multiplayer.multiplayer_peer = null peer.create_server(DEF_PORT) multiplayer.multiplayer_peer = peer @@ -81,11 +81,11 @@ func _on_Host_pressed(): start_game() -func _on_Disconnect_pressed(): +func _on_Disconnect_pressed() -> void: _close_network() -func _on_Connect_pressed(): +func _on_Connect_pressed() -> void: multiplayer.multiplayer_peer = null peer.create_client("ws://" + _host_edit.text + ":" + str(DEF_PORT)) multiplayer.multiplayer_peer = peer diff --git a/plugins/.gitignore b/plugins/.gitignore new file mode 100644 index 00000000..0e3782ac --- /dev/null +++ b/plugins/.gitignore @@ -0,0 +1,2 @@ +# "Silly Material" files written by the editor plugin +*.silly_mat diff --git a/plugins/addons/custom_node/heart.gd b/plugins/addons/custom_node/heart.gd index 17edbf32..99f5cb56 100644 --- a/plugins/addons/custom_node/heart.gd +++ b/plugins/addons/custom_node/heart.gd @@ -1,12 +1,12 @@ @tool extends Node2D -var heart = preload("res://addons/custom_node/heart.png") - -func _draw(): - draw_texture(heart, -heart.get_size() / 2) +const HEART_TEXTURE := preload("res://addons/custom_node/heart.png") -func _get_item_rect(): - # override - return Rect2(-heart.get_size() / 2, heart.get_size()) +func _draw() -> void: + draw_texture(HEART_TEXTURE, -HEART_TEXTURE.get_size() / 2) + + +func _get_item_rect() -> Rect2: + return Rect2(-HEART_TEXTURE.get_size() / 2, HEART_TEXTURE.get_size()) diff --git a/plugins/addons/custom_node/heart_plugin.gd b/plugins/addons/custom_node/heart_plugin.gd index 1b73d873..c0961bfc 100644 --- a/plugins/addons/custom_node/heart_plugin.gd +++ b/plugins/addons/custom_node/heart_plugin.gd @@ -1,11 +1,12 @@ @tool extends EditorPlugin -func _enter_tree(): - # When this plugin node enters tree, add the custom type + +func _enter_tree() -> void: + # When this plugin node enters tree, add the custom type. add_custom_type("Heart", "Node2D", preload("res://addons/custom_node/heart.gd"), preload("res://addons/custom_node/heart_icon.png")) -func _exit_tree(): - # When the plugin node exits the tree, remove the custom type +func _exit_tree() -> void: + # When the plugin node exits the tree, remove the custom type. remove_custom_type("Heart") diff --git a/plugins/addons/main_screen/main_panel.tscn b/plugins/addons/main_screen/main_panel.tscn index f3abc1f6..e706e0eb 100644 --- a/plugins/addons/main_screen/main_panel.tscn +++ b/plugins/addons/main_screen/main_panel.tscn @@ -12,10 +12,6 @@ size_flags_vertical = 3 [node name="PrintHello" type="Button" parent="."] layout_mode = 2 -offset_left = 460.0 -offset_top = 297.0 -offset_right = 691.0 -offset_bottom = 351.0 text = "Print Hello (check Output bottom panel)" script = ExtResource("1") diff --git a/plugins/addons/main_screen/main_screen_plugin.gd b/plugins/addons/main_screen/main_screen_plugin.gd index b5d2c83e..5e5ad451 100644 --- a/plugins/addons/main_screen/main_screen_plugin.gd +++ b/plugins/addons/main_screen/main_screen_plugin.gd @@ -3,9 +3,10 @@ extends EditorPlugin const MainPanel = preload("res://addons/main_screen/main_panel.tscn") -var main_panel_instance +var main_panel_instance: CenterContainer -func _enter_tree(): + +func _enter_tree() -> void: main_panel_instance = MainPanel.instantiate() # Add the main panel to the editor's main viewport. get_editor_interface().get_editor_main_screen().add_child(main_panel_instance) @@ -13,29 +14,28 @@ func _enter_tree(): _make_visible(false) -func _exit_tree(): +func _exit_tree() -> void: if main_panel_instance: main_panel_instance.queue_free() -func _has_main_screen(): +func _has_main_screen() -> bool: return true -func _make_visible(visible): +func _make_visible(visible: bool) -> void: if main_panel_instance: main_panel_instance.visible = visible # If your plugin doesn't handle any node types, you can remove this method. -func _handles(object): +func _handles(object: Object) -> bool: return is_instance_of(object, preload("res://addons/main_screen/handled_by_main_screen.gd")) -func _get_plugin_name(): +func _get_plugin_name() -> String: return "Main Screen Plugin" -func _get_plugin_icon(): - # Must return some kind of Texture2D for the icon. +func _get_plugin_icon() -> Texture2D: return get_editor_interface().get_base_control().get_theme_icon("Node", "EditorIcons") diff --git a/plugins/addons/main_screen/print_hello.gd b/plugins/addons/main_screen/print_hello.gd index 59fbfaaa..d6b7f961 100644 --- a/plugins/addons/main_screen/print_hello.gd +++ b/plugins/addons/main_screen/print_hello.gd @@ -1,5 +1,6 @@ @tool extends Button -func _on_PrintHello_pressed(): + +func _on_PrintHello_pressed() -> void: print("Hello from the main screen plugin!") diff --git a/plugins/addons/material_creator/material_creator.gd b/plugins/addons/material_creator/material_creator.gd index 9c5d1661..efe117ee 100644 --- a/plugins/addons/material_creator/material_creator.gd +++ b/plugins/addons/material_creator/material_creator.gd @@ -3,73 +3,74 @@ extends Panel # In this file, the word "silly" is used to make it obvious that the name is arbitrary. var silly_material_resource = preload("res://addons/material_creator/material_resource.gd") -var editor_interface +var editor_interface: EditorInterface -func _ready(): + +func _ready() -> void: # Connect all of the signals we'll need to save and load silly materials. - get_node(^"VBoxContainer/ApplyButton").pressed.connect(apply_pressed) - get_node(^"VBoxContainer/SaveButton").pressed.connect(save_pressed) - get_node(^"VBoxContainer/LoadButton").pressed.connect(load_pressed) - get_node(^"SaveMaterialDialog").file_selected.connect(save_file_selected) - get_node(^"LoadMaterialDialog").file_selected.connect(load_file_selected) + $VBoxContainer/ApplyButton.pressed.connect(apply_pressed) + $VBoxContainer/SaveButton.pressed.connect(save_pressed) + $VBoxContainer/LoadButton.pressed.connect(load_pressed) + $SaveMaterialDialog.file_selected.connect(save_file_selected) + $LoadMaterialDialog.file_selected.connect(load_file_selected) RenderingServer.canvas_item_set_clip(get_canvas_item(), true) -func save_pressed(): - get_node(^"SaveMaterialDialog").popup_centered_ratio() +func save_pressed() -> void: + $SaveMaterialDialog.popup_centered_ratio() -func load_pressed(): - get_node(^"LoadMaterialDialog").popup_centered_ratio() +func load_pressed() -> void: + $LoadMaterialDialog.popup_centered_ratio() -func apply_pressed(): +func apply_pressed() -> void: # Using the passed in editor interface, get the selected nodes in the editor. - var editor_selection = editor_interface.get_selection() - var selected_nodes = editor_selection.get_selected_nodes() + var editor_selection: EditorSelection = editor_interface.get_selection() + var selected_nodes := editor_selection.get_selected_nodes() if selected_nodes.is_empty(): push_error("Material Creator: Can't apply the material, because there are no nodes selected!") - var material = _silly_resource_from_values().make_material() + var new_material: StandardMaterial3D = _silly_resource_from_values().make_material() # Go through the selected nodes and see if they have the "set_surface_override_material" # function (which only MeshInstance3D has by default). If they do, then set the material # to the silly material. for node in selected_nodes: if node.has_method("set_surface_override_material"): - node.set_surface_override_material(0, material) + node.set_surface_override_material(0, new_material) -func save_file_selected(path): - var silly_resource = _silly_resource_from_values() +func save_file_selected(path: String) -> bool: + var silly_resource: Variant = _silly_resource_from_values() # Make a file, store the silly material as a JSON string. - var file = FileAccess.open(path, FileAccess.WRITE) + var file := FileAccess.open(path, FileAccess.WRITE) file.store_string(silly_resource.make_json()) return true -func load_file_selected(path): - var SpatialMaterial_Silly = null +func load_file_selected(path: String) -> bool: + var SpatialMaterial_Silly: StandardMaterial3D = null # Make a new silly resource (which in this case actually is a node) # and initialize it. - var silly_resource = silly_material_resource.new() - silly_resource.init() + var silly_resource: Variant = silly_material_resource.new() + #silly_resource.init() # If the file exists, then open it. if FileAccess.file_exists(path): - var file = FileAccess.open(path, FileAccess.READ) + var file := FileAccess.open(path, FileAccess.READ) # Get the JSON string and convert it into a silly material. - var json_dict_as_string = file.get_line() + var json_dict_as_string := file.get_line() if json_dict_as_string != null: silly_resource.from_json(json_dict_as_string) else: return false - get_node(^"VBoxContainer/AlbedoColorPicker").color = silly_resource.albedo_color - get_node(^"VBoxContainer/MetallicSlider").value = silly_resource.metallic_strength - get_node(^"VBoxContainer/RoughnessSlider").value = silly_resource.roughness_strength + $VBoxContainer/AlbedoColorPicker.color = silly_resource.albedo_color + $VBoxContainer/MetallicSlider.value = silly_resource.metallic_strength + $VBoxContainer/RoughnessSlider.value = silly_resource.roughness_strength # Return `true` to indicate success. return true @@ -78,14 +79,14 @@ func load_file_selected(path): return false -func _silly_resource_from_values(): +func _silly_resource_from_values() -> Variant: # Get the values from the sliders and color picker. - var color = get_node(^"VBoxContainer/AlbedoColorPicker").color - var metallic = get_node(^"VBoxContainer/MetallicSlider").value - var roughness = get_node(^"VBoxContainer/RoughnessSlider").value + var color: Color = $VBoxContainer/AlbedoColorPicker.color + var metallic: float = $VBoxContainer/MetallicSlider.value + var roughness: float = $VBoxContainer/RoughnessSlider.value # Make a new silly resource (which in this case actually is a node) and initialize it. - var silly_resource = silly_material_resource.new() - silly_resource.init() + var silly_resource: Variant = silly_material_resource.new() + #silly_resource.init() # Assign the values. silly_resource.albedo_color = color diff --git a/plugins/addons/material_creator/material_dock.tscn b/plugins/addons/material_creator/material_dock.tscn index 929564fa..3ecc8bc5 100644 --- a/plugins/addons/material_creator/material_dock.tscn +++ b/plugins/addons/material_creator/material_dock.tscn @@ -3,6 +3,7 @@ [ext_resource type="Script" path="res://addons/material_creator/material_creator.gd" id="1"] [node name="Material Creator" type="Panel"] +custom_minimum_size = Vector2(208, 0) offset_right = 220.0 offset_bottom = 340.0 script = ExtResource("1") diff --git a/plugins/addons/material_creator/material_plugin.gd b/plugins/addons/material_creator/material_plugin.gd index 944a3da5..d5135b37 100644 --- a/plugins/addons/material_creator/material_plugin.gd +++ b/plugins/addons/material_creator/material_plugin.gd @@ -11,13 +11,14 @@ @tool extends EditorPlugin -var io_material_dialog +var io_material_dialog: Panel -func _enter_tree(): + +func _enter_tree() -> void: io_material_dialog = preload("res://addons/material_creator/material_dock.tscn").instantiate() io_material_dialog.editor_interface = get_editor_interface() add_control_to_dock(DOCK_SLOT_LEFT_UL, io_material_dialog) -func _exit_tree(): +func _exit_tree() -> void: remove_control_from_docks(io_material_dialog) diff --git a/plugins/addons/material_creator/material_resource.gd b/plugins/addons/material_creator/material_resource.gd index 5e5d78e9..4cdef99a 100644 --- a/plugins/addons/material_creator/material_resource.gd +++ b/plugins/addons/material_creator/material_resource.gd @@ -1,26 +1,19 @@ @tool extends Node - -# NOTE: in theory this would extend from resource, but until saving and loading resources -# works in godot, we'll stick with extending from node -# and using JSON files to save/load data +# NOTE: In theory, this would extend from Resource, but until saving and loading resources +# works in Godot, we'll stick with extending from Node and using JSON files to save/load data. # -# See material_import.gd for more information +# See `material_import.gd` for more information. -var albedo_color -var metallic_strength -var roughness_strength - -func init(): - albedo_color = Color() - metallic_strength = 0 - roughness_strength = 0 +var albedo_color := Color.BLACK +var metallic_strength := 0.0 +var roughness_strength := 0.0 # Convert our data into an dictonary so we can convert it -# into the JSON format -func make_json(): - var json_dict = {} +# into the JSON format. +func make_json() -> String: + var json_dict := {} json_dict["albedo_color"] = {} json_dict["albedo_color"]["r"] = albedo_color.r @@ -30,15 +23,13 @@ func make_json(): json_dict["metallic_strength"] = metallic_strength json_dict["roughness_strength"] = roughness_strength - return JSON.new().stringify(json_dict) + return JSON.stringify(json_dict) -# Convert the passed in string to a json dictonary, and then +# Convert the passed in string to a JSON dictonary, and then # fill in our data. -func from_json(json_dict_as_string): - var json = JSON.new() - json.parse(json_dict_as_string) - var json_dict = json.get_data() +func from_json(json_dict_as_string: String) -> void: + var json_dict: Dictionary = JSON.parse_string(json_dict_as_string) albedo_color.r = json_dict["albedo_color"]["r"] albedo_color.g = json_dict["albedo_color"]["g"] @@ -49,11 +40,11 @@ func from_json(json_dict_as_string): # Make a StandardMaterial3D using our variables. -func make_material(): - var mat = StandardMaterial3D.new() +func make_material() -> StandardMaterial3D: + var material := StandardMaterial3D.new() - mat.albedo_color = albedo_color - mat.metallic = metallic_strength - mat.roughness = roughness_strength + material.albedo_color = albedo_color + material.metallic = metallic_strength + material.roughness = roughness_strength - return mat + return material diff --git a/plugins/addons/material_import_plugin/import.gd b/plugins/addons/material_import_plugin/import.gd index 9dae2900..57cbcc95 100644 --- a/plugins/addons/material_import_plugin/import.gd +++ b/plugins/addons/material_import_plugin/import.gd @@ -1,66 +1,72 @@ @tool extends EditorImportPlugin -enum Presets { PRESET_DEFAULT } +enum Preset { + PRESET_DEFAULT, +} -func _get_importer_name(): + +func _get_importer_name() -> String: return "demos.sillymaterial" -func _get_visible_name(): +func _get_visible_name() -> String: return "Silly Material" -func _get_recognized_extensions(): +func _get_recognized_extensions() -> PackedStringArray: return ["mtxt"] -func _get_save_extension(): +func _get_save_extension() -> String: return "res" -func _get_resource_type(): +func _get_resource_type() -> String: return "Material" -func _get_preset_count(): - return Presets.size() +func _get_preset_count() -> int: + return Preset.size() -func _get_preset_name(preset): +func _get_preset_name(preset: Preset) -> String: match preset: - Presets.PRESET_DEFAULT: return "Default" - _: return "Unknown" + Preset.PRESET_DEFAULT: + return "Default" + _: + return "Unknown" -func _get_import_options(_path, preset): +func _get_import_options(_path: String, preset: Preset) -> Array[Dictionary]: match preset: - Presets.PRESET_DEFAULT: + Preset.PRESET_DEFAULT: return [{ - "name": "use_red_anyway", - "default_value": false - }] - _: return [] + "name": "use_red_anyway", + "default_value": false, + }] + _: + return [] -func _get_import_order(): +func _get_import_order() -> int: return ResourceImporter.IMPORT_ORDER_DEFAULT -func _get_option_visibility(path, option, options): +func _get_option_visibility(path: String, option: StringName, options: Dictionary) -> bool: return true -func _import(source_file, save_path, options, r_platform_variants, r_gen_files): - var file = FileAccess.open(source_file, FileAccess.READ) - var line = file.get_line() +func _import(source_file: String, save_path: String, options: Dictionary, r_platform_variants: Array[String], r_gen_files: Array[String]) -> Error: + var file := FileAccess.open(source_file, FileAccess.READ) + var line := file.get_line() - var channels = line.split(",") + var channels := line.split(",") if channels.size() != 3: return ERR_PARSE_ERROR - var color = Color8(int(channels[0]), int(channels[1]), int(channels[2])) - var material = StandardMaterial3D.new() + var color := Color8(int(channels[0]), int(channels[1]), int(channels[2])) + var material := StandardMaterial3D.new() if options.use_red_anyway: color = Color8(255, 0, 0) diff --git a/plugins/addons/material_import_plugin/plugin.gd b/plugins/addons/material_import_plugin/plugin.gd index e2029bd2..c75edd66 100644 --- a/plugins/addons/material_import_plugin/plugin.gd +++ b/plugins/addons/material_import_plugin/plugin.gd @@ -1,13 +1,14 @@ @tool extends EditorPlugin -var import_plugin +var import_plugin: EditorImportPlugin -func _enter_tree(): + +func _enter_tree() -> void: import_plugin = preload("import.gd").new() add_import_plugin(import_plugin) -func _exit_tree(): +func _exit_tree() -> void: remove_import_plugin(import_plugin) import_plugin = null diff --git a/plugins/project.godot b/plugins/project.godot index 4cef69fc..c0c226f6 100644 --- a/plugins/project.godot +++ b/plugins/project.godot @@ -25,9 +25,13 @@ run/main_scene="res://test_scene.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [editor_plugins] -enabled=PackedStringArray("res://addons/main_screen/plugin.cfg", "res://addons/material_creator/plugin.cfg", "res://addons/material_import_plugin/plugin.cfg", "res://addons/custom_node/plugin.cfg") +enabled=PackedStringArray("res://addons/custom_node/plugin.cfg", "res://addons/main_screen/plugin.cfg", "res://addons/material_creator/plugin.cfg", "res://addons/material_import_plugin/plugin.cfg") [rendering] diff --git a/plugins/test_scene.tscn b/plugins/test_scene.tscn index 10608e80..d680b9c0 100644 --- a/plugins/test_scene.tscn +++ b/plugins/test_scene.tscn @@ -12,7 +12,6 @@ script = ExtResource("2") [node name="MeshInstance3D" type="MeshInstance3D" parent="."] mesh = SubResource("1") -skeleton = NodePath("") [node name="HandledByMainScreen" type="Node" parent="."] script = ExtResource("1") diff --git a/viewport/2d_in_3d/2d_in_3d.gd b/viewport/2d_in_3d/2d_in_3d.gd index 341310d2..16a236bf 100644 --- a/viewport/2d_in_3d/2d_in_3d.gd +++ b/viewport/2d_in_3d/2d_in_3d.gd @@ -1,9 +1,23 @@ extends Node3D -func _ready(): +## Camera idle scale effect intensity. +const CAMERA_IDLE_SCALE = 0.005 + +var counter := 0.0 +@onready var camera_base_rotation: Vector3 = $Camera3D.rotation + +func _ready() -> void: # Clear the viewport. - var viewport = $SubViewport - $SubViewport.set_clear_mode(SubViewport.CLEAR_MODE_ONCE) + var viewport: SubViewport = $SubViewport + viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_ONCE # Retrieve the texture and set it to the viewport quad. $ViewportQuad.material_override.albedo_texture = viewport.get_texture() + + +func _process(delta: float) -> void: + # Animate the camera with an "idle" animation. + counter += delta + $Camera3D.rotation.x = camera_base_rotation.y + cos(counter) * CAMERA_IDLE_SCALE + $Camera3D.rotation.y = camera_base_rotation.y + sin(counter) * CAMERA_IDLE_SCALE + $Camera3D.rotation.z = camera_base_rotation.y + sin(counter) * CAMERA_IDLE_SCALE diff --git a/viewport/2d_in_3d/2d_in_3d.tscn b/viewport/2d_in_3d/2d_in_3d.tscn index 69a0f374..2d370f51 100644 --- a/viewport/2d_in_3d/2d_in_3d.tscn +++ b/viewport/2d_in_3d/2d_in_3d.tscn @@ -66,9 +66,8 @@ tonemap_white = 2.0 script = ExtResource("1_b8rgl") [node name="Camera3D" type="Camera3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.35, 0.6) -fov = 62.0 -near = 0.1 +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.35, 0.5) +fov = 60.0 [node name="ViewportQuad" type="MeshInstance3D" parent="."] transform = Transform3D(2, 0, 0, 0, 0, -1.333, 0, 1, 0, 0, 1.2, -4.25) diff --git a/viewport/2d_in_3d/pong.gd b/viewport/2d_in_3d/pong.gd index 03561353..9ce08dc8 100644 --- a/viewport/2d_in_3d/pong.gd +++ b/viewport/2d_in_3d/pong.gd @@ -1,29 +1,29 @@ extends Node2D const PAD_SPEED = 150 -const INITIAL_BALL_SPEED = 80 +const INITIAL_BALL_SPEED = 80.0 -var ball_speed = INITIAL_BALL_SPEED -var screen_size = Vector2(640, 400) +var ball_speed := INITIAL_BALL_SPEED +var screen_size := Vector2(640, 400) # Default ball direction. -var direction = Vector2.LEFT -var pad_size = Vector2(8, 32) +var direction := Vector2.LEFT +var pad_size := Vector2(8, 32) -@onready var ball = $Ball -@onready var left_paddle = $LeftPaddle -@onready var right_paddle = $RightPaddle +@onready var ball: Sprite2D = $Ball +@onready var left_paddle: Sprite2D = $LeftPaddle +@onready var right_paddle: Sprite2D = $RightPaddle -func _ready(): - screen_size = get_viewport_rect().size # Get actual size. +func _ready() -> void: + screen_size = get_viewport_rect().size # Get actual size. pad_size = left_paddle.get_texture().get_size() -func _process(delta): +func _process(delta: float) -> void: # Get ball position and pad rectangles. - var ball_pos = ball.get_position() - var left_rect = Rect2(left_paddle.get_position() - pad_size * 0.5, pad_size) - var right_rect = Rect2(right_paddle.get_position() - pad_size * 0.5, pad_size) + var ball_pos := ball.get_position() + var left_rect := Rect2(left_paddle.get_position() - pad_size * 0.5, pad_size) + var right_rect := Rect2(right_paddle.get_position() - pad_size * 0.5, pad_size) # Integrate new ball postion. ball_pos += direction * ball_speed * delta @@ -48,7 +48,7 @@ func _process(delta): ball.set_position(ball_pos) # Move left pad. - var left_pos = left_paddle.get_position() + var left_pos := left_paddle.get_position() if left_pos.y > 0 and Input.is_action_pressed(&"left_move_up"): left_pos.y += -PAD_SPEED * delta @@ -58,7 +58,7 @@ func _process(delta): left_paddle.set_position(left_pos) # Move right pad. - var right_pos = right_paddle.get_position() + var right_pos := right_paddle.get_position() if right_pos.y > 0 and Input.is_action_pressed(&"right_move_up"): right_pos.y += -PAD_SPEED * delta if right_pos.y < screen_size.y and Input.is_action_pressed(&"right_move_down"): diff --git a/viewport/2d_in_3d/project.godot b/viewport/2d_in_3d/project.godot index aee5852c..7b2966c3 100644 --- a/viewport/2d_in_3d/project.godot +++ b/viewport/2d_in_3d/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://2d_in_3d.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [input] left_move_up={ diff --git a/viewport/3d_in_2d/3d_in_2d.gd b/viewport/3d_in_2d/3d_in_2d.gd index 0d6d2d0c..2f5aa060 100644 --- a/viewport/3d_in_2d/3d_in_2d.gd +++ b/viewport/3d_in_2d/3d_in_2d.gd @@ -1,19 +1,18 @@ extends Node2D -var viewport_initial_size = Vector2() +@onready var viewport: SubViewport = $SubViewport +@onready var viewport_initial_size: Vector2i = viewport.size +@onready var viewport_sprite: Sprite2D = $ViewportSprite -@onready var viewport = $SubViewport -@onready var viewport_sprite = $ViewportSprite -func _ready(): +func _ready() -> void: $AnimatedSprite2D.play() get_viewport().size_changed.connect(_root_viewport_size_changed) - viewport_initial_size = viewport.size # Called when the root's viewport size changes (i.e. when the window is resized). # This is done to handle multiple resolutions without losing quality. -func _root_viewport_size_changed(): +func _root_viewport_size_changed() -> void: # The viewport is resized depending on the window height. # To compensate for the larger resolution, the viewport sprite is scaled down. viewport.size = Vector2.ONE * get_viewport().size.y diff --git a/viewport/3d_in_2d/project.godot b/viewport/3d_in_2d/project.godot index e6b9fffa..3b20f369 100644 --- a/viewport/3d_in_2d/project.godot +++ b/viewport/3d_in_2d/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://3d_in_2d.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/viewport/3d_in_2d/robot_3d.gd b/viewport/3d_in_2d/robot_3d.gd index 7938767c..b7869847 100644 --- a/viewport/3d_in_2d/robot_3d.gd +++ b/viewport/3d_in_2d/robot_3d.gd @@ -1,7 +1,8 @@ extends Node +## A simple script that rotates the model. -# A simple script to rotate the model. -@onready var model = $Model +@onready var model: Node3D = $Model -func _process(delta): - model.rotate_y(delta * 0.7) + +func _process(delta: float) -> void: + model.rotation.y += delta * 0.7 diff --git a/viewport/3d_scaling/cubes.tscn b/viewport/3d_scaling/cubes.tscn index 8cdc8107..67bd2da9 100644 --- a/viewport/3d_scaling/cubes.tscn +++ b/viewport/3d_scaling/cubes.tscn @@ -108,7 +108,7 @@ mesh = SubResource("1") [node name="Camera3D" type="Camera3D" parent="."] transform = Transform3D(0.877582, 0.229849, -0.420736, 0, 0.877582, 0.479426, 0.479426, -0.420736, 0.770151, -1.68294, 2.25571, 3.0806) -fov = 74.0 +fov = 60.0 [node name="OmniLight3D" type="OmniLight3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.3, 2, 1) diff --git a/viewport/3d_scaling/hud.gd b/viewport/3d_scaling/hud.gd index 2688cd2d..4cee9837 100644 --- a/viewport/3d_scaling/hud.gd +++ b/viewport/3d_scaling/hud.gd @@ -1,28 +1,28 @@ extends Control +## The 3D viewport's shrink factor. For instance, 1 is full resolution, +## 2 is half resolution and 4 is quarter resolution. Lower values look +## sharper but are slower to render. +var scale_factor := 1 -# The 3D viewport's shrink factor. For instance, 1 is full resolution, -# 2 is half resolution and 4 is quarter resolution. Lower values look -# sharper but are slower to render. -var scale_factor = 1 -var filter_mode = Viewport.SCALING_3D_MODE_BILINEAR +var filter_mode := Viewport.SCALING_3D_MODE_BILINEAR -@onready var viewport = get_tree().root -@onready var scale_label = $VBoxContainer/Scale -@onready var filter_label = $VBoxContainer/Filter +@onready var viewport: Window = get_tree().root +@onready var scale_label: Label = $VBoxContainer/Scale +@onready var filter_label: Label = $VBoxContainer/Filter -func _ready(): - viewport.scaling_3d_mode = Viewport.SCALING_3D_MODE_BILINEAR +func _ready() -> void: + viewport.scaling_3d_mode = filter_mode -func _unhandled_input(event): - if event.is_action_pressed("cycle_viewport_resolution"): +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed(&"cycle_viewport_resolution"): scale_factor = wrapi(scale_factor + 1, 1, 5) viewport.scaling_3d_scale = 1.0 / scale_factor scale_label.text = "Scale: %3.0f%%" % (100.0 / scale_factor) - if event.is_action_pressed("toggle_filtering"): + if event.is_action_pressed(&"toggle_filtering"): filter_mode = wrapi(filter_mode + 1, Viewport.SCALING_3D_MODE_BILINEAR, Viewport.SCALING_3D_MODE_MAX) as Viewport.Scaling3DMode viewport.scaling_3d_mode = filter_mode filter_label.text = ( diff --git a/viewport/3d_scaling/project.godot b/viewport/3d_scaling/project.godot index d21ed862..6032a98b 100644 --- a/viewport/3d_scaling/project.godot +++ b/viewport/3d_scaling/project.godot @@ -21,6 +21,10 @@ run/main_scene="res://hud.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/viewport/dynamic_split_screen/camera_controller.gd b/viewport/dynamic_split_screen/camera_controller.gd index 6a922f42..239c7a6d 100644 --- a/viewport/dynamic_split_screen/camera_controller.gd +++ b/viewport/dynamic_split_screen/camera_controller.gd @@ -1,5 +1,4 @@ extends Node3D - # Handle the motion of both player cameras as well as communication with the # SplitScreen shader to achieve the dynamic split screen effet # @@ -19,22 +18,22 @@ extends Node3D # depending on the distance between players. If false, the thickness will # be constant and equal to split_line_thickness -@export var max_separation: float = 20.0 -@export var split_line_thickness: float = 3.0 -@export var split_line_color: Color = Color.BLACK -@export var adaptive_split_line_thickness: bool = true +@export var max_separation := 20.0 +@export var split_line_thickness := 3.0 +@export var split_line_color := Color.BLACK +@export var adaptive_split_line_thickness := true -@onready var player1 = $"../Player1" -@onready var player2 = $"../Player2" -@onready var view = $View -@onready var viewport1 = $Viewport1 -@onready var viewport2 = $Viewport2 -@onready var camera1 = viewport1.get_node(^"Camera1") -@onready var camera2 = viewport2.get_node(^"Camera2") +@onready var player1: CharacterBody3D = $"../Player1" +@onready var player2: CharacterBody3D = $"../Player2" +@onready var view: TextureRect = $View +@onready var viewport1: SubViewport = $Viewport1 +@onready var viewport2: SubViewport = $Viewport2 +@onready var camera1: Camera3D = viewport1.get_node(^"Camera1") +@onready var camera2: Camera3D = viewport2.get_node(^"Camera2") -var viewport_base_height = ProjectSettings.get_setting("display/window/size/viewport_height") +var viewport_base_height := int(ProjectSettings.get_setting("display/window/size/viewport_height")) -func _ready(): +func _ready() -> void: _on_size_changed() _update_splitscreen() @@ -44,15 +43,15 @@ func _ready(): view.material.set_shader_parameter("viewport2", viewport2.get_texture()) -func _process(_delta): +func _process(_delta: float) -> void: _move_cameras() _update_splitscreen() -func _move_cameras(): - var position_difference = _compute_position_difference_in_world() +func _move_cameras() -> void: + var position_difference := _get_position_difference_in_world() - var distance = clamp(_compute_horizontal_length(position_difference), 0, max_separation) + var distance := clampf(_get_horizontal_length(position_difference), 0, max_separation) position_difference = position_difference.normalized() * distance @@ -63,37 +62,38 @@ func _move_cameras(): camera2.position.z = player2.position.z - position_difference.z / 2.0 -func _update_splitscreen(): - var screen_size = get_viewport().get_visible_rect().size - var player1_position = camera1.unproject_position(player1.position) / screen_size - var player2_position = camera2.unproject_position(player2.position) / screen_size +func _update_splitscreen() -> void: + var screen_size := get_viewport().get_visible_rect().size + var player1_position := camera1.unproject_position(player1.position) / screen_size + var player2_position := camera2.unproject_position(player2.position) / screen_size - var thickness + var thickness := 0.0 if adaptive_split_line_thickness: - var position_difference = _compute_position_difference_in_world() - var distance = _compute_horizontal_length(position_difference) + var position_difference := _get_position_difference_in_world() + var distance := _get_horizontal_length(position_difference) thickness = lerpf(0, split_line_thickness, (distance - max_separation) / max_separation) thickness = clampf(thickness, 0, split_line_thickness) else: thickness = split_line_thickness - view.material.set_shader_parameter("split_active", _get_split_state()) + view.material.set_shader_parameter("split_active", _is_split_state()) view.material.set_shader_parameter("player1_position", player1_position) view.material.set_shader_parameter("player2_position", player2_position) view.material.set_shader_parameter("split_line_thickness", thickness) view.material.set_shader_parameter("split_line_color", split_line_color) -# Split screen is active if players are too far apart from each other. -# Only the horizontal components (x, z) are used for distance computation -func _get_split_state(): - var position_difference = _compute_position_difference_in_world() - var separation_distance = _compute_horizontal_length(position_difference) +## Returns `true` if split screen is active (which occurs when players are +## too far apart from each other), `false` otherwise. +## Only the horizontal components (x, z) are used for distance computation. +func _is_split_state() -> bool: + var position_difference := _get_position_difference_in_world() + var separation_distance := _get_horizontal_length(position_difference) return separation_distance > max_separation -func _on_size_changed(): - var screen_size = get_viewport().get_visible_rect().size +func _on_size_changed() -> void: + var screen_size := get_viewport().get_visible_rect().size $Viewport1.size = screen_size $Viewport2.size = screen_size @@ -101,9 +101,9 @@ func _on_size_changed(): view.material.set_shader_parameter("viewport_size", screen_size) -func _compute_position_difference_in_world(): +func _get_position_difference_in_world() -> Vector3: return player2.position - player1.position -func _compute_horizontal_length(vec): +func _get_horizontal_length(vec: Vector3) -> float: return Vector2(vec.x, vec.z).length() diff --git a/viewport/dynamic_split_screen/player.gd b/viewport/dynamic_split_screen/player.gd index a199d839..03cfc0a5 100644 --- a/viewport/dynamic_split_screen/player.gd +++ b/viewport/dynamic_split_screen/player.gd @@ -2,16 +2,16 @@ extends CharacterBody3D # Moves the player -@export_range(1, 2) var player_id: int = 1 -@export var walk_speed: float = 2 +@export_range(1, 2) var player_id := 1 +@export var walk_speed := 2.0 -func _physics_process(_delta): - var move_direction = Input.get_vector( - "move_left_player" + str(player_id), - "move_right_player" + str(player_id), - "move_up_player" + str(player_id), - "move_down_player" + str(player_id), +func _physics_process(_delta: float) -> void: + var move_direction := Input.get_vector( + &"move_left_player" + str(player_id), + &"move_right_player" + str(player_id), + &"move_up_player" + str(player_id), + &"move_down_player" + str(player_id), ) velocity.x += move_direction.x * walk_speed velocity.z += move_direction.y * walk_speed diff --git a/viewport/dynamic_split_screen/project.godot b/viewport/dynamic_split_screen/project.godot index feb0a6e5..1e347135 100644 --- a/viewport/dynamic_split_screen/project.godot +++ b/viewport/dynamic_split_screen/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://split_screen.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [input] move_up_player1={ @@ -86,5 +90,4 @@ common/physics_ticks_per_second=120 renderer/rendering_method="gl_compatibility" renderer/rendering_method.mobile="gl_compatibility" lights_and_shadows/directional_shadow/soft_shadow_filter_quality=4 -environment/defaults/default_clear_color=Color(1, 1, 1, 1) anti_aliasing/quality/msaa_3d=2 diff --git a/viewport/dynamic_split_screen/split_screen.tscn b/viewport/dynamic_split_screen/split_screen.tscn index 912eeebc..e73389bd 100644 --- a/viewport/dynamic_split_screen/split_screen.tscn +++ b/viewport/dynamic_split_screen/split_screen.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=63 format=3 uid="uid://dksa68cph6y4b"] +[gd_scene load_steps=67 format=3 uid="uid://dksa68cph6y4b"] [ext_resource type="Script" path="res://camera_controller.gd" id="2"] [ext_resource type="Shader" path="res://split_screen.gdshader" id="3"] @@ -13,14 +13,12 @@ ground_horizon_color = Color(0.64625, 0.65575, 0.67075, 1) sky_material = SubResource("ProceduralSkyMaterial_16la2") [sub_resource type="Environment" id="Environment_vdrvu"] -background_mode = 2 sky = SubResource("Sky_i64ko") -ambient_light_source = 2 +ambient_light_source = 3 ambient_light_color = Color(0.79, 0.8775, 1, 1) -ambient_light_sky_contribution = 0.0 ambient_light_energy = 0.33 +reflected_light_source = 2 tonemap_mode = 2 -glow_enabled = true [sub_resource type="ShaderMaterial" id="1"] shader = ExtResource("3") @@ -67,6 +65,24 @@ emission = Color(0.12549, 0.501961, 1, 1) material = SubResource("6") size = Vector2(200, 200) +[sub_resource type="Gradient" id="Gradient_3phjx"] +offsets = PackedFloat32Array(0.139344, 0.196721, 0.237705, 0.377049, 0.598361, 0.795082, 1) +colors = PackedColorArray(0.08, 0.432667, 1, 1, 0.945098, 1, 0.929412, 1, 0.574026, 0.479268, 0.220411, 1, 1, 0.7525, 0.45, 1, 0.0322, 0.23, 0.0322, 1, 0.181569, 0.353991, 0.245845, 1, 1, 1, 1, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_2bwlb"] +noise_type = 4 +domain_warp_enabled = true +domain_warp_frequency = 0.002 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_ha3y6"] +seamless = true +color_ramp = SubResource("Gradient_3phjx") +noise = SubResource("FastNoiseLite_2bwlb") + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_i0wmt"] +albedo_texture = SubResource("NoiseTexture2D_ha3y6") +uv1_scale = Vector3(64, 64, 64) + [sub_resource type="BoxShape3D" id="8"] [sub_resource type="BoxShape3D" id="9"] @@ -265,6 +281,17 @@ surface_material_override/0 = SubResource("StandardMaterial3D_63nwq") [node name="OmniLight3D" type="OmniLight3D" parent="Player1"] light_color = Color(1, 0, 0, 1) +light_energy = 2.5 +omni_range = 10.0 + +[node name="Label3D" type="Label3D" parent="Player1"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +pixel_size = 0.01 +offset = Vector2(0, 50) +billboard = 1 +double_sided = false +modulate = Color(1, 0.323333, 0.3, 1) +text = "P1" [node name="Player2" type="CharacterBody3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.184, 0.875, 3.019) @@ -286,12 +313,24 @@ surface_material_override/0 = SubResource("StandardMaterial3D_wi7e2") [node name="OmniLight3D" type="OmniLight3D" parent="Player2"] light_color = Color(0.12549, 0.501961, 1, 1) +light_energy = 2.5 +omni_range = 10.0 + +[node name="Label3D" type="Label3D" parent="Player2"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +pixel_size = 0.01 +offset = Vector2(0, 50) +billboard = 1 +double_sided = false +modulate = Color(0.3, 0.65, 1, 1) +text = "P2" [node name="Ground" type="StaticBody3D" parent="."] [node name="Mesh" type="MeshInstance3D" parent="Ground"] transform = Transform3D(20, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0) mesh = SubResource("7") +surface_material_override/0 = SubResource("StandardMaterial3D_i0wmt") [node name="CollisionShape3D" type="CollisionShape3D" parent="Ground"] transform = Transform3D(200, 0, 0, 0, 1, 0, 0, 0, 200, 0, -1, 0) diff --git a/viewport/dynamic_split_screen/wall_coloring.gd b/viewport/dynamic_split_screen/wall_coloring.gd index f1cfb1d1..dcec3585 100644 --- a/viewport/dynamic_split_screen/wall_coloring.gd +++ b/viewport/dynamic_split_screen/wall_coloring.gd @@ -1,13 +1,13 @@ @tool extends Node3D +## Sets a random color to all objects in the "walls" group. +## To use, attach this script to the "Walls" node. -# Set a random color to all objects in the "walls" group. -# To use, attach this script to the "Walls" node. -func _ready(): - var walls = get_tree().get_nodes_in_group("walls") +func _ready() -> void: + var walls := get_tree().get_nodes_in_group("walls") for wall in walls: - var material = StandardMaterial3D.new() + var material := StandardMaterial3D.new() material.albedo_color = Color(randf(), randf(), randf()) wall.material_override = material diff --git a/viewport/gui_in_3d/gui_3d.gd b/viewport/gui_in_3d/gui_3d.gd index cbe7e95b..c98de9d9 100644 --- a/viewport/gui_in_3d/gui_3d.gd +++ b/viewport/gui_in_3d/gui_3d.gd @@ -1,17 +1,19 @@ extends Node3D -# Used for checking if the mouse is inside the Area3D. -var is_mouse_inside = false -# The last processed input touch/mouse event. To calculate relative movement. -var last_event_pos2D = null -# The time of the last event in seconds since engine start. -var last_event_time: float = -1.0 +## Used for checking if the mouse is inside the Area3D. +var is_mouse_inside := false -@onready var node_viewport = $SubViewport -@onready var node_quad = $Quad -@onready var node_area = $Quad/Area3D +## The last processed input touch/mouse event. Used to calculate relative movement. +var last_event_pos2D := Vector2() -func _ready(): +## The time of the last event in seconds since engine start. +var last_event_time := -1.0 + +@onready var node_viewport: SubViewport = $SubViewport +@onready var node_quad: MeshInstance3D = $Quad +@onready var node_area: Area3D = $Quad/Area3D + +func _ready() -> void: node_area.mouse_entered.connect(_mouse_entered_area) node_area.mouse_exited.connect(_mouse_exited_area) node_area.input_event.connect(_mouse_input_event) @@ -21,20 +23,20 @@ func _ready(): set_process(false) -func _process(_delta): +func _process(_delta: float) -> void: # NOTE: Remove this function if you don't plan on using billboard settings. rotate_area_to_billboard() -func _mouse_entered_area(): +func _mouse_entered_area() -> void: is_mouse_inside = true -func _mouse_exited_area(): +func _mouse_exited_area() -> void: is_mouse_inside = false -func _unhandled_input(event): +func _unhandled_input(event: InputEvent) -> void: # Check if the event is a non-mouse/non-touch event for mouse_event in [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]: if is_instance_of(event, mouse_event): @@ -44,23 +46,23 @@ func _unhandled_input(event): node_viewport.push_input(event) -func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Vector3, _normal: Vector3, _shape_idx: int): - # Get mesh size to detect edges and make conversions. This code only support PlaneMesh and QuadMesh. - var quad_mesh_size = node_quad.mesh.size +func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Vector3, _normal: Vector3, _shape_idx: int) -> void: + # Get mesh size to detect edges and make conversions. This code only supports PlaneMesh and QuadMesh. + var quad_mesh_size: Vector2 = node_quad.mesh.size # Event position in Area3D in world coordinate space. - var event_pos3D = event_position + var event_pos3D := event_position # Current time in seconds since engine start. - var now: float = Time.get_ticks_msec() / 1000.0 + var now := Time.get_ticks_msec() / 1000.0 # Convert position to a coordinate space relative to the Area3D node. - # NOTE: affine_inverse accounts for the Area3D node's scale, rotation, and position in the scene! + # NOTE: `affine_inverse()` accounts for the Area3D node's scale, rotation, and position in the scene! event_pos3D = node_quad.global_transform.affine_inverse() * event_pos3D # TODO: Adapt to bilboard mode or avoid completely. - var event_pos2D: Vector2 = Vector2() + var event_pos2D := Vector2() if is_mouse_inside: # Convert the relative event position from 3D to 2D. @@ -109,15 +111,15 @@ func _mouse_input_event(_camera: Camera3D, event: InputEvent, event_position: Ve node_viewport.push_input(event) -func rotate_area_to_billboard(): - var billboard_mode = node_quad.get_surface_override_material(0).billboard_mode +func rotate_area_to_billboard() -> void: + var billboard_mode: BaseMaterial3D.BillboardMode = node_quad.get_surface_override_material(0).billboard_mode # Try to match the area with the material's billboard setting, if enabled. if billboard_mode > 0: # Get the camera. - var camera = get_viewport().get_camera_3d() + var camera := get_viewport().get_camera_3d() # Look in the same direction as the camera. - var look = camera.to_global(Vector3(0, 0, -100)) - camera.global_transform.origin + var look := camera.to_global(Vector3(0, 0, -100)) - camera.global_transform.origin look = node_area.position + look # Y-Billboard: Lock Y rotation, but gives bad results if the camera is tilted. diff --git a/viewport/gui_in_3d/project.godot b/viewport/gui_in_3d/project.godot index da44efc0..e90d4662 100644 --- a/viewport/gui_in_3d/project.godot +++ b/viewport/gui_in_3d/project.godot @@ -18,6 +18,10 @@ run/main_scene="res://gui_in_3d.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [gui] theme/default_theme_scale=2.0 diff --git a/viewport/screen_capture/project.godot b/viewport/screen_capture/project.godot index 2baac540..1841a76c 100644 --- a/viewport/screen_capture/project.godot +++ b/viewport/screen_capture/project.godot @@ -17,6 +17,10 @@ run/main_scene="res://screen_capture.tscn" config/features=PackedStringArray("4.2") config/icon="res://icon.webp" +[debug] + +gdscript/warnings/untyped_declaration=1 + [display] window/stretch/mode="canvas_items" diff --git a/viewport/screen_capture/screen_capture.gd b/viewport/screen_capture/screen_capture.gd index 0d768a01..e9dc2777 100644 --- a/viewport/screen_capture/screen_capture.gd +++ b/viewport/screen_capture/screen_capture.gd @@ -1,13 +1,23 @@ extends Node -@onready var captured_image = $CapturedImage +@onready var captured_image: TextureRect = $CapturedImage +@onready var capture_button: Button = $CaptureButton -func _on_CaptureButton_pressed(): + +func _ready() -> void: + # Focus button for keyboard/gamepad-friendly navigation. + capture_button.grab_focus() + + +func _on_capture_button_pressed() -> void: # Retrieve the captured image. - var img = get_viewport().get_texture().get_image() + var img := get_viewport().get_texture().get_image() # Create a texture for it. - var tex = ImageTexture.create_from_image(img) + var tex := ImageTexture.create_from_image(img) # Set the texture to the captured image node. captured_image.set_texture(tex) + + # Colorize the button with a random color, so you can see which button belongs to which capture. + capture_button.modulate = Color.from_hsv(randf(), randf_range(0.2, 0.8), 1.0) diff --git a/viewport/screen_capture/screen_capture.tscn b/viewport/screen_capture/screen_capture.tscn index b7528a07..61e6d0f4 100644 --- a/viewport/screen_capture/screen_capture.tscn +++ b/viewport/screen_capture/screen_capture.tscn @@ -41,6 +41,7 @@ offset_left = 50.0 offset_top = 50.0 offset_right = 190.0 offset_bottom = 110.0 -text = "Capture screen" +text = "Capture +Screen" -[connection signal="pressed" from="CaptureButton" to="." method="_on_CaptureButton_pressed"] +[connection signal="pressed" from="CaptureButton" to="." method="_on_capture_button_pressed"] diff --git a/xr/openxr_character_centric_movement/objects/black_out.gd b/xr/openxr_character_centric_movement/objects/black_out.gd index 6243df4a..148016c5 100644 --- a/xr/openxr_character_centric_movement/objects/black_out.gd +++ b/xr/openxr_character_centric_movement/objects/black_out.gd @@ -1,15 +1,16 @@ @tool extends Node3D -@export_range(0, 1, 0.1) var fade = 0.0: +@export_range(0, 1, 0.1) var fade := 0.0: set(value): fade = value if is_inside_tree(): _update_fade() -var material : ShaderMaterial +var material: ShaderMaterial -func _update_fade(): + +func _update_fade() -> void: if fade == 0.0: $MeshInstance3D.visible = false else: @@ -17,7 +18,7 @@ func _update_fade(): material.set_shader_parameter("albedo", Color(0.0, 0.0, 0.0, fade)) $MeshInstance3D.visible = true -# Called when the node enters the scene tree for the first time. -func _ready(): + +func _ready() -> void: material = $MeshInstance3D.material_override _update_fade() diff --git a/xr/openxr_character_centric_movement/player.gd b/xr/openxr_character_centric_movement/player.gd index 047556d7..6bbece63 100644 --- a/xr/openxr_character_centric_movement/player.gd +++ b/xr/openxr_character_centric_movement/player.gd @@ -1,75 +1,77 @@ extends CharacterBody3D -# Settings to control the character -@export var rotation_speed : float = 1.0 -@export var movement_speed : float = 5.0 -@export var movement_acceleration : float = 5.0 +# Settings to control the character. +@export var rotation_speed := 1.0 +@export var movement_speed := 5.0 +@export var movement_acceleration := 5.0 # Get the gravity from the project settings to be synced with RigidBody nodes. -var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") +var gravity := float(ProjectSettings.get_setting("physics/3d/default_gravity")) -# Helper variables to keep our code readable -@onready var origin_node : XROrigin3D = $XROrigin3D -@onready var camera_node : XRCamera3D = $XROrigin3D/XRCamera3D -@onready var neck_position_node : Node3D = $XROrigin3D/XRCamera3D/Neck -@onready var black_out : Node3D = $XROrigin3D/XRCamera3D/BlackOut +# Helper variables to keep our code readable. +@onready var origin_node: XROrigin3D = $XROrigin3D +@onready var camera_node: XRCamera3D = $XROrigin3D/XRCamera3D +@onready var neck_position_node: Node3D = $XROrigin3D/XRCamera3D/Neck +@onready var black_out: Node3D = $XROrigin3D/XRCamera3D/BlackOut -# `recenter` is called when the user has requested their view to be recentered. -# The code here assumes the player has walked into an area they shouldn't be -# and we return the player back to the character body. -# But other strategies can be applied here as well such as returning the player -# to a starting position or a checkpoint. -func recenter(): - # Calculate where our camera should be, we start with our global transform +## Called when the user has requested their view to be recentered. +func recenter() -> void: + # The code here assumes the player has walked into an area they shouldn't be + # and we return the player back to the character body. + # But other strategies can be applied here as well such as returning the player + # to a starting position or a checkpoint. + + # Calculate where our camera should be, we start with our global transform. var new_camera_transform : Transform3D = global_transform - # Set to the height of our neck joint + # Set to the height of our neck joint. new_camera_transform.origin.y = neck_position_node.global_position.y - # Apply transform our our next position to get our desired camera transform + # Apply transform our our next position to get our desired camera transform. new_camera_transform = new_camera_transform * neck_position_node.transform.inverse() - # Remove tilt from camera transform + # Remove tilt from camera transform. var camera_transform : Transform3D = camera_node.transform var forward_dir : Vector3 = camera_transform.basis.z forward_dir.y = 0.0 camera_transform = camera_transform.looking_at(camera_transform.origin + forward_dir.normalized(), Vector3.UP, true) - # Update our XR location + # Update our XR location. origin_node.global_transform = new_camera_transform * camera_transform.inverse() -# `_get_movement_input` returns our move input by querying the move action on each controller + +# Returns our move input by querying the move action on each controller. func _get_movement_input() -> Vector2: - var movement : Vector2 = Vector2() + var movement := Vector2() # If move is not bound to one of our controllers, - # that controller will return a Vector2(0.0, 0.0) + # that controller will return `Vector2.ZERO`. movement += $XROrigin3D/LeftHand.get_vector2("move") movement += $XROrigin3D/RightHand.get_vector2("move") return movement -# `_process_on_physical_movement` handles the physical movement of the player +# `_process_on_physical_movement()` handles the physical movement of the player # adjusting our character body position to "catch up to" the player. # If the character body encounters an obstruction our view will black out # and we will stop further character movement until the player physically # moves back. -func _process_on_physical_movement(delta) -> bool: - # Remember our current velocity, we'll apply that later - var current_velocity = velocity +func _process_on_physical_movement(delta: float) -> bool: + # Remember our current velocity, as we'll apply that later. + var current_velocity := velocity - # Start by rotating the player to face the same way our real player is + # Start by rotating the player to face the same way our real player is. var camera_basis: Basis = origin_node.transform.basis * camera_node.transform.basis var forward: Vector2 = Vector2(camera_basis.z.x, camera_basis.z.z) var angle: float = forward.angle_to(Vector2(0.0, 1.0)) - # Rotate our character body + # Rotate our character body. transform.basis = transform.basis.rotated(Vector3.UP, angle) - # Reverse this rotation our origin node + # Reverse this rotation our origin node. origin_node.transform = Transform3D().rotated(Vector3.UP, -angle) * origin_node.transform - # Now apply movement, first move our player body to the right location + # Now apply movement, first move our player body to the right location. var org_player_body: Vector3 = global_transform.origin var player_body_location: Vector3 = origin_node.transform * camera_node.transform * neck_position_node.transform.origin player_body_location.y = 0.0 @@ -78,34 +80,33 @@ func _process_on_physical_movement(delta) -> bool: velocity = (player_body_location - org_player_body) / delta move_and_slide() - # Now move our XROrigin back - var delta_movement = global_transform.origin - org_player_body + # Now move our XROrigin back. + var delta_movement := global_transform.origin - org_player_body origin_node.global_transform.origin -= delta_movement - # Negate any height change in local space due to player hitting ramps etc. + # Negate any height change in local space due to player hitting ramps, etc. origin_node.transform.origin.y = 0.0 - # Return our value + # Return our value. velocity = current_velocity - # Check if we managed to move where we wanted to - var location_offset = (player_body_location - global_transform.origin).length() + # Check if we managed to move where we wanted to. + var location_offset := (player_body_location - global_transform.origin).length() if location_offset > 0.1: - # We couldn't go where we wanted to, black out our screen - black_out.fade = clamp((location_offset - 0.1) / 0.1, 0.0, 1.0) - + # We couldn't go where we wanted to, black out our screen. + black_out.fade = clampf((location_offset - 0.1) / 0.1, 0.0, 1.0) return true else: black_out.fade = 0.0 return false -# `_process_movement_on_input` handles movement through controller input. +# `_process_movement_on_input()` handles movement through controller input. # We first handle rotating the player and then apply movement. # We also apply the effects of gravity at this point. -func _process_movement_on_input(is_colliding, delta): - if !is_colliding: +func _process_movement_on_input(is_colliding: bool, delta: float) -> void: + if not is_colliding: # Only handle input if we've not physically moved somewhere we shouldn't. - var movement_input = _get_movement_input() + var movement_input := _get_movement_input() # First handle rotation, to keep this example simple we are implementing # "smooth" rotation here. This can lead to motion sickness. @@ -117,7 +118,7 @@ func _process_movement_on_input(is_colliding, delta): # Straffing can be added by using the movement_input.x input # and using a different input for rotational control. # Straffing is more prone to motion sickness. - var direction = global_transform.basis * Vector3(0.0, 0.0, -movement_input.y) * movement_speed + var direction := global_transform.basis * Vector3(0.0, 0.0, -movement_input.y) * movement_speed if direction: velocity.x = move_toward(velocity.x, direction.x, delta * movement_acceleration) velocity.z = move_toward(velocity.z, direction.z, delta * movement_acceleration) @@ -130,7 +131,7 @@ func _process_movement_on_input(is_colliding, delta): move_and_slide() -# _physics_process handles our player movement. -func _physics_process(delta): - var is_colliding = _process_on_physical_movement(delta) +# `_physics_process()` handles our player movement. +func _physics_process(delta: float) -> void: + var is_colliding := _process_on_physical_movement(delta) _process_movement_on_input(is_colliding, delta) diff --git a/xr/openxr_character_centric_movement/project.godot b/xr/openxr_character_centric_movement/project.godot index 279595fd..91c0d7e9 100644 --- a/xr/openxr_character_centric_movement/project.godot +++ b/xr/openxr_character_centric_movement/project.godot @@ -11,10 +11,14 @@ config_version=5 [application] config/name="OpenXR Character Centric Movement" +config/tags=PackedStringArray("demo", "official", "xr") run/main_scene="res://main.tscn" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" -config/tags=PackedStringArray("demo", "official", "xr") + +[debug] + +gdscript/warnings/untyped_declaration=1 [rendering] diff --git a/xr/openxr_character_centric_movement/start_vr.gd b/xr/openxr_character_centric_movement/start_vr.gd index 0fbb2ebe..7e283879 100644 --- a/xr/openxr_character_centric_movement/start_vr.gd +++ b/xr/openxr_character_centric_movement/start_vr.gd @@ -7,29 +7,28 @@ signal pose_recentered @export var maximum_refresh_rate : int = 90 var xr_interface : OpenXRInterface -var xr_is_focussed = false +var xr_is_focused := false -# Called when the node enters the scene tree for the first time. -func _ready(): +func _ready() -> void: xr_interface = XRServer.find_interface("OpenXR") if xr_interface and xr_interface.is_initialized(): print("OpenXR instantiated successfully.") var vp : Viewport = get_viewport() - # Enable XR on our viewport + # Enable XR on our viewport. vp.use_xr = true - # Make sure v-sync is off, v-sync is handled by OpenXR + # Make sure V-Sync is off, as V-Sync is handled by OpenXR. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) - # Enable VRS + # Enable variable rate shading. if RenderingServer.get_rendering_device(): vp.vrs_mode = Viewport.VRS_XR elif int(ProjectSettings.get_setting("xr/openxr/foveation_level")) == 0: push_warning("OpenXR: Recommend setting Foveation level to High in Project Settings") - # Connect the OpenXR events + # Connect the OpenXR events. xr_interface.session_begun.connect(_on_openxr_session_begun) xr_interface.session_visible.connect(_on_openxr_visible_state) xr_interface.session_focussed.connect(_on_openxr_focused_state) @@ -41,22 +40,22 @@ func _ready(): get_tree().quit() -# Handle OpenXR session ready +# Handle OpenXR session ready. func _on_openxr_session_begun() -> void: - # Get the reported refresh rate - var current_refresh_rate = xr_interface.get_display_refresh_rate() + # Get the reported refresh rate. + var current_refresh_rate := xr_interface.get_display_refresh_rate() if current_refresh_rate > 0: print("OpenXR: Refresh rate reported as ", str(current_refresh_rate)) else: print("OpenXR: No refresh rate given by XR runtime") - # See if we have a better refresh rate available - var new_rate = current_refresh_rate - var available_rates : Array = xr_interface.get_available_display_refresh_rates() - if available_rates.size() == 0: + # See if we have a better refresh rate available. + var new_rate := current_refresh_rate + var available_rates: Array[float] = xr_interface.get_available_display_refresh_rates() + if available_rates.is_empty(): print("OpenXR: Target does not support refresh rate extension") elif available_rates.size() == 1: - # Only one available, so use it + # Only one available, so use it. new_rate = available_rates[0] else: for rate in available_rates: @@ -69,20 +68,21 @@ func _on_openxr_session_begun() -> void: xr_interface.set_display_refresh_rate(new_rate) current_refresh_rate = new_rate - # Now match our physics rate - Engine.physics_ticks_per_second = current_refresh_rate + # Now match our physics rate. This is currently needed to avoid jittering, + # due to physics interpolation not being used. + Engine.physics_ticks_per_second = roundi(current_refresh_rate) -# Handle OpenXR visible state +# Handle OpenXR visible state. func _on_openxr_visible_state() -> void: # We always pass this state at startup, - # but the second time we get this it means our player took off their headset - if xr_is_focussed: + # but the second time we get this, it means our player took off their headset. + if xr_is_focused: print("OpenXR lost focus") - xr_is_focussed = false + xr_is_focused = false - # pause our game + # Pause our game. process_mode = Node.PROCESS_MODE_DISABLED focus_lost.emit() @@ -91,19 +91,21 @@ func _on_openxr_visible_state() -> void: # Handle OpenXR focused state func _on_openxr_focused_state() -> void: print("OpenXR gained focus") - xr_is_focussed = true + xr_is_focused = true - # unpause our game + # Unpause our game. process_mode = Node.PROCESS_MODE_INHERIT focus_gained.emit() -# Handle OpenXR stopping state + +# Handle OpenXR stopping state. func _on_openxr_stopping() -> void: # Our session is being stopped. print("OpenXR is stopping") -# Handle OpenXR pose recentered signal + +# Handle OpenXR pose recentered signal. func _on_openxr_pose_recentered() -> void: # User recentered view, we have to react to this by recentering the view. # This is game implementation dependent. diff --git a/xr/openxr_origin_centric_movement/objects/black_out.gd b/xr/openxr_origin_centric_movement/objects/black_out.gd index 6243df4a..d095e4c9 100644 --- a/xr/openxr_origin_centric_movement/objects/black_out.gd +++ b/xr/openxr_origin_centric_movement/objects/black_out.gd @@ -1,15 +1,15 @@ @tool extends Node3D -@export_range(0, 1, 0.1) var fade = 0.0: +@export_range(0, 1, 0.1) var fade := 0.0: set(value): fade = value if is_inside_tree(): _update_fade() -var material : ShaderMaterial +var material: ShaderMaterial -func _update_fade(): +func _update_fade() -> void: if fade == 0.0: $MeshInstance3D.visible = false else: @@ -17,7 +17,7 @@ func _update_fade(): material.set_shader_parameter("albedo", Color(0.0, 0.0, 0.0, fade)) $MeshInstance3D.visible = true -# Called when the node enters the scene tree for the first time. -func _ready(): + +func _ready() -> void: material = $MeshInstance3D.material_override _update_fade() diff --git a/xr/openxr_origin_centric_movement/player.gd b/xr/openxr_origin_centric_movement/player.gd index 191e9dde..9a50fac2 100644 --- a/xr/openxr_origin_centric_movement/player.gd +++ b/xr/openxr_origin_centric_movement/player.gd @@ -1,53 +1,53 @@ extends XROrigin3D - -# Settings to control the character -@export var rotation_speed : float = 1.0 -@export var movement_speed : float = 5.0 -@export var movement_acceleration : float = 5.0 +# Settings to control the character. +@export var rotation_speed := 1.0 +@export var movement_speed := 5.0 +@export var movement_acceleration := 5.0 # Get the gravity from the project settings to be synced with RigidBody nodes. -var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") +var gravity := float(ProjectSettings.get_setting("physics/3d/default_gravity")) -# Helper variables to keep our code readable +# Helper variables to keep our code readable. @onready var character_body : CharacterBody3D = $CharacterBody3D @onready var camera_node : XRCamera3D = $XRCamera3D @onready var neck_position_node : Node3D = $XRCamera3D/Neck @onready var black_out : Node3D = $XRCamera3D/BlackOut -# `recenter` is called when the user has requested their view to be recentered. -# The code here assumes the player has walked into an area they shouldn't be -# and we return the player back to the character body. -# But other strategies can be applied here as well such as returning the player -# to a starting position or a checkpoint. -func recenter(): - # Calculate where our camera should be, we start with our global transform - var new_camera_transform : Transform3D = character_body.global_transform +## Called when the user has requested their view to be recentered. +func recenter() -> void: + # The code here assumes the player has walked into an area they shouldn't be + # and we return the player back to the character body. + # But other strategies can be applied here as well such as returning the player + # to a starting position or a checkpoint. - # Set to the height of our neck joint + # Calculate where our camera should be, we start with our global transform. + var new_camera_transform: Transform3D = character_body.global_transform + + # Set to the height of our neck joint. new_camera_transform.origin.y = neck_position_node.global_position.y - # Apply transform our our next position to get our desired camera transform + # Apply transform our our next position to get our desired camera transform. new_camera_transform = new_camera_transform * neck_position_node.transform.inverse() - # Remove tilt from camera transform - var camera_transform : Transform3D = camera_node.transform - var forward_dir : Vector3 = camera_transform.basis.z + # Remove tilt from camera transform. + var camera_transform: Transform3D = camera_node.transform + var forward_dir: Vector3 = camera_transform.basis.z forward_dir.y = 0.0 camera_transform = camera_transform.looking_at(camera_transform.origin + forward_dir.normalized(), Vector3.UP, true) - # Update our XR location + # Update our XR location. global_transform = new_camera_transform * camera_transform.inverse() - # Recenter character body + # Recenter character body. character_body.transform = Transform3D() -# `_get_movement_input` returns our move input by querying the move action on each controller +# `_get_movement_input()` returns our move input by querying the move action on each controller. func _get_movement_input() -> Vector2: var movement : Vector2 = Vector2() # If move is not bound to one of our controllers, - # that controller will return a Vector2(0.0, 0.0) + # that controller will return `Vector2.ZERO`. movement += $LeftHand.get_vector2("move") movement += $RightHand.get_vector2("move") @@ -58,33 +58,33 @@ func _get_movement_input() -> Vector2: # If the character body encounters an obstruction our view will black out # and we will stop further character movement until the player physically # moves back. -func _process_on_physical_movement(delta) -> bool: - # Remember our current velocity, we'll apply that later - var current_velocity = character_body.velocity +func _process_on_physical_movement(delta: float) -> bool: + # Remember our current velocity, as we'll apply that later. + var current_velocity := character_body.velocity - # Remember where our player body currently is + # Remember where our player body currently is. var org_player_body: Vector3 = character_body.global_transform.origin - # Determine where our player body should be + # Determine where our player body should be. var player_body_location: Vector3 = camera_node.transform * neck_position_node.transform.origin player_body_location.y = 0.0 player_body_location = global_transform * player_body_location - # Attempt to move our character + # Attempt to move our character. character_body.velocity = (player_body_location - org_player_body) / delta character_body.move_and_slide() - # Set back to our current value + # Set back to our current value. character_body.velocity = current_velocity - # Check if we managed to move all the way, ignoring height change - var movement_left = player_body_location - character_body.global_transform.origin + # Check if we managed to move all the way, ignoring height change. + var movement_left := player_body_location - character_body.global_transform.origin movement_left.y = 0.0 - # Check if we managed to move where we wanted to - var location_offset = movement_left.length() + # Check if we managed to move where we wanted to. + var location_offset := movement_left.length() if location_offset > 0.1: - # We couldn't go where we wanted to, black out our screen + # We couldn't go where we wanted to, black out our screen. black_out.fade = clamp((location_offset - 0.1) / 0.1, 0.0, 1.0) return true @@ -92,23 +92,25 @@ func _process_on_physical_movement(delta) -> bool: black_out.fade = 0.0 return false -func _copy_player_rotation_to_character_body(): - # We only copy our forward direction to our character body, we ignore tilt - var camera_forward: Vector3 = -camera_node.global_transform.basis.z - var body_forward: Vector3 = Vector3(camera_forward.x, 0.0, camera_forward.z) + +func _copy_player_rotation_to_character_body() -> void: + # We only copy our forward direction to our character body, we ignore tilt. + var camera_forward := -camera_node.global_transform.basis.z + var body_forward := Vector3(camera_forward.x, 0.0, camera_forward.z) character_body.global_transform.basis = Basis.looking_at(body_forward, Vector3.UP) + # `_process_movement_on_input` handles movement through controller input. # We first handle rotating the player and then apply movement. # We also apply the effects of gravity at this point. -func _process_movement_on_input(is_colliding, delta): - # Remember where our player body currently is +func _process_movement_on_input(is_colliding: bool, delta: float) -> void: + # Remember where our player body currently is. var org_player_body: Vector3 = character_body.global_transform.origin - if !is_colliding: + if not is_colliding: # Only handle input if we've not physically moved somewhere we shouldn't. - var movement_input = _get_movement_input() + var movement_input := _get_movement_input() # First handle rotation, to keep this example simple we are implementing # "smooth" rotation here. This can lead to motion sickness. @@ -119,15 +121,15 @@ func _process_movement_on_input(is_colliding, delta): var t2 := Transform3D() var rot := Transform3D() - # We are going to rotate the origin around the player - var player_position = character_body.global_transform.origin - global_transform.origin + # We are going to rotate the origin around the player. + var player_position := character_body.global_transform.origin - global_transform.origin t1.origin = -player_position t2.origin = player_position rot = rot.rotated(Vector3(0.0, 1.0, 0.0), -movement_input.x * delta * rotation_speed) global_transform = (global_transform * t2 * rot * t1).orthonormalized() - # Now ensure our player body is facing the correct way as well + # Now ensure our player body is facing the correct way as well. _copy_player_rotation_to_character_body() # Now handle forward/backwards movement. @@ -142,16 +144,17 @@ func _process_movement_on_input(is_colliding, delta): character_body.velocity.x = move_toward(character_body.velocity.x, 0, delta * movement_acceleration) character_body.velocity.z = move_toward(character_body.velocity.z, 0, delta * movement_acceleration) - # Always handle gravity + # Always handle gravity. character_body.velocity.y -= gravity * delta - # Attempt to move our player + # Attempt to move our player. character_body.move_and_slide() - # And now apply the actual movement to our origin + # And now apply the actual movement to our origin. global_transform.origin += character_body.global_transform.origin - org_player_body + # _physics_process handles our player movement. -func _physics_process(delta): - var is_colliding = _process_on_physical_movement(delta) +func _physics_process(delta: float) -> void: + var is_colliding := _process_on_physical_movement(delta) _process_movement_on_input(is_colliding, delta) diff --git a/xr/openxr_origin_centric_movement/project.godot b/xr/openxr_origin_centric_movement/project.godot index b1acb4b7..a0375857 100644 --- a/xr/openxr_origin_centric_movement/project.godot +++ b/xr/openxr_origin_centric_movement/project.godot @@ -11,10 +11,14 @@ config_version=5 [application] config/name="OpenXR Origin Centric Movement" +config/tags=PackedStringArray("demo", "official", "xr") run/main_scene="res://main.tscn" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" -config/tags=PackedStringArray("demo", "official", "xr") + +[debug] + +gdscript/warnings/untyped_declaration=1 [rendering] diff --git a/xr/openxr_origin_centric_movement/start_vr.gd b/xr/openxr_origin_centric_movement/start_vr.gd index 0fbb2ebe..3def74a5 100644 --- a/xr/openxr_origin_centric_movement/start_vr.gd +++ b/xr/openxr_origin_centric_movement/start_vr.gd @@ -4,32 +4,31 @@ signal focus_lost signal focus_gained signal pose_recentered -@export var maximum_refresh_rate : int = 90 +@export var maximum_refresh_rate: int = 90 -var xr_interface : OpenXRInterface -var xr_is_focussed = false +var xr_interface: OpenXRInterface +var xr_is_focused := false -# Called when the node enters the scene tree for the first time. -func _ready(): +func _ready() -> void: xr_interface = XRServer.find_interface("OpenXR") if xr_interface and xr_interface.is_initialized(): print("OpenXR instantiated successfully.") - var vp : Viewport = get_viewport() + var vp: Viewport = get_viewport() - # Enable XR on our viewport + # Enable XR on our viewport. vp.use_xr = true - # Make sure v-sync is off, v-sync is handled by OpenXR + # Make sure V-Sync is off, as V-Sync is handled by OpenXR. DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED) - # Enable VRS + # Enable variable rate shading. if RenderingServer.get_rendering_device(): vp.vrs_mode = Viewport.VRS_XR elif int(ProjectSettings.get_setting("xr/openxr/foveation_level")) == 0: push_warning("OpenXR: Recommend setting Foveation level to High in Project Settings") - # Connect the OpenXR events + # Connect the OpenXR events. xr_interface.session_begun.connect(_on_openxr_session_begun) xr_interface.session_visible.connect(_on_openxr_visible_state) xr_interface.session_focussed.connect(_on_openxr_focused_state) @@ -41,22 +40,22 @@ func _ready(): get_tree().quit() -# Handle OpenXR session ready +# Handle OpenXR session ready. func _on_openxr_session_begun() -> void: - # Get the reported refresh rate - var current_refresh_rate = xr_interface.get_display_refresh_rate() + # Get the reported refresh rate. + var current_refresh_rate := xr_interface.get_display_refresh_rate() if current_refresh_rate > 0: print("OpenXR: Refresh rate reported as ", str(current_refresh_rate)) else: print("OpenXR: No refresh rate given by XR runtime") - # See if we have a better refresh rate available - var new_rate = current_refresh_rate - var available_rates : Array = xr_interface.get_available_display_refresh_rates() - if available_rates.size() == 0: + # See if we have a better refresh rate available. + var new_rate := current_refresh_rate + var available_rates: Array[float] = xr_interface.get_available_display_refresh_rates() + if available_rates.is_empty(): print("OpenXR: Target does not support refresh rate extension") elif available_rates.size() == 1: - # Only one available, so use it + # Only one available, so use it. new_rate = available_rates[0] else: for rate in available_rates: @@ -69,20 +68,21 @@ func _on_openxr_session_begun() -> void: xr_interface.set_display_refresh_rate(new_rate) current_refresh_rate = new_rate - # Now match our physics rate - Engine.physics_ticks_per_second = current_refresh_rate + # Now match our physics rate. This is currently needed to avoid jittering, + # due to physics interpolation not being used. + Engine.physics_ticks_per_second = roundi(current_refresh_rate) # Handle OpenXR visible state func _on_openxr_visible_state() -> void: # We always pass this state at startup, - # but the second time we get this it means our player took off their headset - if xr_is_focussed: + # but the second time we get this, it means our player took off their headset. + if xr_is_focused: print("OpenXR lost focus") - xr_is_focussed = false + xr_is_focused = false - # pause our game + # Pause our game. process_mode = Node.PROCESS_MODE_DISABLED focus_lost.emit() @@ -91,19 +91,19 @@ func _on_openxr_visible_state() -> void: # Handle OpenXR focused state func _on_openxr_focused_state() -> void: print("OpenXR gained focus") - xr_is_focussed = true + xr_is_focused = true - # unpause our game + # Unpause our game. process_mode = Node.PROCESS_MODE_INHERIT focus_gained.emit() -# Handle OpenXR stopping state +# Handle OpenXR stopping state. func _on_openxr_stopping() -> void: # Our session is being stopped. print("OpenXR is stopping") -# Handle OpenXR pose recentered signal +# Handle OpenXR pose recentered signal. func _on_openxr_pose_recentered() -> void: # User recentered view, we have to react to this by recentering the view. # This is game implementation dependent.