Skip to content

feat(fp): punch, shove and emote on foot; people react and the city remembers - #18

Merged
KunalSiyag merged 1 commit into
mainfrom
fp/body-actions
Oct 21, 2026
Merged

KunalSiyag merged 1 commit into
mainfrom
fp/body-actions

Conversation

@KunalSiyag

Copy link
Copy Markdown
Owner

Summary

Addresses "LMB/RMB do nothing" and "hitting people has no consequences". The hero can now shove, punch and emote on foot, the people hit react, and the city remembers it: moods and memories, police or an ambulance, lines in the chat, and sound. The car the player drives now strikes pedestrians too.

What you can do

  • Left click / right trigger: shove whoever stands in front of you.
  • Hold right click / left trigger: guard (fists up, body squared to the camera, camera pulled in). Left click then throws a jab and a cross in turn.
  • 1-5: wave, nod, shake your head, shout, dance. People nearby answer.
  • Nothing swings in a car, in photo mode or the overview, in a conversation, under a modal or with the phone open. The click that captures the mouse throws nothing.

What happens to the people you hit

  • A light blow: they reel (hit_chest / hit_head) and slide back.
  • A hard blow, the third punch in a row, or a fast car: they go down (knockback), lie a while, get up (get_up), then shout at you, run off or walk back. People nearby who saw it run off or shout too.
  • The resident who was hit gets a memory and a mood drop (a shove least, a car most, more when knocked down). People who saw it get a memory and a small drop.
  • An assault (a knock-down punch, or 3 punches within 60 s) calls the police. Someone a car knocks down gets an ambulance. The crew drives out from the nearest station and stays a while. Each kind is called at most once per 90 s.
  • Chat: the victim and a witness post lines (one scene per 8 s, though a harder blow still posts), and a called crew posts a City Alert card.
  • Audio: a thump for each blow (a car's is lower and louder), a whoosh for each swing, and the fall.

Implementation

  • scripts/fp/actions/actions_feature.gd (new integration feature actions, flag on by default): swings, combo, guard, emotes. Strike and emote presses are read in _unhandled_input (ARCHITECTURE rule 7). A trigger counts once per pull because every motion event past the dead zone reads as pressed. The guard is a held action.
  • Traffic: reactions.gd (reel, fall, get up, run off or walk back, witnesses, emote answers) and incidents.gd (memories, mood, crews). New APIs: walkers_near, hit_walker, answer_emote, pose_walker and call_crew. fleets.gd crews can answer a call and stay at the scene. Walkers get a react state, and people.gd / people_kit.gd play the reaction clips.
  • car_body.gd strikes people it closes on faster than 0.5 m/s, as hard as the closing speed over 12 m/s, and each person at most once per 1.5 s. The car loses little speed. Drive _report leaves people to person_hit.
  • Player: hero_rig.gd gets an action layer (upper-body one-shots, the dance on the whole body, a guard pose) and strike_time, measured on the clip with the new hero_fk.gd (which now also does the foot-contact forward kinematics). FpPlayer.aim_yaw / kick_view and TpsRig.arm_scale are new.
  • GameBus: person_hit(at, cause, info) and hero_action(action, at).
  • Chat: chat/street_lines.gd, plus a "street" incident icon in chat_panel_row.gd.
  • Audio: punch_hit, punch_whoosh and body_fall, synthesized by tools/audio/synth_fp_sfx.py, and a hit emitter type.
  • Assets: 7 UAL clips (punch_jab, punch_cross, hit_head, hit_chest, dance, get_up, shout) via tools/characters/build_clips.py. ual.glb grows from 1.0 to 1.3 MB, and the new .res clips and WAVs total about 280 KB. No file is over 5 MB.
  • Inputs: act_strike, act_aim and emote_wave through emote_dance. Only this block of project.godot is in the commit.

Tests

  • fp_actions_test (new): the rig action layer and strike times; the shove; the jab-cross combo and its knock-down; misses (nobody ahead, behind, out of reach); emotes and their answers; the guard aim and camera; what blocks actions; presses (events, trigger edge, echo, modal, input off) and held guard; the car striking a pedestrian at 36 km/h but not at 1 km/h; teardown.
  • fp_chat_street_test (new): victim and witness lines, pacing, severity override, crew cards.
  • fp_audio_test: blow, swing and fall sounds.
  • fp_core_test: feature count 16. fp_overview_test: on-foot pad lists include the triggers.

Docs

README controls, pause-menu key legend, docs/fp/ARCHITECTURE.md (new "Integration: body actions" row, plus the A, C, E, HC, I and driving rows and the input list), docs/fp/S0-foundation.md §9 (the two signals), the HC clip table, the I-audio asset table, and regenerated API docs.

Validation

  • tools/gate.sh full: PASS (38 steps: parse, 35 unit tests, the orbit and first-person smokes).
  • tools/gate.sh render --only fp_photo: PASS. The tour adds actions_guard and actions_guard_hud: the hero with the guard up beside someone reeling from a blow.
  • pre-commit run --all-files and python tools/checks/run_all.py: PASS, no new findings.
  • Every new or touched script passes gdlint, gdformat and the complexity check with no new findings.

…emembers

The hero can now use its body in the street (new integration feature
"actions", flag on by default). Left click or the right trigger shoves
whoever stands in front. Holding right click or the left trigger raises
the guard: fists up, the body squared to where the camera looks and the
camera arm pulled in, and the strike button then throws a jab and a
cross in turn. A blow lands when the fist is furthest out on the
nearest person in reach ahead, harder when running, and jolts the view.
Keys 1-5 wave, nod, shake the head, shout and dance, and the people
around answer. Nothing swings in a car, in photo mode or the overview,
in a conversation, under a modal or with the phone open. The presses
come as events (a trigger counts once per pull) and the click that
captures the mouse throws nothing.

People hit react (traffic/reactions.gd): a light blow makes them reel
(hit_chest, hit_head) and slide back; a hard one, the third punch in a
row or a fast car knocks them down (knockback), and they lie a while,
get up (get_up), then shout, run off or walk back. People nearby who
saw it run off or shout too. traffic/incidents.gd gives the residents
involved a memory and a mood drop, calls the police after an assault
and an ambulance for someone a car knocks down; the crew drives out
from the nearest station (call_crew, fleets.gd) and stays a while.
TrafficFeature gains walkers_near, hit_walker, answer_emote and
pose_walker; GameBus gains person_hit and hero_action.

The player's car strikes the people it runs into (car_body.gd, as hard
as its closing speed), and they barely slow it. The chat hears of it
(chat/street_lines.gd): the one who was hit and a witness say so, and a
crew called to the scene posts a City Alert card. The audio feature
plays the blow, the whoosh of each swing and the fall, synthesized by
tools/audio/synth_fp_sfx.py (3 small WAVs).

hero_rig.gd gains an action layer (upper-body one-shots with quick
fades, the dance on the whole body, a guard pose) and strike_time,
measured on the clip by the new hero_fk.gd, which also takes over the
rig's foot-contact forward kinematics. FpPlayer gains aim_yaw and
kick_view, TpsRig arm_scale. Seven UAL clips join the libraries
(punch_jab, punch_cross, hit_head, hit_chest, dance, get_up, shout).

fp_actions_test (new) covers the rig's action layer, the shove, the
combo and its knock-down, misses, emotes and their answers, the guard,
what blocks the actions, presses and held input and the car striking
people; fp_chat_street_test (new) the street lines and their pacing;
fp_audio_test the blow, swing and fall sounds. The pause menu legend,
README, ARCHITECTURE, S0 section 9, the HC clip table and the API docs
describe it.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Automated review

No new findings on the 59 changed files (gdlint, complexity, TODO policy, dead code).

Run python3 tools/checks/run_all.py locally for the full set of checks.

@KunalSiyag
KunalSiyag merged commit 344f6f6 into main Oct 21, 2026
8 checks passed
@KunalSiyag
KunalSiyag deleted the fp/body-actions branch October 21, 2026 13:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant