diff --git a/changelog.txt b/changelog.txt index f8ca4c917..e3762b3dd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,44 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/05/2016 == +mackal: Implement extra bind points (secondary recall) + For SE_Gate, base2 is which bind to use (starting at 1) + For SE_BindAffinity, base1 is which bind to set (starting at 1) + For SE_GateCastersBindpoint, base1 is which bind to use (starting at 1) + There was actually no spells that don't send to the main bind, but it uses a base1 of 1 which matches with SE_Gate + This also doesn't break anything + +== 03/01/2016 == +Uleat: Fix for LDoN treasure 'npcs' not leaving a corpse (please report any issues..) + +== 02/29/2016 == +Uleat: Change in AddItemBonuses - now includes ammo slot for skill mods only. Defined SoD- client SkillModMax packet property (client does not show..but, does enforce.) + +== 02/11/2016 == +Hateborne: Added IgnoreSpellDmgLvlRestriction rule (boolean) to ignore the 5 level spread when checking to add SpellDmg + +== 02/10/2016 == +Hateborne: Added FlatItemExtraSpellAmt rule (boolean) to allow SpellDmg on items to be added as raw damage versus scaled. + +== 01/26/2016 == +Uleat: Fix for Berserker 'Piercing' skill issues. Server Admins: If you run custom skill sets, this patch touches the code segments that you will need to modify if you have changed the default berserker 1H-/2H-piercing skill values. +Uleat (Daerath): Fix for precision-loss item weight conversions in older clients. + - WARNING: YOU MUST RE-RUN SHARED_MEMORY.EXE BEFORE STARTING SERVER OR ITEM LOSS WILL OCCUR! + - Note: Cmake must be re-run to include/exclude the required files + +== 01/13/2016 == +Kinglykrab: Modified #flag so you can refresh your target's account status (GM status level) without them having to relog. + - Just target the person whose flag you want to refresh and type #flag. +Uleat: Added itemlink functionality to the #summonitem command. Current use is limited to extracting the item id from the link. + - Invoking by item link '#summonitem Arrow' produces the same result as by item id '#summonitem 8005' + +== 01/12/2016 == +Athrogate: Adding ClearCompassMark() to Lua. + - Lua didn't have ClearCompassMark(). Perl already had this. + +== 01/12/2016 == +Uleat: Fix for tradeskill containers remaining locked after a RoF+ client leaves. Intermediary fix for RoF+ clients accessing tradeskill containers when in use by another player (thanks Natedog!) + == 12/29/2015 == Akkadius: Implemented standardized zone controller scripts (Rule Zone, UseZoneController) Defaulted to true - When a zone boots, it will spawn an invisible npc by the name of zone_controller diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index f847957db..09ed7e02c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -213,7 +213,8 @@ SET(common_headers patches/rof2_structs.h patches/titanium.h patches/titanium_constants.h - patches/titanium_itemfields.h + patches/titanium_itemfields_a.h + patches/titanium_itemfields_b.h patches/titanium_ops.h patches/titanium_structs.h patches/uf.h @@ -265,7 +266,8 @@ SOURCE_GROUP(Patches FILES patches/rof2_constants.h patches/rof2_structs.h patches/titanium.h - patches/titanium_itemfields.h + patches/titanium_itemfields_a.h + patches/titanium_itemfields_b.h patches/titanium_ops.h patches/titanium_constants.h patches/titanium_structs.h diff --git a/common/database.cpp b/common/database.cpp index 932aa4229..cdafaa165 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -636,11 +636,11 @@ bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, Playe ); auto results = QueryDatabase(query); /* Save Bind Points */ - query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i), " "(%u, %u, %u, %f, %f, %f, %f, %i)", character_id, pp->binds[0].zoneId, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0, - character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 1 + character_id, pp->binds[4].zoneId, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4 ); results = QueryDatabase(query); /* Save Skills */ @@ -2185,8 +2185,7 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) std::string query = StringFormat("SELECT minute,hour,day,month,year,realtime FROM eqtime limit 1"); auto results = QueryDatabase(query); - if (!results.Success() || results.RowCount() == 0) - { + if (!results.Success() || results.RowCount() == 0){ Log.Out(Logs::Detail, Logs::World_Server, "Loading EQ time of day failed. Using defaults."); eqTime.minute = 0; eqTime.hour = 9; @@ -2195,15 +2194,16 @@ struct TimeOfDay_Struct Database::LoadTime(time_t &realtime) eqTime.year = 3100; realtime = time(0); } + else{ + auto row = results.begin(); - auto row = results.begin(); - - eqTime.minute = atoi(row[0]); - eqTime.hour = atoi(row[1]); - eqTime.day = atoi(row[2]); - eqTime.month = atoi(row[3]); - eqTime.year = atoi(row[4]); - realtime = atoi(row[5]); + eqTime.minute = atoi(row[0]); + eqTime.hour = atoi(row[1]); + eqTime.day = atoi(row[2]); + eqTime.month = atoi(row[3]); + eqTime.year = atoi(row[4]); + realtime = atoi(row[5]); + } return eqTime; } @@ -2215,4 +2215,4 @@ bool Database::SaveTime(int8 minute, int8 hour, int8 day, int8 month, int16 year return results.Success(); -} \ No newline at end of file +} diff --git a/common/eq_constants.h b/common/eq_constants.h index 0fec1f223..728013eba 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -32,17 +32,17 @@ enum LightTypes lightTypeTorch, lightTypeTinyGlowingSkull, lightTypeSmallLantern, - lightTypeSteinOfMoggok, + lightTypeSteinOfMoggok, // 5 lightTypeLargeLantern, lightTypeFlamelessLantern, lightTypeGlobeOfStars, lightTypeLightGlobe, - lightTypeLightstone, + lightTypeLightstone, // 10 lightTypeGreaterLightstone, lightTypeFireBeetleEye, lightTypeColdlight, lightTypeUnknown1, - lightTypeUnknown2 + lightTypeUnknown2 // 15 }; #define LIGHT_TYPES_COUNT 16 @@ -58,12 +58,12 @@ enum LightLevels lightLevelTorch, lightLevelSmallMagic, lightLevelRedLight, - lightLevelBlueLight, + lightLevelBlueLight, // 5 lightLevelSmallLantern, lightLevelMagicLantern, lightLevelLargeLantern, lightLevelLargeMagic, - lightLevelBrilliant + lightLevelBrilliant // 10 }; #define LIGHT_LEVELS_COUNT 11 @@ -111,62 +111,62 @@ enum ItemUseTypes : uint8 /*9140*/ ItemType1HPiercing, /*9139*/ ItemType1HBlunt, /*9142*/ ItemType2HBlunt, -/*5504*/ ItemTypeBow, +/*5504*/ ItemTypeBow, // 5 /*----*/ ItemTypeUnknown1, /*----*/ ItemTypeLargeThrowing, /*5505*/ ItemTypeShield, /*5506*/ ItemTypeScroll, -/*5507*/ ItemTypeArmor, +/*5507*/ ItemTypeArmor, // 10 /*5508*/ ItemTypeMisc, // a lot of random crap has this item use. /*7564*/ ItemTypeLockPick, /*----*/ ItemTypeUnknown2, /*5509*/ ItemTypeFood, -/*5510*/ ItemTypeDrink, +/*5510*/ ItemTypeDrink, // 15 /*5511*/ ItemTypeLight, /*5512*/ ItemTypeCombinable, // not all stackable items are this use... /*5513*/ ItemTypeBandage, /*----*/ ItemTypeSmallThrowing, -/*----*/ ItemTypeSpell, // spells and tomes +/*----*/ ItemTypeSpell, // 20 // spells and tomes /*5514*/ ItemTypePotion, /*----*/ ItemTypeUnknown3, /*0406*/ ItemTypeWindInstrument, /*0407*/ ItemTypeStringedInstrument, -/*0408*/ ItemTypeBrassInstrument, +/*0408*/ ItemTypeBrassInstrument, // 25 /*0405*/ ItemTypePercussionInstrument, /*5515*/ ItemTypeArrow, /*----*/ ItemTypeUnknown4, /*5521*/ ItemTypeJewelry, -/*----*/ ItemTypeSkull, +/*----*/ ItemTypeSkull, // 30 /*5516*/ ItemTypeBook, // skill-up tomes/books? (would probably need a pp flag if true...) /*5517*/ ItemTypeNote, /*5518*/ ItemTypeKey, /*----*/ ItemTypeCoin, -/*5520*/ ItemType2HPiercing, +/*5520*/ ItemType2HPiercing, // 35 /*----*/ ItemTypeFishingPole, /*----*/ ItemTypeFishingBait, /*5519*/ ItemTypeAlcohol, /*----*/ ItemTypeKey2, // keys and satchels?? (questable keys?) -/*----*/ ItemTypeCompass, +/*----*/ ItemTypeCompass, // 40 /*----*/ ItemTypeUnknown5, /*----*/ ItemTypePoison, // might be wrong, but includes poisons /*----*/ ItemTypeUnknown6, /*----*/ ItemTypeUnknown7, -/*5522*/ ItemTypeMartial, +/*5522*/ ItemTypeMartial, // 45 /*----*/ ItemTypeUnknown8, /*----*/ ItemTypeUnknown9, /*----*/ ItemTypeUnknown10, /*----*/ ItemTypeUnknown11, -/*----*/ ItemTypeSinging, +/*----*/ ItemTypeSinging, // 50 /*5750*/ ItemTypeAllInstrumentTypes, /*5776*/ ItemTypeCharm, /*----*/ ItemTypeDye, /*----*/ ItemTypeAugmentation, -/*----*/ ItemTypeAugmentationSolvent, +/*----*/ ItemTypeAugmentationSolvent, // 55 /*----*/ ItemTypeAugmentationDistiller, /*----*/ ItemTypeUnknown12, /*----*/ ItemTypeFellowshipKit, /*----*/ ItemTypeUnknown13, -/*----*/ ItemTypeRecipe, +/*----*/ ItemTypeRecipe, // 60 /*----*/ ItemTypeAdvancedRecipe, /*----*/ ItemTypeJournal, // only one(1) database entry /*----*/ ItemTypeAltCurrency, // alt-currency (as opposed to coinage) @@ -237,32 +237,32 @@ enum AugmentationUseTypes : uint8 { AugTypeGeneralMultipleStat, AugTypeGeneralSpellEffect, AugTypeWeaponGeneral, - AugTypeWeaponElemDamage, + AugTypeWeaponElemDamage, // 5 AugTypeWeaponBaseDamage, AugTypeGeneralGroup, AugTypeGeneralRaid, AugTypeGeneralDragonsPoints, - AugTypeCraftedCommon, + AugTypeCraftedCommon, // 10 AugTypeCraftedGroup1, AugTypeCraftedRaid1, AugTypeEnergeiacGroup, AugTypeEnergeiacRaid, - AugTypeEmblem, + AugTypeEmblem, // 15 AugTypeCraftedGroup2, AugTypeCraftedRaid2, AugTypeUnknown1, AugTypeUnknown2, - AugTypeOrnamentation, + AugTypeOrnamentation, // 20 AugTypeSpecialOrnamentation, AugTypeUnknown3, AugTypeUnknown4, AugTypeUnknown5, - AugTypeUnknown6, + AugTypeUnknown6, // 25 AugTypeUnknown7, AugTypeUnknown8, AugTypeUnknown9, AugTypeUnknown10, - AugTypeEpic25, + AugTypeEpic25, // 30 AugTypeTest, _AugTypeCount, AugTypeAll = 255 @@ -280,17 +280,17 @@ enum AugmentationRestrictionTypes : uint8 { /*9135*/ AugRestrWeapons, /*9136*/ AugRestr1HWeapons, /*9137*/ AugRestr2HWeapons, -/*9138*/ AugRestr1HSlash, +/*9138*/ AugRestr1HSlash, // 5 /*9139*/ AugRestr1HBlunt, /*9140*/ AugRestrPiercing, /*9148*/ AugRestrHandToHand, /*9141*/ AugRestr2HSlash, -/*9142*/ AugRestr2HBlunt, +/*9142*/ AugRestr2HBlunt, // 10 /*9143*/ AugRestr2HPierce, /*9144*/ AugRestrBows, /*9145*/ AugRestrShields, /*8052*/ AugRestr1HSlash1HBluntOrHandToHand, -/*9200*/ AugRestr1HBluntOrHandToHand, // no listed peq entries +/*9200*/ AugRestr1HBluntOrHandToHand, // 15 // no listed peq entries // these three appear to be post-RoF (12-10-2012) and can not be verified until RoF (05-10-2013) is supported /*????*/ AugRestrUnknown1, @@ -317,57 +317,57 @@ enum ContainerUseTypes : uint8 /*3402*/ BagTypeQuiver, /*3403*/ BagTypeBeltPouch, /*3404*/ BagTypeWristPouch, -/*3405*/ BagTypeBackPack, +/*3405*/ BagTypeBackPack, // 5 /*3406*/ BagTypeSmallChest, /*3407*/ BagTypeLargeChest, /*----*/ BagTypeBandolier, // <*Database Reference Only> /*3408*/ BagTypeMedicineBag, -/*3409*/ BagTypeToolBox, +/*3409*/ BagTypeToolBox, // 10 /*3410*/ BagTypeLexicon, /*3411*/ BagTypeMortar, /*3412*/ BagTypeSelfDusting, // Quest container (Auto-clear contents?) /*3413*/ BagTypeMixingBowl, -/*3414*/ BagTypeOven, +/*3414*/ BagTypeOven, // 15 /*3415*/ BagTypeSewingKit, /*3416*/ BagTypeForge, /*3417*/ BagTypeFletchingKit, /*3418*/ BagTypeBrewBarrel, -/*3419*/ BagTypeJewelersKit, +/*3419*/ BagTypeJewelersKit, // 20 /*3420*/ BagTypePotteryWheel, /*3421*/ BagTypeKiln, /*3422*/ BagTypeKeymaker, // (no database entries as of peq rev 69) /*3423*/ BagTypeWizardsLexicon, -/*3424*/ BagTypeMagesLexicon, +/*3424*/ BagTypeMagesLexicon, // 25 /*3425*/ BagTypeNecromancersLexicon, /*3426*/ BagTypeEnchantersLexicon, /*----*/ BagTypeUnknown1, // (a coin pouch/purse?) (no database entries as of peq rev 69) /*----*/ BagTypeConcordanceofResearch, // <*Database Reference Only> -/*3427*/ BagTypeAlwaysWorks, // Quest container (Never-fail combines?) +/*3427*/ BagTypeAlwaysWorks, // 30 // Quest container (Never-fail combines?) /*3428*/ BagTypeKoadaDalForge, // High Elf /*3429*/ BagTypeTeirDalForge, // Dark Elf /*3430*/ BagTypeOggokForge, // Ogre /*3431*/ BagTypeStormguardForge, // Dwarf -/*3432*/ BagTypeAkanonForge, // Gnome +/*3432*/ BagTypeAkanonForge, // 35 // Gnome /*3433*/ BagTypeNorthmanForge, // Barbarian /*----*/ BagTypeUnknown2, // (no database entries as of peq rev 69) /*3434*/ BagTypeCabilisForge, // Iksar /*3435*/ BagTypeFreeportForge, // Human 1 -/*3436*/ BagTypeRoyalQeynosForge, // Human 2 +/*3436*/ BagTypeRoyalQeynosForge, // 40 // Human 2 /*3439*/ BagTypeHalflingTailoringKit, /*3438*/ BagTypeErudTailoringKit, /*3440*/ BagTypeFierDalTailoringKit, // Wood Elf /*3441*/ BagTypeFierDalFletchingKit, // Wood Elf -/*3437*/ BagTypeIksarPotteryWheel, +/*3437*/ BagTypeIksarPotteryWheel, // 45 /*3442*/ BagTypeTackleBox, /*3443*/ BagTypeTrollForge, /*3445*/ BagTypeFierDalForge, // Wood Elf /*3444*/ BagTypeValeForge, // Halfling -/*3446*/ BagTypeErudForge, +/*3446*/ BagTypeErudForge, // 50 /*----*/ BagTypeTradersSatchel, // <*Database Reference Only> (db: Yellow Trader's Satchel Token?) /*5785*/ BagTypeGuktaForge, // Froglok (no database entries as of peq rev 69) /*3359*/ BagTypeAugmentationSealer, /*----*/ BagTypeIceCreamChurn, // <*Database Reference Only> -/*6325*/ BagTypeTransformationmold, // Ornamentation +/*6325*/ BagTypeTransformationmold, // 55 // Ornamentation /*6340*/ BagTypeDetransformationmold, // Ornamentation Stripper /*5400*/ BagTypeUnattuner, /*7684*/ BagTypeTradeskillBag, @@ -799,10 +799,10 @@ static const uint8 SkillDamageTypes[HIGHEST_SKILL + 1] = // change to _SkillServ /*Intimidation*/ DamageTypeUnknown, /*Berserking*/ DamageTypeUnknown, /*Taunt*/ DamageTypeUnknown, -/*Frenzy*/ 74 //, -// /*RemoveTrap*/ DamageTypeUnknown, // Needs research (set for SenseTrap value) -// /*TripleAttack*/ DamageTypeUnknown, // Needs research (set for DoubleAttack value) -// /*2HPiercing*/ 36 // Needs research (set for 1HPiercing value - similar to slash/blunt) +/*Frenzy*/ 74, +/*RemoveTrap*/ DamageTypeUnknown, // Needs research (set for SenseTrap value) +/*TripleAttack*/ DamageTypeUnknown, // Needs research (set for DoubleAttack value) +/*2HPiercing*/ 36 // Needs research (set for 1HPiercing value - similar to slash/blunt) }; /* @@ -816,7 +816,7 @@ enum MaterialUseSlots : uint8 MaterialArms, MaterialWrist, MaterialHands, - MaterialLegs, + MaterialLegs, // 5 MaterialFeet, MaterialPrimary, MaterialSecondary, @@ -864,22 +864,22 @@ enum InventoryMapTypes : int16 { MapSharedBank, MapTrade, MapWorld, - MapLimbo, + MapLimbo, // 5 MapTribute, MapTrophyTribute, MapGuildTribute, MapMerchant, - MapDeleted, + MapDeleted, // 10 MapCorpse, MapBazaar, MapInspect, MapRealEstate, - MapViewMODPC, + MapViewMODPC, // 15 MapViewMODBank, MapViewMODSharedBank, MapViewMODLimbo, MapAltStorage, - MapArchived, + MapArchived, // 20 MapMail, MapGuildTrophyTribute, MapKrono, @@ -893,35 +893,35 @@ enum InventoryMainTypes : int16 { MainHead, MainFace, MainEar2, - MainNeck, + MainNeck, // 5 MainShoulders, MainArms, MainBack, MainWrist1, - MainWrist2, + MainWrist2, // 10 MainRange, MainHands, MainPrimary, MainSecondary, - MainFinger1, + MainFinger1, // 15 MainFinger2, MainChest, MainLegs, MainFeet, - MainWaist, + MainWaist, // 20 MainPowerSource = 9999, // temp MainAmmo = 21, // temp MainGeneral1, MainGeneral2, MainGeneral3, - MainGeneral4, + MainGeneral4, // 25 MainGeneral5, MainGeneral6, MainGeneral7, MainGeneral8, //MainGeneral9, //MainGeneral10, - MainCursor, + MainCursor, // 30 _MainCount }; diff --git a/common/features.h b/common/features.h index 8115efd82..9ceddb31b 100644 --- a/common/features.h +++ b/common/features.h @@ -273,6 +273,9 @@ enum { #define NPC_DEFAULT_LOGGING_ENABLED false +// This is the item ID we use for say links, we use the max that fits in 5 ASCII chars +#define SAYLINK_ITEM_ID 0xFFFFF + /* diff --git a/common/item.cpp b/common/item.cpp index 8e8ec6f1a..5d1142d2c 100644 --- a/common/item.cpp +++ b/common/item.cpp @@ -2230,11 +2230,12 @@ void ItemInst::ScaleItem() { m_scaledItem->Mana = (int32)((float)m_item->Mana*Mult); m_scaledItem->AC = (int32)((float)m_item->AC*Mult); - m_scaledItem->SkillModValue = (int32)((float)m_item->SkillModValue*Mult); - m_scaledItem->BaneDmgAmt = (int8)((float)m_item->BaneDmgAmt*Mult); - m_scaledItem->BardValue = (int32)((float)m_item->BardValue*Mult); - m_scaledItem->ElemDmgAmt = (uint8)((float)m_item->ElemDmgAmt*Mult); - m_scaledItem->Damage = (uint32)((float)m_item->Damage*Mult); + // check these..some may not need to be modified (really need to check all stats/bonuses) + //m_scaledItem->SkillModValue = (int32)((float)m_item->SkillModValue*Mult); + //m_scaledItem->BaneDmgAmt = (int8)((float)m_item->BaneDmgAmt*Mult); // watch (10 entries with charmfileid) + m_scaledItem->BardValue = (int32)((float)m_item->BardValue*Mult); // watch (no entries with charmfileid) + m_scaledItem->ElemDmgAmt = (uint8)((float)m_item->ElemDmgAmt*Mult); // watch (no entries with charmfileid) + m_scaledItem->Damage = (uint32)((float)m_item->Damage*Mult); // watch m_scaledItem->CombatEffects = (int8)((float)m_item->CombatEffects*Mult); m_scaledItem->Shielding = (int8)((float)m_item->Shielding*Mult); @@ -2322,6 +2323,708 @@ void ItemInst::ClearTimers() { m_timers.clear(); } +int ItemInst::GetItemArmorClass(bool augments) const +{ + int ac = 0; + const auto item = GetItem(); + if (item) { + ac = item->AC; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + ac += GetAugment(i)->GetItemArmorClass(); + } + return ac; +} + +int ItemInst::GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments) const +{ + const auto item = GetItem(); + if (item) { + switch (item->ElemDmgType) { + case RESIST_MAGIC: + magic += item->ElemDmgAmt; + break; + case RESIST_FIRE: + fire += item->ElemDmgAmt; + break; + case RESIST_COLD: + cold += item->ElemDmgAmt; + break; + case RESIST_POISON: + poison += item->ElemDmgAmt; + break; + case RESIST_DISEASE: + disease += item->ElemDmgAmt; + break; + case RESIST_CHROMATIC: + chromatic += item->ElemDmgAmt; + break; + case RESIST_PRISMATIC: + prismatic += item->ElemDmgAmt; + break; + case RESIST_PHYSICAL: + physical += item->ElemDmgAmt; + break; + case RESIST_CORRUPTION: + corruption += item->ElemDmgAmt; + break; + } + + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + GetAugment(i)->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption); + } + return magic + fire + cold + poison + disease + chromatic + prismatic + physical + corruption; +} + +int ItemInst::GetItemElementalFlag(bool augments) const +{ + int flag = 0; + const auto item = GetItem(); + if (item) { + flag = item->ElemDmgType; + if (flag) + return flag; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + if (GetAugment(i)) + flag = GetAugment(i)->GetItemElementalFlag(); + if (flag) + return flag; + } + } + } + return flag; +} + +int ItemInst::GetItemElementalDamage(bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + damage = item->ElemDmgAmt; + if (damage) + return damage; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + if (GetAugment(i)) + damage = GetAugment(i)->GetItemElementalDamage(); + if (damage) + return damage; + } + } + } + return damage; +} + +int ItemInst::GetItemRecommendedLevel(bool augments) const +{ + int level = 0; + const auto item = GetItem(); + if (item) { + level = item->RecLevel; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + int temp = 0; + if (GetAugment(i)) { + temp = GetAugment(i)->GetItemRecommendedLevel(); + if (temp > level) + level = temp; + } + } + } + } + + return level; +} + +int ItemInst::GetItemRequiredLevel(bool augments) const +{ + int level = 0; + const auto item = GetItem(); + if (item) { + level = item->ReqLevel; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) { + int temp = 0; + if (GetAugment(i)) { + temp = GetAugment(i)->GetItemRequiredLevel(); + if (temp > level) + level = temp; + } + } + } + } + + return level; +} + +int ItemInst::GetItemWeaponDamage(bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + damage = item->Damage; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemWeaponDamage(); + } + } + return damage; +} + +int ItemInst::GetItemBackstabDamage(bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + damage = item->BackstabDmg; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemBackstabDamage(); + } + } + return damage; +} + +int ItemInst::GetItemBaneDamageBody(bool augments) const +{ + int body = 0; + const auto item = GetItem(); + if (item) { + body = item->BaneDmgBody; + if (body) + return body; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) { + body = GetAugment(i)->GetItemBaneDamageBody(); + if (body) + return body; + } + } + } + return body; +} + +int ItemInst::GetItemBaneDamageRace(bool augments) const +{ + int race = 0; + const auto item = GetItem(); + if (item) { + race = item->BaneDmgRace; + if (race) + return race; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) { + race = GetAugment(i)->GetItemBaneDamageRace(); + if (race) + return race; + } + } + } + return race; +} + +int ItemInst::GetItemBaneDamageBody(bodyType against, bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + if (item->BaneDmgBody == against) + damage += item->BaneDmgAmt; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemBaneDamageBody(against); + } + } + return damage; +} + +int ItemInst::GetItemBaneDamageRace(uint16 against, bool augments) const +{ + int damage = 0; + const auto item = GetItem(); + if (item) { + if (item->BaneDmgRace == against) + damage += item->BaneDmgRaceAmt; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + damage += GetAugment(i)->GetItemBaneDamageRace(against); + } + } + return damage; +} + +int ItemInst::GetItemMagical(bool augments) const +{ + const auto item = GetItem(); + if (item) { + if (item->Magic) + return 1; + + if (augments) { + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i) && GetAugment(i)->GetItemMagical()) + return 1; + } + } + return 0; +} + +int ItemInst::GetItemHP(bool augments) const +{ + int hp = 0; + const auto item = GetItem(); + if (item) { + hp = item->HP; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + hp += GetAugment(i)->GetItemHP(); + } + return hp; +} + +int ItemInst::GetItemMana(bool augments) const +{ + int mana = 0; + const auto item = GetItem(); + if (item) { + mana = item->Mana; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + mana += GetAugment(i)->GetItemMana(); + } + return mana; +} + +int ItemInst::GetItemEndur(bool augments) const +{ + int endur = 0; + const auto item = GetItem(); + if (item) { + endur = item->Endur; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + endur += GetAugment(i)->GetItemEndur(); + } + return endur; +} + +int ItemInst::GetItemAttack(bool augments) const +{ + int atk = 0; + const auto item = GetItem(); + if (item) { + atk = item->Attack; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + atk += GetAugment(i)->GetItemAttack(); + } + return atk; +} + +int ItemInst::GetItemStr(bool augments) const +{ + int str = 0; + const auto item = GetItem(); + if (item) { + str = item->AStr; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + str += GetAugment(i)->GetItemStr(); + } + return str; +} + +int ItemInst::GetItemSta(bool augments) const +{ + int sta = 0; + const auto item = GetItem(); + if (item) { + sta = item->ASta; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + sta += GetAugment(i)->GetItemSta(); + } + return sta; +} + +int ItemInst::GetItemDex(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->ADex; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemDex(); + } + return total; +} + +int ItemInst::GetItemAgi(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->AAgi; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemAgi(); + } + return total; +} + +int ItemInst::GetItemInt(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->AInt; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemInt(); + } + return total; +} + +int ItemInst::GetItemWis(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->AWis; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemWis(); + } + return total; +} + +int ItemInst::GetItemCha(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->ACha; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemCha(); + } + return total; +} + +int ItemInst::GetItemMR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->MR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemMR(); + } + return total; +} + +int ItemInst::GetItemFR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->FR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemFR(); + } + return total; +} + +int ItemInst::GetItemCR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->CR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemCR(); + } + return total; +} + +int ItemInst::GetItemPR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->PR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemPR(); + } + return total; +} + +int ItemInst::GetItemDR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->DR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemDR(); + } + return total; +} + +int ItemInst::GetItemCorrup(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->SVCorruption; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemCorrup(); + } + return total; +} + +int ItemInst::GetItemHeroicStr(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicStr; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicStr(); + } + return total; +} + +int ItemInst::GetItemHeroicSta(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicSta; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicSta(); + } + return total; +} + +int ItemInst::GetItemHeroicDex(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicDex; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicDex(); + } + return total; +} + +int ItemInst::GetItemHeroicAgi(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicAgi; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicAgi(); + } + return total; +} + +int ItemInst::GetItemHeroicInt(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicInt; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicInt(); + } + return total; +} + +int ItemInst::GetItemHeroicWis(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicWis; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicWis(); + } + return total; +} + +int ItemInst::GetItemHeroicCha(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicCha; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicCha(); + } + return total; +} + +int ItemInst::GetItemHeroicMR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicMR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicMR(); + } + return total; +} + +int ItemInst::GetItemHeroicFR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicFR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicFR(); + } + return total; +} + +int ItemInst::GetItemHeroicCR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicCR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicCR(); + } + return total; +} + +int ItemInst::GetItemHeroicPR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicPR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicPR(); + } + return total; +} + +int ItemInst::GetItemHeroicDR(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicDR; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicDR(); + } + return total; +} + +int ItemInst::GetItemHeroicCorrup(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->HeroicSVCorrup; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) + total += GetAugment(i)->GetItemHeroicCorrup(); + } + return total; +} + +int ItemInst::GetItemHaste(bool augments) const +{ + int total = 0; + const auto item = GetItem(); + if (item) { + total = item->Haste; + if (augments) + for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; ++i) + if (GetAugment(i)) { + int temp = GetAugment(i)->GetItemHaste(); + if (temp > total) + total = temp; + } + } + return total; +} // // class EvolveInfo @@ -2416,7 +3119,7 @@ uint8 LightProfile_Struct::TypeToLevel(uint8 lightType) return lightLevelSmallMagic; // 3 case lightTypeTorch: return lightLevelTorch; // 2 - case lightLevelCandle: + case lightTypeCandle: return lightLevelCandle; // 1 default: return lightLevelUnlit; // 0 diff --git a/common/item.h b/common/item.h index a5dd01f95..b6babde9f 100644 --- a/common/item.h +++ b/common/item.h @@ -29,6 +29,7 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/eq_constants.h" #include "../common/item_struct.h" #include "../common/timer.h" +#include "../common/bodytypes.h" #include #include @@ -418,6 +419,58 @@ public: void StopTimer(std::string name); void ClearTimers(); + // Get a total of a stat, including augs + // These functions should be used in place of other code manually totaling + // to centralize where it is done to make future changes easier (ex. whenever powersources come around) + // and to minimize errors. CalcItemBonuses however doesn't use these in interest of performance + // by default these do not recurse into augs + int GetItemArmorClass(bool augments = false) const; + int GetItemElementalDamage(int &magic, int &fire, int &cold, int &poison, int &disease, int &chromatic, int &prismatic, int &physical, int &corruption, bool augments = false) const; + // These two differ in the fact that they're quick checks (they are checked BEFORE the one above + int GetItemElementalFlag(bool augments = false) const; + int GetItemElementalDamage(bool augments = false) const; + int GetItemRecommendedLevel(bool augments = false) const; + int GetItemRequiredLevel(bool augments = false) const; + int GetItemWeaponDamage(bool augments = false) const; + int GetItemBackstabDamage(bool augments = false) const; + // these two are just quick checks + int GetItemBaneDamageBody(bool augments = false) const; + int GetItemBaneDamageRace(bool augments = false) const; + int GetItemBaneDamageBody(bodyType against, bool augments = false) const; + int GetItemBaneDamageRace(uint16 against, bool augments = false) const; + int GetItemMagical(bool augments = false) const; + int GetItemHP(bool augments = false) const; + int GetItemMana(bool augments = false) const; + int GetItemEndur(bool augments = false) const; + int GetItemAttack(bool augments = false) const; + int GetItemStr(bool augments = false) const; + int GetItemSta(bool augments = false) const; + int GetItemDex(bool augments = false) const; + int GetItemAgi(bool augments = false) const; + int GetItemInt(bool augments = false) const; + int GetItemWis(bool augments = false) const; + int GetItemCha(bool augments = false) const; + int GetItemMR(bool augments = false) const; + int GetItemFR(bool augments = false) const; + int GetItemCR(bool augments = false) const; + int GetItemPR(bool augments = false) const; + int GetItemDR(bool augments = false) const; + int GetItemCorrup(bool augments = false) const; + int GetItemHeroicStr(bool augments = false) const; + int GetItemHeroicSta(bool augments = false) const; + int GetItemHeroicDex(bool augments = false) const; + int GetItemHeroicAgi(bool augments = false) const; + int GetItemHeroicInt(bool augments = false) const; + int GetItemHeroicWis(bool augments = false) const; + int GetItemHeroicCha(bool augments = false) const; + int GetItemHeroicMR(bool augments = false) const; + int GetItemHeroicFR(bool augments = false) const; + int GetItemHeroicCR(bool augments = false) const; + int GetItemHeroicPR(bool augments = false) const; + int GetItemHeroicDR(bool augments = false) const; + int GetItemHeroicCorrup(bool augments = false) const; + int GetItemHaste(bool augments = false) const; + protected: ////////////////////////// // Protected Members diff --git a/common/item_struct.h b/common/item_struct.h index ba8afcd14..0d7505a2c 100644 --- a/common/item_struct.h +++ b/common/item_struct.h @@ -83,7 +83,7 @@ struct Item_Struct { char Lore[80]; // Lore Name: *=lore, &=summoned, #=artifact, ~=pending lore char IDFile[30]; // Visible model uint32 ID; // Unique ID (also PK for DB) - uint8 Weight; // Item weight * 10 + int32 Weight; // Item weight * 10 uint8 NoRent; // No Rent: 0=norent, 255=not norent uint8 NoDrop; // No Drop: 0=nodrop, 255=not nodrop uint8 Size; // Size: 0=tiny, 1=small, 2=medium, 3=large, 4=giant @@ -160,7 +160,7 @@ struct Item_Struct { //uint32 Unk059; union { uint32 Fulfilment; // Food fulfilment (How long it lasts) - int16 CastTime; // Cast Time for clicky effects, in milliseconds + uint32 CastTime; // Cast Time for clicky effects, in milliseconds }; uint32 EliteMaterial; int32 ProcRate; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 76d62e3a4..b5349b617 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -975,8 +975,8 @@ namespace RoF VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); @@ -2392,13 +2392,14 @@ namespace RoF outapp->WriteSInt32(234); // Endurance Total ? outapp->WriteSInt32(345); // Mana Total ? - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown + // these are needed to fix display bugs + outapp->WriteUInt32(0x19); // base CR + outapp->WriteUInt32(0x19); // base FR + outapp->WriteUInt32(0x19); // base MR + outapp->WriteUInt32(0xf); // base DR + outapp->WriteUInt32(0xf); // base PR + outapp->WriteUInt32(0xf); // base PhR? + outapp->WriteUInt32(0xf); // base Corrup outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a8b231300..1724b8167 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1046,8 +1046,8 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); @@ -2471,13 +2471,14 @@ namespace RoF2 outapp->WriteSInt32(234); // Endurance Total ? outapp->WriteSInt32(345); // Mana Total ? - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(0); // Unknown + // these are needed to fix display bugs + outapp->WriteUInt32(0x19); // base CR + outapp->WriteUInt32(0x19); // base FR + outapp->WriteUInt32(0x19); // base MR + outapp->WriteUInt32(0xf); // base DR + outapp->WriteUInt32(0xf); // base PR + outapp->WriteUInt32(0xf); // base PhR? + outapp->WriteUInt32(0xf); // base Corrup outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown @@ -4075,6 +4076,17 @@ namespace RoF2 if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; + if (emu->DestructibleObject || emu->class_ == 62) + { + if (emu->DestructibleObject) + PacketSize = PacketSize - 4; // No bodytype + + PacketSize += 53; // Fixed portion + PacketSize += strlen(emu->DestructibleModel) + 1; + PacketSize += strlen(emu->DestructibleName2) + 1; + PacketSize += strlen(emu->DestructibleString) + 1; + } + bool ShowName = 1; if (emu->bodytype >= 66) { @@ -4109,7 +4121,14 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(Buffer, emu->name); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height? + if (emu->DestructibleObject) + { + VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000 + } + else + { + VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height? + } VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer; @@ -4129,6 +4148,12 @@ namespace RoF2 Bitfields->targetable_with_hotkey = emu->targetable_with_hotkey ? 1 : 0; Bitfields->showname = ShowName; + if (emu->DestructibleObject) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x1d600000); + Buffer = Buffer - 4; + } + // Not currently found // Bitfields->statue = 0; // Bitfields->buyer = 0; @@ -4137,21 +4162,66 @@ namespace RoF2 uint8 OtherData = 0; + if (emu->class_ == 62) //LDoN Chest + OtherData = OtherData | 0x04; + if (strlen(emu->title)) OtherData = OtherData | 16; if (strlen(emu->suffix)) OtherData = OtherData | 32; + if (emu->DestructibleObject) + OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); - VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3 + if (emu->DestructibleObject) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); + } + else + { + VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3 + } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - // Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not - // present. Will sort that out later. - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype); + if (emu->DestructibleObject || emu->class_ == 62) + { + VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); + VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); + VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleString); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleAppearance); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID1); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID2); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID3); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID4); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk2); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk3); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk4); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk5); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk6); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk7); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9); + } + + + if (!emu->DestructibleObject) + { + // Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not + // present. Will sort that out later. + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype); + } + else + { + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + } VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->curHp); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->haircolor); diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h index 4c8245737..0732044ca 100644 --- a/common/patches/rof2_constants.h +++ b/common/patches/rof2_constants.h @@ -186,6 +186,8 @@ namespace RoF2 { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 56; + + static const size_t PLAYER_PROFILE_SKILL_MAX = Skill2HPiercing; } namespace limits { diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 1e93b7434..20d3b47f2 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2845,7 +2845,8 @@ struct Object_Struct { /*00*/ uint32 drop_id; // Unique object id for zone /*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? /*00*/ float heading; // heading -/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00 +/*00*/ float x_tilt; //Tilt entire object on X axis +/*00*/ float y_tilt; //Tilt entire object on Y axis /*00*/ float size; // Size - default 1 /*00*/ float z; // z coord /*00*/ float x; // x coord diff --git a/common/patches/rof_constants.h b/common/patches/rof_constants.h index 8b5fadbf2..b348f5fd5 100644 --- a/common/patches/rof_constants.h +++ b/common/patches/rof_constants.h @@ -185,6 +185,8 @@ namespace RoF { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 55; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index e24935d35..86f8b0872 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2873,7 +2873,8 @@ struct Object_Struct { /*00*/ uint32 drop_id; // Unique object id for zone /*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? /*00*/ float heading; // heading -/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00 +/*00*/ float x_tilt; //Tilt entire object on X axis +/*00*/ float y_tilt; //Tilt entire object on Y axis /*00*/ float size; // Size - default 1 /*00*/ float z; // z coord /*00*/ float x; // x coord diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index bbd5acd45..424ad5a22 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3623,7 +3623,8 @@ namespace SoD memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct)); ibs.id = item->ID; - ibs.weight = item->Weight; + // weight is uint8 in the struct, and some weights exceed that, so capping at 255. + ibs.weight = (item->Weight > 255) ? 255 : item->Weight; ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; @@ -3660,7 +3661,7 @@ namespace SoD ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.unknown6 = 0; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = item->SkillModType; ibs.BaneDmgRace = item->BaneDmgRace; ibs.BaneDmgBody = item->BaneDmgBody; diff --git a/common/patches/sod_constants.h b/common/patches/sod_constants.h index 5dad9bb09..ebd1d7d48 100644 --- a/common/patches/sod_constants.h +++ b/common/patches/sod_constants.h @@ -182,6 +182,8 @@ namespace SoD { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 50; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index d9abef4c6..20e2a56b4 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -4006,7 +4006,7 @@ struct ItemBodyStruct uint32 Races; uint32 Deity; int32 SkillModValue; - uint32 unknown6; + uint32 SkillModMax; uint32 SkillModType; uint32 BaneDmgRace; uint32 BaneDmgBody; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index d8b7db541..11e365a71 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2945,7 +2945,8 @@ namespace SoF memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct)); ibs.id = item->ID; - ibs.weight = item->Weight; + // weight is uint8 in the struct, and some weights exceed that, so capping at 255. + ibs.weight = (item->Weight > 255) ? 255 : item->Weight; ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; @@ -2982,7 +2983,7 @@ namespace SoF ibs.Races = item->Races; ibs.Deity = item->Deity; ibs.SkillModValue = item->SkillModValue; - ibs.unknown6 = 0; + ibs.SkillModMax = item->SkillModMax; ibs.SkillModType = item->SkillModType; ibs.BaneDmgRace = item->BaneDmgRace; ibs.BaneDmgBody = item->BaneDmgBody; diff --git a/common/patches/sof_constants.h b/common/patches/sof_constants.h index 260722f00..4ffcdd525 100644 --- a/common/patches/sof_constants.h +++ b/common/patches/sof_constants.h @@ -182,6 +182,8 @@ namespace SoF { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 50; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index db7cfe028..d78277721 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -3861,7 +3861,7 @@ struct ItemBodyStruct uint32 Races; uint32 Deity; int32 SkillModValue; - uint32 unknown6; + uint32 SkillModMax; uint32 SkillModType; uint32 BaneDmgRace; uint32 BaneDmgBody; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 42544f3b9..d3873dd97 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -2126,7 +2126,9 @@ namespace Titanium #define C(field) "|%s" #define S(field) "|%s" #define F(field) "|%f" -#include "titanium_itemfields.h" +#include "titanium_itemfields_a.h" + "|%i" // mask for item->Weight +#include "titanium_itemfields_b.h" "%.*s\"" // Quotes (and protection, if needed) around static data "|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" // Sub items "%.*s%s" // For trailing quotes (and protection) if a subitem; @@ -2138,7 +2140,9 @@ namespace Titanium #define C(field) ,field #define S(field) ,item->field #define F(field) ,item->field -#include "titanium_itemfields.h" +#include "titanium_itemfields_a.h" + , ((item->Weight > 255) ? (255) : (item->Weight)) +#include "titanium_itemfields_b.h" , depth, protection , sub_items[0] ? sub_items[0] : "" , sub_items[1] ? sub_items[1] : "" diff --git a/common/patches/titanium_constants.h b/common/patches/titanium_constants.h index d7e2a4964..4915c829c 100644 --- a/common/patches/titanium_constants.h +++ b/common/patches/titanium_constants.h @@ -181,6 +181,8 @@ namespace Titanium { static const size_t POTION_BELT_ITEM_COUNT = 4; static const size_t TEXT_LINK_BODY_LENGTH = 45; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillFrenzy; } namespace limits { diff --git a/common/patches/titanium_itemfields_a.h b/common/patches/titanium_itemfields_a.h new file mode 100644 index 000000000..ba8d7b1c6 --- /dev/null +++ b/common/patches/titanium_itemfields_a.h @@ -0,0 +1,19 @@ +/* + + +These fields must be in the order of how they are serialized! + + + +*/ + + +/* 000 */ //I(ItemClass) Leave this one off on purpose +/* 001 */ S(Name) +/* 002 */ S(Lore) +/* 003 */ S(IDFile) +/* 004 */ I(ID) + +/* 005 */ //I(Weight) handled manually + +// titanium_itemfields_b.h diff --git a/common/patches/titanium_itemfields.h b/common/patches/titanium_itemfields_b.h similarity index 95% rename from common/patches/titanium_itemfields.h rename to common/patches/titanium_itemfields_b.h index dc87a714e..30dc73bff 100644 --- a/common/patches/titanium_itemfields.h +++ b/common/patches/titanium_itemfields_b.h @@ -8,12 +8,10 @@ These fields must be in the order of how they are serialized! */ -/* 000 */ //I(ItemClass) Leave this one off on purpose -/* 001 */ S(Name) -/* 002 */ S(Lore) -/* 003 */ S(IDFile) -/* 004 */ I(ID) -/* 005 */ I(Weight) +// titanium_itemfields_a.h + +/* 005 */ //I(Weight) handled manually + /* 006 */ I(NoRent) /* 007 */ I(NoDrop) /* 008 */ I(Size) @@ -41,7 +39,7 @@ These fields must be in the order of how they are serialized! /* 030 */ I(AC) /* 031 */ I(Deity) /* 032 */ I(SkillModValue) -/* 033 */ C("0") +/* 033 */ I(SkillModMax) /* 034 */ I(SkillModType) /* 035 */ I(BaneDmgRace) /* 036 */ I(BaneDmgAmt) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 3535503a0..bc7d2906c 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -857,8 +857,8 @@ namespace UF // This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this // field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same // issue. - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0 + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //X tilt + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); //Y tilt VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); @@ -2818,9 +2818,11 @@ namespace UF if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - if (emu->DestructibleObject) + if (emu->DestructibleObject || emu->class_ == 62) { - PacketSize = PacketSize - 4; // No bodytype + if (emu->DestructibleObject) + PacketSize = PacketSize - 4; // No bodytype + PacketSize += 53; // Fixed portion PacketSize += strlen(emu->DestructibleModel) + 1; PacketSize += strlen(emu->DestructibleName2) + 1; @@ -2903,6 +2905,9 @@ namespace UF uint8 OtherData = 0; + if (emu->class_ == 62) //Ldon chest + OtherData = OtherData | 0x01; + if (strlen(emu->title)) OtherData = OtherData | 0x04; @@ -2924,7 +2929,7 @@ namespace UF } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - if (emu->DestructibleObject) + if (emu->DestructibleObject || emu->class_ == 62) { VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); @@ -3048,11 +3053,21 @@ namespace UF VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + if (emu->equipment[MaterialPrimary].Material > 99999) { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); + } else { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary].Material); + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + if (emu->equipment[MaterialSecondary].Material > 99999) { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 63); + } else { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary].Material); + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } @@ -3062,7 +3077,11 @@ namespace UF structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; for (k = 0; k < 9; k++) { - Equipment[k].Material = emu->equipment[k].Material; + if (emu->equipment[k].Material > 99999) { + Equipment[k].Material = 63; + } else { + Equipment[k].Material = emu->equipment[k].Material; + } Equipment[k].Unknown1 = emu->equipment[k].Unknown1; Equipment[k].EliteMaterial = emu->equipment[k].EliteMaterial; } @@ -3910,7 +3929,8 @@ namespace UF memset(&ibs, 0, sizeof(UF::structs::ItemBodyStruct)); ibs.id = item->ID; - ibs.weight = item->Weight; + // weight is uint8 in the struct, and some weights exceed that, so capping at 255. + ibs.weight = (item->Weight > 255) ? 255 : item->Weight; ibs.norent = item->NoRent; ibs.nodrop = item->NoDrop; ibs.attune = item->Attuneable; diff --git a/common/patches/uf_constants.h b/common/patches/uf_constants.h index 1a5a4cc44..b8096fd58 100644 --- a/common/patches/uf_constants.h +++ b/common/patches/uf_constants.h @@ -182,6 +182,8 @@ namespace UF { static const size_t POTION_BELT_ITEM_COUNT = 5; static const size_t TEXT_LINK_BODY_LENGTH = 50; + + static const size_t PLAYER_PROFILE_SKILL_MAX = SkillTripleAttack; } namespace limits { diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 7f3a7dcc0..75e590abd 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -2450,7 +2450,8 @@ struct Object_Struct { /*20*/ uint32 unknown020; // 00 00 00 00 /*24*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? /*40*/ float heading; // heading -/*32*/ uint8 unknown032[8]; // 00 00 00 00 00 00 00 00 +/*00*/ float x_tilt; //Tilt entire object on X axis +/*00*/ float y_tilt; //Tilt entire object on Y axis /*28*/ float size; // Size - default 1 /*44*/ float z; // z coord /*48*/ float x; // x coord diff --git a/common/ruletypes.h b/common/ruletypes.h index f83ea0266..641266b2f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -126,6 +126,7 @@ RULE_INT(Character, InvSnapshotMinIntervalM, 180) // Minimum time (in minutes) b RULE_INT(Character, InvSnapshotMinRetryM, 30) // Time (in minutes) to re-attempt an inventory snapshot after a failure RULE_INT(Character, InvSnapshotHistoryD, 30) // Time (in days) to keep snapshot entries RULE_BOOL(Character, RestrictSpellScribing, false) // Restricts spell scribing to allowable races/classes of spell scroll, if true +RULE_BOOL(Character, UseStackablePickPocketing, true) // Allows stackable pickpocketed items to stack instead of only being allowed in empty inventory slots RULE_CATEGORY_END() RULE_CATEGORY(Mercs) @@ -361,6 +362,8 @@ RULE_BOOL(Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell RULE_BOOL(Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects. RULE_BOOL(Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot. RULE_BOOL(Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true +RULE_BOOL(Spells, FlatItemExtraSpellAmt, false) // allow SpellDmg stat to affect all spells, regardless of cast time/cooldown/etc +RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spread on applying SpellDmg RULE_CATEGORY_END() RULE_CATEGORY(Combat) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index f82d54fad..79bac527e 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -857,7 +857,7 @@ void SharedDatabase::LoadItems(void *data, uint32 size, int32 items, uint32 max_ strcpy(item.IDFile, row[ItemField::idfile]); item.ID = (uint32)atoul(row[ItemField::id]); - item.Weight = (uint8)atoi(row[ItemField::weight]); + item.Weight = (int32)atoi(row[ItemField::weight]); item.NoRent = disableNoRent ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::norent]); item.NoDrop = disableNoDrop ? (uint8)atoi("255") : (uint8)atoi(row[ItemField::nodrop]); item.Size = (uint8)atoi(row[ItemField::size]); @@ -1920,6 +1920,7 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { "ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id"; auto results = QueryDatabase(query); if (!results.Success()) { + return; } uint32 current_id = 0; diff --git a/common/skills.cpp b/common/skills.cpp index 5edca778b..987004a2a 100644 --- a/common/skills.cpp +++ b/common/skills.cpp @@ -71,7 +71,7 @@ float EQEmu::GetSkillMeleePushForce(SkillUseTypes skill) case SkillEagleStrike: case SkillKick: case SkillTigerClaw: - //case Skill2HPiercing: + case Skill2HPiercing: return 0.2f; case SkillArchery: return 0.15f; @@ -106,3 +106,89 @@ bool EQEmu::IsBardInstrumentSkill(SkillUseTypes skill) return false; } } + +const std::map& EQEmu::GetSkillUseTypesMap() +{ + static const std::map skill_use_types_map = { + { Skill1HBlunt, "1H Blunt" }, + { Skill1HSlashing, "1H Slashing" }, + { Skill2HBlunt, "2H Blunt" }, + { Skill2HSlashing, "2H Slashing" }, + { SkillAbjuration, "Abjuration" }, + { SkillAlteration, "Alteration" }, + { SkillApplyPoison, "Apply Poison" }, + { SkillArchery, "Archery" }, + { SkillBackstab, "Backstab" }, + { SkillBindWound, "Bind Wound" }, + { SkillBash, "Bash" }, + { SkillBlock, "Block" }, + { SkillBrassInstruments, "Brass Instruments" }, + { SkillChanneling, "Channeling" }, + { SkillConjuration, "Conjuration" }, + { SkillDefense, "Defense" }, + { SkillDisarm, "Disarm" }, + { SkillDisarmTraps, "Disarm Traps" }, + { SkillDivination, "Divination" }, + { SkillDodge, "Dodge" }, + { SkillDoubleAttack, "Double Attack" }, + { SkillDragonPunch, "Dragon Punch" }, + { SkillDualWield, "Dual Wield" }, + { SkillEagleStrike, "Eagle Strike" }, + { SkillEvocation, "Evocation" }, + { SkillFeignDeath, "Feign Death" }, + { SkillFlyingKick, "Flying Kick" }, + { SkillForage, "Forage" }, + { SkillHandtoHand, "Hand to Hand" }, + { SkillHide, "Hide" }, + { SkillKick, "Kick" }, + { SkillMeditate, "Meditate" }, + { SkillMend, "Mend" }, + { SkillOffense, "Offense" }, + { SkillParry, "Parry" }, + { SkillPickLock, "Pick Lock" }, + { Skill1HPiercing, "1H Piercing" }, + { SkillRiposte, "Riposte" }, + { SkillRoundKick, "Round Kick" }, + { SkillSafeFall, "Safe Fall" }, + { SkillSenseHeading, "Sense Heading" }, + { SkillSinging, "Singing" }, + { SkillSneak, "Sneak" }, + { SkillSpecializeAbjure, "Specialize Abjuration" }, + { SkillSpecializeAlteration, "Specialize Alteration" }, + { SkillSpecializeConjuration, "Specialize Conjuration" }, + { SkillSpecializeDivination, "Specialize Divination" }, + { SkillSpecializeEvocation, "Specialize Evocation" }, + { SkillPickPockets, "Pick Pockets" }, + { SkillStringedInstruments, "Stringed Instruments" }, + { SkillSwimming, "Swimming" }, + { SkillThrowing, "Throwing" }, + { SkillTigerClaw, "Tiger Claw" }, + { SkillTracking, "Tracking" }, + { SkillWindInstruments, "Wind Instruments" }, + { SkillFishing, "Fishing" }, + { SkillMakePoison, "Make Poison" }, + { SkillTinkering, "Tinkering" }, + { SkillResearch, "Research" }, + { SkillAlchemy, "Alchemy" }, + { SkillBaking, "Baking" }, + { SkillTailoring, "Tailoring" }, + { SkillSenseTraps, "Sense Traps" }, + { SkillBlacksmithing, "Blacksmithing" }, + { SkillFletching, "Fletching" }, + { SkillBrewing, "Brewing" }, + { SkillAlcoholTolerance, "Alcohol Tolerance" }, + { SkillBegging, "Begging" }, + { SkillJewelryMaking, "Jewelry Making" }, + { SkillPottery, "Pottery" }, + { SkillPercussionInstruments, "Percussion Instruments" }, + { SkillIntimidation, "Intimidation" }, + { SkillBerserking, "Berserking" }, + { SkillTaunt, "Taunt" }, + { SkillFrenzy, "Frenzy" }, + { SkillRemoveTraps, "Remove Traps" }, + { SkillTripleAttack, "Triple Attack" }, + { Skill2HPiercing, "2H Piercing" } + }; + + return skill_use_types_map; +} diff --git a/common/skills.h b/common/skills.h index c79a522ee..0868c3329 100644 --- a/common/skills.h +++ b/common/skills.h @@ -18,12 +18,8 @@ #ifndef SKILLS_H #define SKILLS_H -/* -** This is really messed up... Are we using SkillTypes as a pseudo repository? The 76th skill really throws -** things for standardization... -** -** Below is an attempt to clean this up a little... -*/ +#include +#include /* ** Skill use types @@ -37,84 +33,84 @@ enum SkillUseTypes /*13857*/ Skill2HBlunt, /*13858*/ Skill2HSlashing, /*13859*/ SkillAbjuration, -/*13861*/ SkillAlteration, +/*13861*/ SkillAlteration, // 5 /*13862*/ SkillApplyPoison, /*13863*/ SkillArchery, /*13864*/ SkillBackstab, /*13866*/ SkillBindWound, -/*13867*/ SkillBash, +/*13867*/ SkillBash, // 10 /*13871*/ SkillBlock, /*13872*/ SkillBrassInstruments, /*13874*/ SkillChanneling, /*13875*/ SkillConjuration, -/*13876*/ SkillDefense, +/*13876*/ SkillDefense, // 15 /*13877*/ SkillDisarm, /*13878*/ SkillDisarmTraps, /*13879*/ SkillDivination, /*13880*/ SkillDodge, -/*13881*/ SkillDoubleAttack, +/*13881*/ SkillDoubleAttack, // 20 /*13882*/ SkillDragonPunch, /*13924*/ SkillTailRake = SkillDragonPunch, // Iksar Monk equivilent /*13883*/ SkillDualWield, /*13884*/ SkillEagleStrike, /*13885*/ SkillEvocation, -/*13886*/ SkillFeignDeath, +/*13886*/ SkillFeignDeath, // 25 /*13888*/ SkillFlyingKick, /*13889*/ SkillForage, /*13890*/ SkillHandtoHand, /*13891*/ SkillHide, -/*13893*/ SkillKick, +/*13893*/ SkillKick, // 30 /*13894*/ SkillMeditate, /*13895*/ SkillMend, /*13896*/ SkillOffense, /*13897*/ SkillParry, -/*13899*/ SkillPickLock, +/*13899*/ SkillPickLock, // 35 /*13900*/ Skill1HPiercing, // Changed in RoF2(05-10-2013) /*13903*/ SkillRiposte, /*13904*/ SkillRoundKick, /*13905*/ SkillSafeFall, -/*13906*/ SkillSenseHeading, +/*13906*/ SkillSenseHeading, // 40 /*13908*/ SkillSinging, /*13909*/ SkillSneak, /*13910*/ SkillSpecializeAbjure, // No idea why they truncated this one..especially when there are longer ones... /*13911*/ SkillSpecializeAlteration, -/*13912*/ SkillSpecializeConjuration, +/*13912*/ SkillSpecializeConjuration, // 45 /*13913*/ SkillSpecializeDivination, /*13914*/ SkillSpecializeEvocation, /*13915*/ SkillPickPockets, /*13916*/ SkillStringedInstruments, -/*13917*/ SkillSwimming, +/*13917*/ SkillSwimming, // 50 /*13919*/ SkillThrowing, /*13920*/ SkillTigerClaw, /*13921*/ SkillTracking, /*13923*/ SkillWindInstruments, -/*13854*/ SkillFishing, +/*13854*/ SkillFishing, // 55 /*13853*/ SkillMakePoison, /*13852*/ SkillTinkering, /*13851*/ SkillResearch, /*13850*/ SkillAlchemy, -/*13865*/ SkillBaking, +/*13865*/ SkillBaking, // 60 /*13918*/ SkillTailoring, /*13907*/ SkillSenseTraps, /*13870*/ SkillBlacksmithing, /*13887*/ SkillFletching, -/*13873*/ SkillBrewing, +/*13873*/ SkillBrewing, // 65 /*13860*/ SkillAlcoholTolerance, /*13868*/ SkillBegging, /*13892*/ SkillJewelryMaking, /*13901*/ SkillPottery, -/*13898*/ SkillPercussionInstruments, +/*13898*/ SkillPercussionInstruments, // 70 /*13922*/ SkillIntimidation, /*13869*/ SkillBerserking, /*13902*/ SkillTaunt, -/*05837*/ SkillFrenzy, // This appears to be the only listed one not grouped with the others +/*05837*/ SkillFrenzy, // 74 // This appears to be the only listed one not grouped with the others // SoF+ specific skills -/*03670*/ SkillRemoveTraps, +/*03670*/ SkillRemoveTraps, // 75 /*13049*/ SkillTripleAttack, // RoF2+ specific skills -// /*00789*/ Skill2HPiercing, +/*00789*/ Skill2HPiercing, // 77 // /*01216*/ SkillNone, // This needs to move down as new skills are added /*00000*/ _EmuSkillCount // move to last position of active enumeration labels @@ -171,101 +167,13 @@ enum SkillUseTypes }; // temporary until it can be sorted out... -#define HIGHEST_SKILL SkillTripleAttack +#define HIGHEST_SKILL Skill2HPiercing // Spell Effects use this value to determine if an effect applies to all skills. #define ALL_SKILLS -1 // server profile does not reflect this yet..so, prefixed with 'PACKET_' #define PACKET_SKILL_ARRAY_SIZE 100 -// TODO: add string return for skill names - -/* -** Old typedef enumeration -** -*/ -/* Correct Skill Numbers as of 4-14-2002 -typedef enum { - _1H_BLUNT = 0, - _1H_SLASHING = 1, - _2H_BLUNT = 2, - _2H_SLASHING = 3, - ABJURE = 4, - ALTERATION = 5, - APPLY_POISON = 6, - ARCHERY = 7, - BACKSTAB = 8, - BIND_WOUND = 9, - BASH = 10, - BLOCKSKILL = 11, - BRASS_INSTRUMENTS = 12, - CHANNELING = 13, - CONJURATION = 14, - DEFENSE = 15, - DISARM = 16, - DISARM_TRAPS = 17, - DIVINATION = 18, - DODGE = 19, - DOUBLE_ATTACK = 20, - DRAGON_PUNCH = 21, //aka Tail Rake - DUAL_WIELD = 22, - EAGLE_STRIKE = 23, - EVOCATION = 24, - FEIGN_DEATH = 25, - FLYING_KICK = 26, - FORAGE = 27, - HAND_TO_HAND = 28, - HIDE = 29, - KICK = 30, - MEDITATE = 31, - MEND = 32, - OFFENSE = 33, - PARRY = 34, - PICK_LOCK = 35, - PIERCING = 36, - RIPOSTE = 37, - ROUND_KICK = 38, - SAFE_FALL = 39, - SENSE_HEADING = 40, - SINGING = 41, - SNEAK = 42, - SPECIALIZE_ABJURE = 43, - SPECIALIZE_ALTERATION = 44, - SPECIALIZE_CONJURATION = 45, - SPECIALIZE_DIVINATION = 46, - SPECIALIZE_EVOCATION = 47, - PICK_POCKETS = 48, - STRINGED_INSTRUMENTS = 49, - SWIMMING = 50, - THROWING = 51, - TIGER_CLAW = 52, - TRACKING = 53, - WIND_INSTRUMENTS = 54, - FISHING = 55, - MAKE_POISON = 56, - TINKERING = 57, - RESEARCH = 58, - ALCHEMY = 59, - BAKING = 60, - TAILORING = 61, - SENSE_TRAPS = 62, - BLACKSMITHING = 63, - FLETCHING = 64, - BREWING = 65, - ALCOHOL_TOLERANCE = 66, - BEGGING = 67, - JEWELRY_MAKING = 68, - POTTERY = 69, - PERCUSSION_INSTRUMENTS = 70, - INTIMIDATION = 71, - BERSERKING = 72, - TAUNT = 73, - FRENZY = 74, - GENERIC_TRADESKILL = 75 -} SkillType; - -#define HIGHEST_SKILL FRENZY -*/ // for skill related helper functions namespace EQEmu { @@ -273,6 +181,8 @@ namespace EQEmu { bool IsSpecializedSkill(SkillUseTypes skill); float GetSkillMeleePushForce(SkillUseTypes skill); bool IsBardInstrumentSkill(SkillUseTypes skill); + + const std::map& GetSkillUseTypesMap(); } #endif diff --git a/common/version.h b/common/version.h index 00a999add..04bf9189c 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9094 +#define CURRENT_BINARY_DATABASE_VERSION 9096 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9000 #else diff --git a/shared_memory/main.cpp b/shared_memory/main.cpp index 3d47f217f..11d21153b 100644 --- a/shared_memory/main.cpp +++ b/shared_memory/main.cpp @@ -62,6 +62,18 @@ int main(int argc, char **argv) { database.LoadLogSettings(Log.log_settings); Log.StartFileLogs(); + database.LoadVariables(); + + /* If we're running shared memory and hotfix has no custom name, we probably want to start from scratch... */ + char db_hotfix_name[256] = { 0 }; + if (database.GetVariable("hotfix_name", db_hotfix_name, 256)) { + if (strlen(db_hotfix_name) > 0 && strcasecmp("hotfix_", db_hotfix_name) == 0) { + Log.Out(Logs::General, Logs::Status, "Current hotfix in variables is the default %s, clearing out variable", db_hotfix_name); + std::string query = StringFormat("UPDATE `variables` SET `value`='' WHERE (`varname`='hotfix_name')"); + database.QueryDatabase(query); + } + } + std::string hotfix_name = ""; bool load_all = true; bool load_items = false; diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 6afb7209e..8ae8a1a69 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -540,6 +540,9 @@ OP_FeignDeath=0x52fa OP_Mend=0x0ecf OP_Bind_Wound=0x0386 OP_LDoNOpen=0x3d5c +#OP_LDoNDisarmTraps= #Same as OP_DisarmTraps in RoF +OP_LDoNPickLock=0x9be3 +OP_LDoNInspect=0x0438 # Task packets OP_TaskDescription=0x3714 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index e3af9aa7d..1e57a202d 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -535,6 +535,9 @@ OP_InstillDoubt=0x221a # C OP_FeignDeath=0x002b # C OP_Mend=0x10a6 # C OP_LDoNOpen=0x032b # C +OP_LDoNDisarmTraps=0x1a84 +OP_LDoNPickLock=0x0370 +OP_LDoNInspect=0x0aaa # Task packets OP_TaskActivityComplete=0x5832 # C diff --git a/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql b/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql deleted file mode 100644 index a48b3318b..000000000 --- a/utils/scripts/bot_command_spell_scripts/bind_affinity_spells.sql +++ /dev/null @@ -1,78 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '14' - AND '25' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY mana_cost DESC, - FIELD(target_type, 'Single'), - spell_level, - FIELD(caster_class, 'CLERIC', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/charm_spells.sql b/utils/scripts/bot_command_spell_scripts/charm_spells.sql deleted file mode 100644 index f2c5e82b8..000000000 --- a/utils/scripts/bot_command_spell_scripts/charm_spells.sql +++ /dev/null @@ -1,73 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' - WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' - WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' - WHEN `targettype` = '16' AND `CastRestriction` = '0' THEN 'Plant' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `ResistDiff` resist_diff, - `max1` max_target_level --- extra - -FROM ( - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '22' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY resist_diff, - FIELD(target_type, 'Animal', 'Undead', 'Summoned', 'Plant', 'Single'), - max_target_level DESC, - spell_level, - FIELD(caster_class, 'DRUID', 'SHAMAN', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/cure_spells.sql b/utils/scripts/bot_command_spell_scripts/cure_spells.sql deleted file mode 100644 index 75ef1d25c..000000000 --- a/utils/scripts/bot_command_spell_scripts/cure_spells.sql +++ /dev/null @@ -1,193 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - ( - (IF(('20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '1', '0')) | - (IF(('35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '2', '0')) | - (IF(('36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '4', '0')) | - (IF(('116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '8', '0')) | - (IF(('369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '16', '0')) - ) cure_mask --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'BARD' caster_class, `classes8` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes8` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` = '1' --- 6-self, 10-undead, 14-pet, 45-ring - AND `targettype` NOT IN ('6', '10', '14', '45') - AND ( --- 20-blindness, 35-disease, 36-poison, 116-curse, 369-corruption - '20' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '35' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '36' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '116' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '369' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - spell_level DESC, - cure_mask DESC, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'BARD', 'SHAMAN', 'NECROMANCER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/depart_spells.sql b/utils/scripts/bot_command_spell_scripts/depart_spells.sql deleted file mode 100644 index 205ba27f1..000000000 --- a/utils/scripts/bot_command_spell_scripts/depart_spells.sql +++ /dev/null @@ -1,61 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - CONCAT('"', `teleport_zone`, '"') short_name, - CONCAT('"', IFNULL((SELECT `long_name` FROM `zone` WHERE `short_name` = `teleport_zone` LIMIT 1), 'Unreachable Destination'), '"') long_name --- extra - -FROM ( - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `teleport_zone` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND ( - '83' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '86' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR ( - '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` NOT LIKE 'same' - ) - ) -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `teleport_zone` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND ( - '83' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '86' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR ( - '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` NOT LIKE 'same' - ) - ) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'GroupV1'), - FIELD(caster_class, 'DRUID', 'WIZARD'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/escape_spells.sql b/utils/scripts/bot_command_spell_scripts/escape_spells.sql deleted file mode 100644 index 4e08ddeb0..000000000 --- a/utils/scripts/bot_command_spell_scripts/escape_spells.sql +++ /dev/null @@ -1,45 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` LIKE 'same' -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` = '40' - AND '88' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - AND `teleport_zone` LIKE 'same' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'GroupV2'), - FIELD(caster_class, 'DRUID', 'WIZARD'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/grow_spells.sql b/utils/scripts/bot_command_spell_scripts/grow_spells.sql deleted file mode 100644 index 4dbca1a06..000000000 --- a/utils/scripts/bot_command_spell_scripts/grow_spells.sql +++ /dev/null @@ -1,39 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '10' --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '89' -- implementation restricted to `effectid1` - AND `effect_base_value1` > 100 -- implementation restricted to `effect_base_value1` -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single'), - FIELD(caster_class, 'SHAMAN'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql b/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql deleted file mode 100644 index 8545cab30..000000000 --- a/utils/scripts/bot_command_spell_scripts/invisibility_spells.sql +++ /dev/null @@ -1,151 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - CASE - WHEN `effectid1` = '12' THEN 'Living' - WHEN `effectid1` = '13' THEN 'See' - WHEN `effectid1` = '28' THEN 'Undead' - WHEN `effectid1` = '29' THEN 'Animal' - ELSE `effectid1` -- 'UNDEFINED' - END invis_type --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effectid1` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('5', '9') --- 6-self - AND `targettype` NOT IN ('6') --- 12-living, 13-see, 28-undead, 29-animal - AND `effectid1` IN ('12', '13', '28', '29') -- implementation restricted to `effectid1` -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(invis_type, 'Animal', 'Undead', 'Living', 'See'), - FIELD(target_type, 'Single', 'GroupV2'), - zone_type, - spell_level DESC, - spell_name, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/levitation_spells.sql b/utils/scripts/bot_command_spell_scripts/levitation_spells.sql deleted file mode 100644 index 2193c75b7..000000000 --- a/utils/scripts/bot_command_spell_scripts/levitation_spells.sql +++ /dev/null @@ -1,94 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'WIZARD' caster_class, `classes12` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes12` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '28') --- 6-self, 43-groupclientandpet - AND `targettype` NOT IN ('6', '43') - AND '57' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV2'), - zone_type, - spell_level DESC, - spell_name, - FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'NECROMANCER', 'WIZARD', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/lull_spells.sql b/utils/scripts/bot_command_spell_scripts/lull_spells.sql deleted file mode 100644 index 2d0989b85..000000000 --- a/utils/scripts/bot_command_spell_scripts/lull_spells.sql +++ /dev/null @@ -1,86 +0,0 @@ --- needs criteria refinement - -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' - WHEN `targettype` = '9' AND `CastRestriction` = '0' THEN 'Animal' - WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '12' - AND '18' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Animal', 'Undead', 'Single', 'AETarget'), - target_type, - zone_type, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'NECROMANCER', 'ENCHANTER'), - spell_level, - spell_id, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql b/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql deleted file mode 100644 index a23d62af6..000000000 --- a/utils/scripts/bot_command_spell_scripts/mesmerize_spells.sql +++ /dev/null @@ -1,76 +0,0 @@ --- needs criteria refinement - -SELECT --- base - CASE - WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '8' AND `CastRestriction` = '0' THEN 'AETarget' - WHEN `targettype` = '10' AND `CastRestriction` = '0' THEN 'Undead' - WHEN `targettype` = '11' AND `CastRestriction` = '0' THEN 'Summoned' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `ResistDiff` resist_diff, - `max1` max_target_level --- extra - -FROM ( - SELECT 'BARD' caster_class, `classes8` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes8` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `ResistDiff`, `max1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('12', '13', '25', '27', '41', '43') --- 45-ring - AND `targettype` NOT IN ('45') - AND `effectid1` = '31' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY resist_diff, - FIELD(target_type, 'Undead', 'Summoned', 'Single', 'AECaster', 'AETarget'), - max_target_level DESC, - spell_level DESC, - FIELD(caster_class, 'BARD', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER') diff --git a/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql b/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql deleted file mode 100644 index aaabf2fa2..000000000 --- a/utils/scripts/bot_command_spell_scripts/movement_speed_spells.sql +++ /dev/null @@ -1,74 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `effect_base_value2` base_speed --- extra - -FROM ( - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value2` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('7', '10') --- 6-self - AND `targettype` NOT IN ('6') - AND `CastRestriction` = '0' - AND `effectdescnum` = '65' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - effect_base_value2 DESC, - spell_level, - FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/resistance_spells.sql b/utils/scripts/bot_command_spell_scripts/resistance_spells.sql deleted file mode 100644 index 0cda671e7..000000000 --- a/utils/scripts/bot_command_spell_scripts/resistance_spells.sql +++ /dev/null @@ -1,221 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - ( - (IF(('46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '1', '0')) | - (IF(('47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '2', '0')) | - (IF(('48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '4', '0')) | - (IF(('49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '8', '0')) | - (IF(('50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '16', '0')) | - (IF(('370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`)), '32', '0')) - ) resist_type --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHADOWKNIGHT' caster_class, `classes5` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes5` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'MAGICIAN' caster_class, `classes13` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes13` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, - `effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' --- 6-self, 14-pet, 39-groupnopets, 46-targetstarget - AND `targettype` NOT IN ('6', '14', '39', '46') - AND ( - - '46' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '47' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '48' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '49' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '50' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - OR '370' IN (`effectid1`, `effectid2`, `effectid3`, `effectid4`, `effectid5`, `effectid6`, `effectid7`, `effectid8`, `effectid9`, `effectid10`, `effectid11`, `effectid12`) - ) -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - spell_level DESC, - resist_type DESC, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'RANGER', 'SHADOWKNIGHT', 'DRUID', 'SHAMAN', 'NECROMANCER', 'MAGICIAN', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql b/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql deleted file mode 100644 index ac5903727..000000000 --- a/utils/scripts/bot_command_spell_scripts/resurrect_spells.sql +++ /dev/null @@ -1,71 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '4' AND `CastRestriction` = '0' THEN 'AECaster' - WHEN `targettype` = '15' AND `CastRestriction` = '0' THEN 'Corpse' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `effect_base_value1` percent --- extra - -FROM ( - SELECT 'CLERIC' caster_class, `classes2` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes2` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'PALADIN' caster_class, `classes3` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes3` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `effect_base_value1` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('1', '13') - AND `effectid1` = '81' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY percent DESC, - FIELD(target_type, 'Corpse', 'AETarget'), - zone_type, - FIELD(caster_class, 'CLERIC', 'PALADIN', 'DRUID', 'SHAMAN', 'NECROMANCER'), - spell_level, - spell_id, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/rune_spells.sql b/utils/scripts/bot_command_spell_scripts/rune_spells.sql deleted file mode 100644 index 30ebee130..000000000 --- a/utils/scripts/bot_command_spell_scripts/rune_spells.sql +++ /dev/null @@ -1,40 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '3' AND `CastRestriction` = '0' THEN 'GroupV1' - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost, --- base --- extra - `max1` max_absorbtion --- extra - -FROM ( - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana`, `max1` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` = '2' - AND `effectid1` = '55' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV1', 'GroupV2'), - spell_level DESC, - max1 DESC diff --git a/utils/scripts/bot_command_spell_scripts/shrink_spells.sql b/utils/scripts/bot_command_spell_scripts/shrink_spells.sql deleted file mode 100644 index 26ee84883..000000000 --- a/utils/scripts/bot_command_spell_scripts/shrink_spells.sql +++ /dev/null @@ -1,49 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` = '10' --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '89' -- implementation restricted to `effectid1` - AND `effect_base_value1` < 100 -- implementation restricted to `effect_base_value1` -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` = '10' --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '89' -- implementation restricted to `effectid1` - AND `effect_base_value1` < 100 -- implementation restricted to `effect_base_value1` -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single'), - FIELD(caster_class, 'SHAMAN', 'BEASTLORD'), - spell_level, - spell_name diff --git a/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql b/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql deleted file mode 100644 index b6f815429..000000000 --- a/utils/scripts/bot_command_spell_scripts/water_breathing_spells.sql +++ /dev/null @@ -1,84 +0,0 @@ -SELECT --- base - CASE - WHEN `targettype` = '5' AND `CastRestriction` = '0' THEN 'Single' - WHEN `targettype` = '41' AND `CastRestriction` = '0' THEN 'GroupV2' - ELSE CONCAT(`targettype`, ', ', `CastRestriction`) -- 'UNDEFINED' - END target_type, - CASE - WHEN `zonetype` NOT IN ('-1', '0') THEN `zonetype` - ELSE '0' - END zone_type, - caster_class, - spell_level, - `id` spell_id, - CONCAT('"', `name`, '"') spell_name, - `mana` mana_cost --- base - -FROM ( - SELECT 'RANGER' caster_class, `classes4` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes4` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'DRUID' caster_class, `classes6` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes6` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'SHAMAN' caster_class, `classes10` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes10` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'NECROMANCER' caster_class, `classes11` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes11` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'ENCHANTER' caster_class, `classes14` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes14` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -UNION ALL - SELECT 'BEASTLORD' caster_class, `classes15` spell_level, - `targettype`, `CastRestriction`, `zonetype`, `id`, `name`, `mana` - FROM `spells_new` - WHERE `classes15` NOT IN ('254', '255') - AND `SpellAffectIndex` IN ('2', '14') --- 6-self - AND `targettype` NOT IN ('6') - AND `effectid1` = '14' -) spells - --- WHERE `name` NOT LIKE '%II' --- --- --- WHERE `name` NOT LIKE '%Rk. II%' --- AND `name` NOT LIKE '%Rk.II%' --- AND `name` NOT LIKE '%Rk. III%' --- AND `name` NOT LIKE '%Rk.III%' -ORDER BY FIELD(target_type, 'Single', 'GroupV2'), - spell_level, - spell_name, - FIELD(caster_class, 'RANGER', 'DRUID', 'SHAMAN', 'NECROMANCER', 'ENCHANTER', 'BEASTLORD') diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 86f7ebe7c..6f48f983e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -348,6 +348,8 @@ 9092|2015_12_17_eqtime.sql|SHOW TABLES LIKE 'eqtime'|empty| 9093|2015_12_21_items_updates_evoitem.sql|SHOW COLUMNS FROM `items` LIKE 'evoitem'|empty| 9094|2015_12_29_quest_zone_events.sql|SELECT * FROM perl_event_export_settings WHERE event_description = 'EVENT_SPAWN_ZONE'|empty| +9095|2016_01_08_command_find_aliases.sql|SELECT * FROM `command_settings` WHERE `command` LIKE 'findaliases'|empty| +9096|2016_03_05_secondary_recall.sql|SHOW COLUMNS FROM `character_bind` LIKE 'slot'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2016_01_08_command_find_aliases.sql b/utils/sql/git/required/2016_01_08_command_find_aliases.sql new file mode 100644 index 000000000..ad798dd6a --- /dev/null +++ b/utils/sql/git/required/2016_01_08_command_find_aliases.sql @@ -0,0 +1 @@ +INSERT INTO `command_settings` VALUES ('findaliases', 0, 'fa'); diff --git a/utils/sql/git/required/2016_03_05_secondary_recall.sql b/utils/sql/git/required/2016_03_05_secondary_recall.sql new file mode 100644 index 000000000..7b0f02754 --- /dev/null +++ b/utils/sql/git/required/2016_03_05_secondary_recall.sql @@ -0,0 +1,6 @@ +ALTER TABLE `character_bind` ADD `slot` int(4) AFTER `id`; +UPDATE `character_bind` SET `slot`='0' WHERE `is_home`=0; +UPDATE `character_bind` SET `slot`='4' WHERE `is_home`=1; +ALTER TABLE `character_bind` DROP PRIMARY KEY, ADD PRIMARY KEY(`id`, `slot`); +ALTER TABLE `character_bind` DROP COLUMN `is_home`; + diff --git a/world/client.cpp b/world/client.cpp index 9a194e5ec..dc17d7b4d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1814,6 +1814,11 @@ void Client::SetClassStartingSkills(PlayerProfile_Struct *pp) pp->skills[i] = database.GetSkillCap(pp->class_, (SkillUseTypes)i, 1); } } + + if (cle->GetClientVersion() < static_cast(ClientVersion::RoF2) && pp->class_ == BERSERKER) { + pp->skills[Skill1HPiercing] = pp->skills[Skill2HPiercing]; + pp->skills[Skill2HPiercing] = 0; + } } void Client::SetRaceStartingSkills( PlayerProfile_Struct *pp ) diff --git a/world/worlddb.cpp b/world/worlddb.cpp index b09758888..357ab3c33 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -159,10 +159,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou } /* Set Bind Point Data for any character that may possibly be missing it for any reason */ - cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `is_home` FROM `character_bind` WHERE `id` = %i LIMIT 2", character_id); + cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind` WHERE `id` = %i LIMIT 5", character_id); auto results_bind = database.QueryDatabase(cquery); for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) { - if (row_b[6] && atoi(row_b[6]) == 1){ has_home = 1; } + if (row_b[6] && atoi(row_b[6]) == 4){ has_home = 1; } if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; } } @@ -189,14 +189,14 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou pp.binds[0] = pp.binds[4]; /* If no home bind set, set it */ if (has_home == 0) { - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", - character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 1); + character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4); auto results_bset = QueryDatabase(query); } /* If no regular bind set, set it */ if (has_bind == 0) { - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" + std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)" " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0); auto results_bset = QueryDatabase(query); @@ -285,7 +285,7 @@ int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum) bindnum = 0; } - std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND is_home = %u LIMIT 1", CharID, bindnum == 4 ? 1 : 0); + std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND slot = %u LIMIT 1", CharID, bindnum); auto results = database.QueryDatabase(query); if(!results.Success() || results.RowCount() == 0) { return 0; diff --git a/zone/attack.cpp b/zone/attack.cpp index 532a53686..858e6aee9 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -76,7 +76,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w case ItemType1HPiercing: // Piercing { skillinuse = Skill1HPiercing; - type = animPiercing; + type = anim1HPiercing; break; } case ItemType1HBlunt: // 1H Blunt @@ -93,7 +93,10 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } case ItemType2HPiercing: // 2H Piercing { - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated + if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + skillinuse = Skill1HPiercing; + else + skillinuse = Skill2HPiercing; type = anim2HWeapon; break; } @@ -127,7 +130,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w } case Skill1HPiercing: // Piercing { - type = animPiercing; + type = anim1HPiercing; break; } case Skill1HBlunt: // 1H Blunt @@ -140,7 +143,7 @@ bool Mob::AttackAnimation(SkillUseTypes &skillinuse, int Hand, const ItemInst* w type = anim2HSlashing; //anim2HWeapon break; } - case 99: // 2H Piercing // change to Skill2HPiercing once activated + case Skill2HPiercing: // 2H Piercing { type = anim2HWeapon; break; @@ -928,231 +931,108 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate int banedmg = 0; int x = 0; - if(!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)){ + if (!against || against->GetInvul() || against->GetSpecialAbility(IMMUNE_MELEE)) return 0; - } - //check for items being illegally attained - if(weapon_item){ - const Item_Struct *mWeaponItem = weapon_item->GetItem(); - if(mWeaponItem){ - if(mWeaponItem->ReqLevel > GetLevel()){ - return 0; - } - - if(!weapon_item->IsEquipable(GetBaseRace(), GetClass())){ - return 0; - } - } - else{ + // check for items being illegally attained + if (weapon_item) { + if (!weapon_item->GetItem()) + return 0; + + if (weapon_item->GetItemRequiredLevel(true) > GetLevel()) + return 0; + + if (!weapon_item->IsEquipable(GetBaseRace(), GetClass())) return 0; - } } - if(against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)){ - if(weapon_item){ + if (against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) { + if (weapon_item) { // check to see if the weapon is magic - bool MagicWeapon = false; - if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) - MagicWeapon = true; - else - if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) - MagicWeapon = true; + bool MagicWeapon = weapon_item->GetItemMagical(true) || spellbonuses.MagicWeapon || itembonuses.MagicWeapon; + if (MagicWeapon) { + auto rec_level = weapon_item->GetItemRecommendedLevel(true); + if (IsClient() && GetLevel() < rec_level) + dmg = CastToClient()->CalcRecommendedLevelBonus( + GetLevel(), rec_level, weapon_item->GetItemWeaponDamage(true)); else - // An augment on the weapon that is marked magic makes - // the item magical. - for(x = 0; MagicWeapon == false && x < EmuConstants::ITEM_COMMON_SIZE; x++) - { - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()) - { - if (weapon_item->GetAugment(x)->GetItem()->Magic) - MagicWeapon = true; - } - } - - if(MagicWeapon) { - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; - } - - for(int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } + dmg = weapon_item->GetItemWeaponDamage(true); dmg = dmg <= 0 ? 1 : dmg; - } - else + } else { return 0; - } - else{ - bool MagicGloves=false; + } + } else { + bool MagicGloves = false; if (IsClient()) { - ItemInst *gloves=CastToClient()->GetInv().GetItem(MainHands); - if (gloves != nullptr) { - MagicGloves = gloves->GetItem()->Magic; - } + const ItemInst *gloves = CastToClient()->GetInv().GetItem(MainHands); + if (gloves) + MagicGloves = gloves->GetItemMagical(true); } - if((GetClass() == MONK || GetClass() == BEASTLORD)) { - if(MagicGloves || GetLevel() >= 30){ + if (GetClass() == MONK || GetClass() == BEASTLORD) { + if (MagicGloves || GetLevel() >= 30) { dmg = GetHandToHandDamage(); - if (hate) *hate += dmg; + if (hate) + *hate += dmg; } - } - else if(GetOwner() && GetLevel() >= RuleI(Combat, PetAttackMagicLevel)){ //pets wouldn't actually use this but... - dmg = 1; //it gives us an idea if we can hit - } - else if(MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)){ + } else if (GetOwner() && + GetLevel() >= + RuleI(Combat, PetAttackMagicLevel)) { // pets wouldn't actually use this but... + dmg = 1; // it gives us an idea if we can hit + } else if (MagicGloves || GetSpecialAbility(SPECATK_MAGICAL)) { dmg = 1; - } - else + } else return 0; } - } - else{ - if(weapon_item){ - if(weapon_item->GetItem()){ - - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - dmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->Damage); - } - else{ - dmg = weapon_item->GetItem()->Damage; + } else { + if (weapon_item) { + if (weapon_item->GetItem()) { + auto rec_level = weapon_item->GetItemRecommendedLevel(true); + if (IsClient() && GetLevel() < rec_level) { + dmg = CastToClient()->CalcRecommendedLevelBonus( + GetLevel(), rec_level, weapon_item->GetItemWeaponDamage(true)); + } else { + dmg = weapon_item->GetItemWeaponDamage(true); } - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - dmg += weapon_item->GetAugment(x)->GetItem()->Damage; - if (hate) *hate += weapon_item->GetAugment(x)->GetItem()->Damage + weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt; - } - } dmg = dmg <= 0 ? 1 : dmg; } - } - else{ + } else { dmg = GetHandToHandDamage(); - if (hate) *hate += dmg; + if (hate) + *hate += dmg; } } int eledmg = 0; - if(!against->GetSpecialAbility(IMMUNE_MAGIC)){ - if(weapon_item && weapon_item->GetItem() && weapon_item->GetItem()->ElemDmgAmt){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - eledmg = CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->ElemDmgAmt); - } - else{ - eledmg = weapon_item->GetItem()->ElemDmgAmt; - } - - if(eledmg) - { - eledmg = (eledmg * against->ResistSpell(weapon_item->GetItem()->ElemDmgType, 0, this) / 100); - } - } - - if(weapon_item){ - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt) - eledmg += (weapon_item->GetAugment(x)->GetItem()->ElemDmgAmt * against->ResistSpell(weapon_item->GetAugment(x)->GetItem()->ElemDmgType, 0, this) / 100); - } - } - } + if (!against->GetSpecialAbility(IMMUNE_MAGIC)) { + if (weapon_item && weapon_item->GetItem() && weapon_item->GetItemElementalFlag(true)) + // the client actually has the way this is done, it does not appear to check req! + eledmg = against->ResistElementalWeaponDmg(weapon_item); } - if(against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)){ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } + if (weapon_item && weapon_item->GetItem() && + (weapon_item->GetItemBaneDamageBody(true) || weapon_item->GetItemBaneDamageRace(true))) + banedmg = against->CheckBaneDamage(weapon_item); - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } - } - - if(!eledmg && !banedmg) - { - if(!GetSpecialAbility(SPECATK_BANE)) + if (against->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) { + if (!eledmg && !banedmg) { + if (!GetSpecialAbility(SPECATK_BANE)) return 0; else return 1; - } - else { + } else { dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; - } - } - else{ - if(weapon_item && weapon_item->GetItem()){ - if(weapon_item->GetItem()->BaneDmgBody == against->GetBodyType()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgAmt; - } - } - - if(weapon_item->GetItem()->BaneDmgRace == against->GetRace()){ - if(IsClient() && GetLevel() < weapon_item->GetItem()->RecLevel){ - banedmg += CastToClient()->CalcRecommendedLevelBonus(GetLevel(), weapon_item->GetItem()->RecLevel, weapon_item->GetItem()->BaneDmgRaceAmt); - } - else{ - banedmg += weapon_item->GetItem()->BaneDmgRaceAmt; - } - } - - for (int x = 0; x < EmuConstants::ITEM_COMMON_SIZE; x++){ - if(weapon_item->GetAugment(x) && weapon_item->GetAugment(x)->GetItem()){ - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgBody == against->GetBodyType()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgAmt; - } - - if(weapon_item->GetAugment(x)->GetItem()->BaneDmgRace == against->GetRace()){ - banedmg += weapon_item->GetAugment(x)->GetItem()->BaneDmgRaceAmt; - } - } - } + if (hate) + *hate += banedmg; } + } else { dmg += (banedmg + eledmg); - if (hate) *hate += banedmg; + if (hate) + *hate += banedmg; } - if(dmg <= 0){ - return 0; - } - else - return dmg; + return std::max(0, dmg); } //note: throughout this method, setting `damage` to a negative is a way to @@ -1775,10 +1655,10 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool skillinuse = Skill2HSlashing; break; case ItemType1HPiercing: - //skillinuse = Skill1HPiercing; - //break; + skillinuse = Skill1HPiercing; + break; case ItemType2HPiercing: - skillinuse = Skill1HPiercing; // change to Skill2HPiercing once activated + skillinuse = Skill2HPiercing; break; case ItemType1HBlunt: skillinuse = Skill1HBlunt; @@ -1806,11 +1686,6 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool ItemInst weapon_inst(weapon, charges); AttackAnimation(skillinuse, Hand, &weapon_inst); - // Remove this once Skill2HPiercing is activated - //Work-around for there being no 2HP skill - We use 99 for the 2HB animation and 36 for pierce messages - if(skillinuse == 99) - skillinuse = static_cast(36); - //basically "if not immune" then do the attack if((weapon_damage) > 0) { @@ -1999,50 +1874,52 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes attack } } -bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill) { - Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", killer_mob->GetName(), damage, spell, attack_skill); +bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attack_skill) +{ + Log.Out(Logs::Detail, Logs::Combat, "Fatal blow dealt by %s with %d damage, spell %d, skill %d", + ((killer_mob) ? (killer_mob->GetName()) : ("[nullptr]")), damage, spell, attack_skill); Mob *oos = nullptr; - if(killer_mob) { + if (killer_mob) { oos = killer_mob->GetOwnerOrSelf(); char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) - { - if(GetHP() < 0) { + snprintf(buffer, 47, "%d %d %d %d", killer_mob->GetID(), damage, spell, static_cast(attack_skill)); + + if (parse->EventNPC(EVENT_DEATH, this, oos, buffer, 0) != 0) { + if (GetHP() < 0) { SetHP(0); } return false; } - if(killer_mob && killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { - char val1[20]={0}; + if (killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { + char val1[20] = { 0 }; entity_list.MessageClose_StringID(this, false, 100, MT_NonMelee, HIT_NON_MELEE, killer_mob->GetCleanName(), GetCleanName(), ConvertArray(damage, val1)); } - } else { - + } + else { char buffer[48] = { 0 }; - snprintf(buffer, 47, "%d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill)); - if(parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) - { - if(GetHP() < 0) { + snprintf(buffer, 47, "%d %d %d %d", 0, damage, spell, static_cast(attack_skill)); + + if (parse->EventNPC(EVENT_DEATH, this, nullptr, buffer, 0) != 0) { + if (GetHP() < 0) { SetHP(0); } return false; } } - if (IsEngaged()) - { + if (IsEngaged()) { zone->DelAggroMob(); Log.Out(Logs::Detail, Logs::Attack, "%s Mobs currently Aggro %i", __FUNCTION__, zone->MobsAggroCount()); } + SetHP(0); SetPet(0); - if (GetSwarmOwner()){ + if (GetSwarmOwner()) { Mob* owner = entity_list.GetMobID(GetSwarmOwner()); if (owner) owner->SetTempPetCount(owner->GetTempPetCount() - 1); @@ -2052,14 +1929,24 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac entity_list.RemoveFromTargets(this, p_depop); - if(p_depop == true) + if (p_depop == true) return false; HasAISpellEffects = false; BuffFadeAll(); uint8 killed_level = GetLevel(); - EQApplicationPacket* app= new EQApplicationPacket(OP_Death,sizeof(Death_Struct)); + if (GetClass() == LDON_TREASURE) { // open chest + EQApplicationPacket* outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); + Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; + anim->spawnid = GetID(); + anim->action = 0x0F; + anim->speed = 10; + entity_list.QueueCloseClients(this, outapp); + safe_delete(outapp); + } + + EQApplicationPacket* app = new EQApplicationPacket(OP_Death, sizeof(Death_Struct)); Death_Struct* d = (Death_Struct*)app->pBuffer; d->spawn_id = GetID(); d->killer_id = killer_mob ? killer_mob->GetID() : 0; @@ -2070,55 +1957,49 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac app->priority = 6; entity_list.QueueClients(killer_mob, app, false); - if(respawn2) { + safe_delete(app); + + if (respawn2) { respawn2->DeathReset(1); } - if (killer_mob) { - if(GetClass() != LDON_TREASURE) - hate_list.AddEntToHateList(killer_mob, damage); - } - - safe_delete(app); + if (killer_mob && GetClass() != LDON_TREASURE) + hate_list.AddEntToHateList(killer_mob, damage); Mob *give_exp = hate_list.GetDamageTopOnHateList(this); - if(give_exp == nullptr) + if (give_exp == nullptr) give_exp = killer; - if(give_exp && give_exp->HasOwner()) { + if (give_exp && give_exp->HasOwner()) { bool ownerInGroup = false; - if((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) + if ((give_exp->HasGroup() && give_exp->GetGroup()->IsGroupMember(give_exp->GetUltimateOwner())) || (give_exp->IsPet() && (give_exp->GetOwner()->IsClient() - || ( give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner()))))) + || (give_exp->GetOwner()->HasGroup() && give_exp->GetOwner()->GetGroup()->IsGroupMember(give_exp->GetOwner()->GetUltimateOwner()))))) ownerInGroup = true; give_exp = give_exp->GetUltimateOwner(); #ifdef BOTS - if(!RuleB(Bots, BotGroupXP) && !ownerInGroup) { + if (!RuleB(Bots, BotGroupXP) && !ownerInGroup) { give_exp = nullptr; } #endif //BOTS } - if(give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) { - - if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()){ - Mob* temp_owner = nullptr; - temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner()); - + if (give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) { + if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()) { + Mob* temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner()); if (temp_owner) give_exp = temp_owner; } } - int PlayerCount = 0; // QueryServ Player Counting Client *give_exp_client = nullptr; - if(give_exp && give_exp->IsClient()) + if (give_exp && give_exp->IsClient()) give_exp_client = give_exp->CastToClient(); //do faction hits even if we are a merchant, so long as a player killed us @@ -2126,43 +2007,43 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac hate_list.DoFactionHits(GetNPCFactionID()); bool IsLdonTreasure = (this->GetClass() == LDON_TREASURE); - if (give_exp_client && !IsCorpse()) - { + + if (give_exp_client && !IsCorpse()) { Group *kg = entity_list.GetGroupByClient(give_exp_client); Raid *kr = entity_list.GetRaidByClient(give_exp_client); int32 finalxp = EXP_FORMULA; finalxp = give_exp_client->mod_client_xp(finalxp, this); - if(kr) - { - if(!IsLdonTreasure && MerchantType == 0) { + if (kr) { + if (!IsLdonTreasure && MerchantType == 0) { kr->SplitExp((finalxp), this); - if(killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()))) - killer_mob->TrySpellOnKill(killed_level,spell); + if (killer_mob && (kr->IsRaidMember(killer_mob->GetName()) || kr->IsRaidMember(killer_mob->GetUltimateOwner()->GetName()))) + killer_mob->TrySpellOnKill(killed_level, spell); } + /* Send the EVENT_KILLED_MERIT event for all raid members */ for (int i = 0; i < MAX_RAID_MEMBERS; i++) { if (kr->members[i].member != nullptr && kr->members[i].member->IsClient()) { // If Group Member is Client Client *c = kr->members[i].member; parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - if(RuleB(NPC, EnableMeritBasedFaction)) + if (RuleB(NPC, EnableMeritBasedFaction)) c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); mod_npc_killed_merit(kr->members[i].member); - if(RuleB(TaskSystem, EnableTaskSystem)) + if (RuleB(TaskSystem, EnableTaskSystem)) kr->members[i].member->UpdateTasksOnKill(GetNPCTypeID()); PlayerCount++; } } // QueryServ Logging - Raid Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ + if (RuleB(QueryServ, PlayerLogNPCKills)) { ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); QS->s1.Type = 2; // Raid Fight @@ -2179,13 +2060,13 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac // End QueryServ Logging } - else if (give_exp_client->IsGrouped() && kg != nullptr) - { - if(!IsLdonTreasure && MerchantType == 0) { + else if (give_exp_client->IsGrouped() && kg != nullptr) { + if (!IsLdonTreasure && MerchantType == 0) { kg->SplitExp((finalxp), this); - if(killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()))) - killer_mob->TrySpellOnKill(killed_level,spell); + if (killer_mob && (kg->IsGroupMember(killer_mob->GetName()) || kg->IsGroupMember(killer_mob->GetUltimateOwner()->GetName()))) + killer_mob->TrySpellOnKill(killed_level, spell); } + /* Send the EVENT_KILLED_MERIT event and update kill tasks * for all group members */ for (int i = 0; i < MAX_GROUP_MEMBERS; i++) { @@ -2193,12 +2074,12 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac Client *c = kg->members[i]->CastToClient(); parse->EventNPC(EVENT_KILLED_MERIT, this, c, "killed", 0); - if(RuleB(NPC, EnableMeritBasedFaction)) + if (RuleB(NPC, EnableMeritBasedFaction)) c->SetFactionLevel(c->CharacterID(), GetNPCFactionID(), c->GetBaseClass(), c->GetBaseRace(), c->GetDeity()); mod_npc_killed_merit(c); - if(RuleB(TaskSystem, EnableTaskSystem)) + if (RuleB(TaskSystem, EnableTaskSystem)) c->UpdateTasksOnKill(GetNPCTypeID()); PlayerCount++; @@ -2206,10 +2087,10 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } // QueryServ Logging - Group Kills - if(RuleB(QueryServ, PlayerLogNPCKills)){ + if (RuleB(QueryServ, PlayerLogNPCKills)) { ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * PlayerCount)); PlayerCount = 0; - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); QS->s1.Type = 1; // Group Fight @@ -2225,36 +2106,34 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } // End QueryServ Logging } - else - { - if(!IsLdonTreasure && MerchantType == 0) { + else { + if (!IsLdonTreasure && MerchantType == 0) { int conlevel = give_exp->GetLevelCon(GetLevel()); - if (conlevel != CON_GREEN) - { - if(!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) - { + if (conlevel != CON_GREEN) { + if (!GetOwner() || (GetOwner() && !GetOwner()->IsClient())) { give_exp_client->AddEXP((finalxp), conlevel); - if(killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) - killer_mob->TrySpellOnKill(killed_level,spell); + if (killer_mob && (killer_mob->GetID() == give_exp_client->GetID() || killer_mob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) + killer_mob->TrySpellOnKill(killed_level, spell); } } } - /* Send the EVENT_KILLED_MERIT event */ + + /* Send the EVENT_KILLED_MERIT event */ parse->EventNPC(EVENT_KILLED_MERIT, this, give_exp_client, "killed", 0); - if(RuleB(NPC, EnableMeritBasedFaction)) + if (RuleB(NPC, EnableMeritBasedFaction)) give_exp_client->SetFactionLevel(give_exp_client->CharacterID(), GetNPCFactionID(), give_exp_client->GetBaseClass(), - give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); + give_exp_client->GetBaseRace(), give_exp_client->GetDeity()); mod_npc_killed_merit(give_exp_client); - if(RuleB(TaskSystem, EnableTaskSystem)) + if (RuleB(TaskSystem, EnableTaskSystem)) give_exp_client->UpdateTasksOnKill(GetNPCTypeID()); // QueryServ Logging - Solo - if(RuleB(QueryServ, PlayerLogNPCKills)){ + if (RuleB(QueryServ, PlayerLogNPCKills)) { ServerPacket* pack = new ServerPacket(ServerOP_QSPlayerLogNPCKills, sizeof(QSPlayerLogNPCKill_Struct) + (sizeof(QSPlayerLogNPCKillsPlayers_Struct) * 1)); - QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*) pack->pBuffer; + QSPlayerLogNPCKill_Struct* QS = (QSPlayerLogNPCKill_Struct*)pack->pBuffer; QS->s1.NPCID = this->GetNPCTypeID(); QS->s1.ZoneID = this->GetZoneID(); QS->s1.Type = 0; // Solo Fight @@ -2269,74 +2148,73 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } if (!HasOwner() && !IsMerc() && class_ != MERCHANT && class_ != ADVENTUREMERCHANT && !GetSwarmInfo() - && MerchantType == 0 && killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || + && MerchantType == 0 && ((killer && (killer->IsClient() || (killer->HasOwner() && killer->GetUltimateOwner()->IsClient()) || (killer->IsNPC() && killer->CastToNPC()->GetSwarmInfo() && killer->CastToNPC()->GetSwarmInfo()->GetOwner() && killer->CastToNPC()->GetSwarmInfo()->GetOwner()->IsClient()))) + || (killer_mob && IsLdonTreasure))) { - if(killer != 0) - { - if(killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) + if (killer != 0) { + if (killer->GetOwner() != 0 && killer->GetOwner()->IsClient()) killer = killer->GetOwner(); - if(!killer->CastToClient()->GetGM() && killer->IsClient()) + if (killer->IsClient() && !killer->CastToClient()->GetGM()) this->CheckMinMaxLevel(killer); } + entity_list.RemoveFromAutoXTargets(this); uint16 emoteid = this->GetEmoteID(); - Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata,level>54?RuleI(NPC,MajorNPCCorpseDecayTimeMS):RuleI(NPC,MinorNPCCorpseDecayTimeMS)); + Corpse* corpse = new Corpse(this, &itemlist, GetNPCTypeID(), &NPCTypedata, level>54 ? RuleI(NPC, MajorNPCCorpseDecayTimeMS) : RuleI(NPC, MinorNPCCorpseDecayTimeMS)); entity_list.LimitRemoveNPC(this); entity_list.AddCorpse(corpse, GetID()); entity_list.UnMarkNPC(GetID()); entity_list.RemoveNPC(GetID()); this->SetID(0); - if(killer != 0 && emoteid != 0) + + if (killer != 0 && emoteid != 0) corpse->CastToNPC()->DoNPCEmote(AFTERDEATH, emoteid); - if(killer != 0 && killer->IsClient()) { + if (killer != 0 && killer->IsClient()) { corpse->AllowPlayerLoot(killer, 0); - if(killer->IsGrouped()) { + if (killer->IsGrouped()) { Group* group = entity_list.GetGroupByClient(killer->CastToClient()); - if(group != 0) { - for(int i=0;i<6;i++) { // Doesnt work right, needs work - if(group->members[i] != nullptr) { - corpse->AllowPlayerLoot(group->members[i],i); + if (group != 0) { + for (int i = 0; i<6; i++) { // Doesnt work right, needs work + if (group->members[i] != nullptr) { + corpse->AllowPlayerLoot(group->members[i], i); } } } } - else if(killer->IsRaidGrouped()){ + else if (killer->IsRaidGrouped()) { Raid* r = entity_list.GetRaidByClient(killer->CastToClient()); - if(r){ + if (r) { int i = 0; - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - switch(r->GetLootType()) - { + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + switch (r->GetLootType()) { case 0: case 1: - if(r->members[x].member && r->members[x].IsRaidLeader){ + if (r->members[x].member && r->members[x].IsRaidLeader) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 2: - if(r->members[x].member && r->members[x].IsRaidLeader){ + if (r->members[x].member && r->members[x].IsRaidLeader) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } - else if(r->members[x].member && r->members[x].IsGroupLeader){ + else if (r->members[x].member && r->members[x].IsGroupLeader) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 3: - if(r->members[x].member && r->members[x].IsLooter){ + if (r->members[x].member && r->members[x].IsLooter) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } break; case 4: - if(r->members[x].member) - { + if (r->members[x].member) { corpse->AllowPlayerLoot(r->members[x].member, i); i++; } @@ -2346,42 +2224,42 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac } } } + else if (killer_mob && IsLdonTreasure) { + auto u_owner = killer_mob->GetUltimateOwner(); + if (u_owner->IsClient()) + corpse->AllowPlayerLoot(u_owner, 0); + } - if(zone && zone->adv_data) - { + if (zone && zone->adv_data) { ServerZoneAdventureDataReply_Struct *sr = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; - if(sr->type == Adventure_Kill) - { + if (sr->type == Adventure_Kill) { zone->DoAdventureCountIncrease(); } - else if(sr->type == Adventure_Assassinate) - { - if(sr->data_id == GetNPCTypeID()) - { + else if (sr->type == Adventure_Assassinate) { + if (sr->data_id == GetNPCTypeID()) { zone->DoAdventureCountIncrease(); } - else - { + else { zone->DoAdventureAssassinationCountIncrease(); } } } } - else + else { entity_list.RemoveFromXTargets(this); + } // Parse quests even if we're killed by an NPC - if(oos) { + if (oos) { mod_npc_killed(oos); uint16 emoteid = this->GetEmoteID(); - if(emoteid != 0) + if (emoteid != 0) this->DoNPCEmote(ONDEATH, emoteid); - if(oos->IsNPC()) - { + if (oos->IsNPC()) { parse->EventNPC(EVENT_NPC_SLAY, oos->CastToNPC(), this, "", 0); uint16 emoteid = oos->GetEmoteID(); - if(emoteid != 0) + if (emoteid != 0) oos->CastToNPC()->DoNPCEmote(KILLEDNPC, emoteid); killer_mob->TrySpellOnKill(killed_level, spell); } @@ -2389,7 +2267,8 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac WipeHateList(); p_depop = true; - if(killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted + + if (killer_mob && killer_mob->GetTarget() == this) //we can kill things without having them targeted killer_mob->SetTarget(nullptr); //via AE effects and such.. entity_list.UpdateFindableNPCState(this, true); @@ -2400,7 +2279,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, SkillUseTypes attac /* Zone controller process EVENT_DEATH_ZONE (Death events) */ if (RuleB(Zone, UseZoneController)) { - if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ + if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && this->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID) { char data_pass[100] = { 0 }; snprintf(data_pass, 99, "%d %d %d %d %d", killer_mob ? killer_mob->GetID() : 0, damage, spell, static_cast(attack_skill), this->GetNPCTypeID()); parse->EventNPC(EVENT_DEATH_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index f8edee26d..413b8d6c6 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -144,12 +144,12 @@ void Client::CalcItemBonuses(StatBonuses* newbon) { SetTwoHanderEquipped(false); unsigned int i; - //should not include 21 (SLOT_AMMO) - for (i = MainCharm; i < MainAmmo; i++) { + // Update: MainAmmo should only calc skill mods (TODO: Check for other cases) + for (i = MainCharm; i <= MainAmmo; i++) { const ItemInst* inst = m_inv[i]; if(inst == 0) continue; - AddItemBonuses(inst, newbon); + AddItemBonuses(inst, newbon, false, false, 0, (i == MainAmmo)); //These are given special flags due to how often they are checked for various spell effects. const Item_Struct *item = inst->GetItem(); @@ -207,354 +207,328 @@ void Client::ProcessItemCaps() itembonuses.ATK = std::min(itembonuses.ATK, CalcItemATKCap()); } -void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { - if(!inst || !inst->IsType(ItemClassCommon)) - { +void Client::AddItemBonuses(const ItemInst *inst, StatBonuses *newbon, bool isAug, bool isTribute, int rec_override, bool ammo_slot_item) +{ + if (!inst || !inst->IsType(ItemClassCommon)) { return; } - if(inst->GetAugmentType()==0 && isAug == true) - { + if (inst->GetAugmentType() == 0 && isAug == true) { return; } const Item_Struct *item = inst->GetItem(); - if(!isTribute && !inst->IsEquipable(GetBaseRace(),GetClass())) - { - if(item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) + if (!isTribute && !inst->IsEquipable(GetBaseRace(), GetClass())) { + if (item->ItemType != ItemTypeFood && item->ItemType != ItemTypeDrink) return; } - if(GetLevel() < item->ReqLevel) - { + if (GetLevel() < inst->GetItemRequiredLevel(true)) { return; } + + // So there isn't a very nice way to get the real rec level from the aug's inst, so we just pass it in, only + // used for augs + auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true); - if(GetLevel() >= item->RecLevel) - { - newbon->AC += item->AC; - newbon->HP += item->HP; - newbon->Mana += item->Mana; - newbon->Endurance += item->Endur; - newbon->ATK += item->Attack; - newbon->STR += (item->AStr + item->HeroicStr); - newbon->STA += (item->ASta + item->HeroicSta); - newbon->DEX += (item->ADex + item->HeroicDex); - newbon->AGI += (item->AAgi + item->HeroicAgi); - newbon->INT += (item->AInt + item->HeroicInt); - newbon->WIS += (item->AWis + item->HeroicWis); - newbon->CHA += (item->ACha + item->HeroicCha); + if (!ammo_slot_item) { + if (GetLevel() >= rec_level) { + newbon->AC += item->AC; + newbon->HP += item->HP; + newbon->Mana += item->Mana; + newbon->Endurance += item->Endur; + newbon->ATK += item->Attack; + newbon->STR += (item->AStr + item->HeroicStr); + newbon->STA += (item->ASta + item->HeroicSta); + newbon->DEX += (item->ADex + item->HeroicDex); + newbon->AGI += (item->AAgi + item->HeroicAgi); + newbon->INT += (item->AInt + item->HeroicInt); + newbon->WIS += (item->AWis + item->HeroicWis); + newbon->CHA += (item->ACha + item->HeroicCha); - newbon->MR += (item->MR + item->HeroicMR); - newbon->FR += (item->FR + item->HeroicFR); - newbon->CR += (item->CR + item->HeroicCR); - newbon->PR += (item->PR + item->HeroicPR); - newbon->DR += (item->DR + item->HeroicDR); - newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup); + newbon->MR += (item->MR + item->HeroicMR); + newbon->FR += (item->FR + item->HeroicFR); + newbon->CR += (item->CR + item->HeroicCR); + newbon->PR += (item->PR + item->HeroicPR); + newbon->DR += (item->DR + item->HeroicDR); + newbon->Corrup += (item->SVCorruption + item->HeroicSVCorrup); - newbon->STRCapMod += item->HeroicStr; - newbon->STACapMod += item->HeroicSta; - newbon->DEXCapMod += item->HeroicDex; - newbon->AGICapMod += item->HeroicAgi; - newbon->INTCapMod += item->HeroicInt; - newbon->WISCapMod += item->HeroicWis; - newbon->CHACapMod += item->HeroicCha; - newbon->MRCapMod += item->HeroicMR; - newbon->CRCapMod += item->HeroicFR; - newbon->FRCapMod += item->HeroicCR; - newbon->PRCapMod += item->HeroicPR; - newbon->DRCapMod += item->HeroicDR; - newbon->CorrupCapMod += item->HeroicSVCorrup; + newbon->STRCapMod += item->HeroicStr; + newbon->STACapMod += item->HeroicSta; + newbon->DEXCapMod += item->HeroicDex; + newbon->AGICapMod += item->HeroicAgi; + newbon->INTCapMod += item->HeroicInt; + newbon->WISCapMod += item->HeroicWis; + newbon->CHACapMod += item->HeroicCha; + newbon->MRCapMod += item->HeroicMR; + newbon->CRCapMod += item->HeroicFR; + newbon->FRCapMod += item->HeroicCR; + newbon->PRCapMod += item->HeroicPR; + newbon->DRCapMod += item->HeroicDR; + newbon->CorrupCapMod += item->HeroicSVCorrup; - newbon->HeroicSTR += item->HeroicStr; - newbon->HeroicSTA += item->HeroicSta; - newbon->HeroicDEX += item->HeroicDex; - newbon->HeroicAGI += item->HeroicAgi; - newbon->HeroicINT += item->HeroicInt; - newbon->HeroicWIS += item->HeroicWis; - newbon->HeroicCHA += item->HeroicCha; - newbon->HeroicMR += item->HeroicMR; - newbon->HeroicFR += item->HeroicFR; - newbon->HeroicCR += item->HeroicCR; - newbon->HeroicPR += item->HeroicPR; - newbon->HeroicDR += item->HeroicDR; - newbon->HeroicCorrup += item->HeroicSVCorrup; + newbon->HeroicSTR += item->HeroicStr; + newbon->HeroicSTA += item->HeroicSta; + newbon->HeroicDEX += item->HeroicDex; + newbon->HeroicAGI += item->HeroicAgi; + newbon->HeroicINT += item->HeroicInt; + newbon->HeroicWIS += item->HeroicWis; + newbon->HeroicCHA += item->HeroicCha; + newbon->HeroicMR += item->HeroicMR; + newbon->HeroicFR += item->HeroicFR; + newbon->HeroicCR += item->HeroicCR; + newbon->HeroicPR += item->HeroicPR; + newbon->HeroicDR += item->HeroicDR; + newbon->HeroicCorrup += item->HeroicSVCorrup; - } - else - { - int lvl = GetLevel(); - int reclvl = item->RecLevel; + } + else { + int lvl = GetLevel(); - newbon->AC += CalcRecommendedLevelBonus( lvl, reclvl, item->AC ); - newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP ); - newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana ); - newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur ); - newbon->ATK += CalcRecommendedLevelBonus( lvl, reclvl, item->Attack ); - newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) ); - newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) ); - newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) ); - newbon->AGI += CalcRecommendedLevelBonus( lvl, reclvl, (item->AAgi + item->HeroicAgi) ); - newbon->INT += CalcRecommendedLevelBonus( lvl, reclvl, (item->AInt + item->HeroicInt) ); - newbon->WIS += CalcRecommendedLevelBonus( lvl, reclvl, (item->AWis + item->HeroicWis) ); - newbon->CHA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ACha + item->HeroicCha) ); + newbon->AC += CalcRecommendedLevelBonus(lvl, rec_level, item->AC); + newbon->HP += CalcRecommendedLevelBonus(lvl, rec_level, item->HP); + newbon->Mana += CalcRecommendedLevelBonus(lvl, rec_level, item->Mana); + newbon->Endurance += CalcRecommendedLevelBonus(lvl, rec_level, item->Endur); + newbon->ATK += CalcRecommendedLevelBonus(lvl, rec_level, item->Attack); + newbon->STR += CalcRecommendedLevelBonus(lvl, rec_level, (item->AStr + item->HeroicStr)); + newbon->STA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ASta + item->HeroicSta)); + newbon->DEX += CalcRecommendedLevelBonus(lvl, rec_level, (item->ADex + item->HeroicDex)); + newbon->AGI += CalcRecommendedLevelBonus(lvl, rec_level, (item->AAgi + item->HeroicAgi)); + newbon->INT += CalcRecommendedLevelBonus(lvl, rec_level, (item->AInt + item->HeroicInt)); + newbon->WIS += CalcRecommendedLevelBonus(lvl, rec_level, (item->AWis + item->HeroicWis)); + newbon->CHA += CalcRecommendedLevelBonus(lvl, rec_level, (item->ACha + item->HeroicCha)); - newbon->MR += CalcRecommendedLevelBonus( lvl, reclvl, (item->MR + item->HeroicMR) ); - newbon->FR += CalcRecommendedLevelBonus( lvl, reclvl, (item->FR + item->HeroicFR) ); - newbon->CR += CalcRecommendedLevelBonus( lvl, reclvl, (item->CR + item->HeroicCR) ); - newbon->PR += CalcRecommendedLevelBonus( lvl, reclvl, (item->PR + item->HeroicPR) ); - newbon->DR += CalcRecommendedLevelBonus( lvl, reclvl, (item->DR + item->HeroicDR) ); - newbon->Corrup += CalcRecommendedLevelBonus( lvl, reclvl, (item->SVCorruption + item->HeroicSVCorrup) ); + newbon->MR += CalcRecommendedLevelBonus(lvl, rec_level, (item->MR + item->HeroicMR)); + newbon->FR += CalcRecommendedLevelBonus(lvl, rec_level, (item->FR + item->HeroicFR)); + newbon->CR += CalcRecommendedLevelBonus(lvl, rec_level, (item->CR + item->HeroicCR)); + newbon->PR += CalcRecommendedLevelBonus(lvl, rec_level, (item->PR + item->HeroicPR)); + newbon->DR += CalcRecommendedLevelBonus(lvl, rec_level, (item->DR + item->HeroicDR)); + newbon->Corrup += + CalcRecommendedLevelBonus(lvl, rec_level, (item->SVCorruption + item->HeroicSVCorrup)); - newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->STACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); + newbon->STRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); + newbon->STACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); + newbon->DEXCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); + newbon->AGICapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); + newbon->INTCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); + newbon->WISCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); + newbon->CHACapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); + newbon->MRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); + newbon->CRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); + newbon->FRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); + newbon->PRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); + newbon->DRCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); + newbon->CorrupCapMod += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); - newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); - } + newbon->HeroicSTR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicStr); + newbon->HeroicSTA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSta); + newbon->HeroicDEX += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDex); + newbon->HeroicAGI += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicAgi); + newbon->HeroicINT += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicInt); + newbon->HeroicWIS += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicWis); + newbon->HeroicCHA += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCha); + newbon->HeroicMR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicMR); + newbon->HeroicFR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicFR); + newbon->HeroicCR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicCR); + newbon->HeroicPR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicPR); + newbon->HeroicDR += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicDR); + newbon->HeroicCorrup += CalcRecommendedLevelBonus(lvl, rec_level, item->HeroicSVCorrup); + } - //FatherNitwit: New style haste, shields, and regens - if(newbon->haste < (int32)item->Haste) { - newbon->haste = item->Haste; - } - if(item->Regen > 0) - newbon->HPRegen += item->Regen; + // FatherNitwit: New style haste, shields, and regens + if (newbon->haste < (int32)item->Haste) { + newbon->haste = item->Haste; + } + if (item->Regen > 0) + newbon->HPRegen += item->Regen; - if(item->ManaRegen > 0) - newbon->ManaRegen += item->ManaRegen; + if (item->ManaRegen > 0) + newbon->ManaRegen += item->ManaRegen; - if(item->EnduranceRegen > 0) - newbon->EnduranceRegen += item->EnduranceRegen; + if (item->EnduranceRegen > 0) + newbon->EnduranceRegen += item->EnduranceRegen; - if(item->DamageShield > 0) { - if((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) - newbon->DamageShield = RuleI(Character, ItemDamageShieldCap); - else - newbon->DamageShield += item->DamageShield; - } - if(item->SpellShield > 0) { - if((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) - newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap); - else - newbon->SpellShield += item->SpellShield; - } - if(item->Shielding > 0) { - if((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) - newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap); - else - newbon->MeleeMitigation += item->Shielding; - } - if(item->StunResist > 0) { - if((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) - newbon->StunResist = RuleI(Character, ItemStunResistCap); - else - newbon->StunResist += item->StunResist; - } - if(item->StrikeThrough > 0) { - if((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) - newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap); - else - newbon->StrikeThrough += item->StrikeThrough; - } - if(item->Avoidance > 0) { - if((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) - newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap); - else - newbon->AvoidMeleeChance += item->Avoidance; - } - if(item->Accuracy > 0) { - if((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) - newbon->HitChance = RuleI(Character, ItemAccuracyCap); - else - newbon->HitChance += item->Accuracy; - } - if(item->CombatEffects > 0) { - if((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) - newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); - else - newbon->ProcChance += item->CombatEffects; - } - if(item->DotShielding > 0) { - if((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) - newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap); - else - newbon->DoTShielding += item->DotShielding; - } + if (item->DamageShield > 0) { + if ((newbon->DamageShield + item->DamageShield) > RuleI(Character, ItemDamageShieldCap)) + newbon->DamageShield = RuleI(Character, ItemDamageShieldCap); + else + newbon->DamageShield += item->DamageShield; + } + if (item->SpellShield > 0) { + if ((newbon->SpellShield + item->SpellShield) > RuleI(Character, ItemSpellShieldingCap)) + newbon->SpellShield = RuleI(Character, ItemSpellShieldingCap); + else + newbon->SpellShield += item->SpellShield; + } + if (item->Shielding > 0) { + if ((newbon->MeleeMitigation + item->Shielding) > RuleI(Character, ItemShieldingCap)) + newbon->MeleeMitigation = RuleI(Character, ItemShieldingCap); + else + newbon->MeleeMitigation += item->Shielding; + } + if (item->StunResist > 0) { + if ((newbon->StunResist + item->StunResist) > RuleI(Character, ItemStunResistCap)) + newbon->StunResist = RuleI(Character, ItemStunResistCap); + else + newbon->StunResist += item->StunResist; + } + if (item->StrikeThrough > 0) { + if ((newbon->StrikeThrough + item->StrikeThrough) > RuleI(Character, ItemStrikethroughCap)) + newbon->StrikeThrough = RuleI(Character, ItemStrikethroughCap); + else + newbon->StrikeThrough += item->StrikeThrough; + } + if (item->Avoidance > 0) { + if ((newbon->AvoidMeleeChance + item->Avoidance) > RuleI(Character, ItemAvoidanceCap)) + newbon->AvoidMeleeChance = RuleI(Character, ItemAvoidanceCap); + else + newbon->AvoidMeleeChance += item->Avoidance; + } + if (item->Accuracy > 0) { + if ((newbon->HitChance + item->Accuracy) > RuleI(Character, ItemAccuracyCap)) + newbon->HitChance = RuleI(Character, ItemAccuracyCap); + else + newbon->HitChance += item->Accuracy; + } + if (item->CombatEffects > 0) { + if ((newbon->ProcChance + item->CombatEffects) > RuleI(Character, ItemCombatEffectsCap)) + newbon->ProcChance = RuleI(Character, ItemCombatEffectsCap); + else + newbon->ProcChance += item->CombatEffects; + } + if (item->DotShielding > 0) { + if ((newbon->DoTShielding + item->DotShielding) > RuleI(Character, ItemDoTShieldingCap)) + newbon->DoTShielding = RuleI(Character, ItemDoTShieldingCap); + else + newbon->DoTShielding += item->DotShielding; + } - if(item->HealAmt > 0) { - if((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) - newbon->HealAmt = RuleI(Character, ItemHealAmtCap); - else - newbon->HealAmt += item->HealAmt; - } - if(item->SpellDmg > 0) { - if((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) - newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap); - else - newbon->SpellDmg += item->SpellDmg; - } - if(item->Clairvoyance > 0) { - if((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) - newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap); - else - newbon->Clairvoyance += item->Clairvoyance; - } + if (item->HealAmt > 0) { + if ((newbon->HealAmt + item->HealAmt) > RuleI(Character, ItemHealAmtCap)) + newbon->HealAmt = RuleI(Character, ItemHealAmtCap); + else + newbon->HealAmt += item->HealAmt; + } + if (item->SpellDmg > 0) { + if ((newbon->SpellDmg + item->SpellDmg) > RuleI(Character, ItemSpellDmgCap)) + newbon->SpellDmg = RuleI(Character, ItemSpellDmgCap); + else + newbon->SpellDmg += item->SpellDmg; + } + if (item->Clairvoyance > 0) { + if ((newbon->Clairvoyance + item->Clairvoyance) > RuleI(Character, ItemClairvoyanceCap)) + newbon->Clairvoyance = RuleI(Character, ItemClairvoyanceCap); + else + newbon->Clairvoyance += item->Clairvoyance; + } - if(item->DSMitigation > 0) { - if((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) - newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap); - else - newbon->DSMitigation += item->DSMitigation; - } - if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) {// latent effects - ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); - } + if (item->DSMitigation > 0) { + if ((newbon->DSMitigation + item->DSMitigation) > RuleI(Character, ItemDSMitigationCap)) + newbon->DSMitigation = RuleI(Character, ItemDSMitigationCap); + else + newbon->DSMitigation += item->DSMitigation; + } + if (item->Worn.Effect > 0 && item->Worn.Type == ET_WornEffect) { // latent effects + ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, item->Worn.Type); + } - if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects - ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); - } + if (item->Focus.Effect > 0 && (item->Focus.Type == ET_Focus)) { // focus effects + ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0); + } - switch(item->BardType) - { - case 51: /* All (e.g. Singing Short Sword) */ - { - if(item->BardValue > newbon->singingMod) + switch (item->BardType) { + case 51: /* All (e.g. Singing Short Sword) */ + if (item->BardValue > newbon->singingMod) newbon->singingMod = item->BardValue; - if(item->BardValue > newbon->brassMod) + if (item->BardValue > newbon->brassMod) newbon->brassMod = item->BardValue; - if(item->BardValue > newbon->stringedMod) + if (item->BardValue > newbon->stringedMod) newbon->stringedMod = item->BardValue; - if(item->BardValue > newbon->percussionMod) + if (item->BardValue > newbon->percussionMod) newbon->percussionMod = item->BardValue; - if(item->BardValue > newbon->windMod) + if (item->BardValue > newbon->windMod) newbon->windMod = item->BardValue; break; - } - case 50: /* Singing */ - { - if(item->BardValue > newbon->singingMod) + case 50: /* Singing */ + if (item->BardValue > newbon->singingMod) newbon->singingMod = item->BardValue; break; - } - case 23: /* Wind */ - { - if(item->BardValue > newbon->windMod) + case 23: /* Wind */ + if (item->BardValue > newbon->windMod) newbon->windMod = item->BardValue; break; - } - case 24: /* stringed */ - { - if(item->BardValue > newbon->stringedMod) + case 24: /* stringed */ + if (item->BardValue > newbon->stringedMod) newbon->stringedMod = item->BardValue; break; - } - case 25: /* brass */ - { - if(item->BardValue > newbon->brassMod) + case 25: /* brass */ + if (item->BardValue > newbon->brassMod) newbon->brassMod = item->BardValue; break; - } - case 26: /* Percussion */ - { - if(item->BardValue > newbon->percussionMod) + case 26: /* Percussion */ + if (item->BardValue > newbon->percussionMod) newbon->percussionMod = item->BardValue; break; } + + // Add Item Faction Mods + if (item->FactionMod1) { + if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) { + AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); + } + else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) { + AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); + } + } + if (item->FactionMod2) { + if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) { + AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); + } + else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) { + AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); + } + } + if (item->FactionMod3) { + if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) { + AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); + } + else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) { + AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); + } + } + if (item->FactionMod4) { + if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) { + AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); + } + else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) { + AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); + } + } + + if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { + if ((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > + RuleI(Character, ItemExtraDmgCap)) + newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); + else + newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; + } } - if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL){ + // Process when ammo_slot_item = true or false + if (item->SkillModValue != 0 && item->SkillModType <= HIGHEST_SKILL) { if ((item->SkillModValue > 0 && newbon->skillmod[item->SkillModType] < item->SkillModValue) || - (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) - { + (item->SkillModValue < 0 && newbon->skillmod[item->SkillModType] > item->SkillModValue)) { + newbon->skillmod[item->SkillModType] = item->SkillModValue; newbon->skillmodmax[item->SkillModType] = item->SkillModMax; } } - // Add Item Faction Mods - if (item->FactionMod1) - { - if (item->FactionAmt1 > 0 && item->FactionAmt1 > GetItemFactionBonus(item->FactionMod1)) - { - AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - } - else if (item->FactionAmt1 < 0 && item->FactionAmt1 < GetItemFactionBonus(item->FactionMod1)) - { - AddItemFactionBonus(item->FactionMod1, item->FactionAmt1); - } + if (!isAug) { + for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) + AddItemBonuses(inst->GetAugment(i), newbon, true, false, rec_level, ammo_slot_item); } - if (item->FactionMod2) - { - if (item->FactionAmt2 > 0 && item->FactionAmt2 > GetItemFactionBonus(item->FactionMod2)) - { - AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - } - else if (item->FactionAmt2 < 0 && item->FactionAmt2 < GetItemFactionBonus(item->FactionMod2)) - { - AddItemFactionBonus(item->FactionMod2, item->FactionAmt2); - } - } - if (item->FactionMod3) - { - if (item->FactionAmt3 > 0 && item->FactionAmt3 > GetItemFactionBonus(item->FactionMod3)) - { - AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - } - else if (item->FactionAmt3 < 0 && item->FactionAmt3 < GetItemFactionBonus(item->FactionMod3)) - { - AddItemFactionBonus(item->FactionMod3, item->FactionAmt3); - } - } - if (item->FactionMod4) - { - if (item->FactionAmt4 > 0 && item->FactionAmt4 > GetItemFactionBonus(item->FactionMod4)) - { - AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - } - else if (item->FactionAmt4 < 0 && item->FactionAmt4 < GetItemFactionBonus(item->FactionMod4)) - { - AddItemFactionBonus(item->FactionMod4, item->FactionAmt4); - } - } - - if (item->ExtraDmgSkill != 0 && item->ExtraDmgSkill <= HIGHEST_SKILL) { - if((newbon->SkillDamageAmount[item->ExtraDmgSkill] + item->ExtraDmgAmt) > RuleI(Character, ItemExtraDmgCap)) - newbon->SkillDamageAmount[item->ExtraDmgSkill] = RuleI(Character, ItemExtraDmgCap); - else - newbon->SkillDamageAmount[item->ExtraDmgSkill] += item->ExtraDmgAmt; - } - - if (!isAug) - { - int i; - for (i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - AddItemBonuses(inst->GetAugment(i),newbon,true); - } - } - } void Client::AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug) { @@ -1555,9 +1529,12 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon) NegateSpellsBonuses(buffs[i].spellid); } } + + // THIS IS WRONG, leaving for now //this prolly suffer from roundoff error slightly... - newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. - if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells. + newbon->AC = newbon->AC * 10 / 34; //ratio determined impirically from client. + if (GetClass() == BARD) + newbon->ManaRegen = 0; // Bards do not get mana regen from spells. } void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *new_bonus, uint16 casterId, @@ -2209,10 +2186,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne // Bad data or unsupported new skill if (base2 > HIGHEST_SKILL) break; - if(base2 == ALL_SKILLS) - new_bonus->DamageModifier[HIGHEST_SKILL+1] += effect_value; - else - new_bonus->DamageModifier[base2] += effect_value; + int skill = base2 == ALL_SKILLS ? HIGHEST_SKILL + 1 : base2; + if (effect_value < 0 && new_bonus->DamageModifier[skill] > effect_value) + new_bonus->DamageModifier[skill] = effect_value; + else if (effect_value > 0 && new_bonus->DamageModifier[skill] < effect_value) + new_bonus->DamageModifier[skill] = effect_value; break; } @@ -2221,10 +2199,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne // Bad data or unsupported new skill if (base2 > HIGHEST_SKILL) break; - if(base2 == ALL_SKILLS) - new_bonus->DamageModifier2[HIGHEST_SKILL+1] += effect_value; - else - new_bonus->DamageModifier2[base2] += effect_value; + int skill = base2 == ALL_SKILLS ? HIGHEST_SKILL + 1 : base2; + if (effect_value < 0 && new_bonus->DamageModifier2[skill] > effect_value) + new_bonus->DamageModifier2[skill] = effect_value; + else if (effect_value > 0 && new_bonus->DamageModifier2[skill] < effect_value) + new_bonus->DamageModifier2[skill] = effect_value; break; } @@ -2233,10 +2212,11 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne // Bad data or unsupported new skill if (base2 > HIGHEST_SKILL) break; - if(base2 == ALL_SKILLS) - new_bonus->MinDamageModifier[HIGHEST_SKILL+1] += effect_value; - else - new_bonus->MinDamageModifier[base2] += effect_value; + int skill = base2 == ALL_SKILLS ? HIGHEST_SKILL + 1 : base2; + if (effect_value < 0 && new_bonus->MinDamageModifier[skill] > effect_value) + new_bonus->MinDamageModifier[skill] = effect_value; + else if (effect_value > 0 && new_bonus->MinDamageModifier[skill] < effect_value) + new_bonus->MinDamageModifier[skill] = effect_value; break; } diff --git a/zone/bot.cpp b/zone/bot.cpp index 01f2da41d..dee437849 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -1179,7 +1179,7 @@ uint16 Bot::GetPrimarySkillValue() { break; } case ItemType2HPiercing: { - skill = Skill1HPiercing; // change to Skill2HPiercing once activated + skill = Skill2HPiercing; break; } case ItemTypeMartial: { @@ -5463,7 +5463,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 LimitFound = true; break; case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - base1; //every level over cap reduces the effect by base2 percent unless from a clicky when ItemCastsUseFocus is true if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { @@ -5477,7 +5477,7 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 } break; case SE_LimitMinLevel: - if((spell.classes[(GetClass() % 16) - 1]) < base1) + if((spell.classes[(GetClass() % 17) - 1]) < base1) LimitFound = true; break; case SE_LimitCastTimeMin: @@ -5915,7 +5915,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel case SE_LimitMaxLevel:{ if (IsNPC()) break; - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = (spell_level - focus_spell.base[i]); if(lvldiff > 0 && (spell_level <= RuleI(Character, MaxLevel) || RuleB(Character, ItemCastsUseFocus) == false)) { if(focus_spell.base2[i] > 0) { @@ -5931,7 +5931,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel case SE_LimitMinLevel: if (IsNPC()) break; - if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) + if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base[i]) return 0; break; @@ -6493,7 +6493,7 @@ void Bot::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) { ndamage = -5; DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime); - DoAnim(animPiercing); + DoAnim(anim1HPiercing); } void Bot::RogueAssassinate(Mob* other) { @@ -6505,7 +6505,7 @@ void Bot::RogueAssassinate(Mob* other) { other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); } - DoAnim(animPiercing); + DoAnim(anim1HPiercing); } void Bot::DoClassAttacks(Mob *target, bool IsRiposte) { @@ -7083,7 +7083,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100); entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value); @@ -7102,7 +7102,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id); value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id); - if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); return value; @@ -7135,7 +7135,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 16) - 1] >= GetLevel() - 5) + if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value += (GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier); value += (value * target->GetHealRate(spell_id, this) / 100); @@ -7239,7 +7239,7 @@ int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) { } int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) { - if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) { + if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { int32 mana_back = (this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100); if(mana_back > cost) mana_back = cost; @@ -8829,7 +8829,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon) newbon->EnduranceRegen = CalcEnduranceRegenCap(); } -void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute) { +void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, bool isTribute, int rec_override) { if(!inst || !inst->IsType(ItemClassCommon)) { return; @@ -8848,12 +8848,13 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, return; } - if(GetLevel() < item->ReqLevel) + if(GetLevel() < inst->GetItemRequiredLevel(true)) { return; } - if(GetLevel() >= item->RecLevel) + auto rec_level = isAug ? rec_override : inst->GetItemRecommendedLevel(true); + if(GetLevel() >= rec_level) { newbon->AC += item->AC; newbon->HP += item->HP; @@ -8907,55 +8908,54 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, else { int lvl = GetLevel(); - int reclvl = item->RecLevel; - newbon->AC += CalcRecommendedLevelBonus( lvl, reclvl, item->AC ); - newbon->HP += CalcRecommendedLevelBonus( lvl, reclvl, item->HP ); - newbon->Mana += CalcRecommendedLevelBonus( lvl, reclvl, item->Mana ); - newbon->Endurance += CalcRecommendedLevelBonus( lvl, reclvl, item->Endur ); - newbon->ATK += CalcRecommendedLevelBonus( lvl, reclvl, item->Attack ); - newbon->STR += CalcRecommendedLevelBonus( lvl, reclvl, (item->AStr + item->HeroicStr) ); - newbon->STA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ASta + item->HeroicSta) ); - newbon->DEX += CalcRecommendedLevelBonus( lvl, reclvl, (item->ADex + item->HeroicDex) ); - newbon->AGI += CalcRecommendedLevelBonus( lvl, reclvl, (item->AAgi + item->HeroicAgi) ); - newbon->INT += CalcRecommendedLevelBonus( lvl, reclvl, (item->AInt + item->HeroicInt) ); - newbon->WIS += CalcRecommendedLevelBonus( lvl, reclvl, (item->AWis + item->HeroicWis) ); - newbon->CHA += CalcRecommendedLevelBonus( lvl, reclvl, (item->ACha + item->HeroicCha) ); + newbon->AC += CalcRecommendedLevelBonus( lvl, rec_level, item->AC ); + newbon->HP += CalcRecommendedLevelBonus( lvl, rec_level, item->HP ); + newbon->Mana += CalcRecommendedLevelBonus( lvl, rec_level, item->Mana ); + newbon->Endurance += CalcRecommendedLevelBonus( lvl, rec_level, item->Endur ); + newbon->ATK += CalcRecommendedLevelBonus( lvl, rec_level, item->Attack ); + newbon->STR += CalcRecommendedLevelBonus( lvl, rec_level, (item->AStr + item->HeroicStr) ); + newbon->STA += CalcRecommendedLevelBonus( lvl, rec_level, (item->ASta + item->HeroicSta) ); + newbon->DEX += CalcRecommendedLevelBonus( lvl, rec_level, (item->ADex + item->HeroicDex) ); + newbon->AGI += CalcRecommendedLevelBonus( lvl, rec_level, (item->AAgi + item->HeroicAgi) ); + newbon->INT += CalcRecommendedLevelBonus( lvl, rec_level, (item->AInt + item->HeroicInt) ); + newbon->WIS += CalcRecommendedLevelBonus( lvl, rec_level, (item->AWis + item->HeroicWis) ); + newbon->CHA += CalcRecommendedLevelBonus( lvl, rec_level, (item->ACha + item->HeroicCha) ); - newbon->MR += CalcRecommendedLevelBonus( lvl, reclvl, (item->MR + item->HeroicMR) ); - newbon->FR += CalcRecommendedLevelBonus( lvl, reclvl, (item->FR + item->HeroicFR) ); - newbon->CR += CalcRecommendedLevelBonus( lvl, reclvl, (item->CR + item->HeroicCR) ); - newbon->PR += CalcRecommendedLevelBonus( lvl, reclvl, (item->PR + item->HeroicPR) ); - newbon->DR += CalcRecommendedLevelBonus( lvl, reclvl, (item->DR + item->HeroicDR) ); - newbon->Corrup += CalcRecommendedLevelBonus( lvl, reclvl, (item->SVCorruption + item->HeroicSVCorrup) ); + newbon->MR += CalcRecommendedLevelBonus( lvl, rec_level, (item->MR + item->HeroicMR) ); + newbon->FR += CalcRecommendedLevelBonus( lvl, rec_level, (item->FR + item->HeroicFR) ); + newbon->CR += CalcRecommendedLevelBonus( lvl, rec_level, (item->CR + item->HeroicCR) ); + newbon->PR += CalcRecommendedLevelBonus( lvl, rec_level, (item->PR + item->HeroicPR) ); + newbon->DR += CalcRecommendedLevelBonus( lvl, rec_level, (item->DR + item->HeroicDR) ); + newbon->Corrup += CalcRecommendedLevelBonus( lvl, rec_level, (item->SVCorruption + item->HeroicSVCorrup) ); - newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->STACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); + newbon->STRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicStr ); + newbon->STACapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSta ); + newbon->DEXCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDex ); + newbon->AGICapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicAgi ); + newbon->INTCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicInt ); + newbon->WISCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicWis ); + newbon->CHACapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCha ); + newbon->MRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicMR ); + newbon->CRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicFR ); + newbon->FRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCR ); + newbon->PRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicPR ); + newbon->DRCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDR ); + newbon->CorrupCapMod += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSVCorrup ); - newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicStr ); - newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSta ); - newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDex ); - newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicAgi ); - newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicInt ); - newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicWis ); - newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCha ); - newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicMR ); - newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicFR ); - newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicCR ); - newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicPR ); - newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicDR ); - newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, reclvl, item->HeroicSVCorrup ); + newbon->HeroicSTR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicStr ); + newbon->HeroicSTA += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSta ); + newbon->HeroicDEX += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDex ); + newbon->HeroicAGI += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicAgi ); + newbon->HeroicINT += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicInt ); + newbon->HeroicWIS += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicWis ); + newbon->HeroicCHA += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCha ); + newbon->HeroicMR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicMR ); + newbon->HeroicFR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicFR ); + newbon->HeroicCR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicCR ); + newbon->HeroicPR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicPR ); + newbon->HeroicDR += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicDR ); + newbon->HeroicCorrup += CalcRecommendedLevelBonus( lvl, rec_level, item->HeroicSVCorrup ); } //FatherNitwit: New style haste, shields, and regens @@ -9124,10 +9124,8 @@ void Bot::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug, if (!isAug) { - int i; - for (i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) { - AddItemBonuses(inst->GetAugment(i),newbon,true); - } + for (int i = 0; i < EmuConstants::ITEM_COMMON_SIZE; i++) + AddItemBonuses(inst->GetAugment(i),newbon,true, false, rec_level); } } @@ -13776,11 +13774,10 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) } safe_delete_array(escaped_string); - sayid += 500000; - Client::TextLink linker; linker.SetLinkType(linker.linkItemData); - linker.SetProxyItemID(sayid); + linker.SetProxyItemID(SAYLINK_ITEM_ID); + linker.SetProxyAugment1ID(sayid); linker.SetProxyText(name); auto say_link = linker.GenerateLink(); diff --git a/zone/bot.h b/zone/bot.h index a280a2a58..c35fd1f7b 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -193,7 +193,7 @@ public: virtual int32 CheckAggroAmount(uint16 spellid); virtual void CalcBonuses(); void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false); + void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); virtual void MakePet(uint16 spell_id, const char* pettype, const char *petname = nullptr); virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther); diff --git a/zone/client.cpp b/zone/client.cpp index ceedf19d7..f41e35bd2 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -587,10 +587,9 @@ bool Client::Save(uint8 iCommitNow) { database.SaveCharacterCurrency(CharacterID(), &m_pp); /* Save Current Bind Points */ - auto regularBindPosition = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f); - auto homeBindPosition = glm::vec4(m_pp.binds[4].x, m_pp.binds[4].y, m_pp.binds[4].z, 0.0f); - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPosition, 0); /* Regular bind */ - database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[4].zoneId, m_pp.binds[4].instance_id, homeBindPosition, 1); /* Home Bind */ + for (int i = 0; i < 5; i++) + if (m_pp.binds[i].zoneId) + database.SaveCharacterBindPoint(CharacterID(), m_pp.binds[i], i); /* Save Character Buffs */ database.SaveBuffs(this); @@ -2343,11 +2342,17 @@ bool Client::HasSkill(SkillUseTypes skill_id) const { } bool Client::CanHaveSkill(SkillUseTypes skill_id) const { + if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skill_id == Skill1HPiercing) + skill_id = Skill2HPiercing; + return(database.GetSkillCap(GetClass(), skill_id, RuleI(Character, MaxLevel)) > 0); //if you don't have it by max level, then odds are you never will? } uint16 Client::MaxSkill(SkillUseTypes skillid, uint16 class_, uint16 level) const { + if (GetClientVersion() < ClientVersion::RoF2 && class_ == BERSERKER && skillid == Skill1HPiercing) + skillid = Skill2HPiercing; + return(database.GetSkillCap(class_, skillid, level)); } @@ -4211,7 +4216,10 @@ uint16 Client::GetPrimarySkillValue() } case ItemType2HPiercing: // 2H Piercing { - skill = Skill1HPiercing; // change to Skill2HPiercing once activated + if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + skill = Skill1HPiercing; + else + skill = Skill2HPiercing; break; } case ItemTypeMartial: // Hand to Hand @@ -4629,7 +4637,7 @@ void Client::HandleLDoNOpen(NPC *target) AddEXP(target->GetLevel()*target->GetLevel()*2625/10, GetLevelCon(target->GetLevel())); } } - target->Death(this, 1, SPELL_UNKNOWN, SkillHandtoHand); + target->Death(this, 0, SPELL_UNKNOWN, SkillHandtoHand); } } } @@ -4942,36 +4950,27 @@ void Client::ShowSkillsWindow() { const char *WindowTitle = "Skills"; std::string WindowText; - // using a map for easy alphabetizing of the skills list - std::map Skills; - std::map::iterator it; + std::map Skills = EQEmu::GetSkillUseTypesMap(); - // this list of names must keep the same order as that in common/skills.h - const char* SkillName[] = {"1H Blunt","1H Slashing","2H Blunt","2H Slashing","Abjuration","Alteration","Apply Poison","Archery", - "Backstab","Bind Wound","Bash","Block","Brass Instruments","Channeling","Conjuration","Defense","Disarm","Disarm Traps","Divination", - "Dodge","Double Attack","Dragon Punch","Dual Wield","Eagle Strike","Evocation","Feign Death","Flying Kick","Forage","Hand to Hand", - "Hide","Kick","Meditate","Mend","Offense","Parry","Pick Lock","Piercing","Ripost","Round Kick","Safe Fall","Sense Heading", - "Singing","Sneak","Specialize Abjuration","Specialize Alteration","Specialize Conjuration","Specialize Divination","Specialize Evocation","Pick Pockets", - "Stringed Instruments","Swimming","Throwing","Tiger Claw","Tracking","Wind Instruments","Fishing","Make Poison","Tinkering","Research", - "Alchemy","Baking","Tailoring","Sense Traps","Blacksmithing","Fletching","Brewing","Alcohol Tolerance","Begging","Jewelry Making", - "Pottery","Percussion Instruments","Intimidation","Berserking","Taunt","Frenzy","Remove Traps","Triple Attack"}; - for(int i = 0; i <= (int)HIGHEST_SKILL; i++) - Skills[SkillName[i]] = (SkillUseTypes)i; + if (GetClientVersion() < ClientVersion::RoF2) + Skills[Skill1HPiercing] = "Piercing"; // print out all available skills - for(it = Skills.begin(); it != Skills.end(); ++it) { - if(GetSkill(it->second) > 0 || MaxSkill(it->second) > 0) { - WindowText += it->first; - // line up the values - for (int j = 0; j < EmuConstants::ITEM_COMMON_SIZE; j++) - WindowText += " "; - WindowText += itoa(this->GetSkill(it->second)); - if (MaxSkill(it->second) > 0) { - WindowText += "/"; - WindowText += itoa(this->GetMaxSkillAfterSpecializationRules(it->second,this->MaxSkill(it->second))); - } - WindowText += "
"; + for (auto skills_iter : Skills) { + if (skills_iter.first == Skill2HPiercing && GetClientVersion() < ClientVersion::RoF2) + continue; + if (!GetSkill(skills_iter.first) && !MaxSkill(skills_iter.first)) + continue; + + WindowText += skills_iter.second; + // line up the values + WindowText += "      "; + WindowText += itoa(this->GetSkill(skills_iter.first)); + if (MaxSkill(skills_iter.first) > 0) { + WindowText += "/"; + WindowText += itoa(this->GetMaxSkillAfterSpecializationRules(skills_iter.first, this->MaxSkill(skills_iter.first))); } + WindowText += "
"; } this->SendPopupToClient(WindowTitle, WindowText.c_str()); } @@ -8423,7 +8422,19 @@ void Client::TextLink::Reset() m_ItemData = nullptr; m_LootData = nullptr; m_ItemInst = nullptr; + m_Proxy_unknown_1 = NOT_USED; m_ProxyItemID = NOT_USED; + m_ProxyAugment1ID = NOT_USED; + m_ProxyAugment2ID = NOT_USED; + m_ProxyAugment3ID = NOT_USED; + m_ProxyAugment4ID = NOT_USED; + m_ProxyAugment5ID = NOT_USED; + m_ProxyAugment6ID = NOT_USED; + m_ProxyIsEvolving = NOT_USED; + m_ProxyEvolveGroup = NOT_USED; + m_ProxyEvolveLevel = NOT_USED; + m_ProxyOrnamentIcon = NOT_USED; + m_ProxyHash = NOT_USED; m_ProxyText = nullptr; m_TaskUse = false; m_Link.clear(); @@ -8439,8 +8450,8 @@ void Client::TextLink::generate_body() RoF2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X" (56) RoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (55) - SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) - 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) + SoF: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%05X" "%08X" (50) + 6.2: "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%1X" "%08X" (45) */ memset(&m_LinkBodyStruct, 0, sizeof(TextLinkBody_Struct)); @@ -8492,13 +8503,36 @@ void Client::TextLink::generate_body() break; } - if (m_ProxyItemID != NOT_USED) { + if (m_Proxy_unknown_1) + m_LinkBodyStruct.unknown_1 = m_Proxy_unknown_1; + if (m_ProxyItemID) m_LinkBodyStruct.item_id = m_ProxyItemID; - } + if (m_ProxyAugment1ID) + m_LinkBodyStruct.augment_1 = m_ProxyAugment1ID; + if (m_ProxyAugment2ID) + m_LinkBodyStruct.augment_2 = m_ProxyAugment2ID; + if (m_ProxyAugment3ID) + m_LinkBodyStruct.augment_3 = m_ProxyAugment3ID; + if (m_ProxyAugment4ID) + m_LinkBodyStruct.augment_4 = m_ProxyAugment4ID; + if (m_ProxyAugment5ID) + m_LinkBodyStruct.augment_5 = m_ProxyAugment5ID; + if (m_ProxyAugment6ID) + m_LinkBodyStruct.augment_6 = m_ProxyAugment6ID; + if (m_ProxyIsEvolving) + m_LinkBodyStruct.is_evolving = m_ProxyIsEvolving; + if (m_ProxyEvolveGroup) + m_LinkBodyStruct.evolve_group = m_ProxyEvolveGroup; + if (m_ProxyEvolveLevel) + m_LinkBodyStruct.evolve_level = m_ProxyEvolveLevel; + if (m_ProxyOrnamentIcon) + m_LinkBodyStruct.ornament_icon = m_ProxyOrnamentIcon; + if (m_ProxyHash) + m_LinkBodyStruct.hash = m_ProxyHash; - if (m_TaskUse) { + + if (m_TaskUse) m_LinkBodyStruct.hash = 0x14505DC2; - } m_LinkBody = StringFormat( "%1X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%05X" "%1X" "%04X" "%02X" "%05X" "%08X", @@ -8515,7 +8549,7 @@ void Client::TextLink::generate_body() (0xFF & m_LinkBodyStruct.evolve_level), (0x000FFFFF & m_LinkBodyStruct.ornament_icon), (0xFFFFFFFF & m_LinkBodyStruct.hash) - ); + ); } void Client::TextLink::generate_text() diff --git a/zone/client.h b/zone/client.h index bc2f89b87..f36422d3a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -582,8 +582,8 @@ public: void GoToBind(uint8 bindnum = 0); void GoToSafeCoords(uint16 zone_id, uint16 instance_id); - void Gate(); - void SetBindPoint(int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); + void Gate(uint8 bindnum = 0); + void SetBindPoint(int bind_num = 0, int to_zone = -1, int to_instance = 0, const glm::vec3& location = glm::vec3()); void SetStartZone(uint32 zoneid, float x = 0.0f, float y =0.0f, float z = 0.0f); uint32 GetStartZone(void); void MovePC(const char* zonename, float x, float y, float z, float heading, uint8 ignorerestrictions = 0, ZoneMode zm = ZoneSolicited); @@ -831,7 +831,22 @@ public: void SetItemData(const Item_Struct* itemData) { m_ItemData = itemData; } void SetLootData(const ServerLootItem_Struct* lootData) { m_LootData = lootData; } void SetItemInst(const ItemInst* itemInst) { m_ItemInst = itemInst; } - void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } // mainly for saylinks..but, not limited to + + // mainly for saylinks..but, not limited to + void SetProxyUnknown1(uint8 proxyUnknown1) { m_Proxy_unknown_1 = proxyUnknown1; } + void SetProxyItemID(uint32 proxyItemID) { m_ProxyItemID = proxyItemID; } + void SetProxyAugment1ID(uint32 proxyAugmentID) { m_ProxyAugment1ID = proxyAugmentID; } + void SetProxyAugment2ID(uint32 proxyAugmentID) { m_ProxyAugment2ID = proxyAugmentID; } + void SetProxyAugment3ID(uint32 proxyAugmentID) { m_ProxyAugment3ID = proxyAugmentID; } + void SetProxyAugment4ID(uint32 proxyAugmentID) { m_ProxyAugment4ID = proxyAugmentID; } + void SetProxyAugment5ID(uint32 proxyAugmentID) { m_ProxyAugment5ID = proxyAugmentID; } + void SetProxyAugment6ID(uint32 proxyAugmentID) { m_ProxyAugment6ID = proxyAugmentID; } + void SetProxyIsEvolving(uint8 proxyIsEvolving) { m_ProxyIsEvolving = proxyIsEvolving; } + void SetProxyEvolveGroup(uint32 proxyEvolveGroup) { m_ProxyEvolveGroup = proxyEvolveGroup; } + void SetProxyEvolveLevel(uint8 proxyEvolveLevel) { m_ProxyEvolveLevel = proxyEvolveLevel; } + void SetProxyOrnamentIcon(uint32 proxyOrnamentIcon) { m_ProxyOrnamentIcon = proxyOrnamentIcon; } + void SetProxyHash(int proxyHash) { m_ProxyHash = proxyHash; } + void SetProxyText(const char* proxyText) { m_ProxyText = proxyText; } // overrides standard text use void SetTaskUse() { m_TaskUse = true; } @@ -855,7 +870,20 @@ public: const Item_Struct* m_ItemData; const ServerLootItem_Struct* m_LootData; const ItemInst* m_ItemInst; + + uint8 m_Proxy_unknown_1; uint32 m_ProxyItemID; + uint32 m_ProxyAugment1ID; + uint32 m_ProxyAugment2ID; + uint32 m_ProxyAugment3ID; + uint32 m_ProxyAugment4ID; + uint32 m_ProxyAugment5ID; + uint32 m_ProxyAugment6ID; + uint8 m_ProxyIsEvolving; + uint32 m_ProxyEvolveGroup; + uint8 m_ProxyEvolveLevel; + uint32 m_ProxyOrnamentIcon; + int m_ProxyHash; const char* m_ProxyText; bool m_TaskUse; TextLinkBody_Struct m_LinkBodyStruct; @@ -1275,7 +1303,7 @@ public: protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); - void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false); + void AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false); void AdditiveWornBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAug = false); int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat); void CalcEdibleBonuses(StatBonuses* newbon); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 06c267fd4..9fc36a57e 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1633,13 +1633,19 @@ int32 Client::CalcMR() MR = 30; break; case DRAKKIN: - MR = 35; + { + MR = 25; + if (GetDrakkinHeritage() == 2) + MR += 10; + else if (GetDrakkinHeritage() == 5) + MR += 2; break; + } default: MR = 20; } MR += itembonuses.MR + spellbonuses.MR + aabonuses.MR; - if (GetClass() == WARRIOR) { + if (GetClass() == WARRIOR || GetClass() == BERSERKER) { MR += GetLevel() / 2; } if (MR < 1) { @@ -1701,8 +1707,14 @@ int32 Client::CalcFR() FR = 25; break; case DRAKKIN: + { FR = 25; + if (GetDrakkinHeritage() == 0) + FR += 10; + else if (GetDrakkinHeritage() == 5) + FR += 2; break; + } default: FR = 20; } @@ -1714,6 +1726,13 @@ int32 Client::CalcFR() FR += l - 49; } } + if (c == MONK) { + FR += 8; + int l = GetLevel(); + if (l > 49) { + FR += l - 49; + } + } FR += itembonuses.FR + spellbonuses.FR + aabonuses.FR; if (FR < 1) { FR = 1; @@ -1774,12 +1793,24 @@ int32 Client::CalcDR() DR = 15; break; case DRAKKIN: + { DR = 15; + if (GetDrakkinHeritage() == 1) + DR += 10; + else if (GetDrakkinHeritage() == 5) + DR += 2; break; + } default: DR = 15; } int c = GetClass(); + // the monk one is part of base resist + if (c == MONK) { + int l = GetLevel(); + if (l > 50) + DR += l - 50; + } if (c == PALADIN) { DR += 8; int l = GetLevel(); @@ -1787,7 +1818,7 @@ int32 Client::CalcDR() DR += l - 49; } } - else if (c == SHADOWKNIGHT) { + else if (c == SHADOWKNIGHT || c == BEASTLORD) { DR += 4; int l = GetLevel(); if (l > 49) { @@ -1854,12 +1885,24 @@ int32 Client::CalcPR() PR = 30; break; case DRAKKIN: + { PR = 15; + if (GetDrakkinHeritage() == 3) + PR += 10; + else if (GetDrakkinHeritage() == 5) + PR += 2; break; + } default: PR = 15; } int c = GetClass(); + // this monk bonus is part of the base + if (c == MONK) { + int l = GetLevel(); + if (l > 50) + PR += l - 50; + } if (c == ROGUE) { PR += 8; int l = GetLevel(); @@ -1934,13 +1977,19 @@ int32 Client::CalcCR() CR = 25; break; case DRAKKIN: + { CR = 25; + if (GetDrakkinHeritage() == 4) + CR += 10; + else if (GetDrakkinHeritage() == 5) + CR += 2; break; + } default: CR = 25; } int c = GetClass(); - if (c == RANGER) { + if (c == RANGER || c == BEASTLORD) { CR += 4; int l = GetLevel(); if (l > 49) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f20ffb5f4..7aa4c0de5 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4253,15 +4253,11 @@ void Client::Handle_OP_ClickObjectAction(const EQApplicationPacket *app) EQApplicationPacket end_trade2(OP_FinishWindow2, 0); QueuePacket(&end_trade2); - return; - // RoF sends a 0 sized packet for closing objects - /* - Object* object = GetTradeskillObject(); - if (object) { - object->CastToObject()->Close(); - } - */ + if (GetTradeskillObject() && GetClientVersion() >= ClientVersion::RoF) + GetTradeskillObject()->CastToObject()->Close(); + + return; } else { @@ -6131,7 +6127,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app) char *escSearchString = new char[129]; database.DoEscapeString(escSearchString, gmscs->Name, strlen(gmscs->Name)); - std::string query = StringFormat("SELECT charname, zoneid, x, y, z, time_of_death, is_rezzed, is_buried " + std::string query = StringFormat("SELECT charname, zone_id, x, y, z, time_of_death, is_rezzed, is_buried " "FROM character_corpses WheRE charname LIKE '%%%s%%' ORDER BY charname LIMIT %i", escSearchString, maxResults); safe_delete_array(escSearchString); @@ -8094,97 +8090,80 @@ void Client::Handle_OP_InstillDoubt(const EQApplicationPacket *app) void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app) { - if (app->size != sizeof(ItemViewRequest_Struct)){ - Log.Out(Logs::General, Logs::Error, "Wrong size on OP_ItemLinkClick. Got: %i, Expected: %i", app->size, sizeof(ItemViewRequest_Struct)); + if (app->size != sizeof(ItemViewRequest_Struct)) { + Log.Out(Logs::General, Logs::Error, "Wrong size on OP_ItemLinkClick. Got: %i, Expected: %i", app->size, + sizeof(ItemViewRequest_Struct)); DumpPacket(app); return; } DumpPacket(app); - ItemViewRequest_Struct* ivrs = (ItemViewRequest_Struct*)app->pBuffer; + ItemViewRequest_Struct *ivrs = (ItemViewRequest_Struct *)app->pBuffer; - //todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data from the item DB + // todo: verify ivrs->link_hash based on a rule, in case we don't care about people being able to sniff data + // from the item DB - const Item_Struct* item = database.GetItem(ivrs->item_id); + const Item_Struct *item = database.GetItem(ivrs->item_id); if (!item) { - if (ivrs->item_id > 500000) - { - std::string response = ""; - int sayid = ivrs->item_id - 500000; - bool silentsaylink = false; - - if (sayid > 250000) //Silent Saylink - { - sayid = sayid - 250000; - silentsaylink = true; - } - - if (sayid > 0) - { - - std::string query = StringFormat("SELECT `phrase` FROM saylink WHERE `id` = '%i'", sayid); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); - return; - } - - if (results.RowCount() != 1) { - Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); - return; - } - - auto row = results.begin(); - response = row[0]; - - } - - if ((response).size() > 0) - { - if (!mod_saylink(response, silentsaylink)) { return; } - - if (GetTarget() && GetTarget()->IsNPC()) - { - if (silentsaylink) - { - parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response.c_str(), 0); - parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); - } - else - { - Message(7, "You say, '%s'", response.c_str()); - ChannelMessageReceived(8, 0, 100, response.c_str()); - } - return; - } - else - { - if (silentsaylink) - { - parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); - } - else - { - Message(7, "You say, '%s'", response.c_str()); - ChannelMessageReceived(8, 0, 100, response.c_str()); - } - return; - } - } - else - { - Message(13, "Error: Say Link not found or is too long."); - return; - } - } - else { + if (ivrs->item_id != SAYLINK_ITEM_ID) { Message(13, "Error: The item for the link you have clicked on does not exist!"); return; } + // This new scheme will shuttle the ID in the first augment for non-silent links + // and the second augment for silent. + std::string response = ""; + bool silentsaylink = ivrs->augments[1] > 0 ? true : false; + int sayid = silentsaylink ? ivrs->augments[1] : ivrs->augments[0]; + if (sayid > 0) { + std::string query = StringFormat("SELECT `phrase` FROM saylink WHERE `id` = '%i'", sayid); + auto results = database.QueryDatabase(query); + if (!results.Success()) { + Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); + return; + } + + if (results.RowCount() != 1) { + Message(13, "Error: The saylink (%s) was not found in the database.", response.c_str()); + return; + } + + auto row = results.begin(); + response = row[0]; + } + + if ((response).size() > 0) { + if (!mod_saylink(response, silentsaylink)) { + return; + } + + if (GetTarget() && GetTarget()->IsNPC()) { + if (silentsaylink) { + parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response.c_str(), 0); + parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); + } else { + Message(7, "You say, '%s'", response.c_str()); + ChannelMessageReceived(8, 0, 100, response.c_str()); + } + return; + } else { + if (silentsaylink) { + parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0); + } else { + Message(7, "You say, '%s'", response.c_str()); + ChannelMessageReceived(8, 0, 100, response.c_str()); + } + return; + } + } else { + Message(13, "Error: Say Link not found or is too long."); + return; + } } - ItemInst* inst = database.CreateItem(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], ivrs->augments[3], ivrs->augments[4], ivrs->augments[5]); + ItemInst *inst = + database.CreateItem(item, item->MaxCharges, ivrs->augments[0], ivrs->augments[1], ivrs->augments[2], + ivrs->augments[3], ivrs->augments[4], ivrs->augments[5]); if (inst) { SendItemPacket(0, inst, ItemPacketViewLink); safe_delete(inst); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 3b973e7b7..3154a9ca9 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -1553,6 +1553,11 @@ void Client::OPGMTraining(const EQApplicationPacket *app) //Set it to 1 with CanHaveSkill or you wont be able to train past 1. } } + + if (GetClientVersion() < ClientVersion::RoF2 && GetClass() == BERSERKER) { + gmtrain->skills[Skill1HPiercing] = gmtrain->skills[Skill2HPiercing]; + gmtrain->skills[Skill2HPiercing] = 0; + } //#pragma GCC pop_options uchar ending[]={0x34,0x87,0x8a,0x3F,0x01 diff --git a/zone/command.cpp b/zone/command.cpp index 5eede229f..b5d060f87 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -194,6 +194,7 @@ int command_init(void) command_add("enablerecipe", "[recipe_id] - Enables a recipe using the recipe id.", 80, command_enablerecipe) || command_add("equipitem", "[slotid(0-21)] - Equip the item on your cursor into the specified slot", 50, command_equipitem) || command_add("face", "- Change the face of your target", 80, command_face) || + command_add("findaliases", "[search term]- Searches for available command aliases, by alias or command", 0, command_findaliases) || command_add("findnpctype", "[search criteria] - Search database NPC types", 100, command_findnpctype) || command_add("findspell", "[searchstring] - Search for a spell", 50, command_findspell) || command_add("findzone", "[search criteria] - Search database zones", 100, command_findzone) || @@ -423,7 +424,9 @@ int command_init(void) std::map>> command_settings; database.GetCommandSettings(command_settings); - for (std::map::iterator iter_cl = commandlist.begin(); iter_cl != commandlist.end(); ++iter_cl) { + + std::map working_cl = commandlist; + for (std::map::iterator iter_cl = working_cl.begin(); iter_cl != working_cl.end(); ++iter_cl) { std::map>>::iterator iter_cs = command_settings.find(iter_cl->first); if (iter_cs == command_settings.end()) { if (iter_cl->second->access == 0) @@ -4394,8 +4397,14 @@ void command_uptime(Client *c, const Seperator *sep) void command_flag(Client *c, const Seperator *sep) { if(sep->arg[2][0] == 0) { - c->UpdateAdmin(); - c->Message(0, "Refreshed your admin flag from DB."); + if (!c->GetTarget() || (c->GetTarget() && c->GetTarget() == c)) { + c->UpdateAdmin(); + c->Message(0, "Refreshed your admin flag from DB."); + } else if (c->GetTarget() && c->GetTarget() != c && c->GetTarget()->IsClient()) { + c->GetTarget()->CastToClient()->UpdateAdmin(); + c->Message(0, "%s's admin flag has been refreshed.", c->GetTarget()->GetName()); + c->GetTarget()->Message(0, "%s refreshed your admin flag.", c->GetName()); + } } else if (!sep->IsNumber(1) || atoi(sep->arg[1]) < -2 || atoi(sep->arg[1]) > 255 || strlen(sep->arg[2]) == 0) c->Message(0, "Usage: #flag [status] [acctname]"); @@ -4945,6 +4954,38 @@ void command_face(Client *c, const Seperator *sep) } } +void command_findaliases(Client *c, const Seperator *sep) +{ + if (!sep->arg[1][0]) { + c->Message(0, "Usage: #findaliases [alias | command]"); + return; + } + + std::map::iterator find_iter = commandaliases.find(sep->arg[1]); + if (find_iter == commandaliases.end()) { + c->Message(15, "No commands or aliases match '%s'", sep->arg[1]); + return; + } + + std::map::iterator command_iter = commandlist.find(find_iter->second); + if (find_iter->second.empty() || command_iter == commandlist.end()) { + c->Message(0, "An unknown condition occurred..."); + return; + } + + c->Message(0, "Available command aliases for '%s':", command_iter->first.c_str()); + + int commandaliasesshown = 0; + for (std::map::iterator alias_iter = commandaliases.begin(); alias_iter != commandaliases.end(); ++alias_iter) { + if (strcasecmp(find_iter->second.c_str(), alias_iter->second.c_str()) || c->Admin() < command_iter->second->access) + continue; + + c->Message(0, "%c%s", COMMAND_CHAR, alias_iter->first.c_str()); + ++commandaliasesshown; + } + c->Message(0, "%d command alias%s listed.", commandaliasesshown, commandaliasesshown != 1 ? "es" : ""); +} + void command_details(Client *c, const Seperator *sep) { Mob *target=c->GetTarget(); @@ -5445,36 +5486,54 @@ void command_interrupt(Client *c, const Seperator *sep) void command_summonitem(Client *c, const Seperator *sep) { - if (!sep->IsNumber(1)) - c->Message(0, "Usage: #summonitem [item id] [charges], charges are optional"); - else { - uint32 itemid = atoi(sep->arg[1]); - int16 item_status = 0; - const Item_Struct* item = database.GetItem(itemid); - if(item) { - item_status = static_cast(item->MinStatus); - } + uint32 itemid = 0; - if (item_status > c->Admin()) - c->Message(13, "Error: Insufficient status to summon this item."); - else if (sep->argnum==2 && sep->IsNumber(2)) - c->SummonItem(itemid, atoi(sep->arg[2])); - else if (sep->argnum==3) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3])); - else if (sep->argnum==4) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); - else if (sep->argnum==5) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); - else if (sep->argnum==6) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); - else if (sep->argnum==7) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); - else if (sep->argnum==8) - c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); - else { - c->SummonItem(itemid); - } + std::string cmd_msg = sep->msg; + size_t link_open = cmd_msg.find('\x12'); + size_t link_close = cmd_msg.find_last_of('\x12'); + if (link_open != link_close && (cmd_msg.length() - link_open) > EmuConstants::TEXT_LINK_BODY_LENGTH) { + TextLinkBody_Struct link_body; + Client::TextLink::DegenerateLinkBody(link_body, cmd_msg.substr(link_open + 1, EmuConstants::TEXT_LINK_BODY_LENGTH)); + itemid = link_body.item_id; } + else if (!sep->IsNumber(1)) { + c->Message(0, "Usage: #summonitem [item id | link] [charges], charges are optional"); + return; + } + else { + itemid = atoi(sep->arg[1]); + } + if (!itemid) { + c->Message(0, "A valid item id number is required (derived: 0)"); + return; + } + + int16 item_status = 0; + const Item_Struct* item = database.GetItem(itemid); + if (item) { + item_status = static_cast(item->MinStatus); + } + + if (item_status > c->Admin()) + c->Message(13, "Error: Insufficient status to summon this item."); + else if (sep->argnum == 2 && sep->IsNumber(2)) + c->SummonItem(itemid, atoi(sep->arg[2])); + else if (sep->argnum == 3) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3])); + else if (sep->argnum == 4) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); + else if (sep->argnum == 5) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5])); + else if (sep->argnum == 6) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6])); + else if (sep->argnum == 7) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7])); + else if (sep->argnum == 8) + c->SummonItem(itemid, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]), atoi(sep->arg[7]), atoi(sep->arg[8])); + else { + c->SummonItem(itemid); + } + } void command_giveitem(Client *c, const Seperator *sep) diff --git a/zone/command.h b/zone/command.h index 45aa31fa6..eb3633f57 100644 --- a/zone/command.h +++ b/zone/command.h @@ -94,6 +94,7 @@ void command_emoteview(Client* c, const Seperator *sep); void command_enablerecipe(Client *c, const Seperator *sep); void command_equipitem(Client *c, const Seperator *sep); void command_face(Client *c, const Seperator *sep); +void command_findaliases(Client *c, const Seperator *sep); void command_findnpctype(Client *c, const Seperator *sep); void command_findspell(Client *c, const Seperator *sep); void command_findzone(Client *c, const Seperator *sep); diff --git a/zone/common.h b/zone/common.h index 48749dbc3..bcae779a9 100644 --- a/zone/common.h +++ b/zone/common.h @@ -511,7 +511,7 @@ typedef struct //make DoAnim take it instead of int, to enforce its use. enum { //type arguments to DoAnim animKick = 1, - animPiercing = 2, //might be piercing? + anim1HPiercing = 2, //might be piercing? anim2HSlashing = 3, anim2HWeapon = 4, anim1HWeapon = 5, diff --git a/zone/effects.cpp b/zone/effects.cpp index dc3392403..05f6cd927 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -112,7 +112,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio / 100; + + else if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; else if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -145,7 +148,10 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= GetFocusEffect(focusFcDamageAmt, spell_id); value -= GetFocusEffect(focusFcDamageAmt2, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if (RuleB(Spells, IgnoreSpellDmgLvlRestriction) && !spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg) + value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); + + else if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); if (IsNPC() && CastToNPC()->GetSpellScale()) @@ -225,6 +231,9 @@ int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg) { + if (RuleB(Spells, FlatItemExtraSpellAmt)) + return extra_spell_amt; + int total_cast_time = 0; if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) @@ -287,7 +296,7 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { value += GetFocusEffect(focusFcHealAmt, spell_id); value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier; value += value*target->GetHealRate(spell_id, this)/100; @@ -336,7 +345,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) cost *= 2; // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { int16 mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell diff --git a/zone/entity.cpp b/zone/entity.cpp index 92fefb2ec..a79d01609 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -644,15 +644,6 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); - /* Zone controller process EVENT_SPAWN_ZONE */ - if (RuleB(Zone, UseZoneController)) { - if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ - char data_pass[100] = { 0 }; - snprintf(data_pass, 99, "%d %d", npc->GetID(), npc->GetNPCTypeID()); - parse->EventNPC(EVENT_SPAWN_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); - } - } - uint16 emoteid = npc->GetEmoteID(); if (emoteid != 0) npc->DoNPCEmote(ONSPAWN, emoteid); @@ -678,6 +669,16 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) npc_list.insert(std::pair(npc->GetID(), npc)); mob_list.insert(std::pair(npc->GetID(), npc)); + + /* Zone controller process EVENT_SPAWN_ZONE */ + if (RuleB(Zone, UseZoneController)) { + if (entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID) && npc->GetNPCTypeID() != ZONE_CONTROLLER_NPC_ID){ + char data_pass[100] = { 0 }; + snprintf(data_pass, 99, "%d %d", npc->GetID(), npc->GetNPCTypeID()); + parse->EventNPC(EVENT_SPAWN_ZONE, entity_list.GetNPCByNPCTypeID(ZONE_CONTROLLER_NPC_ID)->CastToNPC(), nullptr, data_pass, 0); + } + } + } void EntityList::AddMerc(Merc *merc, bool SendSpawnPacket, bool dontqueue) diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 1e785ce9b..3db1eabea 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -232,27 +232,27 @@ void Lua_Client::SetBindPoint() { void Lua_Client::SetBindPoint(int to_zone) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone); + self->SetBindPoint(0, to_zone); } void Lua_Client::SetBindPoint(int to_zone, int to_instance) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance); + self->SetBindPoint(0, to_zone, to_instance); } void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f)); + self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x,0.0f,0.0f)); } void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f)); + self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, 0.0f)); } void Lua_Client::SetBindPoint(int to_zone, int to_instance, float new_x, float new_y, float new_z) { Lua_Safe_Call_Void(); - self->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); + self->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); } float Lua_Client::GetBindX() { @@ -1067,6 +1067,11 @@ void Lua_Client::MarkSingleCompassLoc(float in_x, float in_y, float in_z, int co self->MarkSingleCompassLoc(in_x, in_y, in_z, count); } +void Lua_Client::ClearCompassMark() { + Lua_Safe_Call_Void(); + self->MarkSingleCompassLoc(0,0,0,0); +} + int Lua_Client::GetNextAvailableSpellBookSlot() { Lua_Safe_Call_Int(); return self->GetNextAvailableSpellBookSlot(); @@ -1548,6 +1553,7 @@ luabind::scope lua_register_client() { .def("GrantAlternateAdvancementAbility", (bool(Lua_Client::*)(int, int, bool))&Lua_Client::GrantAlternateAdvancementAbility) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float))&Lua_Client::MarkSingleCompassLoc) .def("MarkSingleCompassLoc", (void(Lua_Client::*)(float,float,float,int))&Lua_Client::MarkSingleCompassLoc) + .def("ClearCompassMark",(void(Lua_Client::*)(void))&Lua_Client::ClearCompassMark) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(void))&Lua_Client::GetNextAvailableSpellBookSlot) .def("GetNextAvailableSpellBookSlot", (int(Lua_Client::*)(int))&Lua_Client::GetNextAvailableSpellBookSlot) .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) diff --git a/zone/lua_client.h b/zone/lua_client.h index 4584edfd0..36ea2b8a4 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -240,6 +240,7 @@ public: bool GrantAlternateAdvancementAbility(int aa_id, int points, bool ignore_cost); void MarkSingleCompassLoc(float in_x, float in_y, float in_z); void MarkSingleCompassLoc(float in_x, float in_y, float in_z, int count); + void ClearCompassMark(); int GetNextAvailableSpellBookSlot(); int GetNextAvailableSpellBookSlot(int start); int FindSpellBookSlotBySpellID(int spell_id); diff --git a/zone/merc.cpp b/zone/merc.cpp index b4125735e..91a69f374 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -2678,7 +2678,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) { int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost) { // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell - if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) + if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%17) - 1] >= GetLevel() - 5) { int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; // Doesnt generate mana, so best case is a free spell diff --git a/zone/mob.cpp b/zone/mob.cpp index e28ccefcc..0e2cd7d88 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -5029,7 +5029,10 @@ uint16 Mob::GetSkillByItemType(int ItemType) case ItemType2HBlunt: return Skill2HBlunt; case ItemType2HPiercing: - return Skill1HPiercing; // change to 2HPiercing once activated + if (IsClient() && CastToClient()->GetClientVersion() < ClientVersion::RoF2) + return Skill1HPiercing; + else + return Skill2HPiercing; case ItemTypeBow: return SkillArchery; case ItemTypeLargeThrowing: @@ -5057,6 +5060,8 @@ uint8 Mob::GetItemTypeBySkill(SkillUseTypes skill) return ItemType2HSlash; case Skill1HPiercing: return ItemType1HPiercing; + case Skill2HPiercing: // watch for undesired client behavior + return ItemType2HPiercing; case Skill1HBlunt: return ItemType1HBlunt; case Skill2HBlunt: @@ -5112,7 +5117,7 @@ int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) { if (!IsValidSpell(spell_id)) return false; - int spell_level = spells[spell_id].classes[(GetClass()%16) - 1]; + int spell_level = spells[spell_id].classes[(GetClass()%17) - 1]; int effect_value = 0; int lvlModifier = 100; @@ -5689,4 +5694,170 @@ int32 Mob::GetMeleeMitigation() { mitigation += itembonuses.MeleeMitigationEffect; mitigation += aabonuses.MeleeMitigationEffect; return mitigation; -} \ No newline at end of file +} + +/* this is the mob being attacked. + * Pass in the weapon's ItemInst + */ +int Mob::ResistElementalWeaponDmg(const ItemInst *item) +{ + if (!item) + return 0; + int magic = 0, fire = 0, cold = 0, poison = 0, disease = 0, chromatic = 0, prismatic = 0, physical = 0, + corruption = 0; + int resist = 0; + int roll = 0; + /* this is how the client does the resist rolls for these. + * Given the difficulty of parsing out these resists, I'll trust the client + */ + if (item->GetItemElementalDamage(magic, fire, cold, poison, disease, chromatic, prismatic, physical, corruption, true)) { + if (magic) { + resist = GetMR(); + if (resist >= 201) { + magic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + magic = 0; + else if (roll < 100) + magic = magic * roll / 100; + } + } + + if (fire) { + resist = GetFR(); + if (resist >= 201) { + fire = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + fire = 0; + else if (roll < 100) + fire = fire * roll / 100; + } + } + + if (cold) { + resist = GetCR(); + if (resist >= 201) { + cold = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + cold = 0; + else if (roll < 100) + cold = cold * roll / 100; + } + } + + if (poison) { + resist = GetPR(); + if (resist >= 201) { + poison = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + poison = 0; + else if (roll < 100) + poison = poison * roll / 100; + } + } + + if (disease) { + resist = GetDR(); + if (resist >= 201) { + disease = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + disease = 0; + else if (roll < 100) + disease = disease * roll / 100; + } + } + + if (corruption) { + resist = GetCorrup(); + if (resist >= 201) { + corruption = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + corruption = 0; + else if (roll < 100) + corruption = corruption * roll / 100; + } + } + + if (chromatic) { + resist = GetFR(); + int temp = GetCR(); + if (temp < resist) + resist = temp; + + temp = GetMR(); + if (temp < resist) + resist = temp; + + temp = GetDR(); + if (temp < resist) + resist = temp; + + temp = GetPR(); + if (temp < resist) + resist = temp; + + if (resist >= 201) { + chromatic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + chromatic = 0; + else if (roll < 100) + chromatic = chromatic * roll / 100; + } + } + + if (prismatic) { + resist = (GetFR() + GetCR() + GetMR() + GetDR() + GetPR()) / 5; + if (resist >= 201) { + prismatic = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + prismatic = 0; + else if (roll < 100) + prismatic = prismatic * roll / 100; + } + } + + if (physical) { + resist = GetPhR(); + if (resist >= 201) { + physical = 0; + } else { + roll = zone->random.Int(0, 200) - resist; + if (roll < 1) + physical = 0; + else if (roll < 100) + physical = physical * roll / 100; + } + } + } + + return magic + fire + cold + poison + disease + chromatic + prismatic + physical + corruption; +} + +/* this is the mob being attacked. + * Pass in the weapon's ItemInst + */ +int Mob::CheckBaneDamage(const ItemInst *item) +{ + if (!item) + return 0; + + int damage = item->GetItemBaneDamageBody(GetBodyType(), true); + damage += item->GetItemBaneDamageRace(GetRace(), true); + + return damage; +} diff --git a/zone/mob.h b/zone/mob.h index 334c81e51..11c11573f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -231,6 +231,8 @@ public: int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false, int level_override = -1); int ResistPhysical(int level_diff, uint8 caster_level); + int ResistElementalWeaponDmg(const ItemInst *item); + int CheckBaneDamage(const ItemInst *item); uint16 GetSpecializeSkillValue(uint16 spell_id) const; void SendSpellBarDisable(); void SendSpellBarEnable(uint16 spellid); @@ -466,7 +468,7 @@ public: inline bool IsMoving() const { return moving; } virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } virtual void GoToBind(uint8 bindnum = 0) { } - virtual void Gate(); + virtual void Gate(uint8 bindnum = 0); int GetWalkspeed() const { return(_GetWalkSpeed()); } int GetRunspeed() const { return(_GetRunSpeed()); } void SetCurrentSpeed(int in); @@ -885,7 +887,7 @@ public: Mob* GetShieldTarget() const { return shield_target; } void SetShieldTarget(Mob* mob) { shield_target = mob; } bool HasActiveSong() const { return(bardsong != 0); } - bool Charmed() const { return charmed; } + bool Charmed() const { return typeofpet == petCharmed; } static uint32 GetLevelHP(uint8 tlevel); uint32 GetZoneID() const; //for perl virtual int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false); diff --git a/zone/npc.cpp b/zone/npc.cpp index 22e4b4b0d..103b5548e 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1425,13 +1425,13 @@ uint32 NPC::GetMaxDamage(uint8 tlevel) return dmg; } -void NPC::PickPocket(Client* thief) { - +void NPC::PickPocket(Client* thief) +{ thief->CheckIncreaseSkill(SkillPickPockets, nullptr, 5); - //make sure were allowed to targte them: - int olevel = GetLevel(); - if(olevel > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) { + //make sure were allowed to target them: + int over_level = GetLevel(); + if(over_level > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) { thief->Message(13, "You are too inexperienced to pick pocket this target"); thief->SendPickPocketResponse(this, 0, PickPocketFailed); //should we check aggro @@ -1447,150 +1447,109 @@ void NPC::PickPocket(Client* thief) { } int steal_skill = thief->GetSkill(SkillPickPockets); - int stealchance = steal_skill*100/(5*olevel+5); - ItemInst* inst = 0; - int x = 0; - int slot[50]; - int steal_items[50]; - int charges[50]; - int money[4]; - money[0] = GetPlatinum(); - money[1] = GetGold(); - money[2] = GetSilver(); - money[3] = GetCopper(); - if (steal_skill < 125) - money[0] = 0; - if (steal_skill < 60) - money[1] = 0; - memset(slot,0,50); - memset(steal_items,0,50); - memset(charges,0,50); + int steal_chance = steal_skill * 100 / (5 * over_level + 5); + //Determine wheter to steal money or an item. - bool no_coin = ((money[0] + money[1] + money[2] + money[3]) == 0); - bool steal_item = (zone->random.Roll(50) || no_coin); - if (steal_item) - { - ItemList::iterator cur,end; - cur = itemlist.begin(); - end = itemlist.end(); - for(; cur != end && x < 49; ++cur) { - ServerLootItem_Struct* citem = *cur; - const Item_Struct* item = database.GetItem(citem->item_id); - if (item) - { - inst = database.CreateItem(item, citem->charges); - bool is_arrow = (item->ItemType == ItemTypeArrow) ? true : false; - int slot_id = thief->GetInv().FindFreeSlot(false, true, inst->GetItem()->Size, is_arrow); - if (/*!Equipped(item->ID) &&*/ - !item->Magic && item->NoDrop != 0 && !inst->IsType(ItemClassContainer) && slot_id != INVALID_INDEX - /*&& steal_skill > item->StealSkill*/ ) - { - slot[x] = slot_id; - steal_items[x] = item->ID; - if (inst->IsStackable()) - charges[x] = 1; - else - charges[x] = citem->charges; - x++; - } - } + int money[6] = { 0, ((steal_skill >= 125) ? (GetPlatinum()) : (0)), ((steal_skill >= 60) ? (GetGold()) : (0)), GetSilver(), GetCopper(), 0 }; + bool has_coin = ((money[PickPocketPlatinum] | money[PickPocketGold] | money[PickPocketSilver] | money[PickPocketCopper]) != 0); + bool steal_item = (steal_skill >= steal_chance && (zone->random.Roll(50) || !has_coin)); + + // still needs to have FindFreeSlot vs PutItemInInventory issue worked out + while (steal_item) { + std::vector> loot_selection; // + for (auto item_iter : itemlist) { + if (!item_iter || !item_iter->item_id) + continue; + + auto item_test = database.GetItem(item_iter->item_id); + if (item_test->Magic || !item_test->NoDrop || item_test->ItemType == ItemClassContainer || thief->CheckLoreConflict(item_test)) + continue; + + loot_selection.push_back(std::make_pair(item_test, ((item_test->Stackable) ? (1) : (item_iter->charges)))); } - if (x > 0) - { - int random = zone->random.Int(0, x-1); - inst = database.CreateItem(steal_items[random], charges[random]); - if (inst) - { - const Item_Struct* item = inst->GetItem(); - if (item) - { - if (/*item->StealSkill || */steal_skill >= stealchance) - { - thief->PutItemInInventory(slot[random], *inst); - thief->SendItemPacket(slot[random], inst, ItemPacketTrade); - RemoveItem(item->ID); - thief->SendPickPocketResponse(this, 0, PickPocketItem, item); - } - else - steal_item = false; - } - else - steal_item = false; - } - else - steal_item = false; - } - else if (!no_coin) - { + if (loot_selection.empty()) { steal_item = false; - } - else - { - thief->Message(0, "This target's pockets are empty"); - thief->SendPickPocketResponse(this, 0, PickPocketFailed); - } - } - if (!steal_item) //Steal money - { - uint32 amt = zone->random.Int(1, (steal_skill/25)+1); - int steal_type = 0; - if (!money[0]) - { - steal_type = 1; - if (!money[1]) - { - steal_type = 2; - if (!money[2]) - { - steal_type = 3; - } - } + break; } - if (zone->random.Roll(stealchance)) - { - switch (steal_type) - { - case 0:{ - if (amt > GetPlatinum()) - amt = GetPlatinum(); - SetPlatinum(GetPlatinum()-amt); - thief->AddMoneyToPP(0,0,0,amt,false); - thief->SendPickPocketResponse(this, amt, PickPocketPlatinum); - break; - } - case 1:{ - if (amt > GetGold()) - amt = GetGold(); - SetGold(GetGold()-amt); - thief->AddMoneyToPP(0,0,amt,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketGold); - break; - } - case 2:{ - if (amt > GetSilver()) - amt = GetSilver(); - SetSilver(GetSilver()-amt); - thief->AddMoneyToPP(0,amt,0,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketSilver); - break; - } - case 3:{ - if (amt > GetCopper()) - amt = GetCopper(); - SetCopper(GetCopper()-amt); - thief->AddMoneyToPP(amt,0,0,0,false); - thief->SendPickPocketResponse(this, amt, PickPocketCopper); - break; - } + int random = zone->random.Int(0, (loot_selection.size() - 1)); + uint16 slot_id = thief->GetInv().FindFreeSlot(false, true, (loot_selection[random].first->Size), (loot_selection[random].first->ItemType == ItemTypeArrow)); + if (slot_id == INVALID_INDEX) { + steal_item = false; + break; + } + + auto item_inst = database.CreateItem(loot_selection[random].first, loot_selection[random].second); + if (item_inst == nullptr) { + steal_item = false; + break; + } + + // Successful item pickpocket + if (item_inst->IsStackable() && RuleB(Character, UseStackablePickPocketing)) { + if (!thief->TryStacking(item_inst, ItemPacketTrade, false, false)) { + thief->PutItemInInventory(slot_id, *item_inst); + thief->SendItemPacket(slot_id, item_inst, ItemPacketTrade); } } - else - { - thief->SendPickPocketResponse(this, 0, PickPocketFailed); + else { + thief->PutItemInInventory(slot_id, *item_inst); + thief->SendItemPacket(slot_id, item_inst, ItemPacketTrade); } + RemoveItem(item_inst->GetID()); + thief->SendPickPocketResponse(this, 0, PickPocketItem, item_inst->GetItem()); + + return; } - safe_delete(inst); + + while (!steal_item && has_coin) { + uint32 coin_amount = zone->random.Int(1, (steal_skill / 25) + 1); + + int coin_type = PickPocketPlatinum; + while (coin_type <= PickPocketCopper) { + if (money[coin_type]) { + if (coin_amount > money[coin_type]) + coin_amount = money[coin_type]; + break; + } + ++coin_type; + } + if (coin_type > PickPocketCopper) + break; + + memset(money, 0, (sizeof(int) * 6)); + money[coin_type] = coin_amount; + + if (zone->random.Roll(steal_chance)) { // Successful coin pickpocket + switch (coin_type) { + case PickPocketPlatinum: + SetPlatinum(GetPlatinum() - coin_amount); + break; + case PickPocketGold: + SetGold(GetGold() - coin_amount); + break; + case PickPocketSilver: + SetSilver(GetSilver() - coin_amount); + break; + case PickPocketCopper: + SetCopper(GetCopper() - coin_amount); + break; + default: // has_coin..but, doesn't have coin? + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + return; + } + + thief->AddMoneyToPP(money[3], money[2], money[1], money[0], false); + thief->SendPickPocketResponse(this, coin_amount, coin_type); + return; + } + + thief->SendPickPocketResponse(this, 0, PickPocketFailed); + return; + } + + thief->Message(0, "This target's pockets are empty"); + thief->SendPickPocketResponse(this, 0, PickPocketFailed); } void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) { diff --git a/zone/npc.h b/zone/npc.h index 327918c19..fe658aab2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -165,7 +165,7 @@ public: virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther); void GoToBind(uint8 bindnum = 0) { GMMove(m_SpawnPoint.x, m_SpawnPoint.y, m_SpawnPoint.z, m_SpawnPoint.w); } - void Gate(); + void Gate(uint8 bindnum = 0); void GetPetState(SpellBuff_Struct *buffs, uint32 *items, char *name); void SetPetState(SpellBuff_Struct *buffs, uint32 *items); diff --git a/zone/object.cpp b/zone/object.cpp index 7255cd9e9..d06a311c0 100644 --- a/zone/object.cpp +++ b/zone/object.cpp @@ -533,20 +533,26 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object) ClickObjectAction_Struct* coa = (ClickObjectAction_Struct*)outapp->pBuffer; //TODO: there is prolly a better way to do this. - //if this is not the main user, send them a close and a message - if(user == nullptr || user == sender) - coa->open = 0x01; - else { - coa->open = 0x00; - //sender->Message(13, "Somebody is allready using that container."); - } - m_inuse = true; - coa->type = m_type; - coa->unknown16 = 0x0a; + m_inuse = true; + coa->type = m_type; + coa->unknown16 = 0x0a; - coa->drop_id = click_object->drop_id; - coa->player_id = click_object->player_id; - coa->icon = m_icon; + coa->drop_id = click_object->drop_id; + coa->player_id = click_object->player_id; + coa->icon = m_icon; + + //if this is not the main user, send them a close and a message + if (user == nullptr || user == sender) { + coa->open = 0x01; + } + else { + coa->open = 0x00; + + if (sender->GetClientVersion() >= ClientVersion::RoF) { + coa->drop_id = 0xFFFFFFFF; + sender->Message(0, "Someone else is using that. Try again later."); + } + } if(sender->IsLooting()) { diff --git a/zone/oldcode.cpp b/zone/oldcode.cpp index 075923360..600e8ad5c 100644 --- a/zone/oldcode.cpp +++ b/zone/oldcode.cpp @@ -1082,11 +1082,11 @@ int32 Client::GenericFocus(uint16 spell_id, uint16 modspellid) switch( spells[modspellid].effectid[i] ) { case SE_LimitMaxLevel: - if (spell.classes[(GetClass()%16) - 1] > modspell.base[i]) + if (spell.classes[(GetClass()%17) - 1] > modspell.base[i]) return 100; break; case SE_LimitMinLevel: - if (spell.classes[(GetClass()%16) - 1] < modspell.base[i]) + if (spell.classes[(GetClass()%17) - 1] < modspell.base[i]) return 100; break; case SE_IncreaseRange: diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d4c5f34d0..9c51b8a92 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1072,7 +1072,7 @@ XS(XS_Client_SetBindPoint) new_z = (float)SvNV(ST(5)); } - THIS->SetBindPoint(to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); + THIS->SetBindPoint(0, to_zone, to_instance, glm::vec3(new_x, new_y, new_z)); } XSRETURN_EMPTY; } diff --git a/zone/pets.cpp b/zone/pets.cpp index f5f741f44..fd777fab4 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -283,7 +283,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower, npc_type->level += 1 + ((int)act_power / 25) > npc_type->level + RuleR(Pets, PetPowerLevelCap) ? RuleR(Pets, PetPowerLevelCap) : 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2))); npc_type->max_dmg = (npc_type->max_dmg * (1 + (scale_power / 2))); - npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : (1 + (scale_power / 2)); + npc_type->size = npc_type->size * (1 + (scale_power / 2)) > npc_type->size * 3 ? npc_type->size * 3 : npc_type-> size * (1 + (scale_power / 2)); } record.petpower = act_power; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 86b8cb7d9..b16613e75 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -1565,7 +1565,7 @@ void QuestManager::ding() { void QuestManager::rebind(int zoneid, const glm::vec3& location) { QuestManagerCurrentQuestVars(); if(initiator && initiator->IsClient()) { - initiator->SetBindPoint(zoneid, 0, location); + initiator->SetBindPoint(0, zoneid, 0, location); } } @@ -2766,14 +2766,13 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam } safe_delete_array(escaped_string); - if (silent) - sayid = sayid + 750000; - else - sayid = sayid + 500000; - //Create the say link as an item link hash Client::TextLink linker; - linker.SetProxyItemID(sayid); + linker.SetProxyItemID(SAYLINK_ITEM_ID); + if (silent) + linker.SetProxyAugment2ID(sayid); + else + linker.SetProxyAugment1ID(sayid); linker.SetProxyText(LinkName); auto say_link = linker.GenerateLink(); @@ -3164,4 +3163,4 @@ void QuestManager::UpdateZoneHeader(std::string type, std::string value) { memcpy(outapp->pBuffer, &zone->newzone_data, outapp->size); entity_list.QueueClients(0, outapp); safe_delete(outapp); -} \ No newline at end of file +} diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index c43c8f432..6c6177d29 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -100,11 +100,14 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, //this really should go through the same code as normal melee damage to //pick up all the special behavior there - if (!who) + if ((who == nullptr || ((IsClient() && CastToClient()->dead) || (who->IsClient() && who->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(who)))) return; + + if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE)) + max_damage = -5; - if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE) || who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE)) - return; //-5? + if (who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE) && skill != SkillBackstab) + max_damage = -5; uint32 hate = max_damage; if(hate_override > -1) @@ -660,7 +663,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime) } DoSpecialAttackDamage(other, SkillBackstab, ndamage, min_hit, hate, ReuseTime, false, false); - DoAnim(animPiercing); + DoAnim(anim1HPiercing); } // assassinate [No longer used for regular assassinate 6-29-14] @@ -673,7 +676,7 @@ void Mob::RogueAssassinate(Mob* other) }else{ other->Damage(this, -5, SPELL_UNKNOWN, SkillBackstab); } - DoAnim(animPiercing); //piercing animation + DoAnim(anim1HPiercing); //piercing animation } void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { @@ -901,7 +904,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite WDmg = weapon_damage; if (LaunchProjectile){//1: Shoot the Projectile once we calculate weapon damage. - TryProjectileAttack(other, AmmoItem, SkillArchery, WDmg, RangeWeapon, Ammo, AmmoSlot, speed); + TryProjectileAttack(other, AmmoItem, SkillArchery, (WDmg + ADmg), RangeWeapon, Ammo, AmmoSlot, speed); return; } @@ -923,7 +926,10 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite MaxDmg += MaxDmg*bonusArcheryDamageModifier / 100; - Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); + if (RuleB(Combat, ProjectileDmgOnImpact)) + Log.Out(Logs::Detail, Logs::Combat, "Bow and Arrow DMG %d, Max Damage %d.", WDmg, MaxDmg); + else + Log.Out(Logs::Detail, Logs::Combat, "Bow DMG %d, Arrow DMG %d, Max Damage %d.", WDmg, ADmg, MaxDmg); bool dobonus = false; if(GetClass() == RANGER && GetLevel() > 50){ diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e866d1e0f..ca10259a1 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -499,7 +499,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_GateCastersBindpoint: //Shin: Used on Teleport Bind. + case SE_GateCastersBindpoint: // Used on Teleport Bind. case SE_Teleport: // gates, rings, circles, etc case SE_Teleport2: { @@ -532,13 +532,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove } if (effect == SE_GateCastersBindpoint && caster->IsClient()) - { //Shin: Teleport Bind uses caster's bind point - x = caster->CastToClient()->GetBindX(); - y = caster->CastToClient()->GetBindY(); - z = caster->CastToClient()->GetBindZ(); - heading = caster->CastToClient()->GetBindHeading(); + { // Teleport Bind uses caster's bind point + int index = spells[spell_id].base[i] - 1; + if (index < 0 || index > 4) + index = 0; + x = caster->CastToClient()->GetBindX(index); + y = caster->CastToClient()->GetBindY(index); + z = caster->CastToClient()->GetBindZ(index); + heading = caster->CastToClient()->GetBindHeading(index); //target_zone = caster->CastToClient()->GetBindZoneId(); target_zone doesn't work due to const char - CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(), 0, x, y, z, heading); + CastToClient()->MovePC(caster->CastToClient()->GetBindZoneID(index), 0, x, y, z, heading); break; } @@ -917,7 +920,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -966,7 +969,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -1002,7 +1005,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(caster->IsClient() && caster != this) caster->CastToClient()->QueuePacket(message_packet); - CastToClient()->SetBindPoint(); + CastToClient()->SetBindPoint(spells[spell_id].base[i] - 1); Save(); safe_delete(action_packet); safe_delete(message_packet); @@ -1012,7 +1015,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } - case SE_Gate: //TO DO: Add support for secondary and tertiary gate abilities (base2) + case SE_Gate: { #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Gate"); @@ -1020,7 +1023,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if(!spellbonuses.AntiGate){ if(zone->random.Roll(effect_value)) - Gate(); + Gate(spells[spell_id].base2[i] - 1); else caster->Message_StringID(MT_SpellFailure,GATE_FAIL); } @@ -4227,7 +4230,7 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; case SE_LimitMaxLevel: - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - base1; // every level over cap reduces the effect by base2 percent unless from a clicky when // ItemCastsUseFocus is true @@ -4243,7 +4246,7 @@ int16 Client::CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id) break; case SE_LimitMinLevel: - if ((spell.classes[(GetClass() % 16) - 1]) < base1) + if ((spell.classes[(GetClass() % 17) - 1]) < base1) LimitFailure = true; break; @@ -4661,7 +4664,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitMaxLevel: if (IsNPC()) break; - spell_level = spell.classes[(GetClass() % 16) - 1]; + spell_level = spell.classes[(GetClass() % 17) - 1]; lvldiff = spell_level - focus_spell.base[i]; // every level over cap reduces the effect by focus_spell.base2[i] percent unless from a clicky // when ItemCastsUseFocus is true @@ -4679,7 +4682,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_LimitMinLevel: if (IsNPC()) break; - if (spell.classes[(GetClass() % 16) - 1] < focus_spell.base[i]) + if (spell.classes[(GetClass() % 17) - 1] < focus_spell.base[i]) return (0); break; diff --git a/zone/spells.cpp b/zone/spells.cpp index b8c3023b8..90efd791f 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -1732,7 +1732,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(IsRaidGrouped()) { - group_id_caster = (GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = GetRaid()) { + uint32 group_id = raid->GetGroup(CastToClient()); + group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } else if(IsPet()) @@ -1744,7 +1747,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(owner->IsRaidGrouped()) { - group_id_caster = (owner->GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (owner->GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = owner->GetRaid()) { + uint32 group_id = raid->GetGroup(owner->CastToClient()); + group_id_caster = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } #ifdef BOTS @@ -1770,7 +1776,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(spell_target->IsRaidGrouped()) { - group_id_target = (spell_target->GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (spell_target->GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = spell_target->GetRaid()) { + uint32 group_id = raid->GetGroup(spell_target->CastToClient()); + group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } else if(spell_target->IsPet()) @@ -1782,7 +1791,10 @@ bool Mob::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce } else if(owner->IsRaidGrouped()) { - group_id_target = (owner->GetRaid()->GetGroup(CastToClient()) == 0xFFFF) ? 0 : (owner->GetRaid()->GetGroup(CastToClient()) + 1); + if (Raid* raid = owner->GetRaid()) { + uint32 group_id = raid->GetGroup(owner->CastToClient()); + group_id_target = (group_id == 0xFFFFFFFF) ? 0 : (group_id + 1); + } } } #ifdef BOTS @@ -3140,7 +3152,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid Log.Out(Logs::Detail, Logs::Spells, "Adding buff %d will overwrite spell %d in slot %d with caster level %d", spell_id, curbuf.spellid, buffslot, curbuf.casterlevel); // If this is the first buff it would override, use its slot - if (!will_overwrite) + if (!will_overwrite && !IsDisciplineBuff(spell_id)) emptyslot = buffslot; will_overwrite = true; overwrite_slots.push_back(buffslot); @@ -3190,7 +3202,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid // if we hadn't found a free slot before, or if this is earlier // we use it - if (emptyslot == -1 || *cur < emptyslot) + if (emptyslot == -1 || (*cur < emptyslot && !IsDisciplineBuff(spell_id))) emptyslot = *cur; } } diff --git a/zone/tasks.cpp b/zone/tasks.cpp index d52ae842b..0e7de67cb 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -3043,7 +3043,7 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enfor NPC *npc = entity_list.GetID(NPCID)->CastToNPC(); if(!npc) { c->Message(clientMessageYellow, "Task Giver ID is %i", NPCID); - c->Message(clientMessageError, "Unable to find NPC to send EVENT_TASKACCEPTD to. Report this bug."); + c->Message(clientMessageError, "Unable to find NPC to send EVENT_TASKACCEPTED to. Report this bug."); safe_delete_array(buf); return; } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 5ab46dc1f..51a7af4fb 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -1186,8 +1186,7 @@ uint32 ZoneDatabase::GetFreeGrid(uint16 zoneid) { return 0; auto row = results.begin(); - uint32 freeGridID = 1; - freeGridID = atoi(row[0]) + 1; + uint32 freeGridID = row[0] ? atoi(row[0]) + 1 : 1; return freeGridID; } diff --git a/zone/zone.cpp b/zone/zone.cpp index b3a6fc1ca..08a98fb10 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -292,7 +292,7 @@ bool Zone::LoadGroundSpawns() { char* name=0; uint32 gsnumber=0; for(gsindex=0;gsindex<50;gsindex++){ - if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].item<500000){ + if(groundspawn.spawn[gsindex].item>0 && groundspawn.spawn[gsindex].itembinds[4].zoneId = atoi(row[0]); - pp->binds[4].instance_id = atoi(row[1]); - pp->binds[4].x = atoi(row[2]); - pp->binds[4].y = atoi(row[3]); - pp->binds[4].z = atoi(row[4]); - pp->binds[4].heading = atoi(row[5]); + int index = atoi(row[0]); + if (index < 0 || index > 4) continue; - } - /* Is regular bind point */ - pp->binds[0].zoneId = atoi(row[0]); - pp->binds[0].instance_id = atoi(row[1]); - pp->binds[0].x = atoi(row[2]); - pp->binds[0].y = atoi(row[3]); - pp->binds[0].z = atoi(row[4]); - pp->binds[0].heading = atoi(row[5]); + pp->binds[index].zoneId = atoi(row[1]); + pp->binds[index].instance_id = atoi(row[2]); + pp->binds[index].x = atoi(row[3]); + pp->binds[index].y = atoi(row[4]); + pp->binds[index].z = atoi(row[5]); + pp->binds[index].heading = atoi(row[6]); } return true; @@ -1295,19 +1292,23 @@ bool ZoneDatabase::SaveCharacterLanguage(uint32 character_id, uint32 lang_id, ui return true; } -bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home){ - if (zone_id <= 0) { - return false; - } - +bool ZoneDatabase::SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num) +{ /* Save Home Bind Point */ - std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, is_home)" - " VALUES (%u, %u, %u, %f, %f, %f, %f, %i)", character_id, zone_id, instance_id, position.x, position.y, position.z, position.w, is_home); - Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u instance_id: %u position: %s ishome: %u", character_id, zone_id, instance_id, to_string(position).c_str(), is_home); + std::string query = + StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot) VALUES (%u, " + "%u, %u, %f, %f, %f, %f, %i)", + character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num); + + Log.Out(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterBindPoint for character ID: %i zone_id: %u " + "instance_id: %u position: %f %f %f %f bind_num: %u", + character_id, bind.zoneId, bind.instance_id, bind.x, bind.y, bind.z, bind.heading, bind_num); + auto results = QueryDatabase(query); - if (!results.RowsAffected()) { - Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), query.c_str()); - } + if (!results.RowsAffected()) + Log.Out(Logs::General, Logs::None, "ERROR Bind Home Save: %s. %s", results.ErrorMessage().c_str(), + query.c_str()); + return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index c4d26792d..b5e1d3509 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -277,7 +277,7 @@ public: bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp); /* Character Data Saves */ - bool SaveCharacterBindPoint(uint32 character_id, uint32 zone_id, uint32 instance_id, const glm::vec4& position, uint8 is_home); + bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num); bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp); bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp); bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges); diff --git a/zone/zoning.cpp b/zone/zoning.cpp index 5b60448ec..9c7ae87a4 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -707,37 +707,40 @@ void Client::GoToSafeCoords(uint16 zone_id, uint16 instance_id) { } -void Mob::Gate() { - GoToBind(); +void Mob::Gate(uint8 bindnum) { + GoToBind(bindnum); } -void Client::Gate() { - Mob::Gate(); +void Client::Gate(uint8 bindnum) { + Mob::Gate(bindnum); } -void NPC::Gate() { +void NPC::Gate(uint8 bindnum) { entity_list.MessageClose_StringID(this, true, 200, MT_Spells, GATES, GetCleanName()); - Mob::Gate(); + Mob::Gate(bindnum); } -void Client::SetBindPoint(int to_zone, int to_instance, const glm::vec3& location) { +void Client::SetBindPoint(int bind_num, int to_zone, int to_instance, const glm::vec3 &location) +{ + if (bind_num < 0 || bind_num >= 4) + bind_num = 0; + if (to_zone == -1) { - m_pp.binds[0].zoneId = zone->GetZoneID(); - m_pp.binds[0].instance_id = (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; - m_pp.binds[0].x = m_Position.x; - m_pp.binds[0].y = m_Position.y; - m_pp.binds[0].z = m_Position.z; + m_pp.binds[bind_num].zoneId = zone->GetZoneID(); + m_pp.binds[bind_num].instance_id = + (zone->GetInstanceID() != 0 && zone->IsInstancePersistent()) ? zone->GetInstanceID() : 0; + m_pp.binds[bind_num].x = m_Position.x; + m_pp.binds[bind_num].y = m_Position.y; + m_pp.binds[bind_num].z = m_Position.z; + } else { + m_pp.binds[bind_num].zoneId = to_zone; + m_pp.binds[bind_num].instance_id = to_instance; + m_pp.binds[bind_num].x = location.x; + m_pp.binds[bind_num].y = location.y; + m_pp.binds[bind_num].z = location.z; } - else { - m_pp.binds[0].zoneId = to_zone; - m_pp.binds[0].instance_id = to_instance; - m_pp.binds[0].x = location.x; - m_pp.binds[0].y = location.y; - m_pp.binds[0].z = location.z; - } - auto regularBindPoint = glm::vec4(m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, 0.0f); - database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[0].zoneId, m_pp.binds[0].instance_id, regularBindPoint, 0); + database.SaveCharacterBindPoint(this->CharacterID(), m_pp.binds[bind_num], bind_num); } void Client::GoToBind(uint8 bindnum) {