Skip to content

About

AzerothCore module: a class skill doubled for good, discovered at level 60 (XorWoW)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mod-affinity

An AzerothCore module: at level 60 a character discovers its affinity, one of the class skills it knows, drawn at random and doubled for the rest of its life.

Xorbis has reached level 60 and discovered his affinity for [Fireball].

The choice is announced to everyone online and in the character's guild chat, and the boosted skill's own tooltip shows the doubled numbers, on every rank, without a client patch.

How it works

Each candidate skill has a hidden passive (a spell_dbc row, ids 250001+) carrying a +100 % spell modifier on the skill's family bits: SPELL_AURA_ADD_PCT_MODIFIER with op 0 (SPELLMOD_DAMAGE) for direct damage and heals, op 22 (SPELLMOD_DOT) for periodic ticks, op 8 (SPELLMOD_ALL_EFFECTS) for buffs and absorbs. That is exactly how the Improved talents are built (Improved Eviscerate, Improved Corruption, Improved Power Word: Fortitude), so the core applies it in the same places (Unit::SpellDamageBonusDone, SpellHealingBonusDone, MeleeDamageBonusDone, SpellEffectInfo::CalcValue) and the client, which receives the modifier like any talent's, draws the doubled values into the tooltips. Damage and heals double after spell power; buffs double their base value; absorbs double their base (the spell-power part of a shield is added by a script afterwards and is not doubled).

The passive is applied at discovery and put back at every login (passives are not saved with a character's auras); the choice lives in character_affinity. Talent-granted skills are deliberately not in the pool: a respec would strand the affinity.

affinity_pool (world database) holds the 129 candidates: 13 warrior, 11 paladin, 11 hunter, 9 rogue, 15 priest, 9 death knight, 15 shaman, 15 mage, 13 warlock, 18 druid — damage, heals, DoTs/HoTs and buffs, trainer-taught (or quest-taught for death knights) at level 60 or below. Its weight column tunes the roll (0 takes an entry out; .affinity reload picks changes up), the roll only considers skills the character actually knows. The table and the spell_dbc rows are generated by tools/gen_affinity.py from the pool defined at the top of that script and the client's Spell.dbc; the script refuses two entries of one class whose masks overlap and prints what else every mask touches, so a pool change is reviewed before it ships.

Rerolls

A character can reroll its affinity a few times, for gold: 50g, 100g and 250g by default (Affinity.RerollCosts, the number of prices is the number of rerolls). A reroll draws a different skill with the same rules as the discovery and offers it; the character then takes it or keeps the one it has, and the gold is spent either way. The outcome is announced like a discovery:

Xorbis rerolled his affinity and traded [Fireball] for [Frostbolt]. Xorbis rerolled his affinity, was offered [Arcane Missiles] and kept [Fireball].

The offer is stored with the affinity (character_affinity.offer_id), so logging out or a restart before choosing keeps it; one offer at a time, no reroll or choice in combat (keeping is allowed). The addon does it from the spellbook entry; without the addon, .affinity reroll tells the price and .affinity reroll confirm pays it, then .affinity take or .affinity keep. A player's alts played by the bot AI reroll when their owner logs them in.

Bots

With mod-playerbots, the realm's random bots (the rndbot accounts and the .playerbots bot addclass bots) get nothing unless Affinity.RandomBots = 1: they are recycled constantly and every 60+ bot would announce itself at each realm start. A player's own characters driven by the bot AI are players: they roll at 60, are announced, and show their entry when their owner logs them in.

Client addon

Everything else the player sees is drawn by the realm's addon (XorWoW, this repository's client\Interface\AddOns\XorWoW\Affinity.lua): an Affinity entry in the spellbook, in the tab of the boosted skill and with its icon; an Affinity: damage doubled line on the boosted skill's tooltip; a banner with the level-up chime when the affinity is discovered; a shift-click on the spellbook entry links [Affinity: Frostbolt] in chat. The module tells the addon what was rolled through an addon message (prefix XorWoW, AFFINITY;NEW|CUR|SWAP;<pool id>;<spell id>;<text>;<skill names>;<rerolls left>;<next reroll cost in copper>;<passive id>;<passive name>) at login and at discovery, and answers the addon's AFFINITY? request after a UI reload. The chat link is a plain spell link to the hidden passive - the core's link check only lets through real spells named by their own name, which the passive is ("Affinity: ") - and since the client has no data for that spell, the addon draws the clicked link's tooltip itself, after asking AFFINITY?INFO;<passive id> (answer: AFFINITY;INFO;<passive id>;<spell id>;<text>). Rerolls: the addon sends AFFINITY!REROLL, AFFINITY!TAKE or AFFINITY!KEEP; the module answers AFFINITY;OFFER;<pool id>;<spell id>;<text>;<skill names> with a paid offer (again at login while it waits), SWAP when it is taken, CUR when it is declined, AFFINITY;ERR;<reason> when a request is refused. The server checks everything; the addon only asks. Without the addon the doubling, the doubled tooltips and the announcements still work; only the drawn extras are missing.

Commands

Command Who What
.affinity [name] everyone Your affinity, or someone else's.
.affinity reroll [confirm] everyone The price of the next reroll; with confirm, pay it and get an offer.
.affinity take / .affinity keep everyone Swap to the offered affinity / keep yours.
.affinity force [name] GM Roll a different one for free (announced); the paid rerolls are untouched.
.affinity set <pool id> [name] GM Give a specific pool entry (not announced).
.affinity reset [name] GM Remove it and the rerolls used; the next level-up or login rolls a new one.
.affinity list [class id] GM, console The pool.
.affinity reload admin, console Reload affinity_pool.

Install

  1. Clone into modules/mod-affinity and rebuild the core. The SQL under data/sql is applied by the database updater (db-world: pool + passives, db-characters: character_affinity).
  2. conf/mod_affinity.conf.dist documents the settings: Affinity.Enable, Affinity.Level (60), Affinity.Announce, Affinity.AnnounceGuild, Affinity.RandomBots, Affinity.RerollCosts.
  3. Characters already past the level roll at their next login.

To change the pool, edit POOL in tools/gen_affinity.py, run it against a 3.3.5a Spell.dbc (docker cp ac-worldserver:/azerothcore/env/dist/data/dbc/Spell.dbc .), review its report, commit the regenerated SQL. Pool ids are permanent: append, never renumber.

About

AzerothCore module: a class skill doubled for good, discovered at level 60 (XorWoW)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages