mirror of
https://github.com/EQEmu/Server.git
synced 2026-06-24 17:48:20 +00:00
Added spell links to interrupt and fizzle messages
This commit is contained in:
@@ -734,6 +734,8 @@ set(common_headers
|
|||||||
util/uuid.h
|
util/uuid.h
|
||||||
version.h
|
version.h
|
||||||
zone_store.h
|
zone_store.h
|
||||||
|
links.h
|
||||||
|
links.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources})
|
source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources})
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by dannu on 4/18/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "links.h"
|
||||||
|
|
||||||
|
std::string Links::FormatSpellLink(uint32_t SpellID, const std::string& SpellName)
|
||||||
|
{
|
||||||
|
return fmt::format("{}63^{}^0^'{}{}", ITEM_TAG_CHAR, SpellID, SpellName.c_str(), ITEM_TAG_CHAR);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Created by dannu on 4/18/2026.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Links
|
||||||
|
{
|
||||||
|
constexpr char ITEM_TAG_CHAR = '\x12';
|
||||||
|
std::string FormatSpellLink(uint32_t SpellID, const std::string& SpellName);
|
||||||
|
}
|
||||||
@@ -364,7 +364,6 @@ namespace TOB
|
|||||||
//OUT(inventoryslot);
|
//OUT(inventoryslot);
|
||||||
OUT(target_id);
|
OUT(target_id);
|
||||||
|
|
||||||
LogNetcode("S->C OP_CastSpell {}", DumpPacketToString(__packet));
|
|
||||||
FINISH_ENCODE();
|
FINISH_ENCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3652,7 +3651,6 @@ namespace TOB
|
|||||||
IN(y_pos);
|
IN(y_pos);
|
||||||
IN(x_pos);
|
IN(x_pos);
|
||||||
IN(z_pos);
|
IN(z_pos);
|
||||||
LogNetcode("C->S OP_CastSpell {}", DumpPacketToString(__packet));
|
|
||||||
FINISH_DIRECT_DECODE();
|
FINISH_DIRECT_DECODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4864,7 +4862,9 @@ namespace TOB
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
//unsupported etag right now; just pass it as is
|
//unsupported etag right now; just pass it as is
|
||||||
|
message_out.push_back('\x12');
|
||||||
message_out.append(segments[segment_iter]);
|
message_out.append(segments[segment_iter]);
|
||||||
|
message_out.push_back('\x12');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-8
@@ -94,6 +94,9 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "common/links.h"
|
||||||
|
#include "common/packet_dump.h"
|
||||||
|
|
||||||
extern Zone *zone;
|
extern Zone *zone;
|
||||||
extern volatile bool is_zone_loaded;
|
extern volatile bool is_zone_loaded;
|
||||||
extern WorldServer worldserver;
|
extern WorldServer worldserver;
|
||||||
@@ -319,6 +322,10 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
// note that CheckFizzle itself doesn't let NPCs fizzle,
|
// note that CheckFizzle itself doesn't let NPCs fizzle,
|
||||||
// but this code allows for it.
|
// but this code allows for it.
|
||||||
if (slot < CastingSlot::MaxGems && !CheckFizzle(spell_id)) {
|
if (slot < CastingSlot::MaxGems && !CheckFizzle(spell_id)) {
|
||||||
|
/*
|
||||||
|
MessageFormat: You miss a note, bringing your song to a close! (TOB: You miss a note, bringing your %1 to a close!)
|
||||||
|
MessageFormat: Your spell fizzles! (TOB: Your %1 spell fizzles!)
|
||||||
|
*/
|
||||||
int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE;
|
int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE;
|
||||||
|
|
||||||
uint32 use_mana = ((spells[spell_id].mana) / 4);
|
uint32 use_mana = ((spells[spell_id].mana) / 4);
|
||||||
@@ -328,10 +335,16 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
Mob::SetMana(GetMana() - use_mana); // We send StopCasting which will update mana
|
Mob::SetMana(GetMana() - use_mana); // We send StopCasting which will update mana
|
||||||
StopCasting();
|
StopCasting();
|
||||||
|
|
||||||
MessageString(Chat::SpellFailure, fizzle_msg);
|
// TODO: can handle spell name overrides here
|
||||||
|
std::string spell_name(GetSpellName(spell_id));
|
||||||
|
std::string spell_link = Links::FormatSpellLink(spell_id, spell_name);
|
||||||
|
|
||||||
|
// pre-TOB clients will just discard the extra argument here, so don't worry about patching them out in patches
|
||||||
|
MessageString(Chat::SpellFailure, fizzle_msg, spell_link.c_str());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Song Failure message
|
* Song Failure message
|
||||||
|
* pre-TOB clients will just discard the extra argument here, so don't worry about patching them out in patches
|
||||||
*/
|
*/
|
||||||
entity_list.FilteredMessageCloseString(
|
entity_list.FilteredMessageCloseString(
|
||||||
this,
|
this,
|
||||||
@@ -342,11 +355,11 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
|||||||
(fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER),
|
(fizzle_msg == MISS_NOTE ? MISSED_NOTE_OTHER : SPELL_FIZZLE_OTHER),
|
||||||
0,
|
0,
|
||||||
/*
|
/*
|
||||||
MessageFormat: You miss a note, bringing your song to a close! (if missed note)
|
MessageFormat: A missed note brings %1's song to a close! (TOB: A missed note brings %1's %2 to a close!)
|
||||||
MessageFormat: A missed note brings %1's song to a close!
|
MessageFormat: %1's spell fizzles! (TOB: %1's %2 spell fizzles!)
|
||||||
MessageFormat: %1's spell fizzles!
|
|
||||||
*/
|
*/
|
||||||
GetName()
|
GetName(),
|
||||||
|
spell_link.c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
TryTriggerOnCastRequirement();
|
TryTriggerOnCastRequirement();
|
||||||
@@ -1299,14 +1312,20 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
|
|||||||
if(!message)
|
if(!message)
|
||||||
message = IsBardSong(spellid) ? SONG_ENDS_ABRUPTLY : INTERRUPT_SPELL;
|
message = IsBardSong(spellid) ? SONG_ENDS_ABRUPTLY : INTERRUPT_SPELL;
|
||||||
|
|
||||||
|
// TODO: can handle spell name overrides here
|
||||||
|
std::string spellname(GetSpellName(spellid));
|
||||||
|
std::string spelllink = Links::FormatSpellLink(spellid, spellname);
|
||||||
|
|
||||||
// clients need some packets
|
// clients need some packets
|
||||||
if (IsClient() && message != SONG_ENDS)
|
if (IsClient() && message != SONG_ENDS)
|
||||||
{
|
{
|
||||||
// the interrupt message
|
// the interrupt message
|
||||||
outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct));
|
outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + spelllink.size() + 1);
|
||||||
InterruptCast_Struct* ic = (InterruptCast_Struct*) outapp->pBuffer;
|
InterruptCast_Struct* ic = (InterruptCast_Struct*) outapp->pBuffer;
|
||||||
ic->messageid = message;
|
ic->messageid = message;
|
||||||
ic->spawnid = GetID();
|
ic->spawnid = GetID();
|
||||||
|
// pre-TOB clients will just discard the extra argument here, so don't worry about patching them out in patches
|
||||||
|
fmt::format_to_n(ic->message, spelllink.size(), "{}", spelllink);
|
||||||
outapp->priority = 5;
|
outapp->priority = 5;
|
||||||
CastToClient()->QueuePacket(outapp);
|
CastToClient()->QueuePacket(outapp);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
@@ -1336,11 +1355,12 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this is the actual message, it works the same as a formatted message
|
// this is the actual message, it works the same as a formatted message
|
||||||
outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(GetCleanName()) + 1);
|
outapp = new EQApplicationPacket(OP_InterruptCast, sizeof(InterruptCast_Struct) + strlen(GetCleanName()) + spelllink.size() + 2);
|
||||||
InterruptCast_Struct* ic = (InterruptCast_Struct*) outapp->pBuffer;
|
InterruptCast_Struct* ic = (InterruptCast_Struct*) outapp->pBuffer;
|
||||||
ic->messageid = message_other;
|
ic->messageid = message_other;
|
||||||
ic->spawnid = GetID();
|
ic->spawnid = GetID();
|
||||||
strcpy(ic->message, GetCleanName());
|
// pre-TOB clients will just discard the extra argument here, so don't worry about patching them out in patches
|
||||||
|
fmt::format_to_n(ic->message, sizeof(GetCleanName()) + spelllink.size() + 1, "{}\x00{}", GetCleanName(), spelllink);
|
||||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, SongMessages), 0, true, IsClient() ? FilterPCSpells : FilterNPCSpells);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user