Conferring Edges and Hindrances (Savage)
There are a handful of interesting mechanics in Savage Worlds that all hinge on a similar capability within the data files. Edges and hindrances can be automatically conferred by another selection, such as races, injuries, fright, etc.
Detecting Bootstrapped Picks
When an edge or hindrance is conferred by another selection, it must be bootstrapped by that selection. Any edge or hindrance that is handled this way needs to be treated specially, since it should not count as having cost an advance (for edges) nor should it count as earning rewards (for hindrances). This entails special handling that must be instrumented at the component level so that it works smoothly for all instances. Since both edges and hindrances accrue advances and rewards separately, we need to implement the same basic logic within both the "Edge" and "Hindrance" components.
We can determine whether a pick has been bootstrapped by another pick via use of the "isroot" target reference. If "isroot" returns non-zero, the pick has a root pick that bootstrapped it into existence. If we know a pick has been bootstrapped, then we can avoid accruing the appropriate cost into the resource that tracks the edges or hindrances. We can modify the existing Eval scripts that accrue the cost of edges and hindrances by adding this new logic.
What If Bootstrapped And User-Added?
Unfortunately, this isn't a complete solution for what we need. The problem is that users may have already added the edge or hindrance manually, prior to when it is bootstrapped. This results in a conflict. The question becomes whether we should just ignore the user-added selection or treat it normally. So let's consider a couple of examples to figure out how to handle this. The first example is a user who adds an edge to a character during creation and then chooses a custom race that confers the same edge. In this instance, we should probably not count the edge against the character and should warn the user so that he can delete the edge that was manually added. Similarly, consider a user who adds a hindrance to a character during creation and then selects a race that confers the same hindrance. We should probably not count the hindrance and should warn the user about the conflict. Unfortunately, there is a flipside to this. Consider a user who selects the "Ugly" hindrance during character creation and then later incurs a permanent injury that confers the "Ugly" hindrance. In this situation, we simply want to ignore the bootstrapping of "Ugly", since the character is already ugly and is essentially no further impacted by the injury.
These various examples are in direct conflict with one another, and we can't do it both ways. This means that we have to choose one method and simply live with it, even though there will be times that it's not the optimal solution. When considering the two alternatives, we need to consider which ones are (a) more likely to occur and (b) more likely to yield results that are confusing to the user. The examples where we should not count the edge or hindrance only occur during character creation. Furthermore, these examples are unlikely to occur, since races rarely confer edges and hindrances, and the examples rely upon the user manually selecting an edge or hindrance before selecting the character's race. In contrast, situations where the character incurs a permanent injury that replicates a hindrance chosen at creation is much more likely to occur. And if we stop accruing a hindrance that was taken at creation, the character will begin reporting validation errors that don't actually exist. So our choice is pretty clear: we need to always accrue the cost of edges and hindrances that are user-added, even if they are also bootstrapped by other selections.
On the surface, this conclusion might seem to imply that we don't actually need to change anything in the code. However, there is a critical detail in our conclusion that does necessitate a change. In each of our examples, we examined what to do when the user adds an edge/hindrance and that edge/hindrance is bootstrapped by some other selection. However, we also need to deal with edges and hindrances that are only bootstrapped by another selection. In this circumstance, we do not want to accrue the cost of the edge/hindrance.
This means that we only want to accrue the cost if the edge/hindrance was added by the user. If it is also bootstrapped, we still treat it as having been added by the user and accrue it normally. However, if it is only added via bootstrapping, we need to skip it. Fortunately, there is the "isuser" target reference that will tell us whether a given pick has been added by the user. So we'll use this to ascertain whether to accrue the cost for each edge and hindrance. We can now modify the existing Eval scripts to implement the appropriate logic. The revised script for the "Edge" component should end up looking similar to the following.
<eval value="2" phase="Setup" priority="5000"><![CDATA[ ~if this edge is not added directly to the hero (i.e. an advance), skip it entirely if (origin.ishero = 0) then done endif ~if this edge was not added by the user, skip it entirely if (isuser = 0) then done endif ~consume another edge slot #resspent[resEdge] += 1 ]]></eval>
Applying the equivalent change to the Eval script for the "Hindrance" component yields the revised script below.
<eval value="2" phase="Setup" priority="5000"><![CDATA[ ~if this hindrance was not add by the user, skip it entirely if (isuser = 0) then done endif ~consume another hindrance slot or two, depending on the severity #resmax[resHinder] += field[hinMajor].value + 1 ]]></eval>
All Thumbs Again
At this point, we need to revisit something that we did early in our development. When we added the Elven race, we opted to add a new ability that paralleled the "All Thumbs" hindrance so that we could avoid having to deal with hindrances being bootstrapped by races. Well, we just dealt with that situation, so we no longer need to have an ability to mimic the hindrance. We can now go back into the file "thing_races.dat" and do two things. First, we can modify the "Elven" race to bootstrap the "All Thumbs" hindrance instead of the ability. This entails changing the unique id being bootstrapped from "abAllThumb" to "hinThumbs". Second, we can delete the "All Thumbs" ability that is no longer needed nor used.