- Fix #528 - Support for DoF Advancement Window!
* Restrictions based on rule R_Player, TraitTieringSelection = 1, limits to 1 trait selection per group, 0 allows 'free' selection much like newer EQ2 * Racial Traditions and Personal Traits available, Training and Enemy Tactics need content - Fix #472 - Spell damage now has resist added to reduce damage. Resistability support, info struct now has float "max_spell_reduction" and int8 "max_spell_reduction_override". Use override to set manually the resistability. Otherwise uses table for max resistability based on level - Fix #456 - Parital support for NPC Knockback, challenge is the updates are not using delta properly, but they do fly! - Fixed /follow for DoF client - Fixed multiple crashes in adding a trait - Spell book should no longer have type 4 spells (not shown spells) - Spell book issue addressed where innate abilities would wipe out the spell book - Fixed situations on login where HP/Power would not regen since you were not added to the damaged spawns - Implemented a workaround to get all items to appear in inventory for DoF client upon zoning *does not resolve evac/escape - Fixed Spawn info struct, we were not passing spell_effects properly for DoF client **Be sure to check the db file may2024_classictraits_personalandracial.sql and note it has a static max item id 10204351 that may need to be changed in the future if you insert it later
This commit is contained in:
parent
8639e5a7ed
commit
69612e08b6
20 changed files with 1153 additions and 108 deletions
237
DB/updates/may2024_classictraits_personalandracial.sql
Normal file
237
DB/updates/may2024_classictraits_personalandracial.sql
Normal file
|
@ -0,0 +1,237 @@
|
|||
alter table spell_traits add column item_id int(10) unsigned not null default 0;
|
||||
alter table spell_traits add column is_active tinyint(1) unsigned not null default 1;
|
||||
alter table spell_traits add column insert_id int(10) not null default 0;
|
||||
update spell_traits set is_active=0;
|
||||
|
||||
insert into spell_traits set level=8,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=0,isFocusEffect=1,spell_id=1000196;
|
||||
insert into spell_traits set level=8,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=0,isFocusEffect=1,spell_id=1002091;
|
||||
insert into spell_traits set level=8,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=0,isFocusEffect=1,spell_id=1000520;
|
||||
insert into spell_traits set level=8,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=0,isFocusEffect=1,spell_id=1001879;
|
||||
insert into spell_traits set level=8,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=0,isFocusEffect=1,spell_id=1000288;
|
||||
insert into spell_traits set level=14,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=1,isFocusEffect=1,spell_id=1001768;
|
||||
insert into spell_traits set level=14,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=1,isFocusEffect=1,spell_id=1000300;
|
||||
insert into spell_traits set level=14,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=1,isFocusEffect=1,spell_id=1002936;
|
||||
insert into spell_traits set level=14,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=1,isFocusEffect=1,spell_id=1001841;
|
||||
insert into spell_traits set level=14,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=1,isFocusEffect=1,spell_id=1001890;
|
||||
insert into spell_traits set level=22,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=2,isFocusEffect=1,spell_id=1002730;
|
||||
insert into spell_traits set level=22,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=2,isFocusEffect=1,spell_id=1001678;
|
||||
insert into spell_traits set level=22,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=2,isFocusEffect=1,spell_id=1001794;
|
||||
insert into spell_traits set level=22,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=2,isFocusEffect=1,spell_id=1000240;
|
||||
insert into spell_traits set level=28,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=3,isFocusEffect=1,spell_id=1002067;
|
||||
insert into spell_traits set level=28,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=3,isFocusEffect=1,spell_id=1002656;
|
||||
insert into spell_traits set level=28,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=3,isFocusEffect=1,spell_id=1000585;
|
||||
insert into spell_traits set level=28,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=3,isFocusEffect=1,spell_id=1001268;
|
||||
insert into spell_traits set level=28,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=3,isFocusEffect=1,spell_id=1002458;
|
||||
insert into spell_traits set level=36,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=4,isFocusEffect=1,spell_id=1002383;
|
||||
insert into spell_traits set level=36,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=4,isFocusEffect=1,spell_id=1001412;
|
||||
insert into spell_traits set level=36,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=4,isFocusEffect=1,spell_id=1001706;
|
||||
insert into spell_traits set level=36,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=4,isFocusEffect=1,spell_id=1002278;
|
||||
insert into spell_traits set level=36,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=4,isFocusEffect=1,spell_id=1002962;
|
||||
insert into spell_traits set level=42,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=5,isFocusEffect=1,spell_id=1002689;
|
||||
insert into spell_traits set level=42,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=5,isFocusEffect=1,spell_id=1000254;
|
||||
insert into spell_traits set level=42,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=5,isFocusEffect=1,spell_id=1002660;
|
||||
insert into spell_traits set level=42,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=5,isFocusEffect=1,spell_id=1001962;
|
||||
insert into spell_traits set level=46,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=6,isFocusEffect=1,spell_id=1002807;
|
||||
insert into spell_traits set level=46,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=6,isFocusEffect=1,spell_id=1001422;
|
||||
insert into spell_traits set level=46,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=6,isFocusEffect=1,spell_id=1002379;
|
||||
insert into spell_traits set level=46,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=6,isFocusEffect=1,spell_id=1002363;
|
||||
insert into spell_traits set level=46,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=6,isFocusEffect=1,spell_id=1000454;
|
||||
insert into spell_traits set level=48,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=7,isFocusEffect=1,spell_id=1002221;
|
||||
insert into spell_traits set level=48,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=7,isFocusEffect=1,spell_id=1000418;
|
||||
insert into spell_traits set level=48,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=7,isFocusEffect=1,spell_id=1002384;
|
||||
insert into spell_traits set level=48,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=7,isFocusEffect=1,spell_id=1002923;
|
||||
insert into spell_traits set level=48,class_req=255,race_req=255,isTrait=1,isInate=1,tier=1,`group`=7,isFocusEffect=1,spell_id=1000203;
|
||||
|
||||
|
||||
#barbarian racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550454;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550455;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550456;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550457;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550458;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550459;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550460;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1000202;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001806;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=0,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550461;
|
||||
|
||||
|
||||
#dark elf racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550109;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550118;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550464;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550114;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550117;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550115;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550113;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550111;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550112;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=1,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550116;
|
||||
|
||||
|
||||
#dwarf racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550281;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550475;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550280;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550287;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550283;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550282;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550286;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550284;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550476;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=2,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550285;
|
||||
|
||||
#erudite racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550311;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550295;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550301;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550299;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550309;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550298;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550296;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550294;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550300;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=3,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550293;
|
||||
|
||||
|
||||
#froglok is race_req 4 we got nothing!
|
||||
|
||||
#gnome racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1000031;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001418;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550496;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001697;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1000268;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550497;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550498;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550499;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550500;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=5,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550501;
|
||||
|
||||
#half elf racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550109;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=1002991;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=1002992;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550278;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002779;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1000120;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001731;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550463;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550464;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=6,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550465;
|
||||
|
||||
#halfling racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550467;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550468;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002088;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550469;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550470;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550471;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002137;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550472;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550473;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=7,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001907;
|
||||
|
||||
#high elf racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550109;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001734;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550248;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550262;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550246;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002779;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550261;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550251;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001730;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=8,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550253;
|
||||
|
||||
#human racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550483;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550484;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550485;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550486;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1000293;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=1002991;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=80025;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550487;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550463;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550213;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=9,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550488;
|
||||
|
||||
#iksar racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550502;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550489;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=1002280;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002950;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1000378;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550503;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550504;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001942;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550505;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=10,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550506;
|
||||
|
||||
#kerra racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550129;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550139;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550466;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550133;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550128;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001733;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002797;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002797;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550127;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=11,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550143;
|
||||
|
||||
|
||||
#ogre racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550474;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550079;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550086;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550084;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550082;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550078;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550088;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550081;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550087;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=12,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550085;
|
||||
|
||||
#ratonga racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002754;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550477;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550478;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550479;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002201;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001884;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550480;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550336;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550481;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=13,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550482;
|
||||
|
||||
#troll racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550489;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550490;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002835;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002010;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550491;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550492;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550493;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001985;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550494;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=14,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550495;
|
||||
|
||||
#wood elf racials
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550109;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550277;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550462;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1001731;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550273;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550507;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550508;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=2550275;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=0,tier=1,`group`=0,spell_id=2550274;
|
||||
insert into spell_traits set level=0,class_req=255,race_req=15,isTrait=0,isInate=1,tier=1,`group`=0,spell_id=1002926;
|
||||
|
||||
update spell_traits set insert_id = id;
|
||||
|
||||
insert into items ( skill_id_req, id, bPvpDesc, name, item_type, icon, developer_notes, count, tier, description, show_name ) select distinct(st.spell_id), st.insert_id+10204351, 1, s.name, 'Scroll', 75, 'test trait', 0, 1, trim(replace(s.description, '\n', '')), 1 from spell_traits as st inner join spells as s on s.id = st.spell_id;
|
||||
|
||||
update spell_traits set item_id = insert_id + 10204351;
|
|
@ -762,6 +762,7 @@ int8 Entity::DetermineHit(Spawn* victim, int8 type, int8 damage_type, float ToHi
|
|||
if(lua_spell->spell->GetSpellData()->resistibility > 0)
|
||||
bonus -= (1.0f - lua_spell->spell->GetSpellData()->resistibility)*100.0f;
|
||||
|
||||
LogWrite(COMBAT__DEBUG, 9, "Combat", "SpellResist: resistibility %f, bonus %f", lua_spell->spell->GetSpellData()->resistibility, bonus);
|
||||
// Here we take into account Subjugation, Disruption and Ordination (debuffs)
|
||||
if(lua_spell->spell->GetSpellData()->mastery_skill) {
|
||||
int32 master_skill_reduce = rule_manager.GetGlobalRule(R_Spells, MasterSkillReduceSpellResist)->GetInt32();
|
||||
|
@ -781,6 +782,8 @@ int8 Entity::DetermineHit(Spawn* victim, int8 type, int8 damage_type, float ToHi
|
|||
item_stat_bonus = GetStat(item_stat);
|
||||
}
|
||||
bonus += (master_skill->current_val + item_stat_bonus) / master_skill_reduce;
|
||||
LogWrite(COMBAT__DEBUG, 9, "Combat", "SpellResistMasterySkill: skill %u, stat bonus %f, mastery skill reduce %u, bonus %f", master_skill->current_val, item_stat_bonus, master_skill_reduce, bonus);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,13 +791,17 @@ int8 Entity::DetermineHit(Spawn* victim, int8 type, int8 damage_type, float ToHi
|
|||
|
||||
if (victim->IsEntity())
|
||||
bonus -= ((Entity*)victim)->GetDamageTypeResistPercentage(damage_type);
|
||||
|
||||
LogWrite(COMBAT__DEBUG, 9, "Combat", "DamageResistPercent: type %u, bonus %f", damage_type, bonus);
|
||||
|
||||
|
||||
Entity* entity_victim = (Entity*)victim;
|
||||
float chance = 80 + bonus; //80% base chance that the victim will get hit (plus bonus)
|
||||
sint16 roll_chance = 100;
|
||||
if(skill)
|
||||
roll_chance -= skill->current_val / 25;
|
||||
roll_chance -= skill->current_val / 10;
|
||||
|
||||
LogWrite(COMBAT__DEBUG, 9, "Combat", "Chance: fchance %f, roll_chance %i", chance, roll_chance);
|
||||
|
||||
if(!is_caster_spell){ // melee or range attack
|
||||
skill = GetSkillByName("Offense", true); //add this skill for NPCs
|
||||
|
@ -875,7 +882,9 @@ int8 Entity::DetermineHit(Spawn* victim, int8 type, int8 damage_type, float ToHi
|
|||
else{
|
||||
skill = entity_victim->GetSkillByName("Spell Avoidance", true);
|
||||
if(skill)
|
||||
chance -= skill->current_val / 25;
|
||||
chance -= skill->current_val / 10;
|
||||
|
||||
LogWrite(COMBAT__DEBUG, 9, "Combat", "SpellAvoidChance: fchance %f", chance);
|
||||
if(rand()%roll_chance >= chance) {
|
||||
return DAMAGE_PACKET_RESULT_RESIST; //successfully resisted
|
||||
}
|
||||
|
@ -1821,8 +1830,21 @@ sint32 Entity::CalculateDamageAmount(Spawn* target, sint32 damage, int8 base_typ
|
|||
damage = CalculateFormulaByStat(damage, ITEM_STAT_SPELL_DAMAGE);
|
||||
}
|
||||
|
||||
if(base_type == DAMAGE_PACKET_TYPE_SPELL_DAMAGE)
|
||||
if(base_type == DAMAGE_PACKET_TYPE_SPELL_DAMAGE) {
|
||||
damage = CalculateFormulaByStat(damage, ITEM_STAT_SPELL_AND_COMBAT_ART_DAMAGE);
|
||||
|
||||
if(target && target->IsEntity() && damage > 0) {
|
||||
int16 effective_level_attacker = GetInfoStruct()->get_effective_level() != 0 ? GetInfoStruct()->get_effective_level() : GetLevel();
|
||||
float resistBase = ((Entity*)target)->GetDamageTypeResistPercentage(damage_type);
|
||||
if(resistBase > 1.0f) {
|
||||
float dmgReduction = ((Entity*)target)->CalculateSpellDamageReduction((float)damage, resistBase - 1.0f, effective_level_attacker);
|
||||
float newDamage = static_cast<float>(damage) - dmgReduction;
|
||||
if(newDamage < 0.0f)
|
||||
newDamage = 0.0f;
|
||||
damage = static_cast<sint32>(std::floor(newDamage));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// combat abilities only bonus
|
||||
if(damage_type <= DAMAGE_PACKET_DAMAGE_TYPE_PIERCE)
|
||||
|
@ -1868,4 +1890,14 @@ int32 Entity::CalculateFormulaByStat(int32 value, int16 stat) {
|
|||
|
||||
int32 Entity::CalculateFormulaBonus(int32 value, float percent_bonus) {
|
||||
return (int32)((float)value * ((percent_bonus / 100.0f) + 1.0f));
|
||||
}
|
||||
|
||||
float Entity::CalculateSpellDamageReduction(float spellDamage, float resistancePercentage, int16 attackerLevel) {
|
||||
int16 effective_level = GetInfoStruct()->get_effective_level() != 0 ? GetInfoStruct()->get_effective_level() : GetLevel();
|
||||
float levelDifference = std::abs(effective_level - attackerLevel);
|
||||
float logFactor = 1.0f / (1.0f + 0.1f * levelDifference); // Adjust the factor for smoother reduction
|
||||
|
||||
// Calculate the actual damage reduction based on resistance percentage, logarithmic factor, and maximum reduction
|
||||
float reducedDamage = spellDamage * (1.0f - resistancePercentage) * logFactor * GetInfoStruct()->get_max_spell_reduction();
|
||||
return reducedDamage;
|
||||
}
|
|
@ -5743,27 +5743,57 @@ void Commands::Command_AcceptAdvancement(Client* client, Seperator* sep)
|
|||
{
|
||||
Player *player = client->GetPlayer();
|
||||
if (sep && sep->IsSet(0)) {
|
||||
TraitData* trait = master_trait_list.GetTrait(atoul(sep->arg[0]));
|
||||
int32 trait_id = atoul(sep->arg[0]);
|
||||
TraitData* trait = nullptr;
|
||||
if(client->GetVersion() <= 547) {
|
||||
trait = master_trait_list.GetTraitByItemID(trait_id);
|
||||
}
|
||||
else {
|
||||
trait = master_trait_list.GetTrait(trait_id);
|
||||
}
|
||||
|
||||
if(!trait) {
|
||||
LogWrite(COMMAND__ERROR, 0, "Command", "Invalid accept advancement of trait %u, no trait found.", trait_id);
|
||||
return; // not valid lets not crash!
|
||||
}
|
||||
|
||||
if(!master_trait_list.IsPlayerAllowedTrait(client, trait)) {
|
||||
client->SimpleMessage(CHANNEL_COLOR_RED, "Not enough trait points to accept trait.");
|
||||
return;
|
||||
}
|
||||
// Check to see if this is a trait or grandmaster training (traits are always new spells, training is always upgrades)
|
||||
if (!player->HasSpell(trait->spellID, 0, true))
|
||||
{
|
||||
Spell* spell = master_spell_list.GetSpell(trait->spellID, trait->tier);
|
||||
player->AddSpellBookEntry(trait->spellID, trait->tier, player->GetFreeSpellBookSlot(spell->GetSpellData()->spell_book_type), spell->GetSpellData()->spell_book_type, spell->GetSpellData()->linked_timer, true);
|
||||
if(spell) {
|
||||
player->AddSpellBookEntry(trait->spellID, trait->tier, player->GetFreeSpellBookSlot(spell->GetSpellData()->spell_book_type), spell->GetSpellData()->spell_book_type, spell->GetSpellData()->linked_timer, true);
|
||||
}
|
||||
else {
|
||||
client->Message(CHANNEL_COLOR_RED, "ERROR! Trait is not a valid spell id %u may be disabled.", trait->spellID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Spell* spell = master_spell_list.GetSpell(trait->spellID, trait->tier);
|
||||
int8 old_slot = player->GetSpellSlot(spell->GetSpellID());
|
||||
player->RemoveSpellBookEntry(spell->GetSpellID());
|
||||
player->AddSpellBookEntry(spell->GetSpellID(), spell->GetSpellTier(), old_slot, spell->GetSpellData()->spell_book_type, spell->GetSpellData()->linked_timer, true);
|
||||
player->UnlockSpell(spell);
|
||||
client->SendSpellUpdate(spell);
|
||||
if(spell) {
|
||||
int8 old_slot = player->GetSpellSlot(spell->GetSpellID());
|
||||
player->RemoveSpellBookEntry(spell->GetSpellID());
|
||||
player->AddSpellBookEntry(spell->GetSpellID(), spell->GetSpellTier(), old_slot, spell->GetSpellData()->spell_book_type, spell->GetSpellData()->linked_timer, true);
|
||||
player->UnlockSpell(spell);
|
||||
client->SendSpellUpdate(spell);
|
||||
}
|
||||
else {
|
||||
client->Message(CHANNEL_COLOR_RED, "ERROR! Trait is not a valid spell id %u may be disabled.", trait->spellID);
|
||||
}
|
||||
}
|
||||
|
||||
// Spell book update
|
||||
client->QueuePacket(player->GetSpellBookUpdatePacket(client->GetVersion()));
|
||||
client->QueuePacket(master_trait_list.GetTraitListPacket(client));
|
||||
|
||||
if(client->GetVersion() <= 547) {
|
||||
master_trait_list.ChooseNextTrait(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10705,6 +10735,19 @@ void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {
|
|||
client->GetCurrentZone()->SendHealPacket(client->GetPlayer(), client->GetPlayer()->GetTarget() ? client->GetPlayer()->GetTarget() : client->GetPlayer(),
|
||||
atoul(sep->arg[1]), atoul(sep->arg[2]), "TestSpell");
|
||||
}
|
||||
else if(atoi(sep->arg[0]) == 34 && sep->IsNumber(1) && sep->IsNumber(2)) {
|
||||
PacketStruct* packet = configReader.getStruct("WS_QuestRewardPackMsg", client->GetVersion());
|
||||
packet->setSubstructDataByName("reward_data", "unknown1", atoi(sep->arg[1]));
|
||||
Item* item = master_item_list.GetItem(atoul(sep->arg[2]));
|
||||
if(item) {
|
||||
packet->setSubstructArrayLengthByName("reward_data", "num_select_rewards", 1);
|
||||
packet->setArrayDataByName("select_reward_id", item->details.item_id, 0);
|
||||
packet->setItemArrayDataByName("select_item", item, client->GetPlayer(), 0, 0, -1);
|
||||
}
|
||||
|
||||
client->QueuePacket(packet->serialize());
|
||||
safe_delete(packet);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PacketStruct* packet2 = configReader.getStruct("WS_ExamineSpellInfo", client->GetVersion());
|
||||
|
|
|
@ -371,6 +371,9 @@ void Entity::MapInfoStruct()
|
|||
|
||||
get_string_funcs["action_state"] = l::bind(&InfoStruct::get_action_state, &info_struct);
|
||||
get_string_funcs["combat_action_state"] = l::bind(&InfoStruct::get_combat_action_state, &info_struct);
|
||||
|
||||
get_float_funcs["max_spell_reduction"] = l::bind(&InfoStruct::get_max_spell_reduction, &info_struct);
|
||||
get_int8_funcs["max_spell_reduction_override"] = l::bind(&InfoStruct::get_max_spell_reduction_override, &info_struct);
|
||||
|
||||
/** SETS **/
|
||||
set_string_funcs["name"] = l::bind(&InfoStruct::set_name, &info_struct, l::_1);
|
||||
|
@ -575,6 +578,8 @@ void Entity::MapInfoStruct()
|
|||
set_string_funcs["action_state"] = l::bind(&InfoStruct::set_action_state, &info_struct, l::_1);
|
||||
set_string_funcs["combat_action_state"] = l::bind(&InfoStruct::set_combat_action_state, &info_struct, l::_1);
|
||||
|
||||
set_float_funcs["max_spell_reduction"] = l::bind(&InfoStruct::set_max_spell_reduction, &info_struct, l::_1);
|
||||
set_int8_funcs["max_spell_reduction_override"] = l::bind(&InfoStruct::set_max_spell_reduction_override, &info_struct, l::_1);
|
||||
}
|
||||
|
||||
bool Entity::HasMoved(bool include_heading){
|
||||
|
@ -1404,6 +1409,8 @@ void Entity::CalculateBonuses(){
|
|||
|
||||
int16 effective_level = info->get_effective_level() != 0 ? info->get_effective_level() : GetLevel();
|
||||
|
||||
CalculateMaxReduction();
|
||||
|
||||
info->set_block(info->get_block_base());
|
||||
|
||||
info->set_cur_attack(info->get_attack_base());
|
||||
|
@ -3947,4 +3954,28 @@ void Entity::TerminateTrade() {
|
|||
tmpTradePtr->CancelTrade(this);
|
||||
safe_delete(tmpTradePtr);
|
||||
}
|
||||
}
|
||||
|
||||
void Entity::CalculateMaxReduction() {
|
||||
if(GetInfoStruct()->get_max_spell_reduction_override()) {
|
||||
return; // override enabled, don't touch the max reduction
|
||||
}
|
||||
int16 effective_level = GetInfoStruct()->get_effective_level() != 0 ? GetInfoStruct()->get_effective_level() : GetLevel();
|
||||
// Define thresholds and corresponding maximum reduction factors
|
||||
const int thresholds[] = {1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120}; // Thresholds for level differences
|
||||
const float maxReductions[] = {0.2f, 0.2f, 0.15f, 0.15f, 0.1f,0.1f,0.1f,0.1f,0.1f,0.075f,0.075f,0.075f,0.05f,0.05f,0.05f,0.05f,0.05f,0.05f,0.045f,0.045f,0.045f,0.045f,0.045f,0.045f,0.045f}; // Maximum reduction factors for each threshold
|
||||
int numThresholds = sizeof(thresholds) / sizeof(thresholds[0]);
|
||||
|
||||
// Find the appropriate maximum reduction factor based on level difference
|
||||
float maxReduction = .1f; // Default maximum reduction factor
|
||||
for (int i = 0; i < numThresholds; ++i) {
|
||||
if (effective_level >= thresholds[i]) {
|
||||
maxReduction = maxReductions[i];
|
||||
}
|
||||
else {
|
||||
break; // No need to check further
|
||||
}
|
||||
}
|
||||
|
||||
GetInfoStruct()->set_max_spell_reduction(maxReduction);
|
||||
}
|
|
@ -291,6 +291,10 @@ struct InfoStruct{
|
|||
assist_auto_attack_ = 0;
|
||||
|
||||
action_state_ = std::string("");
|
||||
combat_action_state_ = std::string("");
|
||||
|
||||
max_spell_reduction_ = .1f;
|
||||
max_spell_reduction_override_ = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -483,7 +487,19 @@ struct InfoStruct{
|
|||
|
||||
action_state_ = oldStruct->get_action_state();
|
||||
combat_action_state_ = oldStruct->get_combat_action_state();
|
||||
|
||||
|
||||
group_loot_method_ = oldStruct->get_group_loot_method();
|
||||
group_loot_items_rarity_ = oldStruct->get_group_loot_items_rarity();
|
||||
group_auto_split_ = oldStruct->get_group_auto_split();
|
||||
group_default_yell_ = oldStruct->get_group_default_yell();
|
||||
group_autolock_ = oldStruct->get_group_autolock();
|
||||
group_lock_method_ = oldStruct->get_group_lock_method();
|
||||
group_solo_autolock_ = oldStruct->get_group_solo_autolock();
|
||||
group_auto_loot_method_ = oldStruct->get_group_auto_loot_method();
|
||||
assist_auto_attack_ = oldStruct->get_assist_auto_attack();
|
||||
|
||||
max_spell_reduction_ = oldStruct->get_max_spell_reduction();
|
||||
max_spell_reduction_override_ = oldStruct->get_max_spell_reduction_override();
|
||||
}
|
||||
//mutable std::shared_mutex mutex_;
|
||||
std::string get_name() { std::lock_guard<std::mutex> lk(classMutex); return name_; }
|
||||
|
@ -706,6 +722,9 @@ struct InfoStruct{
|
|||
|
||||
std::string get_combat_action_state() { std::lock_guard<std::mutex> lk(classMutex); return combat_action_state_; }
|
||||
|
||||
float get_max_spell_reduction() { std::lock_guard<std::mutex> lk(classMutex); return max_spell_reduction_; }
|
||||
int8 get_max_spell_reduction_override() { std::lock_guard<std::mutex> lk(classMutex); return max_spell_reduction_override_; }
|
||||
|
||||
void set_name(std::string value) { std::lock_guard<std::mutex> lk(classMutex); name_ = value; }
|
||||
|
||||
void set_deity(std::string value) { std::lock_guard<std::mutex> lk(classMutex); deity_ = value; }
|
||||
|
@ -1014,6 +1033,10 @@ struct InfoStruct{
|
|||
|
||||
void set_combat_action_state(std::string value) { std::lock_guard<std::mutex> lk(classMutex); combat_action_state_ = value; }
|
||||
|
||||
void set_max_spell_reduction(float value) { std::lock_guard<std::mutex> lk(classMutex); max_spell_reduction_ = value; }
|
||||
|
||||
void set_max_spell_reduction_override(int8 value) { std::lock_guard<std::mutex> lk(classMutex); max_spell_reduction_override_ = value; }
|
||||
|
||||
void ResetEffects(Spawn* spawn)
|
||||
{
|
||||
for(int i=0;i<45;i++){
|
||||
|
@ -1237,6 +1260,9 @@ private:
|
|||
std::string action_state_;
|
||||
std::string combat_action_state_;
|
||||
|
||||
float max_spell_reduction_;
|
||||
int8 max_spell_reduction_override_;
|
||||
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex classMutex;
|
||||
};
|
||||
|
@ -1927,6 +1953,7 @@ public:
|
|||
bool SetInfoStructSInt(std::string field, sint64 value);
|
||||
bool SetInfoStructFloat(std::string field, float value);
|
||||
|
||||
float CalculateSpellDamageReduction(float spellDamage, int16 competitorLevel);
|
||||
sint32 CalculateHateAmount(Spawn* target, sint32 amt);
|
||||
sint32 CalculateHealAmount(Spawn* target, sint32 amt, int8 crit_mod, bool* crit, bool skip_crit_mod = false);
|
||||
sint32 CalculateDamageAmount(Spawn* target, sint32 damage, int8 base_type, int8 damage_type, LuaSpell* spell);
|
||||
|
@ -1934,6 +1961,7 @@ public:
|
|||
sint32 CalculateFormulaByStat(sint32 value, int16 stat);
|
||||
int32 CalculateFormulaByStat(int32 value, int16 stat);
|
||||
int32 CalculateFormulaBonus(int32 value, float percent_bonus);
|
||||
float CalculateSpellDamageReduction(float spellDamage, float resistancePercentage, int16 attackerLevel);
|
||||
|
||||
float GetStat(int32 item_stat) {
|
||||
float item_chance_or_skill = 0.0f;
|
||||
|
@ -2013,6 +2041,8 @@ public:
|
|||
}
|
||||
|
||||
void TerminateTrade();
|
||||
|
||||
void CalculateMaxReduction();
|
||||
// when PacketStruct is fixed for C++17 this should become a shared_mutex and handle read/write lock
|
||||
std::mutex MEquipment;
|
||||
std::mutex MStats;
|
||||
|
|
|
@ -3528,6 +3528,10 @@ bool PlayerItemList::MoveItem(sint32 to_bag_id, int16 from_index, sint8 to, int8
|
|||
}
|
||||
|
||||
EQ2Packet* PlayerItemList::serialize(Player* player, int16 version){
|
||||
bool firstRun = false;
|
||||
if(!packet_count) {
|
||||
firstRun = true;
|
||||
}
|
||||
EQ2Packet* app = 0;
|
||||
PacketStruct* packet = configReader.getStruct("WS_UpdateInventory",version);
|
||||
Item* item = 0;
|
||||
|
@ -3535,8 +3539,12 @@ EQ2Packet* PlayerItemList::serialize(Player* player, int16 version){
|
|||
if(packet && indexed_items.size() > 0){
|
||||
int8 packet_size = 0;
|
||||
int16 size = indexed_items.size();
|
||||
if (overflowItems.size() > 0)
|
||||
if (!firstRun && overflowItems.size() > 0)
|
||||
size++;
|
||||
|
||||
if(size > 20 && firstRun) {
|
||||
size = 20;
|
||||
}
|
||||
PacketStruct* packet2 = configReader.getStruct("Substruct_Item", version);
|
||||
packet_size = packet2->GetTotalPacketSize();
|
||||
safe_delete(packet2);
|
||||
|
@ -3567,11 +3575,17 @@ EQ2Packet* PlayerItemList::serialize(Player* player, int16 version){
|
|||
if(item && item->details.new_item)
|
||||
new_index++;
|
||||
|
||||
if(firstRun && i > 19) {
|
||||
item->details.new_item = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item && item->details.item_id > 0)
|
||||
AddItemToPacket(packet, player, item, i, false, new_index);
|
||||
|
||||
}
|
||||
|
||||
if (overflowItems.size() > 0) {
|
||||
if (!firstRun && overflowItems.size() > 0) {
|
||||
// We have overflow items, lets get the first one
|
||||
item = overflowItems.at(0);
|
||||
// Lets make sure the item is valid
|
||||
|
|
|
@ -750,6 +750,25 @@ struct ItemAppearance{
|
|||
int8 highlight_green;
|
||||
int8 highlight_blue;
|
||||
};
|
||||
|
||||
enum AddItemType {
|
||||
NOT_SET = 0,
|
||||
BUY_FROM_BROKER = 1,
|
||||
GM_COMMAND = 2
|
||||
};
|
||||
|
||||
struct QuestRewardData {
|
||||
int32 quest_id;
|
||||
bool is_temporary;
|
||||
std::string description;
|
||||
bool is_collection;
|
||||
bool has_displayed;
|
||||
int64 tmp_coin;
|
||||
int32 tmp_status;
|
||||
bool db_saved;
|
||||
int32 db_index;
|
||||
};
|
||||
|
||||
class PlayerItemList;
|
||||
class Item{
|
||||
public:
|
||||
|
|
|
@ -8611,21 +8611,26 @@ int EQ2Emu_lua_Knockback(lua_State* state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (spawn->IsPlayer() && (vertical != 0 || horizontal != 0)) {
|
||||
Client* client = ((Player*)spawn)->GetClient();
|
||||
PacketStruct* packet = configReader.getStruct("WS_PlayerKnockback", client->GetVersion());
|
||||
if (packet) {
|
||||
packet->setDataByName("target_x", target_spawn->GetX());
|
||||
packet->setDataByName("target_y", target_spawn->GetY());
|
||||
packet->setDataByName("target_z", target_spawn->GetZ());
|
||||
packet->setDataByName("vertical_movement", vertical);
|
||||
packet->setDataByName("horizontal_movement", horizontal);
|
||||
if (use_heading)
|
||||
packet->setDataByName("use_player_heading", 1);
|
||||
if ((vertical != 0 || horizontal != 0)) {
|
||||
if(spawn->IsPlayer()) {
|
||||
Client* client = ((Player*)spawn)->GetClient();
|
||||
PacketStruct* packet = configReader.getStruct("WS_PlayerKnockback", client->GetVersion());
|
||||
if (packet) {
|
||||
packet->setDataByName("target_x", target_spawn->GetX());
|
||||
packet->setDataByName("target_y", target_spawn->GetY());
|
||||
packet->setDataByName("target_z", target_spawn->GetZ());
|
||||
packet->setDataByName("vertical_movement", vertical);
|
||||
packet->setDataByName("horizontal_movement", horizontal);
|
||||
if (use_heading)
|
||||
packet->setDataByName("use_player_heading", 1);
|
||||
|
||||
client->QueuePacket(packet->serialize());
|
||||
client->QueuePacket(packet->serialize());
|
||||
}
|
||||
safe_delete(packet);
|
||||
}
|
||||
else {
|
||||
spawn->SetKnockback(target_spawn, duration, vertical, horizontal);
|
||||
}
|
||||
safe_delete(packet);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -122,6 +122,13 @@ Player::Player(){
|
|||
all_spells_locked = false;
|
||||
current_language_id = 0;
|
||||
active_reward = false;
|
||||
|
||||
SortedTraitList = new map <int8, map <int8, vector<TraitData*> > >;
|
||||
ClassTraining = new map <int8, vector<TraitData*> >;
|
||||
RaceTraits = new map <int8, vector<TraitData*> >;
|
||||
InnateRaceTraits = new map <int8, vector<TraitData*> >;
|
||||
FocusEffects = new map <int8, vector<TraitData*> >;
|
||||
need_trait_update = true;
|
||||
}
|
||||
Player::~Player(){
|
||||
SetSaveSpellEffects(true);
|
||||
|
@ -204,6 +211,11 @@ Player::~Player(){
|
|||
ClearPendingItemRewards();
|
||||
ClearEverything();
|
||||
|
||||
safe_delete(SortedTraitList);
|
||||
safe_delete(ClassTraining);
|
||||
safe_delete(RaceTraits);
|
||||
safe_delete(InnateRaceTraits);
|
||||
safe_delete(FocusEffects);
|
||||
// leak fix on Language* pointer from Player::AddLanguage
|
||||
player_languages_list.Clear();
|
||||
}
|
||||
|
@ -2509,7 +2521,7 @@ int16 Player::GetSpellSlotMappingCount(){
|
|||
MSpellsBook.lock();
|
||||
for(int32 i=0;i<spells.size();i++){
|
||||
SpellBookEntry* spell = (SpellBookEntry*)spells[i];
|
||||
if(spell->slot >= 0 && spell->spell_id > 0)
|
||||
if(spell->slot >= 0 && spell->spell_id > 0 && spell->type != SPELL_BOOK_TYPE_NOT_SHOWN)
|
||||
ret++;
|
||||
}
|
||||
MSpellsBook.unlock();
|
||||
|
@ -2535,7 +2547,7 @@ int16 Player::GetSpellPacketCount(){
|
|||
MSpellsBook.lock();
|
||||
for(int32 i=0;i<spells.size();i++){
|
||||
SpellBookEntry* spell = (SpellBookEntry*)spells[i];
|
||||
if(spell->spell_id > 0)
|
||||
if(spell->spell_id > 0 && spell->type != SPELL_BOOK_TYPE_NOT_SHOWN)
|
||||
ret++;
|
||||
}
|
||||
MSpellsBook.unlock();
|
||||
|
@ -2852,7 +2864,7 @@ EQ2Packet* Player::GetSpellSlotMappingPacket(int16 version){
|
|||
MSpellsBook.lock();
|
||||
for(int32 i=0;i<spells.size();i++){
|
||||
SpellBookEntry* spell = (SpellBookEntry*)spells[i];
|
||||
if(spell->slot < 0 || spell->spell_id == 0)
|
||||
if(spell->type == SPELL_BOOK_TYPE_NOT_SHOWN || spell->slot < 0 || spell->spell_id == 0)
|
||||
continue;
|
||||
packet->setArrayDataByName("spell_id", spell->spell_id, ptr);
|
||||
packet->setArrayDataByName("slot_id", (int16)spell->slot, ptr);
|
||||
|
@ -2903,7 +2915,7 @@ EQ2Packet* Player::GetSpellBookUpdatePacket(int16 version) {
|
|||
MSpellsBook.lock();
|
||||
for (int32 i = 0; i < spells.size(); i++) {
|
||||
spell_entry = (SpellBookEntry*)spells[i];
|
||||
if (spell_entry->spell_id == 0)
|
||||
if (spell_entry->spell_id == 0 || spell_entry->type == SPELL_BOOK_TYPE_NOT_SHOWN)
|
||||
continue;
|
||||
spell = master_spell_list.GetSpell(spell_entry->spell_id, spell_entry->tier);
|
||||
if (spell) {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "Titles.h"
|
||||
#include "Languages.h"
|
||||
#include "Achievements/Achievements.h"
|
||||
#include "Traits/Traits.h"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
|
@ -244,18 +245,6 @@ struct SpawnQueueState {
|
|||
int16 index_id;
|
||||
};
|
||||
|
||||
struct QuestRewardData {
|
||||
int32 quest_id;
|
||||
bool is_temporary;
|
||||
std::string description;
|
||||
bool is_collection;
|
||||
bool has_displayed;
|
||||
int64 tmp_coin;
|
||||
int32 tmp_status;
|
||||
bool db_saved;
|
||||
int32 db_index;
|
||||
};
|
||||
|
||||
class PlayerLoginAppearance {
|
||||
public:
|
||||
PlayerLoginAppearance() { appearanceList = new map<int8, LoginAppearances>; }
|
||||
|
@ -435,12 +424,6 @@ private:
|
|||
Mutex MFlagChanges;
|
||||
};
|
||||
|
||||
enum AddItemType {
|
||||
NOT_SET = 0,
|
||||
BUY_FROM_BROKER = 1,
|
||||
GM_COMMAND = 2
|
||||
};
|
||||
|
||||
class Player : public Entity{
|
||||
public:
|
||||
Player();
|
||||
|
@ -1093,6 +1076,14 @@ public:
|
|||
void ProcessSpawnRangeUpdates();
|
||||
Mutex MPlayerQuests;
|
||||
float pos_packet_speed;
|
||||
|
||||
map <int8, map <int8, vector<TraitData*> > >* SortedTraitList;
|
||||
map <int8, vector<TraitData*> >* ClassTraining;
|
||||
map <int8, vector<TraitData*> >* RaceTraits;
|
||||
map <int8, vector<TraitData*> >* InnateRaceTraits;
|
||||
map <int8, vector<TraitData*> >* FocusEffects;
|
||||
mutable std::shared_mutex trait_mutex;
|
||||
std::atomic<bool> need_trait_update;
|
||||
private:
|
||||
bool reset_mentorship;
|
||||
bool range_attack;
|
||||
|
|
|
@ -227,6 +227,12 @@ void RuleManager::Init()
|
|||
RULE_INIT(R_Player, CoinWeightPerStone, "40.0"); // coin weight per stone, 40.0 = 40 coins per 1 stone (per DoF client hover over)
|
||||
RULE_INIT(R_Player, WeightInflictsSpeed, "1"); // whether weight will inflict speed, 1 = on, 0 = off
|
||||
RULE_INIT(R_Player, LevelMasterySkillMultiplier, "5"); // multiplier for adventure level / recommended level when applying mastery damage to determine if they are in mastery range
|
||||
RULE_INIT(R_Player, TraitTieringSelection, "1"); // when set to true limited to single trait per group, otherwise you can freely select from any group
|
||||
RULE_INIT(R_Player, ClassicTraitLevelTable, "1"); // uses built in table based on Prima Guide, see Traits.cpp for more, otherwise uses the levels below
|
||||
RULE_INIT(R_Player, TraitFocusSelectLevel, "9"); // x levels to receive new trait of focus, eg level/rule, level 10, rule value 5, 10/5 = 2 focus traits available at level 10
|
||||
RULE_INIT(R_Player, TraitTrainingSelectLevel, "10"); // x levels to receive new trait of focus
|
||||
RULE_INIT(R_Player, TraitRaceSelectLevel, "10"); // x levels to receive new trait of focus
|
||||
RULE_INIT(R_Player, TraitCharacterSelectLevel, "10"); // x levels to receive new trait of focus
|
||||
|
||||
/* PVP */
|
||||
RULE_INIT(R_PVP, AllowPVP, "0");
|
||||
|
|
|
@ -87,6 +87,12 @@ enum RuleType {
|
|||
CoinWeightPerStone,
|
||||
WeightInflictsSpeed,
|
||||
LevelMasterySkillMultiplier,
|
||||
TraitTieringSelection,
|
||||
ClassicTraitLevelTable,
|
||||
TraitFocusSelectLevel,
|
||||
TraitTrainingSelectLevel,
|
||||
TraitRaceSelectLevel,
|
||||
TraitCharacterSelectLevel,
|
||||
|
||||
/* PVP */
|
||||
AllowPVP,
|
||||
|
|
|
@ -148,6 +148,7 @@ Spawn::Spawn(){
|
|||
is_loot_complete = false;
|
||||
is_loot_dispensed = false;
|
||||
reset_movement = false;
|
||||
ResetKnockedBack();
|
||||
}
|
||||
|
||||
Spawn::~Spawn(){
|
||||
|
@ -522,7 +523,6 @@ EQ2Packet* Spawn::spawn_serialize(Player* player, int16 version, int16 offset, i
|
|||
|
||||
pos_struct->ResetData();
|
||||
InitializePosPacketData(player, pos_struct);
|
||||
|
||||
if (version <= 283) {
|
||||
if (offset == 777) {
|
||||
info_struct->setDataByName("name", "This is a really long name\n");
|
||||
|
@ -2091,7 +2091,13 @@ void Spawn::InitializePosPacketData(Player* player, PacketStruct* packet, bool b
|
|||
m_GridMutex.releasewritelock(__FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
packet->setDataByName("pos_grid_id", new_grid_id != 0 ? new_grid_id : GetLocation());
|
||||
if(IsKnockedBack()) {
|
||||
packet->setDataByName("pos_grid_id", 0);
|
||||
}
|
||||
else {
|
||||
packet->setDataByName("pos_grid_id", new_grid_id != 0 ? new_grid_id : GetLocation());
|
||||
}
|
||||
|
||||
bool include_heading = true;
|
||||
if (IsWidget() && ((Widget*)this)->GetIncludeHeading() == false)
|
||||
include_heading = false;
|
||||
|
@ -2274,7 +2280,6 @@ void Spawn::InitializePosPacketData(Player* player, PacketStruct* packet, bool b
|
|||
}
|
||||
|
||||
|
||||
|
||||
if (IsNPC() || IsPlayer()) {
|
||||
packet->setDataByName("pos_move_type", 25);
|
||||
}
|
||||
|
@ -2284,7 +2289,7 @@ void Spawn::InitializePosPacketData(Player* player, PacketStruct* packet, bool b
|
|||
else if(IsGroundSpawn()) {
|
||||
packet->setDataByName("pos_move_type", 16);
|
||||
}
|
||||
|
||||
|
||||
if (!IsPlayer()) // has to be 2 or NPC's warp around when moving
|
||||
packet->setDataByName("pos_movement_mode", 2);
|
||||
|
||||
|
@ -2437,7 +2442,6 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
|
|||
packet->setDataByName("mood_state", appearance.mood_state);
|
||||
packet->setDataByName("gender", appearance.gender);
|
||||
packet->setDataByName("race", appearance.race);
|
||||
packet->setDataByName("gender", appearance.gender);
|
||||
if (IsEntity()) {
|
||||
Entity* entity = ((Entity*)this);
|
||||
packet->setDataByName("combat_voice", entity->GetCombatVoice());
|
||||
|
@ -2740,7 +2744,10 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
|
|||
*/
|
||||
if (IsPlayer()) {
|
||||
if (((Player*)this)->GetFollowTarget())
|
||||
packet->setDataByName("follow_target", ((((Player*)this)->GetIDWithPlayerSpawn(((Player*)this)->GetFollowTarget()) * -1) - 1));
|
||||
packet->setDataByName("follow_target", version <= 547 ? (((Player*)this)->GetIDWithPlayerSpawn(((Player*)this)->GetFollowTarget())) : ((((Player*)this)->GetIDWithPlayerSpawn(((Player*)this)->GetFollowTarget()) * -1) - 1));
|
||||
else if(version <= 547) {
|
||||
packet->setDataByName("follow_target", 0xFFFFFFFF);
|
||||
}
|
||||
//else
|
||||
// packet->setDataByName("follow_target", 0xFFFFFFFF);
|
||||
}
|
||||
|
@ -2872,6 +2879,12 @@ void Spawn::ProcessMovement(bool isSpawnListLocked){
|
|||
}*/
|
||||
return;
|
||||
}
|
||||
|
||||
if(IsKnockedBack()) {
|
||||
if(CalculateSpawnProjectilePosition(GetX(), GetY(), GetZ()))
|
||||
return; // being launched!
|
||||
}
|
||||
|
||||
if(reset_movement) {
|
||||
ResetMovement();
|
||||
reset_movement = false;
|
||||
|
@ -4170,7 +4183,7 @@ void Spawn::FixZ(bool forceUpdate) {
|
|||
uint32 WidgetID = 0;
|
||||
float new_z = GetY();
|
||||
if(GetMap() != nullptr) {
|
||||
float new_z = FindBestZ(current_loc, nullptr, &GridID, &WidgetID);
|
||||
new_z = FindBestZ(current_loc, nullptr, &GridID, &WidgetID);
|
||||
|
||||
if ((IsTransportSpawn() || !IsFlyingCreature()) && GridID != 0 && GridID != GetLocation()) {
|
||||
LogWrite(PLAYER__DEBUG, 0, "Player", "%s left grid %u and entered grid %u", appearance.name, GetLocation(), GridID);
|
||||
|
@ -5056,4 +5069,125 @@ void Spawn::DistributeGroupLoot_RoundRobin(std::vector<int32>* item_list, bool r
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const double g = 9.81; // acceleration due to gravity (m/s^2)
|
||||
|
||||
void Spawn::CalculateInitialVelocity(float heading, float distanceHorizontal, float distanceVertical, float distanceDepth, float duration) {
|
||||
float vx = distanceHorizontal / duration;
|
||||
float vy = (distanceVertical + 0.5 * g * duration * duration) / duration;
|
||||
float vz = distanceDepth / duration;
|
||||
|
||||
// Convert heading angle to radians
|
||||
knocked_velocity.x = vx * cos(heading);
|
||||
knocked_velocity.y = vy;
|
||||
knocked_velocity.z = vz * sin(heading);
|
||||
}
|
||||
|
||||
// Function to calculate the projectile position at a given time
|
||||
glm::vec3 Spawn::CalculateProjectilePosition(glm::vec3 initialVelocity, float time) {
|
||||
glm::vec3 position;
|
||||
|
||||
position.x = knocked_back_start_x + initialVelocity.x * time;
|
||||
position.y = knocked_back_start_y + initialVelocity.y * time - 0.5 * g * time * time;
|
||||
position.z = knocked_back_start_z + initialVelocity.z * time;
|
||||
|
||||
auto loc = glm::vec3(position.x, position.z, position.y);
|
||||
float new_z = FindBestZ(loc, nullptr);
|
||||
if(new_z > position.y)
|
||||
position.y = new_z;
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
bool Spawn::CalculateSpawnProjectilePosition(float x, float y, float z) {
|
||||
float currentTimeOffset = (Timer::GetCurrentTime2() - last_movement_update) * 0.001; // * 0.001 is the same as / 1000, float muliplications is suppose to be faster though
|
||||
float stepAheadOne = currentTimeOffset+currentTimeOffset;
|
||||
|
||||
knocked_back_time_step += currentTimeOffset;
|
||||
if(Timer::GetCurrentTime2() >= knocked_back_end_time) {
|
||||
ResetKnockedBack();
|
||||
FixZ(true);
|
||||
return false;
|
||||
}
|
||||
glm::vec3 position = CalculateProjectilePosition(knocked_velocity, knocked_back_time_step);
|
||||
glm::vec3 position_two = position;
|
||||
|
||||
if(Timer::GetCurrentTime2() <= knocked_back_end_time+stepAheadOne) {
|
||||
position_two = CalculateProjectilePosition(knocked_velocity, knocked_back_time_step+stepAheadOne);
|
||||
}
|
||||
|
||||
if(GetMap()) {
|
||||
glm::vec3 loc(GetX(), GetZ(), GetY() + .5f);
|
||||
glm::vec3 dest_loc(position_two.x, position_two.z, position_two.y);
|
||||
MIgnoredWidgets.lock_shared();
|
||||
glm::vec3 outNorm;
|
||||
float dist = 0.0f;
|
||||
bool collide_ = GetMap()->DoCollisionCheck(loc, dest_loc, &ignored_widgets, outNorm, dist);
|
||||
if(collide_) {
|
||||
LogWrite(SPAWN__ERROR, 0, "Spawn", "Collision Hit: cur loc x,y,z: %f %f %f. to loc %f %f %f. TimeOffset: %f Total Time: %f Duration: %f", GetX(),GetY(),GetZ(),position_two.x,position_two.y,position_two.z, currentTimeOffset, knocked_back_time_step, knocked_back_duration);
|
||||
MIgnoredWidgets.unlock_shared();
|
||||
ResetKnockedBack();
|
||||
FixZ(true);
|
||||
return false;
|
||||
}
|
||||
MIgnoredWidgets.unlock_shared();
|
||||
}
|
||||
|
||||
LogWrite(SPAWN__ERROR, 0, "Spawn", "x,y,z: %f %f %f. Final %f %f %f. TimeOffset: %f Total Time: %f Duration: %f", GetX(),GetY(),GetZ(),position.x,position.y,position.z, currentTimeOffset, knocked_back_time_step, knocked_back_duration);
|
||||
|
||||
SetX(position.x, false);
|
||||
SetZ(position.z, false);
|
||||
SetY(position.y, false, true);
|
||||
|
||||
SetPos(&appearance.pos.X2, position_two.x, false);
|
||||
SetPos(&appearance.pos.Z2, position_two.z, false);
|
||||
SetPos(&appearance.pos.Y2, position_two.y, false);
|
||||
SetPos(&appearance.pos.X3, position_two.x, false);
|
||||
SetPos(&appearance.pos.Z3, position_two.z, false);
|
||||
SetPos(&appearance.pos.Y3, position_two.y, false);
|
||||
|
||||
position_changed = true;
|
||||
changed = true;
|
||||
GetZone()->AddChangedSpawn(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Spawn::SetKnockback(Spawn* target, int32 duration, float vertical, float horizontal) {
|
||||
if(knocked_back) {
|
||||
return; // already being knocked back
|
||||
}
|
||||
|
||||
// Calculate the direction vector from source to destination
|
||||
glm::vec3 direction = {GetX() - target->GetX(), GetZ() - target->GetZ(), GetY() - target->GetY()};
|
||||
|
||||
// Calculate the heading angle in radians
|
||||
double headingRad = atan2(direction.y, sqrt(direction.x * direction.x + direction.z * direction.z));
|
||||
|
||||
knocked_angle = headingRad;
|
||||
knocked_back_start_x = GetX();
|
||||
knocked_back_start_y = GetY();
|
||||
knocked_back_start_z = GetZ();
|
||||
knocked_back_h_distance = horizontal / 10.0f;
|
||||
knocked_back_v_distance = vertical / 10.0f;
|
||||
knocked_back_duration = static_cast<float>(duration) / 1000.0f;
|
||||
knocked_back_end_time = Timer::GetCurrentTime2() + duration;
|
||||
CalculateInitialVelocity(knocked_angle, knocked_back_h_distance, knocked_back_h_distance, knocked_back_h_distance, knocked_back_duration);
|
||||
knocked_back = true;
|
||||
}
|
||||
|
||||
void Spawn::ResetKnockedBack() {
|
||||
knocked_back = false;
|
||||
knocked_back_time_step = 0.0f;
|
||||
knocked_back_h_distance = 0.0f;
|
||||
knocked_back_v_distance = 0.0f;
|
||||
knocked_back_duration = 0.0f;
|
||||
knocked_back_end_time = 0;
|
||||
knocked_back_start_x = 0.0f;
|
||||
knocked_back_start_y = 0.0f;
|
||||
knocked_back_start_z = 0.0f;
|
||||
knocked_angle = 0.0f;
|
||||
knocked_velocity.x = 0.0f;
|
||||
knocked_velocity.y = 0.0f;
|
||||
knocked_velocity.z = 0.0f;
|
||||
}
|
|
@ -1383,6 +1383,12 @@ public:
|
|||
bool IsItemInLootTier(Item* item);
|
||||
void DistributeGroupLoot_RoundRobin(std::vector<int32>* item_list, bool roundRobinTrashLoot = false); // trash loot is what falls under the item tier requirement by group options
|
||||
|
||||
void CalculateInitialVelocity(float heading, float distanceHorizontal, float distanceVertical, float distanceDepth, float duration);
|
||||
glm::vec3 CalculateProjectilePosition(glm::vec3 initialVelocity, float time);
|
||||
bool CalculateSpawnProjectilePosition(float x, float y, float z);
|
||||
void SetKnockback(Spawn* target, int32 duration, float vertical, float horizontal);
|
||||
void ResetKnockedBack();
|
||||
|
||||
mutable std::shared_mutex MIgnoredWidgets;
|
||||
std::map<int32, bool> ignored_widgets;
|
||||
|
||||
|
@ -1429,6 +1435,7 @@ protected:
|
|||
void CheckProximities();
|
||||
Timer pause_timer;
|
||||
|
||||
bool IsKnockedBack() { return knocked_back; }
|
||||
private:
|
||||
int32 loot_group_id;
|
||||
GroupLootMethod loot_method;
|
||||
|
@ -1517,6 +1524,18 @@ private:
|
|||
bool is_collector;
|
||||
bool scared_by_strong_players;
|
||||
std::atomic<bool> is_alive;
|
||||
std::atomic<bool> knocked_back;
|
||||
float knocked_back_time_step;
|
||||
float knocked_back_h_distance;
|
||||
float knocked_back_v_distance;
|
||||
float knocked_back_duration;
|
||||
float knocked_back_start_x;
|
||||
float knocked_back_start_y;
|
||||
float knocked_back_start_z;
|
||||
int32 knocked_back_end_time;
|
||||
float knocked_angle;
|
||||
glm::vec3 knocked_velocity;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -980,7 +980,7 @@ bool SpellProcess::CheckSpellQueue(Spell* spell, Entity* caster){
|
|||
}
|
||||
|
||||
void SpellProcess::SendSpellBookUpdate(Client* client){
|
||||
if(client){
|
||||
if(client && client->IsReadyForSpawns()){
|
||||
EQ2Packet* app = client->GetPlayer()->GetSpellBookUpdatePacket(client->GetVersion());
|
||||
if(app)
|
||||
client->QueuePacket(app);
|
||||
|
|
|
@ -23,11 +23,18 @@ along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "../../common/Log.h"
|
||||
#include "../Spells.h"
|
||||
#include "../WorldDatabase.h"
|
||||
#include "../client.h"
|
||||
#include "../Rules/Rules.h"
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
extern ConfigReader configReader;
|
||||
extern MasterSpellList master_spell_list;
|
||||
extern WorldDatabase database;
|
||||
extern RuleManager rule_manager;
|
||||
|
||||
using namespace boost::assign;
|
||||
|
||||
MasterTraitList::MasterTraitList(){
|
||||
MMasterTraitList.SetName("MasterTraitList::TraitList");
|
||||
|
@ -47,46 +54,46 @@ int MasterTraitList::Size(){
|
|||
return TraitList.size();
|
||||
}
|
||||
|
||||
EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
||||
bool MasterTraitList::GenerateTraitLists(Client* client, map <int8, map <int8, vector<TraitData*> > >* sortedTraitList, map <int8, vector<TraitData*> >* classTraining,
|
||||
map <int8, vector<TraitData*> >* raceTraits, map <int8, vector<TraitData*> >* innateRaceTraits, map <int8, vector<TraitData*> >* focusEffects, int16 max_level, int8 trait_group)
|
||||
{
|
||||
if (!client) {
|
||||
LogWrite(SPELL__ERROR, 0, "Traits", "GetTraitListPacket called with an invalid client");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
// Sort the Data
|
||||
if (Size() == 0)
|
||||
return NULL;
|
||||
|
||||
map <int8, map <int8, vector<TraitData*> > > SortedTraitList;
|
||||
if (Size() == 0 || !sortedTraitList || !classTraining || !raceTraits || !innateRaceTraits || !focusEffects)
|
||||
return false;
|
||||
|
||||
map <int8, map <int8, vector<TraitData*> > >::iterator itr;
|
||||
map <int8, vector<TraitData*> >::iterator itr2;
|
||||
vector<TraitData*>::iterator itr3;
|
||||
|
||||
map <int8, vector<TraitData*> > ClassTraining;
|
||||
map <int8, vector<TraitData*> > RaceTraits;
|
||||
map <int8, vector<TraitData*> > InnateRaceTraits;
|
||||
map <int8, vector<TraitData*> > FocusEffects;
|
||||
|
||||
MMasterTraitList.readlock(__FUNCTION__, __LINE__);
|
||||
|
||||
for (int i=0; i < Size(); i++) {
|
||||
|
||||
if(max_level > 0 && TraitList[i]->level > max_level) {
|
||||
continue; // skip per max level requirement
|
||||
}
|
||||
if(trait_group != 255 && trait_group != TraitList[i]->group) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sort Character Traits
|
||||
if (TraitList[i]->classReq == 255 && TraitList[i]->raceReq == 255 && !TraitList[i]->isFocusEffect && TraitList[i]->isTrait) {
|
||||
|
||||
itr = SortedTraitList.lower_bound(TraitList[i]->group);
|
||||
if (itr != SortedTraitList.end() && !(SortedTraitList.key_comp()(TraitList[i]->group, itr->first))) {
|
||||
itr = sortedTraitList->lower_bound(TraitList[i]->group);
|
||||
if (itr != sortedTraitList->end() && !(sortedTraitList->key_comp()(TraitList[i]->group, itr->first))) {
|
||||
|
||||
itr2 = (itr->second).lower_bound(TraitList[i]->level);
|
||||
if (itr2 != (itr->second).end() && !((itr->second).key_comp()(TraitList[i]->level, itr2->first))) {
|
||||
((itr->second)[itr2->first]).push_back(TraitList[i]);
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Added Trait: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "Added Trait: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
}
|
||||
else {
|
||||
vector<TraitData*> tempVec;
|
||||
tempVec.push_back(TraitList[i]);
|
||||
(itr->second).insert(make_pair(TraitList[i]->level, tempVec));
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Added Trait: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "Added Trait: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -94,51 +101,55 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
vector <TraitData*> tempVec;
|
||||
tempVec.push_back(TraitList[i]);
|
||||
tempMap.insert(make_pair(TraitList[i]->level, tempVec));
|
||||
SortedTraitList.insert(make_pair(TraitList[i]->group, tempMap));
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Added Trait: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
sortedTraitList->insert(make_pair(TraitList[i]->group, tempMap));
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "Added Trait: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort Class Training
|
||||
if (TraitList[i]->classReq == client->GetPlayer()->GetAdventureClass() && TraitList[i]->isTraining) {
|
||||
itr2 = ClassTraining.lower_bound(TraitList[i]->level);
|
||||
if (itr2 != ClassTraining.end() && !(ClassTraining.key_comp()(TraitList[i]->level, itr2->first))) {
|
||||
itr2 = classTraining->lower_bound(TraitList[i]->level);
|
||||
if (itr2 != classTraining->end() && !(classTraining->key_comp()(TraitList[i]->level, itr2->first))) {
|
||||
(itr2->second).push_back(TraitList[i]);
|
||||
}
|
||||
else {
|
||||
vector<TraitData*> tempVec;
|
||||
tempVec.push_back(TraitList[i]);
|
||||
ClassTraining.insert(make_pair(TraitList[i]->level, tempVec));
|
||||
classTraining->insert(make_pair(TraitList[i]->level, tempVec));
|
||||
}
|
||||
}
|
||||
|
||||
// Sort Racial Abilities
|
||||
if (TraitList[i]->raceReq == client->GetPlayer()->GetRace() && !TraitList[i]->isInate && !TraitList[i]->isTraining) {
|
||||
itr2 = RaceTraits.lower_bound(TraitList[i]->group);
|
||||
if (itr2 != RaceTraits.end() && !(RaceTraits.key_comp()(TraitList[i]->group, itr2->first))) {
|
||||
itr2 = raceTraits->lower_bound(TraitList[i]->group);
|
||||
if (itr2 != raceTraits->end() && !(raceTraits->key_comp()(TraitList[i]->group, itr2->first))) {
|
||||
(itr2->second).push_back(TraitList[i]);
|
||||
}
|
||||
else {
|
||||
vector<TraitData*> tempVec;
|
||||
tempVec.push_back(TraitList[i]);
|
||||
RaceTraits.insert(make_pair(TraitList[i]->group, tempVec));
|
||||
raceTraits->insert(make_pair(TraitList[i]->group, tempVec));
|
||||
}
|
||||
}
|
||||
|
||||
// Sort Innate Racial Abilities
|
||||
if (TraitList[i]->raceReq == client->GetPlayer()->GetRace() && TraitList[i]->isInate) {
|
||||
itr2 = InnateRaceTraits.lower_bound(TraitList[i]->group);
|
||||
if (itr2 != InnateRaceTraits.end() && !(InnateRaceTraits.key_comp()(TraitList[i]->group, itr2->first))) {
|
||||
itr2 = innateRaceTraits->lower_bound(TraitList[i]->group);
|
||||
if (itr2 != innateRaceTraits->end() && !(innateRaceTraits->key_comp()(TraitList[i]->group, itr2->first))) {
|
||||
(itr2->second).push_back(TraitList[i]);
|
||||
}
|
||||
else {
|
||||
vector<TraitData*> tempVec;
|
||||
tempVec.push_back(TraitList[i]);
|
||||
InnateRaceTraits.insert(make_pair(TraitList[i]->group, tempVec));
|
||||
innateRaceTraits->insert(make_pair(TraitList[i]->group, tempVec));
|
||||
}
|
||||
}
|
||||
|
||||
// Sort Focus Effects
|
||||
if ((TraitList[i]->classReq == client->GetPlayer()->GetAdventureClass() || TraitList[i]->classReq == 255) && TraitList[i]->isFocusEffect) {
|
||||
int8 j = 0;
|
||||
itr2 = FocusEffects.lower_bound(TraitList[i]->group);
|
||||
if (itr2 != FocusEffects.end() && !(FocusEffects.key_comp()(TraitList[i]->group, itr2->first))) {
|
||||
itr2 = focusEffects->lower_bound(TraitList[i]->group);
|
||||
if (itr2 != focusEffects->end() && !(focusEffects->key_comp()(TraitList[i]->group, itr2->first))) {
|
||||
|
||||
(itr2->second).push_back(TraitList[i]);
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Added Focus Effect: %u Tier: %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
|
@ -147,14 +158,413 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
else {
|
||||
vector<TraitData*> tempVec;
|
||||
tempVec.push_back(TraitList[i]);
|
||||
FocusEffects.insert(make_pair(TraitList[i]->group, tempVec));
|
||||
focusEffects->insert(make_pair(TraitList[i]->group, tempVec));
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Added Focus Effect: %u Tier %i", TraitList[i]->spellID, TraitList[i]->tier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MMasterTraitList.releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MasterTraitList::IdentifyNextTrait(Client* client, map <int8, vector<TraitData*> >* traitList, vector<TraitData*>* collectTraits, vector<TraitData*>* tieredTraits, std::map<int32, int8>* previousMatchedSpells, bool omitFoundMatches) {
|
||||
bool found_spell_match = false;
|
||||
bool match = false;
|
||||
bool tiered_selection = rule_manager.GetGlobalRule(R_Player, TraitTieringSelection)->GetBool();
|
||||
int8 group_to_apply = 255;
|
||||
int8 count = 0;
|
||||
map <int8, vector<TraitData*> >::iterator itr2;
|
||||
vector<TraitData*>::iterator itr3;
|
||||
|
||||
for (itr2 = traitList->begin(); itr2 != traitList->end(); itr2++) {
|
||||
//LogWrite(SPELL__INFO, 0, "AA", "Character Traits Size...%i ", traits_size);
|
||||
for (itr3 = itr2->second.begin(); itr3 != itr2->second.end(); itr3++) {
|
||||
if(tiered_selection) {
|
||||
if(found_spell_match && (*itr3)->group == group_to_apply) {
|
||||
continue; // skip!
|
||||
}
|
||||
else if((*itr3)->group != group_to_apply) {
|
||||
if(group_to_apply != 255 && !found_spell_match) {
|
||||
// found match
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "Found match to group id %u", group_to_apply);
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "Try match to group... spell id %u, group id %u", (*itr3)->spellID, (*itr3)->group);
|
||||
found_spell_match = false;
|
||||
group_to_apply = (*itr3)->group;
|
||||
count = 0;
|
||||
if(!omitFoundMatches)
|
||||
tieredTraits->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
count++;
|
||||
|
||||
std::map<int32,int8>::iterator spell_itr = previousMatchedSpells->find((*itr3)->spellID);
|
||||
|
||||
if(spell_itr != previousMatchedSpells->end() && (*itr3)->group > spell_itr->second) {
|
||||
continue;
|
||||
}
|
||||
if(!IsPlayerAllowedTrait(client, (*itr3))) {
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "We are not allowed any more spells from this type/group... spell id %u, group id %u", (*itr3)->spellID, (*itr3)->group);
|
||||
found_spell_match = true;
|
||||
}
|
||||
else if (client->GetPlayer()->HasSpell((*itr3)->spellID, (*itr3)->tier)) {
|
||||
LogWrite(SPELL__INFO, 0, "Traits", "Found existing spell match to group... spell id %u, group id %u", (*itr3)->spellID, (*itr3)->group);
|
||||
if(!omitFoundMatches)
|
||||
found_spell_match = true;
|
||||
previousMatchedSpells->insert(std::make_pair((*itr3)->spellID,(*itr3)->group));
|
||||
}
|
||||
else {
|
||||
tieredTraits->push_back((*itr3));
|
||||
collectTraits->push_back((*itr3));
|
||||
}
|
||||
}
|
||||
|
||||
if(match)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(!match && group_to_apply != 255 && !found_spell_match) {
|
||||
// found match
|
||||
match = true;
|
||||
}
|
||||
else if(!tiered_selection && collectTraits->size() > 0) {
|
||||
match = true;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
bool MasterTraitList::ChooseNextTrait(Client* client) {
|
||||
map <int8, map <int8, vector<TraitData*> > >* SortedTraitList = new map <int8, map <int8, vector<TraitData*> > >;
|
||||
map <int8, map <int8, vector<TraitData*> > >::iterator itr;
|
||||
bool tiered_selection = rule_manager.GetGlobalRule(R_Player, TraitTieringSelection)->GetBool();
|
||||
vector<TraitData*>::iterator itr3;
|
||||
|
||||
map <int8, vector<TraitData*> >* ClassTraining = new map <int8, vector<TraitData*> >;
|
||||
map <int8, vector<TraitData*> >* RaceTraits = new map <int8, vector<TraitData*> >;
|
||||
map <int8, vector<TraitData*> >* InnateRaceTraits = new map <int8, vector<TraitData*> >;
|
||||
map <int8, vector<TraitData*> >* FocusEffects = new map <int8, vector<TraitData*> >;
|
||||
vector<TraitData*>* collectTraits = new vector<TraitData*>;
|
||||
vector<TraitData*>* tieredTraits = new vector<TraitData*>;
|
||||
std::map<int32, int8>* previousMatchedSpells = new std::map<int32, int8>;
|
||||
bool match = false;
|
||||
if(GenerateTraitLists(client, SortedTraitList, ClassTraining, RaceTraits, InnateRaceTraits, FocusEffects, client->GetPlayer()->GetLevel())) {
|
||||
|
||||
vector<TraitData*>* endTraits;
|
||||
if(!match || !tiered_selection) {
|
||||
match = IdentifyNextTrait(client, ClassTraining, collectTraits, tieredTraits, previousMatchedSpells);
|
||||
}
|
||||
if(!match || !tiered_selection) {
|
||||
match = IdentifyNextTrait(client, RaceTraits, collectTraits, tieredTraits, previousMatchedSpells, true);
|
||||
|
||||
bool overrideMatch = IdentifyNextTrait(client, InnateRaceTraits, collectTraits, tieredTraits, previousMatchedSpells, true);
|
||||
|
||||
if(!match && overrideMatch)
|
||||
match = true;
|
||||
}
|
||||
if(!match || !tiered_selection) {
|
||||
match = IdentifyNextTrait(client, FocusEffects, collectTraits, tieredTraits, previousMatchedSpells);
|
||||
}
|
||||
|
||||
if(!tiered_selection && collectTraits->size() > 0) {
|
||||
endTraits = collectTraits;
|
||||
}
|
||||
else if (match) {
|
||||
endTraits = tieredTraits;
|
||||
}
|
||||
if(match) {
|
||||
PacketStruct* packet = configReader.getStruct("WS_QuestRewardPackMsg", client->GetVersion());
|
||||
// 0=enemy mastery, 1=specialized training,2=character trait, 3=racial tradition
|
||||
int8 packet_type = 0;
|
||||
int8 item_count = 0;
|
||||
packet->setSubstructArrayLengthByName("reward_data", "num_select_rewards", endTraits->size());
|
||||
for (itr3 = endTraits->begin(); itr3 != endTraits->end(); itr3++) {
|
||||
|
||||
if((*itr3)->item_id) {
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Item %u to be sent", (*itr3)->item_id);
|
||||
Item* item = master_item_list.GetItem((*itr3)->item_id);
|
||||
if(item) {
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Item found %s to be sent", item->name.c_str());
|
||||
packet->setArrayDataByName("select_reward_id", (*itr3)->item_id, item_count);
|
||||
packet->setItemArrayDataByName("select_item", item, client->GetPlayer(), item_count, 0, -1);
|
||||
item_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sort Character Traits
|
||||
if ((*itr3)->classReq == 255 && (*itr3)->raceReq == 255 && (*itr3)->isTrait) {
|
||||
packet_type = 2;
|
||||
}
|
||||
// Sort Class Training
|
||||
else if ((*itr3)->classReq == client->GetPlayer()->GetAdventureClass() && (*itr3)->isTraining) {
|
||||
packet_type = 1;
|
||||
}
|
||||
// Sort Racial Abilities
|
||||
else if ((*itr3)->raceReq == client->GetPlayer()->GetRace() && !(*itr3)->isInate && !(*itr3)->isTraining) {
|
||||
packet_type = 3;
|
||||
}
|
||||
// Sort Innate Racial Abilities
|
||||
else if ((*itr3)->raceReq == client->GetPlayer()->GetRace() && (*itr3)->isInate) {
|
||||
packet_type = 3;
|
||||
}
|
||||
|
||||
//LogWrite(SPELL__INFO, 0, "Traits", "Sending trait %u", (*itr3)->spellID);
|
||||
}
|
||||
packet->setSubstructDataByName("reward_data", "unknown1", packet_type);
|
||||
client->QueuePacket(packet->serialize());
|
||||
safe_delete(packet);
|
||||
}
|
||||
}
|
||||
|
||||
safe_delete(SortedTraitList);
|
||||
safe_delete(ClassTraining);
|
||||
safe_delete(RaceTraits);
|
||||
safe_delete(InnateRaceTraits);
|
||||
safe_delete(FocusEffects);
|
||||
|
||||
safe_delete(collectTraits);
|
||||
safe_delete(tieredTraits);
|
||||
safe_delete(previousMatchedSpells);
|
||||
return match;
|
||||
}
|
||||
|
||||
int16 MasterTraitList::GetSpellCount(Client* client, map <int8, vector<TraitData*> >* traits, bool onlyCharTraits) {
|
||||
if(!traits)
|
||||
return 0;
|
||||
|
||||
int16 count = 0;
|
||||
map <int8, vector<TraitData*> >::iterator itr2;
|
||||
vector<TraitData*>::iterator itr3;
|
||||
for (itr2 = traits->begin(); itr2 != traits->end(); itr2++) {
|
||||
for (itr3 = itr2->second.begin(); itr3 != itr2->second.end(); itr3++) {
|
||||
if (client->GetPlayer()->HasSpell((*itr3)->spellID, (*itr3)->tier)) {
|
||||
if(!onlyCharTraits || (onlyCharTraits && (*itr3)->classReq == 255 && (*itr3)->raceReq == 255 && (*itr3)->isTrait)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
vector<int16> PersonalTraitLevelLimits = boost::assign::list_of(0)(8)(14)(22)(28)(36)(42)(46)(48);
|
||||
vector<int16> TrainingTraitLevelLimits = boost::assign::list_of(0)(10)(20)(30)(40)(50);
|
||||
vector<int16> RacialTraitLevelLimits = boost::assign::list_of(0)(18)(26)(34)(44);
|
||||
vector<int16> CharacterTraitLevelLimits = boost::assign::list_of(0)(12)(16)(24)(32)(38);
|
||||
|
||||
/***
|
||||
Every other level, beginning at Level 8,
|
||||
you gain an additional advantage — a
|
||||
Personal Trait, an Enemy Tactic, a Racial
|
||||
Tradition or a Training ability. Each time
|
||||
you reach an even-numbered level, you
|
||||
can select another advantage from the
|
||||
appropriate list. You don’t have to select
|
||||
in order — you may take any of the avail-
|
||||
able choices.
|
||||
Level Advantage
|
||||
8 Personal Trait (1st)
|
||||
10 Training (1st)
|
||||
12 Enemy Tactic (1st)
|
||||
14 Personal Trait (2nd)
|
||||
16 Enemy Tactic (2nd)
|
||||
18 Racial Tradition (1st)
|
||||
20 Training (2nd)
|
||||
22 Personal Trait (3rd)
|
||||
24 Enemy Tactic (3rd)
|
||||
26 Racial Tradition (2nd)
|
||||
28 Personal Trait (4th)
|
||||
30 Training (3rd)
|
||||
32 Enemy Tactic (4th)
|
||||
34 Racial Tradition (3rd)
|
||||
36 Personal Trait (5th)
|
||||
38 Enemy Tactic (5th)
|
||||
40 Training (4th)
|
||||
42 Personal Trait (6th)
|
||||
44 Racial Tradition (4th)
|
||||
46 Personal Trait (7th)
|
||||
48 Personal Trait (8th)
|
||||
50 Training (5th)
|
||||
***/
|
||||
|
||||
bool MasterTraitList::IsPlayerAllowedTrait(Client* client, TraitData* trait) {
|
||||
std::unique_lock(client->GetPlayer()->trait_mutex);
|
||||
map <int8, map <int8, vector<TraitData*> > >* SortedTraitList = client->GetPlayer()->SortedTraitList;
|
||||
map <int8, map <int8, vector<TraitData*> > >::iterator itr;
|
||||
map <int8, vector<TraitData*> >::iterator itr2;
|
||||
vector<TraitData*>::iterator itr3;
|
||||
bool use_classic_table = rule_manager.GetGlobalRule(R_Player, ClassicTraitLevelTable)->GetBool();
|
||||
|
||||
map <int8, vector<TraitData*> >* ClassTraining = client->GetPlayer()->ClassTraining;
|
||||
map <int8, vector<TraitData*> >* RaceTraits = client->GetPlayer()->RaceTraits;
|
||||
map <int8, vector<TraitData*> >* InnateRaceTraits = client->GetPlayer()->InnateRaceTraits;
|
||||
map <int8, vector<TraitData*> >* FocusEffects = client->GetPlayer()->FocusEffects;
|
||||
if(client->GetPlayer()->need_trait_update) {
|
||||
SortedTraitList->clear();
|
||||
ClassTraining->clear();
|
||||
RaceTraits->clear();
|
||||
InnateRaceTraits->clear();
|
||||
FocusEffects->clear();
|
||||
}
|
||||
bool allowed_trait = false;
|
||||
if(!client->GetPlayer()->need_trait_update || GenerateTraitLists(client, SortedTraitList, ClassTraining, RaceTraits, InnateRaceTraits, FocusEffects, 0)) {
|
||||
client->GetPlayer()->need_trait_update = false;
|
||||
if(trait->isFocusEffect) {
|
||||
|
||||
int32 trait_level = rule_manager.GetGlobalRule(R_Player, TraitFocusSelectLevel)->GetInt32();
|
||||
int16 num_available_selections = 0;
|
||||
if(trait_level > 0) {
|
||||
num_available_selections = client->GetPlayer()->GetLevel() / trait_level;
|
||||
}
|
||||
int16 total_used = GetSpellCount(client, FocusEffects);
|
||||
|
||||
int16 classic_avail = 0;
|
||||
|
||||
if(use_classic_table && PersonalTraitLevelLimits.size() > total_used+1) {
|
||||
int16 classic_level_req = PersonalTraitLevelLimits.at(total_used+1);
|
||||
if(client->GetPlayer()->GetLevel() >= classic_level_req)
|
||||
classic_avail = num_available_selections = total_used+1;
|
||||
else
|
||||
num_available_selections = 0;
|
||||
}
|
||||
else if(use_classic_table)
|
||||
num_available_selections = 0;
|
||||
|
||||
LogWrite(SPELL__INFO, 9, "Traits", "%s FocusEffects used %u, available %u, classic available %u", client->GetPlayer()->GetName(), total_used, num_available_selections, classic_avail);
|
||||
if(total_used < num_available_selections) {
|
||||
allowed_trait = true;
|
||||
}
|
||||
}
|
||||
else if(trait->isTraining) {
|
||||
int32 trait_level = rule_manager.GetGlobalRule(R_Player, TraitTrainingSelectLevel)->GetInt32();
|
||||
int16 num_available_selections = 0;
|
||||
if(trait_level > 0) {
|
||||
num_available_selections = client->GetPlayer()->GetLevel() / trait_level;
|
||||
}
|
||||
int16 total_used = GetSpellCount(client, ClassTraining);
|
||||
|
||||
int16 classic_avail = 0;
|
||||
|
||||
if(use_classic_table && TrainingTraitLevelLimits.size() > total_used+1) {
|
||||
int16 classic_level_req = TrainingTraitLevelLimits.at(total_used+1);
|
||||
if(client->GetPlayer()->GetLevel() >= classic_level_req)
|
||||
classic_avail = num_available_selections = total_used+1;
|
||||
else
|
||||
num_available_selections = 0;
|
||||
}
|
||||
else if(use_classic_table)
|
||||
num_available_selections = 0;
|
||||
|
||||
LogWrite(SPELL__INFO, 9, "Traits", "%s ClassTraining used %u, available %u, classic available %u", client->GetPlayer()->GetName(), total_used, num_available_selections, classic_avail);
|
||||
if(total_used < num_available_selections) {
|
||||
allowed_trait = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(trait->raceReq == client->GetPlayer()->GetRace()) {
|
||||
int32 trait_level = rule_manager.GetGlobalRule(R_Player, TraitRaceSelectLevel)->GetInt32();
|
||||
int16 num_available_selections = 0;
|
||||
if(trait_level > 0) {
|
||||
num_available_selections = client->GetPlayer()->GetLevel() / trait_level;
|
||||
}
|
||||
int16 total_used = GetSpellCount(client, RaceTraits);
|
||||
int16 total_used2 = GetSpellCount(client, InnateRaceTraits);
|
||||
|
||||
int16 classic_avail = 0;
|
||||
|
||||
if(use_classic_table && RacialTraitLevelLimits.size() > total_used+total_used2+1) {
|
||||
int16 classic_level_req = RacialTraitLevelLimits.at(total_used+total_used2+1);
|
||||
if(client->GetPlayer()->GetLevel() >= classic_level_req)
|
||||
classic_avail = num_available_selections = total_used+total_used2+1;
|
||||
else
|
||||
num_available_selections = 0;
|
||||
}
|
||||
else if(use_classic_table)
|
||||
num_available_selections = 0;
|
||||
|
||||
LogWrite(SPELL__INFO, 9, "Traits", "%s RaceTraits used %u, available %u, classic available %u", client->GetPlayer()->GetName(), total_used+total_used2, num_available_selections, classic_avail);
|
||||
if(total_used+total_used2 < num_available_selections) {
|
||||
allowed_trait = true;
|
||||
}
|
||||
}
|
||||
else { // character trait?
|
||||
int16 num_available_selections = 0;
|
||||
int32 trait_level = rule_manager.GetGlobalRule(R_Player, TraitCharacterSelectLevel)->GetInt32();
|
||||
if(trait_level > 0) {
|
||||
num_available_selections = client->GetPlayer()->GetLevel() / trait_level;
|
||||
}
|
||||
int16 total_used = 0;
|
||||
for (itr = SortedTraitList->begin(); itr != SortedTraitList->end(); itr++) {
|
||||
total_used += GetSpellCount(client, &itr->second, true);
|
||||
}
|
||||
|
||||
int16 classic_avail = 0;
|
||||
|
||||
if(use_classic_table && CharacterTraitLevelLimits.size() > total_used+1) {
|
||||
int16 classic_level_req = CharacterTraitLevelLimits.at(total_used+1);
|
||||
if(client->GetPlayer()->GetLevel() >= classic_level_req)
|
||||
classic_avail = num_available_selections = total_used+1;
|
||||
else
|
||||
num_available_selections = 0;
|
||||
}
|
||||
else if(use_classic_table)
|
||||
num_available_selections = 0;
|
||||
|
||||
LogWrite(SPELL__INFO, 9, "Traits", "%s CharacterTraits used %u, available %u, classic available %u", client->GetPlayer()->GetName(), total_used, num_available_selections, classic_avail);
|
||||
if(total_used < num_available_selections) {
|
||||
allowed_trait = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allowed_trait;
|
||||
}
|
||||
|
||||
EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
||||
{
|
||||
std::unique_lock(client->GetPlayer()->trait_mutex);
|
||||
|
||||
if (!client) {
|
||||
LogWrite(SPELL__ERROR, 0, "Traits", "GetTraitListPacket called with an invalid client");
|
||||
return 0;
|
||||
}
|
||||
// Sort the Data
|
||||
if (Size() == 0)
|
||||
return NULL;
|
||||
|
||||
map <int8, map <int8, vector<TraitData*> > >* SortedTraitList = client->GetPlayer()->SortedTraitList;
|
||||
map <int8, map <int8, vector<TraitData*> > >::iterator itr;
|
||||
map <int8, vector<TraitData*> >::iterator itr2;
|
||||
vector<TraitData*>::iterator itr3;
|
||||
|
||||
map <int8, vector<TraitData*> >* ClassTraining = client->GetPlayer()->ClassTraining;
|
||||
map <int8, vector<TraitData*> >* RaceTraits = client->GetPlayer()->RaceTraits;
|
||||
map <int8, vector<TraitData*> >* InnateRaceTraits = client->GetPlayer()->InnateRaceTraits;
|
||||
map <int8, vector<TraitData*> >* FocusEffects = client->GetPlayer()->FocusEffects;
|
||||
|
||||
if(client->GetPlayer()->need_trait_update) {
|
||||
SortedTraitList->clear();
|
||||
ClassTraining->clear();
|
||||
RaceTraits->clear();
|
||||
InnateRaceTraits->clear();
|
||||
FocusEffects->clear();
|
||||
}
|
||||
|
||||
if(client->GetPlayer()->need_trait_update && !GenerateTraitLists(client, SortedTraitList, ClassTraining, RaceTraits, InnateRaceTraits, FocusEffects)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
client->GetPlayer()->need_trait_update = false;
|
||||
|
||||
int16 version = 1;
|
||||
int8 count = 0;
|
||||
int8 index = 0;
|
||||
|
@ -167,18 +577,19 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
version = client->GetVersion();
|
||||
|
||||
// Jabantiz: Get the value for num_traits in the struct (num_traits refers to the number of rows not the total number of traits)
|
||||
for (itr = SortedTraitList.begin(); itr != SortedTraitList.end(); itr++) {
|
||||
for (itr = SortedTraitList->begin(); itr != SortedTraitList->end(); itr++) {
|
||||
num_traits += (itr->second).size();
|
||||
}
|
||||
|
||||
PacketStruct* packet = configReader.getStruct("WS_TraitsList", version);
|
||||
|
||||
if (packet == NULL)
|
||||
if (packet == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
packet->setArrayLengthByName("num_traits", num_traits);
|
||||
|
||||
for (itr = SortedTraitList.begin(); itr != SortedTraitList.end(); itr++) {
|
||||
for (itr = SortedTraitList->begin(); itr != SortedTraitList->end(); itr++) {
|
||||
|
||||
for (itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++, index++) {
|
||||
traits_size += (itr2->second).size();
|
||||
|
@ -260,9 +671,9 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
}
|
||||
|
||||
// Class Training portion of the packet
|
||||
packet->setArrayLengthByName("num_trainings", ClassTraining.size());
|
||||
packet->setArrayLengthByName("num_trainings", ClassTraining->size());
|
||||
index = 0;
|
||||
for (itr2 = ClassTraining.begin(); itr2 != ClassTraining.end(); itr2++, index++) {
|
||||
for (itr2 = ClassTraining->begin(); itr2 != ClassTraining->end(); itr2++, index++) {
|
||||
count = 0;
|
||||
Spell* tmp_spell = 0;
|
||||
packet->setArrayDataByName("training_level", itr2->first, index);
|
||||
|
@ -345,11 +756,11 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
}
|
||||
}
|
||||
// Racial Traits
|
||||
packet->setArrayLengthByName("num_sections", RaceTraits.size());
|
||||
packet->setArrayLengthByName("num_sections", RaceTraits->size());
|
||||
index = 0;
|
||||
string tempStr;
|
||||
int8 num_selections = 0;
|
||||
for (itr2 = RaceTraits.begin(); itr2 != RaceTraits.end(); itr2++, index++) {
|
||||
for (itr2 = RaceTraits->begin(); itr2 != RaceTraits->end(); itr2++, index++) {
|
||||
count = 0;
|
||||
Spell* tmp_spell = 0;
|
||||
switch (itr2->first)
|
||||
|
@ -410,11 +821,11 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
|
||||
// total number of Innate traits
|
||||
num_traits = 0;
|
||||
for (itr2 = InnateRaceTraits.begin(); itr2 != InnateRaceTraits.end(); itr2++) {
|
||||
for (itr2 = InnateRaceTraits->begin(); itr2 != InnateRaceTraits->end(); itr2++) {
|
||||
num_traits += (itr2->second).size();
|
||||
}
|
||||
packet->setArrayLengthByName("num_abilities", num_traits);
|
||||
for (itr2 = InnateRaceTraits.begin(); itr2 != InnateRaceTraits.end(); itr2++) {
|
||||
for (itr2 = InnateRaceTraits->begin(); itr2 != InnateRaceTraits->end(); itr2++) {
|
||||
for (itr3 = itr2->second.begin(); itr3 != itr2->second.end(); itr3++, index++) {
|
||||
Spell* innate_spell = master_spell_list.GetSpell((*itr3)->spellID, (*itr3)->tier);
|
||||
if (innate_spell) {
|
||||
|
@ -433,11 +844,11 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
num_selections = 0;
|
||||
num_focuseffects = 0;
|
||||
index = 0;
|
||||
for (itr2 = FocusEffects.begin(); itr2 != FocusEffects.end(); itr2++) {
|
||||
for (itr2 = FocusEffects->begin(); itr2 != FocusEffects->end(); itr2++) {
|
||||
num_focuseffects += (itr2->second).size();
|
||||
}
|
||||
packet->setArrayLengthByName("num_focuseffects", num_focuseffects);
|
||||
for (itr2 = FocusEffects.begin(); itr2 != FocusEffects.end(); itr2++) {
|
||||
for (itr2 = FocusEffects->begin(); itr2 != FocusEffects->end(); itr2++) {
|
||||
for (itr3 = itr2->second.begin(); itr3 != itr2->second.end(); itr3++, index++) {
|
||||
Spell* spell = master_spell_list.GetSpell((*itr3)->spellID, (*itr3)->tier);
|
||||
if (client->GetPlayer()->HasSpell((*itr3)->spellID, (*itr3)->tier)) {
|
||||
|
@ -474,6 +885,7 @@ EQ2Packet* MasterTraitList::GetTraitListPacket (Client* client)
|
|||
//DumpPacket(outapp);
|
||||
safe_delete(packet);
|
||||
safe_delete(data);
|
||||
|
||||
return outapp;
|
||||
}
|
||||
|
||||
|
@ -494,6 +906,22 @@ TraitData* MasterTraitList::GetTrait(int32 spellID) {
|
|||
return data;
|
||||
}
|
||||
|
||||
TraitData* MasterTraitList::GetTraitByItemID(int32 itemID) {
|
||||
vector<TraitData*>::iterator itr;
|
||||
TraitData* data = NULL;
|
||||
|
||||
MMasterTraitList.readlock(__FUNCTION__, __LINE__);
|
||||
for (itr = TraitList.begin(); itr != TraitList.end(); itr++) {
|
||||
if ((*itr)->item_id == itemID) {
|
||||
data = (*itr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
MMasterTraitList.releasereadlock(__FUNCTION__, __LINE__);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void MasterTraitList::DestroyTraits(){
|
||||
MMasterTraitList.writelock(__FUNCTION__, __LINE__);
|
||||
vector<TraitData*>::iterator itr;
|
||||
|
|
|
@ -22,13 +22,16 @@ along with EQ2Emulator. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define __Traits__
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "../../common/Mutex.h"
|
||||
#include "../../common/types.h"
|
||||
#include "../../common/EQPacket.h"
|
||||
#include "../client.h"
|
||||
|
||||
class Client;
|
||||
|
||||
struct TraitData
|
||||
{
|
||||
int32 spellID ;
|
||||
int32 spellID;
|
||||
int8 level;
|
||||
int8 classReq;
|
||||
int8 raceReq;
|
||||
|
@ -38,6 +41,7 @@ struct TraitData
|
|||
bool isTraining;
|
||||
int8 tier;
|
||||
int8 group;
|
||||
int32 item_id;
|
||||
};
|
||||
|
||||
#define TRAITS_ATTRIBUTES 0
|
||||
|
@ -52,7 +56,14 @@ class MasterTraitList
|
|||
public:
|
||||
MasterTraitList();
|
||||
~MasterTraitList();
|
||||
|
||||
|
||||
bool IdentifyNextTrait(Client* client, map <int8, vector<TraitData*> >* traitList, vector<TraitData*>* collectTraits, vector<TraitData*>* tieredTraits, std::map<int32, int8>* previousMatchedSpells, bool omitFoundMatches = false);
|
||||
bool ChooseNextTrait(Client* client);
|
||||
int16 GetSpellCount(Client* client, map <int8, vector<TraitData*> >* traits, bool onlyCharTraits = false);
|
||||
bool IsPlayerAllowedTrait(Client* client, TraitData* trait);
|
||||
bool GenerateTraitLists(Client* client, map <int8, map <int8, vector<TraitData*> > >* sortedTraitList, map <int8, vector<TraitData*> >* classTraining,
|
||||
map <int8, vector<TraitData*> >* raceTraits, map <int8, vector<TraitData*> >* innateRaceTraits, map <int8, vector<TraitData*> >* focusEffects, int16 max_level = 0, int8 trait_group = 255);
|
||||
|
||||
/// <summary>Sorts the traits for the given client and creats and sends the trait packet.</summary>
|
||||
/// <param name='client'>The Client calling this function</param>
|
||||
/// <returns>EQ2Packet*</returns>
|
||||
|
@ -68,6 +79,10 @@ public:
|
|||
/// <summary>Get the trait data for the given spell.</summary>
|
||||
/// <param name='spellID'>Spell ID to get trait data for.</param>
|
||||
TraitData* GetTrait(int32 spellID);
|
||||
|
||||
/// <summary>Get the trait data for the given item.</summary>
|
||||
/// <param name='itemID'>Item ID to map to the trait data.</param>
|
||||
TraitData* GetTraitByItemID(int32 itemID);
|
||||
|
||||
/// <summary>Empties the master trait list</summary>
|
||||
void DestroyTraits();
|
||||
|
|
|
@ -4735,7 +4735,7 @@ void WorldDatabase::LoadTraits(){
|
|||
MYSQL_ROW row;
|
||||
TraitData* trait;
|
||||
|
||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT `spell_id`, `level`, `class_req`, `race_req`, `isTrait`,`isInate`, `isFocusEffect`, `isTraining`,`tier`, `group` FROM spell_traits");
|
||||
MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT `spell_id`, `level`, `class_req`, `race_req`, `isTrait`,`isInate`, `isFocusEffect`, `isTraining`,`tier`, `group`, `item_id` FROM spell_traits where is_active = 1");
|
||||
while (result && (row = mysql_fetch_row(result))){
|
||||
trait = new TraitData;
|
||||
int8 i = 0;
|
||||
|
@ -4749,6 +4749,7 @@ void WorldDatabase::LoadTraits(){
|
|||
trait->isTraining = (atoi(row[(++i)]) == 0) ? false : true;
|
||||
trait->tier = atoi(row[(++i)]);
|
||||
trait->group = atoi(row[(++i)]);
|
||||
trait->item_id = atoul(row[(++i)]);
|
||||
|
||||
master_trait_list.AddTrait(trait);
|
||||
}
|
||||
|
|
|
@ -1526,9 +1526,17 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
break;
|
||||
}
|
||||
case OP_DoneLoadingUIResourcesMsg: {
|
||||
if(GetVersion() < 546) {
|
||||
if(GetVersion() <= 547) {
|
||||
ClientPacketFunctions::SendUpdateSpellBook(this);
|
||||
}
|
||||
// need to quickly flash the DoF client the rest of their inventory
|
||||
if(GetVersion() <= 547) {
|
||||
EQ2Packet* item_app = player->GetPlayerItemList()->serialize(GetPlayer(), GetVersion());
|
||||
if (item_app) {
|
||||
QueuePacket(item_app);
|
||||
}
|
||||
}
|
||||
|
||||
EQ2Packet* app = new EQ2Packet(OP_DoneLoadingUIResourcesMsg, 0, 0);
|
||||
QueuePacket(app);
|
||||
if(!player_loading_complete)
|
||||
|
@ -1556,6 +1564,7 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
SetReadyForSpawns(true);
|
||||
player->CalculateApplyWeight();
|
||||
SendCharInfo();
|
||||
GetPlayer()->GetZone()->GetSpellProcess()->SendSpellBookUpdate(this);
|
||||
pos_update.Start();
|
||||
quest_pos_timer.Start();
|
||||
break;
|
||||
|
@ -1869,6 +1878,12 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
|
|||
player_pos_changed = true;
|
||||
GetPlayer()->AddChangedZoneSpawn();
|
||||
ProcessZoneIgnoreWidgets();
|
||||
if (version <= 547) {
|
||||
master_trait_list.ChooseNextTrait(this);
|
||||
}
|
||||
|
||||
if (GetPlayer()->GetHP() < GetPlayer()->GetTotalHP() || GetPlayer()->GetPower() < GetPlayer()->GetTotalPower())
|
||||
GetCurrentZone()->AddDamagedSpawn(GetPlayer());
|
||||
}
|
||||
else {
|
||||
LogWrite(CCLIENT__WARNING, 0, "Client", "Player %s reported SysClient/SignalMsg state %s.", GetPlayer()->GetName(), str.data.c_str());
|
||||
|
@ -5157,10 +5172,14 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
// Also need to force the char sheet update or else there can be a large delay from when you level
|
||||
// to when you are actually able to select traits.
|
||||
QueuePacket(GetPlayer()->GetPlayerInfo()->serialize(GetVersion()));
|
||||
QueuePacket(master_trait_list.GetTraitListPacket(this));
|
||||
|
||||
if (version > 546)
|
||||
GetPlayer()->need_trait_update = true;
|
||||
if (version > 547) {
|
||||
QueuePacket(master_trait_list.GetTraitListPacket(this));
|
||||
master_aa_list.DisplayAA(this, 0, 0);
|
||||
}
|
||||
else
|
||||
master_trait_list.ChooseNextTrait(this);
|
||||
|
||||
if (GetPlayer()->SpawnedBots.size() > 0) {
|
||||
map<int32, int32>::iterator itr;
|
||||
|
@ -5170,6 +5189,9 @@ void Client::ChangeLevel(int16 old_level, int16 new_level) {
|
|||
((Bot*)bot)->ChangeLevel(old_level, new_level);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetPlayer()->GetHP() < GetPlayer()->GetTotalHP() || GetPlayer()->GetPower() < GetPlayer()->GetTotalPower())
|
||||
GetPlayer()->GetZone()->AddDamagedSpawn(GetPlayer());
|
||||
}
|
||||
|
||||
void Client::ChangeTSLevel(int16 old_level, int16 new_level) {
|
||||
|
@ -9763,7 +9785,7 @@ void Client::SetReadyForUpdates() {
|
|||
|
||||
ready_for_updates = true;
|
||||
|
||||
if(GetVersion() <= 546) {
|
||||
if(GetVersion() <= 547) {
|
||||
SendRecipeList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -443,9 +443,9 @@
|
|||
<Struct Name="Substruct_SpawnInfoStruct" ClientVersion="546" >
|
||||
<Data ElementName="hp_remaining" Type="int32" Size="1" /> <!-- 0 -->
|
||||
<Data ElementName="power_percent" Type="int32" Size="1" /> <!-- 4 -->
|
||||
<Data ElementName="spells" Substruct="Substruct_TargetSpellEffects" Size="30" /> <!-- 8 -->
|
||||
<Data ElementName="follow_target" Type="int32" Size="1" /> <!-- 278 -->
|
||||
<Data ElementName="spell_effects" Substruct="Substruct_TargetSpellEffects" Size="30" /> <!-- 8 -->
|
||||
<Data ElementName="target_id" Type="int32" Size="1" /> <!-- 282 -->
|
||||
<Data ElementName="follow_target" Type="int32" Size="1" /> <!-- 278 -->
|
||||
<Data ElementName="unknown5" Type="int8" Size="8" /> <!-- 286 -->
|
||||
<Data ElementName="corpse" Type="int8" Size="1" /> <!-- 295 -->
|
||||
<Data ElementName="class" Type="int8" Size="1" /> <!-- 296 -->
|
||||
|
|
Loading…
Reference in a new issue