From 13743caf19591c846e2f443a633e896992d87ef5 Mon Sep 17 00:00:00 2001 From: Shane Lynch Date: Tue, 10 Mar 2015 21:33:44 -0700 Subject: [PATCH 01/20] Enable multiple NPC equipment materials This change allows #npcedit armtexture/bracertexture/handtexture/legtexture/feettexture to work properly and sets individual armor slot materials for NPCs. --- zone/beacon.cpp | 2 +- zone/client.cpp | 8 ++++++-- zone/corpse.cpp | 14 ++++++++++++-- zone/mob.cpp | 16 ++++++++++++++-- zone/npc.cpp | 17 ++++++++++++++++- zone/zonedb.cpp | 13 ++++++++++++- zone/zonedump.h | 5 +++++ 7 files changed, 66 insertions(+), 9 deletions(-) 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 8246e12a8..c5ca6e233 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), diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 551f49a1b..fad65aa3a 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/mob.cpp b/zone/mob.cpp index b4d28c6c0..ca2493b9b 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), @@ -158,6 +163,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; @@ -930,7 +942,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 diff --git a/zone/npc.cpp b/zone/npc.cpp index 22fb5f188..4e69657cd 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/zonedb.cpp b/zone/zonedb.cpp index 685fbd3ca..1fab4aff2 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1904,7 +1904,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() ); @@ -2074,6 +2079,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 { From 2003efb5ab37d71b8a6c678e2937ed8aeb0632b2 Mon Sep 17 00:00:00 2001 From: Shane Lynch Date: Tue, 10 Mar 2015 21:59:31 -0700 Subject: [PATCH 02/20] Enable multiple NPC equipment materials (part2) Adding missing header from previous commit. --- zone/mob.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/zone/mob.h b/zone/mob.h index 6d7b386cf..270ed7461 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -112,7 +112,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(); @@ -971,6 +976,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; From e6835804affef7cb619cde408e52e8c35d0ed85f Mon Sep 17 00:00:00 2001 From: N0ctrnl Date: Wed, 25 Mar 2015 12:00:14 -0500 Subject: [PATCH 03/20] Update ruletypes.h --- common/ruletypes.h | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 ) From c4a7acb6d1768d5c25af3504b5a8d6acfaf5e500 Mon Sep 17 00:00:00 2001 From: N0ctrnl Date: Wed, 25 Mar 2015 12:04:03 -0500 Subject: [PATCH 04/20] Update tradeskills.cpp --- zone/tradeskills.cpp | 53 +++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 07ae6d2a5..15cf45e20 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 From 4dcb679c539b4fce53e48dbd061ffdf860ef8d87 Mon Sep 17 00:00:00 2001 From: JJ Date: Fri, 27 Mar 2015 16:40:02 -0400 Subject: [PATCH 05/20] Manual merge of #387. --- zone/spells.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 08030b8b5..a4bef767c 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; From 94d118fdf803c8233dc33f05129aa07ac5307c68 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 27 Mar 2015 17:12:39 -0400 Subject: [PATCH 06/20] Some vendors would decide not to see based on deity, but messages were picking the next best reason. Added a message choice that seemed to make sense for deity. --- zone/client.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 8246e12a8..3d0a8d75a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -7763,7 +7763,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 +7812,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; } From b6cc0706338419f0319c5e9f8aaff7cd5696c1d3 Mon Sep 17 00:00:00 2001 From: SecretsOTheP Date: Sun, 29 Mar 2015 01:35:24 -0400 Subject: [PATCH 07/20] Identified the Target Ring fields for RoF/RoF2 and added a perl accessor for the last target ring position received from the client. Usage: $client->GetTargetRingX(), $client->GetTargetRingY(), $client->GetTargetRingZ() --- changelog.txt | 4 ++ common/patches/rof.cpp | 4 ++ common/patches/rof2.cpp | 3 ++ common/patches/rof2_structs.h | 5 ++- common/patches/rof_structs.h | 5 ++- zone/perl_client.cpp | 81 +++++++++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+), 2 deletions(-) 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/patches/rof.cpp b/common/patches/rof.cpp index 0495935b1..81865d12b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -4236,6 +4236,10 @@ namespace RoF //IN(inventoryslot); IN(target_id); + IN(y_pos); + IN(x_pos); + IN(z_pos); + FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 9e0bd9c8a..f51ee685c 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4380,6 +4380,9 @@ namespace RoF2 emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); //IN(inventoryslot); IN(target_id); + IN(y_pos); + IN(x_pos); + IN(z_pos); FINISH_DIRECT_DECODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 79da918b9..033e0ed9a 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*/ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index a623c7cf4..456c7b1a9 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*/ }; 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; } From a75f4e70a1791c436e5a0fa648dc924a7d8aa158 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Sun, 29 Mar 2015 02:11:02 -0400 Subject: [PATCH 08/20] sympathetic proc fix --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 21ba36e0a..b159fbabc 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); } From b6a01871d84f09f6a7a14e68eafe565fc1a31f9a Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 28 Mar 2015 23:38:41 -0700 Subject: [PATCH 09/20] Fix for another bazaar problem --- zone/trading.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index b6c869b61..df8d159b1 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)) From e304e67cf1a7f24bbaf0f62ad52a0dd8e1b19f51 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sun, 29 Mar 2015 01:00:06 -0700 Subject: [PATCH 10/20] Fix how Alternate Currency Reclaim and Create works if the player has 0 currency available --- zone/client_packet.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 21ab1c7cf..52afd6460 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2604,7 +2604,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) ++iter; } - if (item_id == 0 || reclaim->count == 0) { + if (item_id == 0) { return; } @@ -2624,6 +2624,9 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) /* Cursor to Item storage */ else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); + + if(max_currency == 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) { From 8bd22e8c385baeebe18a61adab5b37aa8002643e Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sun, 29 Mar 2015 02:16:16 -0700 Subject: [PATCH 11/20] 2nd part to Alternate currency fix forgot to paste this back in --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 52afd6460..07e9876ca 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2625,7 +2625,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); - if(max_currency == 0) + 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 */ From b3efd8a8173c6d22323b2331663108f0266f94bd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 2 Apr 2015 13:42:47 -0400 Subject: [PATCH 12/20] Quick fix for RoF2 discs showing in song window This is just a hack until someone does a proper solution --- common/patches/rof2.cpp | 43 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index f51ee685c..90affbf9a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -158,7 +158,7 @@ namespace RoF2 eq->exit_url_length = emu->exit_url_length; eq->exit_url_length2 = emu->exit_url_length2; - + FINISH_ENCODE(); } @@ -183,7 +183,7 @@ namespace RoF2 { eq->entries[i] = 1; } - + FINISH_ENCODE(); } @@ -513,6 +513,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); @@ -545,7 +550,7 @@ namespace RoF2 eq->slot = 13; else OUT(slot); - + OUT(spell_id); eq->inventoryslot = ServerToRoF2Slot(emu->inventoryslot); //OUT(inventoryslot); @@ -569,7 +574,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; @@ -768,7 +773,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) @@ -1315,7 +1320,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 } @@ -2388,9 +2393,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); @@ -2486,7 +2491,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 @@ -2541,12 +2546,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); @@ -3112,7 +3117,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; } } @@ -3918,7 +3923,7 @@ namespace RoF2 } ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } - + ENCODE(OP_ZonePlayerToBind) { SETUP_VAR_ENCODE(ZonePlayerToBind_Struct); @@ -4109,8 +4114,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; } // } } @@ -4193,7 +4198,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)) @@ -4375,7 +4380,7 @@ namespace RoF2 emu->slot = 10; else IN(slot); - + IN(spell_id); emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); //IN(inventoryslot); @@ -5101,7 +5106,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(); @@ -5790,7 +5795,7 @@ namespace RoF2 RoF2Slot.SlotType = maps::MapPossessions; RoF2Slot.MainSlot = serverSlot; } - + if (serverSlot == MainPowerSource) RoF2Slot.MainSlot = slots::MainPowerSource; From 51a314fa314faa960b0b2f2ae8b665dd49a81bfd Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 2 Apr 2015 14:54:11 -0400 Subject: [PATCH 13/20] for whatever reason spell based procs generate casting messages --- zone/attack.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 950663a38..e573b12cc 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 Item_Struct *weapon, Mob *on, 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); From 7e1c296ecfaa1e70794cacc72d74a34c9220a0ef Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 4 Apr 2015 05:04:12 -0700 Subject: [PATCH 14/20] Fix for RoF2 Bow shoot animation struct was off --- common/patches/rof2_structs.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 033e0ed9a..b33d568d0 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -4189,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*/ }; From fc1d6c0676b6a6962d9f0fcbc108e97347ce1a5f Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 4 Apr 2015 17:03:28 -0700 Subject: [PATCH 15/20] Fix for mindrop on drop tables sometimes not being fully respected --- zone/loottables.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 0d392ec68..5d4b6f92b 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 Item_Struct* db_item = GetItem(lds->Entries[i].item_id); @@ -146,15 +147,45 @@ 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); + 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; + } + } + } + } + int item_count = zone->random.Int(mindrop, droplimit); - for(int i = 0; i < item_count; ++i) { + for(int i = mindrop; i < item_count; ++i) { float roll = (float)zone->random.Real(0.0, roll_t); for(uint32 j = 0; j < lds->NumEntries; ++j) { const Item_Struct* db_item = GetItem(lds->Entries[j].item_id); From 7662eaf9837fb907158ce7836892b40b50d45a08 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 6 Apr 2015 03:01:48 -0700 Subject: [PATCH 16/20] All animation structs were backwards and poorly named.. RoF+ animations work properly --- common/eq_packet_structs.h | 4 ++-- common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/rof2_structs.h | 4 ++-- common/patches/rof_structs.h | 4 ++-- common/patches/sod_structs.h | 4 ++-- common/patches/sof_structs.h | 4 ++-- common/patches/titanium_structs.h | 4 ++-- common/patches/uf_structs.h | 4 ++-- zone/client_packet.cpp | 9 ++++++--- zone/mob.cpp | 6 +++--- 11 files changed, 25 insertions(+), 22 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 57dfe5482..1481fce8c 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1279,8 +1279,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 81865d12b..1c9cf3fd6 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(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 90affbf9a..681bef783 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -293,8 +293,8 @@ namespace RoF2 SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); OUT(spawnid); - OUT(value); OUT(action); + OUT(speed); FINISH_ENCODE(); } diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index b33d568d0..21681df5e 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -1418,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*/ }; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 456c7b1a9..622305833 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -1448,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 ef4dd32cb..55730423b 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 51dbef1f5..fff207893 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 1c3afd90b..5ad997d5b 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 d7b14b385..a82bfc4e3 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/zone/client_packet.cpp b/zone/client_packet.cpp index 07e9876ca..e7a4684d8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2831,9 +2831,12 @@ 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); - + if (GetClientVersion() >= ClientVersion::RoF) { + DoAnim(s->speed, s->action); //This was backwards so we gotta make up for it here + } else { + DoAnim(s->action, s->speed); + } + return; } diff --git a/zone/mob.cpp b/zone/mob.cpp index d196e3ce8..d47be1957 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1314,12 +1314,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); From 7bd185b7b7302d99ddadbe9005814f97b6b6a662 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 6 Apr 2015 16:13:58 -0400 Subject: [PATCH 17/20] Fix RoF+ OP_Animation handling That's handled in the patch file --- zone/client_packet.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e7a4684d8..201b0d13e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -336,7 +336,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; @@ -412,10 +412,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; @@ -457,7 +457,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); @@ -2624,7 +2624,7 @@ void Client::Handle_OP_AltCurrencyReclaim(const EQApplicationPacket *app) /* Cursor to Item storage */ else { uint32 max_currency = GetAlternateCurrencyValue(reclaim->currency_id); - + if(max_currency == 0 || reclaim->count == 0) return; @@ -2831,12 +2831,8 @@ void Client::Handle_OP_Animation(const EQApplicationPacket *app) Animation_Struct *s = (Animation_Struct *)app->pBuffer; //might verify spawn ID, but it wouldent affect anything - if (GetClientVersion() >= ClientVersion::RoF) { - DoAnim(s->speed, s->action); //This was backwards so we gotta make up for it here - } else { - DoAnim(s->action, s->speed); - } - + DoAnim(s->action, s->speed); + return; } @@ -3018,7 +3014,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(); @@ -5424,12 +5420,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(); @@ -9846,7 +9842,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; @@ -9942,7 +9938,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); @@ -11676,7 +11672,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; @@ -12317,7 +12313,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; @@ -13405,7 +13401,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) { @@ -13550,7 +13546,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", From 979590db9ff2185c080d7e4e7d0a9d70249b7f71 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 6 Apr 2015 17:42:15 -0700 Subject: [PATCH 18/20] Fix for lower than intended drop rates for drop limit loot tables after the min drop changes --- zone/loottables.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 5d4b6f92b..3170729d0 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -184,8 +184,7 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml } } - int item_count = zone->random.Int(mindrop, droplimit); - for(int i = mindrop; i < item_count; ++i) { + 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 Item_Struct* db_item = GetItem(lds->Entries[j].item_id); From 739a7b6f7542bc330ea5b1054684df03644e43b7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 6 Apr 2015 21:46:37 -0400 Subject: [PATCH 19/20] Add decoder for OP_Animation for RoF/RoF2 --- common/patches/rof.cpp | 34 +++++++++++++++++++++++----------- common/patches/rof2.cpp | 12 ++++++++++++ common/patches/rof2_ops.h | 1 + common/patches/rof_ops.h | 1 + 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 1c9cf3fd6..7bb64735b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -479,7 +479,7 @@ namespace RoF eq->slot = 13; else OUT(slot); - + OUT(spell_id); eq->inventoryslot = ServerToRoFSlot(emu->inventoryslot); //OUT(inventoryslot); @@ -702,7 +702,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) @@ -1249,7 +1249,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 } @@ -2989,7 +2989,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); } @@ -3046,7 +3046,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; } } @@ -3313,7 +3313,7 @@ namespace RoF delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); - + #if 0 // original code EQApplicationPacket *in = *p; *p = nullptr; @@ -3777,7 +3777,7 @@ namespace RoF } ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } - + ENCODE(OP_ZonePlayerToBind) { SETUP_VAR_ENCODE(ZonePlayerToBind_Struct); @@ -3968,8 +3968,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; } // } } @@ -4118,6 +4118,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); @@ -4230,7 +4242,7 @@ namespace RoF emu->slot = 10; else IN(slot); - + IN(spell_id); emu->inventoryslot = RoFToServerSlot(eq->inventoryslot); //IN(inventoryslot); @@ -5105,7 +5117,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 681bef783..06c524053 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4269,6 +4269,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); 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/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) From 0321bf72a511c87ac7d343ad6490f4451768c616 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 7 Apr 2015 10:22:47 -0400 Subject: [PATCH 20/20] Attempt to catch rare crash in zoneserver process. See http://www.eqemulator.org/forums/showthread.php?t=39549 --- world/zoneserver.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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; }