kimi gone wild
This commit is contained in:
39
lib/odinsea/game/movement/absolute.ex
Normal file
39
lib/odinsea/game/movement/absolute.ex
Normal file
@@ -0,0 +1,39 @@
|
||||
defmodule Odinsea.Game.Movement.Absolute do
|
||||
@moduledoc """
|
||||
Absolute life movement - normal walking, flying, etc.
|
||||
Ported from Java AbsoluteLifeMovement.java
|
||||
|
||||
This is the most common movement type for:
|
||||
- Normal walking (command 0)
|
||||
- Flying (commands 37-42)
|
||||
- Rush skills (when not instant)
|
||||
|
||||
Contains position, velocity, and offset information.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (0, 37-42)
|
||||
x: integer(), # Target X position
|
||||
y: integer(), # Target Y position
|
||||
vx: integer(), # X velocity (pixels per second)
|
||||
vy: integer(), # Y velocity (pixels per second)
|
||||
unk: integer(), # Unknown short value
|
||||
offset_x: integer(), # X offset
|
||||
offset_y: integer(), # Y offset
|
||||
stance: integer(), # New stance/move action
|
||||
duration: integer() # Movement duration in ms
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:x,
|
||||
:y,
|
||||
:vx,
|
||||
:vy,
|
||||
:unk,
|
||||
:offset_x,
|
||||
:offset_y,
|
||||
:stance,
|
||||
:duration
|
||||
]
|
||||
end
|
||||
24
lib/odinsea/game/movement/aran.ex
Normal file
24
lib/odinsea/game/movement/aran.ex
Normal file
@@ -0,0 +1,24 @@
|
||||
defmodule Odinsea.Game.Movement.Aran do
|
||||
@moduledoc """
|
||||
Aran movement - Aran class combat step movements.
|
||||
Ported from Java AranMovement.java
|
||||
|
||||
Used for:
|
||||
- Aran combat steps (commands 21-31)
|
||||
- Special Aran skills (command 35)
|
||||
|
||||
Note: Position is not used for this movement type.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (21-31, 35)
|
||||
stance: integer(), # New stance/move action
|
||||
unk: integer() # Unknown short value
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:stance,
|
||||
:unk
|
||||
]
|
||||
end
|
||||
31
lib/odinsea/game/movement/bounce.ex
Normal file
31
lib/odinsea/game/movement/bounce.ex
Normal file
@@ -0,0 +1,31 @@
|
||||
defmodule Odinsea.Game.Movement.Bounce do
|
||||
@moduledoc """
|
||||
Bounce movement - bouncing off surfaces.
|
||||
Ported from Java BounceMovement.java
|
||||
|
||||
Used for:
|
||||
- Bouncing (command -1)
|
||||
- Wall bouncing (commands 18, 19)
|
||||
- Platform bouncing (commands 5-7)
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (-1, 5-7, 18, 19)
|
||||
x: integer(), # Bounce X position
|
||||
y: integer(), # Bounce Y position
|
||||
unk: integer(), # Unknown short value
|
||||
foothold: integer(), # Foothold after bounce
|
||||
stance: integer(), # New stance/move action
|
||||
duration: integer() # Movement duration in ms
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:x,
|
||||
:y,
|
||||
:unk,
|
||||
:foothold,
|
||||
:stance,
|
||||
:duration
|
||||
]
|
||||
end
|
||||
29
lib/odinsea/game/movement/chair.ex
Normal file
29
lib/odinsea/game/movement/chair.ex
Normal file
@@ -0,0 +1,29 @@
|
||||
defmodule Odinsea.Game.Movement.Chair do
|
||||
@moduledoc """
|
||||
Chair movement - sitting on chairs/mounts.
|
||||
Ported from Java ChairMovement.java
|
||||
|
||||
Used for:
|
||||
- Sitting on chairs (commands 9, 12)
|
||||
- Mount riding (command 13 in GMS)
|
||||
- Special seating
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (9, 10, 11, 12, 13)
|
||||
x: integer(), # Chair X position
|
||||
y: integer(), # Chair Y position
|
||||
unk: integer(), # Unknown short value
|
||||
stance: integer(), # New stance/move action
|
||||
duration: integer() # Movement duration in ms
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:x,
|
||||
:y,
|
||||
:unk,
|
||||
:stance,
|
||||
:duration
|
||||
]
|
||||
end
|
||||
22
lib/odinsea/game/movement/change_equip.ex
Normal file
22
lib/odinsea/game/movement/change_equip.ex
Normal file
@@ -0,0 +1,22 @@
|
||||
defmodule Odinsea.Game.Movement.ChangeEquip do
|
||||
@moduledoc """
|
||||
Change equip special awesome - equipment change during movement.
|
||||
Ported from Java ChangeEquipSpecialAwesome.java
|
||||
|
||||
Used for:
|
||||
- Changing equipment mid-movement (commands 10, 11)
|
||||
- Quick gear switching
|
||||
|
||||
Note: Position is always 0,0 for this fragment type.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (10, 11)
|
||||
wui: integer() # Weapon upgrade index or similar
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:wui
|
||||
]
|
||||
end
|
||||
40
lib/odinsea/game/movement/jump_down.ex
Normal file
40
lib/odinsea/game/movement/jump_down.ex
Normal file
@@ -0,0 +1,40 @@
|
||||
defmodule Odinsea.Game.Movement.JumpDown do
|
||||
@moduledoc """
|
||||
Jump down movement - falling through platforms.
|
||||
Ported from Java JumpDownMovement.java
|
||||
|
||||
Used for:
|
||||
- Jumping down through platforms (commands 13, 14)
|
||||
- Controlled falling
|
||||
|
||||
Contains foothold information for landing detection.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (13, 14)
|
||||
x: integer(), # Target X position
|
||||
y: integer(), # Target Y position
|
||||
vx: integer(), # X velocity
|
||||
vy: integer(), # Y velocity
|
||||
unk: integer(), # Unknown short value
|
||||
foothold: integer(), # Target foothold ID
|
||||
offset_x: integer(), # X offset
|
||||
offset_y: integer(), # Y offset
|
||||
stance: integer(), # New stance/move action
|
||||
duration: integer() # Movement duration in ms
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:x,
|
||||
:y,
|
||||
:vx,
|
||||
:vy,
|
||||
:unk,
|
||||
:foothold,
|
||||
:offset_x,
|
||||
:offset_y,
|
||||
:stance,
|
||||
:duration
|
||||
]
|
||||
end
|
||||
443
lib/odinsea/game/movement/path.ex
Normal file
443
lib/odinsea/game/movement/path.ex
Normal file
@@ -0,0 +1,443 @@
|
||||
defmodule Odinsea.Game.Movement.Path do
|
||||
@moduledoc """
|
||||
MovePath for mob movement (newer movement system).
|
||||
Ported from Java MovePath.java
|
||||
|
||||
This is an alternative movement system used by mobs in newer
|
||||
versions of MapleStory. It uses a more compact encoding.
|
||||
|
||||
Structure:
|
||||
- Initial position (x, y, vx, vy)
|
||||
- List of movement elements
|
||||
- Optional passive data (keypad states, movement rect)
|
||||
"""
|
||||
|
||||
import Bitwise
|
||||
alias Odinsea.Net.Packet.In
|
||||
|
||||
defstruct [
|
||||
:x, # Initial X position
|
||||
:y, # Initial Y position
|
||||
:vx, # Initial X velocity
|
||||
:vy, # Initial Y velocity
|
||||
elements: [], # List of MoveElem
|
||||
key_pad_states: [], # Keypad states (passive mode)
|
||||
move_rect: nil # Movement rectangle (passive mode)
|
||||
]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
x: integer() | nil,
|
||||
y: integer() | nil,
|
||||
vx: integer() | nil,
|
||||
vy: integer() | nil,
|
||||
elements: list(MoveElem.t()),
|
||||
key_pad_states: list(integer()),
|
||||
move_rect: map() | nil
|
||||
}
|
||||
|
||||
defmodule MoveElem do
|
||||
@moduledoc """
|
||||
Individual movement element within a MovePath.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
attribute: integer(), # Movement type/attribute
|
||||
x: integer(), # X position
|
||||
y: integer(), # Y position
|
||||
vx: integer(), # X velocity
|
||||
vy: integer(), # Y velocity
|
||||
fh: integer(), # Foothold
|
||||
fall_start: integer(), # Fall start position
|
||||
offset_x: integer(), # X offset
|
||||
offset_y: integer(), # Y offset
|
||||
sn: integer(), # Skill/stat number
|
||||
move_action: integer(), # Move action/stance
|
||||
elapse: integer() # Elapsed time
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:attribute,
|
||||
:x,
|
||||
:y,
|
||||
:vx,
|
||||
:vy,
|
||||
:fh,
|
||||
:fall_start,
|
||||
:offset_x,
|
||||
:offset_y,
|
||||
:sn,
|
||||
:move_action,
|
||||
:elapse
|
||||
]
|
||||
end
|
||||
|
||||
@doc """
|
||||
Decodes a MovePath from a packet.
|
||||
|
||||
## Parameters
|
||||
- packet: The incoming packet
|
||||
- passive: Whether to decode passive data (keypad, rect)
|
||||
|
||||
## Returns
|
||||
%MovePath{} struct with decoded data
|
||||
"""
|
||||
def decode(packet, passive \\ false) do
|
||||
old_x = In.decode_short(packet)
|
||||
old_y = In.decode_short(packet)
|
||||
old_vx = In.decode_short(packet)
|
||||
old_vy = In.decode_short(packet)
|
||||
|
||||
count = In.decode_byte(packet)
|
||||
|
||||
{elements, final_x, final_y, final_vx, final_vy, _fh_last} =
|
||||
decode_elements(packet, count, old_x, old_y, old_vx, old_vy, [])
|
||||
|
||||
path = %__MODULE__{
|
||||
x: old_x,
|
||||
y: old_y,
|
||||
vx: old_vx,
|
||||
vy: old_vy,
|
||||
elements: Enum.reverse(elements)
|
||||
}
|
||||
|
||||
if passive do
|
||||
{key_pad_states, move_rect} = decode_passive_data(packet)
|
||||
%{path |
|
||||
x: final_x,
|
||||
y: final_y,
|
||||
vx: final_vx,
|
||||
vy: final_vy,
|
||||
key_pad_states: key_pad_states,
|
||||
move_rect: move_rect
|
||||
}
|
||||
else
|
||||
%{path |
|
||||
x: final_x,
|
||||
y: final_y,
|
||||
vx: final_vx,
|
||||
vy: final_vy
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Encodes a MovePath to binary for packet output.
|
||||
"""
|
||||
def encode(%__MODULE__{} = path, _passive \\ false) do
|
||||
elements_data = Enum.map_join(path.elements, &encode_element/1)
|
||||
|
||||
<<path.x::16-little, path.y::16-little,
|
||||
path.vx::16-little, path.vy::16-little,
|
||||
length(path.elements)::8,
|
||||
elements_data::binary>>
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the final position from the MovePath.
|
||||
"""
|
||||
def get_final_position(%__MODULE__{} = path) do
|
||||
case List.last(path.elements) do
|
||||
nil -> %{x: path.x, y: path.y}
|
||||
elem -> %{x: elem.x, y: elem.y}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the final move action/stance from the MovePath.
|
||||
"""
|
||||
def get_final_action(%__MODULE__{} = path) do
|
||||
case List.last(path.elements) do
|
||||
nil -> 0
|
||||
elem -> elem.move_action
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets the final foothold from the MovePath.
|
||||
"""
|
||||
def get_final_foothold(%__MODULE__{} = path) do
|
||||
case List.last(path.elements) do
|
||||
nil -> 0
|
||||
elem -> elem.fh
|
||||
end
|
||||
end
|
||||
|
||||
# ============================================================================
|
||||
# Private Functions
|
||||
# ============================================================================
|
||||
|
||||
defp decode_elements(_packet, 0, old_x, old_y, old_vx, old_vy, acc),
|
||||
do: {acc, old_x, old_y, old_vx, old_vy, 0}
|
||||
|
||||
defp decode_elements(packet, count, old_x, old_y, old_vx, old_vy, acc) do
|
||||
attr = In.decode_byte(packet)
|
||||
|
||||
{elem, new_x, new_y, new_vx, new_vy, _fh_last} =
|
||||
case attr do
|
||||
# Absolute with foothold
|
||||
a when a in [0, 6, 13, 15, 37, 38] ->
|
||||
x = In.decode_short(packet)
|
||||
y = In.decode_short(packet)
|
||||
vx = In.decode_short(packet)
|
||||
vy = In.decode_short(packet)
|
||||
fh = In.decode_short(packet)
|
||||
|
||||
fall_start = if attr == 13, do: In.decode_short(packet), else: 0
|
||||
offset_x = In.decode_short(packet)
|
||||
offset_y = In.decode_short(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: x,
|
||||
y: y,
|
||||
vx: vx,
|
||||
vy: vy,
|
||||
fh: fh,
|
||||
fall_start: fall_start,
|
||||
offset_x: offset_x,
|
||||
offset_y: offset_y
|
||||
}
|
||||
{elem, x, y, vx, vy, fh}
|
||||
|
||||
# Velocity only
|
||||
a when a in [1, 2, 14, 17, 19, 32, 33, 34, 35] ->
|
||||
vx = In.decode_short(packet)
|
||||
vy = In.decode_short(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: old_x,
|
||||
y: old_y,
|
||||
vx: vx,
|
||||
vy: vy,
|
||||
fh: 0
|
||||
}
|
||||
{elem, old_x, old_y, vx, vy, 0}
|
||||
|
||||
# Position with foothold
|
||||
a when a in [3, 4, 5, 7, 8, 9, 11] ->
|
||||
x = In.decode_short(packet)
|
||||
y = In.decode_short(packet)
|
||||
fh = In.decode_short(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: x,
|
||||
y: y,
|
||||
vx: 0,
|
||||
vy: 0,
|
||||
fh: fh
|
||||
}
|
||||
{elem, x, y, 0, 0, fh}
|
||||
|
||||
# Stat change
|
||||
10 ->
|
||||
sn = In.decode_byte(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
sn: sn,
|
||||
x: old_x,
|
||||
y: old_y,
|
||||
vx: 0,
|
||||
vy: 0,
|
||||
fh: 0,
|
||||
elapse: 0,
|
||||
move_action: 0
|
||||
}
|
||||
{elem, old_x, old_y, 0, 0, 0}
|
||||
|
||||
# Start fall down
|
||||
12 ->
|
||||
vx = In.decode_short(packet)
|
||||
vy = In.decode_short(packet)
|
||||
fall_start = In.decode_short(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: old_x,
|
||||
y: old_y,
|
||||
vx: vx,
|
||||
vy: vy,
|
||||
fh: 0,
|
||||
fall_start: fall_start
|
||||
}
|
||||
{elem, old_x, old_y, vx, vy, 0}
|
||||
|
||||
# Flying block
|
||||
18 ->
|
||||
x = In.decode_short(packet)
|
||||
y = In.decode_short(packet)
|
||||
vx = In.decode_short(packet)
|
||||
vy = In.decode_short(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: x,
|
||||
y: y,
|
||||
vx: vx,
|
||||
vy: vy,
|
||||
fh: 0
|
||||
}
|
||||
{elem, x, y, vx, vy, 0}
|
||||
|
||||
# No change (21-31)
|
||||
a when a in [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] ->
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: old_x,
|
||||
y: old_y,
|
||||
vx: old_vx,
|
||||
vy: old_vy,
|
||||
fh: 0
|
||||
}
|
||||
{elem, old_x, old_y, old_vx, old_vy, 0}
|
||||
|
||||
# Special case 36
|
||||
36 ->
|
||||
x = In.decode_short(packet)
|
||||
y = In.decode_short(packet)
|
||||
vx = In.decode_short(packet)
|
||||
vy = In.decode_short(packet)
|
||||
fh = In.decode_short(packet)
|
||||
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: x,
|
||||
y: y,
|
||||
vx: vx,
|
||||
vy: vy,
|
||||
fh: fh
|
||||
}
|
||||
{elem, x, y, vx, vy, fh}
|
||||
|
||||
# Unknown attribute - skip gracefully
|
||||
_unknown ->
|
||||
elem = %MoveElem{
|
||||
attribute: attr,
|
||||
x: old_x,
|
||||
y: old_y,
|
||||
vx: old_vx,
|
||||
vy: old_vy,
|
||||
fh: 0
|
||||
}
|
||||
{elem, old_x, old_y, old_vx, old_vy, 0}
|
||||
end
|
||||
|
||||
# Read move action and elapse (except for stat change)
|
||||
{elem, new_x, new_y, new_vx, new_vy} =
|
||||
if attr != 10 do
|
||||
move_action = In.decode_byte(packet)
|
||||
elapse = In.decode_short(packet)
|
||||
|
||||
{%{elem |
|
||||
move_action: move_action,
|
||||
elapse: elapse
|
||||
}, elem.x, elem.y, elem.vx, elem.vy}
|
||||
else
|
||||
{elem, new_x, new_y, new_vx, new_vy}
|
||||
end
|
||||
|
||||
decode_elements(
|
||||
packet,
|
||||
count - 1,
|
||||
new_x,
|
||||
new_y,
|
||||
new_vx,
|
||||
new_vy,
|
||||
[elem | acc]
|
||||
)
|
||||
end
|
||||
|
||||
defp decode_passive_data(packet) do
|
||||
keys = In.decode_byte(packet)
|
||||
|
||||
key_pad_states =
|
||||
if keys > 0 do
|
||||
decode_keypad_states(packet, keys, 0, [])
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
move_rect = %{
|
||||
left: In.decode_short(packet),
|
||||
top: In.decode_short(packet),
|
||||
right: In.decode_short(packet),
|
||||
bottom: In.decode_short(packet)
|
||||
}
|
||||
|
||||
{Enum.reverse(key_pad_states), move_rect}
|
||||
end
|
||||
|
||||
defp decode_keypad_states(_packet, 0, _value, acc), do: acc
|
||||
|
||||
defp decode_keypad_states(packet, remaining, value, acc) do
|
||||
{new_value, decoded} =
|
||||
if rem(length(acc), 2) != 0 do
|
||||
{bsr(value, 4), band(value, 0x0F)}
|
||||
else
|
||||
v = In.decode_byte(packet)
|
||||
{v, band(v, 0x0F)}
|
||||
end
|
||||
|
||||
decode_keypad_states(packet, remaining - 1, new_value, [decoded | acc])
|
||||
end
|
||||
|
||||
defp encode_element(%MoveElem{} = elem) do
|
||||
attr = elem.attribute
|
||||
|
||||
base = <<attr::8>>
|
||||
|
||||
data =
|
||||
case attr do
|
||||
a when a in [0, 6, 13, 15, 37, 38] ->
|
||||
<<elem.x::16-little, elem.y::16-little,
|
||||
elem.vx::16-little, elem.vy::16-little,
|
||||
elem.fh::16-little>> <>
|
||||
if attr == 13 do
|
||||
<<elem.fall_start::16-little>>
|
||||
else
|
||||
<<>>
|
||||
end <>
|
||||
<<elem.offset_x::16-little, elem.offset_y::16-little>>
|
||||
|
||||
a when a in [1, 2, 14, 17, 19, 32, 33, 34, 35] ->
|
||||
<<elem.vx::16-little, elem.vy::16-little>>
|
||||
|
||||
a when a in [3, 4, 5, 7, 8, 9, 11] ->
|
||||
<<elem.x::16-little, elem.y::16-little,
|
||||
elem.fh::16-little>>
|
||||
|
||||
10 ->
|
||||
<<elem.sn::8>>
|
||||
|
||||
12 ->
|
||||
<<elem.vx::16-little, elem.vy::16-little,
|
||||
elem.fall_start::16-little>>
|
||||
|
||||
18 ->
|
||||
<<elem.x::16-little, elem.y::16-little,
|
||||
elem.vx::16-little, elem.vy::16-little>>
|
||||
|
||||
a when a in [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31] ->
|
||||
<<>>
|
||||
|
||||
36 ->
|
||||
<<elem.x::16-little, elem.y::16-little,
|
||||
elem.vx::16-little, elem.vy::16-little,
|
||||
elem.fh::16-little>>
|
||||
|
||||
_ ->
|
||||
<<>>
|
||||
end
|
||||
|
||||
footer =
|
||||
if attr != 10 do
|
||||
<<elem.move_action::8, elem.elapse::16-little>>
|
||||
else
|
||||
<<>>
|
||||
end
|
||||
|
||||
base <> data <> footer
|
||||
end
|
||||
end
|
||||
29
lib/odinsea/game/movement/relative.ex
Normal file
29
lib/odinsea/game/movement/relative.ex
Normal file
@@ -0,0 +1,29 @@
|
||||
defmodule Odinsea.Game.Movement.Relative do
|
||||
@moduledoc """
|
||||
Relative life movement - small position adjustments.
|
||||
Ported from Java RelativeLifeMovement.java
|
||||
|
||||
Used for:
|
||||
- Small adjustments (commands 1, 2)
|
||||
- Float movements (commands 33, 34, 36)
|
||||
- Fine-tuning position
|
||||
|
||||
Contains relative offset from current position.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (1, 2, 33, 34, 36)
|
||||
x: integer(), # X offset (delta from current)
|
||||
y: integer(), # Y offset (delta from current)
|
||||
stance: integer(), # New stance/move action
|
||||
duration: integer() # Movement duration in ms
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:x,
|
||||
:y,
|
||||
:stance,
|
||||
:duration
|
||||
]
|
||||
end
|
||||
32
lib/odinsea/game/movement/teleport.ex
Normal file
32
lib/odinsea/game/movement/teleport.ex
Normal file
@@ -0,0 +1,32 @@
|
||||
defmodule Odinsea.Game.Movement.Teleport do
|
||||
@moduledoc """
|
||||
Teleport movement - instant position change.
|
||||
Ported from Java TeleportMovement.java
|
||||
|
||||
Used for:
|
||||
- Rush skills (command 3)
|
||||
- Teleport (command 4)
|
||||
- Assassinate (command 8)
|
||||
- Special skills (commands 100, 101)
|
||||
|
||||
Note: Duration is always 0 for teleports.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (3, 4, 8, 100, 101)
|
||||
x: integer(), # Target X position
|
||||
y: integer(), # Target Y position
|
||||
vx: integer(), # X velocity (visual effect)
|
||||
vy: integer(), # Y velocity (visual effect)
|
||||
stance: integer() # New stance/move action
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:x,
|
||||
:y,
|
||||
:vx,
|
||||
:vy,
|
||||
:stance
|
||||
]
|
||||
end
|
||||
36
lib/odinsea/game/movement/unknown.ex
Normal file
36
lib/odinsea/game/movement/unknown.ex
Normal file
@@ -0,0 +1,36 @@
|
||||
defmodule Odinsea.Game.Movement.Unknown do
|
||||
@moduledoc """
|
||||
Unknown movement type - placeholder for unhandled commands.
|
||||
Ported from Java UnknownMovement.java
|
||||
|
||||
Used for:
|
||||
- Command 32 (unknown structure)
|
||||
- Any future/unrecognized movement types
|
||||
|
||||
Parses generic structure that may match unknown commands.
|
||||
"""
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
command: integer(), # Movement command type (32, or unknown)
|
||||
unk: integer(), # Unknown short value
|
||||
x: integer(), # X position
|
||||
y: integer(), # Y position
|
||||
vx: integer(), # X velocity
|
||||
vy: integer(), # Y velocity
|
||||
foothold: integer(), # Foothold
|
||||
stance: integer(), # New stance/move action
|
||||
duration: integer() # Movement duration in ms
|
||||
}
|
||||
|
||||
defstruct [
|
||||
:command,
|
||||
:unk,
|
||||
:x,
|
||||
:y,
|
||||
:vx,
|
||||
:vy,
|
||||
:foothold,
|
||||
:stance,
|
||||
:duration
|
||||
]
|
||||
end
|
||||
Reference in New Issue
Block a user