Merge branch 'master' of github.com:EQEmu/Server

This commit is contained in:
KimLS
2020-02-03 17:17:26 -08:00
81 changed files with 1651 additions and 6732 deletions
+9 -9
View File
@@ -724,20 +724,20 @@ int Mob::GetClassRaceACBonus()
hardcap = 32;
softcap = 15;
}
int weight = IsClient() ? CastToClient()->CalcCurrentWeight() : 0;
int weight = IsClient() ? CastToClient()->CalcCurrentWeight()/10 : 0;
if (weight < hardcap - 1) {
int temp = level + 5;
double temp = level + 5;
if (weight > softcap) {
double redux = (weight - softcap) * 6.66667;
double redux = static_cast<double>(weight - softcap) * 6.66667;
redux = (100.0 - std::min(100.0, redux)) * 0.01;
temp = std::max(0, static_cast<int>(temp * redux));
temp = std::max(0.0, temp * redux);
}
ac_bonus = (4 * temp) / 3;
ac_bonus = static_cast<int>((4.0 * temp) / 3.0);
}
else if (weight > hardcap + 1) {
int temp = level + 5;
double multiplier = std::min(1.0, (weight - (hardcap - 10.0)) / 100.0);
temp = (4 * temp) / 3;
double temp = level + 5;
double multiplier = std::min(1.0, (weight - (static_cast<double>(hardcap) - 10.0)) / 100.0);
temp = (4.0 * temp) / 3.0;
ac_bonus -= static_cast<int>(temp * multiplier);
}
}
@@ -5491,4 +5491,4 @@ int32 Mob::GetHPRegen() const
int32 Mob::GetManaRegen() const
{
return mana_regen;
}
}
+431 -242
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -73,7 +73,7 @@ private:
int m_owner;
int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell
int spell_id; // spell we cast
int distance; // distance we remove
float distance; // distance we remove
Timer remove_timer; // when we depop
Timer process_timer; // rate limit process calls
Timer cast_timer; // some auras pulse
+87 -55
View File
@@ -5234,7 +5234,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b
return false;
}
int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id)
int32 Bot::CalcBotAAFocus(focusType type, uint32 aa_ID, uint32 points, uint16 spell_id)
{
const SPDat_Spell_Struct &spell = spells[spell_id];
int32 value = 0;
@@ -5388,6 +5388,10 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
if (type == focusImprovedDamage && base1 > value)
value = base1;
break;
case SE_ImprovedDamage2:
if (type == focusImprovedDamage2 && base1 > value)
value = base1;
break;
case SE_ImprovedHeal:
if (type == focusImprovedHeal && base1 > value)
value = base1;
@@ -5499,6 +5503,11 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
value = base1;
break;
}
case SE_FcDamageAmt2: {
if(type == focusFcDamageAmt2)
value = base1;
break;
}
case SE_FcDamageAmtCrit: {
if(type == focusFcDamageAmtCrit)
value = base1;
@@ -5557,8 +5566,8 @@ int32 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16
return (value * lvlModifier / 100);
}
int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
if (IsBardSong(spell_id) && bottype != BotfocusFcBaseEffects)
int32 Bot::GetBotFocusEffect(focusType bottype, uint16 spell_id) {
if (IsBardSong(spell_id) && bottype != focusFcBaseEffects)
return 0;
int32 realTotal = 0;
@@ -5567,7 +5576,7 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
bool rand_effectiveness = false;
//Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages
//In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance
if((bottype == BotfocusManaCost || bottype == BotfocusImprovedHeal || bottype == BotfocusImprovedDamage) && RuleB(Spells, LiveLikeFocusEffects))
if(RuleB(Spells, LiveLikeFocusEffects) && (bottype == focusManaCost || bottype == focusImprovedHeal || bottype == focusImprovedDamage || bottype == focusImprovedDamage2 || bottype == focusResistRate))
rand_effectiveness = true;
//Check if item focus effect exists for the client.
@@ -5708,16 +5717,16 @@ int32 Bot::GetBotFocusEffect(BotfocusType bottype, uint16 spell_id) {
}
}
if(bottype == BotfocusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))
if(bottype == focusReagentCost && IsSummonPetSpell(spell_id) && GetAA(aaElementalPact))
return 100;
if(bottype == BotfocusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id)))
if(bottype == focusReagentCost && (IsEffectInSpell(spell_id, SE_SummonItem) || IsSacrificeSpell(spell_id)))
return 0;
return (realTotal + realTotal2);
}
int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) {
int32 Bot::CalcBotFocusEffect(focusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus) {
if(!IsValidSpell(focus_id) || !IsValidSpell(spell_id))
return 0;
@@ -5847,7 +5856,21 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
return 0;
break;
case SE_ImprovedDamage:
if (bottype == BotfocusImprovedDamage) {
if (bottype == focusImprovedDamage) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
else
value = focus_spell.base[i];
}
else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i])
value = focus_spell.base[i];
else
value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]);
}
break;
case SE_ImprovedDamage2:
if (bottype == focusImprovedDamage2) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
@@ -5861,7 +5884,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_ImprovedHeal:
if (bottype == BotfocusImprovedHeal) {
if (bottype == focusImprovedHeal) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
@@ -5875,7 +5898,7 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_ReduceManaCost:
if (bottype == BotfocusManaCost) {
if (bottype == focusManaCost) {
if(best_focus) {
if (focus_spell.base2[i] != 0)
value = focus_spell.base2[i];
@@ -5889,39 +5912,39 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_IncreaseSpellHaste:
if (bottype == BotfocusSpellHaste && focus_spell.base[i] > value)
if (bottype == focusSpellHaste && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_IncreaseSpellDuration:
if (bottype == BotfocusSpellDuration && focus_spell.base[i] > value)
if (bottype == focusSpellDuration && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SpellDurationIncByTic:
if (bottype == BotfocusSpellDurByTic && focus_spell.base[i] > value)
if (bottype == focusSpellDurByTic && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SwarmPetDuration:
if (bottype == BotfocusSwarmPetDuration && focus_spell.base[i] > value)
if (bottype == focusSwarmPetDuration && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_IncreaseRange:
if (bottype == BotfocusRange && focus_spell.base[i] > value)
if (bottype == focusRange && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_ReduceReagentCost:
if (bottype == BotfocusReagentCost && focus_spell.base[i] > value)
if (bottype == focusReagentCost && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_PetPowerIncrease:
if (bottype == BotfocusPetPower && focus_spell.base[i] > value)
if (bottype == focusPetPower && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SpellResistReduction:
if (bottype == BotfocusResistRate && focus_spell.base[i] > value)
if (bottype == focusResistRate && focus_spell.base[i] > value)
value = focus_spell.base[i];
break;
case SE_SpellHateMod:
if (bottype == BotfocusSpellHateMod) {
if (bottype == focusSpellHateMod) {
if(value != 0) {
if(value > 0) {
if(focus_spell.base[i] > value)
@@ -5936,12 +5959,12 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_ReduceReuseTimer: {
if(bottype == BotfocusReduceRecastTime)
if(bottype == focusReduceRecastTime)
value = (focus_spell.base[i] / 1000);
break;
}
case SE_TriggerOnCast: {
if(bottype == BotfocusTriggerOnCast) {
if(bottype == focusTriggerOnCast) {
if(zone->random.Int(0, 100) <= focus_spell.base[i])
value = focus_spell.base2[i];
else
@@ -5950,24 +5973,24 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_FcSpellVulnerability: {
if(bottype == BotfocusSpellVulnerability)
if(bottype == focusSpellVulnerability)
value = focus_spell.base[i];
break;
}
case SE_BlockNextSpellFocus: {
if(bottype == BotfocusBlockNextSpell) {
if(bottype == focusBlockNextSpell) {
if(zone->random.Int(1, 100) <= focus_spell.base[i])
value = 1;
}
break;
}
case SE_FcTwincast: {
if(bottype == BotfocusTwincast)
if(bottype == focusTwincast)
value = focus_spell.base[i];
break;
}
case SE_SympatheticProc: {
if(bottype == BotfocusSympatheticProc) {
if(bottype == focusSympatheticProc) {
float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]);
if(zone->random.Real(0, 1) <= ProcChance)
value = focus_id;
@@ -5977,49 +6000,54 @@ int32 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_FcDamageAmt: {
if(bottype == BotfocusFcDamageAmt)
if(bottype == focusFcDamageAmt)
value = focus_spell.base[i];
break;
}
case SE_FcDamageAmt2: {
if(bottype == focusFcDamageAmt2)
value = focus_spell.base[i];
break;
}
case SE_FcDamageAmtCrit: {
if(bottype == BotfocusFcDamageAmtCrit)
if(bottype == focusFcDamageAmtCrit)
value = focus_spell.base[i];
break;
}
case SE_FcHealAmtIncoming:
if(bottype == BotfocusFcHealAmtIncoming)
if(bottype == focusFcHealAmtIncoming)
value = focus_spell.base[i];
break;
case SE_FcHealPctCritIncoming:
if (bottype == BotfocusFcHealPctCritIncoming)
if (bottype == focusFcHealPctCritIncoming)
value = focus_spell.base[i];
break;
case SE_FcHealAmtCrit:
if(bottype == BotfocusFcHealAmtCrit)
if(bottype == focusFcHealAmtCrit)
value = focus_spell.base[i];
break;
case SE_FcHealAmt:
if(bottype == BotfocusFcHealAmt)
if(bottype == focusFcHealAmt)
value = focus_spell.base[i];
break;
case SE_FcHealPctIncoming:
if(bottype == BotfocusFcHealPctIncoming)
if(bottype == focusFcHealPctIncoming)
value = focus_spell.base[i];
break;
case SE_FcBaseEffects: {
if (bottype == BotfocusFcBaseEffects)
if (bottype == focusFcBaseEffects)
value = focus_spell.base[i];
break;
}
case SE_FcDamagePctCrit: {
if(bottype == BotfocusFcDamagePctCrit)
if(bottype == focusFcDamagePctCrit)
value = focus_spell.base[i];
break;
}
case SE_FcIncreaseNumHits: {
if(bottype == BotfocusIncreaseNumHits)
if(bottype == focusIncreaseNumHits)
value = focus_spell.base[i];
break;
@@ -6559,14 +6587,14 @@ void Bot::DoClassAttacks(Mob *target, bool IsRiposte) {
int32 Bot::CheckAggroAmount(uint16 spellid) {
int32 AggroAmount = Mob::CheckAggroAmount(spellid, nullptr);
int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid);
int32 focusAggro = GetBotFocusEffect(focusSpellHateMod, spellid);
AggroAmount = (AggroAmount * (100 + focusAggro) / 100);
return AggroAmount;
}
int32 Bot::CheckHealAggroAmount(uint16 spellid, Mob *target, uint32 heal_possible) {
int32 AggroAmount = Mob::CheckHealAggroAmount(spellid, target, heal_possible);
int32 focusAggro = GetBotFocusEffect(BotfocusSpellHateMod, spellid);
int32 focusAggro = GetBotFocusEffect(focusSpellHateMod, spellid);
AggroAmount = (AggroAmount * (100 + focusAggro) / 100);
return AggroAmount;
}
@@ -6840,7 +6868,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
bool Critical = false;
int32 value_BaseEffect = 0;
value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100));
value_BaseEffect = (value + (value*GetBotFocusEffect(focusFcBaseEffects, spell_id) / 100));
// Need to scale HT damage differently after level 40! It no longer scales by the constant value in the spell file. It scales differently, instead of 10 more damage per level, it does 30 more damage per level. So we multiply the level minus 40 times 20 if they are over level 40.
if ( (spell_id == SPELL_HARM_TOUCH || spell_id == SPELL_HARM_TOUCH2 || spell_id == SPELL_IMP_HARM_TOUCH ) && GetLevel() > 40)
value -= ((GetLevel() - 40) * 20);
@@ -6868,16 +6896,18 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
ratio += RuleI(Spells, WizCritRatio);
if (Critical) {
value = (value_BaseEffect * ratio / 100);
value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100);
value += (int(value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100) * ratio / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage2, spell_id) / 100);
value += (int(value_BaseEffect * GetBotFocusEffect(focusFcDamagePctCrit, spell_id) / 100) * ratio / 100);
if (target) {
value += (int(value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100) * ratio / 100);
value -= target->GetFcDamageAmtIncoming(this, spell_id);
}
value -= (GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id) * ratio / 100);
value -= (GetBotFocusEffect(focusFcDamageAmtCrit, spell_id) * ratio / 100);
value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt2, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100);
@@ -6889,15 +6919,17 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
}
value = value_BaseEffect;
value += (value_BaseEffect * GetBotFocusEffect(BotfocusImprovedDamage, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(BotfocusFcDamagePctCrit, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusImprovedDamage2, spell_id) / 100);
value += (value_BaseEffect * GetBotFocusEffect(focusFcDamagePctCrit, spell_id) / 100);
if (target) {
value += (value_BaseEffect * target->GetVulnerability(this, spell_id, 0) / 100);
value -= target->GetFcDamageAmtIncoming(this, spell_id);
}
value -= GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id);
value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmtCrit, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt, spell_id);
value -= GetBotFocusEffect(focusFcDamageAmt2, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
@@ -6912,9 +6944,9 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 chance = 0;
int8 modifier = 1;
bool Critical = false;
value_BaseEffect = (value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id) / 100));
value_BaseEffect = (value + (value*GetBotFocusEffect(focusFcBaseEffects, spell_id) / 100));
value = value_BaseEffect;
value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id) / 100);
value += int(value_BaseEffect*GetBotFocusEffect(focusImprovedHeal, spell_id) / 100);
if(spells[spell_id].buffduration < 1) {
chance += (itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance);
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
@@ -6927,8 +6959,8 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
}
value *= modifier;
value += (GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier);
value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id);
value += (GetBotFocusEffect(focusFcHealAmtCrit, spell_id) * modifier);
value += GetBotFocusEffect(focusFcHealAmt, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
@@ -6953,7 +6985,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
int32 cast_reducer = 0;
cast_reducer += GetBotFocusEffect(BotfocusSpellHaste, spell_id);
cast_reducer += GetBotFocusEffect(focusSpellHaste, spell_id);
uint8 botlevel = GetLevel();
uint8 botclass = GetClass();
if (botlevel >= 51 && casttime >= 3000 && !BeneficialSpell(spell_id) && (botclass == SHADOWKNIGHT || botclass == RANGER || botclass == PALADIN || botclass == BEASTLORD ))
@@ -7088,7 +7120,7 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
}
}
int32 focus_redux = GetBotFocusEffect(BotfocusManaCost, spell_id);
int32 focus_redux = GetBotFocusEffect(focusManaCost, spell_id);
if(focus_redux > 0)
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
@@ -7115,14 +7147,14 @@ int32 Bot::GetActSpellCost(uint16 spell_id, int32 cost) {
float Bot::GetActSpellRange(uint16 spell_id, float range) {
float extrange = 100;
extrange += GetBotFocusEffect(BotfocusRange, spell_id);
extrange += GetBotFocusEffect(focusRange, spell_id);
return ((range * extrange) / 100);
}
int32 Bot::GetActSpellDuration(uint16 spell_id, int32 duration) {
int increase = 100;
increase += GetBotFocusEffect(BotfocusSpellDuration, spell_id);
int tic_inc = 0; tic_inc = GetBotFocusEffect(BotfocusSpellDurByTic, spell_id);
increase += GetBotFocusEffect(focusSpellDuration, spell_id);
int tic_inc = 0; tic_inc = GetBotFocusEffect(focusSpellDurByTic, spell_id);
if(IsBeneficialSpell(spell_id)) {
switch (GetAA(aaSpellCastingReinforcement)) {
+3 -37
View File
@@ -99,40 +99,6 @@ class Bot : public NPC {
friend class Mob;
public:
// Class enums
enum BotfocusType { //focus types
BotfocusSpellHaste = 1,
BotfocusSpellDuration,
BotfocusRange,
BotfocusReagentCost,
BotfocusManaCost,
BotfocusImprovedHeal,
BotfocusImprovedDamage,
BotfocusImprovedDOT, //i dont know about this...
BotfocusFcDamagePctCrit,
BotfocusImprovedUndeadDamage,
BotfocusPetPower,
BotfocusResistRate,
BotfocusSpellHateMod,
BotfocusTriggerOnCast,
BotfocusSpellVulnerability,
BotfocusTwincast,
BotfocusSympatheticProc,
BotfocusFcDamageAmt,
BotfocusFcDamageAmtCrit,
BotfocusSpellDurByTic,
BotfocusSwarmPetDuration,
BotfocusReduceRecastTime,
BotfocusBlockNextSpell,
BotfocusFcHealPctIncoming,
BotfocusFcDamageAmtIncoming,
BotfocusFcHealAmtIncoming,
BotfocusFcBaseEffects,
BotfocusIncreaseNumHits,
BotfocusFcHealPctCritIncoming,
BotfocusFcHealAmt,
BotfocusFcHealAmtCrit,
};
enum BotTradeType { // types of trades a bot can do
BotTradeClientNormal,
BotTradeClientNoDropNoTrade
@@ -636,9 +602,9 @@ protected:
virtual void PetAIProcess();
virtual void BotMeditate(bool isSitting);
virtual bool CheckBotDoubleAttack(bool Triple = false);
virtual int32 GetBotFocusEffect(BotfocusType bottype, uint16 spell_id);
virtual int32 CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int32 CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
virtual int32 GetBotFocusEffect(focusType bottype, uint16 spell_id);
virtual int32 CalcBotFocusEffect(focusType bottype, uint16 focus_id, uint16 spell_id, bool best_focus=false);
virtual int32 CalcBotAAFocus(focusType type, uint32 aa_ID, uint32 points, uint16 spell_id);
virtual void PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* client);
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
+6
View File
@@ -3414,6 +3414,12 @@ void bot_command_help(Client *c, const Seperator *sep)
c->Message(m_usage, "%c%s - %s", BOT_COMMAND_CHAR, command_iter.first.c_str(), command_iter.second->desc == nullptr ? "[no description]" : command_iter.second->desc);
++bot_commands_shown;
}
if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
int i = parse->EventPlayer(EVENT_BOT_COMMAND, c, sep->msg, 0);
if (i >= 1) {
bot_commands_shown += i;
}
}
c->Message(m_message, "%d bot command%s listed.", bot_commands_shown, bot_commands_shown != 1 ? "s" : "");
c->Message(m_note, "type %ccommand [help | usage] for more information", BOT_COMMAND_CHAR);
}
+65 -13
View File
@@ -1106,40 +1106,56 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
case ChatChannel_Say: { /* Say */
if(message[0] == COMMAND_CHAR) {
if(command_dispatch(this, message) == -2) {
if(parse->PlayerHasQuestSub(EVENT_COMMAND)) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
if(i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Command '%s' not recognized.", message);
}
} else {
if(!RuleB(Chat, SuppressCommandErrors))
}
else if (parse->PlayerHasQuestSub(EVENT_SAY)) {
int i = parse->EventPlayer(EVENT_SAY, this, message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Command '%s' not recognized.", message);
}
}
else {
if (!RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Command '%s' not recognized.", message);
}
}
}
break;
}
if (EQEmu::ProfanityManager::IsCensorshipActive())
EQEmu::ProfanityManager::RedactMessage(message);
#ifdef BOTS
if (message[0] == BOT_COMMAND_CHAR) {
if (bot_command_dispatch(this, message) == -2) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, this, message, 0);
if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
int i = parse->EventPlayer(EVENT_BOT_COMMAND, this, message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Bot command '%s' not recognized.", message);
}
}
else if (parse->PlayerHasQuestSub(EVENT_SAY)) {
int i = parse->EventPlayer(EVENT_SAY, this, message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Bot command '%s' not recognized.", message);
}
}
else {
if (!RuleB(Chat, SuppressCommandErrors))
if (!RuleB(Chat, SuppressCommandErrors)) {
Message(Chat::Red, "Bot command '%s' not recognized.", message);
}
}
}
break;
}
#endif
if (EQEmu::ProfanityManager::IsCensorshipActive()) {
EQEmu::ProfanityManager::RedactMessage(message);
}
Mob* sender = this;
if (GetPet() && GetTarget() == GetPet() && GetPet()->FindType(SE_VoiceGraft))
sender = GetPet();
@@ -8517,13 +8533,13 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
qr->mob_id = target->GetID(); // Entity ID for the from mob name
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name
qr->target_id = GetID(); // The Client ID (this)
qr->copper = copper;
qr->silver = silver;
qr->gold = gold;
qr->platinum = platinum;
qr->item_id = itemid;
qr->item_id[0] = itemid;
qr->exp_reward = exp;
if (copper > 0 || silver > 0 || gold > 0 || platinum > 0)
@@ -8534,7 +8550,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
if (faction)
{
if (target->IsNPC())
if (target && target->IsNPC())
{
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
@@ -8550,6 +8566,42 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
safe_delete(outapp);
}
void Client::QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction)
{
auto outapp = new EQApplicationPacket(OP_Sound, sizeof(QuestReward_Struct));
memset(outapp->pBuffer, 0, sizeof(QuestReward_Struct));
QuestReward_Struct* qr = (QuestReward_Struct*)outapp->pBuffer;
memcpy(qr, &reward, sizeof(QuestReward_Struct));
// not set in caller because reasons
qr->mob_id = target ? target->GetID() : 0; // Entity ID for the from mob name
if (reward.copper > 0 || reward.silver > 0 || reward.gold > 0 || reward.platinum > 0)
AddMoneyToPP(reward.copper, reward.silver, reward.gold, reward.platinum, false);
for (int i = 0; i < QUESTREWARD_COUNT; ++i)
if (reward.item_id[i] > 0)
SummonItem(reward.item_id[i], 0, 0, 0, 0, 0, 0, false, EQEmu::invslot::slotCursor);
if (faction)
{
if (target && target->IsNPC())
{
int32 nfl_id = target->CastToNPC()->GetNPCFactionID();
SetFactionLevel(CharacterID(), nfl_id, GetBaseClass(), GetBaseRace(), GetDeity(), true);
qr->faction = target->CastToNPC()->GetPrimaryFaction();
qr->faction_mod = 1; // Too lazy to get real value, not sure if this is even used by client anyhow.
}
}
if (reward.exp_reward> 0)
AddEXP(reward.exp_reward);
QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
safe_delete(outapp);
}
void Client::SendHPUpdateMarquee(){
if (!this || !this->IsClient() || !this->current_hp || !this->max_hp)
return;
+1
View File
@@ -1282,6 +1282,7 @@ 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 QuestReward(Mob* target, const QuestReward_Struct &reward, bool faction); // TODO: Fix faction processing
void ResetHPUpdateTimer() { hpupdate_timer.Start(); }
+14 -12
View File
@@ -336,6 +336,10 @@ int32 Client::CalcMaxHP()
current_hp = curHP_cap;
}
}
// hack fix for client health not reflecting server value
last_max_hp = 0;
return max_hp;
}
@@ -610,14 +614,13 @@ int32 Client::CalcBaseMana()
case 'I':
WisInt = GetINT();
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
ConvertedWisInt = WisInt;
int over200 = WisInt;
if (WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if (WisInt > 201) {
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
if (WisInt > 200) {
over200 = (WisInt - 200) / -2 + WisInt;
}
}
else {
ConvertedWisInt = WisInt;
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
@@ -643,14 +646,13 @@ int32 Client::CalcBaseMana()
case 'W':
WisInt = GetWIS();
if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
ConvertedWisInt = WisInt;
int over200 = WisInt;
if (WisInt > 100) {
ConvertedWisInt = (((WisInt - 100) * 5 / 2) + 100);
if (WisInt > 201) {
ConvertedWisInt -= ((WisInt - 201) * 5 / 4);
if (WisInt > 200) {
over200 = (WisInt - 200) / -2 + WisInt;
}
}
else {
ConvertedWisInt = WisInt;
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
+30 -2
View File
@@ -905,6 +905,8 @@ void Client::CompleteConnect()
entity_list.RefreshClientXTargets(this);
worldserver.RequestTellQueue(GetName());
entity_list.ScanCloseMobs(close_mobs, this);
}
// connecting opcode handlers
@@ -8286,7 +8288,18 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
if (GetTarget() && GetTarget()->IsNPC()) {
if (silentsaylink) {
parse->EventNPC(EVENT_SAY, GetTarget()->CastToNPC(), this, response.c_str(), 0);
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
if (response[0] == '#' && parse->PlayerHasQuestSub(EVENT_COMMAND)) {
parse->EventPlayer(EVENT_COMMAND, this, response.c_str(), 0);
}
#ifdef BOTS
else if (response[0] == '^' && parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
parse->EventPlayer(EVENT_BOT_COMMAND, this, response.c_str(), 0);
}
#endif
else {
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
}
}
else {
Message(Chat::LightGray, "You say, '%s'", response.c_str());
@@ -8296,7 +8309,17 @@ void Client::Handle_OP_ItemLinkClick(const EQApplicationPacket *app)
}
else {
if (silentsaylink) {
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
if (response[0] == '#' && parse->PlayerHasQuestSub(EVENT_COMMAND)) {
parse->EventPlayer(EVENT_COMMAND, this, response.c_str(), 0);
}
#ifdef BOTS
else if (response[0] == '^' && parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
parse->EventPlayer(EVENT_BOT_COMMAND, this, response.c_str(), 0);
}
#endif
else {
parse->EventPlayer(EVENT_SAY, this, response.c_str(), 0);
}
}
else {
Message(Chat::LightGray, "You say, '%s'", response.c_str());
@@ -11107,6 +11130,11 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
break;
}
if (player_to_invite_group && player_to_invite_group->IsGroupMember(this)) {
MessageString(Chat::Red, ALREADY_IN_PARTY);
break;
}
if (player_to_invite_group && !player_to_invite_group->IsLeader(player_to_invite)) {
Message(Chat::Red, "You can only invite an ungrouped player or group leader to join your raid.");
break;
+1 -22
View File
@@ -256,28 +256,7 @@ bool Client::Process() {
* Used in aggro checks
*/
if (mob_close_scan_timer.Check()) {
close_mobs.clear();
float scan_range = RuleI(Range, MobCloseScanDistance) * RuleI(Range, MobCloseScanDistance);
auto &mob_list = entity_list.GetMobList();
for (auto itr : mob_list) {
Mob *mob = itr.second;
float distance = DistanceSquared(m_Position, mob->GetPosition());
if (mob->GetID() <= 0) {
continue;
}
if (mob->IsNPC() || mob->IsClient()) {
if (distance <= scan_range) {
close_mobs.insert(std::pair<uint16, Mob *>(mob->GetID(), mob));
}
else if ((mob->GetAggroRange() * mob->GetAggroRange()) > scan_range) {
close_mobs.insert(std::pair<uint16, Mob *>(mob->GetID(), mob));
}
}
}
entity_list.ScanCloseMobs(close_mobs, this);
}
bool may_use_attacks = false;
+8 -21
View File
@@ -783,6 +783,12 @@ void command_help(Client *c, const Seperator *sep)
commands_shown++;
c->Message(Chat::White, " %c%s %s", COMMAND_CHAR, cur->first.c_str(), cur->second->desc == nullptr?"":cur->second->desc);
}
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, c, sep->msg, 0);
if (i >= 1) {
commands_shown += i;
}
}
c->Message(Chat::White, "%d command%s listed.", commands_shown, commands_shown!=1?"s":"");
}
@@ -2167,25 +2173,6 @@ void command_spoff(Client *c, const Seperator *sep)
safe_delete(outapp);
}
void command_itemtest(Client *c, const Seperator *sep)
{
char chBuffer[8192] = {0};
//Using this to determine new item layout
FILE* f = nullptr;
if (!(f = fopen("c:\\EQEMUcvs\\ItemDump.txt", "rb"))) {
c->Message(Chat::Red, "Error: Could not open c:\\EQEMUcvs\\ItemDump.txt");
return;
}
fread(chBuffer, sizeof(chBuffer), sizeof(char), f);
fclose(f);
auto outapp = new EQApplicationPacket(OP_ItemLinkResponse, strlen(chBuffer) + 5);
memcpy(&outapp->pBuffer[4], chBuffer, strlen(chBuffer));
c->QueuePacket(outapp);
safe_delete(outapp);
}
void command_gassign(Client *c, const Seperator *sep)
{
if (sep->IsNumber(1) && c->GetTarget() && c->GetTarget()->IsNPC() && c->GetTarget()->CastToNPC()->GetSpawnPointID() > 0) {
@@ -13264,8 +13251,8 @@ void command_bot(Client *c, const Seperator *sep)
}
if (bot_command_dispatch(c, bot_message.c_str()) == -2) {
if (parse->PlayerHasQuestSub(EVENT_COMMAND)) {
int i = parse->EventPlayer(EVENT_COMMAND, c, bot_message, 0);
if (parse->PlayerHasQuestSub(EVENT_BOT_COMMAND)) {
int i = parse->EventPlayer(EVENT_BOT_COMMAND, c, bot_message, 0);
if (i == 0 && !RuleB(Chat, SuppressCommandErrors)) {
c->Message(Chat::Red, "Bot command '%s' not recognized.", bot_message.c_str());
}
-1
View File
@@ -150,7 +150,6 @@ void command_ipc(Client *c, const Seperator *sep);
void command_iplookup(Client *c, const Seperator *sep);
void command_iteminfo(Client *c, const Seperator *sep);
void command_itemsearch(Client *c, const Seperator *sep);
void command_itemtest(Client *c, const Seperator *sep);
void command_kick(Client *c, const Seperator *sep);
void command_killallnpcs(Client *c, const Seperator *sep);
void command_kill(Client *c, const Seperator *sep);
+13
View File
@@ -647,6 +647,19 @@ enum {
SKILLUP_FAILURE = 2
};
enum {
GridCircular,
GridRandom10,
GridRandom,
GridPatrol,
GridOneWayRepop,
GridRand5LoS,
GridOneWayDepop,
GridCenterPoint,
GridRandomCenterPoint,
GridRandomPath
};
typedef enum {
petFamiliar, //only listens to /pet get lost
petAnimation, //does not listen to any commands
+4 -2
View File
@@ -809,11 +809,13 @@ void EntityList::AESpell(
* 1 = PC
* 2 = NPC
*/
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc()) {
if (spells[spell_id].pcnpc_only_flag == 1 && !current_mob->IsClient() && !current_mob->IsMerc() &&
!current_mob->IsBot()) {
continue;
}
if (spells[spell_id].pcnpc_only_flag == 2 && (current_mob->IsClient() || current_mob->IsMerc())) {
if (spells[spell_id].pcnpc_only_flag == 2 &&
(current_mob->IsClient() || current_mob->IsMerc() || current_mob->IsBot())) {
continue;
}
+16 -3
View File
@@ -98,7 +98,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_DUEL_LOSE",
"EVENT_ENCOUNTER_LOAD",
"EVENT_ENCOUNTER_UNLOAD",
"EVENT_SAY",
"EVENT_COMMAND",
"EVENT_DROP_ITEM",
"EVENT_DESTROY_ITEM",
"EVENT_FEIGN_DEATH",
@@ -119,6 +119,7 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_DEATH_ZONE",
"EVENT_USE_SKILL",
"EVENT_COMBINE_VALIDATE",
"EVENT_BOT_COMMAND"
};
PerlembParser::PerlembParser() : perl(nullptr)
@@ -1542,9 +1543,12 @@ void PerlembParser::ExportEventVariables(
}
case EVENT_COMMAND: {
Seperator sep(data);
ExportVar(package_name.c_str(), "command", (sep.arg[0] + 1));
ExportVar(package_name.c_str(), "args", (sep.argnum >= 1 ? (&data[strlen(sep.arg[0]) + 1]) : "0"));
ExportVar(package_name.c_str(), "data", objid);
ExportVar(package_name.c_str(), "text", data);
ExportVar(package_name.c_str(), "data", "0");
ExportVar(package_name.c_str(), "langid", "0");
ExportVar(package_name.c_str(), "langid", extradata);
break;
}
@@ -1610,6 +1614,15 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "tradeskill_id", tradeskill_id.c_str());
break;
}
case EVENT_BOT_COMMAND: {
Seperator sep(data);
ExportVar(package_name.c_str(), "bot_command", (sep.arg[0] + 1));
ExportVar(package_name.c_str(), "args", (sep.argnum >= 1 ? (&data[strlen(sep.arg[0]) + 1]) : "0"));
ExportVar(package_name.c_str(), "data", objid);
ExportVar(package_name.c_str(), "text", data);
ExportVar(package_name.c_str(), "langid", extradata);
break;
}
default: {
break;
+39
View File
@@ -1812,6 +1812,43 @@ XS(XS__summonallplayercorpses) {
XSRETURN(1);
}
XS(XS__getplayercorpsecount);
XS(XS__getplayercorpsecount) {
dXSARGS;
if (items != 1)
Perl_croak(aTHX_ "Usage: quest::getplayercorpsecount(uint32 char_id)");
uint32 RETVAL;
dXSTARG;
uint32 char_id = (int) SvIV(ST(0));
RETVAL = quest_manager.getplayercorpsecount(char_id);
XSprePUSH;
PUSHu((IV) RETVAL);
XSRETURN(1);
}
XS(XS__getplayercorpsecountbyzoneid);
XS(XS__getplayercorpsecountbyzoneid) {
dXSARGS;
if (items != 2)
Perl_croak(aTHX_ "Usage: quest::getplayercorpsecountbyzoneid(uint32 char_id, uint32 zone_id)");
uint32 RETVAL;
dXSTARG;
uint32 char_id = (int) SvIV(ST(0));
uint32 zone_id = (int)SvIV(ST(1));
RETVAL = quest_manager.getplayercorpsecountbyzoneid(char_id, zone_id);
XSprePUSH;
PUSHu((IV) RETVAL);
XSRETURN(1);
}
XS(XS__getplayerburiedcorpsecount);
XS(XS__getplayerburiedcorpsecount) {
dXSARGS;
@@ -3907,6 +3944,8 @@ EXTERN_C XS(boot_quest) {
newXS(strcpy(buf, "getguildnamebyid"), XS__getguildnamebyid, file);
newXS(strcpy(buf, "getlevel"), XS__getlevel, file);
newXS(strcpy(buf, "getplayerburiedcorpsecount"), XS__getplayerburiedcorpsecount, file);
newXS(strcpy(buf, "getplayercorpsecount"), XS__getplayercorpsecount, file);
newXS(strcpy(buf, "getplayercorpsecountbyzoneid"), XS__getplayercorpsecountbyzoneid, file);
newXS(strcpy(buf, "gettaskactivitydonecount"), XS__gettaskactivitydonecount, file);
newXS(strcpy(buf, "givecash"), XS__givecash, file);
newXS(strcpy(buf, "gmmove"), XS__gmmove, file);
+26 -3
View File
@@ -2624,6 +2624,24 @@ bool EntityList::RemoveMobFromCloseLists(Mob *mob)
return false;
}
/**
* @param mob
* @return
*/
void EntityList::RemoveAuraFromMobs(Mob *aura)
{
LogEntityManagement(
"Attempting to remove aura [{}] from mobs entity_id ({})",
aura->GetCleanName(),
aura->GetID()
);
for (auto &it : mob_list) {
auto mob = it.second;
mob->RemoveAura(aura->GetID());
}
}
/**
* @param close_mobs
* @param scanning_mob
@@ -2654,7 +2672,12 @@ void EntityList::ScanCloseMobs(std::unordered_map<uint16, Mob *> &close_mobs, Mo
}
}
LogAIScanClose("Close List Size [{}] for mob [{}]", close_mobs.size(), scanning_mob->GetCleanName());
LogAIScanClose(
"[{}] Scanning Close List | list_size [{}] moving [{}]",
scanning_mob->GetCleanName(),
close_mobs.size(),
scanning_mob->IsMoving() ? "true" : "false"
);
}
bool EntityList::RemoveMerc(uint16 delete_id)
@@ -4955,10 +4978,10 @@ void EntityList::GetTargetsForConeArea(Mob *start, float min_radius, float radiu
continue;
}
// check PC/NPC only flag 1 = PCs, 2 = NPCs
if (pcnpc == 1 && !ptr->IsClient() && !ptr->IsMerc()) {
if (pcnpc == 1 && !ptr->IsClient() && !ptr->IsMerc() && !ptr->IsBot()) {
++it;
continue;
} else if (pcnpc == 2 && (ptr->IsClient() || ptr->IsMerc())) {
} else if (pcnpc == 2 && (ptr->IsClient() || ptr->IsMerc() || ptr->IsBot())) {
++it;
continue;
}
+1 -1
View File
@@ -293,6 +293,7 @@ public:
bool RemoveObject(uint16 delete_id);
bool RemoveProximity(uint16 delete_npc_id);
bool RemoveMobFromCloseLists(Mob *mob);
void RemoveAuraFromMobs(Mob *aura);
void RemoveAllMobs();
void RemoveAllClients();
void RemoveAllNPCs();
@@ -584,7 +585,6 @@ private:
private:
std::list<Bot*> bot_list;
#endif
};
class BulkZoneSpawnPacket {
+1
View File
@@ -87,6 +87,7 @@ typedef enum {
EVENT_DEATH_ZONE,
EVENT_USE_SKILL,
EVENT_COMBINE_VALIDATE,
EVENT_BOT_COMMAND,
_LargestEventID
} QuestEventID;
+48 -20
View File
@@ -1385,59 +1385,87 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
return;
}
uint32 copper = 0;
uint32 silver = 0;
uint32 gold = 0;
uint32 platinum = 0;
uint32 itemid = 0;
uint32 exp = 0;
QuestReward_Struct quest_reward;
quest_reward.mob_id = 0;
quest_reward.target_id = self->GetID();
quest_reward.copper = 0;
quest_reward.silver = 0;
quest_reward.gold = 0;
quest_reward.platinum = 0;
quest_reward.exp_reward = 0;
quest_reward.faction = 0;
quest_reward.faction_mod = 0;
bool faction = false;
std::fill(std::begin(quest_reward.item_id), std::end(quest_reward.item_id), -1);
auto cur = reward["copper"];
if (luabind::type(cur) != LUA_TNIL) {
try {
copper = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
quest_reward.copper = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed &) {
}
}
cur = reward["silver"];
if (luabind::type(cur) != LUA_TNIL) {
try {
silver = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
quest_reward.silver = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed &) {
}
}
cur = reward["gold"];
if (luabind::type(cur) != LUA_TNIL) {
try {
gold = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
quest_reward.gold = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed &) {
}
}
cur = reward["platinum"];
if (luabind::type(cur) != LUA_TNIL) {
try {
platinum = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
quest_reward.platinum = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed &) {
}
}
cur = reward["itemid"];
if (luabind::type(cur) != LUA_TNIL) {
try {
itemid = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
quest_reward.item_id[0] = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed &) {
}
}
// if you define both an itemid and items table, the itemid is thrown away
// should we error?
cur = reward["items"];
if (luabind::type(cur) == LUA_TTABLE) {
try {
// assume they defined a compatible table
for (int i = 1; i <= QUESTREWARD_COUNT; ++i) {
auto item = cur[i];
int cur_value = -1;
if (luabind::type(item) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<uint32>(item);
} catch (luabind::cast_failed &) {
}
} else {
break;
}
quest_reward.item_id[i - 1] = cur_value;
}
} catch (luabind::cast_failed &) {
}
}
cur = reward["exp"];
if (luabind::type(cur) != LUA_TNIL) {
try {
exp = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
quest_reward.exp_reward = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed &) {
}
}
@@ -1445,11 +1473,11 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
if (luabind::type(cur) != LUA_TNIL) {
try {
faction = luabind::object_cast<bool>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, faction);
self->QuestReward(target, quest_reward, faction);
}
bool Lua_Client::IsDead() {
+29 -19
View File
@@ -549,6 +549,14 @@ void lua_summon_all_player_corpses(uint32 char_id, float x, float y, float z, fl
quest_manager.summonallplayercorpses(char_id, glm::vec4(x, y, z, h));
}
int lua_get_player_corpse_count(uint32 char_id) {
return database.CountCharacterCorpses(char_id);
}
int lua_get_player_corpse_count_by_zone_id(uint32 char_id, uint32 zone_id) {
return database.CountCharacterCorpsesByZoneID(char_id, zone_id);
}
int lua_get_player_buried_corpse_count(uint32 char_id) {
return quest_manager.getplayerburiedcorpsecount(char_id);
}
@@ -571,7 +579,7 @@ void lua_task_selector(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
} else {
count = i - 1;
@@ -601,7 +609,7 @@ void lua_enable_task(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
} else {
count = i - 1;
@@ -628,7 +636,7 @@ void lua_disable_task(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
} else {
count = i - 1;
@@ -1156,7 +1164,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
spawn2_id = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1167,7 +1175,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
spawngroup_id = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1178,7 +1186,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
x = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1189,7 +1197,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
y = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1200,7 +1208,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
z = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1211,7 +1219,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
heading = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1222,7 +1230,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
respawn = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1233,7 +1241,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
variance = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
return;
}
} else {
@@ -1244,7 +1252,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
timeleft = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1252,7 +1260,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
grid = luabind::object_cast<uint32>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1260,7 +1268,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
condition_id = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1268,7 +1276,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
condition_min_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1276,7 +1284,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
enabled = luabind::object_cast<bool>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1284,7 +1292,7 @@ void lua_add_spawn_point(luabind::adl::object table) {
if(luabind::type(cur) != LUA_TNIL) {
try {
animation = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1399,7 +1407,7 @@ void lua_update_zone_header(std::string type, std::string value) {
try { \
npc_type->name = luabind::object_cast<c_type>(cur); \
} \
catch(luabind::cast_failed) { \
catch(luabind::cast_failed &) { \
npc_type->size = default_value; \
} \
} \
@@ -1415,7 +1423,7 @@ void lua_update_zone_header(std::string type, std::string value) {
std::string tmp = luabind::object_cast<std::string>(cur); \
strncpy(npc_type->name, tmp.c_str(), str_length); \
} \
catch(luabind::cast_failed) { \
catch(luabind::cast_failed &) { \
strncpy(npc_type->name, default_value, str_length); \
} \
} \
@@ -1663,6 +1671,8 @@ luabind::scope lua_register_general() {
luabind::def("toggle_spawn_event", &lua_toggle_spawn_event),
luabind::def("summon_buried_player_corpse", &lua_summon_buried_player_corpse),
luabind::def("summon_all_player_corpses", &lua_summon_all_player_corpses),
luabind::def("get_player_corpse_count", &lua_get_player_corpse_count),
luabind::def("get_player_corpse_count_by_zone_id", &lua_get_player_corpse_count_by_zone_id),
luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count),
luabind::def("bury_player_corpse", &lua_bury_player_corpse),
luabind::def("task_selector", &lua_task_selector),
+28 -28
View File
@@ -113,7 +113,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.armor_pen_flat = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -121,7 +121,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.crit_flat = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -129,7 +129,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.damage_flat = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -137,7 +137,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.hate_flat = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -145,7 +145,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.armor_pen_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -153,7 +153,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.crit_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -161,7 +161,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.damage_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -169,7 +169,7 @@ bool Lua_Mob::Attack(Lua_Mob other, int hand, bool from_riposte, bool is_striket
if(luabind::type(cur) != LUA_TNIL) {
try {
options.hate_percent = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
}
@@ -785,7 +785,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.speak_mode = static_cast<Journal::SpeakMode>(luabind::object_cast<int>(cur));
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -793,7 +793,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.journal_mode = static_cast<Journal::Mode>(luabind::object_cast<int>(cur));
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -801,7 +801,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.language = luabind::object_cast<int>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
@@ -809,7 +809,7 @@ void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::obj
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.message_type = luabind::object_cast<int>(cur);
} catch (luabind::cast_failed) {
} catch (luabind::cast_failed &) {
}
}
}
@@ -1568,7 +1568,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
race = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1576,7 +1576,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
gender = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1584,7 +1584,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
texture = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1592,7 +1592,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
helmtexture = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1600,7 +1600,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
haircolor = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1608,7 +1608,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
beardcolor = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1616,7 +1616,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
eyecolor1 = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1624,7 +1624,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
eyecolor2 = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1632,7 +1632,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
hairstyle = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1640,7 +1640,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
luclinface = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1648,7 +1648,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
beard = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1656,7 +1656,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
aa_title = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1664,7 +1664,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
drakkin_heritage = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1672,7 +1672,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
drakkin_tattoo = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1680,7 +1680,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
drakkin_details = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
@@ -1688,7 +1688,7 @@ void Lua_Mob::SendIllusionPacket(luabind::adl::object illusion) {
if(luabind::type(cur) != LUA_TNIL) {
try {
size = luabind::object_cast<float>(cur);
} catch(luabind::cast_failed) {
} catch(luabind::cast_failed &) {
}
}
+3 -1
View File
@@ -124,7 +124,8 @@ const char *LuaEvents[_LargestEventID] = {
"event_spawn_zone",
"event_death_zone",
"event_use_skill",
"event_combine_validate"
"event_combine_validate",
"event_bot_command"
};
extern Zone *zone;
@@ -208,6 +209,7 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet;
PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill;
PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate;
PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
+19
View File
@@ -539,6 +539,25 @@ void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client*
lua_setfield(L, -2, "tradeskill_id");
}
void handle_player_bot_command(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any>* extra_pointers) {
Seperator sep(data.c_str(), ' ', 10, 100, true);
std::string bot_command(sep.arg[0] + 1);
lua_pushstring(L, bot_command.c_str());
lua_setfield(L, -2, "bot_command");
luabind::adl::object args = luabind::newtable(L);
int max_args = sep.GetMaxArgNum();
for (int i = 1; i < max_args; ++i) {
if (strlen(sep.arg[i]) > 0) {
args[i] = std::string(sep.arg[i]);
}
}
args.push(L);
lua_setfield(L, -2, "args");
}
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers) {
+2
View File
@@ -99,6 +99,8 @@ void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client
std::vector<EQEmu::Any> *extra_pointers);
void handle_player_combine_validate(QuestInterface* parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any>* extra_pointers);
void handle_player_bot_command(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data,
std::vector<EQEmu::Any> *extra_pointers);
//Item
void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data,
+19 -2
View File
@@ -186,6 +186,7 @@ Mob::Mob(
last_hp_percent = 0;
last_hp = 0;
last_max_hp = 0;
current_speed = base_runspeed;
@@ -459,6 +460,8 @@ Mob::Mob(
#ifdef BOTS
m_manual_follow = false;
#endif
mob_scan_close.Trigger();
}
Mob::~Mob()
@@ -501,6 +504,8 @@ Mob::~Mob()
UninitializeBuffSlots();
entity_list.RemoveMobFromCloseLists(this);
entity_list.RemoveAuraFromMobs(this);
close_mobs.clear();
#ifdef BOTS
@@ -1330,6 +1335,16 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
* If our HP is different from last HP update call - let's update selves
*/
if (IsClient()) {
// delay to allow the client to catch up on buff states
if (max_hp != last_max_hp) {
last_max_hp = max_hp;
CastToClient()->hp_self_update_throttle_timer.Trigger();
return;
}
if (current_hp != last_hp || force_update_all) {
/**
@@ -1337,10 +1352,12 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
*/
if (this->CastToClient()->hp_self_update_throttle_timer.Check() || force_update_all) {
Log(Logs::General, Logs::HPUpdate,
"Mob::SendHPUpdate :: Update HP of self (%s) HP: %i last: %i skip_self: %s",
"Mob::SendHPUpdate :: Update HP of self (%s) HP: %i/%i last: %i/%i skip_self: %s",
this->GetCleanName(),
current_hp,
max_hp,
last_hp,
last_max_hp,
(skip_self ? "true" : "false")
);
@@ -1367,7 +1384,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal
}
}
int8 current_hp_percent = static_cast<int8>(max_hp == 0 ? 0 : static_cast<int>(current_hp * 100 / max_hp));
auto current_hp_percent = GetIntHPRatio();
Log(Logs::General,
Logs::HPUpdate,
+2 -2
View File
@@ -624,8 +624,7 @@ public:
//AI
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
inline uint32 GetLevelCon(uint8 iOtherLevel) const {
return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GRAY; }
inline uint32 GetLevelCon(uint8 iOtherLevel) const { return GetLevelCon(GetLevel(), iOtherLevel); }
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false);
bool RemoveFromHateList(Mob* mob);
@@ -1527,6 +1526,7 @@ protected:
int8 last_hp_percent;
int32 last_hp;
int32 last_max_hp;
int cur_wp;
glm::vec4 m_CurrentWayPoint;
+25 -5
View File
@@ -1693,12 +1693,32 @@ void NPC::AI_DoMovement() {
GetZ(),
GetGrid());
if (wandertype == GridRandomPath)
{
if (cur_wp == patrol)
{
// reached our randomly selected destination; force a pause
if (cur_wp_pause == 0)
{
if (Waypoints.size() > 0 && Waypoints[0].pause)
cur_wp_pause = Waypoints[0].pause;
else
cur_wp_pause = 38;
}
Log(Logs::Detail, Logs::AI, "NPC using wander type GridRandomPath on grid %d at waypoint %d has reached its random destination; pause time is %d", GetGrid(), cur_wp, cur_wp_pause);
}
else
cur_wp_pause = 0; // skipping pauses until destination
}
SetWaypointPause();
SetAppearance(eaStanding, false);
if (cur_wp_pause > 0) {
if (GetAppearance() != eaStanding) {
SetAppearance(eaStanding, false);
}
if (cur_wp_pause > 0 && m_CurrentWayPoint.w >= 0.0) {
RotateTo(m_CurrentWayPoint.w);
}
//kick off event_waypoint arrive
char temp[16];
sprintf(temp, "%d", cur_wp);
@@ -1789,12 +1809,12 @@ void NPC::AI_SetupNextWaypoint() {
}
}
if (wandertype == 4 && cur_wp == CastToNPC()->GetMaxWp()) {
if (wandertype == GridOneWayRepop && cur_wp == CastToNPC()->GetMaxWp()) {
CastToNPC()->Depop(true); //depop and restart spawn timer
if (found_spawn)
found_spawn->SetNPCPointerNull();
}
else if (wandertype == 6 && cur_wp == CastToNPC()->GetMaxWp()) {
else if (wandertype == GridOneWayDepop && cur_wp == CastToNPC()->GetMaxWp()) {
CastToNPC()->Depop(false);//depop without spawn timer
if (found_spawn)
found_spawn->SetNPCPointerNull();
-6
View File
@@ -705,12 +705,6 @@ bool NPC::Process()
SpellProcess();
if (mob_scan_close.Check()) {
LogAIScanClose(
"is_moving [{}] npc [{}] timer [{}]",
moving ? "true" : "false",
GetCleanName(),
mob_scan_close.GetDuration()
);
entity_list.ScanCloseMobs(close_mobs, this);
+3 -2
View File
@@ -303,7 +303,7 @@ public:
int GetMaxWp() const { return max_wp; }
void DisplayWaypointInfo(Client *to);
void CalculateNewWaypoint();
void AssignWaypoints(int32 grid);
void AssignWaypoints(int32 grid, int start_wp = 0);
void SetWaypointPause();
void UpdateWaypoint(int wp_index);
@@ -312,7 +312,8 @@ public:
void ResumeWandering();
void PauseWandering(int pausetime);
void MoveTo(const glm::vec4& position, bool saveguardspot);
void GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::vec3& location);
void GetClosestWaypoints(std::list<wplist> &wp_list, int count, const glm::vec3& location);
int GetClosestWaypoint(const glm::vec3& location);
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id
int32 GetEquipmentMaterial(uint8 material_slot) const;
+1 -1
View File
@@ -199,7 +199,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
}
#ifdef BOTS
else if (this->IsBot())
act_power = CastToBot()->GetBotFocusEffect(Bot::BotfocusPetPower, spell_id);
act_power = CastToBot()->GetBotFocusEffect(focusPetPower, spell_id);
#endif
}
else if (petpower > 0)
+15
View File
@@ -1910,6 +1910,21 @@ bool QuestManager::summonallplayercorpses(uint32 char_id, const glm::vec4& posit
return true;
}
int QuestManager::getplayercorpsecount(uint32 char_id) {
if (char_id > 0) {
return database.CountCharacterCorpses(char_id);
}
return 0;
}
int QuestManager::getplayercorpsecountbyzoneid(uint32 char_id, uint32 zone_id) {
if (char_id > 0 && zone_id > 0) {
return database.CountCharacterCorpsesByZoneID(char_id, zone_id);
}
return 0;
}
uint32 QuestManager::getplayerburiedcorpsecount(uint32 char_id) {
uint32 Result = 0;
+2
View File
@@ -172,6 +172,8 @@ public:
bool summonburiedplayercorpse(uint32 char_id, const glm::vec4& position);
bool summonallplayercorpses(uint32 char_id, const glm::vec4& position);
uint32 getplayerburiedcorpsecount(uint32 char_id);
int getplayercorpsecount(uint32 char_id);
int getplayercorpsecountbyzoneid(uint32 char_id, uint32 zone_id);
bool buryplayercorpse(uint32 char_id);
void forcedooropen(uint32 doorid, bool altmode);
void forcedoorclose(uint32 doorid, bool altmode);
+18 -4
View File
@@ -233,6 +233,20 @@ bool Spawn2::Process() {
}
currentnpcid = npcid;
glm::vec4 loc(x, y, z, heading);
int starting_wp = 0;
if (spawn_group->wp_spawns && grid_ > 0)
{
glm::vec4 wploc;
starting_wp = database.GetRandomWaypointLocFromGrid(wploc, zone->GetZoneID(), grid_);
if (wploc.x != 0.0f || wploc.y != 0.0f || wploc.z != 0.0f)
{
loc = wploc;
Log(Logs::General, Logs::Spawns, "spawning at random waypoint #%i loc: (%.3f, %.3f, %.3f).", starting_wp , loc.x, loc.y, loc.z);
}
}
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Water);
npc->mod_prespawn(this);
@@ -275,7 +289,7 @@ bool Spawn2::Process() {
z
);
LoadGrid();
LoadGrid(starting_wp);
}
else {
LogSpawns("Spawn2 [{}]: Group [{}] spawned [{}] ([{}]) at ([{}], [{}], [{}]). Grid loading delayed",
@@ -302,7 +316,7 @@ void Spawn2::Disable()
enabled = false;
}
void Spawn2::LoadGrid() {
void Spawn2::LoadGrid(int start_wp) {
if (!npcthis)
return;
if (grid_ < 1)
@@ -311,8 +325,8 @@ void Spawn2::LoadGrid() {
return;
//dont set an NPC's grid until its loaded for them.
npcthis->SetGrid(grid_);
npcthis->AssignWaypoints(grid_);
LogSpawns("Spawn2 [{}]: Loading grid [{}] for [{}]", spawn2_id, grid_, npcthis->GetName());
npcthis->AssignWaypoints(grid_, start_wp);
LogSpawns("Spawn2 [{}]: Loading grid [{}] for [{}]; starting wp is [{}]", spawn2_id, grid_, npcthis->GetName(), start_wp);
}
/*
+1 -1
View File
@@ -36,7 +36,7 @@ public:
uint16 cond_id = SC_AlwaysEnabled, int16 min_value = 0, bool in_enabled = true, EmuAppearance anim = eaStanding);
~Spawn2();
void LoadGrid();
void LoadGrid(int start_wp = 0);
void Enable() { enabled = true; }
void Disable();
bool Enabled() { return enabled; }
+11 -5
View File
@@ -48,7 +48,8 @@ SpawnGroup::SpawnGroup(
int delay_in,
int despawn_in,
uint32 despawn_timer_in,
int min_delay_in
int min_delay_in,
bool wp_spawns_in
)
{
id = in_id;
@@ -63,6 +64,7 @@ SpawnGroup::SpawnGroup(
delay = delay_in;
despawn = despawn_in;
despawn_timer = despawn_timer_in;
wp_spawns = wp_spawns_in;
}
uint32 SpawnGroup::GetNPCType(uint16 in_filter)
@@ -198,7 +200,8 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
spawngroup.delay,
spawngroup.despawn,
spawngroup.despawn_timer,
spawngroup.mindelay
spawngroup.mindelay,
spawngroup.wp_spawns
FROM
spawn2,
spawngroup
@@ -229,7 +232,8 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
atoi(row[8]),
atoi(row[9]),
atoi(row[10]),
atoi(row[11])
atoi(row[11]),
atoi(row[12])
);
spawn_group_list->AddSpawnGroup(new_spawn_group);
@@ -305,7 +309,8 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
spawngroup.delay,
spawngroup.despawn,
spawngroup.despawn_timer,
spawngroup.mindelay
spawngroup.mindelay,
spawngroup.wp_spawns
FROM
spawngroup
WHERE
@@ -332,7 +337,8 @@ bool ZoneDatabase::LoadSpawnGroupsByID(int spawn_group_id, SpawnGroupList *spawn
atoi(row[8]),
atoi(row[9]),
atoi(row[10]),
atoi(row[11])
atoi(row[11]),
atoi(row[12])
);
spawn_group_list->AddSpawnGroup(new_spawn_group);
+3 -1
View File
@@ -49,13 +49,15 @@ public:
int delay_in,
int despawn_in,
uint32 despawn_timer_in,
int min_delay_in
int min_delay_in,
bool wp_spawns_in
);
~SpawnGroup();
uint32 GetNPCType(uint16 condition_value_filter=1);
void AddSpawnEntry(SpawnEntry *newEntry);
uint32 id;
bool wp_spawns; // if true, spawn NPCs at a random waypoint location (if spawnpoint has a grid) instead of the spawnpoint's loc
float roamdist;
float roambox[4];
int min_delay;
+55
View File
@@ -286,6 +286,9 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
dmg = -dmg;
}
// hack fix for client health not reflecting server value
last_hp = 0;
//do any AAs apply to these spells?
if(dmg < 0) {
if (!PassCastRestriction(false, spells[spell_id].base2[i], true))
@@ -1820,6 +1823,58 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
break;
}
case SE_SummonCorpseZone:
{
if (IsClient()) {
Client* client_target = this->CastToClient();
if (client_target->IsGrouped()) {
Group* group = client_target->GetGroup();
if (!group->IsGroupMember(caster)) {
if (caster != this) {
caster->MessageString(Chat::Red, SUMMON_ONLY_GROUP_CORPSE);
break;
}
}
} else if (caster) {
if (caster->IsRaidGrouped()) {
Raid *raid = caster->GetRaid();
uint32 group_id = raid->GetGroup(caster->GetName());
if (group_id > 0 && group_id < MAX_RAID_GROUPS) {
if (raid->GetGroup(client_target->GetName()) != group_id) {
caster->MessageString(Chat::Red, SUMMON_ONLY_GROUP_CORPSE);
break;
}
}
} else {
if (caster != this) {
caster->MessageString(Chat::Red, SUMMON_ONLY_GROUP_CORPSE);
break;
}
}
}
if (client_target) {
if (database.CountCharacterCorpses(client_target->CharacterID()) == 0) {
if (caster == this) {
Message(Chat::Yellow, "You have no corpses to summon.");
} else {
caster->Message(Chat::Yellow, "%s has no corpses to summon.", client_target->GetCleanName());
}
} else {
if (caster == this) {
Message(Chat::Spells, "Summoning your corpses.");
} else {
caster->MessageString(Chat::Spells, SUMMONING_CORPSE_ZONE, client_target->GetCleanName());
}
client_target->SummonAllCorpses(client_target->GetPosition());
}
} else {
MessageString(Chat::Spells, TARGET_NOT_FOUND);
LogError("[{}] attempted to cast spell id [{}] with spell effect SE_SummonCorpseZone, but could not cast target into a Client object", GetCleanName(), spell_id);
}
}
break;
}
case SE_AddMeleeProc:
case SE_WeaponProc:
{
+2 -2
View File
@@ -3455,9 +3455,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
// 1 = PCs, 2 = NPCs
if (spells[spell_id].pcnpc_only_flag && spells[spell_id].targettype != ST_AETargetHateList &&
spells[spell_id].targettype != ST_HateList) {
if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc())
if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc() && !spelltar->IsBot())
return false;
else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc()))
else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc() || spelltar->IsBot()))
return false;
}
+3
View File
@@ -65,6 +65,7 @@
#define SILENCED_STRING 207 //You *CANNOT* cast spells, you have been silenced!
#define CANNOT_AFFECT_PC 210 //That spell can not affect this target PC.
#define SPELL_NEED_TAR 214 //You must first select a target for this spell!
#define SUMMON_ONLY_GROUP_CORPSE 215 //You must first target a living group member whose corpse you wish to summon.
#define ONLY_ON_CORPSES 221 //This spell only works on corpses.
#define CANT_DRAIN_SELF 224 //You can't drain yourself!
#define CORPSE_NOT_VALID 230 //This corpse is not valid.
@@ -169,6 +170,7 @@
#define PVP_ON 552 //You are now player kill and follow the ways of Discord.
#define GENERIC_STRINGID_SAY 554 //%1 says '%T2'
#define CANNOT_WAKE 555 //%1 tells you, 'I am unable to wake %2, master.'
#define SUMMONING_CORPSE_ZONE 596 //Summoning %1's corpse(s).
#define PET_HOLD_SET_ON 698 //The pet hold mode has been set to on.
#define PET_HOLD_SET_OFF 699 //The pet hold mode has been set to off.
#define PET_FOCUS_SET_ON 700 //The pet focus mode has been set to on.
@@ -415,6 +417,7 @@
#define TARGET_PLAYER_FOR_GUILD_STATUS 12260
#define GROUP_INVITEE_NOT_FOUND 12268 //You must target a player or use /invite <name> to invite someone to your group.
#define GROUP_INVITEE_SELF 12270 //12270 You cannot invite yourself.
#define ALREADY_IN_PARTY 12272 //That person is already in your party.
#define NO_LONGER_HIDDEN 12337 //You are no longer hidden.
#define STOP_SNEAKING 12338 //You stop sneaking
#define NOT_IN_CONTROL 12368 //You do not have control of yourself right now.
+142 -27
View File
@@ -159,7 +159,7 @@ void NPC::PauseWandering(int pausetime)
if (GetGrid() != 0) {
moving = false;
DistractedFromGrid = true;
LogPathing("Paused Wandering requested. Grid [{}]. Resuming in [{}] ms (0=not until told)", GetGrid(), pausetime);
LogPathing("Paused Wandering requested. Grid [{}]. Resuming in [{}] seconds (0=not until told)", GetGrid(), pausetime);
StopNavigation();
if (pausetime < 1) { // negative grid number stops him dead in his tracks until ResumeWandering()
SetGrid(0 - GetGrid());
@@ -244,14 +244,14 @@ void NPC::CalculateNewWaypoint()
int old_wp = cur_wp;
bool reached_end = false;
bool reached_beginning = false;
if (cur_wp == max_wp)
if (cur_wp == max_wp - 1) //cur_wp starts at 0, max_wp starts at 1.
reached_end = true;
if (cur_wp == 0)
reached_beginning = true;
switch (wandertype)
{
case 0: //circle
case GridCircular:
{
if (reached_end)
cur_wp = 0;
@@ -259,10 +259,10 @@ void NPC::CalculateNewWaypoint()
cur_wp = cur_wp + 1;
break;
}
case 1: //10 closest
case GridRandom10:
{
std::list<wplist> closest;
GetClosestWaypoint(closest, 10, glm::vec3(GetPosition()));
GetClosestWaypoints(closest, 10, glm::vec3(GetPosition()));
auto iter = closest.begin();
if (closest.size() != 0)
{
@@ -273,30 +273,64 @@ void NPC::CalculateNewWaypoint()
break;
}
case 2: //random
case GridRandom:
case GridCenterPoint:
{
cur_wp = zone->random.Int(0, Waypoints.size() - 1);
if (cur_wp == old_wp)
if (wandertype == GridCenterPoint && !reached_beginning)
{
if (cur_wp == (Waypoints.size() - 1))
cur_wp = 0;
}
else
{
cur_wp = zone->random.Int(0, Waypoints.size() - 1);
if (cur_wp == old_wp || (wandertype == GridCenterPoint && cur_wp == 0))
{
if (cur_wp > 0)
if (cur_wp == (Waypoints.size() - 1))
{
cur_wp--;
if (cur_wp > 0)
{
cur_wp--;
}
}
}
else if (cur_wp == 0)
{
if ((Waypoints.size() - 1) > 0)
else if (cur_wp == 0)
{
cur_wp++;
if ((Waypoints.size() - 1) > 0)
{
cur_wp++;
}
}
}
}
break;
}
case 3: //patrol
case GridRandomCenterPoint:
{
bool on_center = Waypoints[cur_wp].centerpoint;
std::vector<wplist> random_waypoints;
for (auto &w : Waypoints)
{
wplist wpl = w;
if (wpl.index != cur_wp &&
((on_center && !wpl.centerpoint) || (!on_center && wpl.centerpoint)))
{
random_waypoints.push_back(w);
}
}
if (random_waypoints.size() == 0)
{
cur_wp = 0;
}
else
{
int windex = zone->random.Roll0(random_waypoints.size());
cur_wp = random_waypoints[windex].index;
}
break;
}
case GridPatrol:
{
if (reached_end)
patrol = 1;
@@ -309,16 +343,16 @@ void NPC::CalculateNewWaypoint()
break;
}
case 4: //goto the end and depop with spawn timer
case 6: //goto the end and depop without spawn timer
case GridOneWayRepop:
case GridOneWayDepop:
{
cur_wp = cur_wp + 1;
break;
}
case 5: //pick random closest 5 and pick one that's in sight
case GridRand5LoS:
{
std::list<wplist> closest;
GetClosestWaypoint(closest, 5, glm::vec3(GetPosition()));
GetClosestWaypoints(closest, 5, glm::vec3(GetPosition()));
auto iter = closest.begin();
while (iter != closest.end())
@@ -341,6 +375,25 @@ void NPC::CalculateNewWaypoint()
}
break;
}
case GridRandomPath: // randomly select a waypoint but follow path to it instead of walk directly to it ignoring walls
{
if (Waypoints.size() == 0)
{
cur_wp = 0;
}
else
{
if (cur_wp == patrol) // reutilizing patrol member instead of making new member for this wander type; here we use it to save a random waypoint
{
while (patrol == cur_wp)
patrol = zone->random.Int(0, Waypoints.size() - 1);
}
if (patrol > cur_wp)
cur_wp = cur_wp + 1;
else
cur_wp = cur_wp - 1;
}
}
}
// Preserve waypoint setting for quest controlled NPCs
@@ -357,7 +410,30 @@ bool wp_distance_pred(const wp_distance& left, const wp_distance& right)
return left.dist < right.dist;
}
void NPC::GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::vec3& location)
int NPC::GetClosestWaypoint(const glm::vec3& location)
{
if (Waypoints.size() <= 1)
return 0;
int closest = 0;
float closestDist = 9999999.0f;
float dist;
for (int i = 0; i < Waypoints.size(); ++i)
{
dist = DistanceSquared(location, glm::vec3(Waypoints[i].x, Waypoints[i].y, Waypoints[i].z));
if (dist < closestDist)
{
closestDist = dist;
closest = i;
}
}
return closest;
}
// fills wp_list with the closest count number of waypoints
void NPC::GetClosestWaypoints(std::list<wplist> &wp_list, int count, const glm::vec3& location)
{
wp_list.clear();
if (Waypoints.size() <= count)
@@ -485,7 +561,7 @@ void Mob::StopNavigation() {
mMovementManager->StopNavigation(this);
}
void NPC::AssignWaypoints(int32 grid)
void NPC::AssignWaypoints(int32 grid, int start_wp)
{
if (grid == 0)
return; // grid ID 0 not supported
@@ -518,7 +594,7 @@ void NPC::AssignWaypoints(int32 grid)
SetGrid(grid); // Assign grid number
// Retrieve all waypoints for this grid
query = StringFormat("SELECT `x`,`y`,`z`,`pause`,`heading` "
query = StringFormat("SELECT `x`,`y`,`z`,`pause`,`heading`, `centerpoint` "
"FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %i "
"ORDER BY `number`", grid, zone->GetZoneID());
results = database.QueryDatabase(query);
@@ -539,14 +615,22 @@ void NPC::AssignWaypoints(int32 grid)
newwp.pause = atoi(row[3]);
newwp.heading = atof(row[4]);
newwp.centerpoint = atobool(row[5]);
Waypoints.push_back(newwp);
}
UpdateWaypoint(0);
cur_wp = start_wp;
UpdateWaypoint(start_wp);
SetWaypointPause();
if (wandertype == 1 || wandertype == 2 || wandertype == 5)
if (wandertype == GridRandomPath) {
cur_wp = GetClosestWaypoint(glm::vec3(GetPosition()));
patrol = cur_wp;
}
if (wandertype == GridRandom10 || wandertype == GridRandom || wandertype == GridRand5LoS)
CalculateNewWaypoint();
}
void Mob::SendTo(float new_x, float new_y, float new_z) {
@@ -687,7 +771,7 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) {
float Mob::GetZOffset() const {
float offset = 3.125f;
switch (race) {
switch (GetModel()) {
case RACE_BASILISK_436:
offset = 0.577f;
break;
@@ -1058,6 +1142,37 @@ int ZoneDatabase::GetHighestWaypoint(uint32 zoneid, uint32 gridid) {
return atoi(row[0]);
}
int ZoneDatabase::GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, int grid)
{
loc.x = loc.y = loc.z = loc.w = 0.0f;
std::string query = StringFormat("SELECT `x`,`y`,`z`,`heading` "
"FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %u ORDER BY `number`", grid, zone->GetZoneID());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
Log(Logs::General, Logs::Error, "MySQL Error while trying get random waypoint loc from grid %i in zoneid %u; %s", grid, zoneid, results.ErrorMessage().c_str());
return 0;
}
if (results.RowCount() > 0)
{
int roll = zone->random.Int(0, results.RowCount() - 1);
int i = 0;
auto row = results.begin();
while (i < roll)
{
row++;
i++;
}
loc.x = atof(row[0]);
loc.y = atof(row[1]);
loc.z = atof(row[2]);
loc.w = atof(row[3]);
return i;
}
return 0;
}
void NPC::SaveGuardSpotCharm()
{
m_GuardPointSaved = m_GuardPoint;
+41
View File
@@ -4707,6 +4707,47 @@ bool ZoneDatabase::SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zone_id
return (CorpseCount > 0);
}
int ZoneDatabase::CountCharacterCorpses(uint32 char_id) {
std::string query = fmt::format(
SQL(
SELECT
COUNT(*)
FROM
character_corpses
WHERE
charid = '{}'
),
char_id
);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
return atoi(row[0]);
}
return 0;
}
int ZoneDatabase::CountCharacterCorpsesByZoneID(uint32 char_id, uint32 zone_id) {
std::string query = fmt::format(
SQL(
SELECT
COUNT(*)
FROM
character_corpses
WHERE
charid = '{}'
AND
zone_id = '{}'
),
char_id,
zone_id
);
auto results = QueryDatabase(query);
for (auto row = results.begin(); row != results.end(); ++row) {
return atoi(row[0]);
}
return 0;
}
bool ZoneDatabase::UnburyCharacterCorpse(uint32 db_id, uint32 new_zone_id, uint16 new_instance_id, const glm::vec4& position) {
std::string query = StringFormat("UPDATE `character_corpses` "
"SET `is_buried` = 0, `zone_id` = %u, `instance_id` = %u, "
+4
View File
@@ -47,6 +47,7 @@ struct wplist {
float z;
int pause;
float heading;
bool centerpoint;
};
#pragma pack(1)
@@ -356,6 +357,8 @@ public:
bool DeleteCharacterCorpse(uint32 dbid);
bool SummonAllCharacterCorpses(uint32 char_id, uint32 dest_zoneid, uint16 dest_instanceid, const glm::vec4& position);
bool SummonAllGraveyardCorpses(uint32 cur_zoneid, uint32 dest_zoneid, uint16 dest_instanceid, const glm::vec4& position);
int CountCharacterCorpses(uint32 char_id);
int CountCharacterCorpsesByZoneID(uint32 char_id, uint32 zone_id);
bool UnburyCharacterCorpse(uint32 dbid, uint32 new_zoneid, uint16 dest_instanceid, const glm::vec4& position);
bool LoadCharacterCorpses(uint32 iZoneID, uint16 iInstanceID);
bool DeleteGraveyard(uint32 zone_id, uint32 graveyard_id);
@@ -432,6 +435,7 @@ public:
void AssignGrid(Client *client, int grid, int spawn2id);
int GetHighestGrid(uint32 zoneid);
int GetHighestWaypoint(uint32 zoneid, uint32 gridid);
int GetRandomWaypointLocFromGrid(glm::vec4 &loc, uint16 zoneid, int grid);
/* NPCs */
+1 -1
View File
@@ -44,7 +44,7 @@ struct NPCType
uint16 race;
uint8 class_;
uint8 bodytype; // added for targettype support
uint8 deity; //not loaded from DB
uint32 deity; //not loaded from DB
uint8 level;
uint32 npc_id;
uint8 texture;