Equipment Variables Proposal Discussion
Contents
Equipment Variables Proposal
We need a variable that is attached to the equipment itself, and not attached to the character. This would allow us to have Intelligent Magic Items, specific DCs, Item HP, Hardness Ratings, etc.
We have a few trackers open to cover this proposal - The following are applicable only to EQUIPMENT and EQUIPMENT MODIFICATIONS:
DEFINE:EQVAR|<Name of Variable>|<numerical value or formula> - I'd like to veto this one and change it to: EQVAR:<Name of Variable>|<numerical value or formula> DEFINES a New EQuipment VARiable on the Equipment or EQuipment Modification
My reasoning - It requires EQVAR to become magical in the DEFINE tag, and increases the work on the coder.
BONUS:EQVAR|<Name of Variable>|<numerical value or formula>
PREEQVARx:y,z x = LT, EQ, NEQ, LTEQ, GT, GTEQ (The normal PREVAR syntax) y = Variable Name z = Number, Variable Name, formula
THESE IF IMPLEMENTED would be GLOBAL:
I don't know if we want any outside influence being able to alter those numbers. Playing Devils advocate here:
BONUS:ITEM=<Name of Equipment>|<EQVAR NAME>|<Value> Allow an ability or other item to alter a specific equipment variable.
and for the other way:
GETEQVAR:<Name of Equipment>|<EQVARNAME> Allow an ability or other item to get the value of a specific equipment variable.
I'm sure those have holes in them, but those are my basic thoughts.
Discussion
> DEFINE:EQVAR|<Name of Variable>|<numerical value or formula> - I'd like to veto this one and change it to:
> EQVAR:<Name of Variable>|<numerical value or formula>
> DEFINES a New EQuipment VARiable on the Equipment or EQuipment Modification
> My reasoning - It requires EQVAR to become magical in the DEFINE tag, and increases the work on the coder.
I'm hesitant of making it different... "ok, you use DEFINE here but not here... yes I know it’s a type of VAR..." but if it truly would be that much simpler to code that way (Devon?) I won’t fight it.
> I don't know if we want any outside influence being able to
> alter those numbers. Playing Devils advocate here:
Yes. Many spells (and IIRC some feats even) enhance an items Hardness and other things, so I think allowing outside modification would be necessary.
> BONUS:ITEM=<Name of Equipment>|<EQVAR NAME>|<Value>
> Allow an ability or other item to alter a specific equipment variable.
Also by TYPE might be necessary.
BONUS:ITEMTYPE=<EquipmentType>|<EQVAR NAME>|<Value>
> and for the other way:
> GETEQVAR:<Name of Equipment>|<EQVARNAME>
> Allow an ability or other item to get the value of a specific equipment variable.
Umm, and how would that be put to use (I like the idea and think it’s necessary, but not seeing how it would be used in this form)? Are you saying that would be put into a formula?
> Okay folks, thoughts, ideas, improvements, suggestions and implementation strategy?
I think the above covers my input on it for the moment.
Barak
James Adds
From JAMES DEMPSEY (Code SB)
Hi,
The proposal looks good to me at this stage, however, I think we need to expand the logic a bit.
My major concern is that we think through and define the scope and lifetime of equipment variables.
The basic questions:
- 1. When is a DEFINE:EQVAR actioned? i.e. when does the variable start to exist
- 2. When are BONUS:EQVAR statements actioned? Presumably these would support PREreqs for both the equipment and the character they are associated.
- 3. A character may have none, 1 or multiple of a particular item. What are the rules for the eqvar() function in those cases?
- 4. Can these be output? e.g for a debugging sheet.
Some more complex questions:
- C1. How does equipped, carried, not carried and not in an equipset affect the behaviour of equipment variables?
- C2. How does having multiple equipsets affect the variables? Do we need to track a value for each item in each equipset?
- C3. What effect do equipment variables have on the calculation cycle of PCGen? i.e. How do we implement them without slowing the core to a crawl?
Lastly, given we are talking a core programming principle, stored values, are there any lessons we should consider from 60 years of computer science and compiler design?
PS: I've pulled this discussion on list as I think it needs to be recorded and others may be able to provide some input.
Cheers, James.
Follow Up
I'll try to answer these as best I can, but understand I'm not a Programmer.
On 12/12/2011 1:41 AM, James Dempsey wrote: > Hi, > > The proposal looks good to me at this stage, however, I think we need to > expand the logic a bit. > > My major concern is that we think through and define the scope and > lifetime of equipment variables. > > The basic questions: > 1. When is a DEFINE:EQVAR actioned? i.e. when does the variable start to > exist
Tough Question - Since it pertains to equipment, it needs to exist whenever the equipment itself "exists" - either made and on the character and during the customization process (Otherwise we can't make items relying on the eqvar). Each piece of equipment is a mini-character in that the vars exist until the equipment no longer exists (Though even that statement might be a fallacy, just being in the equipment list it might need to exist).
> 2. When are BONUS:EQVAR statements actioned? Presumably these would > support PREreqs for both the equipment and the character they are > associated. I'm not certain of the question, but it should be DEFINE > BONUS > .MOD > .COPY= > Validate (PRExxx) in my mind (Or whatever the normal Order of Operations are) As far as BONUS - If the item exists to the character, (Customization or listed on the character in any capacity) the BONUS would need to apply I think.
> 3. A character may have none, 1 or multiple of a particular item. What > are the rules for the eqvar() function in those cases? Each item 'same name var' has to be unique and self-contained - this is where things get tricky in my head.
Let's throw out some scenarios and see what we come up with:
Character A - Is a Dual Dagger Wielding Rogue - Each Dagger has the EQVAR 'Hardness' and 'HP'. Both are equipped (PrimaryHand, SecondaryHand). The rogue has Ability A, that increases the Hardness of One Item.
How do we accomplish it?
BONUS:EQVAR with a PREITEM:1,PrimaryHand (That wouldn't apply to just one, so we need to expand the BONUS to not just 'Item', 'Item TYPE' but also consider Locations or Body Slots)
Character B - Has two longswords, one is a +3 Intelligent Magic Sword, the other is Masterwork Set piece which increases it's mate's effective hide ability by 4. Magic sword is equipped (PrimaryHand) the other is 'Carried'. The Sword increases the Hide Skill Check by 2 per +1 of the sword.
How is this to be accomplished?
James - I think you'll be better to come up with corner case scenarios beyond these simple daily ones.
> 4. Can these be output? e.g for a debugging sheet.
Debugging is always key to making sure something works, ergo, we should be able to output them. It
should be as simple as adding SPROP and '%" variable substitution (Which means EQVAR names need to
work on equipment SPROP tags).
> Some more complex questions:
> C1. How does equipped, carried, not carried and not in an equipset
> affect the behaviour of equipment variables?
Equipped, Carried and Not Carried should be identical as far as EQVAR on the item is concerned -
assume their numbers are unaffected as the character owns them, if there are certain bonuses the
character grants to the item - those need to be stated on whether they affect the item despite
equipped state or not. It's the from the item to another item, or item to character that things get
trickier - Set Items Should Bonus each other as long as they exist together - we should have LST
syntax to determine when the bonus is applied.
> C2. How does having multiple equipsets affect the variables? Do we need > to track a value for each item in each equipset? Since equipment variables should not be affected by their state as long as they exist for a Character. Any bonuses from a character should be constant (Unless said character has an 'Equipped PRExxx' to deny bonusing)
> C3. What effect do equipment variables have on the calculation cycle of > PCGen? i.e. How do we implement them without slowing the core to a crawl? I don't feel adequate to address that question. (Programmer question) Though, might I offer that a subsystem primarily handle it perhaps?
> Lastly, given we are talking a core programming principle, stored > values, are there any lessons we should consider from 60 years of > computer science and compiler design? That seems more suited to our experienced programmers.
> PS: I've pulled this discussion on list as I think it needs to be > recorded and others may be able to provide some input. Fair enough.
Eric Jarman Added
Is there anything here that couldn't be accomplished by adding namespaces to the existing variable logic?
By namespaces, I mean automatically adding some prefix to the variable name depending on where you are accessing the variable from (the variable's scope, if you will). The code would have to automatically assign a unique namespace for each item, then the combination of <namespacetag>.<varname> would become the canonical name for each variable. When you need to bonus a specific item, you would just need to look up whatever namespace tag matches the item you want to bonus, then proceed as with a normal variable.
It might be desirable to add a default (and hidden) namespace for the character variables, to make it impossible to accidentally overwrite an item's variables. (Not unlike what is done with feats and abilitycategories.)
Tom Parker Responds
> Is there anything here that couldn't be accomplished by adding namespaces > to the existing variable logic? That's basically what we're talking about, just using different words.
A challenge we have really comes from a scenario where someone has two of something... dual-wielding daggers, perhaps.
So you have two items: "Dagger" "Dagger"
Now you could assign namespaces: "LH/Dagger" "RH/Dagger"
which breaks because you can't assume which is primary/secondary because of different handedness (left vs. right), so you could try:
"Primary/Dagger" "Secondary/Dagger"
But then you encounter an order of operations problem. These names are only created once an item is equipped (this is a runtime event). So like James asked, do we need to do calculations when things are only carried? If so, how would you ensure changes to objects as they are moved around? ... or does the namespace have to be location independent (in which case we're back to figuring out how to distinguish those two daggers)?
The other order of operations trick here being that the data monkeys have to write the BONUS item into the data, which is a "build time" event that occurs before runtime (before any PCs are created).... So perhaps you assume that it's always "Primary/Dagger" that would get the bonus (to hardness was the example Andrew M used a bit ago). So that means the code has to universally apply the prefix even if there aren't two "Dagger" items that need to be disambiguated (this is probably what you'd expect anyway)
But even then that has a counterexample - what if it's metal hardness only? What if it isn't two "Dagger" items, but: "Primary/Club" "Secondary/Dagger"
So now the bonus would have to be applied to the "Secondary/Dagger" in that scenario.. breaking the assumption of Primary.
(As a side note, it will make it really important to have a specific set of use cases we are targeting so we know how far we have to go. Flexibility is good, but it may also take LOTS more work to implement... so can one or more of the data monkeys gather up concrete examples so we can have those as a guide of what needs vs. wants?)
So running through those scenarios and counterexamples is what produces the headache... we don't want a ton of BONUS objects floating around with all kinds of conditionals... so how do we do this in a way that is "simple"?
So throwing out some ideas (I still haven't found a solution I really like):
- warning* if you read these ideas please do not tell me these tokens won't work because of some syntax error. Read for the theme, not the literal syntax.
(1) Create some method of applying a bonus only once. So you could have something like: BONUS:EQVARONCE|Hardness|4 And then it would run down from Primary and into the secondary weapons and apply that hardness only once. Of course, if it only applies to certain types of weapons like I speculated above... that becomes a problem (because a PRE on the end of the BONUS above would impact whether the bonus was granted, not to what the bonus can be applied!)... so syntax here might not meet the requirements if there can ever be an application constraint.
(2) Constrain things so that only Equipment & EqMod objects can ever impact equipment variables. Note - I think - that this has an interesting "workaround". BONUS:...|PREAPPLY:EQUIP (or whatever the syntax is for using PREAPPLY onto equipment - I'm almost 100% sure one exists) actually places that BONUS into the equipment. So while the data folks may think it's the spell doing the BONUS, in reality it's actually the equipment doing the BONUS to itself after the spell tells it to do so. As a result, we meet the constraint, PROVIDED that the only external things that can modify equipment variables have to be applied to equipment. Is that true? This is where the concrete examples are important.
If we have examples that require more complicated modification, I have another idea I can work through, but that is more involved and will require a revisit after this thing called sleep...
Lee Dowd Asks a question
I'm far from an expert on these things but it seems to me that it's even worse than what is implied below. What if you have a character with say 4 hands? Does he have a primary? or multiple primaries? or ???
Further thoughts from Eric Jarman
My idea would be to have a persistent identifier be a permanent part of the namespace.
Here's an overview of how I see such a namespace being fleshed out. [For the sake of this example, let's assume using a "." as a namespace separator. In the code, it just needs to be any reserved character that should not (but not necessarily cannot) be used in a variable name.]
We would have a unique namespace for each character in memory, which would be persistent across each load of a character. (This is for extending the idea into GMGen, so we can account for bonuses that might affect the whole party.) Each item on a character would have its own unique namespace as well. Existing defined variables would have to be added into their own namespace to avoid accidentally overwriting item variables.
<characterid>.variables.<varname> <characterid>.items.<itemid>.<eqvarname>
Then, for your primary weapon, you would have a reference to the itemid of the weapon you want to hold.
<characterid>.eqslot.primaryweapon.id=<reference_to_an_itemid>
If you want to bonus an eqvar on your primary weapon, you would have to know if it is intended to be permanently applied to that item, then follow the item, or know if it is just a bonus that is applied to whatever weapon you are holding in that slot. Effectively, this is two different kinds of bonus, one that would be stored under the item instance (with the itemid), and one that would be stored in the slot (effectively making the item slot into a virtual item with its own eqvars).
<characterid>.eqslot.primaryweapon.<eqvarname>
This idea could even be extended to be used in multiple equipment sets or
attack cycles, just by adding an additional namespace (cascaded as
required) for each one you want to use.
Effectively, this idea is exposing some of the internals of how the program keeps track of items and variables at runtime down into the saved data in the pcg file.
Now , in the LST code for a specific item, you would not have to make any reference to the namespace, you would just bonus each variable by its eqvarname. It is up to the code to determine the correct namespace (ie "scope") based on when/where it is used. If you're bonusing an eqvar from the character, you would need an appropriate CHOOSE/CHOICE for the code to find the correct namespace of the item to add the bonus into.
I hope these examples help make my thought processes more clear. I'm not familiar with the code internals of how variables are stored, so I'm trying to not make any assumptions based on the existing setup. My examples above are actually based on how Linux uses namespaces to store extended attributes on filesystems which support them. In their most basic form, Linux extended attributes are just key-value pairs, where each key and each value is a character string, with predefined namespaces assigned to specific uses of some key names.