wip level length measure

This commit is contained in:
Jill 2023-05-26 18:37:31 +03:00
parent cb4c0b55a1
commit 4f1fec7fe5
Signed by: oat
GPG Key ID: 33489AA58A955108
2 changed files with 108 additions and 8 deletions

View File

@ -45,6 +45,7 @@ CrystalGauntlet.endpoints["/uploadGJLevel21.php"] = ->(context : HTTP::Server::C
level_raw_objects = Level.decode(params["levelString"])
level_objects = Level.to_objectdata(level_raw_objects)
inner_level_string = level_raw_objects.find! { |obj| !obj.has_key?("1") && obj["kA9"]? == "0" }
objects = level_objects.size
forbidden_objects = config_get("levels.parsing.object_blocklist").as?(Array(TOML::Type))
@ -91,12 +92,11 @@ CrystalGauntlet.endpoints["/uploadGJLevel21.php"] = ->(context : HTTP::Server::C
coins = level_objects.count { |obj| obj.id == 1329 } # user coin id
# todo: check if dual portals even exist?
two_player = false
level_raw_objects.each do |obj|
if !obj.has_key?("1") && obj["kA10"]? == "1"
two_player = true
end
end
two_player = inner_level_string["kA10"]? == "1"
# todo: currently brokey
#level_length_secs = Level.measure_length(level_objects, inner_level_string["kA4"]?.try &.to_i? || 0)
#LOG.debug { "level is #{level_length_secs}s long" }
else
objects = params["objects"].to_i
coins = params["coins"].to_i

View File

@ -21,11 +21,11 @@ module CrystalGauntlet::Level
end
# the X position of the object
def x
@raw["2"].to_i
@raw["2"].to_f
end
# the Y position of the object
def y
@raw["3"].to_i
@raw["3"].to_f
end
# strings
@ -293,4 +293,104 @@ module CrystalGauntlet::Level
def gmd_parse(gmd_file : String)
Level.array_to_hash(XML.parse(gmd_file).first_element_child.not_nil!.children.reject { |node| node.type == XML::Node::Type::TEXT_NODE }.map { |node| node.children.to_s})
end
# heavily references https://github.com/TeamHaxGD/GDDocs/blob/master/algorithms/level_length.c
enum PortalSpeed
# 0.5x
Slow
# 1x
Normal
# 2x
Medium
# 3x
Fast
# 4x
VeryFast
def portal_speed
case self
when .slow?
251.16
when .normal?
311.58
when .medium?
387.42
when .fast?
478.0
when .very_fast?
576.0
else
0.0
end
end
end
def id_to_portal_speed(id : Int32)
case id
when 200
PortalSpeed::Slow
when 201
PortalSpeed::Normal
when 202
PortalSpeed::Medium
when 203
PortalSpeed::Fast
when 1334
PortalSpeed::VeryFast
end
end
def get_seconds_from_xpos(pos : Float64, start_speed : PortalSpeed, portals : Array(ObjectData))
speed = 0.0
last_obj_pos = 0.0
last_segment = 0.0
segments = 0.0
speed = start_speed.portal_speed
if portals.empty?
return pos / speed
end
portals.each do |portal|
s = portal.x - last_obj_pos
if pos < s
s /= speed
last_segment = s
segments += s
speed = id_to_portal_speed(portal.id).not_nil!.portal_speed
last_obj_pos = portal.x
end
end
return ((pos - last_segment) / speed) + segments;
end
def measure_length(objects : Array(ObjectData), ka4 : Int32)
start_speed = case ka4
when 0
PortalSpeed::Normal
when 1
PortalSpeed::Slow
when 2
PortalSpeed::Medium
when 3
PortalSpeed::Fast
when 4
PortalSpeed::VeryFast
else
PortalSpeed::Normal
end
max_x_pos = objects.reduce 0.0 { |a, b| Math.max(a, b.x) }
portals = objects
.select { |obj| id_to_portal_speed(obj.id) && obj.checked }
.sort { |a, b| a.x <=> b.x }
get_seconds_from_xpos(max_x_pos, start_speed, portals)
end
end