Skip to content

Commit

Permalink
Closes #870: Add substitution support to weapon usage and usage notes
Browse files Browse the repository at this point in the history
  • Loading branch information
richardwilkes committed Jul 29, 2024
1 parent f888483 commit 3e7f56b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 26 deletions.
4 changes: 2 additions & 2 deletions model/gurps/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,12 @@ func evalWeaponDamage(ev *eval.Evaluator, arguments string) (any, error) {
return nil, err
}
for _, w := range e.Weapons(true) {
if strings.EqualFold(w.String(), name) && strings.EqualFold(w.Usage, usage) {
if strings.EqualFold(w.String(), name) && strings.EqualFold(w.UsageWithReplacements(), usage) {
return w.Damage.ResolvedDamage(nil), nil
}
}
for _, w := range e.Weapons(false) {
if strings.EqualFold(w.String(), name) && strings.EqualFold(w.Usage, usage) {
if strings.EqualFold(w.String(), name) && strings.EqualFold(w.UsageWithReplacements(), usage) {
return w.Damage.ResolvedDamage(nil), nil
}
}
Expand Down
4 changes: 2 additions & 2 deletions model/gurps/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ func export(entity *Entity, tmpl exporter, exportPath string) (err error) {
data.MeleeWeapons = append(data.MeleeWeapons, &exportedMeleeWeapon{
Description: w.String(),
Notes: w.Notes(),
Usage: w.Usage,
Usage: w.UsageWithReplacements(),
Level: w.SkillLevel(nil),
Parry: parry.String(),
ParryParts: parry,
Expand All @@ -618,7 +618,7 @@ func export(entity *Entity, tmpl exporter, exportPath string) (err error) {
data.RangedWeapons = append(data.RangedWeapons, &exportedRangedWeapon{
Description: w.String(),
Notes: w.Notes(),
Usage: w.Usage,
Usage: w.UsageWithReplacements(),
Level: w.SkillLevel(nil),
Accuracy: accuracy.String(),
AccuracyParts: accuracy,
Expand Down
2 changes: 1 addition & 1 deletion model/gurps/export_legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -1359,7 +1359,7 @@ func (ex *legacyExporter) processWeaponKeys(key string, currentID int, w *Weapon
case descriptionPrimaryExportKey:
ex.writeEncodedText(w.String())
case "USAGE":
ex.writeEncodedText(w.Usage)
ex.writeEncodedText(w.UsageWithReplacements())
case "LEVEL":
ex.writeEncodedText(w.SkillLevel(nil).String())
case "DAMAGE":
Expand Down
58 changes: 37 additions & 21 deletions model/gurps/weapon.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,10 @@ func (w *Weapon) Clone(_ LibraryFile, _ DataOwner, _ *Weapon, preserveID bool) *
func (w *Weapon) Compare(other *Weapon) int {
result := txt.NaturalCmp(w.String(), other.String(), true)
if result == 0 {
if result = txt.NaturalCmp(w.Usage, other.Usage, true); result == 0 {
if result = txt.NaturalCmp(w.UsageNotes, other.UsageNotes, true); result == 0 {
result = cmp.Compare(uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(other))) //nolint:gosec // Just need a tie-breaker
if result = txt.NaturalCmp(w.UsageWithReplacements(), other.UsageWithReplacements(), true); result == 0 {
if result = txt.NaturalCmp(w.UsageNotesWithReplacements(), other.UsageNotesWithReplacements(), true); result == 0 {
//nolint:gosec // Just need a tie-breaker
result = cmp.Compare(uintptr(unsafe.Pointer(w)), uintptr(unsafe.Pointer(other)))
}
}
}
Expand Down Expand Up @@ -373,7 +374,7 @@ func (w *Weapon) Notes() string {
if w.Owner != nil {
buffer.WriteString(w.Owner.Notes())
}
AppendStringOntoNewLine(&buffer, strings.TrimSpace(w.UsageNotes))
AppendStringOntoNewLine(&buffer, strings.TrimSpace(w.UsageNotesWithReplacements()))
return buffer.String()
}

Expand Down Expand Up @@ -436,8 +437,9 @@ func (w *Weapon) SkillLevel(tooltip *xio.ByteBuffer) fxp.Int {
}

func (w *Weapon) usesCrossbowSkill() bool {
replacements := w.NameableReplacements()
for _, def := range w.Defaults {
if def.Name == "Crossbow" {
if def.NameWithReplacements(replacements) == "Crossbow" {
return true
}
}
Expand All @@ -464,7 +466,7 @@ func (w *Weapon) skillLevelBaseAdjustment(e *Entity, tooltip *xio.ByteBuffer) fx
}
}
nameQualifier := w.String()
for _, bonus := range e.NamedWeaponSkillBonusesFor(nameQualifier, w.Usage, w.Owner.TagList(), tooltip) {
for _, bonus := range e.NamedWeaponSkillBonusesFor(nameQualifier, w.UsageWithReplacements(), w.Owner.TagList(), tooltip) {
adj += bonus.AdjustedAmount()
}
for _, f := range w.Owner.FeatureList() {
Expand Down Expand Up @@ -518,7 +520,7 @@ func (w *Weapon) EncumbrancePenalty(e *Entity, tooltip *xio.ByteBuffer) fxp.Int
func (w *Weapon) extractSkillBonusForThisWeapon(f Feature, tooltip *xio.ByteBuffer) fxp.Int {
if sb, ok := f.(*SkillBonus); ok {
if sb.SelectionType.EnsureValid() == skillsel.ThisWeapon {
if sb.SpecializationCriteria.Matches(w.Owner.NameableReplacements(), w.Usage) {
if sb.SpecializationCriteria.Matches(w.NameableReplacements(), w.UsageWithReplacements()) {
sb.AddToTooltip(tooltip)
return sb.AdjustedAmount()
}
Expand Down Expand Up @@ -553,14 +555,6 @@ func (w *Weapon) ResolveBoolFlag(switchType wswitch.Type, initial bool) bool {
return initial
}

// NameableReplacements returns the replacements to be used with this weapon.
func (w *Weapon) NameableReplacements() map[string]string {
if toolbox.IsNil(w.Owner) {
return nil
}
return w.Owner.NameableReplacements()
}

func (w *Weapon) collectWeaponBonuses(dieCount int, tooltip *xio.ByteBuffer, allowedFeatureTypes ...feature.Type) []*WeaponBonus {
entity := w.Entity()
if entity == nil {
Expand Down Expand Up @@ -588,9 +582,11 @@ func (w *Weapon) collectWeaponBonuses(dieCount int, tooltip *xio.ByteBuffer, all
name = bestDef.NameWithReplacements(replacements)
specialization = bestDef.SpecializationWithReplacements(replacements)
}
entity.AddWeaponWithSkillBonusesFor(name, specialization, w.Usage, tags, dieCount, tooltip, bonusSet, allowed)
entity.AddWeaponWithSkillBonusesFor(name, specialization, w.UsageWithReplacements(), tags, dieCount, tooltip,
bonusSet, allowed)
nameQualifier := w.String()
entity.AddNamedWeaponBonusesFor(nameQualifier, w.Usage, tags, dieCount, tooltip, bonusSet, allowed)
entity.AddNamedWeaponBonusesFor(nameQualifier, w.UsageWithReplacements(), tags, dieCount, tooltip, bonusSet,
allowed)
for _, f := range w.Owner.FeatureList() {
w.extractWeaponBonus(f, bonusSet, allowed, fxp.From(dieCount), tooltip)
}
Expand Down Expand Up @@ -635,19 +631,19 @@ func (w *Weapon) extractWeaponBonus(f Feature, set map[*WeaponBonus]bool, allowe
savedDieCount := bonus.WeaponLeveledAmount.DieCount
bonus.WeaponLeveledAmount.Level = bonus.DerivedLevel()
bonus.WeaponLeveledAmount.DieCount = dieCount
replacements := w.Owner.NameableReplacements()
replacements := w.NameableReplacements()
switch bonus.SelectionType {
case wsel.WithRequiredSkill:
case wsel.ThisWeapon:
if bonus.SpecializationCriteria.Matches(replacements, w.Usage) {
if bonus.SpecializationCriteria.Matches(replacements, w.UsageWithReplacements()) {
if _, exists := set[bonus]; !exists {
set[bonus] = true
bonus.AddToTooltip(tooltip)
}
}
case wsel.WithName:
if bonus.NameCriteria.Matches(replacements, w.String()) &&
bonus.SpecializationCriteria.Matches(replacements, w.Usage) &&
bonus.SpecializationCriteria.Matches(replacements, w.UsageWithReplacements()) &&
bonus.TagsCriteria.MatchesList(replacements, w.Owner.TagList()...) {
if _, exists := set[bonus]; !exists {
set[bonus] = true
Expand All @@ -663,8 +659,28 @@ func (w *Weapon) extractWeaponBonus(f Feature, set map[*WeaponBonus]bool, allowe
}
}

// UsageWithReplacements returns the usage of the weapon with any nameable keys replaced.
func (w *Weapon) UsageWithReplacements() string {
return ApplyNameables(w.Usage, w.NameableReplacements())
}

// UsageNotesWithReplacements returns the usage notes of the weapon with any nameable keys replaced.
func (w *Weapon) UsageNotesWithReplacements() string {
return ApplyNameables(w.UsageNotes, w.NameableReplacements())
}

// NameableReplacements returns the replacements to be used with this weapon.
func (w *Weapon) NameableReplacements() map[string]string {
if toolbox.IsNil(w.Owner) {
return nil
}
return w.Owner.NameableReplacements()
}

// FillWithNameableKeys adds any nameable keys found in this Weapon to the provided map.
func (w *Weapon) FillWithNameableKeys(m, existing map[string]string) {
ExtractNameables(w.Usage, m, existing)
ExtractNameables(w.UsageNotes, m, existing)
for _, one := range w.Defaults {
one.FillWithNameableKeys(m, existing)
}
Expand Down Expand Up @@ -777,7 +793,7 @@ func (w *Weapon) CellData(columnID int, data *CellData) {
data.Primary = w.String()
data.Secondary = w.Notes()
case WeaponUsageColumn:
data.Primary = w.Usage
data.Primary = w.UsageWithReplacements()
case WeaponSLColumn:
data.Primary = w.SkillLevel(&buffer).String()
case WeaponParryColumn:
Expand Down

0 comments on commit 3e7f56b

Please sign in to comment.