Merge from master

This commit is contained in:
KimLS
2015-02-05 23:24:51 -08:00
63 changed files with 740 additions and 263 deletions
+6 -4
View File
@@ -1584,10 +1584,12 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes att
//this generates a lot of 'updates' to the client that the client does not need
BuffFadeNonPersistDeath();
if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
UnmemSpellAll(true);
else
UnmemSpellAll(false);
if (RuleB(Character, UnmemSpellsOnDeath)) {
if((GetClientVersionBit() & BIT_SoFAndLater) && RuleB(Character, RespawnFromHover))
UnmemSpellAll(true);
else
UnmemSpellAll(false);
}
if((RuleB(Character, LeaveCorpses) && GetLevel() >= RuleI(Character, DeathItemLossLevel)) || RuleB(Character, LeaveNakedCorpses))
{
+11 -6
View File
@@ -411,11 +411,11 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
newbon->DSMitigation += item->DSMitigation;
}
if (item->Worn.Effect>0 && (item->Worn.Type == ET_WornEffect)) { // latent effects
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true);
ApplySpellsBonuses(item->Worn.Effect, item->Worn.Level, newbon, 0, true, true);
}
if (item->Focus.Effect>0 && (item->Focus.Type == ET_Focus)) { // focus effects
ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true);
ApplySpellsBonuses(item->Focus.Effect, item->Focus.Level, newbon, 0, true, false);
}
switch(item->BardType)
@@ -639,7 +639,7 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
uint8 focus = IsFocusEffect(0, 0, true,effect);
if (focus)
{
newbon->FocusEffects[focus] = effect;
newbon->FocusEffects[focus] = static_cast<uint8>(effect);
continue;
}
@@ -1393,7 +1393,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
int buff_count = GetMaxTotalSlots();
for(i = 0; i < buff_count; i++) {
if(buffs[i].spellid != SPELL_UNKNOWN){
ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, buffs[i].ticsremaining,i);
ApplySpellsBonuses(buffs[i].spellid, buffs[i].casterlevel, newbon, buffs[i].casterid, false, false, buffs[i].ticsremaining,i);
if (buffs[i].numhits > 0)
Numhits(true);
@@ -1416,7 +1416,7 @@ void Mob::CalcSpellBonuses(StatBonuses* newbon)
if (GetClass() == BARD) newbon->ManaRegen = 0; // Bards do not get mana regen from spells.
}
void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, bool item_bonus, uint32 ticsremaining, int buffslot,
void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* new_bonus, uint16 casterId, bool item_bonus, bool IsWornEffect, uint32 ticsremaining, int buffslot,
bool IsAISpellEffect, uint16 effect_id, int32 se_base, int32 se_limit, int32 se_max)
{
int i, effect_value, base2, max, effectid;
@@ -1439,7 +1439,12 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
uint8 focus = IsFocusEffect(spell_id, i);
if (focus)
{
new_bonus->FocusEffects[focus] = spells[spell_id].effectid[i];
if (!IsWornEffect)
new_bonus->FocusEffects[focus] = static_cast<uint8>(spells[spell_id].effectid[i]);
else if (RuleB(Spells, UseAdditiveFocusFromWornSlot))
new_bonus->FocusEffectsWorn[focus] += spells[spell_id].base[i];
continue;
}
+77 -35
View File
@@ -7516,7 +7516,6 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
int32 npc_value[MAX_NPC_FACTIONS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8 temp[MAX_NPC_FACTIONS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int32 current_value;
bool change = false;
// Get the npc faction list
if (!database.GetNPCFactionList(npc_id, faction_id, npc_value, temp))
@@ -7525,43 +7524,81 @@ void Client::SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, ui
{
int32 faction_before_hit;
int32 faction_to_use_for_messaging;
FactionMods fm;
int32 this_faction_max;
int32 this_faction_min;
if (faction_id[i] <= 0)
continue;
// Find out starting faction for this faction
// It needs to be used to adj max and min personal
// The range is still the same, 1200-3000(4200), but adjusted for base
database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(),
faction_id[i]);
// Adjust the amount you can go up or down so the resulting range
// is PERSONAL_MAX - PERSONAL_MIN
//
// Adjust these values for cases where starting faction is below
// min or above max by not allowing any earn in those directions.
this_faction_min = MIN_PERSONAL_FACTION - fm.base;
this_faction_min = std::min(0, this_faction_min);
this_faction_max = MAX_PERSONAL_FACTION - fm.base;
this_faction_max = std::max(0, this_faction_max);
// Get the characters current value with that faction
current_value = GetCharacterFactionLevel(faction_id[i]);
faction_before_hit = current_value;
change = UpdatePersonalFaction(char_id, npc_value[i], faction_id[i], &current_value, temp[i]);
UpdatePersonalFaction(char_id, npc_value[i], faction_id[i], &current_value, temp[i], this_faction_min, this_faction_max);
if (change)
{
SendFactionMessage(npc_value[i], faction_id[i], faction_before_hit, current_value, temp[i]);
}
//Message(14, "Min(%d) Max(%d) Before(%d), After(%d)\n", this_faction_min, this_faction_max, faction_before_hit, current_value);
SendFactionMessage(npc_value[i], faction_id[i], faction_before_hit, current_value, temp[i], this_faction_min, this_faction_max);
}
return;
}
void Client::SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp)
{
int32 current_value;
bool change=false;
//Get the npc faction list
if(faction_id > 0 && value != 0) {
int32 faction_before_hit;
FactionMods fm;
int32 this_faction_max;
int32 this_faction_min;
// Find out starting faction for this faction
// It needs to be used to adj max and min personal
// The range is still the same, 1200-3000(4200), but adjusted for base
database.GetFactionData(&fm, GetClass(), GetRace(), GetDeity(),
faction_id);
// Adjust the amount you can go up or down so the resulting range
// is PERSONAL_MAX - PERSONAL_MIN
//
// Adjust these values for cases where starting faction is below
// min or above max by not allowing any earn/loss in those directions.
// At least one faction starts out way below min, so we don't want
// to allow loses in those cases, just massive gains.
this_faction_min = MIN_PERSONAL_FACTION - fm.base;
this_faction_min = std::min(0, this_faction_min);
this_faction_max = MAX_PERSONAL_FACTION - fm.base;
this_faction_max = std::max(0, this_faction_max);
//Get the faction modifiers
current_value = GetCharacterFactionLevel(faction_id);
faction_before_hit = current_value;
change = UpdatePersonalFaction(char_id, value, faction_id, &current_value, temp);
UpdatePersonalFaction(char_id, value, faction_id, &current_value, temp, this_faction_min, this_faction_max);
if (change)
{
SendFactionMessage(value, faction_id, faction_before_hit, current_value, temp);
}
//Message(14, "Min(%d) Max(%d) Before(%d), After(%d)\n", this_faction_min, this_faction_max, faction_before_hit, current_value);
SendFactionMessage(value, faction_id, faction_before_hit, current_value, temp, this_faction_min, this_faction_max);
}
return;
@@ -7583,7 +7620,7 @@ int32 Client::GetCharacterFactionLevel(int32 faction_id)
// Checks for bottom out and max faction and old faction db entries
// Updates the faction if we are not minned, maxed or we need to repair
bool Client::UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp)
void Client::UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max)
{
bool repair = false;
bool change = false;
@@ -7601,33 +7638,38 @@ bool Client::UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction
npc_value *= 2;
}
}
// Set flag when to update db
if (*current_value > MAX_PERSONAL_FACTION)
// Repair needed, as db changes could modify a base value for a faction
// and we need to auto correct when that happens.
if (*current_value > this_faction_max)
{
*current_value = MAX_PERSONAL_FACTION;
*current_value = this_faction_max;
repair = true;
}
else if (*current_value < MIN_PERSONAL_FACTION)
else if (*current_value < this_faction_min)
{
*current_value = MIN_PERSONAL_FACTION;
*current_value = this_faction_min;
repair = true;
}
else if ((m_pp.gm != 1) && (npc_value != 0) && ((*current_value != MAX_PERSONAL_FACTION) || (*current_value != MIN_PERSONAL_FACTION)))
else if ((m_pp.gm != 1) && (npc_value != 0) &&
((npc_value > 0 && *current_value != this_faction_max) ||
((npc_value < 0 && *current_value != this_faction_min))))
change = true;
*current_value += npc_value;
if (*current_value > MAX_PERSONAL_FACTION)
*current_value = MAX_PERSONAL_FACTION;
else if (*current_value < MIN_PERSONAL_FACTION)
*current_value = MIN_PERSONAL_FACTION;
if (change || repair)
{
*current_value += npc_value;
if (*current_value > this_faction_max)
*current_value = this_faction_max;
else if (*current_value < this_faction_min)
*current_value = this_faction_min;
database.SetCharacterFactionLevel(char_id, faction_id, *current_value, temp, factionvalues);
}
return (repair || change);
return;
}
// returns the character's faction level, adjusted for racial, class, and deity modifiers
@@ -7708,21 +7750,21 @@ void Client::MerchantRejectMessage(Mob *merchant, int primaryfaction)
//o--------------------------------------------------------------
//| Purpose: Send faction change message to client
//o--------------------------------------------------------------
void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp)
void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max)
{
char name[50];
int32 faction_value;
// If we're dropping from MAX or raising from MIN, we should
// base the message on the new updated value so we don't show
// If we're dropping from MAX or raising from MIN or repairing,
// we should base the message on the new updated value so we don't show
// a min MAX message
//
// If we're changing any other place, we use the value before the
// hit. For example, if we go from 1199 to 1200 which is the MAX
// we still want to say faction got better this time around.
if ( (faction_before_hit == MAX_PERSONAL_FACTION) ||
(faction_before_hit == MIN_PERSONAL_FACTION))
if ( (faction_before_hit >= this_faction_max) ||
(faction_before_hit <= this_faction_min))
faction_value = totalvalue;
else
faction_value = faction_before_hit;
@@ -7733,13 +7775,13 @@ void Client::SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_
if (tmpvalue == 0 || temp == 1 || temp == 2)
return;
else if (faction_value >= MAX_PERSONAL_FACTION)
else if (faction_value >= this_faction_max)
Message_StringID(15, FACTION_BEST, name);
else if (faction_value <= MIN_PERSONAL_FACTION)
else if (faction_value <= this_faction_min)
Message_StringID(15, FACTION_WORST, name);
else if (tmpvalue > 0 && faction_value < MAX_PERSONAL_FACTION && !RuleB(Client, UseLiveFactionMessage))
else if (tmpvalue > 0 && faction_value < this_faction_max && !RuleB(Client, UseLiveFactionMessage))
Message_StringID(15, FACTION_BETTER, name);
else if (tmpvalue < 0 && faction_value > MIN_PERSONAL_FACTION && !RuleB(Client, UseLiveFactionMessage))
else if (tmpvalue < 0 && faction_value > this_faction_min && !RuleB(Client, UseLiveFactionMessage))
Message_StringID(15, FACTION_WORSE, name);
else if (RuleB(Client, UseLiveFactionMessage))
Message(15, "Your faction standing with %s has been adjusted by %i.", name, tmpvalue); //New Live faction message (14261)
+2 -2
View File
@@ -607,9 +607,9 @@ public:
int32 GetCharacterFactionLevel(int32 faction_id);
int32 GetModCharacterFactionLevel(int32 faction_id);
void MerchantRejectMessage(Mob *merchant, int primaryfaction);
void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp);
void SendFactionMessage(int32 tmpvalue, int32 faction_id, int32 faction_before_hit, int32 totalvalue, uint8 temp, int32 this_faction_min, int32 this_faction_max);
bool UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp);
void UpdatePersonalFaction(int32 char_id, int32 npc_value, int32 faction_id, int32 *current_value, int32 temp, int32 this_faction_min, int32 this_faction_max);
void SetFactionLevel(uint32 char_id, uint32 npc_id, uint8 char_class, uint8 char_race, uint8 char_deity);
void SetFactionLevel2(uint32 char_id, int32 faction_id, uint8 char_class, uint8 char_race, uint8 char_deity, int32 value, uint8 temp);
int32 GetRawItemAC();
+19 -16
View File
@@ -398,12 +398,18 @@ void ClearMappedOpcode(EmuOpcode op)
// client methods
int Client::HandlePacket(const EQApplicationPacket *app)
{
if(Log.log_settings[Logs::LogCategory::Netcode].log_to_console > 0) {
if (Log.log_settings[Logs::LogCategory::Netcode].is_category_enabled == 1) {
char buffer[64];
app->build_header_dump(buffer);
Log.Out(Logs::Detail, Logs::Client_Server_Packet, "Dispatch opcode: %s", buffer);
}
if (Log.log_settings[Logs::Client_Server_Packet].is_category_enabled == 1)
Log.Out(Logs::General, Logs::Client_Server_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size());
if (Log.log_settings[Logs::Client_Server_Packet_With_Dump].is_category_enabled == 1)
Log.Out(Logs::General, Logs::Client_Server_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode(), app->Size(), DumpPacketToString(app).c_str());
EmuOpcode opcode = app->GetOpcode();
if (opcode == OP_AckPacket) {
return true;
@@ -445,23 +451,16 @@ int Client::HandlePacket(const EQApplicationPacket *app)
case CLIENT_CONNECTED: {
ClientPacketProc p;
p = ConnectedOpcodes[opcode];
if(p == nullptr) {
if(p == nullptr) {
std::vector<EQEmu::Any> args;
args.push_back(const_cast<EQApplicationPacket*>(app));
parse->EventPlayer(EVENT_UNHANDLED_OPCODE, this, "", 0, &args);
char buffer[64];
Log.Out(Logs::Detail, Logs::Client_Server_Packet, "Unhandled incoming opcode: %s - 0x%04x", OpcodeManager::EmuToName(app->GetOpcode()), app->GetOpcode());
if (Log.log_settings[Logs::Client_Server_Packet].log_to_console > 0){
if (Log.log_settings[Logs::Client_Server_Packet_Unhandled].is_category_enabled == 1){
char buffer[64];
app->build_header_dump(buffer);
if (app->size < 1000)
DumpPacket(app, app->size);
else{
std::cout << "Dump limited to 1000 characters:\n";
DumpPacket(app, 1000);
}
Log.Out(Logs::General, Logs::Client_Server_Packet_Unhandled, "%s %s", buffer, DumpPacketToString(app).c_str());
}
break;
}
@@ -1392,6 +1391,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
if (RuleB(Character, SharedBankPlat))
m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID());
database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
@@ -5516,7 +5516,7 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
if (damage < 0)
damage = 31337;
if (admin >= minStatusToAvoidFalling && GetGM()){
if (admin >= minStatusToAvoidFalling && GetGM()) {
Message(13, "Your GM status protects you from %i points of type %i environmental damage.", ed->damage, ed->dmgtype);
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
return;
@@ -5526,11 +5526,11 @@ void Client::Handle_OP_EnvDamage(const EQApplicationPacket *app)
SetHP(GetHP() - 1);//needed or else the client wont acknowledge
return;
}
else if (zone->GetZoneID() == 183 || zone->GetZoneID() == 184){
else if (zone->GetZoneID() == 183 || zone->GetZoneID() == 184) {
// Hard coded tutorial and load zones for no fall damage
return;
}
else{
else {
SetHP(GetHP() - (damage * RuleR(Character, EnvironmentDamageMulipliter)));
/* EVENT_ENVIRONMENTAL_DAMAGE */
@@ -9862,6 +9862,9 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
return;
}
if (mypet->GetPetType() == petTargetLock && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST))
return;
if (mypet->GetPetType() == petAnimation && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST) && !GetAA(aaAnimationEmpathy))
return;
+9
View File
@@ -10591,6 +10591,15 @@ void command_logs(Client *c, const Seperator *sep){
c->Message(15, "Your Log Settings have been applied");
c->Message(15, "Output Method: %s :: Debug Level: %i - Category: %s", sep->arg[2], atoi(sep->arg[4]), Logs::LogCategoryName[atoi(sep->arg[3])]);
}
/* We use a general 'is_category_enabled' now, let's update when we update any output settings
This is used in hot places of code to check if its enabled in any way before triggering logs
*/
if (sep->arg[4] > 0){
Log.log_settings[atoi(sep->arg[3])].is_category_enabled = 1;
}
else{
Log.log_settings[atoi(sep->arg[3])].is_category_enabled = 0;
}
}
}
else {
+3 -2
View File
@@ -350,7 +350,8 @@ struct StatBonuses {
int32 CharmBreakChance; // chance to break charm
int32 SongRange; // increases range of beneficial bard songs
uint32 HPToManaConvert; // Uses HP to cast spells at specific conversion
uint32 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
uint8 FocusEffects[HIGHEST_FOCUS+1]; // Stores the focus effectid for each focustype you have.
int16 FocusEffectsWorn[HIGHEST_FOCUS+1]; // Optional to allow focus effects to be applied additively from worn slot
bool NegateEffects; // Check if you contain a buff with negate effect. (only spellbonuses)
int32 SkillDamageAmount2[HIGHEST_SKILL+2]; // Adds skill specific damage
uint32 NegateAttacks[3]; // 0 = bool HasEffect 1 = Buff Slot 2 = Max damage absorbed per hit
@@ -505,7 +506,7 @@ typedef enum {
petOther,
petCharmed,
petNPCFollow,
petHatelist //remain active as long something is on the hatelist. Don't listen to any commands
petTargetLock //remain active as long something is on the hatelist. Don't listen to any commands
} PetType;
typedef enum {
+6 -1
View File
@@ -965,6 +965,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
Save();
}
auto timestamps = database.GetItemRecastTimestamps(client->CharacterID());
outapp->priority = 6;
client->QueuePacket(outapp);
safe_delete(outapp);
@@ -973,6 +974,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
const Item_Struct* item = database.GetItem(pkitem);
ItemInst* inst = database.CreateItem(item, item->MaxCharges);
if(inst) {
if (item->RecastDelay)
inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
client->SendItemPacket(EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
safe_delete(inst);
}
@@ -1004,6 +1007,8 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
if(client && item) {
ItemInst* inst = database.CreateItem(item, item_data->charges, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned);
if(inst) {
if (item->RecastDelay)
inst->SetRecastTimestamp(timestamps.count(item->RecastType) ? timestamps.at(item->RecastType) : 0);
// MainGeneral1 is the corpse inventory start offset for Ti(EMu) - CORPSE_END = MainGeneral1 + MainCursor
client->SendItemPacket(i + EmuConstants::CORPSE_BEGIN, inst, ItemPacketLoot);
safe_delete(inst);
@@ -1460,4 +1465,4 @@ void Corpse::LoadPlayerCorpseDecayTime(uint32 corpse_db_id){
else {
corpse_graveyard_timer.SetTimer(3000);
}
}
}
+2 -2
View File
@@ -749,9 +749,9 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_
if (bad) {
if (!caster->IsAttackAllowed(curmob, true))
continue;
if (center && !center->CheckLosFN(curmob))
if (center && !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob))
continue;
if (!center && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize()))
if (!center && !spells[spell_id].npc_no_los && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize()))
continue;
} else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies...
// This does not check faction for beneficial AE buffs..only agro and attackable.
+2 -2
View File
@@ -72,8 +72,8 @@ public:
uint32 GetTotalGroupDamage(Mob* other);
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
inline void SetLeader(Mob* newleader){ leader=newleader; };
inline Mob* GetLeader(){ return leader; };
char* GetLeaderName() { return membername[0]; };
inline Mob* GetLeader() { return leader; };
const char* GetLeaderName() { return leader->GetName(); };
void SendHPPacketsTo(Mob* newmember);
void SendHPPacketsFrom(Mob* newmember);
bool UpdatePlayer(Mob* update);
+100 -90
View File
@@ -19,6 +19,7 @@
#include "../common/global_define.h"
#include "../common/loottable.h"
#include "../common/misc_functions.h"
#include "../common/data_verification.h"
#include "client.h"
#include "entity.h"
@@ -35,7 +36,7 @@
// Queries the loottable: adds item & coin to the npc
void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* itemlist, uint32* copper, uint32* silver, uint32* gold, uint32* plat) {
const LootTable_Struct* lts = 0;
const LootTable_Struct* lts = nullptr;
*copper = 0;
*silver = 0;
*gold = 0;
@@ -45,44 +46,39 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
if (!lts)
return;
// do coin
if (lts->mincash > lts->maxcash) {
std::cerr << "Error in loottable #" << loottable_id << ": mincash > maxcash" << std::endl;
uint32 min_cash = lts->mincash;
uint32 max_cash = lts->maxcash;
if(min_cash > max_cash) {
uint32 t = min_cash;
min_cash = max_cash;
max_cash = t;
}
else if (lts->maxcash != 0) {
uint32 cash = 0;
if (lts->mincash == lts->maxcash)
cash = lts->mincash;
else
cash = zone->random.Int(lts->mincash, lts->maxcash);
if (cash != 0) {
if (lts->avgcoin != 0) {
//this is some crazy ass stuff... and makes very little sense... dont use it, k?
uint32 mincoin = (uint32) (lts->avgcoin * 0.75 + 1);
uint32 maxcoin = (uint32) (lts->avgcoin * 1.25 + 1);
*copper = zone->random.Int(mincoin, maxcoin);
*silver = zone->random.Int(mincoin, maxcoin);
*gold = zone->random.Int(mincoin, maxcoin);
if(*copper > cash) { *copper = cash; }
cash -= *copper;
if(*silver>(cash/10)) { *silver = (cash/10); }
cash -= *silver*10;
if(*gold > (cash/100)) { *gold = (cash/100); }
cash -= *gold*100;
}
if (cash < 0) {
cash = 0;
}
*plat = cash / 1000;
cash -= *plat * 1000;
uint32 gold2 = cash / 100;
cash -= gold2 * 100;
uint32 silver2 = cash / 10;
cash -= silver2 * 10;
*gold += gold2;
*silver += silver2;
*copper += cash;
uint32 cash = 0;
if(max_cash > 0 && lts->avgcoin > 0 && EQEmu::ValueWithin(lts->avgcoin, min_cash, max_cash)) {
float upper_chance = (float)(lts->avgcoin - min_cash) / (float)(max_cash - min_cash);
float avg_cash_roll = (float)zone->random.Real(0.0, 1.0);
if(avg_cash_roll < upper_chance) {
cash = zone->random.Int(lts->avgcoin, max_cash);
} else {
cash = zone->random.Int(min_cash, lts->avgcoin);
}
} else {
cash = zone->random.Int(min_cash, max_cash);
}
if(cash != 0) {
*plat = cash / 1000;
cash -= *plat * 1000;
*gold = cash / 100;
cash -= *gold * 100;
*silver = cash / 10;
cash -= *silver * 10;
*copper = cash;
}
// Do items
@@ -97,11 +93,11 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite
float drop_chance = 0.0f;
if(ltchance > 0.0 && ltchance < 100.0) {
drop_chance = zone->random.Real(0.0, 100.0);
drop_chance = (float)zone->random.Real(0.0, 100.0);
}
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance < ltchance)) {
AddLootDropToNPC(npc,lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
if (ltchance != 0.0 && (ltchance == 100.0 || drop_chance <= ltchance)) {
AddLootDropToNPC(npc, lts->Entries[i].lootdrop_id, itemlist, droplimit, mindrop);
}
}
}
@@ -114,63 +110,76 @@ void ZoneDatabase::AddLootDropToNPC(NPC* npc,uint32 lootdrop_id, ItemList* iteml
if (!lds) {
return;
}
if(lds->NumEntries == 0) //nothing possible to add
if(lds->NumEntries == 0)
return;
// Too long a list needs to be limited.
if(lds->NumEntries > 99 && droplimit < 1)
droplimit = lds->NumEntries/100;
uint8 limit = 0;
// Start at a random point in itemlist.
uint32 item = zone->random.Int(0, lds->NumEntries-1);
// Main loop.
for (uint32 i=0; i<lds->NumEntries;)
{
//Force the itemlist back to beginning.
if (item > (lds->NumEntries-1))
item = 0;
uint8 charges = lds->Entries[item].multiplier;
uint8 pickedcharges = 0;
// Loop to check multipliers.
for (uint32 x=1; x<=charges; x++)
{
// Actual roll.
float thischance = 0.0;
thischance = lds->Entries[item].chance;
float drop_chance = 0.0;
if(thischance != 100.0)
drop_chance = zone->random.Real(0.0, 100.0);
#if EQDEBUG>=11
Log.Out(Logs::General, Logs::None, "Drop chance for npc: %s, this chance:%f, drop roll:%f", npc->GetName(), thischance, drop_chance);
#endif
if (thischance == 100.0 || drop_chance < thischance)
{
uint32 itemid = lds->Entries[item].item_id;
const Item_Struct* dbitem = GetItem(itemid);
npc->AddLootDrop(dbitem, itemlist, lds->Entries[item].item_charges, lds->Entries[item].minlevel, lds->Entries[item].maxlevel, lds->Entries[item].equip_item, false);
pickedcharges++;
if(droplimit == 0 && mindrop == 0) {
for(uint32 i = 0; i < lds->NumEntries; ++i) {
int charges = lds->Entries[i].multiplier;
for(int j = 0; j < charges; ++j) {
if(zone->random.Real(0.0, 100.0) <= lds->Entries[i].chance) {
const Item_Struct* dbitem = GetItem(lds->Entries[i].item_id);
npc->AddLootDrop(dbitem, itemlist, lds->Entries[i].item_charges, lds->Entries[i].minlevel,
lds->Entries[i].maxlevel, lds->Entries[i].equip_item > 0 ? true : false, false);
}
}
}
// Items with multipliers only count as 1 towards the limit.
if(pickedcharges > 0)
limit++;
return;
}
// If true, limit reached.
if(limit >= droplimit && droplimit > 0)
break;
if(lds->NumEntries > 100 && droplimit == 0) {
droplimit = 10;
}
item++;
i++;
if(droplimit < mindrop) {
droplimit = mindrop;
}
// We didn't reach our minimium, run loop again.
if(i == lds->NumEntries){
if(limit < mindrop){
i = 0;
float roll_t = 0.0f;
bool active_item_list = false;
for(uint32 i = 0; i < lds->NumEntries; ++i) {
const Item_Struct* db_item = GetItem(lds->Entries[i].item_id);
if(db_item) {
roll_t += lds->Entries[i].chance;
active_item_list = true;
}
}
roll_t = EQEmu::ClampLower(roll_t, 100.0f);
if(!active_item_list) {
return;
}
mindrop = EQEmu::ClampLower(mindrop, (uint8)1);
int item_count = zone->random.Int(mindrop, droplimit);
for(int i = 0; i < item_count; ++i) {
float roll = (float)zone->random.Real(0.0, roll_t);
for(uint32 j = 0; j < lds->NumEntries; ++j) {
const Item_Struct* db_item = GetItem(lds->Entries[j].item_id);
if(db_item) {
if(roll < lds->Entries[j].chance) {
npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);
int charges = (int)lds->Entries[i].multiplier;
charges = EQEmu::ClampLower(charges, 1);
for(int k = 1; k < charges; ++k) {
float c_roll = (float)zone->random.Real(0.0, 100.0);
if(c_roll <= lds->Entries[i].chance) {
npc->AddLootDrop(db_item, itemlist, lds->Entries[j].item_charges, lds->Entries[j].minlevel,
lds->Entries[j].maxlevel, lds->Entries[j].equip_item > 0 ? true : false, false);
}
}
j = lds->NumEntries;
break;
}
else {
roll -= lds->Entries[j].chance;
}
}
}
} // We either ran out of items or reached our limit.
@@ -215,6 +224,7 @@ void NPC::AddLootDrop(const Item_Struct *item2, ItemList* itemlist, int16 charge
item->attuned = 0;
item->min_level = minlevel;
item->max_level = maxlevel;
if (equipit) {
uint8 eslot = 0xFF;
char newid[20];
+15 -2
View File
@@ -17,6 +17,7 @@
#include "questmgr.h"
#include "qglobals.h"
#include "../common/timer.h"
#include "../common/eqemu_logsys.h"
struct Events { };
struct Factions { };
@@ -1221,7 +1222,6 @@ std::string lua_get_encounter() {
return quest_manager.GetEncounter();
}
void lua_map_opcodes() {
MapOpcodes();
}
@@ -1249,6 +1249,17 @@ double lua_clock() {
return static_cast<double>(t) / 1000.0;
}
void lua_debug(std::string message) {
Log.Out(Logs::General, Logs::QuestDebug, message);
}
void lua_debug(std::string message, int level) {
if (level < Logs::General || level > Logs::Detail)
return;
Log.Out(static_cast<Logs::DebugLevel>(level), Logs::QuestDebug, message);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -1582,7 +1593,9 @@ luabind::scope lua_register_general() {
luabind::def("disable_recipe", &lua_disable_recipe),
luabind::def("clear_npctype_cache", &lua_clear_npctype_cache),
luabind::def("clock", &lua_clock),
luabind::def("create_npc", &lua_create_npc)
luabind::def("create_npc", &lua_create_npc),
luabind::def("debug", (void(*)(std::string))&lua_debug),
luabind::def("debug", (void(*)(std::string, int))&lua_debug)
];
}
+2 -2
View File
@@ -35,14 +35,13 @@
#include "zone.h"
#include "lua_parser.h"
const char *LuaEvents[_LargestEventID] = {
const char *LuaEvents[_LargestEventID] = {
"event_say",
"event_trade",
"event_death",
"event_spawn",
"event_attack",
"event_combat",
"event_environmental_damage",
"event_aggro",
"event_slay",
"event_npc_slay",
@@ -68,6 +67,7 @@ const char *LuaEvents[_LargestEventID] = {
"event_aggro_say",
"event_player_pickup",
"event_popup_response",
"event_environmental_damage",
"event_proximity_say",
"event_cast",
"event_cast_begin",
+27 -2
View File
@@ -300,6 +300,7 @@ Mob::Mob(const char* in_name,
focused = false;
_IsTempPet = false;
pet_owner_client = false;
pet_targetlock_id = 0;
attacked_count = 0;
mezzed = false;
@@ -1981,9 +1982,10 @@ void Mob::TempName(const char *newname)
strn0cpy(temp_name, GetCleanName(), 64);
}
// Remove Numbers before making name unique
EntityList::RemoveNumbers(temp_name);
// Make the new name unique and set it
strn0cpy(temp_name, entity_list.MakeNameUnique(temp_name), 64);
entity_list.MakeNameUnique(temp_name);
// Send the new name to all clients
EQApplicationPacket* outapp = new EQApplicationPacket(OP_MobRename, sizeof(MobRename_Struct));
@@ -5362,3 +5364,26 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot)
return stat;
}
bool Mob::CanClassEquipItem(uint32 item_id)
{
const Item_Struct* itm = nullptr;
itm = database.GetItem(item_id);
if (!itm)
return false;
if(itm->Classes == 65535 )
return true;
if (GetClass() > 16)
return false;
int bitmask = 1;
bitmask = bitmask << (GetClass() - 1);
if(!(itm->Classes & bitmask))
return false;
else
return true;
}
+7 -2
View File
@@ -194,7 +194,7 @@ public:
bool IsBeneficialAllowed(Mob *target);
virtual int GetCasterLevel(uint16 spell_id);
void ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* newbon, uint16 casterID = 0,
bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1,
bool item_bonus = false, bool IsWornEffect = false, uint32 ticsremaining = 0, int buffslot = -1,
bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0);
void NegateSpellsBonuses(uint16 spell_id);
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
@@ -315,6 +315,7 @@ public:
virtual int32 GetHerosForgeModel(uint8 material_slot) const;
virtual uint32 GetEquipmentColor(uint8 material_slot) const;
virtual uint32 IsEliteMaterialItem(uint8 material_slot) const;
bool CanClassEquipItem(uint32 item_id);
bool AffectedBySpellExcludingSlot(int slot, int effect);
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, SkillUseTypes attack_skill) = 0;
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, SkillUseTypes attack_skill,
@@ -621,7 +622,7 @@ public:
bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true);
bool ImprovedTaunt();
bool TryRootFadeByDamage(int buffslot, Mob* attacker);
int16 GetSlowMitigation() const {return slow_mitigation;}
float GetSlowMitigation() const { return slow_mitigation; }
void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr);
inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; };
inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; };
@@ -675,6 +676,9 @@ public:
bool IsFamiliar() const { return(typeofpet == petFamiliar); }
bool IsAnimation() const { return(typeofpet == petAnimation); }
bool IsCharmed() const { return(typeofpet == petCharmed); }
bool IsTargetLockPet() const { return(typeofpet == petTargetLock); }
inline uint32 GetPetTargetLockID() { return pet_targetlock_id; };
inline void SetPetTargetLockID(uint32 value) { pet_targetlock_id = value; };
void SetOwnerID(uint16 NewOwnerID);
inline uint16 GetOwnerID() const { return ownerid; }
inline virtual bool HasOwner() { if(GetOwnerID()==0){return false;} return( entity_list.GetMob(GetOwnerID()) != 0); }
@@ -1244,6 +1248,7 @@ protected:
bool _IsTempPet;
int16 count_TempPet;
bool pet_owner_client; //Flags regular and pets as belonging to a client
uint32 pet_targetlock_id;
EGNode *_egnode; //the EG node we are in
glm::vec3 m_TargetLocation;
+10
View File
@@ -2419,4 +2419,14 @@ void NPC::DepopSwarmPets()
}
}
}
if (IsPet() && GetPetType() == petTargetLock && GetPetTargetLockID()){
Mob *targMob = entity_list.GetMob(GetPetTargetLockID());
if(!targMob || (targMob && targMob->IsCorpse())){
Kill();
return;
}
}
}
+1 -1
View File
@@ -253,7 +253,7 @@ public:
uint32 GetMaxDMG() const {return max_dmg;}
uint32 GetMinDMG() const {return min_dmg;}
int16 GetSlowMitigation() const {return slow_mitigation;}
float GetSlowMitigation() const { return slow_mitigation; }
float GetAttackSpeed() const {return attack_speed;}
uint8 GetAttackDelay() const {return attack_delay;}
bool IsAnimal() const { return(bodytype == BT_Animal); }
+8 -3
View File
@@ -467,16 +467,21 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
if (m_inst && sender) {
// if there is a lore conflict, delete the offending item from the server inventory
// the client updates itself and takes care of sending "duplicate lore item" messages
if(sender->CheckLoreConflict(m_inst->GetItem())) {
int16 loreslot = sender->GetInv().HasItem(m_inst->GetItem()->ID, 0, invWhereBank);
auto item = m_inst->GetItem();
if(sender->CheckLoreConflict(item)) {
int16 loreslot = sender->GetInv().HasItem(item->ID, 0, invWhereBank);
if (loreslot != INVALID_INDEX) // if the duplicate is in the bank, delete it.
sender->DeleteItemInInventory(loreslot);
else
cursordelete = true; // otherwise, we delete the new one
}
if (item->RecastDelay)
m_inst->SetRecastTimestamp(
database.GetItemRecastTimestamp(sender->CharacterID(), item->RecastType));
char buf[10];
snprintf(buf, 9, "%u", m_inst->GetItem()->ID);
snprintf(buf, 9, "%u", item->ID);
buf[9] = '\0';
std::vector<EQEmu::Any> args;
args.push_back(m_inst);
+2 -2
View File
@@ -342,8 +342,8 @@ XS(XS_Group_GetLeaderName)
if (items != 1)
Perl_croak(aTHX_ "Usage: Group::GetLeaderName(THIS)");
{
Group * THIS;
char * RETVAL;
Group * THIS;
const char * RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "Group")) {
+28
View File
@@ -8367,6 +8367,33 @@ XS(XS_Mob_ProcessSpecialAbilities)
XSRETURN_EMPTY;
}
XS(XS_Mob_CanClassEquipItem); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_CanClassEquipItem)
{
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: Mob::CanClassEquipItem(THIS, item_id)");
{
Mob * THIS;
bool RETVAL;
uint32 item_id = (uint32)SvUV(ST(1));
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Mob *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Mob");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->CanClassEquipItem(item_id);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
#ifdef __cplusplus
extern "C"
#endif
@@ -8675,6 +8702,7 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "SetSpecialAbilityParam"), XS_Mob_SetSpecialAbilityParam, file, "$$$$");
newXSproto(strcpy(buf, "ClearSpecialAbilities"), XS_Mob_ClearSpecialAbilities, file, "$");
newXSproto(strcpy(buf, "ProcessSpecialAbilities"), XS_Mob_ProcessSpecialAbilities, file, "$$");
newXSproto(strcpy(buf, "CanClassEquipItem"), XS_Mob_CanClassEquipItem, file, "$$");
XSRETURN_YES;
}
+2 -2
View File
@@ -2076,7 +2076,7 @@ XS(XS_NPC_GetSlowMitigation)
Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)");
{
NPC * THIS;
int16 RETVAL;
float RETVAL;
dXSTARG;
if (sv_derived_from(ST(0), "NPC")) {
@@ -2089,7 +2089,7 @@ XS(XS_NPC_GetSlowMitigation)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
RETVAL = THIS->GetSlowMitigation();
XSprePUSH; PUSHn((UV)RETVAL);
XSprePUSH; PUSHn((double)RETVAL);
}
XSRETURN(1);
}
+14
View File
@@ -426,6 +426,20 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
entity_list.AddNPC(npc, true, true);
SetPetID(npc->GetID());
// We need to handle PetType 5 (petHatelist), add the current target to the hatelist of the pet
if (record.petcontrol == petTargetLock)
{
Mob* target = GetTarget();
if (target){
npc->AddToHateList(target, 1);
npc->SetPetTargetLockID(target->GetID());
npc->SetSpecialAbility(IMMUNE_AGGRO, 1);
}
else
npc->Kill(); //On live casts spell 892 Unsummon (Kayen - Too limiting to use that for emu since pet can have more than 20k HP)
}
}
/* This is why the pets ghost - pets were being spawned too far away from its npc owner and some
into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I
+6 -1
View File
@@ -5527,7 +5527,12 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
//Summon Spells that require reagents are typically imbue type spells, enchant metal, sacrifice and shouldn't be affected
//by reagent conservation for obvious reasons.
return realTotal + realTotal2 + realTotal3;
//Non-Live like feature to allow for an additive focus bonus to be applied from foci that are placed in worn slot. (No limit checks)
int16 worneffect_bonus = 0;
if (RuleB(Spells, UseAdditiveFocusFromWornSlot))
worneffect_bonus = itembonuses.FocusEffectsWorn[type];
return realTotal + realTotal2 + realTotal3 + worneffect_bonus;
}
int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
+18 -2
View File
@@ -1242,6 +1242,8 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
{
//Can we start the timer here? I don't see why not.
CastToClient()->GetPTimers().Start((pTimerItemStart + recasttype), recastdelay);
database.UpdateItemRecastTimestamps(CastToClient()->CharacterID(), recasttype,
CastToClient()->GetPTimers().Get(pTimerItemStart + recasttype)->GetReadyTimestamp());
}
}
@@ -2023,6 +2025,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
//
// Switch #2 - execute the spell
//
switch(CastAction)
{
default:
@@ -2146,6 +2149,15 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
// caster if they're not using TGB
// NOTE: this will always hit the caster, plus the target's group so
// it can affect up to 7 people if the targeted group is not our own
// Allow pets who cast group spells to affect the group.
if (spell_target->IsPetOwnerClient()){
Mob* owner = spell_target->GetOwner();
if (owner)
spell_target = owner;
}
if(spell_target->IsGrouped())
{
Group *target_group = entity_list.GetGroupByMob(spell_target);
@@ -2270,11 +2282,15 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
{
ItemInst *itm = CastToClient()->GetInv().GetItem(inventory_slot);
if(itm && itm->GetItem()->RecastDelay > 0){
CastToClient()->GetPTimers().Start((pTimerItemStart + itm->GetItem()->RecastType), itm->GetItem()->RecastDelay);
auto recast_type = itm->GetItem()->RecastType;
CastToClient()->GetPTimers().Start((pTimerItemStart + recast_type), itm->GetItem()->RecastDelay);
database.UpdateItemRecastTimestamps(
CastToClient()->CharacterID(), recast_type,
CastToClient()->GetPTimers().Get(pTimerItemStart + recast_type)->GetReadyTimestamp());
EQApplicationPacket *outapp = new EQApplicationPacket(OP_ItemRecastDelay, sizeof(ItemRecastDelay_Struct));
ItemRecastDelay_Struct *ird = (ItemRecastDelay_Struct *)outapp->pBuffer;
ird->recast_delay = itm->GetItem()->RecastDelay;
ird->recast_type = itm->GetItem()->RecastType;
ird->recast_type = recast_type;
CastToClient()->QueuePacket(outapp);
safe_delete(outapp);
}
+7 -1
View File
@@ -2872,7 +2872,13 @@ int ClientTaskState::GetTaskActivityDoneCountFromTaskID(int TaskID, int Activity
break;
}
}
return ActiveTasks[ActiveTaskIndex].Activity[ActivityID].DoneCount;
if (ActiveTasks[ActiveTaskIndex].Activity[ActivityID].DoneCount){
return ActiveTasks[ActiveTaskIndex].Activity[ActivityID].DoneCount;
}
else{
return 0;
}
}
int ClientTaskState::GetTaskStartTime(int index) {
+20 -11
View File
@@ -23,6 +23,7 @@
#include "../common/rulesys.h"
#include "../common/types.h"
#include "../common/random.h"
#include "../common/string_util.h"
#include "qglobals.h"
#include "spawn2.h"
#include "spawngroup.h"
@@ -67,16 +68,6 @@ struct item_tick_struct {
std::string qglobal;
};
// static uint32 gmsay_log_message_colors[EQEmuLogSys::MaxLogID] = {
// 15, // "Status", - Yellow
// 15, // "Normal", - Yellow
// 3, // "Error", - Red
// 14, // "Debug", - Light Green
// 4, // "Quest",
// 5, // "Command",
// 3 // "Crash"
// };
class Client;
class Map;
class Mob;
@@ -266,7 +257,25 @@ public:
// random object that provides random values for the zone
EQEmu::Random random;
static void GMSayHookCallBackProcess(uint16 log_category, const std::string& message){ entity_list.MessageStatus(0, 80, Log.GetGMSayColorFromCategory(log_category), "%s", message.c_str()); }
static void GMSayHookCallBackProcess(uint16 log_category, std::string message){
/* Cut messages down to 4000 max to prevent client crash */
if (!message.empty())
message = message.substr(0, 4000);
/* Replace Occurrences of % or MessageStatus will crash */
find_replace(message, std::string("%"), std::string("."));
if (message.find("\n") != std::string::npos){
auto message_split = SplitString(message, '\n');
entity_list.MessageStatus(0, 80, Log.GetGMSayColorFromCategory(log_category), "%s", message_split[0].c_str());
for (size_t iter = 1; iter < message_split.size(); ++iter) {
entity_list.MessageStatus(0, 80, Log.GetGMSayColorFromCategory(log_category), "--- %s", message_split[iter].c_str());
}
}
else{
entity_list.MessageStatus(0, 80, Log.GetGMSayColorFromCategory(log_category), "%s", message.c_str());
}
}
//MODDING HOOKS
void mod_init();
+21 -23
View File
@@ -1118,11 +1118,9 @@ bool ZoneDatabase::LoadCharacterMaterialColor(uint32 character_id, PlayerProfile
bool ZoneDatabase::LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp){
std::string query = StringFormat("SELECT `bandolier_id`, `bandolier_slot`, `item_id`, `icon`, `bandolier_name` FROM `character_bandolier` WHERE `id` = %u LIMIT 16", character_id);
auto results = database.QueryDatabase(query); int i = 0; int r = 0; int si = 0;
for (i = 0; i <= EmuConstants::BANDOLIERS_COUNT; i++){
for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++){
for (i = 0; i < EmuConstants::BANDOLIERS_COUNT; i++)
for (int si = 0; si < EmuConstants::BANDOLIER_SIZE; si++)
pp->bandoliers[i].items[si].icon = 0;
}
}
for (auto row = results.begin(); row != results.end(); ++row) {
r = 0;
@@ -2999,6 +2997,14 @@ void ZoneDatabase::RemoveTempFactions(Client *client) {
QueryDatabase(query);
}
void ZoneDatabase::UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type, uint32 timestamp)
{
std::string query =
StringFormat("REPLACE INTO character_item_recast (id, recast_type, timestamp) VALUES (%u, %u, %u)", char_id,
recast_type, timestamp);
QueryDatabase(query);
}
void ZoneDatabase::LoadPetInfo(Client *client) {
// Load current pet and suspended pet
@@ -3204,16 +3210,7 @@ bool ZoneDatabase::GetNPCFactionList(uint32 npcfaction_id, int32* faction_id, in
bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, int32 value, uint8 temp, faction_map &val_list)
{
std::string query = StringFormat("DELETE FROM faction_values "
"WHERE char_id=%i AND faction_id = %i",
char_id, faction_id);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
}
if(value == 0)
return true;
std::string query;
if(temp == 2)
temp = 0;
@@ -3221,17 +3218,18 @@ bool ZoneDatabase::SetCharacterFactionLevel(uint32 char_id, int32 faction_id, in
if(temp == 3)
temp = 1;
query = StringFormat("INSERT INTO faction_values (char_id, faction_id, current_value, temp) "
"VALUES (%i, %i, %i, %i)", char_id, faction_id, value, temp);
results = QueryDatabase(query);
if (!results.Success()) {
query = StringFormat("INSERT INTO `faction_values` "
"(`char_id`, `faction_id`, `current_value`, `temp`) "
"VALUES (%i, %i, %i, %i) "
"ON DUPLICATE KEY UPDATE `current_value`=%i,`temp`=%i",
char_id, faction_id, value, temp, value, temp);
auto results = QueryDatabase(query);
if (!results.Success())
return false;
}
else
val_list[faction_id] = value;
if (results.RowsAffected() == 0)
return false;
val_list[faction_id] = value;
return true;
}
+1
View File
@@ -256,6 +256,7 @@ public:
void LoadPetInfo(Client *c);
void SavePetInfo(Client *c);
void RemoveTempFactions(Client *c);
void UpdateItemRecastTimestamps(uint32 char_id, uint32 recast_type, uint32 timestamp);
/* Character Data Loaders */
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);