mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
Merge remote-tracking branch 'upstream/master' into spa395fix2
This commit is contained in:
+6
-5
@@ -2701,8 +2701,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
}
|
||||
|
||||
if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0))
|
||||
TryTriggerOnValueAmount(false, false, false, true);
|
||||
if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) {
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
|
||||
if (IsClient() && !IsAIControlled())
|
||||
return;
|
||||
@@ -3343,7 +3344,7 @@ int32 Mob::ReduceAllDamage(int32 damage)
|
||||
if (GetMana() >= mana_reduced) {
|
||||
damage -= mana_reduced;
|
||||
SetMana(GetMana() - mana_reduced);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3356,7 +3357,7 @@ int32 Mob::ReduceAllDamage(int32 damage)
|
||||
if (IsClient() && CastToClient()->GetEndurance() >= endurance_drain) {
|
||||
damage -= damage_reduced;
|
||||
CastToClient()->SetEndurance(CastToClient()->GetEndurance() - endurance_drain);
|
||||
TryTriggerOnValueAmount(false, false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3646,7 +3647,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
|
||||
TryDeathSave();
|
||||
}
|
||||
|
||||
TryTriggerOnValueAmount(true);
|
||||
TryTriggerOnCastRequirement();
|
||||
|
||||
//fade mez if we are mezzed
|
||||
if (IsMezzed() && attacker) {
|
||||
|
||||
+18
-4
@@ -1256,8 +1256,11 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
|
||||
}
|
||||
|
||||
case SE_MitigateDamageShield: {
|
||||
if (base1 < 0)
|
||||
|
||||
//AA that increase mitigation are set to negative.
|
||||
if (base1 < 0) {
|
||||
base1 = base1 * (-1);
|
||||
}
|
||||
|
||||
newbon->DSMitigationOffHand += base1;
|
||||
break;
|
||||
@@ -2663,8 +2666,15 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_MitigateDamageShield:
|
||||
{
|
||||
if (effect_value < 0)
|
||||
effect_value = effect_value*-1;
|
||||
/*
|
||||
Bard songs have identical negative base value and positive max
|
||||
The effect for the songs should increase mitigation. There are
|
||||
spells that do decrease the mitigation with just negative base values.
|
||||
To be consistent all values that increase mitigation will be set to positives
|
||||
*/
|
||||
if (max > 0 && effect_value < 0) {
|
||||
effect_value = max;
|
||||
}
|
||||
|
||||
new_bonus->DSMitigationOffHand += effect_value;
|
||||
break;
|
||||
@@ -3198,7 +3208,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_TriggerOnReqTarget:
|
||||
case SE_TriggerOnReqCaster:
|
||||
new_bonus->TriggerOnValueAmount = true;
|
||||
new_bonus->TriggerOnCastRequirement = true;
|
||||
break;
|
||||
|
||||
case SE_DivineAura:
|
||||
@@ -3661,6 +3671,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
new_bonus->ZoneSuspendMinion = effect_value;
|
||||
break;
|
||||
|
||||
case SE_CompleteHeal:
|
||||
new_bonus->CompleteHealBuffBlocker = true;
|
||||
break;
|
||||
|
||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||
if (IsAISpellEffect) {
|
||||
|
||||
|
||||
+10
-6
@@ -9191,7 +9191,7 @@ void Client::SetDisplayMobInfoWindow(bool display_mob_info_window)
|
||||
|
||||
bool Client::IsDevToolsEnabled() const
|
||||
{
|
||||
return dev_tools_enabled && RuleB(World, EnableDevTools);
|
||||
return dev_tools_enabled && GetGM() && RuleB(World, EnableDevTools);
|
||||
}
|
||||
|
||||
void Client::SetDevToolsEnabled(bool in_dev_tools_enabled)
|
||||
@@ -9481,12 +9481,16 @@ void Client::SendCrossZoneMessage(
|
||||
}
|
||||
else if (!character_name.empty() && !message.empty())
|
||||
{
|
||||
uint32_t pack_size = sizeof(CZMessagePlayer_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_CZMessagePlayer, pack_size);
|
||||
auto buf = reinterpret_cast<CZMessagePlayer_Struct*>(pack->pBuffer);
|
||||
uint32_t pack_size = sizeof(CZMessage_Struct);
|
||||
auto pack = std::make_unique<ServerPacket>(ServerOP_CZMessage, pack_size);
|
||||
auto buf = reinterpret_cast<CZMessage_Struct*>(pack->pBuffer);
|
||||
uint8 update_type = CZUpdateType_Character;
|
||||
int update_identifier = 0;
|
||||
buf->update_type = update_type;
|
||||
buf->update_identifier = update_identifier;
|
||||
buf->type = chat_type;
|
||||
strn0cpy(buf->character_name, character_name.c_str(), sizeof(buf->character_name));
|
||||
strn0cpy(buf->message, message.c_str(), sizeof(buf->message));
|
||||
strn0cpy(buf->client_name, character_name.c_str(), sizeof(buf->client_name));
|
||||
|
||||
worldserver.SendPacket(pack.get());
|
||||
}
|
||||
@@ -9519,7 +9523,7 @@ void Client::SendCrossZoneMessageString(
|
||||
auto buf = reinterpret_cast<CZClientMessageString_Struct*>(pack->pBuffer);
|
||||
buf->string_id = string_id;
|
||||
buf->chat_type = chat_type;
|
||||
strn0cpy(buf->character_name, character_name.c_str(), sizeof(buf->character_name));
|
||||
strn0cpy(buf->client_name, character_name.c_str(), sizeof(buf->client_name));
|
||||
buf->args_size = args_size;
|
||||
memcpy(buf->args, argument_buffer.buffer(), argument_buffer.size());
|
||||
|
||||
|
||||
+4
-2
@@ -203,8 +203,10 @@ enum eInnateSkill {
|
||||
InnateDisabled = 255
|
||||
};
|
||||
|
||||
const std::string DIAWIND_RESPONSE_KEY = "diawind_npcresponse";
|
||||
const uint32 POPUPID_DIAWIND = 999;
|
||||
const std::string DIAWIND_RESPONSE_ONE_KEY = "diawind_npc_response_one";
|
||||
const std::string DIAWIND_RESPONSE_TWO_KEY = "diawind_npc_response_two";
|
||||
const uint32 POPUPID_DIAWIND_ONE = 99999;
|
||||
const uint32 POPUPID_DIAWIND_TWO = 100000;
|
||||
const uint32 POPUPID_UPDATE_SHOWSTATSWINDOW = 1000000;
|
||||
|
||||
struct ClientReward
|
||||
|
||||
+16
-5
@@ -11155,9 +11155,18 @@ void Client::Handle_OP_PopupResponse(const EQApplicationPacket *app)
|
||||
return;
|
||||
break;
|
||||
|
||||
case POPUPID_DIAWIND:
|
||||
if (EntityVariableExists(DIAWIND_RESPONSE_KEY.c_str())) {
|
||||
response = GetEntityVariable(DIAWIND_RESPONSE_KEY.c_str());
|
||||
case POPUPID_DIAWIND_ONE:
|
||||
if (EntityVariableExists(DIAWIND_RESPONSE_ONE_KEY.c_str())) {
|
||||
response = GetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str());
|
||||
if (!response.empty()) {
|
||||
ChannelMessageReceived(8, 0, 100, response.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case POPUPID_DIAWIND_TWO:
|
||||
if (EntityVariableExists(DIAWIND_RESPONSE_TWO_KEY.c_str())) {
|
||||
response = GetEntityVariable(DIAWIND_RESPONSE_TWO_KEY.c_str());
|
||||
if (!response.empty()) {
|
||||
ChannelMessageReceived(8, 0, 100, response.c_str());
|
||||
}
|
||||
@@ -12189,7 +12198,8 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
|
||||
tr.name,
|
||||
tr.trivial,
|
||||
SUM(tre.componentcount),
|
||||
tr.tradeskill
|
||||
tr.tradeskill,
|
||||
tr.must_learn
|
||||
FROM
|
||||
tradeskill_recipe AS tr
|
||||
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
|
||||
@@ -12289,7 +12299,8 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app)
|
||||
tr.name,
|
||||
tr.trivial,
|
||||
SUM(tre.componentcount),
|
||||
tr.tradeskill
|
||||
tr.tradeskill,
|
||||
tr.must_learn
|
||||
FROM
|
||||
tradeskill_recipe AS tr
|
||||
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
|
||||
|
||||
@@ -183,6 +183,8 @@ bool Client::Process() {
|
||||
|
||||
SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline);
|
||||
|
||||
parse->EventPlayer(EVENT_DISCONNECT, this, "", 0);
|
||||
|
||||
return false; //delete client
|
||||
}
|
||||
|
||||
@@ -1864,7 +1866,7 @@ void Client::DoEnduranceUpkeep() {
|
||||
|
||||
if(upkeep_sum != 0){
|
||||
SetEndurance(GetEndurance() - upkeep_sum);
|
||||
TryTriggerOnValueAmount(false, false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
|
||||
if (!has_effect)
|
||||
|
||||
+796
-639
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -554,6 +554,7 @@ struct StatBonuses {
|
||||
int32 ItemEnduranceRegenCap; // modify endurance regen cap
|
||||
int32 WeaponStance[WEAPON_STANCE_TYPE_MAX +1];// base = trigger spell id, base2 = 0 is 2h, 1 is shield, 2 is dual wield, [0]spid 2h, [1]spid shield, [2]spid DW
|
||||
bool ZoneSuspendMinion; // base 1 allows suspended minions to zone
|
||||
bool CompleteHealBuffBlocker; // Use in SPA 101 to prevent recast of complete heal from this effect till blocker buff is removed.
|
||||
|
||||
// AAs
|
||||
uint16 SecondaryForte; // allow a second skill to be specialized with a cap of this value.
|
||||
@@ -602,7 +603,7 @@ struct StatBonuses {
|
||||
int32 FinishingBlow[2]; // Chance to do a finishing blow for specified damage amount.
|
||||
uint32 FinishingBlowLvl[2]; // Sets max level an NPC can be affected by FB. (base1 = lv, base2= ???)
|
||||
int32 ShieldEquipDmgMod; // Increases weapon's base damage by base1 % when shield is equipped (indirectly increasing hate)
|
||||
bool TriggerOnValueAmount; // Triggers off various different conditions, bool to check if client has effect.
|
||||
bool TriggerOnCastRequirement; // Triggers off various different conditions defined as emum SpellRestrictions
|
||||
int8 StunBashChance; // chance to stun with bash.
|
||||
int8 IncreaseChanceMemwipe; // increases chance to memory wipe
|
||||
int8 CriticalMend; // chance critical monk mend
|
||||
|
||||
+125
-11
@@ -11,7 +11,8 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
}
|
||||
|
||||
// zero this out
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_KEY.c_str(), "");
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str(), "");
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_TWO_KEY.c_str(), "");
|
||||
|
||||
// simple find and replace for the markdown
|
||||
find_replace(output, "~", "</c>");
|
||||
@@ -32,10 +33,10 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
|
||||
// mysterious voice
|
||||
bool render_mysterious_voice = false;
|
||||
if (markdown.find("mysterious") != std::string::npos) {
|
||||
if (markdown.find("{mysterious}") != std::string::npos) {
|
||||
render_mysterious_voice = true;
|
||||
LogDiaWind("Client [{}] Rendering mysterious voice", c->GetCleanName());
|
||||
find_replace(output, "mysterious", "");
|
||||
find_replace(output, "{mysterious}", "");
|
||||
}
|
||||
|
||||
// noquotes
|
||||
@@ -98,10 +99,10 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
}
|
||||
}
|
||||
|
||||
uint32 popup_id = POPUPID_DIAWIND;
|
||||
uint32 negative_id = 0;
|
||||
char *button_name_0 = nullptr;
|
||||
char *button_name_1 = nullptr;
|
||||
uint32 popup_id = POPUPID_DIAWIND_ONE;
|
||||
uint32 negative_id = POPUPID_DIAWIND_TWO;
|
||||
std::string button_one_name;
|
||||
std::string button_two_name;
|
||||
uint32 sound_controls = 0;
|
||||
|
||||
// window type
|
||||
@@ -171,6 +172,96 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
}
|
||||
}
|
||||
|
||||
// secondresponseid
|
||||
std::string secondresponseid;
|
||||
if (markdown.find("secondresponseid") != std::string::npos) {
|
||||
LogDiaWind("Client [{}] Rendering secondresponseid option", c->GetCleanName());
|
||||
|
||||
auto first_split = split_string(output, "secondresponseid:");
|
||||
if (!first_split.empty()) {
|
||||
auto second_split = split_string(first_split[1], " ");
|
||||
if (!second_split.empty()) {
|
||||
secondresponseid = second_split[0];
|
||||
LogDiaWindDetail("Client [{}] Rendering secondresponseid option secondresponseid [{}]", c->GetCleanName(), secondresponseid);
|
||||
}
|
||||
|
||||
if (first_split[1].length() == 1) {
|
||||
secondresponseid = first_split[1];
|
||||
LogDiaWindDetail(
|
||||
"Client [{}] Rendering secondresponseid (end) option secondresponseid [{}]",
|
||||
c->GetCleanName(),
|
||||
secondresponseid
|
||||
);
|
||||
}
|
||||
|
||||
find_replace(output, fmt::format("secondresponseid:{}", secondresponseid), "");
|
||||
|
||||
if (!secondresponseid.empty()) {
|
||||
negative_id = (StringIsNumber(secondresponseid) ? std::atoi(secondresponseid.c_str()) : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Buttons Text
|
||||
std::string button_one;
|
||||
std::string button_two;
|
||||
if (
|
||||
markdown.find("button_one") != std::string::npos &&
|
||||
markdown.find("button_two") != std::string::npos
|
||||
) {
|
||||
LogDiaWind("Client [{}] Rendering button_one option.", c->GetCleanName());
|
||||
|
||||
auto one_first_split = split_string(output, "button_one:");
|
||||
if (!one_first_split.empty()) {
|
||||
auto one_second_split = split_string(one_first_split[1], " ");
|
||||
if (!one_second_split.empty()) {
|
||||
button_one = one_second_split[0];
|
||||
LogDiaWindDetail("Client [{}] Rendering button_one option button_one [{}]", c->GetCleanName(), button_one);
|
||||
}
|
||||
|
||||
if (one_first_split[1].length() == 1) {
|
||||
button_one = one_first_split[1];
|
||||
LogDiaWindDetail(
|
||||
"Client [{}] Rendering button_one (end) option button_one [{}]",
|
||||
c->GetCleanName(),
|
||||
button_one
|
||||
);
|
||||
}
|
||||
|
||||
find_replace(output, fmt::format("button_one:{}", button_one), "");
|
||||
|
||||
if (!button_one.empty()) {
|
||||
button_one_name = button_one.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
LogDiaWind("Client [{}] Rendering button_two option.", c->GetCleanName());
|
||||
|
||||
auto two_first_split = split_string(output, "button_two:");
|
||||
if (!two_first_split.empty()) {
|
||||
auto two_second_split = split_string(two_first_split[1], " ");
|
||||
if (!two_second_split.empty()) {
|
||||
button_two = two_second_split[0];
|
||||
LogDiaWindDetail("Client [{}] Rendering button_two option button_two [{}]", c->GetCleanName(), button_two);
|
||||
}
|
||||
|
||||
if (two_first_split[1].length() == 1) {
|
||||
button_two = two_first_split[1];
|
||||
LogDiaWindDetail(
|
||||
"Client [{}] Rendering button_two (end) option button_two [{}]",
|
||||
c->GetCleanName(),
|
||||
button_two
|
||||
);
|
||||
}
|
||||
|
||||
find_replace(output, fmt::format("button_two:{}", button_two), "");
|
||||
|
||||
if (!button_two.empty()) {
|
||||
button_two_name = button_two.c_str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// bracket responses
|
||||
std::vector<std::string> responses;
|
||||
std::vector<std::string> bracket_responses;
|
||||
@@ -209,13 +300,25 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
}
|
||||
}
|
||||
|
||||
// Placed here to allow silent message or other message to override default for custom values.
|
||||
if (!button_one_name.empty() && !button_two_name.empty()) {
|
||||
c->SetEntityVariable(
|
||||
DIAWIND_RESPONSE_ONE_KEY.c_str(),
|
||||
button_one_name.c_str()
|
||||
);
|
||||
c->SetEntityVariable(
|
||||
DIAWIND_RESPONSE_TWO_KEY.c_str(),
|
||||
button_two_name.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
// handle silent prompts from the [> silent syntax
|
||||
std::string silent_message;
|
||||
if (responses.empty() && markdown.find('[') != std::string::npos && markdown.find('>') != std::string::npos) {
|
||||
silent_message = get_between(output, "[", ">");
|
||||
|
||||
// temporary and used during the response
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_KEY.c_str(), silent_message.c_str());
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str(), silent_message.c_str());
|
||||
|
||||
// pop the silent message off
|
||||
find_replace(output, fmt::format("[{}>", silent_message), "");
|
||||
@@ -225,7 +328,7 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
silent_message = responses[0];
|
||||
|
||||
// temporary and used during the response
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_KEY.c_str(), silent_message.c_str());
|
||||
c->SetEntityVariable(DIAWIND_RESPONSE_ONE_KEY.c_str(), silent_message.c_str());
|
||||
|
||||
// pop the silent message off
|
||||
find_replace(output, fmt::format("[{}]", silent_message), "");
|
||||
@@ -282,6 +385,17 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
);
|
||||
}
|
||||
|
||||
if (!button_one_name.empty() && !button_two_name.empty()) {
|
||||
click_response = fmt::format(
|
||||
"<c \"#F07F00\">Click [{}] to respond with [{}]...<br>"
|
||||
"Click [{}] to respond with [{}]...</c>",
|
||||
button_one_name,
|
||||
button_one_name,
|
||||
button_two_name,
|
||||
button_two_name
|
||||
);
|
||||
}
|
||||
|
||||
// post processing of color markdowns
|
||||
// {spring_green_1} = <c "#5EFB6E">
|
||||
if (markdown.find('{') != std::string::npos && markdown.find('}') != std::string::npos) {
|
||||
@@ -325,8 +439,8 @@ void DialogueWindow::Render(Client *c, std::string markdown)
|
||||
negative_id,
|
||||
window_type,
|
||||
window_expire_seconds,
|
||||
button_name_0,
|
||||
button_name_1,
|
||||
button_one_name.c_str(),
|
||||
button_two_name.c_str(),
|
||||
sound_controls
|
||||
);
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
|
||||
"EVENT_BOT_COMMAND",
|
||||
"EVENT_WARP",
|
||||
"EVENT_TEST_BUFF",
|
||||
"EVENT_COMBINE",
|
||||
"EVENT_CONSIDER",
|
||||
"EVENT_CONSIDER_CORPSE"
|
||||
};
|
||||
@@ -1657,6 +1658,11 @@ void PerlembParser::ExportEventVariables(
|
||||
break;
|
||||
}
|
||||
|
||||
case EVENT_COMBINE: {
|
||||
ExportVar(package_name.c_str(), "container_slot", std::stoi(data));
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
|
||||
+2357
-1579
File diff suppressed because it is too large
Load Diff
@@ -90,6 +90,7 @@ typedef enum {
|
||||
EVENT_BOT_COMMAND,
|
||||
EVENT_WARP,
|
||||
EVENT_TEST_BUFF,
|
||||
EVENT_COMBINE,
|
||||
EVENT_CONSIDER,
|
||||
EVENT_CONSIDER_CORPSE,
|
||||
_LargestEventID
|
||||
|
||||
@@ -129,7 +129,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
std::vector<std::string> move_h_options_negative;
|
||||
std::vector<std::string> set_size_options_positive;
|
||||
std::vector<std::string> set_size_options_negative;
|
||||
for (const auto &move_option : move_options) {
|
||||
for (const auto &move_option : move_options) {
|
||||
if (move_option == move_x_action) {
|
||||
move_x_options_positive.emplace_back(
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
@@ -165,7 +165,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} -.25", move_option),
|
||||
false,
|
||||
"-.25"
|
||||
".25"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -190,7 +190,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
for (int move_index = -15; move_index <= 0; move_index += 5) {
|
||||
int value = (move_index == 0 ? 1 : move_index);
|
||||
int value = (move_index == 0 ? -1 : move_index);
|
||||
move_y_options_negative.emplace_back(
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} {}", move_option, value),
|
||||
@@ -204,7 +204,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} -.25", move_option),
|
||||
false,
|
||||
"-.25"
|
||||
".25"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -229,7 +229,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
for (int move_index = -15; move_index <= 0; move_index += 5) {
|
||||
int value = (move_index == 0 ? 1 : move_index);
|
||||
int value = (move_index == 0 ? -1 : move_index);
|
||||
move_z_options_negative.emplace_back(
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} {}", move_option, value),
|
||||
@@ -243,7 +243,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} -.25", move_option),
|
||||
false,
|
||||
"-.25"
|
||||
".25"
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -260,7 +260,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
for (int move_index = -50; move_index <= 0; move_index += 5) {
|
||||
int value = (move_index == 0 ? 1 : move_index);
|
||||
int value = (move_index == 0 ? -1 : move_index);
|
||||
move_h_options_negative.emplace_back(
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} {}", move_option, value),
|
||||
@@ -283,7 +283,7 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
for (int move_index = -100; move_index <= 0; move_index += 10) {
|
||||
int value = (move_index == 0 ? 1 : move_index);
|
||||
int value = (move_index == 0 ? -1 : move_index);
|
||||
set_size_options_negative.emplace_back(
|
||||
EQ::SayLinkEngine::GenerateQuestSaylink(
|
||||
fmt::format("#door edit {} {}", move_option, value),
|
||||
@@ -297,26 +297,30 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
|
||||
|
||||
// we're passing a move action here
|
||||
if (!arg3.empty() && StringIsNumber(arg3)) {
|
||||
int x_move = 0;
|
||||
int y_move = 0;
|
||||
int z_move = 0;
|
||||
int h_move = 0;
|
||||
int set_size = 0;
|
||||
float x_move = 0.0f;
|
||||
float y_move = 0.0f;
|
||||
float z_move = 0.0f;
|
||||
float h_move = 0.0f;
|
||||
float set_size = 0.0f;
|
||||
|
||||
if (arg2 == move_x_action) {
|
||||
x_move = std::atoi(arg3.c_str());
|
||||
x_move = std::atof(arg3.c_str());
|
||||
}
|
||||
|
||||
if (arg2 == move_y_action) {
|
||||
y_move = std::atoi(arg3.c_str());
|
||||
y_move = std::atof(arg3.c_str());
|
||||
}
|
||||
|
||||
if (arg2 == move_z_action) {
|
||||
z_move = std::atoi(arg3.c_str());
|
||||
z_move = std::atof(arg3.c_str());
|
||||
}
|
||||
|
||||
if (arg2 == move_h_action) {
|
||||
h_move = std::atoi(arg3.c_str());
|
||||
h_move = std::atof(arg3.c_str());
|
||||
}
|
||||
|
||||
if (arg2 == set_size_action) {
|
||||
set_size = std::atoi(arg3.c_str());
|
||||
set_size = std::atof(arg3.c_str());
|
||||
}
|
||||
|
||||
door->SetLocation(
|
||||
|
||||
+1383
-700
File diff suppressed because it is too large
Load Diff
@@ -133,6 +133,7 @@ const char *LuaEvents[_LargestEventID] = {
|
||||
"event_bot_command",
|
||||
"event_warp",
|
||||
"event_test_buff",
|
||||
"event_combine",
|
||||
"event_consider",
|
||||
"event_consider_corpse"
|
||||
};
|
||||
@@ -222,6 +223,7 @@ LuaParser::LuaParser() {
|
||||
PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate;
|
||||
PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command;
|
||||
PlayerArgumentDispatch[EVENT_WARP] = handle_player_warp;
|
||||
PlayerArgumentDispatch[EVENT_COMBINE] = handle_player_quest_combine;
|
||||
PlayerArgumentDispatch[EVENT_CONSIDER] = handle_player_consider;
|
||||
PlayerArgumentDispatch[EVENT_CONSIDER_CORPSE] = handle_player_consider_corpse;
|
||||
|
||||
|
||||
@@ -573,6 +573,11 @@ void handle_player_warp(QuestInterface* parse, lua_State* L, Client* client, std
|
||||
lua_setfield(L, -2, "from_z");
|
||||
}
|
||||
|
||||
void handle_player_quest_combine(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector<EQ::Any>* extra_pointers) {
|
||||
lua_pushinteger(L, std::stoi(data));
|
||||
lua_setfield(L, -2, "container_slot");
|
||||
}
|
||||
|
||||
void handle_player_consider(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector<EQ::Any>* extra_pointers) {
|
||||
lua_pushinteger(L, std::stoi(data));
|
||||
lua_setfield(L, -2, "entity_id");
|
||||
|
||||
@@ -105,6 +105,8 @@ void handle_player_bot_command(QuestInterface *parse, lua_State* L, Client* clie
|
||||
std::vector<EQ::Any> *extra_pointers);
|
||||
void handle_player_warp(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQ::Any>* extra_pointers);
|
||||
void handle_player_quest_combine(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQ::Any>* extra_pointers);
|
||||
void handle_player_consider(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
std::vector<EQ::Any>* extra_pointers);
|
||||
void handle_player_consider_corpse(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
|
||||
|
||||
@@ -987,7 +987,7 @@ int32 Lua_StatBonuses::GetShieldEquipDmgMod() const {
|
||||
|
||||
bool Lua_StatBonuses::GetTriggerOnValueAmount() const {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->TriggerOnValueAmount;
|
||||
return self->TriggerOnCastRequirement;
|
||||
}
|
||||
|
||||
int8 Lua_StatBonuses::GetStunBashChance() const {
|
||||
|
||||
+18
-73
@@ -2838,10 +2838,17 @@ bool Mob::HateSummon() {
|
||||
if(summon_level == 1) {
|
||||
entity_list.MessageClose(this, true, 500, Chat::Say, "%s says 'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() );
|
||||
|
||||
auto new_pos = m_Position;
|
||||
float angle = new_pos.w - target->GetHeading();
|
||||
new_pos.w = target->GetHeading();
|
||||
|
||||
// probably should be like half melee range, but we can't get melee range nicely because reasons :)
|
||||
new_pos = target->TryMoveAlong(new_pos, 5.0f, angle);
|
||||
|
||||
if (target->IsClient())
|
||||
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Position.x, m_Position.y, m_Position.z, target->GetHeading(), 0, SummonPC);
|
||||
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), new_pos.x, new_pos.y, new_pos.z, new_pos.w, 0, SummonPC);
|
||||
else
|
||||
target->GMMove(m_Position.x, m_Position.y, m_Position.z, target->GetHeading());
|
||||
target->GMMove(new_pos.x, new_pos.y, new_pos.z, new_pos.w);
|
||||
|
||||
return true;
|
||||
} else if(summon_level == 2) {
|
||||
@@ -3602,81 +3609,20 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsPet)
|
||||
void Mob::TryTriggerOnCastRequirement()
|
||||
{
|
||||
/*
|
||||
At present time there is no obvious difference between ReqTarget and ReqCaster
|
||||
ReqTarget is typically used in spells cast on a target where the trigger occurs on that target.
|
||||
ReqCaster is typically self only spells where the triggers on self.
|
||||
Regardless both trigger on the owner of the buff.
|
||||
*/
|
||||
|
||||
/*
|
||||
Base2 Range: 1004 = Below < 80% HP
|
||||
Base2 Range: 500-520 = Below (base2 - 500)*5 HP
|
||||
Base2 Range: 521 = Below (?) Mana UKNOWN - Will assume its 20% unless proven otherwise
|
||||
Base2 Range: 522 = Below (40%) Endurance
|
||||
Base2 Range: 523 = Below (40%) Mana
|
||||
Base2 Range: 220-? = Number of pets on hatelist to trigger (base2 - 220) (Set at 30 pets max for now)
|
||||
38311 = < 10% mana;
|
||||
*/
|
||||
|
||||
if (!spellbonuses.TriggerOnValueAmount)
|
||||
return;
|
||||
|
||||
if (spellbonuses.TriggerOnValueAmount){
|
||||
|
||||
if (spellbonuses.TriggerOnCastRequirement) {
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
|
||||
for(int e = 0; e < buff_count; e++){
|
||||
|
||||
uint32 spell_id = buffs[e].spellid;
|
||||
|
||||
if (IsValidSpell(spell_id)){
|
||||
|
||||
for(int i = 0; i < EFFECT_COUNT; i++){
|
||||
|
||||
for (int e = 0; e < buff_count; e++) {
|
||||
int spell_id = buffs[e].spellid;
|
||||
if (IsValidSpell(spell_id)) {
|
||||
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||
if ((spells[spell_id].effectid[i] == SE_TriggerOnReqTarget) || (spells[spell_id].effectid[i] == SE_TriggerOnReqCaster)) {
|
||||
|
||||
int base2 = spells[spell_id].base2[i];
|
||||
bool use_spell = false;
|
||||
|
||||
if (IsHP){
|
||||
if ((base2 >= 500 && base2 <= 520) && GetHPRatio() < (base2 - 500)*5)
|
||||
use_spell = true;
|
||||
|
||||
else if (base2 == 1004 && GetHPRatio() < 80)
|
||||
use_spell = true;
|
||||
}
|
||||
|
||||
else if (IsMana){
|
||||
if ( (base2 = 521 && GetManaRatio() < 20) || (base2 = 523 && GetManaRatio() < 40))
|
||||
use_spell = true;
|
||||
|
||||
else if (base2 == 38311 && GetManaRatio() < 10)
|
||||
use_spell = true;
|
||||
}
|
||||
|
||||
else if (IsEndur){
|
||||
if (base2 == 522 && GetEndurancePercent() < 40){
|
||||
use_spell = true;
|
||||
}
|
||||
}
|
||||
|
||||
else if (IsPet){
|
||||
int count = hate_list.GetSummonedPetCountOnHateList(this);
|
||||
if ((base2 >= 220 && base2 <= 250) && count >= (base2 - 220)){
|
||||
use_spell = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_spell){
|
||||
if (PassCastRestriction(spells[spell_id].base2[i])) {
|
||||
SpellFinished(spells[spell_id].base[i], this, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
|
||||
if(!TryFadeEffect(e))
|
||||
if (!TryFadeEffect(e)) {
|
||||
BuffFadeBySlot(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3685,7 +3631,6 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Twincast Focus effects should stack across different types (Spell, AA - when implemented ect)
|
||||
void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
|
||||
{
|
||||
|
||||
+5
-1
@@ -623,6 +623,7 @@ public:
|
||||
void Teleport(const glm::vec3 &pos);
|
||||
void Teleport(const glm::vec4 &pos);
|
||||
void TryMoveAlong(float distance, float angle, bool send = true);
|
||||
glm::vec4 TryMoveAlong(const glm::vec4 &start, float distance, float angle);
|
||||
void ProcessForcedMovement();
|
||||
inline void IncDeltaX(float in) { m_Delta.x += in; }
|
||||
inline void IncDeltaY(float in) { m_Delta.y += in; }
|
||||
@@ -796,7 +797,7 @@ public:
|
||||
void TryTriggerOnCastFocusEffect(focusType type, uint16 spell_id);
|
||||
bool TryTriggerOnCastProc(uint16 focusspellid, uint16 spell_id, uint16 proc_spellid);
|
||||
bool TrySpellTrigger(Mob *target, uint32 spell_id, int effect);
|
||||
void TryTriggerOnValueAmount(bool IsHP = false, bool IsMana = false, bool IsEndur = false, bool IsPet = false);
|
||||
void TryTriggerOnCastRequirement();
|
||||
void TryTwincast(Mob *caster, Mob *target, uint32 spell_id);
|
||||
void TrySympatheticProc(Mob *target, uint32 spell_id);
|
||||
bool TryFadeEffect(int slot);
|
||||
@@ -844,6 +845,8 @@ public:
|
||||
bool CanFocusUseRandomEffectivenessByType(focusType type);
|
||||
int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0);
|
||||
int GetHealRate() const { return itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate; }
|
||||
int GetMemoryBlurChance(int base_chance);
|
||||
|
||||
|
||||
bool TryDoubleMeleeRoundEffect();
|
||||
bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; }
|
||||
@@ -1532,6 +1535,7 @@ protected:
|
||||
bool endur_upkeep;
|
||||
bool degenerating_effects; // true if we have a buff that needs to be recalced every tick
|
||||
bool spawned_in_water;
|
||||
|
||||
public:
|
||||
bool GetWasSpawnedInWater() const;
|
||||
|
||||
|
||||
@@ -4016,7 +4016,7 @@ XS(XS_Client_Freeze);
|
||||
XS(XS_Client_Freeze) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Client:Freeze(THIS)");
|
||||
Perl_croak(aTHX_ "Usage: Client::Freeze(THIS)");
|
||||
{
|
||||
Client *THIS;
|
||||
VALIDATE_THIS_IS_CLIENT;
|
||||
@@ -4029,7 +4029,7 @@ XS(XS_Client_UnFreeze);
|
||||
XS(XS_Client_UnFreeze) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Client:UnFreeze(THIS)");
|
||||
Perl_croak(aTHX_ "Usage: Client::UnFreeze(THIS)");
|
||||
{
|
||||
Client *THIS;
|
||||
VALIDATE_THIS_IS_CLIENT;
|
||||
|
||||
+1
-1
@@ -304,7 +304,7 @@ XS(XS_Raid_GetClientByIndex); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Raid_GetClientByIndex) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Raid::GetClientByIndex(THIS, uint16 raid_indez)"); // @categories Raid
|
||||
Perl_croak(aTHX_ "Usage: Raid::GetClientByIndex(THIS, uint16 raid_index)"); // @categories Raid
|
||||
{
|
||||
Raid *THIS;
|
||||
Client *RETVAL;
|
||||
|
||||
+203
-886
File diff suppressed because it is too large
Load Diff
+16
-81
@@ -290,87 +290,22 @@ public:
|
||||
static std::string GetZoneLongName(std::string zone_short_name);
|
||||
static std::string GetZoneLongNameByID(uint32 zone_id);
|
||||
static std::string GetZoneShortName(uint32 zone_id);
|
||||
void CrossZoneAssignTaskByCharID(int character_id, uint32 task_id, bool enforce_level_requirement = false);
|
||||
void CrossZoneAssignTaskByGroupID(int group_id, uint32 task_id, bool enforce_level_requirement = false);
|
||||
void CrossZoneAssignTaskByRaidID(int raid_id, uint32 task_id, bool enforce_level_requirement = false);
|
||||
void CrossZoneAssignTaskByGuildID(int guild_id, uint32 task_id, bool enforce_level_requirement = false);
|
||||
void CrossZoneCastSpellByCharID(int character_id, uint32 spell_id);
|
||||
void CrossZoneCastSpellByGroupID(int group_id, uint32 spell_id);
|
||||
void CrossZoneCastSpellByRaidID(int raid_id, uint32 spell_id);
|
||||
void CrossZoneCastSpellByGuildID(int guild_id, uint32 spell_id);
|
||||
void CrossZoneDisableTaskByCharID(int character_id, uint32 task_id);
|
||||
void CrossZoneDisableTaskByGroupID(int group_id, uint32 task_id);
|
||||
void CrossZoneDisableTaskByRaidID(int raid_id, uint32 task_id);
|
||||
void CrossZoneDisableTaskByGuildID(int guild_id, uint32 task_id);
|
||||
void CrossZoneEnableTaskByCharID(int character_id, uint32 task_id);
|
||||
void CrossZoneEnableTaskByGroupID(int group_id, uint32 task_id);
|
||||
void CrossZoneEnableTaskByRaidID(int raid_id, uint32 task_id);
|
||||
void CrossZoneEnableTaskByGuildID(int guild_id, uint32 task_id);
|
||||
void CrossZoneFailTaskByCharID(int character_id, uint32 task_id);
|
||||
void CrossZoneFailTaskByGroupID(int group_id, uint32 task_id);
|
||||
void CrossZoneFailTaskByRaidID(int raid_id, uint32 task_id);
|
||||
void CrossZoneFailTaskByGuildID(int guild_id, uint32 task_id);
|
||||
void CrossZoneLDoNUpdate(uint8 type, uint8 subtype, int identifier, uint32 theme_id, int points = 1);
|
||||
void CrossZoneMarqueeByCharID(int character_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message);
|
||||
void CrossZoneMarqueeByGroupID(int group_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message);
|
||||
void CrossZoneMarqueeByRaidID(int raid_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message);
|
||||
void CrossZoneMarqueeByGuildID(int guild_id, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message);
|
||||
void CrossZoneMessagePlayerByName(uint32 type, const char *character_name, const char *message);
|
||||
void CrossZoneMessagePlayerByGroupID(uint32 type, int group_id, const char *message);
|
||||
void CrossZoneMessagePlayerByRaidID(uint32 type, int raid_id, const char *message);
|
||||
void CrossZoneMessagePlayerByGuildID(uint32 type, int guild_id, const char *message);
|
||||
void CrossZoneMovePlayerByCharID(int character_id, const char *zone_short_name);
|
||||
void CrossZoneMovePlayerByGroupID(int group_id, const char *zone_short_name);
|
||||
void CrossZoneMovePlayerByRaidID(int raid_id, const char *zone_short_name);
|
||||
void CrossZoneMovePlayerByGuildID(int guild_id, const char *zone_short_name);
|
||||
void CrossZoneMoveInstanceByCharID(int character_id, uint16 instance_id);
|
||||
void CrossZoneMoveInstanceByGroupID(int group_id, uint16 instance_id);
|
||||
void CrossZoneMoveInstanceByRaidID(int raid_id, uint16 instance_id);
|
||||
void CrossZoneMoveInstanceByGuildID(int guild_id, uint16 instance_id);
|
||||
void CrossZoneRemoveSpellByCharID(int character_id, uint32 spell_id);
|
||||
void CrossZoneRemoveSpellByGroupID(int group_id, uint32 spell_id);
|
||||
void CrossZoneRemoveSpellByRaidID(int raid_id, uint32 spell_id);
|
||||
void CrossZoneRemoveSpellByGuildID(int guild_id, uint32 spell_id);
|
||||
void CrossZoneRemoveTaskByCharID(int character_id, uint32 task_id);
|
||||
void CrossZoneRemoveTaskByGroupID(int group_id, uint32 task_id);
|
||||
void CrossZoneRemoveTaskByRaidID(int raid_id, uint32 task_id);
|
||||
void CrossZoneRemoveTaskByGuildID(int guild_id, uint32 task_id);
|
||||
void CrossZoneResetActivityByCharID(int character_id, uint32 task_id, int activity_id);
|
||||
void CrossZoneResetActivityByGroupID(int group_id, uint32 task_id, int activity_id);
|
||||
void CrossZoneResetActivityByRaidID(int raid_id, uint32 task_id, int activity_id);
|
||||
void CrossZoneResetActivityByGuildID(int guild_id, uint32 task_id, int activity_id);
|
||||
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *variable_name, const char *variable_value);
|
||||
void CrossZoneSetEntityVariableByClientName(const char *character_name, const char *variable_name, const char *variable_value);
|
||||
void CrossZoneSetEntityVariableByGroupID(int group_id, const char *variable_name, const char *variable_value);
|
||||
void CrossZoneSetEntityVariableByRaidID(int raid_id, const char *variable_name, const char *variable_value);
|
||||
void CrossZoneSetEntityVariableByGuildID(int guild_id, const char *variable_name, const char *variable_value);
|
||||
void CrossZoneSignalPlayerByCharID(int charid, uint32 signal);
|
||||
void CrossZoneSignalPlayerByGroupID(int group_id, uint32 signal);
|
||||
void CrossZoneSignalPlayerByRaidID(int raid_id, uint32 signal);
|
||||
void CrossZoneSignalPlayerByGuildID(int guild_id, uint32 signal);
|
||||
void CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 signal);
|
||||
void CrossZoneSignalPlayerByName(const char *character_name, uint32 signal);
|
||||
void CrossZoneUpdateActivityByCharID(int character_id, uint32 task_id, int activity_id, int activity_count = 1);
|
||||
void CrossZoneUpdateActivityByGroupID(int group_id, uint32 task_id, int activity_id, int activity_count = 1);
|
||||
void CrossZoneUpdateActivityByRaidID(int raid_id, uint32 task_id, int activity_id, int activity_count = 1);
|
||||
void CrossZoneUpdateActivityByGuildID(int guild_id, uint32 task_id, int activity_id, int activity_count = 1);
|
||||
void WorldWideAssignTask(uint32 task_id, bool enforce_level_requirement = false, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideCastSpell(uint32 spell_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideDisableTask(uint32 task_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideEnableTask(uint32 task_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideFailTask(uint32 task_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char *message, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMessage(uint32 type, const char *message, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMove(const char *zone_short_name, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMoveInstance(uint16 instance_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideRemoveSpell(uint32 spell_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideRemoveTask(uint32 task_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideResetActivity(uint32 task_id, int activity_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideSetEntityVariableClient(const char *variable_name, const char *variable_value, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideSetEntityVariableNPC(const char *variable_name, const char *variable_value);
|
||||
void WorldWideSignalClient(uint32 signal, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideSignalNPC(uint32 signal);
|
||||
void WorldWideUpdateActivity(uint32 task_id, int activity_id, int activity_count = 1, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void CrossZoneLDoNUpdate(uint8 update_type, uint8 update_subtype, int update_identifier, uint32 theme_id, int points = 1, const char* client_name = "");
|
||||
void CrossZoneMarquee(uint8 update_type, int update_identifier, uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message, const char* client_name = "");
|
||||
void CrossZoneMessage(uint8 update_type, int update_identifier, uint32 type, const char* message, const char* client_name = "");
|
||||
void CrossZoneMove(uint8 update_type, uint8 update_subtype, int update_identifier, const char* zone_short_name, uint16 instance_id, const char* client_name = "");
|
||||
void CrossZoneSetEntityVariable(uint8 update_type, int update_identifier, const char* variable_name, const char* variable_value, const char* client_name = "");
|
||||
void CrossZoneSignal(uint8 update_type, int update_identifier, uint32 signal, const char* client_name = "");
|
||||
void CrossZoneSpell(uint8 update_type, uint8 update_subtype, int update_identifier, uint32 spell_id, const char* client_name = "");
|
||||
void CrossZoneTaskUpdate(uint8 update_type, uint8 update_subtype, int update_identifier, uint32 task_identifier, int task_subidentifier = -1, int update_count = 1, bool enforce_level_requirement = false, const char* client_name = "");
|
||||
void WorldWideLDoNUpdate(uint8 update_type, uint32 theme_id, int points = 1, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMarquee(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, const char* message, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMessage(uint32 type, const char* message, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideMove(uint8 update_type, const char* zone_short_name, uint16 instance_id = 0, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideSetEntityVariable(uint8 update_type, const char* variable_name, const char* variable_value, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideSignal(uint8 update_type, uint32 signal, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideSpell(uint8 update_type, uint32 spell_id, uint8 min_status = 0, uint8 max_status = 0);
|
||||
void WorldWideTaskUpdate(uint8 update_type, uint32 task_identifier, int task_subidentifier = -1, int update_count = 1, bool enforce_level_requirement = false, uint8 min_status = 0, uint8 max_status = 0);
|
||||
bool EnableRecipe(uint32 recipe_id);
|
||||
bool DisableRecipe(uint32 recipe_id);
|
||||
void ClearNPCTypeCache(int npctype_id);
|
||||
|
||||
+93
-61
@@ -63,6 +63,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
if (spell.disallow_sit && IsBuffSpell(spell_id) && IsClient() && (CastToClient()->IsSitting() || CastToClient()->GetHorseId() != 0))
|
||||
return false;
|
||||
|
||||
bool CanMemoryBlurFromMez = true;
|
||||
if (IsMezzed()) { //Check for special memory blur behavior when on mez, this needs to be before buff override.
|
||||
CanMemoryBlurFromMez = false;
|
||||
}
|
||||
|
||||
bool c_override = false;
|
||||
if (caster && caster->IsClient() && GetCastedSpellInvSlot() > 0) {
|
||||
const EQ::ItemInstance *inst = caster->CastToClient()->GetInv().GetItem(GetCastedSpellInvSlot());
|
||||
@@ -343,31 +348,13 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Complete Heal");
|
||||
#endif
|
||||
//make sure they are not allready affected by this...
|
||||
//I think that is the point of making this a buff.
|
||||
//this is in the wrong spot, it should be in the immune
|
||||
//section so the buff timer does not get refreshed!
|
||||
|
||||
int i;
|
||||
bool inuse = false;
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
for(i = 0; i < buff_count; i++) {
|
||||
if(buffs[i].spellid == spell_id && i != buffslot) {
|
||||
Message(0, "You must wait before you can be affected by this spell again.");
|
||||
inuse = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(inuse)
|
||||
break;
|
||||
|
||||
int32 val = 0;
|
||||
val = 7500 * effect_value;
|
||||
if (caster)
|
||||
int val = 7500 * effect_value;
|
||||
if (caster) {
|
||||
val = caster->GetActSpellHealing(spell_id, val, this);
|
||||
|
||||
if (val > 0)
|
||||
}
|
||||
if (val > 0) {
|
||||
HealDamage(val, caster);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -387,7 +374,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
caster->SetMana(caster->GetMana() + std::abs(effect_value));
|
||||
|
||||
if (effect_value < 0)
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
if (caster)
|
||||
caster->Message(Chat::White, "You have gained %+i mana!", effect_value);
|
||||
@@ -403,7 +390,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
|
||||
SetMana(GetMana() + effect_value);
|
||||
if (effect_value < 0)
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -600,7 +587,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
snprintf(effect_desc, _EDLEN, "Invisibility to Animals");
|
||||
#endif
|
||||
invisible_animals = true;
|
||||
SetInvisible(0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -611,7 +597,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
snprintf(effect_desc, _EDLEN, "Invisibility to Undead");
|
||||
#endif
|
||||
invisible_undead = true;
|
||||
SetInvisible(0);
|
||||
break;
|
||||
}
|
||||
case SE_SeeInvis:
|
||||
@@ -1136,13 +1121,23 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
|
||||
case SE_Purify:
|
||||
{
|
||||
//Attempt to remove all Deterimental buffs.
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
for(int slot = 0; slot < buff_count; slot++) {
|
||||
if (buffs[slot].spellid != SPELL_UNKNOWN &&
|
||||
IsDetrimentalSpell(buffs[slot].spellid) && spells[buffs[slot].spellid].dispel_flag == 0)
|
||||
{
|
||||
if (caster && TryDispel(caster->GetLevel(),buffs[slot].casterlevel, effect_value)){
|
||||
//Attempt to remove up to base amount of detrimental effects (excluding charm, fear, resurrection, and revival sickness).
|
||||
int purify_count = spells[spell_id].base[i];
|
||||
if (purify_count > GetMaxTotalSlots()) {
|
||||
purify_count = GetMaxTotalSlots();
|
||||
}
|
||||
|
||||
for(int slot = 0; slot < purify_count; slot++) {
|
||||
if (IsValidSpell(buffs[slot].spellid) && IsDetrimentalSpell(buffs[slot].spellid)){
|
||||
|
||||
if (!IsEffectInSpell(buffs[slot].spellid, SE_Charm) &&
|
||||
!IsEffectInSpell(buffs[slot].spellid, SE_Fear) &&
|
||||
buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS &&
|
||||
buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS2 &&
|
||||
buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS3 &&
|
||||
buffs[slot].spellid != SPELL_RESURRECTION_SICKNESS4 &&
|
||||
buffs[slot].spellid != SPELL_REVIVAL_SICKNESS)
|
||||
{
|
||||
BuffFadeBySlot(slot);
|
||||
}
|
||||
}
|
||||
@@ -1531,16 +1526,16 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#ifdef SPELL_EFFECT_SPAM
|
||||
snprintf(effect_desc, _EDLEN, "Memory Blur: %d", effect_value);
|
||||
#endif
|
||||
int wipechance = spells[spell_id].base[i];
|
||||
int bonus = 0;
|
||||
|
||||
if (caster){
|
||||
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
|
||||
caster->itembonuses.IncreaseChanceMemwipe +
|
||||
caster->aabonuses.IncreaseChanceMemwipe;
|
||||
//Memory blur component of Mez spells is not checked again if Mez is recast on a target that is already mezed
|
||||
if (!CanMemoryBlurFromMez && IsEffectInSpell(spell_id, SE_Mez)) {
|
||||
break;
|
||||
}
|
||||
|
||||
int wipechance = 0;
|
||||
|
||||
if (caster) {
|
||||
wipechance = caster->GetMemoryBlurChance(effect_value);
|
||||
}
|
||||
|
||||
wipechance += wipechance*bonus/100;
|
||||
|
||||
if(zone->random.Roll(wipechance))
|
||||
{
|
||||
@@ -2458,8 +2453,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#endif
|
||||
if(IsClient()) {
|
||||
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + effect_value);
|
||||
if (effect_value < 0)
|
||||
TryTriggerOnValueAmount(false, false, true);
|
||||
if (effect_value < 0) {
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2470,10 +2466,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
snprintf(effect_desc, _EDLEN, "Current Endurance Once: %+i", effect_value);
|
||||
#endif
|
||||
|
||||
if(IsClient()) {
|
||||
if (IsClient()) {
|
||||
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + effect_value);
|
||||
if (effect_value < 0)
|
||||
TryTriggerOnValueAmount(false, false, true);
|
||||
if (effect_value < 0) {
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2652,7 +2649,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
int32 mana_to_use = GetMana() - spell.base[i];
|
||||
if(mana_to_use > -1) {
|
||||
SetMana(GetMana() - spell.base[i]);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
// we take full dmg(-10 to make the damage the right sign)
|
||||
mana_damage = spell.base[i] / -10 * spell.base2[i];
|
||||
Damage(caster, mana_damage, spell_id, spell.skill, false, i, true);
|
||||
@@ -2672,7 +2669,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
int32 end_to_use = CastToClient()->GetEndurance() - spell.base[i];
|
||||
if(end_to_use > -1) {
|
||||
CastToClient()->SetEndurance(CastToClient()->GetEndurance() - spell.base[i]);
|
||||
TryTriggerOnValueAmount(false, false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
// we take full dmg(-10 to make the damage the right sign)
|
||||
end_damage = spell.base[i] / -10 * spell.base2[i];
|
||||
Damage(caster, end_damage, spell_id, spell.skill, false, i, true);
|
||||
@@ -2754,7 +2751,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
else {
|
||||
dmg = ratio*max_mana/10;
|
||||
caster->SetMana(caster->GetMana() - max_mana);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
|
||||
if(IsDetrimentalSpell(spell_id)) {
|
||||
@@ -3858,19 +3855,15 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
}
|
||||
|
||||
case SE_WipeHateList: {
|
||||
if (IsMezSpell(buff.spellid))
|
||||
if (IsMezSpell(buff.spellid)) {
|
||||
break;
|
||||
|
||||
int wipechance = spells[buff.spellid].base[i];
|
||||
int bonus = 0;
|
||||
|
||||
if (caster) {
|
||||
bonus = caster->spellbonuses.IncreaseChanceMemwipe +
|
||||
caster->itembonuses.IncreaseChanceMemwipe +
|
||||
caster->aabonuses.IncreaseChanceMemwipe;
|
||||
}
|
||||
|
||||
wipechance += wipechance * bonus / 100;
|
||||
int wipechance = 0;
|
||||
|
||||
if (caster) {
|
||||
wipechance = caster->GetMemoryBlurChance(effect_value);
|
||||
}
|
||||
|
||||
if (zone->random.Roll(wipechance)) {
|
||||
if (IsAIControlled()) {
|
||||
@@ -8528,3 +8521,42 @@ int Mob::GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool
|
||||
|
||||
return zone->random.Int(focus_base, focus_base2);
|
||||
}
|
||||
|
||||
int Mob::GetMemoryBlurChance(int base_chance)
|
||||
{
|
||||
/*
|
||||
Memory Blur mechanic for SPA 62
|
||||
Chance formula is effect chance + charisma modifer + caster level modifier
|
||||
Effect chance is base value of spell
|
||||
Charisma modifier is CHA/10 = %, with MAX of 15% (thus 150 cha gives you max bonus)
|
||||
Caster level modifier. +100% if caster < level 17 which scales down to 25% at > 53. **
|
||||
(Yes the above gets worse as you level. Behavior was confirmed on live.)
|
||||
Memory blur is applied to mez on initial cast using same formula. However, recasting on a target that
|
||||
is already mezed will not give a chance to memory blur. The blur is not checked on buff ticks.
|
||||
|
||||
SPA 242 SE_IncreaseChanceMemwipe modifies the final chance after all bonuses are applied.
|
||||
This is also applied to memory blur from mez spells.
|
||||
|
||||
this = caster
|
||||
*/
|
||||
int cha_mod = int(GetCHA() / 10);
|
||||
cha_mod = std::min(cha_mod, 15);
|
||||
|
||||
int lvl_mod = 0;
|
||||
if (GetLevel() < 17) {
|
||||
lvl_mod = 100;
|
||||
}
|
||||
else if (GetLevel() > 53) {
|
||||
lvl_mod = 25;
|
||||
}
|
||||
else {
|
||||
lvl_mod = 100 + ((GetLevel() - 16)*-2);//Derived from above range of values.**
|
||||
}
|
||||
|
||||
int chance = cha_mod + lvl_mod + base_chance;
|
||||
|
||||
int chance_mod = spellbonuses.IncreaseChanceMemwipe + itembonuses.IncreaseChanceMemwipe + aabonuses.IncreaseChanceMemwipe;
|
||||
|
||||
chance += chance * chance_mod / 100;
|
||||
return chance;
|
||||
}
|
||||
|
||||
+9
-4
@@ -383,7 +383,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
GetName()
|
||||
);
|
||||
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
return(false);
|
||||
}
|
||||
|
||||
@@ -2467,7 +2467,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
|
||||
LogSpells("Spell [{}]: consuming [{}] mana", spell_id, mana_used);
|
||||
if (!DoHPToManaCovert(mana_used)) {
|
||||
SetMana(GetMana() - mana_used);
|
||||
TryTriggerOnValueAmount(false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
}
|
||||
// one may want to check if this is a disc or not, but we actually don't, there are non disc stuff that have end cost
|
||||
@@ -2478,7 +2478,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
|
||||
if (mgb)
|
||||
end_cost *= 2;
|
||||
SetEndurance(GetEndurance() - EQ::ClampUpper(end_cost, GetEndurance()));
|
||||
TryTriggerOnValueAmount(false, false, true);
|
||||
TryTriggerOnCastRequirement();
|
||||
}
|
||||
if (mgb)
|
||||
SetMGB(false);
|
||||
@@ -2931,6 +2931,11 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
|
||||
|
||||
LogSpells("Check Stacking on old [{}] ([{}]) @ lvl [{}] (by [{}]) vs. new [{}] ([{}]) @ lvl [{}] (by [{}])", sp1.name, spellid1, caster_level1, (caster1==nullptr)?"Nobody":caster1->GetName(), sp2.name, spellid2, caster_level2, (caster2==nullptr)?"Nobody":caster2->GetName());
|
||||
|
||||
if (spellbonuses.CompleteHealBuffBlocker && IsEffectInSpell(spellid2, SE_CompleteHeal)) {
|
||||
Message(0, "You must wait before you can be affected by this spell again.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spellid1 == spellid2 ) {
|
||||
if (!IsStackableDot(spellid1) && !IsEffectInSpell(spellid1, SE_ManaBurn)) { // mana burn spells we need to use the stacking command blocks live actually checks those first, we should probably rework to that too
|
||||
if (caster_level1 > caster_level2) { // cur buff higher level than new
|
||||
@@ -3401,7 +3406,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
buffs[emptyslot].focusproclimit_procamt = 0;
|
||||
buffs[emptyslot].instrument_mod = caster ? caster->GetInstrumentMod(spell_id) : 10;
|
||||
|
||||
if (level_override > 0) {
|
||||
if (level_override > 0 || buffs[emptyslot].numhits > 0) {
|
||||
buffs[emptyslot].UpdateClient = true;
|
||||
} else {
|
||||
if (buffs[emptyslot].ticsremaining > (1 + CalcBuffDuration_formula(caster_level, spells[spell_id].buffdurationformula, spells[spell_id].buffduration)))
|
||||
|
||||
+25
-8
@@ -375,6 +375,14 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
|
||||
}
|
||||
|
||||
DBTradeskillRecipe_Struct spec;
|
||||
|
||||
if (parse->EventPlayer(EVENT_COMBINE, user, std::to_string(in_combine->container_slot), 0) == 1) {
|
||||
auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0);
|
||||
user->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!content_db.GetTradeRecipe(container, c_type, some_id, user->CharacterID(), &spec)) {
|
||||
|
||||
LogTradeskillsDetail("[HandleCombine] Check 2");
|
||||
@@ -774,7 +782,7 @@ void Client::SendTradeskillSearchResults(
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (row == nullptr || row[0] == nullptr || row[1] == nullptr || row[2] == nullptr || row[3] == nullptr ||
|
||||
row[5] == nullptr) {
|
||||
row[4] == nullptr || row[5] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -782,27 +790,36 @@ void Client::SendTradeskillSearchResults(
|
||||
const char *name = row[1];
|
||||
uint32 trivial = (uint32) atoi(row[2]);
|
||||
uint32 comp_count = (uint32) atoi(row[3]);
|
||||
uint32 tradeskill = (uint16) atoi(row[5]);
|
||||
uint32 tradeskill = (uint16) atoi(row[4]);
|
||||
uint32 must_learn = (uint16) atoi(row[5]);
|
||||
|
||||
|
||||
// Skip the recipes that exceed the threshold in skill difference
|
||||
// Recipes that have either been made before or were
|
||||
// explicitly learned are excempt from that limit
|
||||
|
||||
auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe(
|
||||
character_learned_recipe_list,
|
||||
recipe_id
|
||||
);
|
||||
|
||||
if (RuleB(Skills, UseLimitTradeskillSearchSkillDiff) &&
|
||||
((int32) trivial - (int32) GetSkill((EQ::skills::SkillType) tradeskill)) >
|
||||
RuleI(Skills, MaxTradeskillSearchSkillDiff)) {
|
||||
|
||||
LogTradeskills("Checking limit recipe_id [{}] name [{}]", recipe_id, name);
|
||||
|
||||
auto character_learned_recipe = CharacterRecipeListRepository::GetRecipe(
|
||||
character_learned_recipe_list,
|
||||
recipe_id
|
||||
);
|
||||
|
||||
if (character_learned_recipe.made_count == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//Skip recipes that must be learned
|
||||
if ((must_learn & 0xf) && !character_learned_recipe.recipe_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_RecipeReply, sizeof(RecipeReply_Struct));
|
||||
RecipeReply_Struct *reply = (RecipeReply_Struct *) outapp->pBuffer;
|
||||
|
||||
@@ -1481,7 +1498,7 @@ bool ZoneDatabase::GetTradeRecipe(
|
||||
recipe_id
|
||||
);
|
||||
|
||||
if (character_learned_recipe.made_count > 0) {
|
||||
if (character_learned_recipe.recipe_id) { //If this exists we learned it
|
||||
LogTradeskills("[GetTradeRecipe] made_count [{}]", character_learned_recipe.made_count);
|
||||
|
||||
spec->has_learnt = true;
|
||||
|
||||
@@ -935,6 +935,32 @@ void Mob::TryMoveAlong(float distance, float angle, bool send)
|
||||
Teleport(new_pos);
|
||||
}
|
||||
|
||||
// like above, but takes a starting position and returns a new location instead of actually moving
|
||||
glm::vec4 Mob::TryMoveAlong(const glm::vec4 &start, float distance, float angle)
|
||||
{
|
||||
angle += start.w;
|
||||
angle = FixHeading(angle);
|
||||
|
||||
glm::vec3 tmp_pos;
|
||||
glm::vec3 new_pos = start;
|
||||
new_pos.x += distance * g_Math.FastSin(angle);
|
||||
new_pos.y += distance * g_Math.FastCos(angle);
|
||||
new_pos.z += GetZOffset();
|
||||
|
||||
if (zone->HasMap()) {
|
||||
auto new_z = zone->zonemap->FindClosestZ(new_pos, nullptr);
|
||||
if (new_z != BEST_Z_INVALID)
|
||||
new_pos.z = new_z;
|
||||
|
||||
if (zone->zonemap->LineIntersectsZone(start, new_pos, 0.0f, &tmp_pos))
|
||||
new_pos = tmp_pos;
|
||||
}
|
||||
|
||||
new_pos.z = GetFixedZ(new_pos);
|
||||
|
||||
return {new_pos.x, new_pos.y, new_pos.z, start.w};
|
||||
}
|
||||
|
||||
int ZoneDatabase::GetHighestGrid(uint32 zoneid) {
|
||||
|
||||
std::string query = StringFormat("SELECT COALESCE(MAX(id), 0) FROM grid WHERE zoneid = %i", zoneid);
|
||||
|
||||
+741
-849
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -153,7 +153,6 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
|
||||
LogInfo("Zone Bootup: [{}] ([{}]: [{}])", zonename, iZoneID, iInstanceID);
|
||||
parse->Init();
|
||||
UpdateWindowTitle(nullptr);
|
||||
zone->GetTimeSync();
|
||||
|
||||
zone->RequestUCSServerStatus();
|
||||
|
||||
@@ -1818,7 +1817,8 @@ void Zone::Repop(uint32 delay)
|
||||
|
||||
void Zone::GetTimeSync()
|
||||
{
|
||||
if (worldserver.Connected() && !zone_has_current_time) {
|
||||
if (!zone_has_current_time) {
|
||||
LogInfo("Requesting world time");
|
||||
auto pack = new ServerPacket(ServerOP_GetWorldTime, 1);
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
|
||||
+5
-1
@@ -167,7 +167,9 @@ bool ZoneDatabase::GetZoneCFG(
|
||||
"fast_regen_endurance, " // 59
|
||||
"npc_max_aggro_dist, " // 60
|
||||
"max_movement_update_range, " // 61
|
||||
"underworld_teleport_index " // 62
|
||||
"underworld_teleport_index, " // 62
|
||||
"lava_damage, " // 63
|
||||
"min_lava_damage " // 64
|
||||
"FROM zone WHERE zoneidnumber = %i AND version = %i %s",
|
||||
zoneid,
|
||||
instance_id,
|
||||
@@ -220,6 +222,8 @@ bool ZoneDatabase::GetZoneCFG(
|
||||
zone_data->FastRegenEndurance = atoi(row[59]);
|
||||
zone_data->NPCAggroMaxDist = atoi(row[60]);
|
||||
zone_data->underworld_teleport_index = atoi(row[62]);
|
||||
zone_data->LavaDamage = atoi(row[63]);
|
||||
zone_data->MinLavaDamage = atoi(row[64]);
|
||||
|
||||
int bindable = 0;
|
||||
bindable = atoi(row[31]);
|
||||
|
||||
Reference in New Issue
Block a user