Repository navigation
Bring the merged v83 stack (#497–#514) to master - #517
Merged
Merged
Conversation
Read and write path elements by type as v83 does (FUN_0068a33c decode, FUN_0068a563 encode): velocity-only types keep the position before them, type 10 is one byte, every other type ends with stance and duration. HC sends velocities in px/s and a real start point, and records element 4 when Teleport is used. The server relays the client's start point instead of 0 and parses from it, for players and mobs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The user's steps merge into runs and go out about once a second, holding back air and rope elements until a foothold follows (FUN_0068ab85, FUN_0068a88d), with the key byte and bounding rect. Other characters queue whole paths and play them on a Hermite curve, a tenth faster when a second or more behind, snapping when over six (FUN_0068b371, FUN_0068adcc).
The controller runs the mob's AI on its own body ahead of what is shown, steps it until it has a second of movement (FUN_0066b6fc), sends that path in MOVE_MONSTER and plays it like every other client. A hit shows at once; the shown path stops at the next foothold and the AI flinches from there (FUN_0068b16f). Other clients play the paths they get in turn.
…L162) The server gives one player per field control of its NPCs (0x103, handed on when they leave) and relays their 0xC5 choices to the whole map as 0x104. HC chooses only for NPCs it controls, waits for the echo, and every client plays what comes back, as v83 does (FUN_006d2918, 006d2e07). HC also handles REMOVE_NPC and control release (mode 0 no longer removes).
Server: buff skills give their level's stats plus their own (Booster, Combo, charges, Hyper Body, Maple Warrior, Dark Sight, Shadow Partner, ...), with MP, cooldown and item costs. GIVE_BUFF carries every stat in the client's bit order with the exact tail. The stats others see go out as GIVE/CANCEL_FOREIGN_BUFF (0xC7/0xC8) on use, cancel, expiry and death, and in SPAWN_PLAYER. Damage caps count attack buffs; Shadow Partner doubles a shot's lines and Soul Arrow needs no arrows. A player leaving a field is shown before mob/NPC control passes on. HC: BuffParser reads the flags in the v83 decode order (FUN_00781d0e) and the remote encoding (FUN_00788156, two-state blocks). Buffstat::by_bit replaces the unordered maps. New 199/200 handlers and the spawn block keep remote buffs on OtherChar. Harness: strict packet loops skip NPC control (0x103).
Locally a ranged attack with Shadow Partner (not Taunt or Vampire) has twice the hits, at most 15, and throws its bullets again from 30 px behind the user, below the first set. Other users' shots read their Shadow Partner foreign buff: twice the bullets and shown hits, the client's start choice by mob index, and a miss's ends 30 px short.
USE_SKILL's party mask now reaches the members it names: the directory maps slot bits to party members on the caster's map, and each applies the buffs (or Heal's share) when alive and within the skill's lt/rb plus 100 px, with user effect 2 showing the skill's affected animation. HC plays that effect on 0xC6 and 0xCE type 2 instead of the use effect.
Server: MobStat flags in the client's decode order, statuses in spawn packets, USE_SKILL mob list, Threaten/Slow/Seal/Doom/Shadow Web applied in area with prop rolls, crashes/Dispel cancel mob buffs, expiry resets. HC: MobStatParser, spawn + 0xF2/0xF3 handlers, Speed into the shoe, Doom look swap/restore, hold for Stun/Freeze/Web, status effects. Harness: mob_debuffs (Slow on snails).
Attacks put their skill's status (stuns, Panic's darkness, freezes, poisons) and a learned Venom on the mobs they hit, rolled per hit that deals damage. Ninja Ambush joins the USE_SKILL debuffs. Poison, Venom and Ambush take HP on the field tick each second (fixedDamage if the mob has one, never below 1 HP), crediting the inflicter and sending them the HP bar. Poison- and ice-immune mobs (elemAttr S1/I1) shrug off Poison and Freeze. HeavenClient shows the numbers each second over the hurt mob as v83's CMob::Update does (MobHurts).
Server: Poison Mist's attack leaves a mist over the skill's lt/rb box around the caster (mirrored facing right). It starts 800 ms later, rolls prop every 2.5 s to poison the live mobs in it, and lifts after the skill's time. AFFECTED_AREA_CREATED goes to the map and to joiners; AFFECTED_AREA_REMOVED lifts it. HeavenClient: MapMists lays the skill's `tile` clouds over the area as v83's FUN_00432776 does (MistLayout.h, a diamond of random tiles), draws them above the map's objects, and fades them out over a second on removal. Harness: poison_mist.
…v83 30/37/51) 30 sets a tab's slot count and refreshes the item window, 37 answers the pending skill request, 51 shows the SkillBook glow on the user (front and back layers) and, for the local player, the Enchant sound and the v83 chat line.
…ULT 0x33 The server reads a book's info/skill, masterLevel, reqSkillLevel and success, takes the skill of the reader's job, spends the book and rolls its success; HeavenClient sends 0x52 for 228/229 items (v83 FUN_00a0a1b2).
HeavenClient answers the pending move and shows v83's reason in chat or a notice. The server refuses a portal it can't resolve with BLOCKED_MAP instead of disconnecting, and channel or cash shop refusals with BLOCKED_SERVER.
Server: GiveFameHandler (level 15, not self), fame_log with the day and 30-day rules, the field routes to the target on the giver's map, the target changes its fame and answers both sides; a miss is forgotten. HC: fame buttons per v83 (FUN_00a23eb5: on-map check, 5 minute cooldown), FameResponseHandler lines, char info fame update. Co-Authored-By: Claude <noreply@anthropic.com>
Server: USE_SKILL casts a summon at the client's spot (within 250x150 of the owner), spending MP and itemCon and giving its buff; the field keeps summons, shows SPAWN/REMOVE/MOVE_SUMMON, checks SUMMON_ATTACK against mobCount and a 2x damage cap, breaks Puppets at their x HP, and brings followers along on a map change. HeavenClient: MapSummons draws and animates summons (v83 CSummoned); SummonRules holds follow/circle movement, placement and damage; Combat places the cast, targets and attacks on the owner's 3 s / 1.5 s clock, and plays others' attacks; chat lines on expiry. Harness: summons test. Docs: combat.md Summons. Report 158.
A local Puppet's spawn makes each mob this client moves that is chasing someone chase the Puppet for 3-4 minutes; its removal lets them go (FUN_00679847). A mob touching an unblinking Puppet rolls 40/(lv+70) times its attack times 10-85% of it, over 100 (FUN_00793687), shows it, and sends DAMAGE_SUMMON (0x7a627a).
The client heals its owner with Aura of the Beholder, else buffs one stat with Hex, each in its skill's time (FUN_007a4080, FUN_007a5ab4, FUN_007a5c99), and sends BEHOLDER (0xB2). The server checks the skills, holds each to its pace in the field, heals or gives the Hex buff, and shows the others SUMMON_SKILL (0xB3).
A summon's hits now carry its skill's status, as a player's attacks do. Silver Hawk and Golden Eagle stun at the level's prop (50% to 99%). Elquines and Frostprey always freeze; their data has no prop. Each status lasts the level's x seconds, inferred from the freezes' x growing from 1 to 3. The client only shows the status it is sent. The harness has an Arch Mage's Elquines freeze a mob for 3 s. The Beholder test now finds its own summon on the shared map.
The server had no storage and the client had no storage window, so storage NPCs only gave their speech. Any NPC with info/trunkPut now opens the account's storage. Stored items and mesos are shared by the account's characters. TRUNK_REQUEST takes out, stores, sorts and moves mesos for the NPC's trunkGet and trunkPut fees, and TRUNK_RESULT answers with the bags that changed or the v83 error mode. Each change is saved with the player in one transaction, so an item is never in both places or neither. HeavenClient gets UIStorage, laid out after v83's CTrunkDlg, with the same count, fee and meso prompts. Buttons are placed by their top-left, as v83 does, which keeps BtSort's (35, 9) origin from pushing it onto the NPC portrait.
A Priest's Mystic Door now works end to end. The server checks the cast as the v83 client does (not in towns, event maps, maps whose fieldLimit forbids it, or within 50 px of a portal), and the owner's client actor keeps the one door, closing it when its time runs out, on a new cast, a channel change and logout. The field shows it to the map with SPAWN_DOOR and REMOVE_DOOR; the directory tells the owner (SPAWN_PORTAL) and the party on the owner's channel (party op 0x25 and the party block's door section) where it leads. USE_DOOR takes the owner and their party from the field to the town's door portal for the owner's slot, and back to the door through SET_FIELD's chase position. HeavenClient casts the door with v83's refusals and messages, draws field doors opening and standing and town doors at their portals, and walks through them with Up after the map's own portals. Doors are placed on the ground at the next update, since SPAWN_DOOR can arrive before the new map's footholds load, and the chase position is looked up from just above, since its rounded y can sit below a slope. DoorRules.h holds the rules apart from the map and has its own tests; the mystic_door harness test covers the server.
Chakra now heals its user by Cosmic's LUK-based range (LUK with equips), answered with an HP and MP stat update. Resurrection reaches only dead party members in its area and raises them with full HP. Time Leap ends every cooldown but its own, sending COOLDOWN 0 for each, for the caster and the members it reaches. These skills have neither buff stats nor a mob debuff, so skills::acts_alone keeps them from being refused as unsupported. In v83 a party member's Resurrection with no dead member in range plays its action and effect but is never sent (0x96d567); HeavenClient now does the same, while alone it is still sent with the 0x80 mask. The new party_skills harness test resurrects a member killed through the database and has a Chief Bandit heal with Chakra.
Mobs now use their Mob.nx attacks. The server answers a controller's move with whether the mob may attack next and its MP, takes each attack's MP cost, and relays the attack's action and data to the other players. A TAKE_DAMAGE may name the attack that hit; it is bounded by v83's damage formula at its largest (game::mob_damage), including the extra damage a player below the expected W.DEF for their job and level takes. Deadly attacks leave 1 HP and 1 MP, and mpBurn attacks burn MP. HeavenClient picks attacks the way v83's FUN_0066a517 does (boxes, aimed shots, balls, and rows of cells), plays them, replays other controllers' attacks, and checks each against the local player after attackAfter. The player's damage from touches and attacks now follows v83's physical and magic formulas and miss rolls (MobDamage.h), replacing the old touch procedure, and Achilles keeps its x per mille rather than taking it off. Tremble, doFirst, element resistance, hits on summons and other mobs, attack knockback speeds, and mob skills are left for later.
The harness stack's Docker build ran cargo with every core regardless of the host's job cap. The compose file now forwards CARGO_BUILD_JOBS as a build argument, and the Dockerfile passes it to cargo as -j when set.
Mobs now cast their MobSkill.img buffs, heals and summons as the v83 client does. The server grants a skill at the end of MOVE_MONSTER_RESPONSE when a controller's move asks to attack, picking from those the mob can pay for, that are off cooldown, within their HP limit and, for summons, under their limit. It checks the cast against the grant, the mob's skill list and its action, then applies it once the animation has played: statuses through MOB_STAT_SET, heals as a negative DAMAGE_MONSTER, and summoned mobs spawned for everyone with their summon effect. HeavenClient keeps the grant from the ack and casts it before picking an attack: it plays skillN, shows the level's effect after effectAfter, and sends the action and skill data. Other clients replay the cast. The spawn tail now reads the summon option as v83 does and plays the Summon.img effect, DAMAGE_MONSTER shows heals in blue, and Power Up and Magic Up scale the mob's hits on the player. Player diseases (phase C) remain.
Mob skills 120-126, 128 and 132 now give the players in the caster's lt/rb box a disease by the level's prop, and mob attacks with a disease give theirs on a damaging hit. A disease is a buff stat whose reason is the mob skill | level << 16: the player gets GIVE_BUFF, the map sees the shown ones with the reason as the value, and the server ends it on time or on death; the player can't cancel it. Poison takes x HP a second but never the last, and Curse halves kill EXP as Cosmic does. Dispel, on the caster and its party mask, rolls its prop per target and cures Poison, Seal, Darkness, Weakness, Curse and Slow. HeavenClient follows v83 CUserLocal: Stun stops all input, attacks and skills; Seduce steers the player by its pattern; Confuse reverses the arrows; Weakness stops jumps; Seal stops every skill but Dispel; Slow sets the walking speed. Each disease plays its MobSkill `affected` animation on the character, at the face for pos 1, and the player gets the v83 grey notice instead of a buff icon. Poison's foreign entry now keeps its reason. Darkness's accuracy, Holy Shield, cure items and the exact v83 head anchor are left open (reports/173-mob-attacks.md).
v83 (FUN_0094289f) flies Energy Orb's ball from 25 px in front of the shot's origin to the middle of its first mob, then on to the middle of each next one, 1.25 ms per pixel (Spark 2). Each mob is hit when the ball arrives, so the hits come one hop after another rather than all by horizontal distance. The client now does this for its own shots and other users', and draws no regular bullet for these skills.
The v83 client's MDamage (FUN_00791617) reads the mob's temporary stats on every hit. Disable turns the hit away. Magic Immunity lets only a roll of 0 in 100 through and otherwise shows 1. The EVA and MDR statuses add to the avoid and magic defense. Magic Guard Up leaves n% after the defense. Hard Skin stops every hit that is not critical, and only Evans crit spells. Weakness adds n%. The hit is also scaled by the weapon's percent for the spell's element (FUN_005d284f): the Elemental Wands and Staffs carry elemDefault and incRMAI/F/L/S/H, and every other weapon gives 100. HeavenClient now keeps Disable's byte as a status, names HardSkin and Weakness, reads the element boosts into EquipData, carries them on the Attack, and applies each step in Mob::next_magic_damage in the client's order.
CalcDamage::PDamage (FUN_0078df87) gates a blow on the same mob statuses MDamage does: Disable makes it miss, Physical Immune caps it at 1 unless the respect roll pierces it, the EVA and PDR statuses add to the mob's avoid and weapon defense, Power Guard Up scales it after the crit (except for Sacrifice), and Hard Skin stops every hit that is not critical. HeavenClient's weapon damage ignored all of them; it now applies them to weapon hits, while fixed damage still skips them as in v83. Unlike magic, PDamage never reads Weakness: its extra percent is Dragon Knight Berserk's damage.
A granted MobSkill 131 cast now lays a type 0 mist over the mob's lt/rb box for the level's time, owned by the mob and carrying the level's elemAttr as its element. As the v83 client does (FUN_00431783 from CUserLocal's update), HeavenClient hurts the player x once a second while they stand in a started mob mist without touching a mob. It shows the number and sends TAKE_DAMAGE from -4 with the skill and level. The server takes damage only for 131 at a known level and up to x, then tells the field through DAMAGE_PLAYER, which drops the mob fields for sources below -1. HeavenClient also learns the v83 Smokescreen rule (FUN_0043193a): a started type 2 area owned by the player or a party member keeps mob attacks, touch and mists off them. The server does not spawn those yet. Mist layout tests cover the hit and shelter lookups, and the harness mob_mists test covers the cast, the area, the damage limits and the expiry.
A mob's Weapon, Magic or full counter puts PCounter (bit 29) and/or MCounter (bit 30) on it, written after the statuses as each counter's spread and one shared chance, as the v83 client reads them. Each player attack (not a summon's) on a countering mob costs the attacker the value give or take half the spread, magic against MCounter. The client shows its own roll and sends nothing, so the server takes the HP. HeavenClient parses the new stats and shows the counter number over the player for each countering target it hits. Harness mob_counters casts Lilynouch's 145 and checks the HP lost to one swing.
A mob's Dispel (127) ends every buff but the diseases of each player in its area, unsummoning summons, and Banish (129) sends up to `count` of them to the mob's `ban/banMap` portal with its `banMsg` as a type 5 BROADCAST_MSG. Both roll the skill's prop first and reach the mob's controller when the skill has no area. The warp helper now takes a portal name. HeavenClient's BROADCAST_MSG handler now follows the client per type: "[Notice]" lines in light blue, the popup, the pink type 5 line, and it reads the extras of types 3, 6 and 7 instead of dropping the packet. The mob_dispel_banish harness test has an Aqua Road mob dispel a beginner's Nimble Feet and a subway Shade banish the player to the ticketing booth. move_mob moved into the harness's hunting helpers.
Mob skills 133-136 now inflict their diseases. Undead shares Puppet's buff bit 46 and is told apart by its mob skill, on both sides. Stop Potion, Stop Motion and Fear are bits 75-77, each shown with one int; the client had read bit 77 as an int and two bytes. The server refuses potions under Stop Potion and halves recovered HP (potions, Heal, Chakra) under Undead. Stop Motion's damage arrives as a mist hit with no skill code, and the server takes up to its value but never the last HP. The client gives the notices, refuses item use under Stop Potion or Seduce, and hurts a player who stands still two seconds under Stop Motion, with the v83 chat line and packet. Under Fear it blacks out the screen except Effect/MapEff.img/Viewrange/3 around the player, using a new cutout shader mode.
Item specs now carry their duration, the stats they raise and the diseases they cure. USE_ITEM cures those diseases (All Cure and the single cures) and gives the stats as a buff of id -item_id for the spec's time, which the client lists with the item's icon. CANCEL_ITEM_EFFECT (0x49) ends it, and HeavenClient now sends it when an item buff's icon is right-clicked, as v83 does (FUN_0045b9fc / FUN_00a096af).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The stack #497–#514 was merged layer by layer into each PR's parent branch, not into master: only #496 reached master. The repo doesn't delete head branches on merge, so GitHub never retargeted the upper PRs to master. So master still lacks everything from #497 to #514.
This branch brings those commits to master unchanged, rebased onto current master. Its tree is identical to the merged stack's tip (
v83/consumables, 6c8b9d9);git diff 6c8b9d95 v83/catch-upis empty.What it brings
Each of these was reviewed in its own PR:
Verification
cargo fmt --checkandcargo check --workspace --testspass on this branch.Merging the stack above
PRs stacked on this one target their parent branch. Head branches aren't deleted on merge here, so GitHub won't retarget them. Please merge bottom-up, and change each PR's base to
masterbefore merging it.