Skip to content

Conversation

@LordMidas
Copy link
Member

@LordMidas LordMidas commented Dec 27, 2022

This allows creating objects with modified fields in-line. Use cases:

  • Modifying values
  • Initializing values

Modifying values

// vanilla style:
function onEquip()
{
	this.weapon.onEquip();
	local cleave = this.new("scripts/skills/actives/cleave");
	cleave.m.Icon = "skills/active_182.png";
	cleave.m.IconDisabled = "skills/active_182_sw.png";
	cleave.m.Overlay = "active_182";
	cleave.m.FatigueCost = 15;
	this.addSkill(cleave);
	this.addSkill(this.new("scripts/skills/actives/decapitate"));
	local skillToAdd = this.new("scripts/skills/actives/split_shield");
	skillToAdd.setFatigueCost(skillToAdd.getFatigueCostRaw() + 5);
	this.addSkill(skillToAdd);
}

// new style:
function onEquip()
{
	this.weapon.onEquip();
	this.addSkill(::MSU.new("scripts/skills/actives/cleave", {
		Icon = "skills/active_182.png";
		IconDisabled = "skills/active_182_sw.png";
		Overlay = "active_182";
		FatigueCost = 15
	}));

	this.addSkill(::new("scripts/skills/actives/decapitate"));
	this.addSkill(::MSU.new("scripts/skills/actives/split_shield"), null, @(o) o.setFatigueCost(o.getFatigueCostRaw() + 5));
}

This is an extreme example. While hooking weapons for Reforged, I very frequently ran into the situation where I wanted to change one or two values of a skill. In that case this is very convenient:

// old method
function onEquip()
{
	this.weapon.onEquip();
	local cleave = this.new("scripts/skills/actives/cleave");
	cleave.m.FatigueCost = 15;
	this.addSkill(cleave);

	local decapitate = this.new("scripts/skills/actives/decapitate");
	decapitate.m.FatigueCost = 27;
	this.addSkill(decapitate);

	local skillToAdd = this.new("scripts/skills/actives/split_shield");
	skillToAdd.setFatigueCost(skillToAdd.getFatigueCostRaw() + 5);
	this.addSkill(skillToAdd);
}

// vs new method:
function onEquip()
{
	this.weapon.onEquip();
	this.addSkill(::MSU.new("scripts/skills/actives/cleave", {FatigueCost = 15}));
	this.addSkill(::MSU.new("scripts/skills/actives/decapitate", {FatigueCost = 27}));
	this.addSkill(::MSU.new("scripts/skills/actives/split_shield"), null, @(o) o.setFatigueCost(o.getFatigueCostRaw() + 5));
}

Initializing values
As create() does not take arguments, I've often worked around it by creating an init function in my classes to set initialization values. This new method provides an alternative way to achieve that, reducing the need for an extra function:

// my current method:
local perkTree = ::new(::DPF.Class.PerkTree).init(value1, value2, value3);

// new method:
local perkTree = ::MSU.new(::DPF.Class.PerkTree, {key1 = value1, key2 = value2, key3 = value3});

Thoughts on _fields parameter
EDIT: On second thought, it is probably ok to remove this parameter and only keep _script and _function.

In theory the _fields parameter is unnecessary as _function can accomplish changing fields too. But since setting fields is the most common thing to change during modifying and/or initializing an object, it is much more convenient to just pass a table instead of writing a function every time. For example:

// Compare
::MSU.new("scripts/skills/actives/cleave", function(o) {
	o.m.FatigueCost = 15;
	o.m.ActionPointCost = 2;
	o.m.Icon = "xyz"
});

// vs

::MSU.new("scripts/skills/actives/cleave", {FatigueCost = 15, ActionPointCost = 2, Icon = "xyz"});

Therefore, I think it makes sense to keep both parameters.

@LordMidas LordMidas added this to the 1.3.0 milestone Dec 27, 2022
@Enduriel
Copy link
Member

I don't like the function part of this, I understand why it's convenient but imo it's not as 'proper' to shorthand that part of this. I'm fine with modifying fields in a constructor style function though I guess.

@LordMidas LordMidas force-pushed the development branch 2 times, most recently from b825c3c to a75ea82 Compare March 2, 2023 13:58
return typeof _object == "table" && "_release_hook_DO_NOT_delete_it_" in _object;
}

::MSU.new <- function( _script, _function = null )
Copy link
Member

Choose a reason for hiding this comment

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

why can function be null? this seems antithetical to the purpose of this PR

Copy link
Member Author

@LordMidas LordMidas Dec 9, 2023

Choose a reason for hiding this comment

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

My thought to allow it to be null was so that ::MSU.new can be used in place of vanilla ::new without causing any issues. E.g. like we do with ::MSU.isKindOf as a replacement for vanilla ::isKindOf.

Copy link
Member

Choose a reason for hiding this comment

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

I disagree, I don't think that's necessary and I don't think we should handle that, if someone really needs a null equivalent for some unknown reason they can pass an empty function

Copy link
Member Author

@LordMidas LordMidas Dec 12, 2023

Choose a reason for hiding this comment

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

The point is that if someone went ahead and did find&replace on this.isKindOf in vanilla codebase to ::MSU.isKindOf and similarly on x == y to ::MSU.isEqual(x, y) it will not break the code. But if someone replaced this.new with ::MSU.new it will break if _function is required parameter. Basically just like our new global functions make it so that you never have to use vanilla this.isKindOf and similarly never have to do == when comparing instances of BB classes, we now say that you can safely always use ::MSU.new instead of ::new. That's the only reason - so if you think that reason is not valid enough then I can remove the optional param and make it required.

@Enduriel Enduriel added the postponed Something to work on eventually, but not now label Feb 17, 2024
@LordMidas LordMidas modified the milestones: 1.3.0, 1.4.0 Apr 13, 2024
@LordMidas LordMidas force-pushed the development branch 2 times, most recently from 6677ac8 to ae825b7 Compare June 17, 2025 23:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

postponed Something to work on eventually, but not now

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants