mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-03 01:06:36 +00:00
Merge branch 'master' into event_loop
This commit is contained in:
@@ -2529,6 +2529,8 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne
|
||||
|
||||
case SE_ImmuneFleeing:
|
||||
new_bonus->ImmuneToFlee = true;
|
||||
if (currently_fleeing) // lets update shit now instead of next tick
|
||||
ProcessFlee();
|
||||
break;
|
||||
|
||||
case SE_DelayDeath:
|
||||
|
||||
+104
-44
@@ -2655,60 +2655,120 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail)
|
||||
bind_out->type = 0;
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillBindWound, nullptr, 5);
|
||||
|
||||
int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound +
|
||||
aabonuses.MaxBindWound;
|
||||
if (RuleB(Character, UseOldBindWound)) {
|
||||
int maxHPBonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound +
|
||||
aabonuses.MaxBindWound;
|
||||
|
||||
int max_percent = 50 + 10 * maxHPBonus;
|
||||
int max_percent = 50 + maxHPBonus;
|
||||
|
||||
if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||
max_percent = 70 + 10 * maxHPBonus;
|
||||
}
|
||||
|
||||
max_percent = mod_bindwound_percent(max_percent, bindmob);
|
||||
|
||||
int max_hp = bindmob->GetMaxHP() * max_percent / 100;
|
||||
|
||||
// send bindmob new hp's
|
||||
if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) {
|
||||
// 0.120 per skill point, 0.60 per skill level, minimum 3 max 30
|
||||
int bindhps = 3;
|
||||
|
||||
if (GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||
bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10;
|
||||
}
|
||||
else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) {
|
||||
bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4;
|
||||
if (GetClass() == MONK && GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||
max_percent = 70 + maxHPBonus;
|
||||
}
|
||||
|
||||
// Implementation of aaMithanielsBinding is a guess (the multiplier)
|
||||
int bindBonus = spellbonuses.BindWound + itembonuses.BindWound +
|
||||
max_percent = mod_bindwound_percent(max_percent, bindmob);
|
||||
|
||||
int max_hp = bindmob->GetMaxHP() * max_percent / 100;
|
||||
|
||||
// send bindmob new hp's
|
||||
if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() <= (max_hp)-1) {
|
||||
// 0.120 per skill point, 0.60 per skill level, minimum 3 max 30
|
||||
int bindhps = 3;
|
||||
|
||||
if (GetSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||
bindhps += GetSkill(EQEmu::skills::SkillBindWound) * 4 / 10;
|
||||
}
|
||||
else if (GetSkill(EQEmu::skills::SkillBindWound) >= 10) {
|
||||
bindhps += GetSkill(EQEmu::skills::SkillBindWound) / 4;
|
||||
}
|
||||
|
||||
// Implementation of aaMithanielsBinding is a guess (the multiplier)
|
||||
int bindBonus = spellbonuses.BindWound + itembonuses.BindWound +
|
||||
aabonuses.BindWound;
|
||||
|
||||
bindhps += bindhps * bindBonus / 100;
|
||||
bindhps += bindhps * bindBonus / 100;
|
||||
|
||||
bindhps = mod_bindwound_hp(bindhps, bindmob);
|
||||
bindhps = mod_bindwound_hp(bindhps, bindmob);
|
||||
|
||||
// if the bind takes them above the max bindable
|
||||
// cap it at that value. Dont know if live does it this way
|
||||
// but it makes sense to me.
|
||||
int chp = bindmob->GetHP() + bindhps;
|
||||
if (chp > max_hp)
|
||||
chp = max_hp;
|
||||
// if the bind takes them above the max bindable
|
||||
// cap it at that value. Dont know if live does it this way
|
||||
// but it makes sense to me.
|
||||
int chp = bindmob->GetHP() + bindhps;
|
||||
if (chp > max_hp)
|
||||
chp = max_hp;
|
||||
|
||||
bindmob->SetHP(chp);
|
||||
bindmob->SendHPUpdate();
|
||||
} else {
|
||||
// I dont have the real, live
|
||||
Message(15, "You cannot bind wounds above %d%% hitpoints.",
|
||||
max_percent);
|
||||
if (bindmob != this && bindmob->IsClient())
|
||||
bindmob->CastToClient()->Message(
|
||||
15,
|
||||
"You cannot have your wounds bound above %d%% hitpoints.",
|
||||
max_percent);
|
||||
// Too many hp message goes here.
|
||||
bindmob->SetHP(chp);
|
||||
bindmob->SendHPUpdate();
|
||||
}
|
||||
else {
|
||||
// I dont have the real, live
|
||||
Message(15, "You cannot bind wounds above %d%% hitpoints.",
|
||||
max_percent);
|
||||
if (bindmob != this && bindmob->IsClient())
|
||||
bindmob->CastToClient()->Message(
|
||||
15,
|
||||
"You cannot have your wounds bound above %d%% hitpoints.",
|
||||
max_percent);
|
||||
// Too many hp message goes here.
|
||||
}
|
||||
}
|
||||
} else {
|
||||
else {
|
||||
int percent_base = 50;
|
||||
if (GetRawSkill(EQEmu::skills::SkillBindWound) > 200) {
|
||||
if ((GetClass() == MONK) || (GetClass() == BEASTLORD))
|
||||
percent_base = 70;
|
||||
else if ((GetLevel() > 50) && ((GetClass() == WARRIOR) || (GetClass() == ROGUE) || (GetClass() == CLERIC)))
|
||||
percent_base = 70;
|
||||
}
|
||||
|
||||
int percent_bonus = 0;
|
||||
if (percent_base >= 70)
|
||||
percent_bonus = spellbonuses.MaxBindWound + itembonuses.MaxBindWound + aabonuses.MaxBindWound;
|
||||
|
||||
int max_percent = percent_base + percent_bonus;
|
||||
if (max_percent < 0)
|
||||
max_percent = 0;
|
||||
if (max_percent > 100)
|
||||
max_percent = 100;
|
||||
|
||||
max_percent = mod_bindwound_percent(max_percent, bindmob);
|
||||
|
||||
int max_hp = (bindmob->GetMaxHP() * max_percent) / 100;
|
||||
if (max_hp > bindmob->GetMaxHP())
|
||||
max_hp = bindmob->GetMaxHP();
|
||||
|
||||
if (bindmob->GetHP() < bindmob->GetMaxHP() && bindmob->GetHP() < max_hp) {
|
||||
int bindhps = 3; // base bind hp
|
||||
if (percent_base >= 70)
|
||||
bindhps = (GetSkill(EQEmu::skills::SkillBindWound) * 4) / 10; // 8:5 skill-to-hp ratio
|
||||
else if (GetSkill(EQEmu::skills::SkillBindWound) >= 12)
|
||||
bindhps = GetSkill(EQEmu::skills::SkillBindWound) / 4; // 4:1 skill-to-hp ratio
|
||||
|
||||
int bonus_hp_percent = 0;
|
||||
if (percent_base >= 70)
|
||||
bonus_hp_percent = spellbonuses.BindWound + itembonuses.BindWound + aabonuses.BindWound;
|
||||
|
||||
bindhps += (bindhps * bonus_hp_percent) / 100;
|
||||
|
||||
if (bindhps < 3)
|
||||
bindhps = 3;
|
||||
|
||||
bindhps = mod_bindwound_hp(bindhps, bindmob);
|
||||
|
||||
bindhps += bindmob->GetHP();
|
||||
if (bindhps > max_hp)
|
||||
bindhps = max_hp;
|
||||
|
||||
bindmob->SetHP(bindhps);
|
||||
bindmob->SendHPUpdate();
|
||||
}
|
||||
else {
|
||||
Message(15, "You cannot bind wounds above %d%% hitpoints", max_percent);
|
||||
if (bindmob != this && bindmob->IsClient())
|
||||
bindmob->CastToClient()->Message(15, "You cannot have your wounds bound above %d%% hitpoints", max_percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Send client bind failed
|
||||
if (bindmob != this)
|
||||
bind_out->type = 6; // They moved
|
||||
|
||||
@@ -795,6 +795,7 @@ public:
|
||||
void SendClearAA();
|
||||
inline uint32 GetMaxAAXP(void) const { return max_AAXP; }
|
||||
inline uint32 GetAAXP() const { return m_pp.expAA; }
|
||||
inline uint32 GetAAPercent() const { return m_epp.perAA; }
|
||||
int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id);
|
||||
void SetAATitle(const char *Title);
|
||||
void SetTitleSuffix(const char *txt);
|
||||
|
||||
@@ -3616,6 +3616,26 @@ XS(XS__crosszonesignalnpcbynpctypeid)
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__worldwidemarquee);
|
||||
XS(XS__worldwidemarquee)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 6)
|
||||
Perl_croak(aTHX_ "Usage: worldwidemarquee(type, priority, fadein, fadeout, duration, message)");
|
||||
|
||||
if (items == 6) {
|
||||
uint32 type = (uint32)SvIV(ST(0));
|
||||
uint32 priority = (uint32)SvIV(ST(1));
|
||||
uint32 fadein = (uint32)SvIV(ST(2));
|
||||
uint32 fadeout = (uint32)SvIV(ST(3));
|
||||
uint32 duration = (uint32)SvIV(ST(4));
|
||||
char* message = (char *)SvPV_nolen(ST(5));
|
||||
quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message);
|
||||
}
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__debug);
|
||||
XS(XS__debug)
|
||||
{
|
||||
@@ -3749,6 +3769,7 @@ EXTERN_C XS(boot_quest)
|
||||
newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file);
|
||||
newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file);
|
||||
newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file);
|
||||
newXS(strcpy(buf, "worldwidemarquee"), XS__worldwidemarquee, file);
|
||||
newXS(strcpy(buf, "debug"), XS__debug, file);
|
||||
newXS(strcpy(buf, "delglobal"), XS__delglobal, file);
|
||||
newXS(strcpy(buf, "depop"), XS__depop, file);
|
||||
|
||||
@@ -185,6 +185,11 @@ uint32 Lua_Client::GetAAExp() {
|
||||
return self->GetAAXP();
|
||||
}
|
||||
|
||||
uint32 Lua_Client::GetAAPercent() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetAAPercent();
|
||||
}
|
||||
|
||||
uint32 Lua_Client::GetTotalSecondsPlayed() {
|
||||
Lua_Safe_Call_Int();
|
||||
return self->GetTotalSecondsPlayed();
|
||||
@@ -1377,6 +1382,7 @@ luabind::scope lua_register_client() {
|
||||
.def("GetWeight", (int(Lua_Client::*)(void))&Lua_Client::GetWeight)
|
||||
.def("GetEXP", (uint32(Lua_Client::*)(void))&Lua_Client::GetEXP)
|
||||
.def("GetAAExp", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAExp)
|
||||
.def("GetAAPercent", (uint32(Lua_Client::*)(void))&Lua_Client::GetAAPercent)
|
||||
.def("GetTotalSecondsPlayed", (uint32(Lua_Client::*)(void))&Lua_Client::GetTotalSecondsPlayed)
|
||||
.def("UpdateLDoNPoints", (void(Lua_Client::*)(int,uint32))&Lua_Client::UpdateLDoNPoints)
|
||||
.def("SetDeity", (void(Lua_Client::*)(int))&Lua_Client::SetDeity)
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
int GetWeight();
|
||||
uint32 GetEXP();
|
||||
uint32 GetAAExp();
|
||||
uint32 GetAAPercent();
|
||||
uint32 GetTotalSecondsPlayed();
|
||||
void UpdateLDoNPoints(int points, uint32 theme);
|
||||
void SetDeity(int v);
|
||||
|
||||
@@ -892,6 +892,10 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons
|
||||
quest_manager.CrossZoneMessagePlayerByName(type, player, message);
|
||||
}
|
||||
|
||||
void lua_world_wide_marquee(uint32 type, uint32 priority, uint32 fadein, uint32 fadeout, uint32 duration, const char *message) {
|
||||
quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message);
|
||||
}
|
||||
|
||||
luabind::adl::object lua_get_qglobals(lua_State *L, Lua_NPC npc, Lua_Client client) {
|
||||
luabind::adl::object ret = luabind::newtable(L);
|
||||
|
||||
@@ -1613,6 +1617,7 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id),
|
||||
luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name),
|
||||
luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name),
|
||||
luabind::def("world_wide_marquee", &lua_world_wide_marquee),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals),
|
||||
luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC))&lua_get_qglobals),
|
||||
|
||||
@@ -871,6 +871,32 @@ XS(XS_Client_GetAAExp)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Client_GetAAPercent);
|
||||
XS(XS_Client_GetAAPercent)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Client::GetAAPercent(THIS)");
|
||||
{
|
||||
Client* THIS;
|
||||
uint32 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->GetAAPercent();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Client_GetTotalSecondsPlayed); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_GetTotalSecondsPlayed)
|
||||
{
|
||||
@@ -6465,6 +6491,7 @@ XS(boot_Client)
|
||||
newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$");
|
||||
newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$");
|
||||
newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$");
|
||||
|
||||
@@ -3017,6 +3017,20 @@ void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, cons
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
void QuestManager::WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message) {
|
||||
uint32 message_len = strlen(Message) + 1;
|
||||
auto pack = new ServerPacket(ServerOP_WWMarquee, sizeof(WWMarquee_Struct) + message_len);
|
||||
WWMarquee_Struct* WWMS = (WWMarquee_Struct*) pack->pBuffer;
|
||||
WWMS->Type = Type;
|
||||
WWMS->Priority = Priority;
|
||||
WWMS->FadeIn = FadeIn;
|
||||
WWMS->FadeOut = FadeOut;
|
||||
WWMS->Duration = Duration;
|
||||
strn0cpy(WWMS->Message, Message, 512);
|
||||
worldserver.SendPacket(pack);
|
||||
safe_delete(pack);
|
||||
}
|
||||
|
||||
bool QuestManager::EnableRecipe(uint32 recipe_id)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
@@ -252,6 +252,7 @@ public:
|
||||
void CrossZoneSignalPlayerByName(const char *CharName, uint32 data);
|
||||
void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var);
|
||||
void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message);
|
||||
void WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message);
|
||||
bool EnableRecipe(uint32 recipe_id);
|
||||
bool DisableRecipe(uint32 recipe_id);
|
||||
void ClearNPCTypeCache(int npctype_id);
|
||||
|
||||
+5
-3
@@ -5458,8 +5458,10 @@ void Mob::SendBuffsToClient(Client *c)
|
||||
EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
|
||||
{
|
||||
uint32 count = 0;
|
||||
uint32 buff_count = GetMaxTotalSlots();
|
||||
for(unsigned int i = 0; i < buff_count; ++i)
|
||||
// for self we want all buffs, for target, we want to skip song window buffs
|
||||
// since NPCs and pets don't have a song window, we still see it for them :P
|
||||
uint32 buff_count = for_target ? GetMaxBuffSlots() : GetMaxTotalSlots();
|
||||
for(int i = 0; i < buff_count; ++i)
|
||||
{
|
||||
if(buffs[i].spellid != SPELL_UNKNOWN)
|
||||
{
|
||||
@@ -5491,7 +5493,7 @@ EQApplicationPacket *Mob::MakeBuffsPacket(bool for_target)
|
||||
buff->type = 0;
|
||||
|
||||
uint32 index = 0;
|
||||
for(unsigned int i = 0; i < buff_count; ++i)
|
||||
for(int i = 0; i < buff_count; ++i)
|
||||
{
|
||||
if(buffs[i].spellid != SPELL_UNKNOWN)
|
||||
{
|
||||
|
||||
@@ -1838,6 +1838,19 @@ void WorldServer::Process() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_WWMarquee:
|
||||
{
|
||||
WWMarquee_Struct* WWMS = (WWMarquee_Struct*) pack->pBuffer;
|
||||
std::list<Client*> client_list;
|
||||
entity_list.GetClientList(client_list);
|
||||
auto iter = client_list.begin();
|
||||
std::string Message = WWMS->Message;
|
||||
while (iter != client_list.end()) {
|
||||
Client* client = (*iter);
|
||||
client->SendMarqueeMessage(WWMS->Type, WWMS->Priority, WWMS->FadeIn, WWMS->FadeOut, WWMS->Duration, Message);
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
case ServerOP_ReloadWorld:
|
||||
{
|
||||
ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer;
|
||||
|
||||
Reference in New Issue
Block a user