Merge branch 'master' into aa

This commit is contained in:
KimLS 2015-06-07 19:42:57 -07:00
commit 6515879c14
25 changed files with 324 additions and 51 deletions

View File

@ -1,5 +1,8 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 06/07/2015 ==
Uleat: Implemented optional rule for using disenchanted bags. Action triggers at the same point that temporary items are removed.
Optional SQL: utils/sql/git/optional/2015_06_07_TransformSummonedBagsRule.sql
== 05/25/2015 ==
Akkadius: Implemented disjointed zone based time, this can be triggered via quest methods

View File

@ -345,6 +345,7 @@ RULE_BOOL ( Spells, SwarmPetTargetLock, false) // Use old method of swarm pets t
RULE_BOOL ( Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects.
RULE_BOOL ( Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects.
RULE_BOOL ( Spells, UseAdditiveFocusFromWornSlot, false) // Allows an additive focus effect to be calculated from worn slot.
RULE_BOOL ( Spells, AlwaysSendTargetsBuffs, false) // ignore LAA level if true
RULE_CATEGORY_END()
RULE_CATEGORY( Combat )
@ -611,6 +612,7 @@ RULE_BOOL ( Inventory, EnforceAugmentUsability, true) // Forces augmented item u
RULE_BOOL ( Inventory, EnforceAugmentWear, true) // Forces augment wear slot validation
RULE_BOOL ( Inventory, DeleteTransformationMold, true) //False if you want mold to last forever
RULE_BOOL ( Inventory, AllowAnyWeaponTransformation, false) //Weapons can use any weapon transformation
RULE_BOOL ( Inventory, TransformSummonedBags, false) //Transforms summoned bags into disenchanted ones instead of deleting
RULE_CATEGORY_END()
RULE_CATEGORY( Client )

View File

@ -1,3 +1,3 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentRestriction', 'false', 'Forces augment slot restrictions.');
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentUsability', 'false', 'Forces augmented item usability.');
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.');
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:EnforceAugmentWear', 'false', 'Forces augment wear slot validation.');

View File

@ -0,0 +1 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Spells:AlwaysSendTargetBuffs', 'false', 'Allows the server to send the targets buffs ignoring the LAA.');

View File

@ -0,0 +1 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'Inventory:TransformSummonedBags', 'true', 'Transforms summoned bags into disenchanted ones instead of deleting.');

View File

@ -20,7 +20,7 @@ SET(zone_sources
embparser_api.cpp
embperl.cpp
embxs.cpp
encounter.cpp
encounter.cpp
entity.cpp
exp.cpp
fearpath.cpp
@ -36,6 +36,7 @@ SET(zone_sources
lua_corpse.cpp
lua_client.cpp
lua_door.cpp
lua_encounter.cpp
lua_entity.cpp
lua_entity_list.cpp
lua_general.cpp
@ -139,7 +140,7 @@ SET(zone_headers
embparser.h
embperl.h
embxs.h
encounter.h
encounter.h
entity.h
errmsg.h
event_codes.h
@ -151,6 +152,7 @@ SET(zone_headers
lua_bit.h
lua_client.h
lua_corpse.h
lua_encounter.h
lua_entity.h
lua_entity_list.h
lua_general.h

View File

@ -3693,7 +3693,7 @@ void Mob::CommonDamage(Mob* attacker, int32 &damage, const uint16 spell_id, cons
//send an HP update if we are hurt
if(GetHP() < GetMaxHP())
SendHPUpdate();
SendHPUpdate(!iBuffTic); // the OP_Damage actually updates the client in these cases, so we skill them
} //end `if damage was done`
//send damage packet...

View File

@ -755,7 +755,7 @@ void Bot::GenerateBaseStats() {
this->Corrup = CorruptionResist;
SetBotSpellID(BotSpellID);
this->size = BotSize;
this->pAggroRange = 0;
this->pAssistRange = 0;
this->raid_target = false;
@ -1381,18 +1381,18 @@ int32 Bot::GenerateBaseHitPoints()
uint32 lm = GetClassLevelFactor();
int32 Post255;
int32 NormalSTA = GetSTA();
if(GetOwner() && GetOwner()->CastToClient() && GetOwner()->CastToClient()->GetClientVersion() >= ClientVersion::SoD && RuleB(Character, SoDClientUseSoDHPManaEnd))
{
float SoDPost255;
if(((NormalSTA - 255) / 2) > 0)
SoDPost255 = ((NormalSTA - 255) / 2);
else
SoDPost255 = 0;
int hp_factor = GetClassHPFactor();
if(level < 41)
{
new_base_hp = (5 + (GetLevel() * hp_factor / 12) + ((NormalSTA - SoDPost255) * GetLevel() * hp_factor / 3600));
@ -1420,7 +1420,7 @@ int32 Bot::GenerateBaseHitPoints()
new_base_hp = (5)+(GetLevel()*lm/10) + (((NormalSTA-Post255)*GetLevel()*lm/3000)) + ((Post255*1)*lm/6000);
}
this->base_hp = new_base_hp;
return new_base_hp;
}
@ -2342,7 +2342,7 @@ bool Bot::IsBotNameAvailable(char *botName, std::string* errorMessage) {
if (results.RowCount()) { //Name already in use!
return false;
}
return true; //We made it with a valid name!
}
@ -2901,7 +2901,7 @@ bool Bot::Process()
SetEndurance(GetEndurance() + CalcEnduranceRegen() + RestRegenEndurance);
}
if (sendhpupdate_timer.Check()) {
if (sendhpupdate_timer.Check(false)) {
SendHPUpdate();
if(HasPet())
@ -5894,7 +5894,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att
// delete from group data
RemoveBotFromGroup(this, g);
//Make sure group still exists if it doesnt they were already updated in RemoveBotFromGroup
g = GetGroup();
if (!g)
@ -5912,7 +5912,7 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, SkillUseTypes att
g->members[j] = nullptr;
}
}
// update the client group
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GroupUpdate, sizeof(GroupJoin_Struct));
GroupJoin_Struct* gu = (GroupJoin_Struct*)outapp->pBuffer;
@ -10823,7 +10823,7 @@ void Bot::CalcItemBonuses(StatBonuses* newbon)
AddItemBonuses(item, newbon);
}
}
// Caps
if(newbon->HPRegen > CalcHPRegenCap())
newbon->HPRegen = CalcHPRegenCap();

View File

@ -116,7 +116,7 @@ Client::Client(EQStreamInterface* ieqs)
),
//these must be listed in the order they appear in client.h
position_timer(250),
hpupdate_timer(1800),
hpupdate_timer(2000),
camp_timer(29000),
process_timer(100),
stamina_timer(40000),
@ -8631,4 +8631,4 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
safe_delete(outapp);
}
}

View File

@ -906,6 +906,7 @@ public:
bool DecreaseByID(uint32 type, uint8 amt);
uint8 SlotConvert2(uint8 slot); //Maybe not needed.
void Escape(); //AA Escape
void DisenchantSummonedBags(bool client_update = true);
void RemoveNoRent(bool client_update = true);
void RemoveDuplicateLore(bool client_update = true);
void MoveSlotNotAllowed(bool client_update = true);
@ -1257,6 +1258,8 @@ public:
int32 GetMeleeDamage(Mob* other, bool GetMinDamage = false);
void QuestReward(Mob* target, uint32 copper = 0, uint32 silver = 0, uint32 gold = 0, uint32 platinum = 0, uint32 itemid = 0, uint32 exp = 0, bool faction = false);
void ResetHPUpdateTimer() { hpupdate_timer.Start(); }
protected:
friend class Mob;
void CalcItemBonuses(StatBonuses* newbon);

View File

@ -12899,7 +12899,7 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
inspect_buffs = group->GetLeadershipAA(groupAAInspectBuffs);
}
}
if (nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) ||
if (GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs) || nt == this || inspect_buffs || (nt->IsClient() && !nt->CastToClient()->GetPVP()) ||
(nt->IsPet() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()) ||
(nt->IsMerc() && nt->GetOwner() && nt->GetOwner()->IsClient() && !nt->GetOwner()->CastToClient()->GetPVP()))
nt->SendBuffsToClient(this);

View File

@ -129,7 +129,9 @@ bool Client::Process() {
if(IsTracking() && (GetClientVersion() >= ClientVersion::SoD) && TrackingTimer.Check())
DoTracking();
if(hpupdate_timer.Check())
// SendHPUpdate calls hpupdate_timer.Start so it can delay this timer, so lets not reset with the check
// since the function will anyways
if(hpupdate_timer.Check(false))
SendHPUpdate();
if(mana_timer.Check())
@ -836,7 +838,11 @@ void Client::BulkSendInventoryItems() {
}
bool deletenorent = database.NoRentExpired(GetName());
if(deletenorent){ RemoveNoRent(false); } //client was offline for more than 30 minutes, delete no rent items
if (deletenorent) { //client was offline for more than 30 minutes, delete no rent items
if (RuleB(Inventory, TransformSummonedBags))
DisenchantSummonedBags(false);
RemoveNoRent(false);
}
RemoveDuplicateLore(false);
MoveSlotNotAllowed(false);

View File

@ -78,7 +78,7 @@ Client *Entity::CastToClient()
}
#ifdef _EQDEBUG
if (!IsClient()) {
Log.Out(Logs::General, Logs::Error, "CastToClient error (not client)");
Log.Out(Logs::General, Logs::Error, "CastToClient error (not client)");
return 0;
}
#endif
@ -267,7 +267,7 @@ const Beacon* Entity::CastToBeacon() const
return static_cast<const Beacon *>(this);
}
const Encounter* Entity::CastToEncounter() const
const Encounter* Entity::CastToEncounter() const
{
return static_cast<const Encounter *>(this);
}
@ -564,7 +564,7 @@ void EntityList::AddGroup(Group *group)
uint32 gid = worldserver.NextGroupID();
if (gid == 0) {
Log.Out(Logs::General, Logs::Error,
Log.Out(Logs::General, Logs::Error,
"Unable to get new group ID from world server. group is going to be broken.");
return;
}
@ -593,7 +593,7 @@ void EntityList::AddRaid(Raid *raid)
uint32 gid = worldserver.NextGroupID();
if (gid == 0) {
Log.Out(Logs::General, Logs::Error,
Log.Out(Logs::General, Logs::Error,
"Unable to get new group ID from world server. group is going to be broken.");
return;
}
@ -1427,7 +1427,9 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap
if (c != sender) {
if (Target == sender) {
if (inspect_buffs) { // if inspect_buffs is true we're sending a mob's buffs to those with the LAA
if (c->IsRaidGrouped()) {
if (c->GetGM() || RuleB(Spells, AlwaysSendTargetsBuffs)) {
Send = true;
} else if (c->IsRaidGrouped()) {
Raid *raid = c->GetRaid();
if (!raid)
continue;

View File

@ -705,7 +705,7 @@ void Group::SplitExp(uint32 exp, Mob* other) {
groupmod = 2.16;
else
groupmod = 1.0;
if(membercount > 1 && membercount < 6)
if(membercount > 1 && membercount <= 6)
groupexp += (uint32)((float)exp * groupmod * (RuleR(Character, GroupExpMultiplier)));
int conlevel = Mob::GetLevelCon(maxlevel, other->GetLevel());

View File

@ -2158,6 +2158,187 @@ bool Client::DecreaseByID(uint32 type, uint8 amt) {
return true;
}
static bool IsSummonedBagID(uint32 item_id)
{
switch (item_id) {
case 17147: // "Spiritual Prismatic Pack"
case 17303: // "Spirit Pouch"
case 17304: // "Dimensional Pocket"
case 17305: // "Dimensional Hole"
case 17306: // "Glowing Backpack"
case 17307: // "Quiver of Marr"
case 17308: // "Bandoleer of Luclin"
case 17309: // "Pouch of Quellious"
case 17310: // "Phantom Satchel"
case 17510: // "Glowing Chest"
case 17900: // "Grandmaster's Satchel"
case 57260: // "Glowing Backpack"
case 57261: // "Pouch of Quellious"
case 57262: // "Phantom Satchel"
case 60224: // "Faded-Glyph Tablet"
case 95199: // "Beginner Artisan Satchel"
case 95200: // "Apprentice Artisan Satchel"
case 95201: // "Freshman Artisan Satchel"
case 95202: // "Journeyman Artisan Satchel"
case 95203: // "Expert Artisan Satchel"
case 95204: // "Master Artisan Satchel"
//case 96960: // "Artisan Satchel" - no 12-slot disenchanted bags
return true;
default:
return false;
}
}
static uint32 GetDisenchantedBagID(uint8 bag_slots)
{
switch (bag_slots) {
case 4:
return 77772; // "Small Disenchanted Backpack"
case 6:
return 77774; // "Disenchanted Backpack"
case 8:
return 77776; // "Large Disenchanted Backpack"
case 10:
return 77778; // "Huge Disenchanted Backpack"
default:
return 0; // no suitable conversions
}
}
static bool CopyBagContents(ItemInst* new_bag, const ItemInst* old_bag)
{
if (!new_bag || !old_bag) { return false; }
if (new_bag->GetItem()->BagSlots < old_bag->GetItem()->BagSlots) { return false; }
// pre-check for size comparisons
for (auto bag_slot = 0; bag_slot < old_bag->GetItem()->BagSlots; ++bag_slot) {
if (!old_bag->GetItem(bag_slot)) { continue; }
if (old_bag->GetItem(bag_slot)->GetItem()->Size > new_bag->GetItem()->BagSize) {
Log.Out(Logs::General, Logs::Inventory, "Copy Bag Contents: Failure due to %s is larger than size capacity of %s (%i > %i)",
old_bag->GetItem(bag_slot)->GetItem()->Name, new_bag->GetItem()->Name, old_bag->GetItem(bag_slot)->GetItem()->Size, new_bag->GetItem()->BagSize);
return false;
}
}
for (auto bag_slot = 0; bag_slot < old_bag->GetItem()->BagSlots; ++bag_slot) {
if (!old_bag->GetItem(bag_slot)) { continue; }
new_bag->PutItem(bag_slot, *(old_bag->GetItem(bag_slot)));
}
return true;
}
void Client::DisenchantSummonedBags(bool client_update)
{
for (auto slot_id = EmuConstants::GENERAL_BEGIN; slot_id <= EmuConstants::GENERAL_END; ++slot_id) {
auto inst = m_inv[slot_id];
if (!inst) { continue; }
if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; }
if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; }
if (inst->GetTotalItemCount() == 1) { continue; }
auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots);
if (!new_id) { continue; }
auto new_item = database.GetItem(new_id);
if (!new_item) { continue; }
auto new_inst = database.CreateBaseItem(new_item);
if (!new_inst) { continue; }
if (CopyBagContents(new_inst, inst)) {
Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id);
PutItemInInventory(slot_id, *new_inst, client_update);
}
safe_delete(new_inst);
}
for (auto slot_id = EmuConstants::BANK_BEGIN; slot_id <= EmuConstants::BANK_END; ++slot_id) {
auto inst = m_inv[slot_id];
if (!inst) { continue; }
if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; }
if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; }
if (inst->GetTotalItemCount() == 1) { continue; }
auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots);
if (!new_id) { continue; }
auto new_item = database.GetItem(new_id);
if (!new_item) { continue; }
auto new_inst = database.CreateBaseItem(new_item);
if (!new_inst) { continue; }
if (CopyBagContents(new_inst, inst)) {
Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id);
PutItemInInventory(slot_id, *new_inst, client_update);
}
safe_delete(new_inst);
}
for (auto slot_id = EmuConstants::SHARED_BANK_BEGIN; slot_id <= EmuConstants::SHARED_BANK_END; ++slot_id) {
auto inst = m_inv[slot_id];
if (!inst) { continue; }
if (!IsSummonedBagID(inst->GetItem()->ID)) { continue; }
if (inst->GetItem()->ItemClass != ItemClassContainer) { continue; }
if (inst->GetTotalItemCount() == 1) { continue; }
auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots);
if (!new_id) { continue; }
auto new_item = database.GetItem(new_id);
if (!new_item) { continue; }
auto new_inst = database.CreateBaseItem(new_item);
if (!new_inst) { continue; }
if (CopyBagContents(new_inst, inst)) {
Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, slot_id);
PutItemInInventory(slot_id, *new_inst, client_update);
}
safe_delete(new_inst);
}
while (!m_inv.CursorEmpty()) {
auto inst = m_inv[MainCursor];
if (!inst) { break; }
if (!IsSummonedBagID(inst->GetItem()->ID)) { break; }
if (inst->GetItem()->ItemClass != ItemClassContainer) { break; }
if (inst->GetTotalItemCount() == 1) { break; }
auto new_id = GetDisenchantedBagID(inst->GetItem()->BagSlots);
if (!new_id) { break; }
auto new_item = database.GetItem(new_id);
if (!new_item) { break; }
auto new_inst = database.CreateBaseItem(new_item);
if (!new_inst) { break; }
if (CopyBagContents(new_inst, inst)) {
Log.Out(Logs::General, Logs::Inventory, "Disenchant Summoned Bags: Replacing %s with %s in slot %i", inst->GetItem()->Name, new_inst->GetItem()->Name, MainCursor);
std::list<ItemInst*> local;
local.push_front(new_inst);
m_inv.PopItem(MainCursor);
safe_delete(inst);
while (!m_inv.CursorEmpty()) {
auto limbo_inst = m_inv.PopItem(MainCursor);
if (limbo_inst == nullptr) { continue; }
local.push_back(limbo_inst);
}
for (auto iter = local.begin(); iter != local.end(); ++iter) {
auto cur_inst = *iter;
if (cur_inst == nullptr) { continue; }
m_inv.PushCursor(*cur_inst);
safe_delete(cur_inst);
}
local.clear();
auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend();
database.SaveCursor(this->CharacterID(), s, e);
}
else {
safe_delete(new_inst); // deletes disenchanted bag if not used
}
break;
}
}
void Client::RemoveNoRent(bool client_update)
{
for (auto slot_id = EmuConstants::EQUIPMENT_BEGIN; slot_id <= EmuConstants::EQUIPMENT_END; ++slot_id) {

13
zone/lua_encounter.cpp Normal file
View File

@ -0,0 +1,13 @@
#ifdef LUA_EQEMU
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include "lua_encounter.h"
#include "encounter.h"
luabind::scope lua_register_encounter() {
return luabind::class_<Lua_Encounter>("Encounter");
}
#endif

30
zone/lua_encounter.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef EQEMU_LUA_ENCOUNTER_H
#define EQEMU_LUA_ENCOUNTER_H
#ifdef LUA_EQEMU
#include "lua_ptr.h"
class Encounter;
namespace luabind {
struct scope;
class object;
}
luabind::scope lua_register_encounter();
class Lua_Encounter : public Lua_Ptr<Encounter>
{
typedef Encounter NativeType;
public:
Lua_Encounter() { SetLuaPtrData(nullptr); }
Lua_Encounter(Encounter *d) { SetLuaPtrData(reinterpret_cast<Encounter*>(d)); }
virtual ~Lua_Encounter() { }
operator Encounter*() {
return reinterpret_cast<Encounter*>(GetLuaPtrData());
}
};
#endif
#endif

View File

@ -19,6 +19,7 @@
#include "../common/timer.h"
#include "../common/eqemu_logsys.h"
#include "encounter.h"
#include "lua_encounter.h"
struct Events { };
struct Factions { };
@ -296,6 +297,10 @@ void lua_set_timer(const char *timer, int time_ms, Lua_Mob mob) {
quest_manager.settimerMS(timer, time_ms, mob);
}
void lua_set_timer(const char *timer, int time_ms, Lua_Encounter enc) {
quest_manager.settimerMS(timer, time_ms, enc);
}
void lua_stop_timer(const char *timer) {
quest_manager.stoptimer(timer);
}
@ -308,6 +313,10 @@ void lua_stop_timer(const char *timer, Lua_Mob mob) {
quest_manager.stoptimer(timer, mob);
}
void lua_stop_timer(const char *timer, Lua_Encounter enc) {
quest_manager.stoptimer(timer, enc);
}
void lua_stop_all_timers() {
quest_manager.stopalltimers();
}
@ -320,6 +329,10 @@ void lua_stop_all_timers(Lua_Mob mob) {
quest_manager.stopalltimers(mob);
}
void lua_stop_all_timers(Lua_Encounter enc) {
quest_manager.stopalltimers(enc);
}
void lua_depop() {
quest_manager.depop(0);
}
@ -1457,12 +1470,15 @@ luabind::scope lua_register_general() {
luabind::def("set_timer", (void(*)(const char*, int))&lua_set_timer),
luabind::def("set_timer", (void(*)(const char*, int, Lua_ItemInst))&lua_set_timer),
luabind::def("set_timer", (void(*)(const char*, int, Lua_Mob))&lua_set_timer),
luabind::def("set_timer", (void(*)(const char*, int, Lua_Encounter))&lua_set_timer),
luabind::def("stop_timer", (void(*)(const char*))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(const char*, Lua_ItemInst))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(const char*, Lua_Mob))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(const char*, Lua_Encounter))&lua_stop_timer),
luabind::def("stop_all_timers", (void(*)(void))&lua_stop_all_timers),
luabind::def("stop_all_timers", (void(*)(Lua_ItemInst))&lua_stop_all_timers),
luabind::def("stop_all_timers", (void(*)(Lua_Mob))&lua_stop_all_timers),
luabind::def("stop_all_timers", (void(*)(Lua_Encounter))&lua_stop_all_timers),
luabind::def("depop", (void(*)(void))&lua_depop),
luabind::def("depop", (void(*)(int))&lua_depop),
luabind::def("depop_with_timer", (void(*)(void))&lua_depop_with_timer),

View File

@ -34,6 +34,7 @@
#include "questmgr.h"
#include "zone.h"
#include "lua_parser.h"
#include "lua_encounter.h"
const char *LuaEvents[_LargestEventID] = {
"event_say",
@ -610,10 +611,11 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
lua_pushstring(L, encounter_name.c_str());
lua_setfield(L, -2, "name");
auto arg_function = EncounterArgumentDispatch[evt];
arg_function(this, L, data, extra_data, extra_pointers);
Encounter *enc = lua_encounters[encounter_name];
auto arg_function = EncounterArgumentDispatch[evt];
arg_function(this, L, enc, data, extra_data, extra_pointers);
quest_manager.StartQuest(enc, nullptr, nullptr, encounter_name);
if(lua_pcall(L, 1, 1, 0)) {
std::string error = lua_tostring(L, -1);
@ -977,6 +979,7 @@ void LuaParser::MapFunctions(lua_State *L) {
lua_register_client_version(),
lua_register_appearance(),
lua_register_entity(),
lua_register_encounter(),
lua_register_mob(),
lua_register_special_abilities(),
lua_register_npc(),

View File

@ -22,6 +22,7 @@
#include "lua_door.h"
#include "lua_object.h"
#include "lua_packet.h"
#include "lua_encounter.h"
#include "zone.h"
#include "lua_parser_events.h"
@ -704,14 +705,20 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl
std::vector<EQEmu::Any> *extra_pointers) {
}
void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_timer(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
if (encounter) {
Lua_Encounter l_enc(encounter);
luabind::adl::object l_enc_o = luabind::adl::object(L, l_enc);
l_enc_o.push(L);
lua_setfield(L, -2, "encounter");
}
if (extra_pointers) {
std::string *str = EQEmu::any_cast<std::string*>(extra_pointers->at(0));
lua_pushstring(L, str->c_str());
@ -719,7 +726,7 @@ void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data
}
}
void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_unload(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
if (extra_pointers) {
std::string *str = EQEmu::any_cast<std::string*>(extra_pointers->at(0));
@ -728,7 +735,7 @@ void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string da
}
}
void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_null(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
}

View File

@ -6,7 +6,7 @@ typedef void(*NPCArgumentHandler)(QuestInterface*, lua_State*, NPC*, Mob*, std::
typedef void(*PlayerArgumentHandler)(QuestInterface*, lua_State*, Client*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*ItemArgumentHandler)(QuestInterface*, lua_State*, Client*, ItemInst*, Mob*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*SpellArgumentHandler)(QuestInterface*, lua_State*, NPC*, Client*, uint32, uint32, std::vector<EQEmu::Any>*);
typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, std::string, uint32, std::vector<EQEmu::Any>*);
typedef void(*EncounterArgumentHandler)(QuestInterface*, lua_State*, Encounter* encounter, std::string, uint32, std::vector<EQEmu::Any>*);
//NPC
void handle_npc_event_say(QuestInterface *parse, lua_State* L, NPC* npc, Mob *init, std::string data, uint32 extra_data,
@ -130,13 +130,13 @@ void handle_spell_null(QuestInterface *parse, lua_State* L, NPC* npc, Client* cl
//Encounter
void handle_encounter_timer(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_timer(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_encounter_load(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_load(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_encounter_unload(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_unload(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
void handle_encounter_null(QuestInterface *parse, lua_State* L, std::string data, uint32 extra_data,
void handle_encounter_null(QuestInterface *parse, lua_State* L, Encounter* encounter, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
#endif

View File

@ -1266,7 +1266,7 @@ void Mob::CreateHPPacket(EQApplicationPacket* app)
}
// sends hp update of this mob to people who might care
void Mob::SendHPUpdate()
void Mob::SendHPUpdate(bool skip_self)
{
EQApplicationPacket hp_app;
Group *group;
@ -1355,8 +1355,7 @@ void Mob::SendHPUpdate()
}
// send to self - we need the actual hps here
if(IsClient())
{
if(IsClient() && !skip_self) {
EQApplicationPacket* hp_app2 = new EQApplicationPacket(OP_HPUpdate,sizeof(SpawnHPUpdate_Struct));
SpawnHPUpdate_Struct* ds = (SpawnHPUpdate_Struct*)hp_app2->pBuffer;
ds->cur_hp = CastToClient()->GetHP() - itembonuses.HP;
@ -1365,6 +1364,7 @@ void Mob::SendHPUpdate()
CastToClient()->QueuePacket(hp_app2);
safe_delete(hp_app2);
}
ResetHPUpdateTimer(); // delay the timer
}
// this one just warps the mob to the current location
@ -4205,25 +4205,25 @@ int32 Mob::GetItemStat(uint32 itemid, const char *identifier)
std::string Mob::GetGlobal(const char *varname) {
int qgCharid = 0;
int qgNpcid = 0;
if (this->IsNPC())
qgNpcid = this->GetNPCTypeID();
if (this->IsClient())
qgCharid = this->CastToClient()->CharacterID();
QGlobalCache *qglobals = nullptr;
std::list<QGlobal> globalMap;
if (this->IsClient())
qglobals = this->CastToClient()->GetQGlobals();
if (this->IsNPC())
qglobals = this->CastToNPC()->GetQGlobals();
if(qglobals)
QGlobalCache::Combine(globalMap, qglobals->GetBucket(), qgNpcid, qgCharid, zone->GetZoneID());
std::list<QGlobal>::iterator iter = globalMap.begin();
while(iter != globalMap.end()) {
if ((*iter).name.compare(varname) == 0)
@ -4231,7 +4231,7 @@ std::string Mob::GetGlobal(const char *varname) {
++iter;
}
return "Undefined";
}

View File

@ -508,7 +508,8 @@ public:
static void CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns);
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
void CreateHPPacket(EQApplicationPacket* app);
void SendHPUpdate();
void SendHPUpdate(bool skip_self = false);
virtual void ResetHPUpdateTimer() {}; // does nothing
//Util
static uint32 RandomTimer(int min, int max);

View File

@ -115,7 +115,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if
knightattack_timer(1000),
assist_timer(AIassistcheck_delay),
qglobal_purge_timer(30000),
sendhpupdate_timer(1000),
sendhpupdate_timer(2000),
enraged_timer(1000),
taunt_timer(TauntReuseTime * 1000),
m_SpawnPoint(position),
@ -650,7 +650,8 @@ bool NPC::Process()
}
}
if (sendhpupdate_timer.Check() && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) {
// we might actually want to reset in this check ... won't until issues arise at least :P
if (sendhpupdate_timer.Check(false) && (IsTargeted() || (IsPet() && GetOwner() && GetOwner()->IsClient()))) {
if(!IsFullHP || cur_hp<max_hp){
SendHPUpdate();
}

View File

@ -407,6 +407,7 @@ public:
void SetHeroForgeModel(uint32 model) { herosforgemodel = model; }
bool IsRaidTarget() const { return raid_target; };
void ResetHPUpdateTimer() { sendhpupdate_timer.Start(); }
protected: