diff --git a/changelog.txt b/changelog.txt index 2d82f375e..ed32c03cd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -7,6 +7,10 @@ Uleat: Added Server<->Corpse slot translators needed for re-enumeration (inactiv Uleat: Fixed Ti(6.2) OP_AugmentInfo translation that I broke (does not currently need and I mis-read a process) Uleat: Moved client patch OP_LootItem slot translation to external handlers +== 10/02/2014 == +Kayen: Exported to PERL $client->SendSpellAnim(targetid, spellid) +This function sends the spell graphic of a spell without actually having to cast the spell. + == 10/02/2014 == Uleat: First round of Ti/6.2 translators added - needed for re-enumeration diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 6291d3077..34ef61f6e 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -345,14 +345,10 @@ namespace Underfoot __packet->pBuffer = new unsigned char[sz]; memset(__packet->pBuffer, 0, sz); - uchar *ptr = __packet->pBuffer; - *((uint32*)ptr) = emu->entity_id; - ptr += sizeof(uint32); - ptr += sizeof(uint32); - *((uint8*)ptr) = emu->all_buffs; - ptr += sizeof(uchar); - *((uint16*)ptr) = emu->count; - ptr += sizeof(uint16); + __packet->WriteUInt32(emu->entity_id); + __packet->WriteUInt32(0); + __packet->WriteUInt8(emu->all_buffs); // 1 = all buffs, 0 = 1 buff + __packet->WriteUInt16(emu->count); for (uint16 i = 0; i < emu->count; ++i) { @@ -366,17 +362,13 @@ namespace Underfoot buffslot += 14; } - *((uint32*)ptr) = buffslot; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].spell_id; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].tics_remaining; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].num_hits; - ptr += sizeof(uint32); - *((uint8*)ptr) = !emu->all_buffs; - ptr += 1; + __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->entries[i].spell_id); + __packet->WriteUInt32(emu->entries[i].tics_remaining); + __packet->WriteUInt32(emu->entries[i].num_hits); + __packet->WriteString(""); } + __packet->WriteUInt8(!emu->all_buffs); FINISH_ENCODE(); /* diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index 5bffdfc93..2e039b404 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -615,6 +615,8 @@ OP_RAWOutOfSession=0x0000 # OP_Some3ByteHPUpdate=0x0000 #initial HP update for mobs OP_InitialHPUpdate=0x0000 # +OP_ItemRecastDelay=0x0ada + # Opcodes from the client that are currently Unknowns: # 0x3E85 - Sent when Guild Management window is opened diff --git a/zone/attack.cpp b/zone/attack.cpp index feb10369f..a7a50a6cd 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3315,7 +3315,10 @@ int32 Mob::AffectMagicalDamage(int32 damage, uint16 spell_id, const bool iBuffTi if(damage < 1) return 0; - + + //Regular runes absorb spell damage (except dots) - Confirmed on live. + if (spellbonuses.MeleeRune[0] && spellbonuses.MeleeRune[1] >= 0) + damage = RuneAbsorb(damage, SE_Rune); if (spellbonuses.AbsorbMagicAtt[0] && spellbonuses.AbsorbMagicAtt[1] >= 0) damage = RuneAbsorb(damage, SE_AbsorbMagicAtt); diff --git a/zone/client.h b/zone/client.h index fe05194bc..03748849d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1156,6 +1156,7 @@ public: const char* GetClassPlural(Client* client); void SendWebLink(const char* website); void SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg); + void SendSpellAnim(uint16 targetid, uint16 spell_id); void DuplicateLoreMessage(uint32 ItemID); void GarbleMessage(char *, uint8); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2ef62c3d3..7edd9202b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3111,6 +3111,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) DeleteItemInInventory(MainCursor, 0, true); if (PutItemInInventory(slot_id, *itemOneToPush, true)) { + CalcBonuses(); //Message(13, "Sucessfully added an augment to your item!"); return; } @@ -3185,6 +3186,7 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (PutItemInInventory(MainCursor, *itemTwoToPush, true)) { + CalcBonuses(); //Message(15, "Successfully removed an augmentation!"); } } diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 04becfdc8..a33e9a8b9 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6046,6 +6046,32 @@ XS(XS_Client_SendColoredText) XSRETURN_EMPTY; } +XS(XS_Client_SendSpellAnim); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_SendSpellAnim) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: SendSpellAnim(uint16 spell_id, uint32 seq)"); + { + Client * THIS; + uint16 targetid = (uint16)SvUV(ST(1)); + uint16 spell_id = (uint16)SvUV(ST(2)); + 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 == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->SendSpellAnim(targetid,spell_id); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" #endif @@ -6286,6 +6312,8 @@ XS(boot_Client) newXSproto(strcpy(buf, "ExpeditionMessage"), XS_Client_ExpeditionMessage, file, "$$$"); newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$"); newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$"); + newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$"); + XSRETURN_YES; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index f86f43bf4..b634ca4a3 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3396,6 +3396,9 @@ void Mob::BuffProcess() if(buffs[buffs_i].UpdateClient == true) { CastToClient()->SendBuffDurationPacket(buffs[buffs_i]); + // Hack to get UF to play nicer, RoF seems fine without it + if (CastToClient()->GetClientVersion() == EQClientUnderfoot && buffs[buffs_i].numhits > 0) + CastToClient()->SendBuffNumHitPacket(buffs[buffs_i], buffs_i); buffs[buffs_i].UpdateClient = false; } } diff --git a/zone/spells.cpp b/zone/spells.cpp index 310bc35bd..c6fb43b24 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -484,19 +484,6 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, uint16 slot, return false; } - // This needs a bit more work for saving timer to PP for zoning etc - if (IsClient() && item_slot != INVALID_INDEX && ((slot == USE_ITEM_SPELL_SLOT) || (slot == POTION_BELT_SPELL_SLOT))) { - ItemInst *itm = CastToClient()->GetInv().GetItem(item_slot); - if (itm && itm->GetItem()->RecastDelay) { - outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct)); - ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer; - ird->recast_delay = itm->GetItem()->RecastDelay; - ird->recast_type = itm->GetItem()->RecastType; - CastToClient()->QueuePacket(outapp); - safe_delete(outapp); - } - } - return(true); } @@ -2228,6 +2215,12 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16 ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot); if(itm && itm->GetItem()->RecastDelay > 0){ CastToClient()->GetPTimers().Start((pTimerItemStart + itm->GetItem()->RecastType), itm->GetItem()->RecastDelay); + EQApplicationPacket *outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct)); + ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer; + ird->recast_delay = itm->GetItem()->RecastDelay; + ird->recast_type = itm->GetItem()->RecastType; + CastToClient()->QueuePacket(outapp); + safe_delete(outapp); } } @@ -5351,3 +5344,19 @@ void NPC::UninitializeBuffSlots() safe_delete_array(buffs); } +void Client::SendSpellAnim(uint16 targetid, uint16 spell_id) +{ + if (!targetid || !IsValidSpell(spell_id)) + return; + + EQApplicationPacket app(OP_Action, sizeof(Action_Struct)); + Action_Struct* a = (Action_Struct*)app.pBuffer; + a->target = targetid; + a->source = this->GetID(); + a->type = 231; + a->spell = spell_id; + a->sequence = 231; + + app.priority = 1; + entity_list.QueueCloseClients(this, &app); +}