diff --git a/changelog.txt b/changelog.txt index 30cdf9ba7..2dca36203 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 03/29/2015 == +Secrets: Identified the Target Ring fields for RoF/RoF2. +Secrets: Added a perl accessor for the last target ring position received from the client. Usage: $client->GetTargetRingX(), $client->GetTargetRingY(), $client->GetTargetRingZ() + == 03/12/2015 == Akkadius: [eqemu_update.pl V7] Add Option 9) LUA Modules - Download latest LUA Modules (Required for Lua) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 6f1d52505..39acb6cc3 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1287,8 +1287,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 50f4eb6de..ef1626e84 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -227,8 +227,8 @@ namespace RoF SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); OUT(spawnid); - OUT(value); OUT(action); + OUT(speed); FINISH_ENCODE(); } @@ -479,7 +479,7 @@ namespace RoF eq->slot = 13; else OUT(slot); - + OUT(spell_id); eq->inventoryslot = ServerToRoFSlot(emu->inventoryslot); //OUT(inventoryslot); @@ -703,7 +703,7 @@ namespace RoF { SETUP_VAR_ENCODE(ExpeditionCompass_Struct); ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); - + OUT(count); for (uint32 i = 0; i < emu->count; ++i) @@ -1250,7 +1250,7 @@ namespace RoF switch (emu_e->rank) { case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0 case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1 - case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 + case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE } @@ -2990,7 +2990,7 @@ namespace RoF eq_cse->Enabled = emu_cse->Enabled; eq_cse->LastLogin = emu_cse->LastLogin; eq_cse->Unknown2 = emu_cse->Unknown2; - + emu_ptr += sizeof(CharacterSelectEntry_Struct); eq_ptr += sizeof(structs::CharacterSelectEntry_Struct); } @@ -3047,7 +3047,7 @@ namespace RoF switch (emu->Rank) { case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0 case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1 - case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 + case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 default: { eq->Rank = emu->Rank; break; } } @@ -3314,7 +3314,7 @@ namespace RoF delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); - + #if 0 // original code EQApplicationPacket *in = *p; *p = nullptr; @@ -3778,7 +3778,7 @@ namespace RoF } ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } - + ENCODE(OP_ZonePlayerToBind) { SETUP_VAR_ENCODE(ZonePlayerToBind_Struct); @@ -3969,8 +3969,8 @@ namespace RoF switch (emu->guildrank) { case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0 case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1 - case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 - default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // + case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 + default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // } } @@ -4119,6 +4119,18 @@ namespace RoF FINISH_DIRECT_DECODE(); } + DECODE(OP_Animation) + { + DECODE_LENGTH_EXACT(structs::Animation_Struct); + SETUP_DIRECT_DECODE(Animation_Struct, structs::Animation_Struct); + + IN(spawnid); + IN(action); + IN(speed); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_ApplyPoison) { DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); @@ -4231,12 +4243,16 @@ namespace RoF emu->slot = 10; else IN(slot); - + IN(spell_id); emu->inventoryslot = RoFToServerSlot(eq->inventoryslot); //IN(inventoryslot); IN(target_id); + IN(y_pos); + IN(x_pos); + IN(z_pos); + FINISH_DIRECT_DECODE(); } @@ -5102,7 +5118,7 @@ namespace RoF hdrf.ItemClass = item->ItemClass; ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); - + if (strlen(item->Name) > 0) { ss.write(item->Name, strlen(item->Name)); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 6bc16c8d5..b60016128 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -160,7 +160,7 @@ namespace RoF2 eq->exit_url_length = emu->exit_url_length; eq->exit_url_length2 = emu->exit_url_length2; - + FINISH_ENCODE(); } @@ -185,7 +185,7 @@ namespace RoF2 { eq->entries[i] = 1; } - + FINISH_ENCODE(); } @@ -295,8 +295,8 @@ namespace RoF2 SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); OUT(spawnid); - OUT(value); OUT(action); + OUT(speed); FINISH_ENCODE(); } @@ -515,6 +515,11 @@ namespace RoF2 { buffslot += 17; } + // TODO: We should really just deal with these "server side" + // so we can have clients not limited to other clients. + // This fixes discs, songs were changed to 20 + if (buffslot == 54) + buffslot = 62; __packet->WriteUInt32(buffslot); __packet->WriteUInt32(emu->entries[i].spell_id); @@ -547,7 +552,7 @@ namespace RoF2 eq->slot = 13; else OUT(slot); - + OUT(spell_id); eq->inventoryslot = ServerToRoF2Slot(emu->inventoryslot); //OUT(inventoryslot); @@ -571,7 +576,7 @@ namespace RoF2 //in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; in->size = strlen(emu->sender) + strlen(emu->targetname) + new_message.length() + 39; - + in->pBuffer = new unsigned char[in->size]; char *OutBuffer = (char *)in->pBuffer; @@ -739,7 +744,7 @@ namespace RoF2 { SETUP_VAR_ENCODE(ExpeditionCompass_Struct); ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); - + OUT(count); for (uint32 i = 0; i < emu->count; ++i) @@ -1286,7 +1291,7 @@ namespace RoF2 switch (emu_e->rank) { case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0 case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1 - case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 + case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE } @@ -2375,9 +2380,9 @@ namespace RoF2 outapp->WriteSInt32(-1); } } - + outapp->WriteUInt32(consts::POTION_BELT_ITEM_COUNT); - + // Copy potion belt where server and client indexes converge for (uint32 r = 0; r < EmuConstants::POTION_BELT_ITEM_COUNT && r < consts::POTION_BELT_ITEM_COUNT; ++r) { outapp->WriteString(emu->potionbelt.Items[r].Name); @@ -2473,7 +2478,7 @@ namespace RoF2 outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(emu->gm); outapp->WriteUInt32(emu->guild_id); - + outapp->WriteUInt8(emu->guildrank); // guildrank outapp->WriteUInt32(0); // Unknown outapp->WriteUInt8(0); // Unknown @@ -2528,12 +2533,12 @@ namespace RoF2 outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown - + for (uint32 r = 0; r < 125; r++) { outapp->WriteUInt8(0); // Unknown } - + outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(0); // Unknown outapp->WriteUInt32(emu->currentRadCrystals); @@ -3099,7 +3104,7 @@ namespace RoF2 switch (emu->Rank) { case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0 case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1 - case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 + case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 default: { eq->Rank = emu->Rank; break; } } @@ -3905,7 +3910,7 @@ namespace RoF2 } ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } - + ENCODE(OP_ZonePlayerToBind) { SETUP_VAR_ENCODE(ZonePlayerToBind_Struct); @@ -4096,8 +4101,8 @@ namespace RoF2 switch (emu->guildrank) { case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0 case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1 - case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 - default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // + case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 + default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // } } @@ -4180,7 +4185,7 @@ namespace RoF2 Position->z = emu->z; Position->animation = emu->animation; Position->deltaY = emu->deltaY; - + Buffer += sizeof(structs::Spawn_Struct_Position); if (strlen(emu->title)) @@ -4251,6 +4256,18 @@ namespace RoF2 FINISH_DIRECT_DECODE(); } + DECODE(OP_Animation) + { + DECODE_LENGTH_EXACT(structs::Animation_Struct); + SETUP_DIRECT_DECODE(Animation_Struct, structs::Animation_Struct); + + IN(spawnid); + IN(action); + IN(speed); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_ApplyPoison) { DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); @@ -4362,11 +4379,14 @@ namespace RoF2 emu->slot = 10; else IN(slot); - + IN(spell_id); emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); //IN(inventoryslot); IN(target_id); + IN(y_pos); + IN(x_pos); + IN(z_pos); FINISH_DIRECT_DECODE(); } @@ -5090,7 +5110,7 @@ namespace RoF2 IN(Quantity); Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct (Unknowns) Unknown004 %d, Unknown008 %d, Unknown012 %d, Unknown076 %d, Unknown276 %d", eq->Unknown004, eq->Unknown008, eq->Unknown012, eq->Unknown076, eq->Unknown276); - Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s", + Log.Out(Logs::Detail, Logs::Trading, "DECODE(OP_TraderShop): TraderBuy_Struct Buy Action %d, Price %d, Trader %d, ItemID %d, Quantity %d, ItemName, %s", eq->Action, eq->Price, eq->TraderID, eq->ItemID, eq->Quantity, eq->ItemName); FINISH_DIRECT_DECODE(); @@ -5720,7 +5740,7 @@ namespace RoF2 RoF2Slot.SlotType = maps::MapPossessions; RoF2Slot.MainSlot = serverSlot; } - + if (serverSlot == MainPowerSource) RoF2Slot.MainSlot = slots::MainPowerSource; diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h index 4e4400cdf..3bb69af5e 100644 --- a/common/patches/rof2_ops.h +++ b/common/patches/rof2_ops.h @@ -124,6 +124,7 @@ E(OP_ZoneSpawns) D(OP_AdventureMerchantSell) D(OP_AltCurrencySell) D(OP_AltCurrencySellSelection) +D(OP_Animation) D(OP_ApplyPoison) D(OP_AugmentInfo) D(OP_AugmentItem) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 36d681587..205d3d603 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -658,7 +658,10 @@ struct CastSpell_Struct /*04*/ uint32 spell_id; /*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast /*20*/ uint32 target_id; -/*24*/ uint32 cs_unknown[5]; +/*24*/ uint32 cs_unknown[2]; +/*32*/ float y_pos; +/*36*/ float x_pos; +/*40*/ float z_pos; /*44*/ }; @@ -1415,8 +1418,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 value; -/*03*/ uint8 action; +/*02*/ uint8 action; +/*03*/ uint8 speed; /*04*/ }; @@ -4186,9 +4189,11 @@ struct Arrow_Struct { /*068*/ uint8 unknown068; /*069*/ uint8 unknown069; /*070*/ uint8 unknown070; -/*071*/ uint8 item_type; -/*072*/ uint8 skill; -/*073*/ uint8 unknown073[16]; +/*071*/ uint8 unknown071; +/*072*/ uint8 unknown072; +/*073*/ uint8 skill; +/*074*/ uint8 item_type; +/*075*/ uint8 unknown075[14]; /*089*/ char model_name[27]; /*116*/ }; diff --git a/common/patches/rof_ops.h b/common/patches/rof_ops.h index 08e8647f3..8e9adfdc9 100644 --- a/common/patches/rof_ops.h +++ b/common/patches/rof_ops.h @@ -109,6 +109,7 @@ E(OP_ZoneSpawns) D(OP_AdventureMerchantSell) D(OP_AltCurrencySell) D(OP_AltCurrencySellSelection) +D(OP_Animation) D(OP_ApplyPoison) D(OP_AugmentInfo) D(OP_AugmentItem) diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 9abeaa889..539560723 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -647,7 +647,10 @@ struct CastSpell_Struct /*04*/ uint32 spell_id; /*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast /*20*/ uint32 target_id; -/*24*/ uint32 cs_unknown[5]; +/*24*/ uint32 cs_unknown[2]; +/*32*/ float y_pos; +/*36*/ float x_pos; +/*40*/ float z_pos; /*44*/ }; @@ -1445,8 +1448,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 value; -/*03*/ uint8 action; +/*02*/ uint8 action; +/*03*/ uint8 speed; /*04*/ }; diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 303bfc3e2..43a179ae9 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1205,8 +1205,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 6d8acdc66..504c82277 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -1182,8 +1182,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 461ea82b6..f00b943eb 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -1062,8 +1062,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 7bcf9086e..42f6ccef6 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1260,8 +1260,8 @@ struct RequestClientZoneChange_Struct { struct Animation_Struct { /*00*/ uint16 spawnid; -/*02*/ uint8 action; -/*03*/ uint8 value; +/*02*/ uint8 speed; +/*03*/ uint8 action; /*04*/ }; diff --git a/common/ruletypes.h b/common/ruletypes.h index 7894c5ebd..c8f9557f5 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -103,6 +103,16 @@ RULE_INT ( Character, BaseRunSpeedCap, 158) // Base Run Speed Cap, on live it's RULE_INT ( Character, OrnamentationAugmentType, 20) //Ornamentation Augment Type RULE_REAL(Character, EnvironmentDamageMulipliter, 1) RULE_BOOL(Character, UnmemSpellsOnDeath, true) +RULE_INT ( Character, TradeskillUpAlchemy, 2 ) // Alchemy skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpBaking, 2 ) // Baking skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpBlacksmithing, 2 ) // Blacksmithing skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpBrewing, 3 ) // Brewing skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpFletching, 2 ) // Fletching skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpJewelcrafting, 2 ) // Jewelcrafting skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpMakePoison, 2 ) // Make Poison skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpPottery, 4 ) // Pottery skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpResearch, 1 ) // Research skillup rate adjust. Lower is faster. +RULE_INT ( Character, TradeskillUpTinkering, 2 ) // Tinkering skillup rate adjust. Lower is faster. RULE_CATEGORY_END() RULE_CATEGORY( Mercs ) diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index e24dc421c..ffc22352a 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1318,8 +1318,10 @@ bool ZoneServer::Process() { break; } } - - delete pack; + if (pack) + delete pack; + else + Log.Out(Logs::Detail, Logs::World_Server, "Zoneserver process tried to delete pack when pack does not exist."); } return true; } diff --git a/zone/attack.cpp b/zone/attack.cpp index e0a362704..c88a9af19 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -384,7 +384,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) int counter_dodge = 0; if (attacker->GetSpecialAbility(COUNTER_AVOID_DAMAGE)){ - + counter_all = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 0); counter_riposte = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE,1); counter_block = attacker->GetSpecialAbilityParam(COUNTER_AVOID_DAMAGE, 2); @@ -406,7 +406,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float riposte_chance = 0.0f; if (CanRiposte && damage > 0 && CanThisClassRiposte() && InFront) { - riposte_chance = (100.0f + static_cast(aabonuses.RiposteChance + spellbonuses.RiposteChance + + riposte_chance = (100.0f + static_cast(aabonuses.RiposteChance + spellbonuses.RiposteChance + itembonuses.RiposteChance - counter_riposte - counter_all)) / 100.0f; skill = GetSkill(SkillRiposte); if (IsClient()) { @@ -437,7 +437,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float block_chance = 0.0f; if (damage > 0 && CanThisClassBlock() && (InFront || bBlockFromRear)) { - block_chance = (100.0f + static_cast(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + + block_chance = (100.0f + static_cast(aabonuses.IncreaseBlockChance + spellbonuses.IncreaseBlockChance + itembonuses.IncreaseBlockChance - counter_block - counter_all)) / 100.0f; skill = CastToClient()->GetSkill(SkillBlock); if (IsClient()) { @@ -455,18 +455,18 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) } //Try Shield Block OR TwoHandBluntBlockCheck - if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear)) + if(damage > 0 && HasShieldEquiped() && (aabonuses.ShieldBlock || spellbonuses.ShieldBlock || itembonuses.ShieldBlock) && (InFront || bBlockFromRear)) RollTable[1] += static_cast(aabonuses.ShieldBlock + spellbonuses.ShieldBlock + itembonuses.ShieldBlock - counter_block - counter_all); - else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear)) + else if(damage > 0 && HasTwoHandBluntEquiped() && (aabonuses.TwoHandBluntBlock || spellbonuses.TwoHandBluntBlock || itembonuses.TwoHandBluntBlock) && (InFront || bBlockFromRear)) RollTable[1] += static_cast(aabonuses.TwoHandBluntBlock + spellbonuses.TwoHandBluntBlock + itembonuses.TwoHandBluntBlock - counter_block - counter_all); - + ////////////////////////////////////////////////////// // parry ////////////////////////////////////////////////////// float parry_chance = 0.0f; if (damage > 0 && CanThisClassParry() && InFront){ - parry_chance = (100.0f + static_cast(aabonuses.ParryChance + itembonuses.ParryChance + + parry_chance = (100.0f + static_cast(aabonuses.ParryChance + itembonuses.ParryChance + itembonuses.ParryChance - counter_parry - counter_all)) / 100.0f; skill = CastToClient()->GetSkill(SkillParry); if (IsClient()) { @@ -490,7 +490,7 @@ bool Mob::AvoidDamage(Mob* other, int32 &damage, bool CanRiposte) float dodge_chance = 0.0f; if (damage > 0 && CanThisClassDodge() && InFront){ - dodge_chance = (100.0f + static_cast(aabonuses.DodgeChance + spellbonuses.DodgeChance + + dodge_chance = (100.0f + static_cast(aabonuses.DodgeChance + spellbonuses.DodgeChance + itembonuses.DodgeChance - counter_dodge - counter_all)) / 100.0f; skill = CastToClient()->GetSkill(SkillDodge); @@ -946,10 +946,10 @@ int Mob::GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate bool MagicWeapon = false; if(weapon_item->GetItem() && weapon_item->GetItem()->Magic) MagicWeapon = true; - else + else if(spellbonuses.MagicWeapon || itembonuses.MagicWeapon) MagicWeapon = true; - else + 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++) @@ -2427,7 +2427,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b bool wasengaged = IsEngaged(); Mob* owner = other->GetOwner(); - Mob* mypet = this->GetPet(); + Mob* mypet = this->GetPet(); Mob* myowner = this->GetOwner(); Mob* targetmob = this->GetTarget(); @@ -3932,7 +3932,7 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand) { float chance = ProcChance * (static_cast(DefensiveProcs[i].chance)/100.0f); if (zone->random.Roll(chance)) { ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on); - CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, + CheckNumHitsRemaining(NumHit::DefensiveSpellProcs, 0, DefensiveProcs[i].base_spellID); } } @@ -4108,6 +4108,14 @@ void Mob::TrySpellProc(const ItemInst *inst, const ItemData *weapon, Mob *on, ui Log.Out(Logs::Detail, Logs::Combat, "Spell proc %d procing spell %d (%.2f percent chance)", i, SpellProcs[i].spellID, chance); + auto outapp = new EQApplicationPacket(OP_BeginCast,sizeof(BeginCast_Struct)); + BeginCast_Struct* begincast = (BeginCast_Struct*)outapp->pBuffer; + begincast->caster_id = GetID(); + begincast->spell_id = SpellProcs[i].spellID; + begincast->cast_time = 0; + outapp->priority = 3; + entity_list.QueueCloseClients(this, outapp, false, 200, 0, true); + safe_delete(outapp); ExecWeaponProc(nullptr, SpellProcs[i].spellID, on); CheckNumHitsRemaining(NumHit::OffensiveSpellProcs, 0, SpellProcs[i].base_spellID); diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 5a952dc9d..0df02b201 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -54,7 +54,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime) :Mob ( nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ), remove_timer(lifetime), spell_timer(0) diff --git a/zone/client.cpp b/zone/client.cpp index 4c260e934..34b16a142 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -107,8 +107,12 @@ Client::Client(EQStreamInterface* ieqs) 0, 0, // qglobal 0, // maxlevel - 0 // scalerate - + 0, // scalerate + 0, + 0, + 0, + 0, + 0 ), //these must be listed in the order they appear in client.h position_timer(250), @@ -7763,7 +7767,8 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) if (primaryfaction > 0) { if (database.GetFactionData(&fmod, GetClass(), GetRace(), GetDeity(), primaryfaction)) { tmpFactionValue = GetCharacterFactionLevel(primaryfaction); - lowestvalue = std::min(tmpFactionValue, std::min(fmod.class_mod, fmod.race_mod)); + lowestvalue = std::min(std::min(tmpFactionValue, fmod.deity_mod), + std::min(fmod.class_mod, fmod.race_mod)); } } // If no primary faction or biggest influence is your faction hit @@ -7811,6 +7816,11 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction) } } else if (lowestvalue == fmod.class_mod) { merchant->Say_StringID(zone->random.Int(WONT_SELL_CLASS1, WONT_SELL_CLASS5), itoa(GetClass())); + } else { + // Must be deity - these two sound the best for that. + // Can't use a message with a field, GUI wants class/race names. + // for those message IDs. These are straight text. + merchant->Say_StringID(zone->random.Int(WONT_SELL_DEEDS1, WONT_SELL_DEEDS2)); } return; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 697a693ba..a24ab3979 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -337,7 +337,7 @@ void MapOpcodes() // Use or Ignore sense heading based on rule. bool train=RuleB(Skills, TrainSenseHeading); - ConnectedOpcodes[OP_SenseHeading] = + ConnectedOpcodes[OP_SenseHeading] = (train) ? &Client::Handle_OP_SenseHeading : &Client::Handle_OP_Ignore; ConnectedOpcodes[OP_SenseTraps] = &Client::Handle_OP_SenseTraps; @@ -413,10 +413,10 @@ int Client::HandlePacket(const EQApplicationPacket *app) if (Log.log_settings[Logs::Client_Server_Packet].is_category_enabled == 1) Log.Out(Logs::General, Logs::Client_Server_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size()); - + if (Log.log_settings[Logs::Client_Server_Packet_With_Dump].is_category_enabled == 1) Log.Out(Logs::General, Logs::Client_Server_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size(), DumpPacketToString(app).c_str()); - + EmuOpcode opcode = app->GetOpcode(); if (opcode == OP_AckPacket) { return true; @@ -458,7 +458,7 @@ int Client::HandlePacket(const EQApplicationPacket *app) case CLIENT_CONNECTED: { ClientPacketProc p; p = ConnectedOpcodes[opcode]; - if(p == nullptr) { + if(p == nullptr) { std::vector args; args.push_back(const_cast(app)); parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args); @@ -2607,7 +2607,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) ++iter; } - if (item_id == 0 || reclaim->count == 0) { + if (item_id == 0) { return; } @@ -2628,6 +2628,9 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); + if(max_currency == 0 || reclaim->count == 0) + return; + /* If you input more than you have currency wise, just give the max of the currency you currently have */ if (reclaim->count > max_currency) { SummonItem(item_id, max_currency, 0); @@ -2831,8 +2834,7 @@ void Client::Handle_OP_Animation(const EQApplicationPacket *app) Animation_Struct *s = (Animation_Struct *)app->pBuffer; //might verify spawn ID, but it wouldent affect anything - - DoAnim(s->action, s->value); + DoAnim(s->action, s->speed); return; } @@ -3015,7 +3017,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) { DeleteItemInInventory(slot_id, 0, true); DeleteItemInInventory(MainCursor, 0, true); - + if (PutItemInInventory(slot_id, *itemOneToPush, true)) { CalcBonuses(); @@ -5421,12 +5423,12 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app) /* EVENT_ENVIRONMENTAL_DAMAGE */ int final_damage = (damage * RuleR(Character, EnvironmentDamageMulipliter)); char buf[24]; - snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage); + snprintf(buf, 23, "%u %u %i", ed->damage, ed->dmgtype, final_damage); parse->EventPlayer(EVENT_ENVIRONMENTAL_DAMAGE, this, buf, 0); } if (GetHP() <= 0) { - mod_client_death_env(); + mod_client_death_env(); Death(0, 32000, SPELL_UNKNOWN, SkillHandtoHand); } SendHPUpdate(); @@ -9793,7 +9795,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) Message_StringID(10, CANNOT_WAKE, mypet->GetCleanName(), GetTarget()->GetCleanName()); break; } - + if (!mypet->IsAttackAllowed(GetTarget())) { mypet->Say_StringID(NOT_LEGAL_TARGET); break; @@ -9889,7 +9891,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } } break; - } + } case PET_TAUNT_ON: { if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_DO_TAUNT); @@ -11623,7 +11625,7 @@ void Client::Handle_OP_SenseHeading(const EQApplicationPacket *app) // eventually sends a message. if (GetLevel() <= 8) chancemod += (9-level) * 10; - + CheckIncreaseSkill(SkillSenseHeading, nullptr, chancemod); return; @@ -12200,7 +12202,7 @@ void Client::Handle_OP_ShopPlayerSell(const EQApplicationPacket *app) int freeslot = 0; if (charges > 0 && (freeslot = zone->SaveTempItem(vendor->CastToNPC()->MerchantType, vendor->GetNPCTypeID(), itemid, charges, true)) > 0){ ItemInst* inst2 = inst->Clone(); - + while (true) { if (inst2 == nullptr) break; @@ -13285,7 +13287,7 @@ void Client::Handle_OP_Trader(const EQApplicationPacket *app) safe_delete(gis); this->Trader_StartTrader(); - + // This refreshes the Trader window to display the End Trader button if (GetClientVersion() >= ClientVersion::RoF) { @@ -13430,7 +13432,7 @@ void Client::Handle_OP_TraderShop(const EQApplicationPacket *app) if (app->size == sizeof(TraderClick_Struct)) { - + TraderClick_Struct* tcs = (TraderClick_Struct*)app->pBuffer; Log.Out(Logs::Detail, Logs::Trading, "Handle_OP_TraderShop: TraderClick_Struct TraderID %d, Code %d, Unknown008 %d, Approval %d", diff --git a/zone/corpse.cpp b/zone/corpse.cpp index b77d4add9..f82695bac 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -152,7 +152,7 @@ Corpse::Corpse(NPC* in_npc, ItemList* in_itemlist, uint32 in_npctypeid, const NP in_npc->GetDeity(),in_npc->GetLevel(),in_npc->GetNPCTypeID(),in_npc->GetSize(),0, in_npc->GetPosition(), in_npc->GetInnateLightType(), in_npc->GetTexture(),in_npc->GetHelmTexture(), 0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0), + 0,0,0,0,0,0,0,0,0,0,0,0xff,0,0,0,0,0,0,0,0,0,0,0,0,0,0), corpse_decay_timer(in_decaytime), corpse_rez_timer(0), corpse_delay_timer(RuleI(NPC, CorpseUnlockTimer)), @@ -253,7 +253,12 @@ Corpse::Corpse(Client* client, int32 in_rezexp) : Mob ( 0, // int32 in_mana_regen, 0, // uint8 in_qglobal, 0, // uint8 in_maxlevel, - 0 // uint32 in_scalerate + 0, // uint32 in_scalerate + 0, // uint8 in_armtexture, + 0, // uint8 in_bracertexture, + 0, // uint8 in_handtexture, + 0, // uint8 in_legtexture, + 0 // uint8 in_feettexture, ), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), @@ -478,6 +483,11 @@ in_helmtexture, 0, 0, 0, +0, +0, +0, +0, +0, 0), corpse_decay_timer(RuleI(Character, CorpseDecayTimeMS)), corpse_rez_timer(RuleI(Character, CorpseResTimeMS)), diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 512436b6b..51190c9db 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -137,6 +137,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } float roll_t = 0.0f; + float roll_t_min = 0.0f; bool active_item_list = false; for(uint32 i = 0; i < lds->NumEntries; ++i) { const ItemData* db_item = GetItem(lds->Entries[i].item_id); @@ -146,15 +147,44 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } } + roll_t_min = roll_t; roll_t = EQEmu::ClampLower(roll_t, 100.0f); if(!active_item_list) { return; } - mindrop = EQEmu::ClampLower(mindrop, (uint8)1); - int item_count = zone->random.Int(mindrop, droplimit); - for(int i = 0; i < item_count; ++i) { + for(int i = 0; i < mindrop; ++i) { + float roll = (float)zone->random.Real(0.0, roll_t_min); + for(uint32 j = 0; j < lds->NumEntries; ++j) { + const Item_Struct* db_item = GetItem(lds->Entries[j].item_id); + if(db_item) { + if(roll < lds->Entries[j].chance) { + npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, + lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false); + + int charges = (int)lds->Entries[i].multiplier; + charges = EQEmu::ClampLower(charges, 1); + + for(int k = 1; k < charges; ++k) { + float c_roll = (float)zone->random.Real(0.0, 100.0); + if(c_roll <= lds->Entries[i].chance) { + npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel, + lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false); + } + } + + j = lds->NumEntries; + break; + } + else { + roll -= lds->Entries[j].chance; + } + } + } + } + + for(int i = mindrop; i < droplimit; ++i) { float roll = (float)zone->random.Real(0.0, roll_t); for(uint32 j = 0; j < lds->NumEntries; ++j) { const ItemData* db_item = GetItem(lds->Entries[j].item_id); diff --git a/zone/mob.cpp b/zone/mob.cpp index ef77c7912..7567eb5c6 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -83,7 +83,12 @@ Mob::Mob(const char* in_name, int32 in_mana_regen, uint8 in_qglobal, uint8 in_maxlevel, - uint32 in_scalerate + uint32 in_scalerate, + uint8 in_armtexture, + uint8 in_bracertexture, + uint8 in_handtexture, + uint8 in_legtexture, + uint8 in_feettexture ) : attack_timer(2000), attack_dw_timer(2000), @@ -159,6 +164,13 @@ Mob::Mob(const char* in_name, texture = in_texture; helmtexture = in_helmtexture; + armtexture = in_armtexture; + bracertexture = in_bracertexture; + handtexture = in_handtexture; + legtexture = in_legtexture; + feettexture = in_feettexture; + multitexture = (armtexture || bracertexture || handtexture || legtexture || feettexture); + haircolor = in_haircolor; beardcolor = in_beardcolor; eyecolor1 = in_eyecolor1; @@ -931,7 +943,7 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.drakkin_heritage = drakkin_heritage; ns->spawn.drakkin_tattoo = drakkin_tattoo; ns->spawn.drakkin_details = drakkin_details; - ns->spawn.equip_chest2 = GetHerosForgeModel(1) != 0 ? 0xff : texture; + ns->spawn.equip_chest2 = GetHerosForgeModel(1) != 0 || multitexture? 0xff : texture; // ns->spawn.invis2 = 0xff;//this used to be labeled beard.. if its not FF it will turn mob invis @@ -1303,12 +1315,12 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; anim->spawnid = GetID(); if(type == 0){ - anim->action = 10; - anim->value=animnum; + anim->action = animnum; + anim->speed = 10; } else{ anim->action = animnum; - anim->value=type; + anim->speed = type; } entity_list.QueueCloseClients(this, outapp, false, 200, 0, ackreq, filter); safe_delete(outapp); diff --git a/zone/mob.h b/zone/mob.h index 156231d09..85b4797f8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -113,7 +113,12 @@ public: int32 in_mana_regen, uint8 in_qglobal, uint8 in_maxlevel, - uint32 in_scalerate + uint32 in_scalerate, + uint8 in_armtexture, + uint8 in_bracertexture, + uint8 in_handtexture, + uint8 in_legtexture, + uint8 in_feettexture ); virtual ~Mob(); @@ -975,6 +980,12 @@ protected: uint16 entity_id_being_looted; //the id of the entity being looted, 0 if not looting. uint8 texture; uint8 helmtexture; + uint8 armtexture; + uint8 bracertexture; + uint8 handtexture; + uint8 legtexture; + uint8 feettexture; + bool multitexture; int AC; int32 ATK; diff --git a/zone/npc.cpp b/zone/npc.cpp index a4b4b3955..c8dc15f58 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -103,7 +103,12 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if d->mana_regen, d->qglobal, d->maxlevel, - d->scalerate ), + d->scalerate, + d->armtexture, + d->bracertexture, + d->handtexture, + d->legtexture, + d->feettexture), attacked_timer(CombatEventTimer_expire), swarm_timer(100), classattack_timer(1000), @@ -1308,6 +1313,16 @@ int32 NPC::GetEquipmentMaterial(uint8 material_slot) const return helmtexture; case MaterialChest: return texture; + case MaterialArms: + return armtexture; + case MaterialWrist: + return bracertexture; + case MaterialHands: + return handtexture; + case MaterialLegs: + return legtexture; + case MaterialFeet: + return feettexture; case MaterialPrimary: return d_melee_texture1; case MaterialSecondary: diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d399d7665..a885922e9 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6110,6 +6110,84 @@ XS(XS_Client_SendSpellAnim) XSRETURN_EMPTY; } +XS(XS_Client_GetTargetRingX); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTargetRingX) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetTargetRingX(THIS)"); + { + Client * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTargetRingX(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Client_GetTargetRingY); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTargetRingY) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetTargetRingY(THIS)"); + { + Client * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTargetRingY(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + +XS(XS_Client_GetTargetRingZ); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_GetTargetRingZ) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::GetTargetRingZ(THIS)"); + { + Client * THIS; + float RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetTargetRingZ(); + XSprePUSH; PUSHn((double)RETVAL); + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -6351,6 +6429,9 @@ XS(boot_Client) newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$"); newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$"); newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$"); + newXSproto(strcpy(buf, "GetTargetRingX"), XS_Client_GetTargetRingX, file, "$$"); + newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$$"); + newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$"); XSRETURN_YES; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index bfc662730..a652651e7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5253,7 +5253,7 @@ uint16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (IsValidSpell(proc_spellid)){ - ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(spell_id)); + ProcChance = GetSympatheticProcChances(spell_id, GetSympatheticSpellProcRate(proc_spellid)); if(zone->random.Roll(ProcChance)) SympatheticProcList.push_back(proc_spellid); } diff --git a/zone/spells.cpp b/zone/spells.cpp index 65a4bfabd..bfaaaae30 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2672,7 +2672,7 @@ int CalcBuffDuration_formula(int level, int formula, int duration) return i < duration ? (i < 1 ? 1 : i) : duration; case 11: - return duration; + return std::min((level + 3) * 30, duration); case 12: return duration; @@ -5254,7 +5254,7 @@ void Client::SendBuffDurationPacket(Buffs_Struct &buff) sbf->slot = 2; sbf->spellid = buff.spellid; sbf->slotid = 0; - sbf->effect = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); + sbf->effect = 255; sbf->level = buff.casterlevel > 0 ? buff.casterlevel : GetLevel(); sbf->bufffade = 0; sbf->duration = buff.ticsremaining; diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index edd01b4aa..750414fe3 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -848,24 +848,41 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) { // Some tradeskills are more eqal then others. ;-) // If you want to customize the stage1 success rate do it here. // Remember: skillup_modifier is (float). Lower is better - switch(spec->tradeskill) { - case SkillFletching: - case SkillAlchemy: - case SkillJewelryMaking: - case SkillPottery: - skillup_modifier = 4; - break; - case SkillBaking: - case SkillBrewing: - skillup_modifier = 3; - break; - case SkillResearch: - skillup_modifier = 1; - break; - default: - skillup_modifier = 2; - break; - } + switch(spec->tradeskill) { + case SkillFletching: + skillup_modifier = RuleI(Character, TradeskillUpFletching); + break; + case SkillAlchemy: + skillup_modifier = RuleI(Character, TradeskillUpAlchemy); + break; + case SkillJewelryMaking: + skillup_modifier = RuleI(Character, TradeskillUpJewelcrafting); + break; + case SkillPottery: + skillup_modifier = RuleI(Character, TradeskillUpPottery); + break; + case SkillBaking: + skillup_modifier = RuleI(Character, TradeskillUpBaking); + break; + case SkillBrewing: + skillup_modifier = RuleI(Character, TradeskillUpBrewing); + break; + case SkillBlacksmithing: + skillup_modifier = RuleI(Character, TradeskillUpBlacksmithing); + break; + case SkillResearch: + skillup_modifier = RuleI(Character, TradeskillUpResearch); + break; + case SkillMakePoison: + skillup_modifier = RuleI(Character, TradeskillUpMakePoison); + break; + case SkillTinkering: + skillup_modifier = RuleI(Character, TradeskillUpTinkering); + break; + default: + skillup_modifier = 2; + break; + } // Some tradeskills take the higher of one additional stat beside INT and WIS // to determine the skillup rate. Additionally these tradeskills do not have an diff --git a/zone/trading.cpp b/zone/trading.cpp index 16283e7c8..1948a3887 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1626,23 +1626,10 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic return; } - ReturnTraderReq(app, outtbs->Quantity, ItemID); - - outtbs->TraderID = this->GetID(); - outtbs->Action = BazaarBuyItem; - strn0cpy(outtbs->ItemName, BuyItem->GetItem()->Name, 64); - - int TraderSlot = 0; - - if(BuyItem->IsStackable()) - SendTraderItem(BuyItem->GetItem()->ID, outtbs->Quantity); - else - SendTraderItem(BuyItem->GetItem()->ID, BuyItem->GetCharges()); - // This cannot overflow assuming MAX_TRANSACTION_VALUE, checked above, is the default of 2000000000 uint32 TotalCost = tbs->Price * outtbs->Quantity; - if (Trader->GetClientVersion() >= ClientVersion::RoF) + if(Trader->GetClientVersion() >= ClientVersion::RoF) { // RoF+ uses individual item price where older clients use total price outtbs->Price = tbs->Price; @@ -1673,6 +1660,19 @@ void Client::BuyTraderItem(TraderBuy_Struct* tbs, Client* Trader, const EQApplic Log.Out(Logs::Detail, Logs::Trading, "Trader Received: %d Platinum, %d Gold, %d Silver, %d Copper", platinum, gold, silver, copper); + ReturnTraderReq(app, outtbs->Quantity, ItemID); + + outtbs->TraderID = this->GetID(); + outtbs->Action = BazaarBuyItem; + strn0cpy(outtbs->ItemName, BuyItem->GetItem()->Name, 64); + + int TraderSlot = 0; + + if(BuyItem->IsStackable()) + SendTraderItem(BuyItem->GetItem()->ID, outtbs->Quantity); + else + SendTraderItem(BuyItem->GetItem()->ID, BuyItem->GetCharges()); + TraderSlot = Trader->FindTraderItem(tbs->ItemID, outtbs->Quantity); if(RuleB(Bazaar, AuditTrail)) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e3df3f5e3..46bddf25a 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1905,7 +1905,12 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.no_target_hotkey, " "npc_types.raid_target, " "npc_types.attack_delay, " - "npc_types.light " + "npc_types.light, " + "npc_types.armtexture, " + "npc_types.bracertexture, " + "npc_types.handtexture, " + "npc_types.legtexture, " + "npc_types.feettexture " "FROM npc_types %s", where_condition.c_str() ); @@ -2075,6 +2080,12 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->attack_delay = atoi(row[90]); temp_npctype_data->light = (atoi(row[91]) & 0x0F); + temp_npctype_data->armtexture = atoi(row[92]); + temp_npctype_data->bracertexture = atoi(row[93]); + temp_npctype_data->handtexture = atoi(row[94]); + temp_npctype_data->legtexture = atoi(row[95]); + temp_npctype_data->feettexture = atoi(row[96]); + // If NPC with duplicate NPC id already in table, // free item we attempted to add. if (zone->npctable.find(temp_npctype_data->npc_id) != zone->npctable.end()) { diff --git a/zone/zonedump.h b/zone/zonedump.h index dc13300e3..e69692339 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -127,6 +127,11 @@ struct NPCType bool no_target_hotkey; bool raid_target; uint8 probability; + uint8 armtexture; + uint8 bracertexture; + uint8 handtexture; + uint8 legtexture; + uint8 feettexture; }; namespace player_lootitem {