Port retail's radius-aware placement ring so a relogging player is seated beside creatures occupying the saved location, and register the local body in the shared resolved-shadow pipeline. Route new forward movement and jump through AbortAutomaticAttack so repeat combat cancels immediately on movement. Co-Authored-By: Codex <codex@openai.com>
3.9 KiB
Login placement and repeat-attack cancellation — retail pseudocode
Sources
CTransition::find_placement_pos@0x0050BA50CTransition::find_placement_position@0x0050C170CObjCell::find_obj_collisions@0x0052B750CPhysicsObj::add_shadows_to_cells@0x00514AE0CPhysicsObj::enter_world@0x00516170ClientCombatSystem::AbortAutomaticAttack@0x0056AE90ClientCombatSystem::CommenceJump@0x0056AF90ACCmdInterp::HandleNewForwardMovement@0x0058B1F0- Named pseudo-C:
docs/research/named-retail/acclient_2013_pseudo_c.txt - Interpretation cross-check: ACE
Transition.cs,CommandInterpreter.cs, andACCmdInterp.cson theACEmulator/ACEmasterbranch.
Enter-world placement
Retail enter_world(position) stores the server position and calls
enter_world(true). That constructs SetPosition flags 0x11, so placement
may slide away from an obstruction.
find_placement_position():
check = current
insert_type = INITIAL_PLACEMENT
test environment/cells at check
(CObjCell skips shadow-object collisions for INITIAL_PLACEMENT)
validate initial placement
insert_type = PLACEMENT
if !find_placement_pos(): fail
optionally step down to a walkable surface
validate final placement
find_placement_pos is the object-aware nearest-clear-point search:
find_placement_pos():
check = current
clear sliding/contact state
if placement_test(check) succeeds:
accept check and return true
if placement sliding is disabled:
return false
search_distance = 4 metres
search_radius = 4 metres
radius = mover foot-sphere radius
if radius < 0.125 metres:
fake_sphere = true
search_radius = 2 metres
else if radius < 0.48 metres:
radius = 0.48 metres
exact_step_count = 4 / radius
if fake_sphere: exact_step_count *= 0.5
if exact_step_count <= 1: return false
step_count = ceil(exact_step_count)
distance_step = search_radius / step_count
radians_step = PI * distance_step / radius
total_distance = 0
total_radians = 0
for each radial step:
total_distance += distance_step
total_radians += radians_step
compass_samples = ceil(total_radians) * 2
heading_step_degrees = 360 / compass_samples
for sample = 0 .. compass_samples-1:
check = current
heading = heading_step_degrees * sample
offset = forward_vector(heading) * total_distance
offset = adjust_offset(offset)
if length(offset) < epsilon: continue
check += offset
clear sliding/contact state
if placement_test(check) succeeds:
accept check and return true
return false
The local player must also own a normal shadow entry. Retail registers every
placed CPhysicsObj; collision queries exclude only the moving object's own
pointer. Therefore remote monsters can collide/de-overlap against the local
player, while the player's placement search skips its own shadow by entity id.
Movement cancels repeat attack
ACCmdInterp.HandleNewForwardMovement():
if combat_system exists:
combat_system.AbortAutomaticAttack()
base.HandleNewForwardMovement() // also stops auto-run
ClientCombatSystem.AbortAutomaticAttack():
if server_response_pending
or attack_request_in_progress
or attack_in_progress
or repeat_attacking:
send Event_CancelAttack
repeat_attacking = false
if combat power build is active:
HidePowerBar()
CommandInterpreter::AddCommand calls HandleNewForwardMovement for the
forward-substate command list, which includes forward/backward/autorun rather
than the independent turn and sidestep lists. Jump has the same cancellation
at ClientCombatSystem::CommenceJump before its jump power bar begins.