Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ship Equipment Overhaul - EquipSet v2 #5734

Draft
wants to merge 55 commits into
base: master
Choose a base branch
from

Conversation

Web-eWorks
Copy link
Member

Creating as WIP PR for visibility and collaboration purposes. No guarantees this runs or is fully functional at this juncture, though I've tried to ensure I have a working test case during most of development.

This branch is the culmination of several years of sporadic design discussion about Pioneer's current equipment system and the problems it presents for certain important gameplay systems we'd like to enable.

We've been laying the groundwork for a replacement system on IRC and in the dev docs for quite some time, and enough ducks lined up in a row to be able to put fingers to keyboard and start writing the replacement for the existing system.

The Problems

  1. It's very difficult to support more than one weapon per ship, since there's no concept of where an equipment slot is, or which individual slot within a type (e.g. laser_front) an item is installed in
  2. Equipment items aren't unique instances - there's no way to have two shield modules installed but only have one of them turned on, damaged, etc. without writing a separate system to handle each equipment state
  3. Since equipment items are "all the same", you can't buy a repaired / slightly damaged equipment module off the secondhand market for cheap. You're buying the exact same module you buy from the ship dealer, down to the table identity. It also makes things more complicated to handle storing purchased equipment items at a station when unequipped but not sold (when we get to that point).

The Solution

We've settled on a logical extension to the slot-based design of the prior equipment system, but allowed players to interact with the individual slots on their ship as first class features rather than hidden constraints.

Slots have type and size constraints (potentially extended to resource availability, e.g. power/ammo in the future) which limit the types of equipment that can be installed and allow some additional stratification of ship roles; an AC33 is probably not going to be happy with a shield generator designed for a Pumpkinseed, and a 20MW pulsecannon cannot physically be connected to a Coronatrix no matter how much you shuffle around the insides.

To complement this system, all equipment items that are installed on ships are now thin instances of equipment item "prototypes". This allows for very easy future support for individual equipment item state, like damage/wear, power on/off, and "tuning" equipment items to be better in specific capabilities (at the expense of others).

Status

This branch is by no means feature complete. As of time of writing, the diff is 4k lines added, 1.8k lines removed, and quite a bit more is expected. I'm creating this PR now to collaborate with other contributors and to seek some feedback from interested parties on anything I might be forgetting.

The overall effort to move to the new equipment system is broken down into three stages:

  1. (This PR) Convert existing equipment items and code to use the new system, and provide very basic slot configurations for all existing ships to get everything playable. 80% of the effort.
  2. Replace legacy systems that were constrained by the old equipment semantics with replacements that enable additional gameplay (e.g. GunManager to support multiple weapons/weapon sets per ship). Add new equipment items to fill the gaps created by diversifying ships according to role and size.
  3. Create totally new features like storing purchased equipment items in cargo or on station, adding wear and power mechanics, and more.

Obviously, there's a lot of work to do, far more than I can accomplish on my own in a reasonable timeframe. I likely won't have as much time to dedicate to Pioneer moving forwards as I did this year, so I hope other developers can help share the load and move towards getting this feature complete.

TODOs:

  • Update new game window to support new equipment system
  • Convert individual module ship outfitting code to use the central ShipBuilder API
  • Handle multi-count equipment items
    • Support flexible-quantity / less-than-maximum slots, e.g. missile racks
    • Support fixed-quantity slots, e.g. engines/maneuvering thrusters
  • Extend the ShipBuilder API to support moddable loadouts or plans for ships (e.g. mods can tweak balance of provided plans)

CC @JonBooth78 @Gliese852 @nozmajner for feedback and collaboration.

Web-eWorks and others added 30 commits December 2, 2023 02:21
- All equipment items defined in Lua are treated as prototypes storing shared data.
- When adding an equipment item to a ship, create a new instance of it and add the instance to the EquipSet.
- This allows tracking per-instance details such as durability or storing specific equipment item instances at a station.
- Promote old equipment prototypes to use top-level mass/volume properties
- Allows forward-compatibility with mods and other values in ShipDef without requiring C++ changes to load and store the new values
- Add simple implementation of Self/Io-style prototypes
- Add table.merge to shallow copy values from one table to another
- Add table.append to concatenate an array to another
- Prototypes operate on a zero-copy delegation model where a new clone is an almost-empty instance

squash: table.merge, table.append
- Avoids runtime errors when interpolating non-string values
- class.New propagates all its arguments to the base class New function
- class.Constructor forwards to the parent constructor if it exists
- Split existing items into various internal slots by size
- Add select new variants of existing items for testing slot sizes
- Ship.cpp no longer holds a reference to an EquipSet, uses LuaComponent system instead
- Simplifies API of querying screenspace position of previously submitted elements, e.g. ui.dummy
- Add type information for Color objects
- Define the pigui 'ui' interface as a class so all assigned functions are available for autocomplete
- Fix incorrect parameters in LuaRand type information
- Unify background drawing across callsites
- More efficient and resilient draw cursor manipulation
- Better handling of whole-card vs detail tooltips
- Reserve space for "highlight bar" drawn in left margin
It's the UI's responsibility to render item stat comparisons; the stats module should just be concerned with formatting raw values into something that can be consumed and compared
- Function prototypes for installing/removing EquipType items
- Separate cabins into their own EquipType subclass
- Use the LuaSerializer persist functionality instead of serializing equipment directly
- Was originally "removed" in 2013, but some references crept back in.
- Prefer using properties defined directly on a Ship object instead
- Amend documentation for C++ set ship properties
- Temporary re-definition of freeCapacity before deprecation
- ShipType capacity is now a floating-point number defining equipment volume
- Added a new cargo value as a migration path for slots.cargo
- Add Lua type definition file for LuaShipDef
Previously, an error in an individual tab's refresh() function would go uncaught and prevent the entire TabView from functioning until the game was restarted.
- Replace the shared capacity metric with separate cargo and equipment volumes.
- If needed later, cargo and equipment space could potentially be "converted" into the other.
Commodity market reuses almost no code from the equipment market, so it makes little sense to depend on it.
* Improve error messaging when a class is attemted to be serialized but isn't registered

Also improve the comment for register class.

* clang format
- Inspired by Eris/Pluto's concept of "persistent objects" which have all references transparently swapped for the runtime-current instance of that value
- Since a common pattern in Lua is to use the version of the value from the savefile if it's no longer defined in code, this implementation requires that persistent objects are also serializable
- The counterpart to a ShipDef, a ShipConfig is concerned with expressing the slot arrangement and equipment capacity of a specific version of a ship's hull
- The default configuration for a ship is loaded from the ship.json file, but additional ship configurations can be supported with minimal effort
- Each ShipConfig is comprised of a set of slots with unique identifiers
- The default set of slots can be modified or overridden entirely from within the ship.json file by specifying key-value pairs in the equipment_slots object
- Responsible for querying, embarking, and disembarking passenger objects from equipped cabins
- Individual cabins now track which Character objects are embarked inside of them and change icon based on their state
- Replaces existing model where empty cabins and occupied cabins are separate equipment added and removed at runtime
- Helper utilities allowing ship loadouts and equipment selection to be written in a generic fashion
- Ship loadouts are written as productions of individual rules applied in order which add equipment items to the prospective ship
- A finished ship plan is then applied to a newly-spawned ship and equipment items created and installed as appropriate
- Replace most GetEquip() calls with querying ship capabilities instead
- Use Ship:GetInstalledHyperdrive() in all cases instead of manually querying for hyperdrive equipment
- Rework missile display + launching
- Display new equipVolume stat instead of ship mass in StationView
- Update mission modules to use Ship:GetInstalledHyperdrive() and Passengers.Embark/Disembark/Count rather than querying the equipment system directly
- Additional work required to convert modules to new ship outfitting code
- Module implements an Elm-style model-view-update pattern which allows maintaining a clear separation between widget state (and state mutations) and display code.
- It provides an easy way to move certain high-runtime-cost logic to only be run when needed, without requiring a significant amount of boilerplate code.
- New equipment outfitter widget provides much richer display of equipment items, confirmation before purchase, and comparison between installed and purchaseable equipment
- Can be made forward-compatible with stored equipment items in ship cargo or station storage
@JonBooth78
Copy link
Contributor

Hey @Web-eWorks , this looks like a big step in the right direction.

Your ShipBuilder API is similar to what I started doing on my pirates branch but I think I called it ShipOutfitter. However, with the equipment changes it looks more straightforward.

As such I've been thinking in that area for a while so I'm very happy to pick up the TODO's around using this throughout the missions and then also extending it, if that works for you.

If you're happy with that, can I send PR's to your working branch?

@Web-eWorks
Copy link
Member Author

Web-eWorks commented Feb 3, 2024

As such I've been thinking in that area for a while so I'm very happy to pick up the TODO's around using this throughout the missions and then also extending it, if that works for you.

If you're happy with that, can I send PR's to your working branch?

That would be absolutely excellent, thank you! I'll double-check the settings on my fork but you should be able to open PRs there. I'll try to squash together the fixup commits sometime tonight and see if I can rebase this on the current release.

EDIT: you should be able to open PRs to my fork from this page, just select the correct branch on your end. Web-eWorks/pioneer@equip-v2...JonBooth78:pioneer:master

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

None yet

2 participants