@@ -0,0 +1,3 @@ | |||||
source_md5="5faf6e1c736b04b625aceb0c743b6628" | |||||
dest_md5="4c773a5e082b39d38854800e6a474759" | |||||
@@ -0,0 +1,3 @@ | |||||
source_md5="f7f2f7d3eadea25b7f8df535eadc659a" | |||||
dest_md5="fec74eac509e110b0cd39633c554e3f1" | |||||
@@ -0,0 +1,7 @@ | |||||
[gd_resource type="DynamicFont" load_steps=2 format=2] | |||||
[ext_resource path="res://jrpg/fonts/Puritan-Regular.otf" type="DynamicFontData" id=1] | |||||
[resource] | |||||
size = 30 | |||||
font_data = ExtResource( 1 ) |
@@ -1,7 +1,9 @@ | |||||
[gd_scene load_steps=4 format=2] | |||||
[gd_scene load_steps=6 format=2] | |||||
[ext_resource path="res://jrpg/models/coinGold.glb" type="PackedScene" id=1] | [ext_resource path="res://jrpg/models/coinGold.glb" type="PackedScene" id=1] | ||||
[ext_resource path="res://jrpg/scripts/pickup.gd" type="Script" id=2] | [ext_resource path="res://jrpg/scripts/pickup.gd" type="Script" id=2] | ||||
[ext_resource path="res://jrpg/models/gold.material" type="Material" id=3] | |||||
[ext_resource path="res://jrpg/models/wood.material" type="Material" id=4] | |||||
[sub_resource type="SphereShape" id=1] | [sub_resource type="SphereShape" id=1] | ||||
radius = 0.436751 | radius = 0.436751 | ||||
@@ -14,6 +16,8 @@ transform = Transform( 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, -0.402459, 0 ) | |||||
[node name="coinGold" parent="coinGold/tmpParent" index="0"] | [node name="coinGold" parent="coinGold/tmpParent" index="0"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) | ||||
material/0 = ExtResource( 3 ) | |||||
material/1 = ExtResource( 4 ) | |||||
[node name="CollisionShape" type="CollisionShape" parent="."] | [node name="CollisionShape" type="CollisionShape" parent="."] | ||||
shape = SubResource( 1 ) | shape = SubResource( 1 ) | ||||
@@ -1,7 +1,6 @@ | |||||
[gd_scene load_steps=6 format=2] | |||||
[gd_scene load_steps=5 format=2] | |||||
[ext_resource path="res://jrpg/models/chars/Casual2_Female.glb" type="PackedScene" id=1] | [ext_resource path="res://jrpg/models/chars/Casual2_Female.glb" type="PackedScene" id=1] | ||||
[ext_resource path="res://jrpg/models/chars/sword.fbx" type="PackedScene" id=2] | |||||
[ext_resource path="res://jrpg/scripts/camera/camera_orbit.gd" type="Script" id=3] | [ext_resource path="res://jrpg/scripts/camera/camera_orbit.gd" type="Script" id=3] | ||||
[ext_resource path="res://jrpg/scripts/player.gd" type="Script" id=4] | [ext_resource path="res://jrpg/scripts/player.gd" type="Script" id=4] | ||||
@@ -26,21 +25,9 @@ script = ExtResource( 3 ) | |||||
transform = Transform( -1, 0, -3.25841e-07, 0, 1, 0, 3.25841e-07, 0, -1, -1, 1, -5 ) | transform = Transform( -1, 0, -3.25841e-07, 0, 1, 0, 3.25841e-07, 0, -1, -1, 1, -5 ) | ||||
current = true | current = true | ||||
[node name="WeaponHolder" type="Spatial" parent="."] | |||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.58, 1, 0.035 ) | |||||
visible = false | |||||
[node name="sword" parent="WeaponHolder" instance=ExtResource( 2 )] | |||||
transform = Transform( -3.10389e-08, 3.10389e-08, 0.26943, 0.190516, 0.190516, 0, -0.190516, 0.190516, -4.38958e-08, 0, 0, 0 ) | |||||
[node name="sword2" parent="WeaponHolder/sword" index="0"] | |||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) | |||||
[node name="AttackRayCast" type="RayCast" parent="."] | [node name="AttackRayCast" type="RayCast" parent="."] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.3, 1, 0.6 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.3, 1, 0.6 ) | ||||
enabled = true | enabled = true | ||||
cast_to = Vector3( 0, 0, 1.5 ) | cast_to = Vector3( 0, 0, 1.5 ) | ||||
[editable path="Casual2_Female"] | [editable path="Casual2_Female"] | ||||
[editable path="WeaponHolder/sword"] |
@@ -0,0 +1,20 @@ | |||||
[gd_scene load_steps=4 format=2] | |||||
[ext_resource path="res://jrpg/models/chars/Zombie_Male.glb" type="PackedScene" id=1] | |||||
[ext_resource path="res://jrpg/scripts/enemy.gd" type="Script" id=2] | |||||
[sub_resource type="CapsuleShape" id=1] | |||||
radius = 0.5 | |||||
[node name="Enemy" type="KinematicBody"] | |||||
script = ExtResource( 2 ) | |||||
[node name="CollisionShape" type="CollisionShape" parent="."] | |||||
transform = Transform( 1, 0, 0, 0, -1.62921e-07, -1, 0, 1, -1.62921e-07, 0, 1, 0 ) | |||||
shape = SubResource( 1 ) | |||||
[node name="Zombie_Male" parent="." instance=ExtResource( 1 )] | |||||
transform = Transform( 0.65, 0, 0, 0, 0.65, 0, 0, 0, 0.65, 0, 0, 0 ) | |||||
[node name="Timer" type="Timer" parent="."] | |||||
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] |
@@ -1,9 +1,11 @@ | |||||
[gd_scene load_steps=21 format=2] | |||||
[gd_scene load_steps=23 format=2] | |||||
[ext_resource path="res://jrpg/models/nature/_defaultMat.material" type="Material" id=1] | [ext_resource path="res://jrpg/models/nature/_defaultMat.material" type="Material" id=1] | ||||
[ext_resource path="res://jrpg/models/nature/grass.material" type="Material" id=2] | [ext_resource path="res://jrpg/models/nature/grass.material" type="Material" id=2] | ||||
[ext_resource path="res://jrpg/models/nature/dirt.material" type="Material" id=3] | [ext_resource path="res://jrpg/models/nature/dirt.material" type="Material" id=3] | ||||
[ext_resource path="res://jrpg/scenes/Pickup.tscn" type="PackedScene" id=4] | [ext_resource path="res://jrpg/scenes/Pickup.tscn" type="PackedScene" id=4] | ||||
[ext_resource path="res://jrpg/scenes/test_enemy.tscn" type="PackedScene" id=5] | |||||
[ext_resource path="res://jrpg/scenes/test_ui.tscn" type="PackedScene" id=6] | |||||
[ext_resource path="res://jrpg/misc/jrpg_env.tres" type="Environment" id=8] | [ext_resource path="res://jrpg/misc/jrpg_env.tres" type="Environment" id=8] | ||||
[ext_resource path="res://jrpg/scenes/test_char.tscn" type="PackedScene" id=9] | [ext_resource path="res://jrpg/scenes/test_char.tscn" type="PackedScene" id=9] | ||||
@@ -242,6 +244,7 @@ transform = Transform( 50.0874, 0, 0, 0, 5.00874, 0, 0, 0, 50.0874, 0, 0.204079, | |||||
[node name="ground_grass" type="MeshInstance" parent="ground_grass/tmpParent"] | [node name="ground_grass" type="MeshInstance" parent="ground_grass/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 1 ) | mesh = SubResource( 1 ) | ||||
material/0 = null | material/0 = null | ||||
@@ -260,6 +263,7 @@ transform = Transform( 5.65286, 0, 0, 0, 5.65286, 0, 0, 0, 5.65286, -12.9201, 0. | |||||
[node name="rock_smallFlatC" type="MeshInstance" parent="ground_grass/Rocks/rock_smallFlatC/tmpParent"] | [node name="rock_smallFlatC" type="MeshInstance" parent="ground_grass/Rocks/rock_smallFlatC/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 3 ) | mesh = SubResource( 3 ) | ||||
material/0 = null | material/0 = null | ||||
material/1 = null | material/1 = null | ||||
@@ -276,6 +280,7 @@ transform = Transform( 5.65286, 0, 0, 0, 5.65286, 0, 0, 0, 5.65286, -14.2025, 0. | |||||
[node name="rock_tallB" type="MeshInstance" parent="ground_grass/Rocks/rock_tallB/tmpParent"] | [node name="rock_tallB" type="MeshInstance" parent="ground_grass/Rocks/rock_tallB/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 5 ) | mesh = SubResource( 5 ) | ||||
material/0 = null | material/0 = null | ||||
material/1 = null | material/1 = null | ||||
@@ -293,6 +298,7 @@ transform = Transform( 6.85371, 0, 0, 0, 6.85371, 0, 0, 0, 6.85371, -18.3314, 2. | |||||
[node name="rock_smallE" type="MeshInstance" parent="ground_grass/Rocks/rock_smallE/tmpParent"] | [node name="rock_smallE" type="MeshInstance" parent="ground_grass/Rocks/rock_smallE/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 7 ) | mesh = SubResource( 7 ) | ||||
material/0 = null | material/0 = null | ||||
material/1 = null | material/1 = null | ||||
@@ -309,6 +315,7 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -18.5467, -3.72529e-09, 13.509 | |||||
[node name="rock_smallA" type="MeshInstance" parent="ground_grass/Rocks/rock_smallA/tmpParent"] | [node name="rock_smallA" type="MeshInstance" parent="ground_grass/Rocks/rock_smallA/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 9 ) | mesh = SubResource( 9 ) | ||||
material/0 = null | material/0 = null | ||||
material/1 = null | material/1 = null | ||||
@@ -325,6 +332,7 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -17.8118, 1.11759e-08, 11.9321 | |||||
[node name="rock_largeD" type="MeshInstance" parent="ground_grass/Rocks/rock_largeD/tmpParent"] | [node name="rock_largeD" type="MeshInstance" parent="ground_grass/Rocks/rock_largeD/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 11 ) | mesh = SubResource( 11 ) | ||||
material/0 = null | material/0 = null | ||||
material/1 = null | material/1 = null | ||||
@@ -342,6 +350,7 @@ transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -10.9969, -2.27243e-07, 12.294 | |||||
[node name="rock_largeC" type="MeshInstance" parent="ground_grass/Rocks/rock_largeC/tmpParent"] | [node name="rock_largeC" type="MeshInstance" parent="ground_grass/Rocks/rock_largeC/tmpParent"] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0 ) | ||||
use_in_baked_light = true | |||||
mesh = SubResource( 13 ) | mesh = SubResource( 13 ) | ||||
material/0 = null | material/0 = null | ||||
material/1 = null | material/1 = null | ||||
@@ -352,6 +361,7 @@ material/1 = null | |||||
shape = SubResource( 14 ) | shape = SubResource( 14 ) | ||||
[node name="Coins" type="Spatial" parent="."] | [node name="Coins" type="Spatial" parent="."] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.96386, 0 ) | |||||
[node name="Pickup" parent="Coins" instance=ExtResource( 4 )] | [node name="Pickup" parent="Coins" instance=ExtResource( 4 )] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.8056, 3.95915 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.8056, 3.95915 ) | ||||
@@ -376,5 +386,14 @@ environment = ExtResource( 8 ) | |||||
[node name="Player" parent="." instance=ExtResource( 9 )] | [node name="Player" parent="." instance=ExtResource( 9 )] | ||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6885, 0 ) | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6885, 0 ) | ||||
ui_path = NodePath("../CanvasLayer/UI") | |||||
[node name="Enemy" parent="." instance=ExtResource( 5 )] | |||||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -4.06601, 1.54631, 5.23785 ) | |||||
player_path = NodePath("../Player") | |||||
[node name="CanvasLayer" type="CanvasLayer" parent="."] | |||||
[node name="UI" parent="CanvasLayer" instance=ExtResource( 6 )] | |||||
[editable path="Player"] | [editable path="Player"] |
@@ -0,0 +1,45 @@ | |||||
[gd_scene load_steps=4 format=2] | |||||
[ext_resource path="res://jrpg/fonts/puritan.tres" type="DynamicFont" id=1] | |||||
[ext_resource path="res://jrpg/textures/white_square.png" type="Texture" id=2] | |||||
[ext_resource path="res://jrpg/scripts/test_ui.gd" type="Script" id=3] | |||||
[node name="UI" type="Control"] | |||||
anchor_right = 1.0 | |||||
anchor_bottom = 1.0 | |||||
script = ExtResource( 3 ) | |||||
__meta__ = { | |||||
"_edit_use_anchors_": false | |||||
} | |||||
healthBar_path = NodePath("HealthBar") | |||||
goldText_path = NodePath("GoldText") | |||||
[node name="GoldText" type="Label" parent="."] | |||||
anchor_top = 1.0 | |||||
anchor_bottom = 1.0 | |||||
margin_left = 36.0 | |||||
margin_top = -133.0 | |||||
margin_right = 293.0 | |||||
margin_bottom = -94.0 | |||||
custom_fonts/font = ExtResource( 1 ) | |||||
text = "Gold : 500" | |||||
valign = 1 | |||||
__meta__ = { | |||||
"_edit_use_anchors_": false | |||||
} | |||||
[node name="HealthBar" type="TextureProgress" parent="."] | |||||
anchor_top = 1.0 | |||||
anchor_bottom = 1.0 | |||||
margin_left = 33.4037 | |||||
margin_top = -92.9199 | |||||
margin_right = 295.404 | |||||
margin_bottom = -36.9199 | |||||
texture_under = ExtResource( 2 ) | |||||
texture_progress = ExtResource( 2 ) | |||||
tint_under = Color( 0.226563, 0.217712, 0.217712, 1 ) | |||||
tint_progress = Color( 1, 0, 0, 1 ) | |||||
nine_patch_stretch = true | |||||
__meta__ = { | |||||
"_edit_use_anchors_": false | |||||
} |
@@ -0,0 +1,71 @@ | |||||
extends KinematicBody | |||||
# stats | |||||
var curHp : int = 3 | |||||
var maxHp : int = 3 | |||||
# attacking | |||||
var damage : int = 1 | |||||
var attackDist : float = 1.5 | |||||
var attackRate : float = 1.0 | |||||
# physics | |||||
var moveSpeed : float = 2.5 | |||||
var gravity : float = 15.0 | |||||
# vectors | |||||
var vel : Vector3 = Vector3() | |||||
# components | |||||
onready var timer = get_node("Timer") | |||||
export var player_path : NodePath | |||||
onready var player = get_node(player_path) | |||||
onready var anim = get_node("Zombie_Male/AnimationPlayer") | |||||
func _ready (): | |||||
# set the timer wait time | |||||
timer.wait_time = attackRate | |||||
timer.start() | |||||
# called every "attackRate" seconds | |||||
func _on_Timer_timeout (): | |||||
# if we're within the attack distance - attack the player | |||||
if translation.distance_to(player.translation) <= attackDist: | |||||
player.take_damage(damage) | |||||
# called 60 times a second | |||||
func _physics_process (delta): | |||||
# get the distance from us to the player | |||||
var dist = translation.distance_to(player.translation) | |||||
# if we're outside of the attack distance, chase after the player | |||||
if dist > attackDist: | |||||
# calculate the direction between us and the player | |||||
var dir = (player.translation - translation).normalized() | |||||
vel.x = dir.x | |||||
vel.z = dir.z | |||||
# gravity | |||||
vel.y -= gravity * delta | |||||
# move towards the player | |||||
vel = move_and_slide(vel, Vector3.UP) | |||||
# called when the player deals damage to us | |||||
func take_damage (damageToTake): | |||||
curHp -= damageToTake | |||||
anim.play("RecieveHit") | |||||
# if our health reaches 0 - die | |||||
if curHp <= 0: | |||||
die() | |||||
# called when our health reaches 0 | |||||
func die (): | |||||
# destroy the node | |||||
queue_free() |
@@ -22,6 +22,19 @@ var vel := Vector3() | |||||
onready var camera = get_node("CameraOrbit") | onready var camera = get_node("CameraOrbit") | ||||
onready var attackCast = get_node("AttackRayCast") | onready var attackCast = get_node("AttackRayCast") | ||||
onready var anim = get_node("Casual2_Female/AnimationPlayer") | onready var anim = get_node("Casual2_Female/AnimationPlayer") | ||||
export var ui_path : NodePath | |||||
onready var ui = get_node(ui_path) | |||||
# called when the node is initialized | |||||
func _ready (): | |||||
# initialize the UI | |||||
ui.update_health_bar(curHp, maxHp) | |||||
ui.update_gold_text(gold) | |||||
func _process(delta): | |||||
# attack input | |||||
if is_on_floor() and Input.is_action_just_pressed("attack"): | |||||
try_attack() | |||||
# called every physics step (60 times a second) | # called every physics step (60 times a second) | ||||
func _physics_process (delta): | func _physics_process (delta): | ||||
@@ -61,20 +74,56 @@ func _physics_process (delta): | |||||
vel.y = jumpForce | vel.y = jumpForce | ||||
if is_on_floor(): | if is_on_floor(): | ||||
if input.x != 0 || input.z != 0: | |||||
if Input.is_action_pressed("run"): | |||||
anim.play("Run") | |||||
if anim.current_animation != "Punch": | |||||
if input.x != 0 || input.z != 0: | |||||
if Input.is_action_pressed("run"): | |||||
anim.play("Run") | |||||
else: | |||||
anim.play("Walk") | |||||
else: | else: | ||||
anim.play("Walk") | |||||
else: | |||||
anim.play("Idle") | |||||
anim.play("Idle") | |||||
else: | else: | ||||
anim.play("RecieveHit") | anim.play("RecieveHit") | ||||
# move along the current velocity | # move along the current velocity | ||||
vel = move_and_slide(vel, Vector3.UP) | |||||
vel = move_and_slide(vel, Vector3.UP, true, 4, deg2rad(89)) | |||||
# called when we collect a coin | # called when we collect a coin | ||||
func give_gold (amount): | func give_gold (amount): | ||||
gold += amount | gold += amount | ||||
print(gold) | |||||
# update the UI | |||||
ui.update_gold_text(gold) | |||||
# called when an enemy deals damage to us | |||||
func take_damage (damageToTake): | |||||
curHp -= damageToTake | |||||
# update the UI | |||||
ui.update_health_bar(curHp, maxHp) | |||||
# if our health is 0, die | |||||
if curHp <= 0: | |||||
die() | |||||
# called when our health reaches 0 | |||||
func die (): | |||||
# reload the scene | |||||
get_tree().reload_current_scene() | |||||
# called when we press the attack button | |||||
func try_attack(): | |||||
# if we're not ready to attack, return | |||||
if OS.get_ticks_msec() - lastAttackTime < attackRate * 1000: | |||||
return | |||||
# set the last attack time to now | |||||
lastAttackTime = OS.get_ticks_msec() | |||||
# play the animation | |||||
anim.stop() | |||||
anim.play("Punch") | |||||
# is the ray cast colliding with an enemy? | |||||
if attackCast.is_colliding(): | |||||
if attackCast.get_collider().has_method("take_damage"): | |||||
attackCast.get_collider().take_damage(damage) |
@@ -0,0 +1,22 @@ | |||||
extends Control | |||||
export var healthBar_path : NodePath | |||||
onready var healthBar = get_node(healthBar_path) | |||||
export var goldText_path : NodePath | |||||
onready var goldText = get_node(goldText_path) | |||||
# called when we take damage | |||||
func update_health_bar (curHp, maxHp): | |||||
fetch_components() | |||||
healthBar.value = (100 / maxHp) * curHp | |||||
# called when our gold changes | |||||
func update_gold_text (gold): | |||||
fetch_components() | |||||
goldText.text = "Gold: " + str(gold) | |||||
func fetch_components(): | |||||
if healthBar == null: | |||||
healthBar = get_node("HealthBar") | |||||
if goldText == null: | |||||
goldText = get_node("GoldText") |
@@ -0,0 +1,34 @@ | |||||
[remap] | |||||
importer="texture" | |||||
type="StreamTexture" | |||||
path="res://.import/white_square.png-f344ecd986efc79bea0a32343c81c38b.stex" | |||||
metadata={ | |||||
"vram_texture": false | |||||
} | |||||
[deps] | |||||
source_file="res://jrpg/textures/white_square.png" | |||||
dest_files=[ "res://.import/white_square.png-f344ecd986efc79bea0a32343c81c38b.stex" ] | |||||
[params] | |||||
compress/mode=0 | |||||
compress/lossy_quality=0.7 | |||||
compress/hdr_mode=0 | |||||
compress/bptc_ldr=0 | |||||
compress/normal_map=0 | |||||
flags/repeat=0 | |||||
flags/filter=true | |||||
flags/mipmaps=false | |||||
flags/anisotropic=false | |||||
flags/srgb=2 | |||||
process/fix_alpha_border=true | |||||
process/premult_alpha=false | |||||
process/HDR_as_SRGB=false | |||||
process/invert_color=false | |||||
stream=false | |||||
size_limit=0 | |||||
detect_3d=true | |||||
svg/scale=1.0 |