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

Refactor: Detach outfit class from weapon #9859

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

RisingLeaf
Copy link
Contributor

Refactor

This PR addresses the strange stuff described in issue #9852

Summary

Removes inheritance of the outfit class to the weapon class and instead makes weapon a member of outfit.
Also creates a new member in hardpoint pointing to the weapon and a getter for that variable.

I am very open to suggestions, this is a first minimum viable product

Usage examples

makes some changes a lot easier

Testing Done

Flew around installed and uninstalled weapons, no errors encountered

Performance Impact

Nothing I noticed

source/Hardpoint.h Outdated Show resolved Hide resolved
source/Outfit.cpp Outdated Show resolved Hide resolved
source/Ship.cpp Outdated Show resolved Hide resolved
source/PrintData.cpp Outdated Show resolved Hide resolved
@bene-dictator bene-dictator added the refactor A request to refactor the engine code label Feb 24, 2024
@Amazinite Amazinite linked an issue Feb 25, 2024 that may be closed by this pull request
Copy link
Contributor

@OcelotWalrus OcelotWalrus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for me.

source/Armament.cpp Outdated Show resolved Hide resolved
Copy link
Collaborator

@tehhowch tehhowch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obligatory context note: I didn't build this, test it, or review the tens of thousands of discussion posts or PRs that have been made since I last had time for this repo.

source/Outfit.h Outdated Show resolved Hide resolved
Comment on lines 463 to 465
attributeValues.emplace_back(outfit.Ammo()->DisplayName());
attributesHeight += 20;
if(outfit.AmmoUsage() != 1)
if(weapon.AmmoUsage() != 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having multiple places that need to be checked for the ammo bits feels off.

Consider moving all ammo bits into Outfit, or vice versa. Another option is to introduce a class like AmmoConsumption, which would handle mapping a Weapon / Outfit definition to the ammo it requires (e.g. if an outfit had multiple weapons, or different firing modes that were internally represented as multiple Weapons belonging to a single Outfit).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Introducing something like AmmoConsumption feels a bit too much for this PR, so I moved the ammo pair into weapon completely. But still left an accessor function in outfit to avoid making the code confusing when it comes to an outfit storing ammo or a weapon consuming ammo

if(it.first->IsWeapon() && it.first->Reload())
{
const Weapon &weapon = it.first->GetWeapon();
if(it.first->IsWeapon() && weapon.Reload())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if(it.first->IsWeapon() && weapon.Reload())
if(weapon.IsWeapon() && weapon.Reload())

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weapon shouldn't have an IsWeapon() function anymore. When I said that IsWeapon should be a function of Outfit, I meant to move it from Weapon to Outfit, not have Outfit call Weapon's function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refer to #9859 (comment)

So I thought for consistency I should always use outfit.isweapon
but ig in this situation what you recommend looks better

@@ -101,7 +101,7 @@ void Weapon::LoadWeapon(const DataNode &node)
else if(key == "submunition")
{
submunitions.emplace_back(
GameData::Outfits().Get(child.Token(1)),
&GameData::Outfits().Get(child.Token(1))->GetWeapon(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is not desirable. Previously, we were storing a pointer to the key of a collection, and the choice of collection meant we had particular guarantees about that pointer (always stable, etc) regardless of the collection size. Now we're storing a pointer to an implementation detail (some field of said managed object). Probably it's fine. But it's definitely something to be aware of.

explicit Submunition(const Weapon *weapon, std::size_t count) noexcept
: weapon(weapon), count(count) {};
const Weapon *weapon = nullptr;

I recall there were previous thoughts of registering / standardizing Weapon (i.e. GameData::Weapons()), but I don't have specifics on why we deferred. Likely it was related to the ability of Person ship variants to have their own specialized weapon definitions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to store a pointer to the outfit?

source/Weapon.h Outdated Show resolved Hide resolved
source/Weapon.h Outdated Show resolved Hide resolved
@@ -202,8 +204,9 @@ class Weapon {
// Return the ranges at which the weapon's damage dropoff begins and ends.
const std::pair<double, double> &DropoffRanges() const;

private:
friend class Outfit;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to make this a friend?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for setturretturn and ammo

@@ -57,6 +57,8 @@ class Weapon {


public:
Weapon() = default;

// Load from a "weapon" node, either in an outfit, a ship (explosion), or a hazard.
void LoadWeapon(const DataNode &node);
bool IsWeapon() const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to have Weapon::IsWeapon? Presumably we only really need Outfit::IsWeapon.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need it for hazards too

source/Outfit.cpp Outdated Show resolved Hide resolved
@@ -101,6 +103,7 @@ class Hardpoint {
private:
// The weapon installed in this hardpoint.
const Outfit *outfit = nullptr;
const Weapon *weapon = nullptr;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why store the weapon? Any reason why we can't use outfit->GetWeapon() where we need to access it?

I didn't check, but maybe GetOutfit() is unused and not needed in which case you remove outfit instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the code just looks a lot cleaner with an extra variable for weapon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactor A request to refactor the engine code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Outfit/Weapon logic is borked
6 participants