Local coop#8354
Conversation
65ba33b to
088967d
Compare
|
Turning into draft until I can rebase it. |
|
I think some of the files in this PR, such as control.cpp, had their line endings changed from CRLF to LF which makes the diff huge |
I guess this changes the controller scheme a bit because I thought we already had spell assignment with SELECT + A/B/X/Y on the speedbook? |
Hmmm, yeah, I changed the controller scheme so the actions have less steps so less interactions to handle and the game is more dynamic (in my biased opinion). In this PR, select opens the character panel and start opens the inventory. I can make it more similar to the current controller scheme. |
Let's gather some more opinions, I haven't even tried this branch yet, maybe it is a lot better. |
721dd2d to
3051308
Compare
|
This PR is not perfect:
But I think it's in a good shape to start discussions. |
1fdc1b6 to
15740b3
Compare
4820f72 to
8105feb
Compare
|
Ready for review |
|
Incredible work! My only complaint/issue I've found is when both players are moving in the same direction at the same time, the screen gets a bit jittery? This is at 480p, windowed mode, on Windows 11 devilutionx_xlVbKgCLWJ.mp4 |
Whoa! Thank you do much for testing. I am glad you only had ONE complain, that shows me I could cover a lot of edge-cases. I tried to fix the camera, that was the best I could get last week. I can try another approach, I will let you know when I have something better. Btw, if you want to try 3 or 4 players I highly recommend changing the screen resolution to 720p. I couldn't try 4 players yet because one of my gamepads is not working, I have to find the other one. |
|
Mate this is actually extremely cool! Hope it gets reviewed soon as it looks like a lot of work to then get stale. |
|
@strich Thanks! You just reminded me that I need to work on the conflicts. Yeah, I really enjoyed working on this feature. I wanted to do that for a loooong time. |
f56a296 to
066c205
Compare
|
Oh damn! I broke the gamepad logic during the rebase. 😅 |
24be989 to
6bf198a
Compare
bef20a7 to
c1fd3f0
Compare
Introduces the local co-op subsystem as a self-contained module under Source/controls/local_coop/: - local_coop_constants.hpp — layout, camera, and input constants - local_coop_assets.hpp/.cpp — asset loading/unloading for coop HUD - local_coop_button_mapper.hpp/.cpp — per-player gamepad button routing - local_coop.hpp/.cpp — core state machine: player join/leave, camera, panel layout, input dispatch, hero selection, and visual store wiring Source/CMakeLists.txt is updated to include the new source files in the build.
- dvlnet/loopback: message queue now stores sender ID alongside the message payload so local co-op players can exchange messages through the loopback provider without being collapsed onto player 0 - multi.cpp / init.cpp: call LoadAvailableHeroesForAllLocalCoopPlayers() after the save file is read so co-op slots know which heroes are eligible - options.cpp/.h: expose IsLocalCoopEnabled() option
- player.cpp/.h: track whether a Player slot belongs to a local co-op player; add helpers queried by other subsystems - pfile.cpp/.h: enumerate hero save files for co-op slot selection; save/restore all local co-op player heroes on game exit - loadsave.cpp: load and save extra player slots during level transitions - portal.cpp: create portals for local co-op players on level change - lighting.cpp/.h: expose per-player light source so co-op players each carry their own light radius independently of player 1 - msg.cpp: route network messages to the correct local co-op player slot
- controller.cpp/controller_motion.cpp: detect hot-plug of additional gamepads and assign them to co-op player slots - devices/game_controller.h, joystick.cpp/.h: expose device index so each physical controller maps to a specific co-op player - game_controls.cpp: dispatch button events to the owning co-op player rather than always targeting player 1 - modifier_hints.cpp/.h: show per-player modifier hint overlays - plrctrls.cpp/.h: route padmenu navigation, attack, skill, belt, and inventory actions to the correct local co-op player; extract DpadGamepadButtonToAxisDirection helper; use skillSlotSize constant - touch/event_handlers.cpp: guard touch events against co-op mode
- scrollrt.cpp: split the viewport so each local co-op player sees their own screen region; expand the walking tile buffer when any co-op player is in motion; apply per-player camera offset; render item/monster/object highlights for all co-op players; skip lighting attenuation for local players who carry their own light source - light_render.cpp: apply lighting correctly per player when multiple local players are present - text_render.cpp: clip text to the active player's panel region - automap.cpp: center the automap on the correct player's position in split-screen mode
- control.hpp: add ShouldHideMainPanelForLocalCoop() and panel-ownership helpers so each co-op player's HUD occupies its own screen quadrant - control_infobox.cpp: render the info box inside the owning player's panel region - control_panel.cpp: lay out life/mana globes, belt, and skill slots per player; draw experience bar; render attribute-available icon - stores.cpp: gate store access to the interacting player; wire InitVisualStore / CloseVisualStore / FreeVisualStoreGFX into the town-load and store-close paths via CloseLocalCoopStore - spells.h: expose speed-spell slot count constant (skillSlotSize) - cursor.cpp: clamp cursor to the active player's panel region in co-op - diablo.cpp: call CloseVisualStore from QuestLogKeyPressed and DisplaySpellsKeyPressed; initialise and free the visual store on town load/unload; route key events to the correct co-op player
- inv.cpp: route inventory open/close, item pick-up, and equipment actions to the player whose panel was interacted with - items.cpp/.h: allow any local co-op player to pick up and use items; guard item-use actions by player proximity - levels/trigs.cpp: trigger level-change portals for all active local co-op players when any player steps on a trigger - missiles.cpp: spawn healing/mana missiles for all local co-op players when appropriate (e.g. town potions) - objects.cpp: allow co-op players to interact with objects inside their proximity range - qol/autopickup.cpp: run auto-pickup logic for each local co-op player - towners.cpp: allow co-op players to talk to town NPCs - lua/lua_event.hpp: declare Lua event hooks needed by the co-op module - utils/hp_mana_units.hpp: extend HP/mana unit helpers used by co-op HUD
- reencode_dun_cels.cpp: initialise frameSize to 0 to silence -Wmaybe-uninitialized on paths where GetReencodedSize returns early - spell_list.cpp: initialise spells to 0 to silence -Wmaybe-uninitialized in IsValidSpeedSpell - platform/ctr/keyboard.cpp: change eventCount to size_t and introduce VkbdEventQueueCapacity constant to silence -Wsign-compare against sizeof(events)
This is my proposal for local coop. I wanted this feature since I played Diablo for the first time via modem and the game kept disconnecting when someone called.
I am creating this PR so the implementation can be discussed and people can try it. I am really open to suggestions, opinions and even abandon this PR if it's not the direction the community wants to follow. Most of the code is AI generated
so I don't want to overwhelm anyone asking for code review yet since I am planning to refactor this entire branch.I tried to make it completely optional and even if enabled should not be intrusive in any way. The UI is close as possible to the original design, nothing fancy, nothing modern.
Limitations
No color distinctions (waiting for: [QOL/UX] Multiplayer Player Colors #8317)How to activate it
First of all, you should enable the setting "Enable local co-op".
Once in a multiplayer game, the main UI panel is hidden and the local co-op panel is displayed, if the game detects more than 1 gamepad, other players will display the character selection panel. The list of characters is based on the multiplayer saved characters.
Gameplay
Panels
The character panel and inventory are fully functional. I introduced the concept of ownership, whoever opens the panel has control over the panel and can do the same actions as a single player.
NPCs Interactions
Work similarly to other panels (whoever opens gets ownership).
Spell Assignment
Alternatively to the default way to assign spells, it's also possible to assign spells to skill slots, so you can have up to 4 spells assigned to your character.
To assign a spell, you have to long press one of the buttons A,B,X or Y. It will open a speedbook and once you press one of those buttons again, the spell/skill is assigned.
Spells can be casted using the assigned button.
Belt
I decided to keep the full belt for players. I wanted the local coop panel to be optional for a single player mode in the future.
To use a belt item you must press one of the shoulder buttons.
Left shoulder button highlights items 1 to 4, right shoulder button highlights items 5 to 8. Once the item is highlighted if you press A,B,X,Y the item will be consumed.
local_coop_town_trim.mp4
local_coop_dungeon_trim.mp4
Closes #1237