Replace the hand-copied character slot number with a real character handle
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 12/100
Research direction
Start with char_control_array, register_npc_char, extract_char and free_char in src/handler.cpp, then target_data and its ch_num field in structs.h. Read how set_character() from #369 is used before adding a handle type with a non-reused identity. Done means target_data and the follower, memory, mount and reply links use the handle, and freeing a character clears a slot only for its owner. The issue asks for design decisions first, so check with the maintainer before coding.
Written by the indexing model from the issue text.
Description
Why engineers need this
The game decides whether a character it remembered is still around by a slot number that every caller copies by hand. The design has let two bugs sit unnoticed for years, and it will produce more.
How it works today:
char_control_array(src/handler.cpp) holds one bit per slot, 0 to 63999.register_npc_char/register_pc_chargive a character a slot (abs_number);extract_char/free_charclear it.- Code that keeps a character for later stores the pointer and the slot number side by side (
target_data::ptr.chandtarget_data::ch_num,fol_number,enemy_number,mount_number, ...), and callschar_exists(number)before using the pointer.
What is wrong with it:
- "Not set" was the same value as a real slot. A forgotten number was 0, and slot 0 is the first mob loaded at boot. #369 changes "no slot" to -1; that makes a forgotten number harmless to others but does not stop it being forgotten.
- Pointer and slot are separate fields that must be set together, and nothing enforces it.
damage(),hit(),damage_stat()anddo_mental()never set the slot, so every hit in the game asked "does slot 0 exist?" instead of "does this victim exist?". #369 addstarget_data::set_character()and uses it where the slot was missing; the other ~25 places that build a character target still set the two fields by hand. ch_numis shared with unrelated data. Depending on the target type it carries a direction, a spell number, a coin amount or a door sentinel, so nothing can tell a forgotten slot from a legitimate value.- Slots are reused. The allocator wraps at 64000, so a number remembered long enough can point at a different character that now has that slot. The check then passes for the wrong character. (Not seen in practice; it follows from the allocator in
register_npc_char.) - Cleanup trusted the number.
stat fileandset filebuild a character that never gets a slot; freeing it cleared slot 0. On builds before #369 that switches off every mob's damage program, and so every shopkeeper's protection, until reboot.
What is wanted
One character handle that cannot be half-filled or point at the wrong character:
- a single type holding the pointer and an identity that is never reused within a boot (a counter, or slot + generation);
- one way to make it from a character, one way to ask "is it still alive, and still the same character";
- used by
target_data(in its own field, not shared with directions and amounts) and by the follower, memory, mount and reply links; free_char/extract_charclearing a slot only for the character that owns it.
Scope and risk
Game-wide: structs.h, the command parser (interpre.cpp), handler.cpp, mobact.cpp, spec_pro.cpp, script.cpp, ranger.cpp, mudlle (SPECIAL_LIST_REFS). It can be done in steps: the handle type and its use in target_data first, the other links after. None of these structs are written to disk.
Raised while answering the review of #369, which carries the two small fixes (-1 for "no slot", set_character()).
- Dominant language
- C++
- Stars
- 3
- Forks
- 4
- Avg merge
- 18h 36m
- Merged PRs (30d)
- 87
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from returnoftheshadow/RotS_Live
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
returnoftheshadow/RotS_Live#521 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
returnoftheshadow/RotS_Live#485 ·
Maintainers usually reply within 1 day
-
Remove dead object refresh code (check_inventory_proto and friends)Possibly taken @drelidan7 claimed this 1 day ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
returnoftheshadow/RotS_Live#414 ·
Maintainers usually reply within 1 day
-
purge <player> idle-saves the immortal instead of the playerPossibly taken @bskalpavrukshab25-sketch claimed this 11 days ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 92/100
returnoftheshadow/RotS_Live#411 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
returnoftheshadow/RotS_Live#410 · 2 comments ·
Maintainers usually reply within 1 day
All issues in returnoftheshadow/RotS_Live
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
enhancement Ready for final check
Difficulty 2/5 1-3 hours Newbie friendliness 79/100
mpogue2/SquareDesk#1818 · 1 comment ·
-
launch-client --save-creds creates creds/<account>/ with mode 755, not 700Possibly taken @metis-sprock claimed this today. Openbacklog bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
EchoTools/nevr-runtime#1471 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 66/100
Maintainers usually reply within 2 days
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
iamankushpandit/Gume#231 ·
Maintainers usually reply within 1 day