I've implemented a few things on Alternate Advancement.
Unfortunately, the PlayerProfile_Struct does NOT contain information about alternate advancement and the server holds a separate table of 128 (?) bytes in size. (table defined below)
I've been fiddling around with the way the server communicates this data to the client... but all I can figure out is that the server sends an opcode of 0x1522 with the table as the payload once the client is connected and established in the zone.
AA experience value is an int32 at location 4529 (4530?) in the PlayerProfile_Struct. I can't figure out where the percentage and number of unspent AA points are stored.
I'm too lazy to fill out the archetype_skills field with correct names. If you're feeling spiffy and want to fill in the names, just go #gm, hit V, and click on the names of the skills in the arch. skill list, the descriptions will show the ID number (which coincides with the position in the buffer). Just be happy I went through ALL the Class skills of each class (yes, they're all listed. no, I didn't forget beastlords -- they just use the same skills as shamen / monks.)
There is, however, a message from the client with an opcode of 0x1422 when the user clicks the arrow buttons in the Alternate Advancement menu, but all I can glean from the 256-byte field is a string containing a word "on" or "off" and a text-encoded number which seems to equal the percentage requested. I can't figure out how to respond with the right value to enable the AAXP percentage, so it stays 0% at all times. Oh well.
I implemented a copy of the Database::GetPlayerProfile() function that returns the "alt_adv" column from the "character_" table. It works pretty well, but it requires that everyone "ALTER TABLE character_ ADD COLUMN alt_adv blob;" their databases, which is icky... and requires that the code that looks up the table will handle a NULL value when the emu tries to look up the alt_adv table when nothing has been saved there before.
Code:
struct PlayerAA_Struct {
/* 0 */ uint8 unknown0;
union {
uint8 unnamed[17];
struct _named {
/* 1 */ uint8 innate_strength;
/* 2 */ uint8 innate_stamina;
/* 3 */ uint8 innate_agility;
/* 4 */ uint8 innate_dexterity;
/* 5 */ uint8 innate_intelligence;
/* 6 */ uint8 innate_wisdom;
/* 7 */ uint8 innate_charisma;
/* 8 */ uint8 innate_fire_protection;
/* 9 */ uint8 innate_cold_protection;
/* 10 */ uint8 innate_magic_protection;
/* 11 */ uint8 innate_poison_protection;
/* 12 */ uint8 innate_disease_protection;
/* 13 */ uint8 innate_run_speed;
/* 14 */ uint8 innate_regeneration;
/* 15 */ uint8 innate_metabolism;
/* 16 */ uint8 innate_lung_capacity;
/* 17 */ uint8 first_aid;
} named;
} general_skills;
union {
uint8 unnamed[17];
struct _named {
/* 18 */ uint8 healing_adept;
/* 19 */ uint8 healing_gift;
/* 20 */ uint8 unknown20;
/* 21 */ uint8 spell_casting_reinforcement;
/* 22 */ uint8 mental_clarity;
/* 23 */ uint8 spell_casting_fury;
/* 24 */ uint8 chanelling_focus;
/* 25 */ uint8 unknown25;
/* 26 */ uint8 unknown26;
/* 27 */ uint8 unknown27;
/* 28 */ uint8 natural_durability;
/* 29 */ uint8 natural_healing;
/* 30 */ uint8 combat_fury;
/* 31 */ uint8 fear_resistance;
/* 32 */ uint8 finishing_blow;
/* 33 */ uint8 combat_stability;
/* 34 */ uint8 combat_agility;
} named;
} archetype_skills;
union {
uint8 unnamed[93];
struct _name {
/* 35 */ uint8 mass_group_buff; // All group-buff-casting classes(?)
// ===== Cleric =====
/* 36 */ uint8 divine_resurrection;
/* 37 */ uint8 innate_invis_to_undead; // cleric, necromancer
/* 38 */ uint8 celestial_regeneration;
/* 39 */ uint8 bestow_divine_aura;
/* 40 */ uint8 turn_undead;
/* 41 */ uint8 purify_soul;
// ===== Druid =====
/* 42 */ uint8 quick_evacuation; // wizard, druid
/* 43 */ uint8 exodus; // wizard, druid
/* 44 */ uint8 quick_damage; // wizard, druid
/* 45 */ uint8 enhanced_root; // druid
/* 46 */ uint8 dire_charm; // enchanter, druid, necromancer
// ===== Shaman =====
/* 47 */ uint8 cannibalization;
/* 48 */ uint8 quick_buff; // shaman, enchanter
/* 49 */ uint8 alchemy_mastery;
/* 50 */ uint8 rabid_bear;
// ===== Wizard =====
/* 51 */ uint8 mana_burn;
/* 52 */ uint8 improved_familiar;
/* 53 */ uint8 nexus_gate;
// ===== Enchanter =====
/* 54 */ uint8 unknown54;
/* 55 */ uint8 permanent_illusion;
/* 56 */ uint8 jewel_craft_mastery;
/* 57 */ uint8 gather_mana;
// ===== Mage =====
/* 58 */ uint8 mend_companion; // mage, necromancer
/* 59 */ uint8 quick_summoning;
/* 60 */ uint8 frenzied_burnout;
/* 61 */ uint8 elemental_form_fire;
/* 62 */ uint8 elemental_form_water;
/* 63 */ uint8 elemental_form_earth;
/* 64 */ uint8 elemental_form_air;
/* 65 */ uint8 improved_reclaim_energy;
/* 66 */ uint8 turn_summoned;
/* 67 */ uint8 elemental_pact;
// ===== Necromancer =====
/* 68 */ uint8 life_burn;
/* 69 */ uint8 dead_mesmerization;
/* 70 */ uint8 fearstorm;
/* 71 */ uint8 flesh_to_bone;
/* 72 */ uint8 call_to_corpse;
// ===== Paladin =====
/* 73 */ uint8 divine_stun;
/* 74 */ uint8 improved_lay_of_hands;
/* 75 */ uint8 slay_undead;
/* 76 */ uint8 act_of_valor;
/* 77 */ uint8 holy_steed;
/* 78 */ uint8 fearless; // paladin, shadowknight
/* 79 */ uint8 two_hand_bash; // paladin, shadowknight
// ===== Ranger =====
/* 80 */ uint8 innate_camouflage; // ranger, druid
/* 81 */ uint8 ambidexterity; // all "dual-wield" users
/* 82 */ uint8 archery_mastery; // ranger
/* 83 */ uint8 unknown83;
/* 84 */ uint8 endless_quiver; // ranger
// ===== Shadow Knight =====
/* 85 */ uint8 unholy_steed;
/* 86 */ uint8 improved_harm_touch;
/* 87 */ uint8 leech_touch;
/* 88 */ uint8 unknown88;
/* 89 */ uint8 soul_abrasion;
// ===== Bard =====
/* 90 */ uint8 instrument_mastery;
/* 91 */ uint8 unknown91;
/* 92 */ uint8 unknown92;
/* 93 */ uint8 unknown93;
/* 94 */ uint8 jam_fest;
/* 95 */ uint8 unknown95;
/* 96 */ uint8 unknown96;
// ===== Monk =====
/* 97 */ uint8 critical_mend;
/* 98 */ uint8 purify_body;
/* 99 */ uint8 unknown99;
/* 100 */ uint8 rapid_feign;
/* 101 */ uint8 return_kick;
// ===== Rogue =====
/* 102 */ uint8 escape;
/* 103 */ uint8 poison_mastery;
/* 104 */ uint8 double_riposte; // all "riposte" users
/* 105 */ uint8 unknown105;
/* 106 */ uint8 unknown106;
/* 107 */ uint8 purge_poison; // rogue
// ===== Warrior =====
/* 108 */ uint8 flurry;
/* 109 */ uint8 rampage;
/* 110 */ uint8 area_taunt;
/* 111 */ uint8 warcry;
/* 112 */ uint8 bandage_wound;
// ===== (Other) =====
/* 113 */ uint8 spell_casting_reinforcement_mastery; // all "pure" casters
/* 114 */ uint8 unknown114;
/* 115 */ uint8 extended_notes; // bard
/* 116 */ uint8 dragon_punch; // monk
/* 117 */ uint8 strong_root; // wizard
/* 118 */ uint8 singing_mastery; // bard
/* 119 */ uint8 body_and_mind_rejuvenation; // paladin, ranger, bard
/* 120 */ uint8 physical_enhancement; // paladin, ranger, bard
/* 121 */ uint8 adv_trap_negotiation; // rogue, bard
/* 122 */ uint8 acrobatics; // all "safe-fall" users
/* 123 */ uint8 scribble_notes; // bard
/* 124 */ uint8 chaotic_stab; // rogue
/* 125 */ uint8 pet_discipline; // all pet classes except enchanter
/* 126 */ uint8 unknown126;
/* 127 */ uint8 unknown127;
} named;
} class_skills;
};
Edit: had a 15 where a 14 should have been. now it's all correct data above.