mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 06:21:28 +00:00
Merge branch 'master' into aa
This commit is contained in:
commit
6515879c14
@ -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
|
||||
|
||||
@ -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 )
|
||||
|
||||
@ -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.');
|
||||
|
||||
@ -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.');
|
||||
@ -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.');
|
||||
@ -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
|
||||
|
||||
@ -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...
|
||||
|
||||
22
zone/bot.cpp
22
zone/bot.cpp
@ -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();
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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
13
zone/lua_encounter.cpp
Normal 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
30
zone/lua_encounter.h
Normal 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
|
||||
@ -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),
|
||||
|
||||
@ -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(),
|
||||
|
||||
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
20
zone/mob.cpp
20
zone/mob.cpp
@ -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";
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -407,6 +407,7 @@ public:
|
||||
void SetHeroForgeModel(uint32 model) { herosforgemodel = model; }
|
||||
|
||||
bool IsRaidTarget() const { return raid_target; };
|
||||
void ResetHPUpdateTimer() { sendhpupdate_timer.Start(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user