mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-02 20:56:37 +00:00
Move out faction changes to later db version as it is still pending.
This commit is contained in:
+3
-2
@@ -82,6 +82,8 @@ SET(zone_sources
|
||||
merc.cpp
|
||||
mob.cpp
|
||||
mob_ai.cpp
|
||||
mob_appearance.cpp
|
||||
mob_movement_manager.cpp
|
||||
mob_info.cpp
|
||||
mod_functions.cpp
|
||||
net.cpp
|
||||
@@ -93,7 +95,6 @@ SET(zone_sources
|
||||
pathfinder_interface.cpp
|
||||
pathfinder_nav_mesh.cpp
|
||||
pathfinder_null.cpp
|
||||
pathfinder_waypoint.cpp
|
||||
pathing.cpp
|
||||
perl_client.cpp
|
||||
perl_doors.cpp
|
||||
@@ -205,6 +206,7 @@ SET(zone_headers
|
||||
message.h
|
||||
merc.h
|
||||
mob.h
|
||||
mob_movement_manager.h
|
||||
net.h
|
||||
npc.h
|
||||
npc_ai.h
|
||||
@@ -214,7 +216,6 @@ SET(zone_headers
|
||||
pathfinder_interface.h
|
||||
pathfinder_nav_mesh.h
|
||||
pathfinder_null.h
|
||||
pathfinder_waypoint.h
|
||||
perlpacket.h
|
||||
petitions.h
|
||||
pets.h
|
||||
|
||||
+16
-16
@@ -126,7 +126,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
|
||||
(npc_dup != nullptr) ? npc_dup : npc_type, //make sure we give the NPC the correct data pointer
|
||||
0,
|
||||
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
|
||||
FlyMode3);
|
||||
GravityBehavior::Water);
|
||||
|
||||
if (followme)
|
||||
swarm_pet_npc->SetFollowID(GetID());
|
||||
@@ -225,7 +225,7 @@ void Mob::TypesTemporaryPets(uint32 typesid, Mob *targ, const char *name_overrid
|
||||
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
|
||||
0,
|
||||
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
|
||||
FlyMode3);
|
||||
GravityBehavior::Water);
|
||||
|
||||
if (followme)
|
||||
swarm_pet_npc->SetFollowID(GetID());
|
||||
@@ -286,7 +286,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
make_npc->min_dmg = 1;
|
||||
|
||||
//base stats
|
||||
make_npc->cur_hp = (GetLevel() * 55);
|
||||
make_npc->current_hp = (GetLevel() * 55);
|
||||
make_npc->max_hp = (GetLevel() * 55);
|
||||
make_npc->STR = 85 + (GetLevel() * 3);
|
||||
make_npc->STA = 85 + (GetLevel() * 3);
|
||||
@@ -356,51 +356,51 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
case PALADIN:
|
||||
//SPECATK_TRIPLE
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->cur_hp = make_npc->cur_hp * 150 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 150 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 150 / 100;
|
||||
make_npc->npc_spells_id = 8;
|
||||
break;
|
||||
case SHADOWKNIGHT:
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->cur_hp = make_npc->cur_hp * 150 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 150 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 150 / 100;
|
||||
make_npc->npc_spells_id = 9;
|
||||
break;
|
||||
case RANGER:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->cur_hp = make_npc->cur_hp * 135 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 135 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 135 / 100;
|
||||
make_npc->npc_spells_id = 10;
|
||||
break;
|
||||
case BARD:
|
||||
strcpy(make_npc->special_abilities, "6,1");
|
||||
make_npc->cur_hp = make_npc->cur_hp * 110 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
make_npc->npc_spells_id = 11;
|
||||
break;
|
||||
case BEASTLORD:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->cur_hp = make_npc->cur_hp * 110 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
make_npc->npc_spells_id = 12;
|
||||
break;
|
||||
case ROGUE:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->cur_hp = make_npc->cur_hp * 110 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 110 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 110 / 100;
|
||||
break;
|
||||
case MONK:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->cur_hp = make_npc->cur_hp * 135 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 135 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 135 / 100;
|
||||
break;
|
||||
case WARRIOR:
|
||||
case BERSERKER:
|
||||
strcpy(make_npc->special_abilities, "7,1");
|
||||
make_npc->max_dmg = make_npc->max_dmg * 150 /100;
|
||||
make_npc->cur_hp = make_npc->cur_hp * 175 / 100;
|
||||
make_npc->current_hp = make_npc->current_hp * 175 / 100;
|
||||
make_npc->max_hp = make_npc->max_hp * 175 / 100;
|
||||
break;
|
||||
default:
|
||||
@@ -413,7 +413,7 @@ void Mob::WakeTheDead(uint16 spell_id, Mob *target, uint32 duration)
|
||||
make_npc->d_melee_texture1 = 0;
|
||||
make_npc->d_melee_texture2 = 0;
|
||||
|
||||
auto npca = new NPC(make_npc, 0, GetPosition(), FlyMode3);
|
||||
auto npca = new NPC(make_npc, 0, GetPosition(), GravityBehavior::Water);
|
||||
|
||||
if(!npca->GetSwarmInfo()){
|
||||
auto nSI = new SwarmPet;
|
||||
@@ -488,7 +488,7 @@ void Client::ResetAA() {
|
||||
|
||||
database.DeleteCharacterLeadershipAAs(CharacterID());
|
||||
// undefined for these clients
|
||||
if (ClientVersionBit() & EQEmu::versions::bit_TitaniumAndEarlier)
|
||||
if (ClientVersionBit() & EQEmu::versions::maskTitaniumAndEarlier)
|
||||
Kick();
|
||||
}
|
||||
|
||||
@@ -1221,12 +1221,12 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
|
||||
|
||||
// Bards can cast instant cast AAs while they are casting another song
|
||||
if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) {
|
||||
if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) {
|
||||
if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::spells::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) {
|
||||
return;
|
||||
}
|
||||
ExpendAlternateAdvancementCharge(ability->id);
|
||||
} else {
|
||||
if(!CastSpell(rank->spell, target_id, EQEmu::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) {
|
||||
if(!CastSpell(rank->spell, target_id, EQEmu::spells::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1455,7 +1455,7 @@ bool Mob::CanUseAlternateAdvancementRank(AA::Rank *rank) {
|
||||
//the one titanium hack i will allow
|
||||
//just to make sure we dont crash the client with newer aas
|
||||
//we'll exclude any expendable ones
|
||||
if(IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_TitaniumAndEarlier) {
|
||||
if(IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::maskTitaniumAndEarlier) {
|
||||
if(ability->charges > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+1
-1
@@ -954,7 +954,7 @@ bool Mob::CombatRange(Mob* other)
|
||||
if (_DistNoRoot <= size_mod)
|
||||
{
|
||||
//A hack to kill an exploit till we get something better.
|
||||
if (flymode == 0 && _zDist > 500 && !CheckLastLosState()) {
|
||||
if (flymode != GravityBehavior::Flying && _zDist > 500 && !CheckLastLosState()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+29
-24
@@ -33,6 +33,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "zone.h"
|
||||
#include "lua_parser.h"
|
||||
#include "fastmath.h"
|
||||
#include "mob.h"
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
@@ -1524,7 +1526,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
}
|
||||
other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks);
|
||||
@@ -1792,7 +1794,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
|
||||
//this generates a lot of 'updates' to the client that the client does not need
|
||||
BuffFadeNonPersistDeath();
|
||||
if (RuleB(Character, UnmemSpellsOnDeath)) {
|
||||
if ((ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) && RuleB(Character, RespawnFromHover))
|
||||
if ((ClientVersionBit() & EQEmu::versions::maskSoFAndLater) && RuleB(Character, RespawnFromHover))
|
||||
UnmemSpellAll(true);
|
||||
else
|
||||
UnmemSpellAll(false);
|
||||
@@ -1855,7 +1857,7 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
|
||||
from these and overwrite what we set in pp anyway
|
||||
*/
|
||||
|
||||
if (LeftCorpse && (ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) && RuleB(Character, RespawnFromHover))
|
||||
if (LeftCorpse && (ClientVersionBit() & EQEmu::versions::maskSoFAndLater) && RuleB(Character, RespawnFromHover))
|
||||
{
|
||||
ClearDraggedCorpses();
|
||||
RespawnFromHoverTimer.Start(RuleI(Character, RespawnFromHoverTimer) * 1000);
|
||||
@@ -2128,7 +2130,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Skill
|
||||
if (IsLDoNTrapped())
|
||||
{
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false);
|
||||
SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false);
|
||||
SetLDoNTrapSpellID(0);
|
||||
SetLDoNTrapped(false);
|
||||
SetLDoNTrapDetected(false);
|
||||
@@ -2668,12 +2670,6 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
|
||||
if (!zone->watermap->InLiquid(glm::vec3(other->GetPosition()))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// first add self
|
||||
|
||||
// The damage on the hate list is used to award XP to the killer. This check is to prevent Killstealing.
|
||||
@@ -2695,16 +2691,24 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
|
||||
#ifdef BOTS
|
||||
// if other is a bot, add the bots client to the hate list
|
||||
if (other->IsBot()) {
|
||||
if (other->CastToBot()->GetBotOwner() && other->CastToBot()->GetBotOwner()->CastToClient()->GetFeigned()) {
|
||||
AddFeignMemory(other->CastToBot()->GetBotOwner()->CastToClient());
|
||||
while (other->IsBot()) {
|
||||
auto other_ = other->CastToBot();
|
||||
if (!other_ || !other_->GetBotOwner())
|
||||
break;
|
||||
|
||||
auto owner_ = other_->GetBotOwner()->CastToClient();
|
||||
if (!owner_ || owner_->IsDead() || !owner_->InZone()) // added isdead and inzone checks to avoid issues in AddAutoXTarget(...) below
|
||||
break;
|
||||
|
||||
if (owner_->GetFeigned()) {
|
||||
AddFeignMemory(owner_);
|
||||
}
|
||||
else {
|
||||
if (!hate_list.IsEntOnHateList(other->CastToBot()->GetBotOwner())) {
|
||||
hate_list.AddEntToHateList(other->CastToBot()->GetBotOwner(), 0, 0, false, true);
|
||||
other->CastToBot()->GetBotOwner()->CastToClient()->AddAutoXTarget(this);
|
||||
}
|
||||
else if (!hate_list.IsEntOnHateList(owner_)) {
|
||||
hate_list.AddEntToHateList(owner_, 0, 0, false, true);
|
||||
owner_->AddAutoXTarget(this); // this was being called on dead/out-of-zone clients
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif //BOTS
|
||||
|
||||
@@ -2716,6 +2720,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
||||
else {
|
||||
if (!hate_list.IsEntOnHateList(other->CastToMerc()->GetMercOwner()))
|
||||
hate_list.AddEntToHateList(other->CastToMerc()->GetMercOwner(), 0, 0, false, true);
|
||||
// if mercs are reworked to include adding 'this' to owner's xtarget list, this should reflect bots code above
|
||||
}
|
||||
} //MERC
|
||||
|
||||
@@ -3786,7 +3791,7 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
|
||||
if (IsBuffSpell(spell_id)) { // hots
|
||||
// message to caster
|
||||
if (caster->IsClient() && caster == this) {
|
||||
if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater)
|
||||
if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater)
|
||||
FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime,
|
||||
HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name);
|
||||
else
|
||||
@@ -3794,7 +3799,7 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
|
||||
YOU_HEALED, GetCleanName(), itoa(acthealed));
|
||||
}
|
||||
else if (caster->IsClient() && caster != this) {
|
||||
if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater)
|
||||
if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater)
|
||||
caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime,
|
||||
HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed),
|
||||
spells[spell_id].name);
|
||||
@@ -3804,7 +3809,7 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
|
||||
}
|
||||
// message to target
|
||||
if (IsClient() && caster != this) {
|
||||
if (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater)
|
||||
if (CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater)
|
||||
FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime,
|
||||
HOT_HEALED_OTHER, caster->GetCleanName(),
|
||||
itoa(acthealed), spells[spell_id].name);
|
||||
@@ -5033,7 +5038,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
|
||||
hit.damage_done = headshot;
|
||||
}
|
||||
else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot
|
||||
if (defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) {
|
||||
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
|
||||
hit.damage_done *= 2;
|
||||
Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE);
|
||||
}
|
||||
@@ -5441,7 +5446,7 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts)
|
||||
// For now, SPECATK_QUAD means innate DW when Combat:UseLiveCombatRounds is true
|
||||
if ((GetSpecialAbility(SPECATK_INNATE_DW) ||
|
||||
(RuleB(Combat, UseLiveCombatRounds) && GetSpecialAbility(SPECATK_QUAD))) ||
|
||||
GetEquipment(EQEmu::textures::weaponSecondary) != 0) {
|
||||
GetEquippedItemFromTextureSlot(EQEmu::textures::weaponSecondary) != 0) {
|
||||
if (CheckDualWield()) {
|
||||
Attack(target, EQEmu::invslot::slotSecondary, false, false, false, opts);
|
||||
if (CanThisClassDoubleAttack() && GetLevel() > 35 && CheckDoubleAttack()) {
|
||||
@@ -5473,4 +5478,4 @@ int32 Mob::GetHPRegen() const
|
||||
int32 Mob::GetManaRegen() const
|
||||
{
|
||||
return mana_regen;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include "raids.h"
|
||||
|
||||
Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record)
|
||||
: NPC(type_data, 0, owner->GetPosition(), FlyMode3), spell_id(record.spell_id), distance(record.distance),
|
||||
: NPC(type_data, 0, owner->GetPosition(), GravityBehavior::Flying), spell_id(record.spell_id), distance(record.distance),
|
||||
remove_timer(record.duration), movement_timer(100), process_timer(100), aura_id(-1)
|
||||
{
|
||||
GiveNPCTypeData(type_data); // we will delete this later on
|
||||
|
||||
@@ -52,10 +52,6 @@ void Mob::CalcBonuses()
|
||||
We set this here because NPC's can cast spells to change walkspeed/runspeed
|
||||
*/
|
||||
float get_walk_speed = static_cast<float>(0.025f * this->GetWalkspeed());
|
||||
if (get_walk_speed >= 0.9 && this->fix_z_timer.GetDuration() != 100) {
|
||||
this->fix_z_timer.SetTimer(100);
|
||||
}
|
||||
|
||||
rooted = FindType(SE_Root);
|
||||
}
|
||||
|
||||
|
||||
+57
-81
@@ -29,7 +29,7 @@
|
||||
extern volatile bool is_zone_loaded;
|
||||
|
||||
// This constructor is used during the bot create command
|
||||
Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1) {
|
||||
Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) {
|
||||
if(botOwner) {
|
||||
this->SetBotOwner(botOwner);
|
||||
this->_botOwnerCharacterID = botOwner->CharacterID();
|
||||
@@ -39,6 +39,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
|
||||
}
|
||||
|
||||
m_inv.SetInventoryVersion(EQEmu::versions::MobVersion::Bot);
|
||||
m_inv.SetGMInventory(false); // bot expansions are not currently implemented (defaults to static)
|
||||
|
||||
_guildRank = 0;
|
||||
_guildId = 0;
|
||||
@@ -89,7 +90,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
|
||||
GenerateAppearance();
|
||||
GenerateBaseStats();
|
||||
// Calculate HitPoints Last As It Uses Base Stats
|
||||
cur_hp = GenerateBaseHitPoints();
|
||||
current_hp = GenerateBaseHitPoints();
|
||||
current_mana = GenerateBaseManaPoints();
|
||||
cur_end = CalcBaseEndurance();
|
||||
hp_regen = CalcHPRegen();
|
||||
@@ -103,7 +104,8 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm
|
||||
}
|
||||
|
||||
// This constructor is used when the bot is loaded out of the database
|
||||
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) : NPC(&npcTypeData, nullptr, glm::vec4(), 0, false), rest_timer(1)
|
||||
Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData)
|
||||
: NPC(&npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1)
|
||||
{
|
||||
this->_botOwnerCharacterID = botOwnerCharacterID;
|
||||
if(this->_botOwnerCharacterID > 0)
|
||||
@@ -112,6 +114,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
auto bot_owner = GetBotOwner();
|
||||
|
||||
m_inv.SetInventoryVersion(EQEmu::versions::MobVersion::Bot);
|
||||
m_inv.SetGMInventory(false); // bot expansions are not currently implemented (defaults to static)
|
||||
|
||||
_guildRank = 0;
|
||||
_guildId = 0;
|
||||
@@ -136,7 +139,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
_baseATK = npcTypeData.ATK;
|
||||
_baseRace = npcTypeData.race;
|
||||
_baseGender = npcTypeData.gender;
|
||||
cur_hp = npcTypeData.cur_hp;
|
||||
current_hp = npcTypeData.current_hp;
|
||||
current_mana = npcTypeData.Mana;
|
||||
RestRegenHP = 0;
|
||||
RestRegenMana = 0;
|
||||
@@ -208,10 +211,10 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
|
||||
hp_regen = CalcHPRegen();
|
||||
mana_regen = CalcManaRegen();
|
||||
end_regen = CalcEnduranceRegen();
|
||||
if(cur_hp > max_hp)
|
||||
cur_hp = max_hp;
|
||||
if(current_hp > max_hp)
|
||||
current_hp = max_hp;
|
||||
|
||||
if(cur_hp <= 0) {
|
||||
if(current_hp <= 0) {
|
||||
SetHP(max_hp/5);
|
||||
SetMana(0);
|
||||
BuffFadeAll();
|
||||
@@ -284,8 +287,7 @@ void Bot::ChangeBotArcherWeapons(bool isArcher) {
|
||||
void Bot::Sit() {
|
||||
if(IsMoving()) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
tar_ndx = 0;
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
SetAppearance(eaSitting);
|
||||
@@ -336,7 +338,7 @@ NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::str
|
||||
BotNPCType.drakkin_heritage = drakkinHeritage;
|
||||
BotNPCType.drakkin_tattoo = drakkinTattoo;
|
||||
BotNPCType.drakkin_details = drakkinDetails;
|
||||
BotNPCType.cur_hp = hp;
|
||||
BotNPCType.current_hp = hp;
|
||||
BotNPCType.Mana = mana;
|
||||
BotNPCType.MR = mr;
|
||||
BotNPCType.CR = cr;
|
||||
@@ -386,7 +388,7 @@ NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string b
|
||||
Result.maxlevel = botLevel;
|
||||
Result.size = 6.0;
|
||||
Result.npc_id = 0;
|
||||
Result.cur_hp = 0;
|
||||
Result.current_hp = 0;
|
||||
Result.drakkin_details = 0;
|
||||
Result.drakkin_heritage = 0;
|
||||
Result.drakkin_tattoo = 0;
|
||||
@@ -1827,7 +1829,6 @@ bool Bot::Process() {
|
||||
if(tic_timer.Check()) {
|
||||
//6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting
|
||||
if(!IsMoving() && !IsEngaged()) {
|
||||
SendPosition();
|
||||
if(IsSitting()) {
|
||||
if(!rest_timer.Enabled())
|
||||
rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000);
|
||||
@@ -2526,7 +2527,7 @@ void Bot::AI_Process() {
|
||||
if (GetArchetype() == ARCHETYPE_CASTER || GetClass() == ROGUE) {
|
||||
if (tar_distance <= melee_distance_max) {
|
||||
if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) {
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotWalkspeed(), true, false);
|
||||
WalkTo(Goal.x, Goal.y, Goal.z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2538,7 +2539,7 @@ void Bot::AI_Process() {
|
||||
if (caster_distance_min && tar_distance < caster_distance_min && !tar->IsFeared()) { // Caster back-off adjustment
|
||||
if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) {
|
||||
if (DistanceSquared(Goal, tar->GetPosition()) <= caster_distance_max) {
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotWalkspeed(), true, false);
|
||||
WalkTo(Goal.x, Goal.y, Goal.z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2546,7 +2547,7 @@ void Bot::AI_Process() {
|
||||
else if (tar_distance < melee_distance_min) { // Melee back-off adjustment
|
||||
if (PlotPositionAroundTarget(this, Goal.x, Goal.y, Goal.z)) {
|
||||
if (DistanceSquared(Goal, tar->GetPosition()) <= melee_distance_max) {
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotWalkspeed(), true, false);
|
||||
WalkTo(Goal.x, Goal.y, Goal.z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2554,7 +2555,7 @@ void Bot::AI_Process() {
|
||||
else if (backstab_weapon && !behind_mob) { // Move the rogue to behind the mob
|
||||
if (PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) {
|
||||
if (DistanceSquared(Goal, tar->GetPosition()) <= melee_distance_max) {
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotRunspeed(), true, false); // rogues are agile enough to run in melee range
|
||||
RunTo(Goal.x, Goal.y, Goal.z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2565,7 +2566,7 @@ void Bot::AI_Process() {
|
||||
PlotPositionAroundTarget(tar, Goal.x, Goal.y, Goal.z)) // If we're behind the mob, we can attack when it's enraged
|
||||
{
|
||||
if (DistanceSquared(Goal, tar->GetPosition()) <= melee_distance_max) {
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotWalkspeed(), true, false);
|
||||
WalkTo(Goal.x, Goal.y, Goal.z);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2710,35 +2711,19 @@ void Bot::AI_Process() {
|
||||
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
|
||||
|
||||
Goal = GetTarget()->GetPosition();
|
||||
|
||||
if (RuleB(Bots, UsePathing) && zone->pathing) {
|
||||
bool WaypointChanged, NodeReached;
|
||||
|
||||
Goal = UpdatePath(Goal.x, Goal.y, Goal.z,
|
||||
GetBotRunspeed(), WaypointChanged, NodeReached);
|
||||
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
}
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotRunspeed());
|
||||
|
||||
RunTo(Goal.x, Goal.y, Goal.z);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (IsMoving())
|
||||
StopMoving();
|
||||
else
|
||||
SendPosition();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fix Z when following during pull, not when engaged and stationary
|
||||
if (IsMoving() && fix_z_timer_engaged.Check()) {
|
||||
FixZ();
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetTarget() && GetTarget()->IsFeared() && !spellend_timer.Enabled() && AI_think_timer->Check()) {
|
||||
if (!IsFacingMob(GetTarget()))
|
||||
@@ -2753,8 +2738,6 @@ void Bot::AI_Process() {
|
||||
} // end not in combat range
|
||||
|
||||
if (!IsMoving() && !spellend_timer.Enabled()) { // This may actually need work...
|
||||
SendPosition();
|
||||
|
||||
if (GetBotStance() == BotStancePassive)
|
||||
return;
|
||||
|
||||
@@ -2789,10 +2772,10 @@ void Bot::AI_Process() {
|
||||
if (IsMoving())
|
||||
StopMoving();
|
||||
|
||||
Warp(glm::vec3(my_guard));
|
||||
Teleport(my_guard);
|
||||
|
||||
if (HasPet())
|
||||
GetPet()->Warp(glm::vec3(my_guard));
|
||||
GetPet()->Teleport(my_guard);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2802,10 +2785,10 @@ void Bot::AI_Process() {
|
||||
if (IsMoving())
|
||||
StopMoving();
|
||||
|
||||
Warp(glm::vec3(leash_owner->GetPosition()));
|
||||
Teleport(leash_owner->GetPosition());
|
||||
|
||||
if (HasPet())
|
||||
GetPet()->Warp(glm::vec3(leash_owner->GetPosition()));
|
||||
GetPet()->Teleport(leash_owner->GetPosition());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -2833,23 +2816,18 @@ void Bot::AI_Process() {
|
||||
if (rest_timer.Enabled())
|
||||
rest_timer.Disable();
|
||||
|
||||
int speed = GetBotRunspeed();
|
||||
bool running = true;
|
||||
if (fm_dist < GetFollowDistance() + BOT_FOLLOW_DISTANCE_WALK)
|
||||
speed = GetBotWalkspeed();
|
||||
running = false;
|
||||
|
||||
Goal = follow_mob->GetPosition();
|
||||
|
||||
if (RuleB(Bots, UsePathing) && zone->pathing) {
|
||||
bool WaypointChanged, NodeReached;
|
||||
|
||||
Goal = UpdatePath(Goal.x, Goal.y, Goal.z,
|
||||
speed, WaypointChanged, NodeReached);
|
||||
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
if (running) {
|
||||
RunTo(Goal.x, Goal.y, Goal.z);
|
||||
}
|
||||
else {
|
||||
WalkTo(Goal.x, Goal.y, Goal.z);
|
||||
}
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2931,14 +2909,14 @@ void Bot::PetAIProcess() {
|
||||
if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
|
||||
// Move the rogue to behind the mob
|
||||
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
|
||||
botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
|
||||
botPet->RunTo(newX, newY, newZ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(GetTarget() == botPet->GetTarget() && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
|
||||
// If the bot owner and the bot are fighting the same mob, then move the pet to the rear arc of the mob
|
||||
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
|
||||
botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
|
||||
botPet->RunTo(newX, newY, newZ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -2953,7 +2931,7 @@ void Bot::PetAIProcess() {
|
||||
moveBehindMob = true;
|
||||
|
||||
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) {
|
||||
botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
|
||||
botPet->RunTo(newX, newY, newZ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3036,15 +3014,14 @@ void Bot::PetAIProcess() {
|
||||
botPet->SetRunAnimSpeed(0);
|
||||
if(!botPet->IsRooted()) {
|
||||
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName());
|
||||
botPet->CalculateNewPosition(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed());
|
||||
botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ());
|
||||
return;
|
||||
} else {
|
||||
botPet->SetHeading(botPet->GetTarget()->GetHeading());
|
||||
if(moved) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
botPet->SendPosition();
|
||||
botPet->SetMoving(false);
|
||||
StopNavigation();
|
||||
botPet->StopNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3064,15 +3041,14 @@ void Bot::PetAIProcess() {
|
||||
float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition());
|
||||
botPet->SetRunAnimSpeed(0);
|
||||
if(dist > 184) {
|
||||
botPet->CalculateNewPosition(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed());
|
||||
botPet->RunTo(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ());
|
||||
return;
|
||||
} else {
|
||||
botPet->SetHeading(botPet->GetTarget()->GetHeading());
|
||||
if(moved) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
botPet->SendPosition();
|
||||
botPet->SetMoving(false);
|
||||
StopNavigation();
|
||||
botPet->StopNavigation();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -3134,7 +3110,7 @@ bool Bot::Spawn(Client* botCharacterOwner) {
|
||||
entity_list.AddBot(this, true, true);
|
||||
// Load pet
|
||||
LoadPet();
|
||||
this->SendPosition();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
// there is something askew with spawn struct appearance fields...
|
||||
// I re-enabled this until I can sort it out
|
||||
uint32 itemID = 0;
|
||||
@@ -5173,7 +5149,7 @@ int Bot::GetHandToHandDamage(void) {
|
||||
// everyone uses this in the revamp!
|
||||
int skill = GetSkill(EQEmu::skills::SkillHandtoHand);
|
||||
int epic = 0;
|
||||
if (CastToNPC()->GetEquipment(EQEmu::textures::armorHands) == 10652 && GetLevel() > 46)
|
||||
if (CastToNPC()->GetEquippedItemFromTextureSlot(EQEmu::textures::armorHands) == 10652 && GetLevel() > 46)
|
||||
epic = 280;
|
||||
if (epic > skill)
|
||||
skill = epic;
|
||||
@@ -5195,7 +5171,7 @@ int Bot::GetHandToHandDamage(void) {
|
||||
9, 9, 9, 9, 9, 10, 10, 10, 10, 10, // 31-40
|
||||
10, 11, 11, 11, 11, 11, 11, 12, 12}; // 41-49
|
||||
if (GetClass() == MONK) {
|
||||
if (CastToNPC()->GetEquipment(EQEmu::textures::armorHands) == 10652 && GetLevel() > 50)
|
||||
if (CastToNPC()->GetEquippedItemFromTextureSlot(EQEmu::textures::armorHands) == 10652 && GetLevel() > 50)
|
||||
return 9;
|
||||
if (level > 62)
|
||||
return 15;
|
||||
@@ -6287,7 +6263,7 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) {
|
||||
Mob::DoBuffTic(buff, slot, caster);
|
||||
}
|
||||
|
||||
bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost,
|
||||
bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot, int32 cast_time, int32 mana_cost,
|
||||
uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) {
|
||||
bool Result = false;
|
||||
if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) {
|
||||
@@ -6327,7 +6303,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot,
|
||||
return false;
|
||||
}
|
||||
|
||||
if(slot < EQEmu::CastingSlot::MaxGems && !CheckFizzle(spell_id)) {
|
||||
if(slot < EQEmu::spells::CastingSlot::MaxGems && !CheckFizzle(spell_id)) {
|
||||
int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE;
|
||||
InterruptSpell(fizzle_msg, 0x121, spell_id);
|
||||
|
||||
@@ -6341,7 +6317,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot,
|
||||
Log(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong);
|
||||
bardsong = 0;
|
||||
bardsong_target_id = 0;
|
||||
bardsong_slot = EQEmu::CastingSlot::Gem1;
|
||||
bardsong_slot = EQEmu::spells::CastingSlot::Gem1;
|
||||
bardsong_timer.Disable();
|
||||
}
|
||||
|
||||
@@ -6471,7 +6447,7 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot) {
|
||||
bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::spells::CastingSlot slot) {
|
||||
bool Result = false;
|
||||
SpellTargetType targetType = spells[spell_id].targettype;
|
||||
if(targetType == ST_GroupClientAndPet) {
|
||||
@@ -6484,7 +6460,7 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) {
|
||||
bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) {
|
||||
bool Result = false;
|
||||
if(GetClass() == BARD)
|
||||
cast_time = 0;
|
||||
@@ -6588,7 +6564,7 @@ void Bot::GenerateSpecialAttacks() {
|
||||
SetSpecialAbility(SPECATK_TRIPLE, 1);
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) {
|
||||
bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) {
|
||||
if(GetClass() == BARD) {
|
||||
if(!ApplyNextBardPulse(bardsong, this, bardsong_slot))
|
||||
InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong);
|
||||
@@ -6598,7 +6574,7 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::Cast
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) {
|
||||
bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) {
|
||||
if(spellTarget) {
|
||||
if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) {
|
||||
bool noGroupSpell = false;
|
||||
@@ -6610,7 +6586,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::
|
||||
bool spelltypeequal = ((spelltype == 2) || (spelltype == 16) || (spelltype == 32));
|
||||
bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].targettype == ST_Self));
|
||||
bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN));
|
||||
bool slotequal = (slot == EQEmu::CastingSlot::Item);
|
||||
bool slotequal = (slot == EQEmu::spells::CastingSlot::Item);
|
||||
if(spellequal || slotequal) {
|
||||
if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) {
|
||||
if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) &&
|
||||
@@ -6649,7 +6625,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) {
|
||||
bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) {
|
||||
bool isMainGroupMGB = false;
|
||||
if(isMainGroupMGB && (GetClass() != BARD)) {
|
||||
BotGroupSay(this, "MGB %s", spells[spell_id].name);
|
||||
@@ -7185,14 +7161,14 @@ int32 Bot::CalcMaxHP() {
|
||||
bot_hp += GroupLeadershipAAHealthEnhancement();
|
||||
bot_hp += (bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f));
|
||||
max_hp = bot_hp;
|
||||
if (cur_hp > max_hp)
|
||||
cur_hp = max_hp;
|
||||
if (current_hp > max_hp)
|
||||
current_hp = max_hp;
|
||||
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[0];
|
||||
if(hp_perc_cap) {
|
||||
int curHP_cap = ((max_hp * hp_perc_cap) / 100);
|
||||
if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1]))
|
||||
cur_hp = curHP_cap;
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1]))
|
||||
current_hp = curHP_cap;
|
||||
}
|
||||
return max_hp;
|
||||
}
|
||||
@@ -8732,7 +8708,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
if(IsCasting())
|
||||
InterruptSpell();
|
||||
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -322,9 +322,9 @@ public:
|
||||
virtual void SetAttackTimer();
|
||||
uint32 GetClassHPFactor();
|
||||
virtual int32 CalcMaxHP();
|
||||
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic);
|
||||
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic);
|
||||
void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color);
|
||||
void Camp(bool databaseSave = true);
|
||||
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false);
|
||||
@@ -425,12 +425,12 @@ public:
|
||||
virtual float GetAOERange(uint16 spell_id);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100);
|
||||
virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr);
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0,
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0,
|
||||
uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::spells::CastingSlot slot);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0);
|
||||
|
||||
// Bot Equipment & Inventory Class Methods
|
||||
void BotTradeSwapItem(Client* client, int16 lootSlot, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true);
|
||||
|
||||
@@ -5273,7 +5273,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
|
||||
|
||||
bot_iter->WipeHateList();
|
||||
bot_iter->SetTarget(nullptr);
|
||||
bot_iter->Warp(glm::vec3(c->GetPosition()));
|
||||
bot_iter->Teleport(c->GetPosition());
|
||||
bot_iter->DoAnim(0);
|
||||
|
||||
if (!bot_iter->HasPet())
|
||||
@@ -5281,7 +5281,7 @@ void bot_subcommand_bot_summon(Client *c, const Seperator *sep)
|
||||
|
||||
bot_iter->GetPet()->WipeHateList();
|
||||
bot_iter->GetPet()->SetTarget(nullptr);
|
||||
bot_iter->GetPet()->Warp(glm::vec3(c->GetPosition()));
|
||||
bot_iter->GetPet()->Teleport(c->GetPosition());
|
||||
}
|
||||
|
||||
if (sbl.size() == 1)
|
||||
@@ -7774,7 +7774,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id,
|
||||
if (annouce_cast)
|
||||
Bot::BotGroupSay(casting_bot, "Attempting to cast '%s' on %s", spells[spell_id].name, target_mob->GetCleanName());
|
||||
|
||||
return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::CastingSlot::Gem2, -1, -1, dont_root_before);
|
||||
return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::spells::CastingSlot::Gem2, -1, -1, dont_root_before);
|
||||
}
|
||||
|
||||
bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, const char *alias, const char *command)
|
||||
|
||||
+127
-355
@@ -54,6 +54,7 @@ extern volatile bool RunLoops;
|
||||
#include "guild_mgr.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "queryserv.h"
|
||||
#include "mob_movement_manager.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
extern EntityList entity_list;
|
||||
@@ -119,7 +120,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
0,
|
||||
0
|
||||
),
|
||||
position_timer(250),
|
||||
hpupdate_timer(2000),
|
||||
camp_timer(29000),
|
||||
process_timer(100),
|
||||
@@ -167,6 +167,7 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
for (int client_filter = 0; client_filter < _FilterCount; client_filter++)
|
||||
ClientFilters[client_filter] = FilterShow;
|
||||
|
||||
mMovementManager->AddClient(this);
|
||||
character_id = 0;
|
||||
conn_state = NoPacketsReceived;
|
||||
client_data_loaded = false;
|
||||
@@ -221,7 +222,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
npcflag = false;
|
||||
npclevel = 0;
|
||||
pQueuedSaveWorkID = 0;
|
||||
position_timer_counter = 0;
|
||||
position_update_same_count = 0;
|
||||
fishing_timer.Disable();
|
||||
shield_timer.Disable();
|
||||
@@ -287,14 +287,6 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
XPRate = 100;
|
||||
current_endurance = 0;
|
||||
|
||||
m_TimeSinceLastPositionCheck = 0;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
m_ShadowStepExemption = 0;
|
||||
m_KnockBackExemption = 0;
|
||||
m_PortExemption = 0;
|
||||
m_SenseExemption = 0;
|
||||
m_AssistExemption = 0;
|
||||
m_CheatDetectMoved = false;
|
||||
CanUseReport = true;
|
||||
aa_los_them_mob = nullptr;
|
||||
los_status = false;
|
||||
@@ -359,6 +351,8 @@ Client::Client(EQStreamInterface* ieqs)
|
||||
}
|
||||
|
||||
Client::~Client() {
|
||||
mMovementManager->RemoveClient(this);
|
||||
|
||||
#ifdef BOTS
|
||||
Bot::ProcessBotOwnerRefDelete(this);
|
||||
#endif
|
||||
@@ -1135,7 +1129,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
CheckLDoNHail(GetTarget());
|
||||
CheckEmoteHail(GetTarget(), message);
|
||||
|
||||
if(DistanceSquaredNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) {
|
||||
if(DistanceNoZ(m_Position, GetTarget()->GetPosition()) <= RuleI(Range, Say)) {
|
||||
NPC *tar = GetTarget()->CastToNPC();
|
||||
parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language);
|
||||
|
||||
@@ -1905,9 +1899,9 @@ void Client::CheckManaEndUpdate() {
|
||||
mana_update->cur_mana = GetMana();
|
||||
mana_update->max_mana = GetMaxMana();
|
||||
mana_update->spawn_id = GetID();
|
||||
if ((ClientVersionBit() & EQEmu::versions::ClientVersionBit::bit_SoDAndLater) != 0)
|
||||
if ((ClientVersionBit() & EQEmu::versions::ClientVersionBitmask::maskSoDAndLater) != 0)
|
||||
QueuePacket(mana_packet); // do we need this with the OP_ManaChange packet above?
|
||||
entity_list.QueueClientsByXTarget(this, mana_packet, false, EQEmu::versions::ClientVersionBit::bit_SoDAndLater);
|
||||
entity_list.QueueClientsByXTarget(this, mana_packet, false, EQEmu::versions::ClientVersionBitmask::maskSoDAndLater);
|
||||
safe_delete(mana_packet);
|
||||
|
||||
last_reported_mana_percent = this->GetManaPercent();
|
||||
@@ -1930,9 +1924,9 @@ void Client::CheckManaEndUpdate() {
|
||||
endurance_update->cur_end = GetEndurance();
|
||||
endurance_update->max_end = GetMaxEndurance();
|
||||
endurance_update->spawn_id = GetID();
|
||||
if ((ClientVersionBit() & EQEmu::versions::ClientVersionBit::bit_SoDAndLater) != 0)
|
||||
if ((ClientVersionBit() & EQEmu::versions::ClientVersionBitmask::maskSoDAndLater) != 0)
|
||||
QueuePacket(endurance_packet); // do we need this with the OP_ManaChange packet above?
|
||||
entity_list.QueueClientsByXTarget(this, endurance_packet, false, EQEmu::versions::ClientVersionBit::bit_SoDAndLater);
|
||||
entity_list.QueueClientsByXTarget(this, endurance_packet, false, EQEmu::versions::ClientVersionBitmask::maskSoDAndLater);
|
||||
safe_delete(endurance_packet);
|
||||
|
||||
last_reported_endurance_percent = this->GetEndurancePercent();
|
||||
@@ -2083,6 +2077,7 @@ bool Client::ChangeFirstName(const char* in_firstname, const char* gmname)
|
||||
|
||||
void Client::SetGM(bool toggle) {
|
||||
m_pp.gm = toggle ? 1 : 0;
|
||||
m_inv.SetGMInventory((bool)m_pp.gm);
|
||||
Message(13, "You are %s a GM.", m_pp.gm ? "now" : "no longer");
|
||||
SendAppearancePacket(AT_GM, m_pp.gm);
|
||||
Save();
|
||||
@@ -2971,13 +2966,12 @@ bool Client::BindWound(Mob *bindmob, bool start, bool fail)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Client::SetMaterial(int16 in_slot, uint32 item_id) {
|
||||
const EQEmu::ItemData* item = database.GetItem(item_id);
|
||||
if (item && item->IsClassCommon())
|
||||
{
|
||||
void Client::SetMaterial(int16 in_slot, uint32 item_id)
|
||||
{
|
||||
const EQEmu::ItemData *item = database.GetItem(item_id);
|
||||
if (item && item->IsClassCommon()) {
|
||||
uint8 matslot = EQEmu::InventoryProfile::CalcMaterialFromSlot(in_slot);
|
||||
if (matslot != EQEmu::textures::materialInvalid)
|
||||
{
|
||||
if (matslot != EQEmu::textures::materialInvalid) {
|
||||
m_pp.item_material.Slot[matslot].Material = GetEquipmentMaterial(matslot);
|
||||
}
|
||||
}
|
||||
@@ -3061,7 +3055,7 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){
|
||||
Filter0(FilterMissedMe);
|
||||
Filter1(FilterDamageShields);
|
||||
|
||||
if (ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) {
|
||||
if (ClientVersionBit() & EQEmu::versions::maskSoDAndLater) {
|
||||
if (filter->filters[FilterDOT] == 0)
|
||||
ClientFilters[FilterDOT] = FilterShow;
|
||||
else if (filter->filters[FilterDOT] == 1)
|
||||
@@ -3082,7 +3076,7 @@ void Client::ServerFilter(SetServerFilter_Struct* filter){
|
||||
Filter1(FilterFocusEffects);
|
||||
Filter1(FilterPetSpells);
|
||||
|
||||
if (ClientVersionBit() & EQEmu::versions::bit_SoDAndLater) {
|
||||
if (ClientVersionBit() & EQEmu::versions::maskSoDAndLater) {
|
||||
if (filter->filters[FilterHealOverTime] == 0)
|
||||
ClientFilters[FilterHealOverTime] = FilterShow;
|
||||
// This is called 'Show Mine Only' in the clients, but functions the same as show
|
||||
@@ -4956,7 +4950,7 @@ void Client::HandleLDoNOpen(NPC *target)
|
||||
if(target->GetLDoNTrapSpellID() != 0)
|
||||
{
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SetLDoNTrapSpellID(0);
|
||||
target->SetLDoNTrapped(false);
|
||||
target->SetLDoNTrapDetected(false);
|
||||
@@ -5078,7 +5072,7 @@ void Client::HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type)
|
||||
break;
|
||||
case -1:
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SetLDoNTrapSpellID(0);
|
||||
target->SetLDoNTrapped(false);
|
||||
target->SetLDoNTrapDetected(false);
|
||||
@@ -5097,7 +5091,7 @@ void Client::HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type)
|
||||
if(target->IsLDoNTrapped())
|
||||
{
|
||||
Message_StringID(13, LDON_ACCIDENT_SETOFF2);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff);
|
||||
target->SetLDoNTrapSpellID(0);
|
||||
target->SetLDoNTrapped(false);
|
||||
target->SetLDoNTrapDetected(false);
|
||||
@@ -5330,177 +5324,6 @@ void Client::ShowSkillsWindow()
|
||||
this->SendPopupToClient(WindowTitle, WindowText.c_str());
|
||||
}
|
||||
|
||||
void Client::SetShadowStepExemption(bool v)
|
||||
{
|
||||
if(v == true)
|
||||
{
|
||||
uint32 cur_time = Timer::GetCurrentTime();
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
|
||||
m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed);
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
{
|
||||
if(IsShadowStepExempted())
|
||||
{
|
||||
if(m_DistanceSinceLastPositionCheck > 800)
|
||||
{
|
||||
CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
else if(IsKnockBackExempted())
|
||||
{
|
||||
//still potential to trigger this if you're knocked back off a
|
||||
//HUGE fall that takes > 2.5 seconds
|
||||
if(speed > 30.0f)
|
||||
{
|
||||
CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
else if(!IsPortExempted())
|
||||
{
|
||||
if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ()))
|
||||
{
|
||||
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
CheatDetected(MQWarp, GetX(), GetY(), GetZ());
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheatDetected(MQWarpLight, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
}
|
||||
m_ShadowStepExemption = v;
|
||||
}
|
||||
|
||||
void Client::SetKnockBackExemption(bool v)
|
||||
{
|
||||
if(v == true)
|
||||
{
|
||||
uint32 cur_time = Timer::GetCurrentTime();
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
{
|
||||
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
|
||||
m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed);
|
||||
if(IsShadowStepExempted())
|
||||
{
|
||||
if(m_DistanceSinceLastPositionCheck > 800)
|
||||
{
|
||||
CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
else if(IsKnockBackExempted())
|
||||
{
|
||||
//still potential to trigger this if you're knocked back off a
|
||||
//HUGE fall that takes > 2.5 seconds
|
||||
if(speed > 30.0f)
|
||||
{
|
||||
CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
else if(!IsPortExempted())
|
||||
{
|
||||
if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ()))
|
||||
{
|
||||
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
CheatDetected(MQWarp, GetX(), GetY(), GetZ());
|
||||
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheatDetected(MQWarpLight, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
}
|
||||
m_KnockBackExemption = v;
|
||||
}
|
||||
|
||||
void Client::SetPortExemption(bool v)
|
||||
{
|
||||
if(v == true)
|
||||
{
|
||||
uint32 cur_time = Timer::GetCurrentTime();
|
||||
if((cur_time - m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck);
|
||||
int runs = GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
{
|
||||
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
|
||||
m_DistanceSinceLastPositionCheck, (cur_time - m_TimeSinceLastPositionCheck), speed);
|
||||
if(IsShadowStepExempted())
|
||||
{
|
||||
if(m_DistanceSinceLastPositionCheck > 800)
|
||||
{
|
||||
CheatDetected(MQWarpShadowStep, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
else if(IsKnockBackExempted())
|
||||
{
|
||||
//still potential to trigger this if you're knocked back off a
|
||||
//HUGE fall that takes > 2.5 seconds
|
||||
if(speed > 30.0f)
|
||||
{
|
||||
CheatDetected(MQWarpKnockBack, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
else if(!IsPortExempted())
|
||||
{
|
||||
if(!IsMQExemptedArea(zone->GetZoneID(), GetX(), GetY(), GetZ()))
|
||||
{
|
||||
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
CheatDetected(MQWarp, GetX(), GetY(), GetZ());
|
||||
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheatDetected(MQWarpLight, GetX(), GetY(), GetZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
}
|
||||
m_PortExemption = v;
|
||||
}
|
||||
|
||||
void Client::Signal(uint32 data)
|
||||
{
|
||||
char buf[32];
|
||||
@@ -5509,158 +5332,6 @@ void Client::Signal(uint32 data)
|
||||
parse->EventPlayer(EVENT_SIGNAL, this, buf, 0);
|
||||
}
|
||||
|
||||
const bool Client::IsMQExemptedArea(uint32 zoneID, float x, float y, float z) const
|
||||
{
|
||||
float max_dist = 90000;
|
||||
switch(zoneID)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
float delta = (x-(-713.6));
|
||||
delta *= delta;
|
||||
float distance = delta;
|
||||
delta = (y-(-160.2));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(-12.8));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
delta = (x-(-153.8));
|
||||
delta *= delta;
|
||||
distance = delta;
|
||||
delta = (y-(-30.3));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(8.2));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
float delta = (x-(-682.5));
|
||||
delta *= delta;
|
||||
float distance = delta;
|
||||
delta = (y-(147.0));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(-9.9));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
delta = (x-(-655.4));
|
||||
delta *= delta;
|
||||
distance = delta;
|
||||
delta = (y-(10.5));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(-51.8));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
break;
|
||||
}
|
||||
case 62:
|
||||
case 75:
|
||||
case 114:
|
||||
case 209:
|
||||
{
|
||||
//The portals are so common in paineel/felwitheb that checking
|
||||
//distances wouldn't be worth it cause unless you're porting to the
|
||||
//start field you're going to be triggering this and that's a level of
|
||||
//accuracy I'm willing to sacrifice
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 24:
|
||||
{
|
||||
float delta = (x-(-183.0));
|
||||
delta *= delta;
|
||||
float distance = delta;
|
||||
delta = (y-(-773.3));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(54.1));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
delta = (x-(-8.8));
|
||||
delta *= delta;
|
||||
distance = delta;
|
||||
delta = (y-(-394.1));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(41.1));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
delta = (x-(-310.3));
|
||||
delta *= delta;
|
||||
distance = delta;
|
||||
delta = (y-(-1411.6));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(-42.8));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
delta = (x-(-183.1));
|
||||
delta *= delta;
|
||||
distance = delta;
|
||||
delta = (y-(-1409.8));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
delta = (z-(37.1));
|
||||
delta *= delta;
|
||||
distance += delta;
|
||||
|
||||
if(distance < max_dist)
|
||||
return true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 110:
|
||||
case 34:
|
||||
case 96:
|
||||
case 93:
|
||||
case 68:
|
||||
case 84:
|
||||
{
|
||||
if(GetBoatID() != 0)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Client::SendRewards()
|
||||
{
|
||||
std::vector<ClientReward> rewards;
|
||||
@@ -5952,7 +5623,7 @@ void Client::SuspendMinion()
|
||||
memset(&m_suspendedminion, 0, sizeof(struct PetInfo));
|
||||
// TODO: These pet command states need to be synced ...
|
||||
// Will just fix them for now
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater) {
|
||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||
SetPetCommandState(PET_BUTTON_STOP, 0);
|
||||
SetPetCommandState(PET_BUTTON_REGROUP, 0);
|
||||
@@ -6493,7 +6164,7 @@ void Client::LocateCorpse()
|
||||
SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY()));
|
||||
SetTarget(ClosestCorpse);
|
||||
SendTargetCommand(ClosestCorpse->GetID());
|
||||
SendPositionUpdate(2);
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0, true);
|
||||
}
|
||||
else if(!GetTarget())
|
||||
Message_StringID(clientMessageError, SENSE_CORPSE_NONE);
|
||||
@@ -6658,7 +6329,7 @@ void Client::Doppelganger(uint16 spell_id, Mob *target, const char *name_overrid
|
||||
(npc_dup!=nullptr)?npc_dup:npc_type, //make sure we give the NPC the correct data pointer
|
||||
0,
|
||||
GetPosition() + glm::vec4(swarmPetLocations[summon_count], 0.0f, 0.0f),
|
||||
FlyMode3);
|
||||
GravityBehavior::Water);
|
||||
|
||||
if(!swarm_pet_npc->GetSwarmInfo()){
|
||||
auto nSI = new SwarmPet;
|
||||
@@ -7961,7 +7632,7 @@ void Client::SendClearMercInfo()
|
||||
|
||||
void Client::DuplicateLoreMessage(uint32 ItemID)
|
||||
{
|
||||
if (!(m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater))
|
||||
if (!(m_ClientVersionBit & EQEmu::versions::maskRoFAndLater))
|
||||
{
|
||||
Message_StringID(0, PICK_LORE);
|
||||
return;
|
||||
@@ -8856,11 +8527,11 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
|
||||
}
|
||||
|
||||
void Client::SendHPUpdateMarquee(){
|
||||
if (!this || !this->IsClient() || !this->cur_hp || !this->max_hp)
|
||||
if (!this || !this->IsClient() || !this->current_hp || !this->max_hp)
|
||||
return;
|
||||
|
||||
/* Health Update Marquee Display: Custom*/
|
||||
uint8 health_percentage = (uint8)(this->cur_hp * 100 / this->max_hp);
|
||||
uint8 health_percentage = (uint8)(this->current_hp * 100 / this->max_hp);
|
||||
if (health_percentage >= 100)
|
||||
return;
|
||||
|
||||
@@ -9351,7 +9022,108 @@ bool Client::IsDevToolsWindowEnabled() const
|
||||
return dev_tools_window_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in_dev_tools_window_enabled
|
||||
*/
|
||||
void Client::SetDevToolsWindowEnabled(bool in_dev_tools_window_enabled)
|
||||
{
|
||||
Client::dev_tools_window_enabled = in_dev_tools_window_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param model_id
|
||||
*/
|
||||
void Client::SetPrimaryWeaponOrnamentation(uint32 model_id)
|
||||
{
|
||||
auto primary_item = m_inv.GetItem(EQEmu::invslot::slotPrimary);
|
||||
if (primary_item) {
|
||||
database.QueryDatabase(
|
||||
StringFormat(
|
||||
"UPDATE `inventory` SET `ornamentidfile` = %i WHERE `charid` = %i AND `slotid` = %i",
|
||||
model_id,
|
||||
character_id,
|
||||
EQEmu::invslot::slotPrimary
|
||||
));
|
||||
|
||||
primary_item->SetOrnamentationIDFile(model_id);
|
||||
SendItemPacket(EQEmu::invslot::slotPrimary, primary_item, ItemPacketTrade);
|
||||
WearChange(EQEmu::textures::weaponPrimary, static_cast<uint16>(model_id), 0);
|
||||
|
||||
Message(15, "Your primary weapon appearance has been modified");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param model_id
|
||||
*/
|
||||
void Client::SetSecondaryWeaponOrnamentation(uint32 model_id)
|
||||
{
|
||||
auto secondary_item = m_inv.GetItem(EQEmu::invslot::slotSecondary);
|
||||
if (secondary_item) {
|
||||
database.QueryDatabase(
|
||||
StringFormat(
|
||||
"UPDATE `inventory` SET `ornamentidfile` = %i WHERE `charid` = %i AND `slotid` = %i",
|
||||
model_id,
|
||||
character_id,
|
||||
EQEmu::invslot::slotSecondary
|
||||
));
|
||||
|
||||
secondary_item->SetOrnamentationIDFile(model_id);
|
||||
SendItemPacket(EQEmu::invslot::slotSecondary, secondary_item, ItemPacketTrade);
|
||||
WearChange(EQEmu::textures::weaponSecondary, static_cast<uint16>(model_id), 0);
|
||||
|
||||
Message(15, "Your secondary weapon appearance has been modified");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used in #goto <player_name>
|
||||
*
|
||||
* @param player_name
|
||||
*/
|
||||
bool Client::GotoPlayer(std::string player_name)
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"SELECT"
|
||||
" character_data.zone_id,"
|
||||
" character_data.zone_instance,"
|
||||
" character_data.x,"
|
||||
" character_data.y,"
|
||||
" character_data.z,"
|
||||
" character_data.heading "
|
||||
"FROM"
|
||||
" character_data "
|
||||
"WHERE"
|
||||
" TRUE"
|
||||
" AND character_data.name = '%s'"
|
||||
" AND character_data.last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name.c_str());
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
auto zone_id = static_cast<uint32>(atoi(row[0]));
|
||||
auto instance_id = static_cast<uint16>(atoi(row[1]));
|
||||
auto x = static_cast<float>(atof(row[2]));
|
||||
auto y = static_cast<float>(atof(row[3]));
|
||||
auto z = static_cast<float>(atof(row[4]));
|
||||
auto heading = static_cast<float>(atof(row[5]));
|
||||
|
||||
if (instance_id > 0 && !database.CheckInstanceExists(instance_id)) {
|
||||
this->Message(15, "Instance no longer exists...");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instance_id > 0) {
|
||||
database.AddClientToInstance(instance_id, this->CharacterID());
|
||||
}
|
||||
|
||||
this->MovePC(zone_id, instance_id, x, y, z, heading);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
+13
-34
@@ -252,6 +252,11 @@ public:
|
||||
bool IsDevToolsWindowEnabled() const;
|
||||
void SetDevToolsWindowEnabled(bool dev_tools_window_enabled);
|
||||
|
||||
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
||||
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
||||
|
||||
bool GotoPlayer(std::string player_name);
|
||||
|
||||
//abstract virtual function implementations required by base abstract class
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill);
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
|
||||
@@ -352,7 +357,7 @@ public:
|
||||
void SetHideMe(bool hm);
|
||||
inline uint16 GetPort() const { return port; }
|
||||
bool IsDead() const { return(dead); }
|
||||
bool IsUnconscious() const { return ((cur_hp <= 0) ? true : false); }
|
||||
bool IsUnconscious() const { return ((current_hp <= 0) ? true : false); }
|
||||
inline bool IsLFP() { return LFP; }
|
||||
void UpdateLFP();
|
||||
|
||||
@@ -554,10 +559,10 @@ public:
|
||||
virtual int GetCurrentBuffSlots() const;
|
||||
virtual int GetCurrentSongSlots() const;
|
||||
virtual int GetCurrentDiscSlots() const { return 1; }
|
||||
virtual int GetMaxBuffSlots() const { return EQEmu::constants::LongBuffs; }
|
||||
virtual int GetMaxSongSlots() const { return EQEmu::constants::ShortBuffs; }
|
||||
virtual int GetMaxDiscSlots() const { return EQEmu::constants::DiscBuffs; }
|
||||
virtual int GetMaxTotalSlots() const { return EQEmu::constants::TotalBuffs; }
|
||||
virtual int GetMaxBuffSlots() const { return EQEmu::spells::LONG_BUFFS; }
|
||||
virtual int GetMaxSongSlots() const { return EQEmu::spells::SHORT_BUFFS; }
|
||||
virtual int GetMaxDiscSlots() const { return EQEmu::spells::DISC_BUFFS; }
|
||||
virtual int GetMaxTotalSlots() const { return EQEmu::spells::TOTAL_BUFFS; }
|
||||
virtual uint32 GetFirstBuffSlot(bool disc, bool song);
|
||||
virtual uint32 GetLastBuffSlot(bool disc, bool song);
|
||||
virtual void InitializeBuffSlots();
|
||||
@@ -798,7 +803,7 @@ public:
|
||||
#ifdef PACKET_PROFILER
|
||||
void DumpPacketProfile() { if(eqs) eqs->DumpPacketProfile(); }
|
||||
#endif
|
||||
uint32 GetEquipment(uint8 material_slot) const; // returns item id
|
||||
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
virtual void UpdateEquipmentLight() { m_Light.Type[EQEmu::lightsource::LightEquipment] = m_inv.FindBrightestLightType(); m_Light.Level[EQEmu::lightsource::LightEquipment] = EQEmu::lightsource::TypeToLevel(m_Light.Type[EQEmu::lightsource::LightEquipment]); }
|
||||
|
||||
@@ -968,23 +973,7 @@ public:
|
||||
void SendRules(Client* client);
|
||||
std::list<std::string> consent_list;
|
||||
|
||||
//Anti-Cheat Stuff
|
||||
uint32 m_TimeSinceLastPositionCheck;
|
||||
float m_DistanceSinceLastPositionCheck;
|
||||
bool m_CheatDetectMoved;
|
||||
void SetShadowStepExemption(bool v);
|
||||
void SetKnockBackExemption(bool v);
|
||||
void SetPortExemption(bool v);
|
||||
void SetSenseExemption(bool v) { m_SenseExemption = v; }
|
||||
void SetAssistExemption(bool v) { m_AssistExemption = v; }
|
||||
const bool IsShadowStepExempted() const { return m_ShadowStepExemption; }
|
||||
const bool IsKnockBackExempted() const { return m_KnockBackExemption; }
|
||||
const bool IsPortExempted() const { return m_PortExemption; }
|
||||
const bool IsSenseExempted() const { return m_SenseExemption; }
|
||||
const bool IsAssistExempted() const { return m_AssistExemption; }
|
||||
const bool GetGMSpeed() const { return (gmspeed > 0); }
|
||||
void CheatDetected(CheatTypes CheatType, float x, float y, float z);
|
||||
const bool IsMQExemptedArea(uint32 zoneID, float x, float y, float z) const;
|
||||
bool CanUseReport;
|
||||
|
||||
//This is used to later set the buff duration of the spell, in slot to duration.
|
||||
@@ -1162,7 +1151,6 @@ public:
|
||||
inline bool IsDraggingCorpse() { return (DraggedCorpses.size() > 0); }
|
||||
void DragCorpses();
|
||||
inline void ClearDraggedCorpses() { DraggedCorpses.clear(); }
|
||||
inline void ResetPositionTimer() { position_timer_counter = 0; }
|
||||
void SendAltCurrencies();
|
||||
void SetAlternateCurrencyValue(uint32 currency_id, uint32 new_amount);
|
||||
void AddAlternateCurrencyValue(uint32 currency_id, int32 amount, int8 method = 0);
|
||||
@@ -1174,7 +1162,7 @@ public:
|
||||
void HandleLFGuildResponse(ServerPacket *pack);
|
||||
void SendLFGuildStatus();
|
||||
void SendGuildLFGuildStatus();
|
||||
inline bool XTargettingAvailable() const { return ((m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) && RuleB(Character, EnableXTargetting)); }
|
||||
inline bool XTargettingAvailable() const { return ((m_ClientVersionBit & EQEmu::versions::maskUFAndLater) && RuleB(Character, EnableXTargetting)); }
|
||||
inline uint8 GetMaxXTargets() const { return MaxXTargets; }
|
||||
void SetMaxXTargets(uint8 NewMax);
|
||||
bool IsXTarget(const Mob *m) const;
|
||||
@@ -1198,7 +1186,7 @@ public:
|
||||
bool GroupFollow(Client* inviter);
|
||||
inline bool GetRunMode() const { return runmode; }
|
||||
|
||||
inline bool AggroMeterAvailable() const { return ((m_ClientVersionBit & EQEmu::versions::bit_RoF2AndLater)) && RuleB(Character, EnableAggroMeter); } // RoF untested
|
||||
inline bool AggroMeterAvailable() const { return ((m_ClientVersionBit & EQEmu::versions::maskRoF2AndLater)) && RuleB(Character, EnableAggroMeter); } // RoF untested
|
||||
inline void SetAggroMeterLock(int in) { m_aggrometer.set_lock_id(in); }
|
||||
|
||||
void ProcessAggroMeter(); // builds packet and sends
|
||||
@@ -1509,9 +1497,6 @@ private:
|
||||
|
||||
WaterRegionType last_region_type;
|
||||
|
||||
Timer position_timer;
|
||||
uint8 position_timer_counter;
|
||||
|
||||
// this is used to try to cut back on position update reflections
|
||||
int position_update_same_count;
|
||||
|
||||
@@ -1552,7 +1537,6 @@ private:
|
||||
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
|
||||
|
||||
glm::vec3 m_Proximity;
|
||||
glm::vec4 last_major_update_position;
|
||||
|
||||
void BulkSendInventoryItems();
|
||||
|
||||
@@ -1596,11 +1580,6 @@ private:
|
||||
|
||||
int XPRate;
|
||||
|
||||
bool m_ShadowStepExemption;
|
||||
bool m_KnockBackExemption;
|
||||
bool m_PortExemption;
|
||||
bool m_SenseExemption;
|
||||
bool m_AssistExemption;
|
||||
bool alternate_currency_loaded;
|
||||
std::map<uint32, uint32> alternate_currency;
|
||||
std::queue<std::pair<uint32, int32>> alternate_currency_queued_operations;
|
||||
|
||||
@@ -325,15 +325,15 @@ int32 Client::CalcMaxHP()
|
||||
max_hp += spellbonuses.HP + aabonuses.HP;
|
||||
max_hp += GroupLeadershipAAHealthEnhancement();
|
||||
max_hp += max_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f);
|
||||
if (cur_hp > max_hp) {
|
||||
cur_hp = max_hp;
|
||||
if (current_hp > max_hp) {
|
||||
current_hp = max_hp;
|
||||
}
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[0];
|
||||
if (hp_perc_cap) {
|
||||
int curHP_cap = (max_hp * hp_perc_cap) / 100;
|
||||
if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1])) {
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1])) {
|
||||
|
||||
cur_hp = curHP_cap;
|
||||
current_hp = curHP_cap;
|
||||
}
|
||||
}
|
||||
return max_hp;
|
||||
@@ -838,7 +838,7 @@ uint32 Client::CalcCurrentWeight()
|
||||
This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd.
|
||||
*/
|
||||
// SoD+ client has no weight for coin
|
||||
if (EQEmu::behavior::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) {
|
||||
if (EQEmu::behavior::StaticLookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) {
|
||||
Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4;
|
||||
}
|
||||
float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat;
|
||||
|
||||
+118
-325
@@ -506,7 +506,6 @@ void Client::CompleteConnect()
|
||||
client_state = CLIENT_CONNECTED;
|
||||
SendAllPackets();
|
||||
hpupdate_timer.Start();
|
||||
position_timer.Start();
|
||||
autosave_timer.Start();
|
||||
SetDuelTarget(0);
|
||||
SetDueling(false);
|
||||
@@ -531,7 +530,7 @@ void Client::CompleteConnect()
|
||||
SendAppearancePacket(AT_GuildID, GuildID(), false);
|
||||
SendAppearancePacket(AT_GuildRank, rank, false);
|
||||
}
|
||||
for (uint32 spellInt = 0; spellInt < MAX_PP_REF_SPELLBOOK; spellInt++) {
|
||||
for (uint32 spellInt = 0; spellInt < EQEmu::spells::SPELLBOOK_SIZE; spellInt++) {
|
||||
if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000)
|
||||
m_pp.spell_book[spellInt] = 0xFFFFFFFF;
|
||||
}
|
||||
@@ -754,7 +753,7 @@ void Client::CompleteConnect()
|
||||
entity_list.SendUntargetable(this);
|
||||
|
||||
int x;
|
||||
for (x = 0; x < 8; x++) {
|
||||
for (x = EQEmu::textures::textureBegin; x <= EQEmu::textures::LastTexture; x++) {
|
||||
SendWearChange(x);
|
||||
}
|
||||
// added due to wear change above
|
||||
@@ -763,7 +762,7 @@ void Client::CompleteConnect()
|
||||
|
||||
Mob *pet = GetPet();
|
||||
if (pet != nullptr) {
|
||||
for (x = 0; x < 8; x++) {
|
||||
for (x = EQEmu::textures::textureBegin; x <= EQEmu::textures::LastTexture; x++) {
|
||||
pet->SendWearChange(x);
|
||||
}
|
||||
// added due to wear change above
|
||||
@@ -810,6 +809,16 @@ void Client::CompleteConnect()
|
||||
std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID());
|
||||
QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update last login since this doesn't get updated until a late save later so we can update online status
|
||||
*/
|
||||
database.QueryDatabase(
|
||||
StringFormat(
|
||||
"UPDATE `character_data` SET `last_login` = UNIX_TIMESTAMP() WHERE id = %u",
|
||||
this->CharacterID()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (zone) {
|
||||
@@ -869,14 +878,14 @@ void Client::CompleteConnect()
|
||||
worldserver.SendPacket(pack);
|
||||
delete pack;
|
||||
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) {
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::maskUFAndLater) {
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
}
|
||||
|
||||
// TODO: load these states
|
||||
// We at least will set them to the correct state for now
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater && GetPet()) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater && GetPet()) {
|
||||
SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||
SetPetCommandState(PET_BUTTON_STOP, 0);
|
||||
SetPetCommandState(PET_BUTTON_REGROUP, 0);
|
||||
@@ -896,108 +905,6 @@ void Client::CompleteConnect()
|
||||
worldserver.RequestTellQueue(GetName());
|
||||
}
|
||||
|
||||
void Client::CheatDetected(CheatTypes CheatType, float x, float y, float z)
|
||||
{
|
||||
//ToDo: Break warp down for special zones. Some zones have special teleportation pads or bad .map files which can trigger the detector without a legit zone request.
|
||||
|
||||
switch (CheatType)
|
||||
{
|
||||
case MQWarp: //Some zones may still have issues. Database updates will eliminate most if not all problems.
|
||||
if (RuleB(Zone, EnableMQWarpDetector)
|
||||
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|
||||
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
|
||||
{
|
||||
Message(13, "Large warp detected.");
|
||||
char hString[250];
|
||||
sprintf(hString, "/MQWarp with location %.2f, %.2f, %.2f", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
}
|
||||
break;
|
||||
case MQWarpShadowStep:
|
||||
if (RuleB(Zone, EnableMQWarpDetector)
|
||||
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|
||||
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
|
||||
{
|
||||
char *hString = nullptr;
|
||||
MakeAnyLenString(&hString, "/MQWarp(SS) with location %.2f, %.2f, %.2f, the target was shadow step exempt but we still found this suspicious.", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
safe_delete_array(hString);
|
||||
}
|
||||
break;
|
||||
case MQWarpKnockBack:
|
||||
if (RuleB(Zone, EnableMQWarpDetector)
|
||||
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|
||||
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
|
||||
{
|
||||
char *hString = nullptr;
|
||||
MakeAnyLenString(&hString, "/MQWarp(KB) with location %.2f, %.2f, %.2f, the target was Knock Back exempt but we still found this suspicious.", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
safe_delete_array(hString);
|
||||
}
|
||||
break;
|
||||
|
||||
case MQWarpLight:
|
||||
if (RuleB(Zone, EnableMQWarpDetector)
|
||||
&& ((this->Admin() < RuleI(Zone, MQWarpExemptStatus)
|
||||
|| (RuleI(Zone, MQWarpExemptStatus)) == -1)))
|
||||
{
|
||||
if (RuleB(Zone, MarkMQWarpLT))
|
||||
{
|
||||
char *hString = nullptr;
|
||||
MakeAnyLenString(&hString, "/MQWarp(LT) with location %.2f, %.2f, %.2f, running fast but not fast enough to get killed, possibly: small warp, speed hack, excessive lag, marked as suspicious.", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
safe_delete_array(hString);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MQZone:
|
||||
if (RuleB(Zone, EnableMQZoneDetector) && ((this->Admin() < RuleI(Zone, MQZoneExemptStatus) || (RuleI(Zone, MQZoneExemptStatus)) == -1)))
|
||||
{
|
||||
char hString[250];
|
||||
sprintf(hString, "/MQZone used at %.2f, %.2f, %.2f to %.2f %.2f %.2f", GetX(), GetY(), GetZ(), x, y, z);
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
}
|
||||
break;
|
||||
case MQZoneUnknownDest:
|
||||
if (RuleB(Zone, EnableMQZoneDetector) && ((this->Admin() < RuleI(Zone, MQZoneExemptStatus) || (RuleI(Zone, MQZoneExemptStatus)) == -1)))
|
||||
{
|
||||
char hString[250];
|
||||
sprintf(hString, "/MQZone used at %.2f, %.2f, %.2f", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
}
|
||||
break;
|
||||
case MQGate:
|
||||
if (RuleB(Zone, EnableMQGateDetector) && ((this->Admin() < RuleI(Zone, MQGateExemptStatus) || (RuleI(Zone, MQGateExemptStatus)) == -1))) {
|
||||
Message(13, "Illegal gate request.");
|
||||
char hString[250];
|
||||
sprintf(hString, "/MQGate used at %.2f, %.2f, %.2f", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
if (zone)
|
||||
{
|
||||
this->SetZone(this->GetZoneID(), zone->GetInstanceID()); //Prevent the player from zoning, place him back in the zone where he tried to originally /gate.
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetZone(this->GetZoneID(), 0); //Prevent the player from zoning, place him back in the zone where he tried to originally /gate.
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MQGhost: //Not currently implemented, but the framework is in place - just needs detection scenarios identified
|
||||
if (RuleB(Zone, EnableMQGhostDetector) && ((this->Admin() < RuleI(Zone, MQGhostExemptStatus) || (RuleI(Zone, MQGhostExemptStatus)) == -1))) {
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, "/MQGhost", zone->GetShortName());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
char *hString = nullptr;
|
||||
MakeAnyLenString(&hString, "Unhandled HackerDetection flag with location %.2f, %.2f, %.2f.", GetX(), GetY(), GetZ());
|
||||
database.SetMQDetectionFlag(this->account_name, this->name, hString, zone->GetShortName());
|
||||
safe_delete_array(hString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// connecting opcode handlers
|
||||
/*
|
||||
void Client::Handle_Connect_0x3e33(const EQApplicationPacket *app)
|
||||
@@ -1247,8 +1154,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
SetClientVersion(Connection()->ClientVersion());
|
||||
m_ClientVersionBit = EQEmu::versions::ConvertClientVersionToClientVersionBit(Connection()->ClientVersion());
|
||||
|
||||
bool siv = m_inv.SetInventoryVersion(m_ClientVersion);
|
||||
Log(Logs::General, Logs::None, "%s inventory version to %s(%i)", (siv ? "Succeeded in setting" : "Failed to set"), ClientVersionName(m_ClientVersion), m_ClientVersion);
|
||||
m_inv.SetInventoryVersion(m_ClientVersion);
|
||||
|
||||
/* Antighost code
|
||||
tmp var is so the search doesnt find this object
|
||||
@@ -1288,7 +1194,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
uint32 cid = CharacterID();
|
||||
character_id = cid; /* Global character_id reference */
|
||||
|
||||
/* Flush and reload factions */
|
||||
/* Flush and reload factions */
|
||||
database.RemoveTempFactions(this);
|
||||
database.LoadCharacterFactionValues(cid, factionvalues);
|
||||
|
||||
@@ -1325,6 +1231,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID());
|
||||
|
||||
database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */
|
||||
// set to full support in case they're a gm with items in disabled expansion slots..but, have their gm flag off...
|
||||
// item loss will occur when they use the 'empty' slots, if this is not done
|
||||
m_inv.SetGMInventory(true);
|
||||
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 */
|
||||
@@ -1341,7 +1250,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */
|
||||
database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */
|
||||
|
||||
/* Load AdventureStats */
|
||||
/* Load AdventureStats */
|
||||
AdventureStats_Struct as;
|
||||
if (database.GetAdventureStats(cid, &as))
|
||||
{
|
||||
@@ -1500,8 +1409,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000) { m_pp.ldon_points_tak = 0; }
|
||||
if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000) { m_pp.ldon_points_available = 0; }
|
||||
|
||||
// need to rework .. not until full scope of change is accounted for, though
|
||||
if (RuleB(World, UseClientBasedExpansionSettings)) {
|
||||
m_pp.expansions = EQEmu::versions::ConvertClientVersionToExpansion(ClientVersion());
|
||||
m_pp.expansions = EQEmu::expansions::ConvertClientVersionToExpansionMask(ClientVersion());
|
||||
}
|
||||
else {
|
||||
m_pp.expansions = RuleI(World, ExpansionSettings);
|
||||
@@ -1512,7 +1422,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
if (SPDAT_RECORDS > 0) {
|
||||
for (uint32 z = 0; z<MAX_PP_MEMSPELL; z++) {
|
||||
for (uint32 z = 0; z < EQEmu::spells::SPELL_GEM_COUNT; z++) {
|
||||
if (m_pp.mem_spells[z] >= (uint32)SPDAT_RECORDS)
|
||||
UnmemSpell(z, false);
|
||||
}
|
||||
@@ -1619,6 +1529,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
Bot::LoadAndSpawnAllZonedBots(this);
|
||||
#endif
|
||||
|
||||
m_inv.SetGMInventory((bool)m_pp.gm); // set to current gm state for calc
|
||||
CalcBonuses();
|
||||
if (RuleB(Zone, EnableLoggedOffReplenishments) &&
|
||||
time(nullptr) - m_pp.lastlogin >= RuleI(Zone, MinOfflineTimeToReplenishments)) {
|
||||
@@ -1643,7 +1554,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
}
|
||||
|
||||
/* Load Spell Slot Refresh from Currently Memoried Spells */
|
||||
for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i)
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i)
|
||||
if (IsValidSpell(m_pp.mem_spells[i]))
|
||||
m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000;
|
||||
|
||||
@@ -1742,6 +1653,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
this is not quite where live sends inventory, they do it after tribute
|
||||
*/
|
||||
if (loaditems) { /* Dont load if a length error occurs */
|
||||
if (admin >= minStatusToBeGM)
|
||||
m_inv.SetGMInventory(true); // set to true to allow expansion-restricted packets through
|
||||
|
||||
BulkSendInventoryItems();
|
||||
/* Send stuff on the cursor which isnt sent in bulk */
|
||||
for (auto iter = m_inv.cursor_cbegin(); iter != m_inv.cursor_cend(); ++iter) {
|
||||
@@ -1751,6 +1665,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
const EQEmu::ItemInstance *inst = *iter;
|
||||
SendItemPacket(EQEmu::invslot::slotCursor, inst, ItemPacketLimbo);
|
||||
}
|
||||
|
||||
// this is kinda hackish atm..this process needs to be realigned to allow a contiguous flow
|
||||
m_inv.SetGMInventory((bool)m_pp.gm); // reset back to current gm state
|
||||
}
|
||||
|
||||
/* Task Packets */
|
||||
@@ -1766,7 +1683,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater) {
|
||||
outapp = new EQApplicationPacket(OP_XTargetResponse, 8);
|
||||
outapp->WriteUInt32(GetMaxXTargets());
|
||||
outapp->WriteUInt32(0);
|
||||
@@ -2973,7 +2890,6 @@ void Client::Handle_OP_Assist(const EQApplicationPacket *app)
|
||||
Mob *new_target = assistee->GetTarget();
|
||||
if (new_target && (GetGM() ||
|
||||
Distance(m_Position, assistee->GetPosition()) <= TARGETING_RANGE)) {
|
||||
SetAssistExemption(true);
|
||||
eid->entity_id = new_target->GetID();
|
||||
} else {
|
||||
eid->entity_id = 0;
|
||||
@@ -3341,42 +3257,40 @@ void Client::Handle_OP_AutoAttack(const EQApplicationPacket *app)
|
||||
return;
|
||||
}
|
||||
|
||||
if (app->pBuffer[0] == 0)
|
||||
{
|
||||
if (app->pBuffer[0] == 0) {
|
||||
auto_attack = false;
|
||||
if (IsAIControlled())
|
||||
if (IsAIControlled()) {
|
||||
return;
|
||||
}
|
||||
attack_timer.Disable();
|
||||
ranged_timer.Disable();
|
||||
attack_dw_timer.Disable();
|
||||
|
||||
m_AutoAttackPosition = glm::vec4();
|
||||
m_AutoAttackPosition = glm::vec4();
|
||||
m_AutoAttackTargetLocation = glm::vec3();
|
||||
aa_los_them_mob = nullptr;
|
||||
aa_los_them_mob = nullptr;
|
||||
}
|
||||
else if (app->pBuffer[0] == 1)
|
||||
{
|
||||
else if (app->pBuffer[0] == 1) {
|
||||
auto_attack = true;
|
||||
auto_fire = false;
|
||||
if (IsAIControlled())
|
||||
auto_fire = false;
|
||||
if (IsAIControlled()) {
|
||||
return;
|
||||
}
|
||||
SetAttackTimer();
|
||||
|
||||
if (GetTarget())
|
||||
{
|
||||
aa_los_them_mob = GetTarget();
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
if (GetTarget()) {
|
||||
aa_los_them_mob = GetTarget();
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
m_AutoAttackTargetLocation = glm::vec3(aa_los_them_mob->GetPosition());
|
||||
los_status = CheckLosFN(aa_los_them_mob);
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
los_status = CheckLosFN(aa_los_them_mob);
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
else {
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
m_AutoAttackTargetLocation = glm::vec3();
|
||||
aa_los_them_mob = nullptr;
|
||||
los_status = false;
|
||||
los_status_facing = false;
|
||||
aa_los_them_mob = nullptr;
|
||||
los_status = false;
|
||||
los_status_facing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3944,6 +3858,8 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app)
|
||||
return;
|
||||
controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat
|
||||
|
||||
Message(0, "Board boat: %s", boatname);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4100,7 +4016,7 @@ void Client::Handle_OP_CancelTrade(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
||||
{
|
||||
using EQEmu::CastingSlot;
|
||||
using EQEmu::spells::CastingSlot;
|
||||
if (app->size != sizeof(CastSpell_Struct)) {
|
||||
std::cout << "Wrong size: OP_CastSpell, size=" << app->size << ", expected " << sizeof(CastSpell_Struct) << std::endl;
|
||||
return;
|
||||
@@ -4121,14 +4037,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
|
||||
/* Memorized Spell */
|
||||
if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id) {
|
||||
uint16 spell_to_cast = 0;
|
||||
if (castspell->slot < MAX_PP_MEMSPELL) {
|
||||
if (castspell->slot < EQEmu::spells::SPELL_GEM_COUNT) {
|
||||
spell_to_cast = m_pp.mem_spells[castspell->slot];
|
||||
if (spell_to_cast != castspell->spell_id) {
|
||||
InterruptSpell(castspell->spell_id); //CHEATER!!!
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (castspell->slot >= MAX_PP_MEMSPELL) {
|
||||
else if (castspell->slot >= EQEmu::spells::SPELL_GEM_COUNT) {
|
||||
InterruptSpell();
|
||||
return;
|
||||
}
|
||||
@@ -4451,9 +4367,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
sizeof(PlayerPositionUpdateClient_Struct), app->size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
PlayerPositionUpdateClient_Struct *ppu = (PlayerPositionUpdateClient_Struct *) app->pBuffer;
|
||||
|
||||
|
||||
/* Boat handling */
|
||||
if (ppu->spawn_id != GetID()) {
|
||||
/* If player is controlling boat */
|
||||
@@ -4463,163 +4379,67 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
controlling_boat_id = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||
boat->SetDelta(boat_delta);
|
||||
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct *ppus = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
||||
boat->MakeSpawnUpdate(ppus);
|
||||
entity_list.QueueCloseClients(boat, outapp, true, 300, this, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
|
||||
/* Update the boat's position on the server, without sending an update */
|
||||
boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading), false);
|
||||
return;
|
||||
} else return;
|
||||
}
|
||||
|
||||
float dist = 0;
|
||||
float tmp;
|
||||
tmp = m_Position.x - ppu->x_pos;
|
||||
dist += tmp * tmp;
|
||||
tmp = m_Position.y - ppu->y_pos;
|
||||
dist += tmp * tmp;
|
||||
dist = sqrt(dist);
|
||||
|
||||
/* Hack checks */
|
||||
if (dist == 0) {
|
||||
if (m_DistanceSinceLastPositionCheck > 0.0) {
|
||||
uint32 cur_time = Timer::GetCurrentTime();
|
||||
if ((cur_time - m_TimeSinceLastPositionCheck) > 0) {
|
||||
float speed =
|
||||
(m_DistanceSinceLastPositionCheck * 100) / (float) (cur_time - m_TimeSinceLastPositionCheck);
|
||||
int runs = GetRunspeed();
|
||||
if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
|
||||
if (!GetGMSpeed() && (runs >= GetBaseRunspeed() ||
|
||||
(speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) {
|
||||
if (IsShadowStepExempted()) {
|
||||
if (m_DistanceSinceLastPositionCheck > 800) {
|
||||
CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
} else if (IsKnockBackExempted()) {
|
||||
if (speed > 30.0f) {
|
||||
CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
} else if (!IsPortExempted()) {
|
||||
if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) {
|
||||
if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
//Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
|
||||
} else {
|
||||
CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetShadowStepExemption(false);
|
||||
SetKnockBackExemption(false);
|
||||
SetPortExemption(false);
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
m_CheatDetectMoved = false;
|
||||
}
|
||||
} else {
|
||||
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
|
||||
m_CheatDetectMoved = false;
|
||||
}
|
||||
} else {
|
||||
m_DistanceSinceLastPositionCheck += dist;
|
||||
m_CheatDetectMoved = true;
|
||||
if (m_TimeSinceLastPositionCheck == 0) {
|
||||
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
|
||||
} else {
|
||||
uint32 cur_time = Timer::GetCurrentTime();
|
||||
if ((cur_time - m_TimeSinceLastPositionCheck) > 2500) {
|
||||
float speed =
|
||||
(m_DistanceSinceLastPositionCheck * 100) / (float) (cur_time - m_TimeSinceLastPositionCheck);
|
||||
int runs = GetRunspeed();
|
||||
if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
|
||||
if (!GetGMSpeed() && (runs >= GetBaseRunspeed() ||
|
||||
(speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) {
|
||||
if (IsShadowStepExempted()) {
|
||||
if (m_DistanceSinceLastPositionCheck > 800) {
|
||||
CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
} else if (IsKnockBackExempted()) {
|
||||
if (speed > 30.0f) {
|
||||
CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
} else if (!IsPortExempted()) {
|
||||
if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) {
|
||||
if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) {
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
} else {
|
||||
CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetShadowStepExemption(false);
|
||||
SetKnockBackExemption(false);
|
||||
SetPortExemption(false);
|
||||
m_TimeSinceLastPositionCheck = cur_time;
|
||||
m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsDraggingCorpse())
|
||||
DragCorpses();
|
||||
}
|
||||
|
||||
if (IsDraggingCorpse())
|
||||
DragCorpses();
|
||||
|
||||
/* Check to see if PPU should trigger an update to the rewind position. */
|
||||
float rewind_x_diff = 0;
|
||||
float rewind_y_diff = 0;
|
||||
|
||||
|
||||
rewind_x_diff = ppu->x_pos - m_RewindLocation.x;
|
||||
rewind_x_diff *= rewind_x_diff;
|
||||
rewind_y_diff = ppu->y_pos - m_RewindLocation.y;
|
||||
rewind_y_diff *= rewind_y_diff;
|
||||
|
||||
|
||||
/*
|
||||
We only need to store updated values if the player has moved.
|
||||
If the player has moved more than units for x or y, then we'll store
|
||||
his pre-PPU x and y for /rewind, in case he gets stuck.
|
||||
*/
|
||||
|
||||
|
||||
if ((rewind_x_diff > 750) || (rewind_y_diff > 750))
|
||||
m_RewindLocation = glm::vec3(m_Position);
|
||||
|
||||
|
||||
/*
|
||||
If the PPU was a large jump, such as a cross zone gate or Call of Hero,
|
||||
just update rewind coordinates to the new ppu coordinates. This will prevent exploitation.
|
||||
*/
|
||||
|
||||
|
||||
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
|
||||
m_RewindLocation = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
|
||||
|
||||
if (proximity_timer.Check()) {
|
||||
entity_list.ProcessMove(this, glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos));
|
||||
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
|
||||
ProcessTaskProximities(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
|
||||
|
||||
m_Proximity = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||
}
|
||||
|
||||
|
||||
/* Update internal state */
|
||||
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||
|
||||
|
||||
if (IsTracking() && ((m_Position.x != ppu->x_pos) || (m_Position.y != ppu->y_pos))) {
|
||||
if (zone->random.Real(0, 100) < 70)//should be good
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
|
||||
}
|
||||
|
||||
|
||||
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
||||
if (ppu->y_pos != m_Position.y || ppu->x_pos != m_Position.x) {
|
||||
if ((hidden || improved_hidden) && !sneaking) {
|
||||
@@ -4638,43 +4458,35 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
}
|
||||
rewind_timer.Start(30000, true);
|
||||
}
|
||||
|
||||
|
||||
/* Handle client aggro scanning timers NPCs */
|
||||
is_client_moving = (ppu->y_pos == m_Position.y && ppu->x_pos == m_Position.x) ? false : true;
|
||||
|
||||
|
||||
if (is_client_moving) {
|
||||
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u",
|
||||
client_scan_npc_aggro_timer.GetDuration());
|
||||
if (client_scan_npc_aggro_timer.GetDuration() > 1000) {
|
||||
|
||||
npc_close_scan_timer.Disable();
|
||||
npc_close_scan_timer.Start(500);
|
||||
|
||||
client_scan_npc_aggro_timer.Disable();
|
||||
client_scan_npc_aggro_timer.Start(500);
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u",
|
||||
client_scan_npc_aggro_timer.GetDuration());
|
||||
if (client_scan_npc_aggro_timer.GetDuration() < 1000) {
|
||||
|
||||
npc_close_scan_timer.Disable();
|
||||
npc_close_scan_timer.Start(6000);
|
||||
|
||||
client_scan_npc_aggro_timer.Disable();
|
||||
client_scan_npc_aggro_timer.Start(3000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float new_heading = EQ12toFloat(ppu->heading);
|
||||
int32 new_animation = ppu->animation;
|
||||
|
||||
|
||||
/* Update internal server position from what the client has sent */
|
||||
m_Position.x = ppu->x_pos;
|
||||
m_Position.y = ppu->y_pos;
|
||||
m_Position.z = ppu->z_pos;
|
||||
|
||||
|
||||
/* Visual Debugging */
|
||||
if (RuleB(Character, OPClientUpdateVisualDebug)) {
|
||||
Log(Logs::General, Logs::Debug, "ClientUpdate: ppu x: %f y: %f z: %f h: %u", ppu->x_pos, ppu->y_pos, ppu->z_pos,
|
||||
@@ -4682,43 +4494,43 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
||||
this->SendAppearanceEffect(41, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Only feed real time updates when client is moving */
|
||||
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
|
||||
|
||||
|
||||
animation = ppu->animation;
|
||||
m_Position.w = EQ12toFloat(ppu->heading);
|
||||
|
||||
|
||||
/* Broadcast update to other clients */
|
||||
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
||||
|
||||
|
||||
MakeSpawnUpdate(position_update);
|
||||
|
||||
|
||||
if (gm_hide_me) {
|
||||
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250);
|
||||
} else {
|
||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Always send position updates to group - send when beyond normal ClientPositionUpdate range */
|
||||
Group *group = this->GetGroup();
|
||||
Raid *raid = this->GetRaid();
|
||||
|
||||
|
||||
if (raid) {
|
||||
raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
||||
} else if (group) {
|
||||
group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
||||
}
|
||||
|
||||
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
|
||||
if (zone->watermap) {
|
||||
if (zone->watermap->InLiquid(glm::vec3(m_Position))) {
|
||||
CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17);
|
||||
|
||||
|
||||
// Dismount horses when entering water
|
||||
if (GetHorseId() && RuleB(Character, DismountWater)) {
|
||||
SetHorseId(0);
|
||||
@@ -4727,7 +4539,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
||||
}
|
||||
CheckRegionTypeChanges();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app)
|
||||
@@ -5452,7 +5263,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app)
|
||||
EQApplicationPacket* outapp = app->Copy();
|
||||
DeleteSpell_Struct* dss = (DeleteSpell_Struct*)outapp->pBuffer;
|
||||
|
||||
if (dss->spell_slot < 0 || dss->spell_slot > int(MAX_PP_SPELLBOOK))
|
||||
if (dss->spell_slot < 0 || dss->spell_slot > int(EQEmu::spells::SPELLBOOK_SIZE))
|
||||
return;
|
||||
|
||||
if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) {
|
||||
@@ -8650,7 +8461,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app)
|
||||
|
||||
void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
|
||||
{
|
||||
using EQEmu::CastingSlot;
|
||||
using EQEmu::spells::CastingSlot;
|
||||
if (app->size != sizeof(ItemVerifyRequest_Struct))
|
||||
{
|
||||
Log(Logs::General, Logs::Error, "OP size error: OP_ItemVerifyRequest expected:%i got:%i", sizeof(ItemVerifyRequest_Struct), app->size);
|
||||
@@ -9376,7 +9187,7 @@ void Client::Handle_OP_LoadSpellSet(const EQApplicationPacket *app)
|
||||
}
|
||||
int i;
|
||||
LoadSpellSet_Struct* ss = (LoadSpellSet_Struct*)app->pBuffer;
|
||||
for (i = 0; i<MAX_PP_MEMSPELL; i++) {
|
||||
for (i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) {
|
||||
if (ss->spell[i] != 0xFFFFFFFF)
|
||||
UnmemSpell(i, true);
|
||||
}
|
||||
@@ -10260,9 +10071,9 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (mypet->IsNPC()) {
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_GUARDINGLIFE);
|
||||
mypet->SetPetOrder(SPO_Guard);
|
||||
mypet->CastToNPC()->SaveGuardSpot();
|
||||
mypet->CastToNPC()->SaveGuardSpot(mypet->GetPosition());
|
||||
if (!mypet->GetTarget()) // want them to not twitch if they're chasing something down
|
||||
mypet->SetCurrentSpeed(0);
|
||||
mypet->StopNavigation();
|
||||
if (mypet->IsPetStop()) {
|
||||
mypet->SetPetStop(false);
|
||||
SetPetCommandState(PET_BUTTON_STOP, 0);
|
||||
@@ -10377,16 +10188,16 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) {
|
||||
if (mypet->IsHeld())
|
||||
{
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_HOLD_SET_OFF);
|
||||
mypet->SetHeld(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_HOLD_SET_ON);
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater)
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_NOW_HOLDING);
|
||||
else
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_HOLD);
|
||||
@@ -10400,10 +10211,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
}
|
||||
case PET_HOLD_ON: {
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && !mypet->IsHeld()) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_HOLD_SET_ON);
|
||||
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater)
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_NOW_HOLDING);
|
||||
else
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_HOLD);
|
||||
@@ -10415,7 +10226,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
}
|
||||
case PET_HOLD_OFF: {
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_HOLD_SET_OFF);
|
||||
mypet->SetHeld(false);
|
||||
}
|
||||
@@ -10425,13 +10236,13 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) {
|
||||
if (mypet->IsGHeld())
|
||||
{
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_OFF_GHOLD);
|
||||
mypet->SetGHeld(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater) {
|
||||
Message_StringID(MT_PetResponse, PET_ON_GHOLD);
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_GHOLD_ON_MSG);
|
||||
} else {
|
||||
@@ -10446,7 +10257,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
}
|
||||
case PET_GHOLD_ON: {
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater) {
|
||||
Message_StringID(MT_PetResponse, PET_ON_GHOLD);
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_GHOLD_ON_MSG);
|
||||
} else {
|
||||
@@ -10460,7 +10271,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
}
|
||||
case PET_GHOLD_OFF: {
|
||||
if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) {
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskUFAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_OFF_GHOLD);
|
||||
mypet->SetGHeld(false);
|
||||
}
|
||||
@@ -10472,13 +10283,13 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
break;
|
||||
if (mypet->IsNoCast()) {
|
||||
Message_StringID(MT_PetResponse, PET_CASTING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_OFF);
|
||||
mypet->SetNoCast(false);
|
||||
}
|
||||
else {
|
||||
Message_StringID(MT_PetResponse, PET_NOT_CASTING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_ON);
|
||||
mypet->SetNoCast(true);
|
||||
}
|
||||
@@ -10491,7 +10302,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
break;
|
||||
if (!mypet->IsNoCast()) {
|
||||
Message_StringID(MT_PetResponse, PET_NOT_CASTING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_ON);
|
||||
mypet->SetNoCast(true);
|
||||
}
|
||||
@@ -10504,7 +10315,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
break;
|
||||
if (mypet->IsNoCast()) {
|
||||
Message_StringID(MT_PetResponse, PET_CASTING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_OFF);
|
||||
mypet->SetNoCast(false);
|
||||
}
|
||||
@@ -10517,13 +10328,13 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
break;
|
||||
if (mypet->IsFocused()) {
|
||||
Message_StringID(MT_PetResponse, PET_NOT_FOCUSING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_FOCUS_SET_OFF);
|
||||
mypet->SetFocused(false);
|
||||
}
|
||||
else {
|
||||
Message_StringID(MT_PetResponse, PET_NOW_FOCUSING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_FOCUS_SET_ON);
|
||||
mypet->SetFocused(true);
|
||||
}
|
||||
@@ -10536,7 +10347,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
break;
|
||||
if (!mypet->IsFocused()) {
|
||||
Message_StringID(MT_PetResponse, PET_NOW_FOCUSING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_FOCUS_SET_ON);
|
||||
mypet->SetFocused(true);
|
||||
}
|
||||
@@ -10549,7 +10360,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
break;
|
||||
if (mypet->IsFocused()) {
|
||||
Message_StringID(MT_PetResponse, PET_NOT_FOCUSING);
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater)
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskSoDAndLater)
|
||||
Message_StringID(MT_PetResponse, PET_FOCUS_SET_OFF);
|
||||
mypet->SetFocused(false);
|
||||
}
|
||||
@@ -10564,7 +10375,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
mypet->SetPetStop(false);
|
||||
} else {
|
||||
mypet->SetPetStop(true);
|
||||
mypet->SetCurrentSpeed(0);
|
||||
mypet->StopNavigation();
|
||||
mypet->SetTarget(nullptr);
|
||||
if (mypet->IsPetRegroup()) {
|
||||
mypet->SetPetRegroup(false);
|
||||
@@ -10580,7 +10391,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app)
|
||||
|
||||
if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) {
|
||||
mypet->SetPetStop(true);
|
||||
mypet->SetCurrentSpeed(0);
|
||||
mypet->StopNavigation();
|
||||
mypet->SetTarget(nullptr);
|
||||
mypet->SayTo_StringID(this, MT_PetResponse, PET_GETLOST_STRING);
|
||||
if (mypet->IsPetRegroup()) {
|
||||
@@ -13526,7 +13337,7 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app)
|
||||
const SwapSpell_Struct* swapspell = (const SwapSpell_Struct*)app->pBuffer;
|
||||
int swapspelltemp;
|
||||
|
||||
if (swapspell->from_slot < 0 || swapspell->from_slot > MAX_PP_SPELLBOOK || swapspell->to_slot < 0 || swapspell->to_slot > MAX_PP_SPELLBOOK)
|
||||
if (swapspell->from_slot < 0 || swapspell->from_slot > EQEmu::spells::SPELLBOOK_SIZE || swapspell->to_slot < 0 || swapspell->to_slot > EQEmu::spells::SPELLBOOK_SIZE)
|
||||
return;
|
||||
|
||||
swapspelltemp = m_pp.spell_book[swapspell->from_slot];
|
||||
@@ -13701,12 +13512,6 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
|
||||
GetTarget()->IsTargeted(1);
|
||||
return;
|
||||
}
|
||||
else if (IsAssistExempted())
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
SetAssistExemption(false);
|
||||
return;
|
||||
}
|
||||
else if (GetTarget()->IsClient())
|
||||
{
|
||||
//make sure this client is in our raid/group
|
||||
@@ -13724,17 +13529,6 @@ void Client::Handle_OP_TargetCommand(const EQApplicationPacket *app)
|
||||
SetTarget((Mob*)nullptr);
|
||||
return;
|
||||
}
|
||||
else if (IsPortExempted())
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
return;
|
||||
}
|
||||
else if (IsSenseExempted())
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
SetSenseExemption(false);
|
||||
return;
|
||||
}
|
||||
else if (IsXTarget(GetTarget()))
|
||||
{
|
||||
GetTarget()->IsTargeted(1);
|
||||
@@ -14676,7 +14470,6 @@ void Client::Handle_OP_WearChange(const EQApplicationPacket *app)
|
||||
|
||||
// we could maybe ignore this and just send our own from moveitem
|
||||
entity_list.QueueClients(this, app, true);
|
||||
return;
|
||||
}
|
||||
|
||||
void Client::Handle_OP_WhoAllRequest(const EQApplicationPacket *app)
|
||||
|
||||
+23
-77
@@ -122,7 +122,7 @@ bool Client::Process() {
|
||||
|
||||
/* I haven't naturally updated my position in 10 seconds, updating manually */
|
||||
if (!is_client_moving && position_update_timer.Check()) {
|
||||
SendPositionUpdate();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
}
|
||||
|
||||
if (mana_timer.Check())
|
||||
@@ -188,10 +188,6 @@ bool Client::Process() {
|
||||
if (IsStunned() && stunned_timer.Check())
|
||||
Mob::UnStun();
|
||||
|
||||
if (!m_CheatDetectMoved) {
|
||||
m_TimeSinceLastPositionCheck = Timer::GetCurrentTime();
|
||||
}
|
||||
|
||||
if (bardsong_timer.Check() && bardsong != 0) {
|
||||
//NOTE: this is kinda a heavy-handed check to make sure the mob still exists before
|
||||
//doing the next pulse on them...
|
||||
@@ -258,20 +254,13 @@ bool Client::Process() {
|
||||
/* Build a close range list of NPC's */
|
||||
if (npc_close_scan_timer.Check()) {
|
||||
close_mobs.clear();
|
||||
|
||||
/* Force spawn updates when traveled far */
|
||||
//Force spawn updates when traveled far
|
||||
bool force_spawn_updates = false;
|
||||
float client_update_range = (RuleI(Range, ClientForceSpawnUpdateRange) * RuleI(Range, ClientForceSpawnUpdateRange));
|
||||
if (DistanceSquared(last_major_update_position, m_Position) >= client_update_range) {
|
||||
last_major_update_position = m_Position;
|
||||
force_spawn_updates = true;
|
||||
}
|
||||
|
||||
float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan));
|
||||
auto &mob_list = entity_list.GetMobList();
|
||||
for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) {
|
||||
Mob* mob = itr->second;
|
||||
|
||||
float distance = DistanceSquared(m_Position, mob->GetPosition());
|
||||
if (mob->IsNPC()) {
|
||||
if (distance <= scan_range) {
|
||||
@@ -281,21 +270,9 @@ bool Client::Process() {
|
||||
close_mobs.insert(std::pair<Mob *, float>(mob, distance));
|
||||
}
|
||||
}
|
||||
|
||||
if (force_spawn_updates && mob != this) {
|
||||
|
||||
if (mob->is_distance_roamer) {
|
||||
mob->SendPositionUpdateToClient(this);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (distance <= client_update_range)
|
||||
mob->SendPositionUpdateToClient(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool may_use_attacks = false;
|
||||
/*
|
||||
Things which prevent us from attacking:
|
||||
@@ -368,25 +345,22 @@ bool Client::Process() {
|
||||
}
|
||||
|
||||
Mob *auto_attack_target = GetTarget();
|
||||
if (auto_attack && auto_attack_target != nullptr && may_use_attacks && attack_timer.Check())
|
||||
{
|
||||
if (auto_attack && auto_attack_target != nullptr && may_use_attacks && attack_timer.Check()) {
|
||||
//check if change
|
||||
//only check on primary attack.. sorry offhand you gotta wait!
|
||||
if (aa_los_them_mob)
|
||||
{
|
||||
if (aa_los_them_mob) {
|
||||
if (auto_attack_target != aa_los_them_mob ||
|
||||
m_AutoAttackPosition.x != GetX() ||
|
||||
m_AutoAttackPosition.y != GetY() ||
|
||||
m_AutoAttackPosition.z != GetZ() ||
|
||||
m_AutoAttackTargetLocation.x != aa_los_them_mob->GetX() ||
|
||||
m_AutoAttackTargetLocation.y != aa_los_them_mob->GetY() ||
|
||||
m_AutoAttackTargetLocation.z != aa_los_them_mob->GetZ())
|
||||
{
|
||||
aa_los_them_mob = auto_attack_target;
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
m_AutoAttackTargetLocation.z != aa_los_them_mob->GetZ()) {
|
||||
aa_los_them_mob = auto_attack_target;
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
m_AutoAttackTargetLocation = glm::vec3(aa_los_them_mob->GetPosition());
|
||||
los_status = CheckLosFN(auto_attack_target);
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
los_status = CheckLosFN(auto_attack_target);
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
}
|
||||
// If only our heading changes, we can skip the CheckLosFN call
|
||||
// but above we still need to update los_status_facing
|
||||
@@ -395,25 +369,21 @@ bool Client::Process() {
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aa_los_them_mob = auto_attack_target;
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
else {
|
||||
aa_los_them_mob = auto_attack_target;
|
||||
m_AutoAttackPosition = GetPosition();
|
||||
m_AutoAttackTargetLocation = glm::vec3(aa_los_them_mob->GetPosition());
|
||||
los_status = CheckLosFN(auto_attack_target);
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
los_status = CheckLosFN(auto_attack_target);
|
||||
los_status_facing = IsFacingMob(aa_los_them_mob);
|
||||
}
|
||||
|
||||
if (!CombatRange(auto_attack_target))
|
||||
{
|
||||
if (!CombatRange(auto_attack_target)) {
|
||||
Message_StringID(MT_TooFarAway, TARGET_TOO_FAR);
|
||||
}
|
||||
else if (auto_attack_target == this)
|
||||
{
|
||||
else if (auto_attack_target == this) {
|
||||
Message_StringID(MT_TooFarAway, TRY_ATTACKING_SOMEONE);
|
||||
}
|
||||
else if (!los_status || !los_status_facing)
|
||||
{
|
||||
else if (!los_status || !los_status_facing) {
|
||||
//you can't see your target
|
||||
}
|
||||
else if (auto_attack_target->GetHP() > -10) // -10 so we can watch people bleed in PvP
|
||||
@@ -423,8 +393,9 @@ bool Client::Process() {
|
||||
TriggerDefensiveProcs(auto_attack_target, EQEmu::invslot::slotPrimary, false);
|
||||
|
||||
DoAttackRounds(auto_attack_target, EQEmu::invslot::slotPrimary);
|
||||
if (CheckAATimer(aaTimerRampage))
|
||||
if (CheckAATimer(aaTimerRampage)) {
|
||||
entity_list.AEAttack(this, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,31 +437,6 @@ bool Client::Process() {
|
||||
}
|
||||
}
|
||||
|
||||
if (position_timer.Check()) {
|
||||
if (IsAIControlled())
|
||||
{
|
||||
if (!IsMoving())
|
||||
{
|
||||
animation = 0;
|
||||
m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w);
|
||||
SendPositionUpdate(2);
|
||||
}
|
||||
}
|
||||
|
||||
// Send a position packet every 8 seconds - if not done, other clients
|
||||
// see this char disappear after 10-12 seconds of inactivity
|
||||
if (position_timer_counter >= 36) { // Approx. 4 ticks per second
|
||||
entity_list.SendPositionUpdates(this, pLastUpdateWZ, RuleI(Range, MobPositionUpdates), GetTarget(), true);
|
||||
pLastUpdate = Timer::GetCurrentTime();
|
||||
pLastUpdateWZ = pLastUpdate;
|
||||
position_timer_counter = 0;
|
||||
}
|
||||
else {
|
||||
pLastUpdate = Timer::GetCurrentTime();
|
||||
position_timer_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (HasVirus()) {
|
||||
if (viral_timer.Check()) {
|
||||
viral_timer_counter++;
|
||||
@@ -866,7 +812,7 @@ void Client::BulkSendInventoryItems()
|
||||
void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
|
||||
const EQEmu::ItemData* handyitem = nullptr;
|
||||
uint32 numItemSlots = 80; //The max number of items passed in the transaction.
|
||||
if (m_ClientVersionBit & EQEmu::versions::bit_RoFAndLater) { // RoF+ can send 200 items
|
||||
if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater) { // RoF+ can send 200 items
|
||||
numItemSlots = 200;
|
||||
}
|
||||
const EQEmu::ItemData *item = nullptr;
|
||||
@@ -1186,7 +1132,7 @@ void Client::CancelSneakHide()
|
||||
// The later clients send back a OP_Hide (this has a size but data is 0)
|
||||
// as well as OP_SpawnAppearance with AT_Invis and one with AT_Sneak
|
||||
// So we don't have to handle any of those flags
|
||||
if (ClientVersionBit() & EQEmu::versions::bit_SoFAndEarlier)
|
||||
if (ClientVersionBit() & EQEmu::versions::maskSoFAndEarlier)
|
||||
sneaking = false;
|
||||
}
|
||||
}
|
||||
@@ -2183,7 +2129,7 @@ void Client::ClearHover()
|
||||
entity_list.QueueClients(this, outapp, false);
|
||||
safe_delete(outapp);
|
||||
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater)
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::maskUFAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
|
||||
+561
-89
@@ -67,6 +67,7 @@
|
||||
#include "water_map.h"
|
||||
#include "worldserver.h"
|
||||
#include "fastmath.h"
|
||||
#include "mob_movement_manager.h"
|
||||
#include "npc_scale_manager.h"
|
||||
|
||||
extern QueryServ* QServ;
|
||||
@@ -205,7 +206,7 @@ int command_init(void)
|
||||
command_add("flag", "[status] [acctname] - Refresh your admin status, or set an account's admin status if arguments provided", 0, command_flag) ||
|
||||
command_add("flagedit", "- Edit zone flags on your target", 100, command_flagedit) ||
|
||||
command_add("flags", "- displays the flags of you or your target", 0, command_flags) ||
|
||||
command_add("flymode", "[0/1/2] - Set your or your player target's flymode to off/on/levitate", 50, command_flymode) ||
|
||||
command_add("flymode", "[0/1/2/3/4/5] - Set your or your player target's flymode to ground/flying/levitate/water/floating/levitate_running", 50, command_flymode) ||
|
||||
command_add("fov", "- Check wether you're behind or in your target's field of view", 80, command_fov) ||
|
||||
command_add("freeze", "- Freeze your target", 80, command_freeze) ||
|
||||
command_add("gassign", "[id] - Assign targetted NPC to predefined wandering grid id", 100, command_gassign) ||
|
||||
@@ -218,6 +219,7 @@ int command_init(void)
|
||||
command_add("globalview", "Lists all qglobals in cache if you were to do a quest with this target.", 80, command_globalview) ||
|
||||
command_add("gm", "- Turn player target's or your GM flag on or off", 80, command_gm) ||
|
||||
command_add("gmspeed", "[on/off] - Turn GM speed hack on/off for you or your player target", 100, command_gmspeed) ||
|
||||
command_add("gmzone", "[zone_short_name] [zone_version=0] [identifier=gmzone] - Zones to a private GM instance", 100, command_gmzone) ||
|
||||
command_add("goto", "[x] [y] [z] - Teleport to the provided coordinates or to your target", 10, command_goto) ||
|
||||
command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", 170, command_grid) ||
|
||||
command_add("guild", "- Guild manipulation commands. Use argument help for more info.", 10, command_guild) ||
|
||||
@@ -248,6 +250,7 @@ int command_init(void)
|
||||
command_add("itemsearch", "[search criteria] - Search for an item", 10, command_itemsearch) ||
|
||||
command_add("kick", "[charname] - Disconnect charname", 150, command_kick) ||
|
||||
command_add("kill", "- Kill your target", 100, command_kill) ||
|
||||
command_add("killallnpcs", " [npc_name] Kills all npcs by search name, leave blank for all attackable NPC's", 200, command_killallnpcs) ||
|
||||
command_add("lastname", "[new lastname] - Set your or your player target's lastname", 50, command_lastname) ||
|
||||
command_add("level", "[level] - Set your or your target's level", 10, command_level) ||
|
||||
command_add("listnpcs", "[name/range] - Search NPCs", 20, command_listnpcs) ||
|
||||
@@ -267,6 +270,7 @@ int command_init(void)
|
||||
command_add("modifynpcstat", "- Modifys a NPC's stats", 150, command_modifynpcstat) ||
|
||||
command_add("motd", "[new motd] - Set message of the day", 150, command_motd) ||
|
||||
command_add("movechar", "[charname] [zonename] - Move charname to zonename", 50, command_movechar) ||
|
||||
command_add("movement", "Various movement commands", 200, command_movement) ||
|
||||
command_add("myskills", "- Show details about your current skill levels", 0, command_myskills) ||
|
||||
command_add("mysqltest", "Akkadius MySQL Bench Test", 250, command_mysqltest) ||
|
||||
command_add("mysql", "Mysql CLI, see 'help' for options.", 250, command_mysql) ||
|
||||
@@ -310,6 +314,7 @@ int command_init(void)
|
||||
#endif
|
||||
|
||||
command_add("push", "Lets you do spell push", 150, command_push) ||
|
||||
command_add("proximity", "Shows NPC proximity", 150, command_proximity) ||
|
||||
command_add("pvp", "[on/off] - Set your or your player target's PVP status", 100, command_pvp) ||
|
||||
command_add("qglobal", "[on/off/view] - Toggles qglobal functionality on an NPC", 100, command_qglobal) ||
|
||||
command_add("questerrors", "Shows quest errors.", 100, command_questerrors) ||
|
||||
@@ -385,6 +390,7 @@ int command_init(void)
|
||||
command_add("tattoo", "- Change the tattoo of your target (Drakkin Only)", 80, command_tattoo) ||
|
||||
command_add("tempname", "[newname] - Temporarily renames your target. Leave name blank to restore the original name.", 100, command_tempname) ||
|
||||
command_add("petname", "[newname] - Temporarily renames your pet. Leave name blank to restore the original name.", 100, command_petname) ||
|
||||
command_add("test", "Test command", 200, command_test) ||
|
||||
command_add("texture", "[texture] [helmtexture] - Change your or your target's appearance, use 255 to show equipment", 10, command_texture) ||
|
||||
command_add("time", "[HH] [MM] - Set EQ time", 90, command_time) ||
|
||||
command_add("timers", "- Display persistent timers for target", 200, command_timers) ||
|
||||
@@ -408,6 +414,7 @@ int command_init(void)
|
||||
command_add("viewpetition", "[petition number] - View a petition", 20, command_viewpetition) ||
|
||||
command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", 200, command_wc) ||
|
||||
command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", 80, command_weather) ||
|
||||
command_add("who", "[search]", 20, command_who) ||
|
||||
command_add("worldshutdown", "- Shut down world and all zones", 200, command_worldshutdown) ||
|
||||
command_add("wp", "[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid", 170, command_wp) ||
|
||||
command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path", 170, command_wpadd) ||
|
||||
@@ -745,21 +752,21 @@ void command_serversidename(Client *c, const Seperator *sep)
|
||||
|
||||
void command_wc(Client *c, const Seperator *sep)
|
||||
{
|
||||
if(sep->argnum < 2)
|
||||
{
|
||||
c->Message(0, "Usage: #wc [wear slot] [material] [ [hero_forge_model] [elite_material] [unknown06] [unknown18] ]");
|
||||
if (sep->argnum < 2) {
|
||||
c->Message(
|
||||
0,
|
||||
"Usage: #wc [wear slot] [material] [ [hero_forge_model] [elite_material] [unknown06] [unknown18] ]"
|
||||
);
|
||||
}
|
||||
else if(c->GetTarget() == nullptr) {
|
||||
else if (c->GetTarget() == nullptr) {
|
||||
c->Message(13, "You must have a target to do a wear change.");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
uint32 hero_forge_model = 0;
|
||||
uint32 wearslot = atoi(sep->arg[1]);
|
||||
uint32 wearslot = atoi(sep->arg[1]);
|
||||
|
||||
// Hero Forge
|
||||
if (sep->argnum > 2)
|
||||
{
|
||||
if (sep->argnum > 2) {
|
||||
hero_forge_model = atoi(sep->arg[3]);
|
||||
|
||||
if (hero_forge_model != 0 && hero_forge_model < 1000) {
|
||||
@@ -775,45 +782,43 @@ void command_wc(Client *c, const Seperator *sep)
|
||||
else
|
||||
Color = c->GetTarget()->GetArmorTint(atoi(sep->arg[1]));
|
||||
*/
|
||||
c->GetTarget()->SendTextureWC(wearslot, atoi(sep->arg[2]), hero_forge_model, atoi(sep->arg[4]), atoi(sep->arg[5]), atoi(sep->arg[6]));
|
||||
c->GetTarget()->SendTextureWC(
|
||||
wearslot,
|
||||
atoi(sep->arg[2]),
|
||||
hero_forge_model,
|
||||
atoi(sep->arg[4]),
|
||||
atoi(sep->arg[5]),
|
||||
atoi(sep->arg[6]));
|
||||
}
|
||||
}
|
||||
|
||||
void command_heromodel(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (sep->argnum < 1)
|
||||
{
|
||||
if (sep->argnum < 1) {
|
||||
c->Message(0, "Usage: #heromodel [hero forge model] [ [slot] ] (example: #heromodel 63)");
|
||||
}
|
||||
else if (c->GetTarget() == nullptr)
|
||||
{
|
||||
else if (c->GetTarget() == nullptr) {
|
||||
c->Message(13, "You must have a target to do a wear change for Hero's Forge Models.");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
uint32 hero_forge_model = atoi(sep->arg[1]);
|
||||
|
||||
if (sep->argnum > 1)
|
||||
{
|
||||
uint8 wearslot = (uint8)atoi(sep->arg[2]);
|
||||
if (sep->argnum > 1) {
|
||||
uint8 wearslot = (uint8) atoi(sep->arg[2]);
|
||||
c->GetTarget()->SendTextureWC(wearslot, 0, hero_forge_model, 0, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hero_forge_model > 0)
|
||||
{
|
||||
else {
|
||||
if (hero_forge_model > 0) {
|
||||
// Conversion to simplify the command arguments
|
||||
// Hero's Forge model is actually model * 1000 + texture * 100 + wearslot
|
||||
// Hero's Forge Model slot 7 is actually for Robes, but it still needs to use wearslot 1 in the packet
|
||||
hero_forge_model *= 100;
|
||||
|
||||
for (uint8 wearslot = 0; wearslot < 7; wearslot++)
|
||||
{
|
||||
for (uint8 wearslot = 0; wearslot < 7; wearslot++) {
|
||||
c->GetTarget()->SendTextureWC(wearslot, 0, (hero_forge_model + wearslot), 0, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
c->Message(13, "Hero's Forge Model must be greater than 0.");
|
||||
}
|
||||
}
|
||||
@@ -824,12 +829,14 @@ void command_setanim(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (c->GetTarget() && sep->IsNumber(1)) {
|
||||
int num = atoi(sep->arg[1]);
|
||||
if(num < 0 || num >= _eaMaxAppearance) {
|
||||
c->Message(0, "Invalid animation number, between 0 and %d", _eaMaxAppearance-1);
|
||||
if (num < 0 || num >= _eaMaxAppearance) {
|
||||
c->Message(0, "Invalid animation number, between 0 and %d", _eaMaxAppearance - 1);
|
||||
}
|
||||
c->GetTarget()->SetAppearance(EmuAppearance(num));
|
||||
} else
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #setanim [animnum]");
|
||||
}
|
||||
}
|
||||
|
||||
void command_serverinfo(Client *c, const Seperator *sep)
|
||||
@@ -1024,7 +1031,7 @@ void command_summon(Client *c, const Seperator *sep)
|
||||
{ // npc target
|
||||
c->Message(0, "Summoning NPC %s to %1.1f, %1.1f, %1.1f", t->GetName(), c->GetX(), c->GetY(), c->GetZ());
|
||||
t->CastToNPC()->GMMove(c->GetX(), c->GetY(), c->GetZ(), c->GetHeading());
|
||||
t->CastToNPC()->SaveGuardSpot(true);
|
||||
t->CastToNPC()->SaveGuardSpot(glm::vec4(0.0f));
|
||||
}
|
||||
else if (t->IsCorpse())
|
||||
{ // corpse target
|
||||
@@ -1261,6 +1268,78 @@ void command_movechar(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_movement(Client *c, const Seperator *sep)
|
||||
{
|
||||
auto &mgr = MobMovementManager::Get();
|
||||
|
||||
if (sep->arg[1][0] == 0) {
|
||||
c->Message(0, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop/packet");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(sep->arg[1], "stats") == 0)
|
||||
{
|
||||
mgr.DumpStats(c);
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "clearstats") == 0)
|
||||
{
|
||||
mgr.ClearStats();
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "walkto") == 0)
|
||||
{
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(0, "No target found.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->WalkTo(c->GetX(), c->GetY(), c->GetZ());
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "runto") == 0)
|
||||
{
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(0, "No target found.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->RunTo(c->GetX(), c->GetY(), c->GetZ());
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "rotateto") == 0)
|
||||
{
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(0, "No target found.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->RotateToWalking(target->CalculateHeadingToTarget(c->GetX(), c->GetY()));
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "stop") == 0)
|
||||
{
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(0, "No target found.");
|
||||
return;
|
||||
}
|
||||
|
||||
target->StopNavigation();
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "packet") == 0)
|
||||
{
|
||||
auto target = c->GetTarget();
|
||||
if (target == nullptr) {
|
||||
c->Message(0, "No target found.");
|
||||
return;
|
||||
}
|
||||
|
||||
mgr.SendCommandToClients(target, atof(sep->arg[2]), atof(sep->arg[3]), atof(sep->arg[4]), atof(sep->arg[5]), atoi(sep->arg[6]), ClientRangeAny);
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #movement stats/clearstats/walkto/runto/rotateto/stop/packet");
|
||||
}
|
||||
}
|
||||
|
||||
void command_viewpetition(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (sep->arg[1][0] == 0) {
|
||||
@@ -2072,7 +2151,7 @@ void command_ai(Client *c, const Seperator *sep)
|
||||
}
|
||||
else if (strcasecmp(sep->arg[1], "guard") == 0) {
|
||||
if (target && target->IsNPC())
|
||||
target->CastToNPC()->SaveGuardSpot();
|
||||
target->CastToNPC()->SaveGuardSpot(target->GetPosition());
|
||||
else
|
||||
c->Message(0, "Usage: (targeted) #ai guard - sets npc to guard the current location (use #summon to move)");
|
||||
}
|
||||
@@ -2185,10 +2264,12 @@ void command_sendzonespawns(Client *c, const Seperator *sep)
|
||||
|
||||
void command_zsave(Client *c, const Seperator *sep)
|
||||
{
|
||||
if(zone->SaveZoneCFG())
|
||||
if (zone->SaveZoneCFG()) {
|
||||
c->Message(13, "Zone header saved successfully.");
|
||||
else
|
||||
}
|
||||
else {
|
||||
c->Message(13, "ERROR: Zone header data was NOT saved.");
|
||||
}
|
||||
}
|
||||
|
||||
void command_dbspawn2(Client *c, const Seperator *sep)
|
||||
@@ -2321,7 +2402,7 @@ void command_grid(Client *c, const Seperator *sep)
|
||||
static_cast<uint32>(atoi(row[4])),
|
||||
static_cast<uint32>(atoi(row[5]))
|
||||
);
|
||||
npc->SetFlyMode(1);
|
||||
npc->SetFlyMode(GravityBehavior::Flying);
|
||||
npc->GMMove(node_position.x, node_position.y, node_position.z, node_position.w);
|
||||
}
|
||||
}
|
||||
@@ -2421,20 +2502,37 @@ void command_mana(Client *c, const Seperator *sep)
|
||||
|
||||
void command_flymode(Client *c, const Seperator *sep)
|
||||
{
|
||||
Client *t=c;
|
||||
Mob *t = c;
|
||||
|
||||
if (strlen(sep->arg[1]) == 1 && !(sep->arg[1][0] == '0' || sep->arg[1][0] == '1' || sep->arg[1][0] == '2'))
|
||||
c->Message(0, "#flymode [0/1/2]");
|
||||
if (strlen(sep->arg[1]) == 1 && !(sep->arg[1][0] == '0' || sep->arg[1][0] == '1' || sep->arg[1][0] == '2' || sep->arg[1][0] == '3' || sep->arg[1][0] == '4' || sep->arg[1][0] == '5'))
|
||||
c->Message(0, "#flymode [0/1/2/3/4/5]");
|
||||
else {
|
||||
if(c->GetTarget() && c->GetTarget()->IsClient())
|
||||
t=c->GetTarget()->CastToClient();
|
||||
t->SendAppearancePacket(AT_Levitate, atoi(sep->arg[1]));
|
||||
if (sep->arg[1][0] == '1')
|
||||
c->Message(0, "Turning %s's Flymode ON", t->GetName());
|
||||
else if (sep->arg[1][0] == '2')
|
||||
c->Message(0, "Turning %s's Flymode LEV", t->GetName());
|
||||
else
|
||||
c->Message(0, "Turning %s's Flymode OFF", t->GetName());
|
||||
if (c->GetTarget()) {
|
||||
t = c->GetTarget();
|
||||
}
|
||||
|
||||
int fm = atoi(sep->arg[1]);
|
||||
|
||||
t->SetFlyMode(static_cast<GravityBehavior>(fm));
|
||||
t->SendAppearancePacket(AT_Levitate, fm);
|
||||
if (sep->arg[1][0] == '0') {
|
||||
c->Message(0, "Setting %s to Grounded", t->GetName());
|
||||
}
|
||||
else if (sep->arg[1][0] == '1') {
|
||||
c->Message(0, "Setting %s to Flying", t->GetName());
|
||||
}
|
||||
else if (sep->arg[1][0] == '2') {
|
||||
c->Message(0, "Setting %s to Levitating", t->GetName());
|
||||
}
|
||||
else if (sep->arg[1][0] == '3') {
|
||||
c->Message(0, "Setting %s to In Water", t->GetName());
|
||||
}
|
||||
else if (sep->arg[1][0] == '4') {
|
||||
c->Message(0, "Setting %s to Floating(Boat)", t->GetName());
|
||||
}
|
||||
else if (sep->arg[1][0] == '5') {
|
||||
c->Message(0, "Setting %s to Levitating While Running", t->GetName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2515,14 +2613,14 @@ void command_castspell(Client *c, const Seperator *sep)
|
||||
else
|
||||
if (c->GetTarget() == 0)
|
||||
if(c->Admin() >= commandInstacast)
|
||||
c->SpellFinished(spellid, 0, EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
c->SpellFinished(spellid, 0, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
else
|
||||
c->CastSpell(spellid, 0, EQEmu::CastingSlot::Item, 0);
|
||||
c->CastSpell(spellid, 0, EQEmu::spells::CastingSlot::Item, 0);
|
||||
else
|
||||
if(c->Admin() >= commandInstacast)
|
||||
c->SpellFinished(spellid, c->GetTarget(), EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
c->SpellFinished(spellid, c->GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff);
|
||||
else
|
||||
c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::CastingSlot::Item, 0);
|
||||
c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::spells::CastingSlot::Item, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2636,18 +2734,21 @@ void command_setskillall(Client *c, const Seperator *sep)
|
||||
|
||||
void command_race(Client *c, const Seperator *sep)
|
||||
{
|
||||
Mob *t=c->CastToMob();
|
||||
Mob *target = c->CastToMob();
|
||||
|
||||
if (sep->IsNumber(1)) {
|
||||
auto race = atoi(sep->arg[1]);
|
||||
if ((race >= 0 && race <= 732) || (race >= 2253 && race <= 2259)) {
|
||||
if ((c->GetTarget()) && c->Admin() >= commandRaceOthers)
|
||||
t = c->GetTarget();
|
||||
t->SendIllusionPacket(race);
|
||||
} else {
|
||||
if ((c->GetTarget()) && c->Admin() >= commandRaceOthers) {
|
||||
target = c->GetTarget();
|
||||
}
|
||||
target->SendIllusionPacket(race);
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #race [0-732, 2253-2259] (0 for back to normal)");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #race [0-732, 2253-2259] (0 for back to normal)");
|
||||
}
|
||||
}
|
||||
@@ -2725,6 +2826,18 @@ void command_spawn(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_test(Client *c, const Seperator *sep)
|
||||
{
|
||||
c->Message(15, "Triggering test command");
|
||||
|
||||
if (sep->arg[1]) {
|
||||
c->SetPrimaryWeaponOrnamentation(atoi(sep->arg[1]));
|
||||
}
|
||||
if (sep->arg[2]) {
|
||||
c->SetSecondaryWeaponOrnamentation(atoi(sep->arg[2]));
|
||||
}
|
||||
}
|
||||
|
||||
void command_texture(Client *c, const Seperator *sep)
|
||||
{
|
||||
|
||||
@@ -2776,7 +2889,7 @@ void command_npctypespawn(Client *c, const Seperator *sep)
|
||||
const NPCType* tmp = 0;
|
||||
if ((tmp = database.LoadNPCTypesData(atoi(sep->arg[1])))) {
|
||||
//tmp->fixedZ = 1;
|
||||
auto npc = new NPC(tmp, 0, c->GetPosition(), FlyMode3);
|
||||
auto npc = new NPC(tmp, 0, c->GetPosition(), GravityBehavior::Water);
|
||||
if (npc && sep->IsNumber(2))
|
||||
npc->SetNPCFactionID(atoi(sep->arg[2]));
|
||||
|
||||
@@ -4317,18 +4430,94 @@ void command_fixmob(Client *c, const Seperator *sep)
|
||||
|
||||
void command_gmspeed(Client *c, const Seperator *sep)
|
||||
{
|
||||
bool state=atobool(sep->arg[1]);
|
||||
Client *t=c;
|
||||
bool state = atobool(sep->arg[1]);
|
||||
Client *t = c;
|
||||
|
||||
if(c->GetTarget() && c->GetTarget()->IsClient())
|
||||
t=c->GetTarget()->CastToClient();
|
||||
|
||||
if(sep->arg[1][0] != 0) {
|
||||
database.SetGMSpeed(t->AccountID(), state?1:0);
|
||||
c->Message(0, "Turning GMSpeed %s for %s (zone to take effect)", state?"On":"Off", t->GetName());
|
||||
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
||||
t = c->GetTarget()->CastToClient();
|
||||
}
|
||||
else
|
||||
|
||||
if (sep->arg[1][0] != 0) {
|
||||
database.SetGMSpeed(t->AccountID(), state ? 1 : 0);
|
||||
c->Message(0, "Turning GMSpeed %s for %s (zone to take effect)", state ? "On" : "Off", t->GetName());
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #gmspeed [on/off]");
|
||||
}
|
||||
}
|
||||
|
||||
void command_gmzone(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!sep->arg[1]) {
|
||||
c->Message(0, "Usage");
|
||||
c->Message(0, "-------");
|
||||
c->Message(0, "#gmzone [zone_short_name] [zone_version=0]");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string zone_short_name_string = sep->arg[1];
|
||||
const char *zone_short_name = sep->arg[1];
|
||||
auto zone_version = static_cast<uint32>(sep->arg[2] ? atoi(sep->arg[2]) : 0);
|
||||
std::string identifier = "gmzone";
|
||||
uint32 zone_id = database.GetZoneID(zone_short_name);
|
||||
uint32 duration = 100000000;
|
||||
uint16 instance_id = 0;
|
||||
|
||||
if (zone_id == 0) {
|
||||
c->Message(13, "Invalid zone specified");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sep->arg[3] && sep->arg[3][0]) {
|
||||
identifier = sep->arg[3];
|
||||
}
|
||||
|
||||
std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str());
|
||||
std::string existing_zone_instance = DataBucket::GetData(bucket_key);
|
||||
|
||||
if (existing_zone_instance.length() > 0) {
|
||||
instance_id = std::stoi(existing_zone_instance);
|
||||
|
||||
c->Message(15, "Found already created instance (%s) (%u)", zone_short_name, instance_id);
|
||||
}
|
||||
|
||||
if (instance_id == 0) {
|
||||
if (!database.GetUnusedInstanceID(instance_id)) {
|
||||
c->Message(13, "Server was unable to find a free instance id.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!database.CreateInstance(instance_id, zone_id, zone_version, duration)) {
|
||||
c->Message(13, "Server was unable to create a new instance.");
|
||||
return;
|
||||
}
|
||||
|
||||
c->Message(15, "New private GM instance %s was created with id %lu.", zone_short_name, (unsigned long) instance_id);
|
||||
DataBucket::SetData(bucket_key, std::to_string(instance_id));
|
||||
}
|
||||
|
||||
if (instance_id > 0) {
|
||||
float target_x = -1, target_y = -1, target_z = -1;
|
||||
int16 min_status = 0;
|
||||
uint8 min_level = 0;
|
||||
|
||||
if (!database.GetSafePoints(
|
||||
zone_short_name,
|
||||
zone_version,
|
||||
&target_x,
|
||||
&target_y,
|
||||
&target_z,
|
||||
&min_status,
|
||||
&min_level
|
||||
)) {
|
||||
c->Message(13, "Failed to find safe coordinates for specified zone");
|
||||
}
|
||||
|
||||
c->Message(15, "Zoning to private GM instance (%s) (%u)", zone_short_name, instance_id);
|
||||
|
||||
c->AssignToInstance(instance_id);
|
||||
c->MovePC(zone_id, instance_id, target_x, target_y, target_z, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void command_title(Client *c, const Seperator *sep)
|
||||
@@ -4511,7 +4700,7 @@ void command_memspell(Client *c, const Seperator *sep)
|
||||
{
|
||||
slot = atoi(sep->arg[1]) - 1;
|
||||
spell_id = atoi(sep->arg[2]);
|
||||
if (slot > MAX_PP_MEMSPELL || spell_id >= SPDAT_RECORDS)
|
||||
if (slot > EQEmu::spells::SPELL_GEM_COUNT || spell_id >= SPDAT_RECORDS)
|
||||
{
|
||||
c->Message(0, "Error: #MemSpell: Arguement out of range");
|
||||
}
|
||||
@@ -4839,6 +5028,78 @@ void command_push(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_proximity(Client *c, const Seperator *sep)
|
||||
{
|
||||
if (!c->GetTarget() && !c->GetTarget()->IsNPC()) {
|
||||
c->Message(0, "You must target an NPC");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &iter : entity_list.GetNPCList()) {
|
||||
auto npc = iter.second;
|
||||
std::string name = npc->GetName();
|
||||
|
||||
if (name.find("Proximity") != std::string::npos) {
|
||||
npc->Depop();
|
||||
}
|
||||
}
|
||||
|
||||
NPC *npc = c->GetTarget()->CastToNPC();
|
||||
|
||||
std::vector<FindPerson_Point> points;
|
||||
|
||||
FindPerson_Point p{};
|
||||
|
||||
if (npc->IsProximitySet()) {
|
||||
glm::vec4 position;
|
||||
position.w = npc->GetHeading();
|
||||
position.x = npc->GetProximityMinX();
|
||||
position.y = npc->GetProximityMinY();
|
||||
position.z = npc->GetZ();
|
||||
|
||||
position.x = npc->GetProximityMinX();
|
||||
position.y = npc->GetProximityMinY();
|
||||
NPC::SpawnNodeNPC("Proximity", "", position);
|
||||
|
||||
position.x = npc->GetProximityMinX();
|
||||
position.y = npc->GetProximityMaxY();
|
||||
NPC::SpawnNodeNPC("Proximity", "", position);
|
||||
|
||||
position.x = npc->GetProximityMaxX();
|
||||
position.y = npc->GetProximityMinY();
|
||||
NPC::SpawnNodeNPC("Proximity", "", position);
|
||||
|
||||
position.x = npc->GetProximityMaxX();
|
||||
position.y = npc->GetProximityMaxY();
|
||||
NPC::SpawnNodeNPC("Proximity", "", position);
|
||||
|
||||
p.x = npc->GetProximityMinX();
|
||||
p.y = npc->GetProximityMinY();
|
||||
p.z = npc->GetZ();
|
||||
points.push_back(p);
|
||||
|
||||
p.x = npc->GetProximityMinX();
|
||||
p.y = npc->GetProximityMaxY();
|
||||
points.push_back(p);
|
||||
|
||||
p.x = npc->GetProximityMaxX();
|
||||
p.y = npc->GetProximityMaxY();
|
||||
points.push_back(p);
|
||||
|
||||
p.x = npc->GetProximityMaxX();
|
||||
p.y = npc->GetProximityMinY();
|
||||
points.push_back(p);
|
||||
|
||||
p.x = npc->GetProximityMinX();
|
||||
p.y = npc->GetProximityMinY();
|
||||
points.push_back(p);
|
||||
}
|
||||
|
||||
if (c->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) {
|
||||
c->SendPathPacket(points);
|
||||
}
|
||||
}
|
||||
|
||||
void command_pvp(Client *c, const Seperator *sep)
|
||||
{
|
||||
bool state=atobool(sep->arg[1]);
|
||||
@@ -4976,6 +5237,49 @@ void command_kill(Client *c, const Seperator *sep)
|
||||
c->GetTarget()->Kill();
|
||||
}
|
||||
|
||||
void command_killallnpcs(Client *c, const Seperator *sep)
|
||||
{
|
||||
std::string search_string;
|
||||
if (sep->arg[1]) {
|
||||
search_string = sep->arg[1];
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (auto &itr : entity_list.GetMobList()) {
|
||||
Mob *entity = itr.second;
|
||||
if (!entity->IsNPC()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string entity_name = entity->GetName();
|
||||
|
||||
/**
|
||||
* Filter by name
|
||||
*/
|
||||
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_not_attackable =
|
||||
(
|
||||
entity->IsInvisible() ||
|
||||
!entity->IsAttackAllowed(c) ||
|
||||
entity->GetRace() == 127 ||
|
||||
entity->GetRace() == 240
|
||||
);
|
||||
|
||||
if (is_not_attackable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entity->Damage(c, 1000000000, 0, EQEmu::skills::SkillDragonPunch);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
c->Message(15, "Killed (%i) npc(s)", count);
|
||||
}
|
||||
|
||||
void command_haste(Client *c, const Seperator *sep)
|
||||
{
|
||||
// #haste command to set client attack speed. Takes a percentage (100 = twice normal attack speed)
|
||||
@@ -5133,13 +5437,65 @@ void command_loc(Client *c, const Seperator *sep)
|
||||
|
||||
void command_goto(Client *c, const Seperator *sep)
|
||||
{
|
||||
// goto function
|
||||
if (sep->arg[1][0] == '\0' && c->GetTarget())
|
||||
c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ(), c->GetTarget()->GetHeading());
|
||||
else if (!(sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)))
|
||||
/**
|
||||
* Goto via target and no args
|
||||
*/
|
||||
if (sep->arg[1][0] == '\0' && c->GetTarget()) {
|
||||
c->MovePC(
|
||||
zone->GetZoneID(),
|
||||
zone->GetInstanceID(),
|
||||
c->GetTarget()->GetX(),
|
||||
c->GetTarget()->GetY(),
|
||||
c->GetTarget()->GetZ(),
|
||||
c->GetTarget()->GetHeading());
|
||||
}
|
||||
|
||||
/**
|
||||
* Goto via player name
|
||||
*/
|
||||
else if (!sep->IsNumber(1) && sep->arg[1]) {
|
||||
|
||||
/**
|
||||
* Find them in zone first
|
||||
*/
|
||||
const char *player_name = sep->arg[1];
|
||||
std::string player_name_string = sep->arg[1];
|
||||
Client *client = entity_list.GetClientByName(player_name);
|
||||
if (client) {
|
||||
c->MovePC(
|
||||
zone->GetZoneID(),
|
||||
zone->GetInstanceID(),
|
||||
client->GetX(),
|
||||
client->GetY(),
|
||||
client->GetZ(),
|
||||
client->GetHeading());
|
||||
|
||||
c->Message(15, "Goto player '%s' same zone", player_name_string.c_str());
|
||||
}
|
||||
else if (c->GotoPlayer(player_name_string)) {
|
||||
c->Message(15, "Goto player '%s' different zone", player_name_string.c_str());
|
||||
}
|
||||
else {
|
||||
c->Message(15, "Player '%s' not found", player_name_string.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Goto via x y z
|
||||
*/
|
||||
else if (sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)) {
|
||||
c->MovePC(
|
||||
zone->GetZoneID(),
|
||||
zone->GetInstanceID(),
|
||||
atof(sep->arg[1]),
|
||||
atof(sep->arg[2]),
|
||||
atof(sep->arg[3]),
|
||||
c->GetHeading());
|
||||
}
|
||||
else {
|
||||
c->Message(0, "Usage: #goto [x y z]");
|
||||
else
|
||||
c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), atof(sep->arg[1]), atof(sep->arg[2]), atof(sep->arg[3]), c->GetHeading());
|
||||
c->Message(0, "Usage: #goto [player_name]");
|
||||
}
|
||||
}
|
||||
|
||||
void command_iteminfo(Client *c, const Seperator *sep)
|
||||
@@ -6085,7 +6441,7 @@ void command_scribespells(Client *c, const Seperator *sep)
|
||||
c->Message(0, "Scribing spells for %s.", t->GetName());
|
||||
Log(Logs::General, Logs::Normal, "Scribe spells request for %s from %s, levels: %u -> %u", t->GetName(), c->GetName(), min_level, max_level);
|
||||
|
||||
for(curspell = 0, book_slot = t->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; curspell++, book_slot = t->GetNextAvailableSpellBookSlot(book_slot))
|
||||
for(curspell = 0, book_slot = t->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < EQEmu::spells::SPELLBOOK_SIZE; curspell++, book_slot = t->GetNextAvailableSpellBookSlot(book_slot))
|
||||
{
|
||||
if
|
||||
(
|
||||
@@ -7807,10 +8163,8 @@ void command_pf(Client *c, const Seperator *sep)
|
||||
Mob *who = c->GetTarget();
|
||||
c->Message(0, "POS: (%.2f, %.2f, %.2f)", who->GetX(), who->GetY(), who->GetZ());
|
||||
c->Message(0, "WP: %s (%d/%d)", to_string(who->GetCurrentWayPoint()).c_str(), who->IsNPC()?who->CastToNPC()->GetMaxWp():-1);
|
||||
c->Message(0, "TAR: (%.2f, %.2f, %.2f)", who->GetTarX(), who->GetTarY(), who->GetTarZ());
|
||||
c->Message(0, "TARV: (%.2f, %.2f, %.2f)", who->GetTarVX(), who->GetTarVY(), who->GetTarVZ());
|
||||
c->Message(0, "|TV|=%.2f index=%d", who->GetTarVector(), who->GetTarNDX());
|
||||
c->Message(0, "pause=%d RAspeed=%d", who->GetCWPP(), who->GetRunAnimSpeed());
|
||||
//who->DumpMovement(c);
|
||||
} else {
|
||||
c->Message(0, "ERROR: target required");
|
||||
}
|
||||
@@ -8131,7 +8485,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(0, "(%d) %s", cur->first, cur->second.c_str());
|
||||
}
|
||||
} else if(!strcasecmp(sep->arg[1], "reload")) {
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset());
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||
c->Message(0, "The active ruleset (%s (%d)) has been reloaded", RuleManager::Instance()->GetActiveRuleset(),
|
||||
RuleManager::Instance()->GetActiveRulesetID());
|
||||
} else if(!strcasecmp(sep->arg[1], "switch")) {
|
||||
@@ -8147,7 +8501,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
}
|
||||
|
||||
//TODO: we likely want to reload this ruleset everywhere...
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2]);
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2], true);
|
||||
|
||||
c->Message(0, "The selected ruleset has been changed to (%s (%d)) and reloaded locally", sep->arg[2], rsid);
|
||||
} else if(!strcasecmp(sep->arg[1], "load")) {
|
||||
@@ -8157,7 +8511,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(13, "Unknown rule set '%s'", sep->arg[2]);
|
||||
return;
|
||||
}
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2]);
|
||||
RuleManager::Instance()->LoadRules(&database, sep->arg[2], true);
|
||||
c->Message(0, "Loaded ruleset '%s' (%d) locally", sep->arg[2], rsid);
|
||||
} else if(!strcasecmp(sep->arg[1], "store")) {
|
||||
if(sep->argnum == 1) {
|
||||
@@ -8181,9 +8535,9 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
return;
|
||||
}
|
||||
} else if(!strcasecmp(sep->arg[1], "reset")) {
|
||||
RuleManager::Instance()->ResetRules();
|
||||
RuleManager::Instance()->ResetRules(true);
|
||||
c->Message(0, "The running ruleset has been set to defaults");
|
||||
|
||||
|
||||
} else if(!strcasecmp(sep->arg[1], "get")) {
|
||||
if(sep->argnum != 2) {
|
||||
c->Message(13, "Invalid argument count, see help.");
|
||||
@@ -8200,7 +8554,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(13, "Invalid argument count, see help.");
|
||||
return;
|
||||
}
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3])) {
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], nullptr, false, true)) {
|
||||
c->Message(13, "Failed to modify rule");
|
||||
} else {
|
||||
c->Message(0, "Rule modified locally.");
|
||||
@@ -8210,7 +8564,7 @@ void command_rules(Client *c, const Seperator *sep) {
|
||||
c->Message(13, "Invalid argument count, see help.");
|
||||
return;
|
||||
}
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true)) {
|
||||
if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true, true)) {
|
||||
c->Message(13, "Failed to modify rule");
|
||||
} else {
|
||||
c->Message(0, "Rule modified locally and in the database.");
|
||||
@@ -8733,9 +9087,7 @@ void command_advnpcspawn(Client *c, const Seperator *sep)
|
||||
}
|
||||
|
||||
c->Message(0, "Updating coordinates successful.");
|
||||
target->CastToNPC()->GMMove(c->GetX(), c->GetY(), c->GetZ(), c->GetHeading());
|
||||
target->CastToNPC()->SaveGuardSpot(true);
|
||||
target->SendPosition();
|
||||
target->GMMove(c->GetX(), c->GetY(), c->GetZ(), c->GetHeading());
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -11573,6 +11925,126 @@ void command_scale(Client *c, const Seperator *sep)
|
||||
}
|
||||
}
|
||||
|
||||
void command_who(Client *c, const Seperator *sep)
|
||||
{
|
||||
std::string query =
|
||||
"SELECT\n"
|
||||
" character_data.account_id,\n"
|
||||
" character_data.name,\n"
|
||||
" character_data.zone_id,\n"
|
||||
" COALESCE((select zone.short_name from zone where zoneidnumber = character_data.zone_id LIMIT 1), \"Not Found\") as zone_name,\n"
|
||||
" character_data.zone_instance,\n"
|
||||
" COALESCE((select guilds.name from guilds where id = ((select guild_id from guild_members where char_id = character_data.id))), \"\") as guild_name,\n"
|
||||
" character_data.level,\n"
|
||||
" character_data.race,\n"
|
||||
" character_data.class,\n"
|
||||
" COALESCE((select account.status from account where account.id = character_data.account_id LIMIT 1), 0) as account_status,\n"
|
||||
" COALESCE((select account.name from account where account.id = character_data.account_id LIMIT 1), \"\") as account_name,\n"
|
||||
" COALESCE((select account_ip.ip from account_ip where account_ip.accid = character_data.account_id ORDER BY account_ip.lastused DESC LIMIT 1), \"\") as account_ip\n"
|
||||
"FROM\n"
|
||||
" character_data\n"
|
||||
"WHERE\n"
|
||||
" last_login > (UNIX_TIMESTAMP() - 600)\n"
|
||||
"ORDER BY character_data.name;";
|
||||
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return;
|
||||
|
||||
if (results.RowCount() == 0) {
|
||||
c->Message(15, "No results found");
|
||||
return;
|
||||
}
|
||||
|
||||
std::string search_string;
|
||||
|
||||
if (sep->arg[1]) {
|
||||
search_string = str_tolower(sep->arg[1]);
|
||||
}
|
||||
|
||||
int found_count = 0;
|
||||
|
||||
c->Message(5, "Players in EverQuest");
|
||||
c->Message(5, "--------------------");
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
auto account_id = static_cast<uint32>(atoi(row[0]));
|
||||
std::string player_name = row[1];
|
||||
auto zone_id = static_cast<uint32>(atoi(row[2]));
|
||||
std::string zone_short_name = row[3];
|
||||
auto zone_instance = static_cast<uint32>(atoi(row[4]));
|
||||
std::string guild_name = row[5];
|
||||
auto player_level = static_cast<uint32>(atoi(row[6]));
|
||||
auto player_race = static_cast<uint32>(atoi(row[7]));
|
||||
auto player_class = static_cast<uint32>(atoi(row[8]));
|
||||
auto account_status = static_cast<uint32>(atoi(row[9]));
|
||||
std::string account_name = row[10];
|
||||
std::string account_ip = row[11];
|
||||
|
||||
std::string base_class_name = GetClassIDName(static_cast<uint8>(player_class), 1);
|
||||
std::string displayed_race_name = GetRaceIDName(static_cast<uint16>(player_race));
|
||||
|
||||
if (search_string.length() > 0) {
|
||||
bool found_search_term =
|
||||
(
|
||||
str_tolower(player_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(zone_short_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(displayed_race_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(base_class_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(guild_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(account_name).find(search_string) != std::string::npos ||
|
||||
str_tolower(account_ip).find(search_string) != std::string::npos
|
||||
);
|
||||
|
||||
if (!found_search_term) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
std::string displayed_guild_name;
|
||||
if (guild_name.length() > 0) {
|
||||
displayed_guild_name = EQEmu::SayLinkEngine::GenerateQuestSaylink(
|
||||
StringFormat(
|
||||
"#who \"%s\"",
|
||||
guild_name.c_str()),
|
||||
false,
|
||||
StringFormat("<%s>", guild_name.c_str())
|
||||
);
|
||||
}
|
||||
|
||||
std::string goto_saylink = EQEmu::SayLinkEngine::GenerateQuestSaylink(
|
||||
StringFormat("#goto %s", player_name.c_str()), false, "Goto"
|
||||
);
|
||||
|
||||
std::string display_class_name = GetClassIDName(static_cast<uint8>(player_class), static_cast<uint8>(player_level));
|
||||
|
||||
c->Message(
|
||||
5, "%s[%u %s] %s (%s) %s ZONE: %s (%u) (%s) (%s) (%s)",
|
||||
(account_status > 0 ? "* GM * " : ""),
|
||||
player_level,
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", base_class_name.c_str()), false, display_class_name).c_str(),
|
||||
player_name.c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", displayed_race_name.c_str()), false, displayed_race_name).c_str(),
|
||||
displayed_guild_name.c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", zone_short_name.c_str()), false, zone_short_name).c_str(),
|
||||
zone_instance,
|
||||
goto_saylink.c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_name.c_str()), false, account_name).c_str(),
|
||||
EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_ip.c_str()), false, account_ip).c_str()
|
||||
);
|
||||
|
||||
found_count++;
|
||||
}
|
||||
|
||||
std::string message = (
|
||||
found_count > 0 ?
|
||||
StringFormat("There is %i player(s) in EverQuest", found_count).c_str() :
|
||||
"There are no players in EverQuest that match those who filters."
|
||||
);
|
||||
|
||||
c->Message(5, message.c_str());
|
||||
}
|
||||
|
||||
// All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block.
|
||||
#ifdef BOTS
|
||||
#include "bot_command.h"
|
||||
|
||||
@@ -117,6 +117,7 @@ void command_givemoney(Client *c, const Seperator *sep);
|
||||
void command_globalview(Client* c, const Seperator *sep);
|
||||
void command_gm(Client *c, const Seperator *sep);
|
||||
void command_gmspeed(Client *c, const Seperator *sep);
|
||||
void command_gmzone(Client *c, const Seperator *sep);
|
||||
void command_goto(Client *c, const Seperator *sep);
|
||||
void command_grid(Client *c, const Seperator *sep);
|
||||
void command_guild(Client *c, const Seperator *sep);
|
||||
@@ -149,6 +150,7 @@ 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);
|
||||
void command_lastname(Client *c, const Seperator *sep);
|
||||
void command_level(Client *c, const Seperator *sep);
|
||||
@@ -170,6 +172,7 @@ void command_merchantopenshop(Client *c, const Seperator *sep);
|
||||
void command_modifynpcstat(Client *c, const Seperator *sep);
|
||||
void command_motd(Client *c, const Seperator *sep);
|
||||
void command_movechar(Client *c, const Seperator *sep);
|
||||
void command_movement(Client *c, const Seperator *sep);
|
||||
void command_myskills(Client *c, const Seperator *sep);
|
||||
void command_mysql(Client *c, const Seperator *sep);
|
||||
void command_mysqltest(Client *c, const Seperator *sep);
|
||||
@@ -213,6 +216,7 @@ void command_profiledump(Client *c, const Seperator *sep);
|
||||
void command_profilereset(Client *c, const Seperator *sep);
|
||||
#endif
|
||||
|
||||
void command_proximity(Client *c, const Seperator *sep);
|
||||
void command_push(Client *c, const Seperator *sep);
|
||||
void command_pvp(Client *c, const Seperator *sep);
|
||||
void command_qglobal(Client *c, const Seperator *sep);
|
||||
@@ -295,6 +299,7 @@ void command_task(Client *c, const Seperator *sep);
|
||||
void command_tattoo(Client *c, const Seperator *sep);
|
||||
void command_tempname(Client *c, const Seperator *sep);
|
||||
void command_petname(Client *c, const Seperator *sep);
|
||||
void command_test(Client *c, const Seperator *sep);
|
||||
void command_testspawn(Client *c, const Seperator *sep);
|
||||
void command_testspawnkill(Client *c, const Seperator *sep);
|
||||
void command_texture(Client *c, const Seperator *sep);
|
||||
@@ -321,6 +326,7 @@ void command_viewnpctype(Client *c, const Seperator *sep);
|
||||
void command_viewpetition(Client *c, const Seperator *sep);
|
||||
void command_wc(Client *c, const Seperator *sep);
|
||||
void command_weather(Client *c, const Seperator *sep);
|
||||
void command_who(Client *c, const Seperator *sep);
|
||||
void command_worldshutdown(Client *c, const Seperator *sep);
|
||||
void command_wp(Client *c, const Seperator *sep);
|
||||
void command_wpadd(Client *c, const Seperator *sep);
|
||||
|
||||
@@ -206,8 +206,6 @@ typedef enum { //fear states
|
||||
fearStateStuck //I cannot move somehow...
|
||||
} FearState;
|
||||
|
||||
enum { FlyMode0 = 0, FlyMode1 = 1, Flymode2 = 2, FlyMode3 = 3 };
|
||||
|
||||
// This is actually FlyMode, from MQ2
|
||||
enum GravityBehavior {
|
||||
Ground,
|
||||
|
||||
+3
-3
@@ -1374,7 +1374,7 @@ void Corpse::QueryLoot(Client* to) {
|
||||
cur = itemlist.begin();
|
||||
end = itemlist.end();
|
||||
|
||||
int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(to->ClientVersion()))->InventoryTypeSize[EQEmu::invtype::typeCorpse];
|
||||
int corpselootlimit = to->GetInv().GetLookup()->InventoryTypeSize.Corpse;
|
||||
|
||||
for(; cur != end; ++cur) {
|
||||
ServerLootItem_Struct* sitem = *cur;
|
||||
@@ -1479,7 +1479,7 @@ void Corpse::Spawn() {
|
||||
safe_delete(app);
|
||||
}
|
||||
|
||||
uint32 Corpse::GetEquipment(uint8 material_slot) const {
|
||||
uint32 Corpse::GetEquippedItemFromTextureSlot(uint8 material_slot) const {
|
||||
int16 invslot;
|
||||
|
||||
if (material_slot > EQEmu::textures::LastTexture) {
|
||||
@@ -1500,7 +1500,7 @@ uint32 Corpse::GetEquipmentColor(uint8 material_slot) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = database.GetItem(GetEquipment(material_slot));
|
||||
item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
|
||||
if(item != 0) {
|
||||
return (item_tint.Slot[material_slot].UseTint ? item_tint.Slot[material_slot].Color : item->Color);
|
||||
}
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ class Corpse : public Mob {
|
||||
void Spawn();
|
||||
|
||||
char corpse_name[64];
|
||||
uint32 GetEquipment(uint8 material_slot) const;
|
||||
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const;
|
||||
uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
inline int GetRezExp() { return rez_experience; }
|
||||
|
||||
|
||||
+1
-1
@@ -496,7 +496,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
|
||||
}
|
||||
}
|
||||
|
||||
void Doors::NPCOpen(NPC* sender, bool alt_mode)
|
||||
void Doors::Open(Mob* sender, bool alt_mode)
|
||||
{
|
||||
if (sender) {
|
||||
if (GetTriggerType() == 255 || GetTriggerDoorID() > 0 || GetLockpick() != 0 || GetKeyItem() != 0 || open_type == 59 || open_type == 58 || !sender->IsNPC()) { // this object isnt triggered or door is locked - NPCs should not open locked doors!
|
||||
|
||||
+1
-1
@@ -49,7 +49,7 @@ public:
|
||||
void ForceClose(Mob *sender, bool alt_mode = false);
|
||||
void ForceOpen(Mob *sender, bool alt_mode = false);
|
||||
void HandleClick(Client *sender, uint8 trigger);
|
||||
void NPCOpen(NPC *sender, bool alt_mode = false);
|
||||
void Open(Mob *sender, bool alt_mode = false);
|
||||
void SetDisableTimer(bool flag);
|
||||
void SetDoorName(const char *name);
|
||||
void SetEntityID(uint32 entity) { entity_id = entity; }
|
||||
|
||||
+3
-3
@@ -643,9 +643,9 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
}
|
||||
|
||||
if (reduced_recast > 0)
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast);
|
||||
else{
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -653,7 +653,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
||||
}
|
||||
else
|
||||
{
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
+34
-2
@@ -3203,9 +3203,9 @@ XS(XS__FlyMode);
|
||||
XS(XS__FlyMode) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: quest::FlyMode(uint8 mode [0-3])");
|
||||
Perl_croak(aTHX_ "Usage: quest::FlyMode(uint8 mode [0-5])");
|
||||
|
||||
uint8 flymode = (int) SvUV(ST(0));
|
||||
GravityBehavior flymode = (GravityBehavior) SvUV(ST(0));
|
||||
quest_manager.FlyMode(flymode);
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
@@ -3622,6 +3622,36 @@ XS(XS__UpdateZoneHeader) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__set_rule);
|
||||
XS(XS__set_rule) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: quest::set_rule(string rule_name, string rule_value)");
|
||||
|
||||
std::string rule_name = (std::string) SvPV_nolen(ST(0));
|
||||
std::string rule_value = (std::string) SvPV_nolen(ST(1));
|
||||
RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str());
|
||||
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS__get_rule);
|
||||
XS(XS__get_rule) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: quest::get_rule(string rule_name)");
|
||||
|
||||
dXSTARG;
|
||||
std::string rule_name = (std::string) SvPV_nolen(ST(0));
|
||||
std::string rule_value;
|
||||
RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value);
|
||||
|
||||
sv_setpv(TARG, rule_value.c_str());
|
||||
XSprePUSH;
|
||||
PUSHTARG;
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS__get_data);
|
||||
XS(XS__get_data) {
|
||||
dXSARGS;
|
||||
@@ -3734,6 +3764,8 @@ EXTERN_C XS(boot_quest) {
|
||||
newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file);
|
||||
newXS(strcpy(buf, "GetZoneID"), XS__GetZoneID, file);
|
||||
newXS(strcpy(buf, "GetZoneLongName"), XS__GetZoneLongName, file);
|
||||
newXS(strcpy(buf, "set_rule"), XS__set_rule, file);
|
||||
newXS(strcpy(buf, "get_rule"), XS__get_rule, file);
|
||||
newXS(strcpy(buf, "get_data"), XS__get_data, file);
|
||||
newXS(strcpy(buf, "get_data_expires"), XS__get_data_expires, file);
|
||||
newXS(strcpy(buf, "set_data"), XS__set_data, file);
|
||||
|
||||
+51
-96
@@ -650,8 +650,6 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue)
|
||||
|
||||
parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0);
|
||||
|
||||
npc->FixZ();
|
||||
|
||||
uint16 emoteid = npc->GetEmoteID();
|
||||
if (emoteid != 0)
|
||||
npc->DoNPCEmote(ONSPAWN, emoteid);
|
||||
@@ -1274,32 +1272,35 @@ void EntityList::SendZoneSpawns(Client *client)
|
||||
|
||||
void EntityList::SendZoneSpawnsBulk(Client *client)
|
||||
{
|
||||
NewSpawn_Struct ns;
|
||||
Mob *spawn;
|
||||
uint32 maxspawns = 100;
|
||||
NewSpawn_Struct ns{};
|
||||
Mob *spawn;
|
||||
EQApplicationPacket *app;
|
||||
|
||||
if (maxspawns > mob_list.size())
|
||||
maxspawns = mob_list.size();
|
||||
auto bzsp = new BulkZoneSpawnPacket(client, maxspawns);
|
||||
uint32 max_spawns = 100;
|
||||
|
||||
if (max_spawns > mob_list.size()) {
|
||||
max_spawns = static_cast<uint32>(mob_list.size());
|
||||
}
|
||||
|
||||
auto bulk_zone_spawn_packet = new BulkZoneSpawnPacket(client, max_spawns);
|
||||
const glm::vec4 &client_position = client->GetPosition();
|
||||
const float distance_max = (600.0 * 600.0);
|
||||
|
||||
bool delaypkt = false;
|
||||
const glm::vec4& cpos = client->GetPosition();
|
||||
const float dmax = 600.0 * 600.0;
|
||||
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
|
||||
spawn = it->second;
|
||||
if (spawn && spawn->GetID() > 0 && spawn->Spawned()) {
|
||||
if (!spawn->ShouldISpawnFor(client))
|
||||
if (!spawn->ShouldISpawnFor(client)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
#if 1
|
||||
const glm::vec4& spos = spawn->GetPosition();
|
||||
const glm::vec4 &spawn_position = spawn->GetPosition();
|
||||
|
||||
delaypkt = false;
|
||||
if (DistanceSquared(cpos, spos) > dmax || (spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE)))
|
||||
delaypkt = true;
|
||||
bool is_delayed_packet = (
|
||||
DistanceSquared(client_position, spawn_position) > distance_max ||
|
||||
(spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE))
|
||||
);
|
||||
|
||||
if (delaypkt) {
|
||||
if (is_delayed_packet) {
|
||||
app = new EQApplicationPacket;
|
||||
spawn->CreateSpawnPacket(app);
|
||||
client->QueuePacket(app, true, Client::CLIENT_CONNECTED);
|
||||
@@ -1308,35 +1309,38 @@ void EntityList::SendZoneSpawnsBulk(Client *client)
|
||||
else {
|
||||
memset(&ns, 0, sizeof(NewSpawn_Struct));
|
||||
spawn->FillSpawnStruct(&ns, client);
|
||||
bzsp->AddSpawn(&ns);
|
||||
bulk_zone_spawn_packet->AddSpawn(&ns);
|
||||
}
|
||||
|
||||
spawn->SendArmorAppearance(client);
|
||||
#else
|
||||
/* original code kept for spawn packet research */
|
||||
int32 race = spawn->GetRace();
|
||||
|
||||
// Illusion races on PCs don't work as a mass spawn
|
||||
// But they will work as an add_spawn AFTER CLIENT_CONNECTED.
|
||||
if (spawn->IsClient() && (race == MINOR_ILL_OBJ || race == TREE)) {
|
||||
app = new EQApplicationPacket;
|
||||
spawn->CreateSpawnPacket(app);
|
||||
client->QueuePacket(app, true, Client::CLIENT_CONNECTED);
|
||||
safe_delete(app);
|
||||
}
|
||||
else {
|
||||
memset(&ns, 0, sizeof(NewSpawn_Struct));
|
||||
spawn->FillSpawnStruct(&ns, client);
|
||||
bzsp->AddSpawn(&ns);
|
||||
}
|
||||
|
||||
// Despite being sent in the OP_ZoneSpawns packet, the client
|
||||
// does not display worn armor correctly so display it.
|
||||
spawn->SendArmorAppearance(client);
|
||||
#endif
|
||||
/**
|
||||
* Original code kept for spawn packet research
|
||||
*
|
||||
* int32 race = spawn->GetRace();
|
||||
*
|
||||
* Illusion races on PCs don't work as a mass spawn
|
||||
* But they will work as an add_spawn AFTER CLIENT_CONNECTED.
|
||||
* if (spawn->IsClient() && (race == MINOR_ILL_OBJ || race == TREE)) {
|
||||
* app = new EQApplicationPacket;
|
||||
* spawn->CreateSpawnPacket(app);
|
||||
* client->QueuePacket(app, true, Client::CLIENT_CONNECTED);
|
||||
* safe_delete(app);
|
||||
* }
|
||||
* else {
|
||||
* memset(&ns, 0, sizeof(NewSpawn_Struct));
|
||||
* spawn->FillSpawnStruct(&ns, client);
|
||||
* bzsp->AddSpawn(&ns);
|
||||
* }
|
||||
*
|
||||
* Despite being sent in the OP_ZoneSpawns packet, the client
|
||||
* does not display worn armor correctly so display it.
|
||||
* spawn->SendArmorAppearance(client);
|
||||
*/
|
||||
}
|
||||
}
|
||||
safe_delete(bzsp);
|
||||
|
||||
safe_delete(bulk_zone_spawn_packet);
|
||||
}
|
||||
|
||||
//this is a hack to handle a broken spawn struct
|
||||
@@ -1558,7 +1562,7 @@ void EntityList::QueueClientsByTarget(Mob *sender, const EQApplicationPacket *ap
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::QueueClientsByXTarget(Mob *sender, const EQApplicationPacket *app, bool iSendToSender, EQEmu::versions::ClientVersionBit client_version_bits)
|
||||
void EntityList::QueueClientsByXTarget(Mob *sender, const EQApplicationPacket *app, bool iSendToSender, EQEmu::versions::ClientVersionBitmask client_version_bits)
|
||||
{
|
||||
auto it = client_list.begin();
|
||||
while (it != client_list.end()) {
|
||||
@@ -2652,56 +2656,6 @@ void EntityList::RemoveDebuffs(Mob *caster)
|
||||
}
|
||||
}
|
||||
|
||||
// Currently, a new packet is sent per entity.
|
||||
// @todo: Come back and use FLAG_COMBINED to pack
|
||||
// all updates into one packet.
|
||||
void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, float update_range, Entity *always_send, bool iSendEvenIfNotChanged)
|
||||
{
|
||||
update_range = (update_range * update_range);
|
||||
|
||||
EQApplicationPacket *outapp = 0;
|
||||
PlayerPositionUpdateServer_Struct *ppu = 0;
|
||||
Mob *mob = 0;
|
||||
|
||||
auto it = mob_list.begin();
|
||||
while (it != mob_list.end()) {
|
||||
|
||||
mob = it->second;
|
||||
|
||||
if (
|
||||
mob && !mob->IsCorpse()
|
||||
&& (it->second != client)
|
||||
&& (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate))
|
||||
&& (it->second->ShouldISpawnFor(client))
|
||||
) {
|
||||
if (
|
||||
update_range == 0
|
||||
|| (it->second == always_send)
|
||||
|| mob->IsClient()
|
||||
|| (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= update_range)
|
||||
) {
|
||||
if (mob && mob->IsClient() && mob->GetID() > 0) {
|
||||
client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
|
||||
|
||||
if (outapp == 0) {
|
||||
outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||
ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer;
|
||||
}
|
||||
|
||||
mob->MakeSpawnUpdate(ppu);
|
||||
|
||||
safe_delete(outapp);
|
||||
outapp = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
char *EntityList::MakeNameUnique(char *name)
|
||||
{
|
||||
bool used[300];
|
||||
@@ -3213,7 +3167,7 @@ void EntityList::AddHealAggro(Mob *target, Mob *caster, uint16 hate)
|
||||
}
|
||||
}
|
||||
|
||||
void EntityList::OpenDoorsNear(NPC *who)
|
||||
void EntityList::OpenDoorsNear(Mob *who)
|
||||
{
|
||||
|
||||
for (auto it = door_list.begin();it != door_list.end(); ++it) {
|
||||
@@ -3226,7 +3180,7 @@ void EntityList::OpenDoorsNear(NPC *who)
|
||||
float curdist = diff.x * diff.x + diff.y * diff.y;
|
||||
|
||||
if (diff.z * diff.z < 10 && curdist <= 100)
|
||||
cdoor->NPCOpen(who);
|
||||
cdoor->Open(who);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4017,8 +3971,9 @@ Mob *EntityList::GetTargetForMez(Mob *caster)
|
||||
|
||||
void EntityList::SendZoneAppearance(Client *c)
|
||||
{
|
||||
if (!c)
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = mob_list.begin();
|
||||
while (it != mob_list.end()) {
|
||||
@@ -4033,7 +3988,7 @@ void EntityList::SendZoneAppearance(Client *c)
|
||||
cur->SendAppearancePacket(AT_Anim, cur->GetAppearanceValue(cur->GetAppearance()), false, true, c);
|
||||
}
|
||||
if (cur->GetSize() != cur->GetBaseSize()) {
|
||||
cur->SendAppearancePacket(AT_Size, (uint32)cur->GetSize(), false, true, c);
|
||||
cur->SendAppearancePacket(AT_Size, (uint32) cur->GetSize(), false, true, c);
|
||||
}
|
||||
}
|
||||
++it;
|
||||
|
||||
+2
-3
@@ -353,7 +353,7 @@ public:
|
||||
void QueueClientsByTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, Mob* SkipThisMob = 0, bool ackreq = true,
|
||||
bool HoTT = true, uint32 ClientVersionBits = 0xFFFFFFFF, bool inspect_buffs = false);
|
||||
|
||||
void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, EQEmu::versions::ClientVersionBit client_version_bits = EQEmu::versions::ClientVersionBit::bit_AllClients);
|
||||
void QueueClientsByXTarget(Mob* sender, const EQApplicationPacket* app, bool iSendToSender = true, EQEmu::versions::ClientVersionBitmask client_version_bits = EQEmu::versions::ClientVersionBitmask::maskAllClients);
|
||||
void QueueToGroupsForNPCHealthAA(Mob* sender, const EQApplicationPacket* app);
|
||||
void QueueManaged(Mob* sender, const EQApplicationPacket* app, bool ignore_sender=false, bool ackreq = true);
|
||||
|
||||
@@ -370,9 +370,8 @@ public:
|
||||
|
||||
void AddHealAggro(Mob* target, Mob* caster, uint16 hate);
|
||||
Mob* FindDefenseNPC(uint32 npcid);
|
||||
void OpenDoorsNear(NPC* opener);
|
||||
void OpenDoorsNear(Mob* opener);
|
||||
void UpdateWho(bool iSendFullUpdate = false);
|
||||
void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float update_range = 0, Entity* always_send = 0, bool iSendEvenIfNotChanged = false);
|
||||
char* MakeNameUnique(char* name);
|
||||
static char* RemoveNumbers(char* name);
|
||||
void SignalMobsByNPCID(uint32 npc_type, int signal_id);
|
||||
|
||||
+1
-1
@@ -1133,7 +1133,7 @@ uint32 Client::GetCharMaxLevelFromQGlobal() {
|
||||
|
||||
uint32 Client::GetCharMaxLevelFromBucket() {
|
||||
uint32 char_id = this->CharacterID();
|
||||
std::string query = StringFormat("SELECT value FROM data_buckets WHERE key = '%i-CharMaxLevel'", char_id);
|
||||
std::string query = StringFormat("SELECT value FROM data_buckets WHERE `key` = '%i-CharMaxLevel'", char_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
Log(Logs::General, Logs::Error, "Data bucket for CharMaxLevel for char ID %i failed.", char_id);
|
||||
|
||||
+2
-26
@@ -157,10 +157,8 @@ void Mob::ProcessFlee()
|
||||
|
||||
void Mob::CalculateNewFearpoint() {
|
||||
if (RuleB(Pathing, Fear) && zone->pathing) {
|
||||
auto Node = zone->pathing->GetRandomLocation();
|
||||
auto Node = zone->pathing->GetRandomLocation(glm::vec3(GetX(), GetY(), GetZ()));
|
||||
if (Node.x != 0.0f || Node.y != 0.0f || Node.z != 0.0f) {
|
||||
|
||||
++Node.z;
|
||||
m_FearWalkTarget = Node;
|
||||
currently_fleeing = true;
|
||||
|
||||
@@ -169,29 +167,7 @@ void Mob::CalculateNewFearpoint() {
|
||||
|
||||
Log(Logs::Detail,
|
||||
Logs::Pathing,
|
||||
"No path found to selected node. Falling through to old fear point selection.");
|
||||
"No path found to selected node during CalculateNewFearpoint.");
|
||||
}
|
||||
|
||||
int loop = 0;
|
||||
float ranx, rany, ranz;
|
||||
|
||||
currently_fleeing = true;
|
||||
while (loop < 100) //Max 100 tries
|
||||
{
|
||||
int ran = 250 - (loop * 2);
|
||||
loop++;
|
||||
ranx = GetX() + zone->random.Int(0, ran - 1) - zone->random.Int(0, ran - 1);
|
||||
rany = GetY() + zone->random.Int(0, ran - 1) - zone->random.Int(0, ran - 1);
|
||||
ranz = FindGroundZ(ranx, rany);
|
||||
if (ranz == BEST_Z_INVALID)
|
||||
continue;
|
||||
float fdist = ranz - GetZ();
|
||||
if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(), GetY(), GetZ(), ranx, rany, ranz)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (currently_fleeing)
|
||||
m_FearWalkTarget = glm::vec3(ranx, rany, ranz);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -284,7 +284,7 @@ void Client::GoFish()
|
||||
if (tmp != nullptr) {
|
||||
auto positionNPC = GetPosition();
|
||||
positionNPC.x = positionNPC.x + 3;
|
||||
auto npc = new NPC(tmp, nullptr, positionNPC, FlyMode3);
|
||||
auto npc = new NPC(tmp, nullptr, positionNPC, GravityBehavior::Water);
|
||||
npc->AddLootTable();
|
||||
if (npc->DropsGlobalLoot())
|
||||
npc->CheckGlobalLootTables();
|
||||
|
||||
+1
-1
@@ -691,7 +691,7 @@ void GuildBankManager::SendGuildBank(Client *c)
|
||||
auto &guild_bank = *Iterator;
|
||||
|
||||
// RoF+ uses a bulk list packet -- This is also how the Action 0 of older clients basically works
|
||||
if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater) {
|
||||
if (c->ClientVersionBit() & EQEmu::versions::maskRoFAndLater) {
|
||||
auto outapp = new EQApplicationPacket(OP_GuildBankItemList, sizeof(GuildBankItemListEntry_Struct) * 240);
|
||||
for (int i = 0; i < GUILD_BANK_DEPOSIT_AREA_SIZE; ++i) {
|
||||
const EQEmu::ItemData *Item = database.GetItem(guild_bank->Items.DepositArea[i].ItemID);
|
||||
|
||||
@@ -335,15 +335,6 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip)
|
||||
continue;
|
||||
}
|
||||
|
||||
auto hateEntryPosition = glm::vec3(cur->entity_on_hatelist->GetX(), cur->entity_on_hatelist->GetY(), cur->entity_on_hatelist->GetZ());
|
||||
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
|
||||
if (!zone->watermap->InLiquid(hateEntryPosition)) {
|
||||
skipped_count++;
|
||||
++iterator;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (cur->entity_on_hatelist->Sanctuary()) {
|
||||
if (hate == -1)
|
||||
{
|
||||
@@ -474,14 +465,6 @@ Mob *HateList::GetEntWithMostHateOnList(Mob *center, Mob *skip)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (center->IsNPC() && center->CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
|
||||
if(!zone->watermap->InLiquid(glm::vec3(cur->entity_on_hatelist->GetPosition()))) {
|
||||
skipped_count++;
|
||||
++iterator;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (cur->entity_on_hatelist != nullptr && ((cur->stored_hate_amount > hate) || cur->is_entity_frenzy))
|
||||
{
|
||||
top_hate = cur->entity_on_hatelist;
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ std::map<uint16, const NPCType *> Horse::horse_types;
|
||||
LinkedList<NPCType *> horses_auto_delete;
|
||||
|
||||
Horse::Horse(Client *_owner, uint16 spell_id, const glm::vec4& position)
|
||||
: NPC(GetHorseType(spell_id), nullptr, position, FlyMode3)
|
||||
: NPC(GetHorseType(spell_id), nullptr, position, GravityBehavior::Water)
|
||||
{
|
||||
//give the horse its proper name.
|
||||
strn0cpy(name, _owner->GetCleanName(), 55);
|
||||
@@ -90,7 +90,7 @@ const NPCType *Horse::BuildHorseType(uint16 spell_id) {
|
||||
strcpy(npc_type->name, "Unclaimed_Mount"); // this should never get used
|
||||
|
||||
strcpy(npc_type->special_abilities, "19,1^20,1^24,1");
|
||||
npc_type->cur_hp = 1;
|
||||
npc_type->current_hp = 1;
|
||||
npc_type->max_hp = 1;
|
||||
npc_type->race = atoi(row[0]);
|
||||
npc_type->gender = atoi(row[1]); // Drogmor's are female horses. Yuck.
|
||||
|
||||
+25
-27
@@ -113,7 +113,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
x++;
|
||||
}
|
||||
|
||||
DeleteItemInInventory(i, 0, ((i - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank]));
|
||||
DeleteItemInInventory(i, 0, ((i - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) {
|
||||
x++;
|
||||
}
|
||||
|
||||
DeleteItemInInventory(i, 0, (((i - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank]));
|
||||
DeleteItemInInventory(i, 0, (((i - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT) >= GetInv().GetLookup()->InventoryTypeSize.Bank));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -781,12 +781,12 @@ int32 Client::GetItemIDAt(int16 slot_id) {
|
||||
return INVALID_ID;
|
||||
}
|
||||
else if (slot_id <= EQEmu::invslot::BANK_END && slot_id >= EQEmu::invslot::BANK_BEGIN) {
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
return INVALID_ID;
|
||||
}
|
||||
else if (slot_id <= EQEmu::invbag::BANK_BAGS_END && slot_id >= EQEmu::invbag::BANK_BAGS_BEGIN) {
|
||||
auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT;
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
return INVALID_ID;
|
||||
}
|
||||
|
||||
@@ -811,12 +811,12 @@ int32 Client::GetAugmentIDAt(int16 slot_id, uint8 augslot) {
|
||||
return INVALID_ID;
|
||||
}
|
||||
else if (slot_id <= EQEmu::invslot::BANK_END && slot_id >= EQEmu::invslot::BANK_BEGIN) {
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
return INVALID_ID;
|
||||
}
|
||||
else if (slot_id <= EQEmu::invbag::BANK_BAGS_END && slot_id >= EQEmu::invbag::BANK_BAGS_BEGIN) {
|
||||
auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT;
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
return INVALID_ID;
|
||||
}
|
||||
|
||||
@@ -1474,11 +1474,11 @@ bool Client::IsValidSlot(uint32 slot) {
|
||||
return ((((uint64)1 << temp_slot) & GetInv().GetLookup()->PossessionsBitmask) != 0);
|
||||
}
|
||||
else if (slot <= EQEmu::invslot::BANK_END && slot >= EQEmu::invslot::BANK_BEGIN) {
|
||||
return ((slot - EQEmu::invslot::BANK_BEGIN) < GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank]);
|
||||
return ((slot - EQEmu::invslot::BANK_BEGIN) < GetInv().GetLookup()->InventoryTypeSize.Bank);
|
||||
}
|
||||
else if (slot <= EQEmu::invbag::BANK_BAGS_END && slot >= EQEmu::invbag::BANK_BAGS_BEGIN) {
|
||||
auto temp_slot = (slot - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT;
|
||||
return (temp_slot < GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank]);
|
||||
return (temp_slot < GetInv().GetLookup()->InventoryTypeSize.Bank);
|
||||
}
|
||||
else if (
|
||||
(slot == (uint32)INVALID_INDEX) ||
|
||||
@@ -2500,7 +2500,7 @@ void Client::DisenchantSummonedBags(bool client_update)
|
||||
}
|
||||
|
||||
for (auto slot_id = EQEmu::invslot::BANK_BEGIN; slot_id <= EQEmu::invslot::BANK_END; ++slot_id) {
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
continue;
|
||||
|
||||
auto inst = m_inv[slot_id];
|
||||
@@ -2627,7 +2627,7 @@ void Client::RemoveNoRent(bool client_update)
|
||||
}
|
||||
|
||||
for (auto slot_id = EQEmu::invslot::BANK_BEGIN; slot_id <= EQEmu::invslot::BANK_END; ++slot_id) {
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
continue;
|
||||
|
||||
auto inst = m_inv[slot_id];
|
||||
@@ -2639,7 +2639,7 @@ void Client::RemoveNoRent(bool client_update)
|
||||
|
||||
for (auto slot_id = EQEmu::invbag::BANK_BAGS_BEGIN; slot_id <= EQEmu::invbag::BANK_BAGS_END; ++slot_id) {
|
||||
auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT;
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
continue;
|
||||
|
||||
auto inst = m_inv[slot_id];
|
||||
@@ -2745,7 +2745,7 @@ void Client::RemoveDuplicateLore(bool client_update)
|
||||
}
|
||||
|
||||
for (auto slot_id = EQEmu::invslot::BANK_BEGIN; slot_id <= EQEmu::invslot::BANK_END; ++slot_id) {
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
continue;
|
||||
|
||||
auto inst = m_inv.PopItem(slot_id);
|
||||
@@ -2762,7 +2762,7 @@ void Client::RemoveDuplicateLore(bool client_update)
|
||||
|
||||
for (auto slot_id = EQEmu::invbag::BANK_BAGS_BEGIN; slot_id <= EQEmu::invbag::BANK_BAGS_END; ++slot_id) {
|
||||
auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT;
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
continue;
|
||||
|
||||
auto inst = m_inv.PopItem(slot_id);
|
||||
@@ -2858,26 +2858,24 @@ void Client::MoveSlotNotAllowed(bool client_update)
|
||||
}
|
||||
|
||||
// these functions operate with a material slot, which is from 0 to 8
|
||||
uint32 Client::GetEquipment(uint8 material_slot) const
|
||||
uint32 Client::GetEquippedItemFromTextureSlot(uint8 material_slot) const
|
||||
{
|
||||
int16 invslot;
|
||||
int16 inventory_slot;
|
||||
|
||||
const EQEmu::ItemInstance *item;
|
||||
|
||||
if(material_slot > EQEmu::textures::LastTexture)
|
||||
{
|
||||
if (material_slot > EQEmu::textures::LastTexture) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot);
|
||||
if (invslot == INVALID_INDEX)
|
||||
{
|
||||
inventory_slot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot);
|
||||
if (inventory_slot == INVALID_INDEX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = m_inv.GetItem(invslot);
|
||||
item = m_inv.GetItem(inventory_slot);
|
||||
|
||||
if(item && item->GetItem())
|
||||
{
|
||||
if (item && item->GetItem()) {
|
||||
return item->GetItem()->ID;
|
||||
}
|
||||
|
||||
@@ -2889,7 +2887,7 @@ int32 Client::GetEquipmentMaterial(uint8 material_slot)
|
||||
{
|
||||
const ItemData *item;
|
||||
|
||||
item = database.GetItem(GetEquipment(material_slot));
|
||||
item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
|
||||
if(item != 0)
|
||||
{
|
||||
return item->Material;
|
||||
@@ -2904,7 +2902,7 @@ uint32 Client::GetEquipmentColor(uint8 material_slot) const
|
||||
if (material_slot > EQEmu::textures::LastTexture)
|
||||
return 0;
|
||||
|
||||
const EQEmu::ItemData *item = database.GetItem(GetEquipment(material_slot));
|
||||
const EQEmu::ItemData *item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
|
||||
if(item != nullptr)
|
||||
return ((m_pp.item_tint.Slot[material_slot].UseTint) ? m_pp.item_tint.Slot[material_slot].Color : item->Color);
|
||||
|
||||
@@ -2927,12 +2925,12 @@ void Client::SendItemPacket(int16 slot_id, const EQEmu::ItemInstance* inst, Item
|
||||
return;
|
||||
}
|
||||
else if (slot_id <= EQEmu::invslot::BANK_END && slot_id >= EQEmu::invslot::BANK_BEGIN) {
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if ((slot_id - EQEmu::invslot::BANK_BEGIN) >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
return;
|
||||
}
|
||||
else if (slot_id <= EQEmu::invbag::BANK_BAGS_END && slot_id >= EQEmu::invbag::BANK_BAGS_BEGIN) {
|
||||
auto temp_slot = (slot_id - EQEmu::invbag::BANK_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT;
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize[EQEmu::invtype::typeBank])
|
||||
if (temp_slot >= GetInv().GetLookup()->InventoryTypeSize.Bank)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1486,6 +1486,16 @@ void Lua_Client::DisableAreaRegens()
|
||||
self->DisableAreaRegens();
|
||||
}
|
||||
|
||||
void Lua_Client::SetPrimaryWeaponOrnamentation(uint32 model_id) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetPrimaryWeaponOrnamentation(model_id);
|
||||
}
|
||||
|
||||
void Lua_Client::SetSecondaryWeaponOrnamentation(uint32 model_id) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetSecondaryWeaponOrnamentation(model_id);
|
||||
}
|
||||
|
||||
luabind::scope lua_register_client() {
|
||||
return luabind::class_<Lua_Client, Lua_Mob>("Client")
|
||||
.def(luabind::constructor<>())
|
||||
@@ -1548,6 +1558,8 @@ luabind::scope lua_register_client() {
|
||||
.def("GetBindHeading", (float(Lua_Client::*)(int))&Lua_Client::GetBindHeading)
|
||||
.def("GetBindZoneID", (uint32(Lua_Client::*)(void))&Lua_Client::GetBindZoneID)
|
||||
.def("GetBindZoneID", (uint32(Lua_Client::*)(int))&Lua_Client::GetBindZoneID)
|
||||
.def("SetPrimaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetPrimaryWeaponOrnamentation)
|
||||
.def("SetSecondaryWeaponOrnamentation", (void(Lua_Client::*)(uint32))&Lua_Client::SetSecondaryWeaponOrnamentation)
|
||||
.def("MovePC", (void(Lua_Client::*)(int,float,float,float,float))&Lua_Client::MovePC)
|
||||
.def("MovePCInstance", (void(Lua_Client::*)(int,int,float,float,float,float))&Lua_Client::MovePCInstance)
|
||||
.def("ChangeLastName", (void(Lua_Client::*)(const char *in))&Lua_Client::ChangeLastName)
|
||||
|
||||
@@ -309,6 +309,10 @@ public:
|
||||
void DisableAreaEndRegen();
|
||||
void EnableAreaRegens(int value);
|
||||
void DisableAreaRegens();
|
||||
|
||||
|
||||
void SetPrimaryWeaponOrnamentation(uint32 model_id);
|
||||
void SetSecondaryWeaponOrnamentation(uint32 model_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -231,7 +231,7 @@ void Lua_EntityList::ReplaceWithTarget(Lua_Mob target, Lua_Mob new_target) {
|
||||
self->ReplaceWithTarget(target, new_target);
|
||||
}
|
||||
|
||||
void Lua_EntityList::OpenDoorsNear(Lua_NPC opener) {
|
||||
void Lua_EntityList::OpenDoorsNear(Lua_Mob opener) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->OpenDoorsNear(opener);
|
||||
}
|
||||
@@ -479,7 +479,7 @@ luabind::scope lua_register_entity_list() {
|
||||
.def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::RemoveFromTargets)
|
||||
.def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob, bool))&Lua_EntityList::RemoveFromTargets)
|
||||
.def("ReplaceWithTarget", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob))&Lua_EntityList::ReplaceWithTarget)
|
||||
.def("OpenDoorsNear", (void(Lua_EntityList::*)(Lua_NPC))&Lua_EntityList::OpenDoorsNear)
|
||||
.def("OpenDoorsNear", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::OpenDoorsNear)
|
||||
.def("MakeNameUnique", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::MakeNameUnique)
|
||||
.def("RemoveNumbers", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::RemoveNumbers)
|
||||
.def("SignalMobsByNPCID", (void(Lua_EntityList::*)(uint32, int))&Lua_EntityList::SignalMobsByNPCID)
|
||||
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
void RemoveFromTargets(Lua_Mob mob);
|
||||
void RemoveFromTargets(Lua_Mob mob, bool RemoveFromXTargets);
|
||||
void ReplaceWithTarget(Lua_Mob target, Lua_Mob new_target);
|
||||
void OpenDoorsNear(Lua_NPC opener);
|
||||
void OpenDoorsNear(Lua_Mob opener);
|
||||
std::string MakeNameUnique(const char *name);
|
||||
std::string RemoveNumbers(const char *name);
|
||||
void SignalMobsByNPCID(uint32 npc_id, int signal);
|
||||
|
||||
+15
-3
@@ -814,6 +814,16 @@ std::string lua_say_link(const char *phrase) {
|
||||
return quest_manager.saylink(text, false, text);
|
||||
}
|
||||
|
||||
void lua_set_rule(std::string rule_name, std::string rule_value) {
|
||||
RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str());
|
||||
}
|
||||
|
||||
std::string lua_get_rule(std::string rule_name) {
|
||||
std::string rule_value;
|
||||
RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value);
|
||||
return rule_value;
|
||||
}
|
||||
|
||||
std::string lua_get_data(std::string bucket_key) {
|
||||
return DataBucket::GetData(bucket_key);
|
||||
}
|
||||
@@ -903,7 +913,7 @@ void lua_flag_instance_by_raid_leader(uint32 zone, uint32 version) {
|
||||
}
|
||||
|
||||
void lua_fly_mode(int flymode) {
|
||||
quest_manager.FlyMode(flymode);
|
||||
quest_manager.FlyMode(static_cast<GravityBehavior>(flymode));
|
||||
}
|
||||
|
||||
int lua_faction_value() {
|
||||
@@ -1413,7 +1423,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
|
||||
luabind::adl::index_proxy<luabind::adl::object> cur = table["name"];
|
||||
LuaCreateNPCParseString(name, 64, "_");
|
||||
LuaCreateNPCParseString(lastname, 64, "");
|
||||
LuaCreateNPCParse(cur_hp, int32, 30);
|
||||
LuaCreateNPCParse(current_hp, int32, 30);
|
||||
LuaCreateNPCParse(max_hp, int32, 30);
|
||||
LuaCreateNPCParse(size, float, 6.0f);
|
||||
LuaCreateNPCParse(runspeed, float, 1.25f);
|
||||
@@ -1511,7 +1521,7 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float
|
||||
LuaCreateNPCParse(no_target_hotkey, bool, false);
|
||||
LuaCreateNPCParse(raid_target, bool, false);
|
||||
|
||||
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), FlyMode3);
|
||||
NPC* npc = new NPC(npc_type, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Water);
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
entity_list.AddNPC(npc);
|
||||
}
|
||||
@@ -1687,6 +1697,8 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link),
|
||||
luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link),
|
||||
luabind::def("say_link", (std::string(*)(const char*))&lua_say_link),
|
||||
luabind::def("set_rule", (void(*)(std::string, std::string))&lua_set_rule),
|
||||
luabind::def("get_rule", (std::string(*)(std::string))&lua_get_rule),
|
||||
luabind::def("get_data", (std::string(*)(std::string))&lua_get_data),
|
||||
luabind::def("get_data_expires", (std::string(*)(std::string))&lua_get_data_expires),
|
||||
luabind::def("set_data", (void(*)(std::string, std::string))&lua_set_data),
|
||||
|
||||
+32
-21
@@ -770,28 +770,28 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id) {
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot));
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot));
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time);
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time);
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost);
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost);
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot));
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot));
|
||||
}
|
||||
|
||||
bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer,
|
||||
int timer_duration) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
static_cast<uint32>(timer), static_cast<uint32>(timer_duration));
|
||||
}
|
||||
|
||||
@@ -800,7 +800,7 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in
|
||||
Lua_Safe_Call_Bool();
|
||||
int16 res = resist_adjust;
|
||||
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
return self->CastSpell(spell_id, target_id, static_cast<EQEmu::spells::CastingSlot>(slot), cast_time, mana_cost, nullptr, static_cast<uint32>(item_slot),
|
||||
static_cast<uint32>(timer), static_cast<uint32>(timer_duration), &res);
|
||||
}
|
||||
|
||||
@@ -811,27 +811,27 @@ bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target) {
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot));
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot));
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used);
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used, inventory_slot);
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust);
|
||||
}
|
||||
|
||||
bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust, bool proc) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust, proc);
|
||||
return self->SpellFinished(spell_id, target, static_cast<EQEmu::spells::CastingSlot>(slot), mana_used, inventory_slot, resist_adjust, proc);
|
||||
}
|
||||
|
||||
void Lua_Mob::SendBeginCast(int spell_id, int cast_time) {
|
||||
@@ -1124,15 +1124,24 @@ double Lua_Mob::CalculateHeadingToTarget(double in_x, double in_y) {
|
||||
return self->CalculateHeadingToTarget(static_cast<float>(in_x), static_cast<float>(in_y));
|
||||
}
|
||||
|
||||
bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CalculateNewPosition(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed));
|
||||
void Lua_Mob::RunTo(double x, double y, double z) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->RunTo(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
|
||||
}
|
||||
|
||||
bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed, bool check_z) {
|
||||
Lua_Safe_Call_Bool();
|
||||
return self->CalculateNewPosition(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed),
|
||||
check_z);
|
||||
void Lua_Mob::WalkTo(double x, double y, double z) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->WalkTo(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
|
||||
}
|
||||
|
||||
void Lua_Mob::NavigateTo(double x, double y, double z) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->NavigateTo(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
|
||||
}
|
||||
|
||||
void Lua_Mob::StopNavigation() {
|
||||
Lua_Safe_Call_Void();
|
||||
self->StopNavigation();
|
||||
}
|
||||
|
||||
float Lua_Mob::CalculateDistance(double x, double y, double z) {
|
||||
@@ -1430,7 +1439,7 @@ void Lua_Mob::SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uin
|
||||
|
||||
void Lua_Mob::SetFlyMode(int in) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SetFlyMode(in);
|
||||
self->SetFlyMode(static_cast<GravityBehavior>(in));
|
||||
}
|
||||
|
||||
void Lua_Mob::SetTexture(int in) {
|
||||
@@ -2361,8 +2370,10 @@ luabind::scope lua_register_mob() {
|
||||
.def("FaceTarget", (void(Lua_Mob::*)(Lua_Mob))&Lua_Mob::FaceTarget)
|
||||
.def("SetHeading", (void(Lua_Mob::*)(double))&Lua_Mob::SetHeading)
|
||||
.def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget)
|
||||
.def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition)
|
||||
.def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::CalculateNewPosition)
|
||||
.def("RunTo", (void(Lua_Mob::*)(double, double, double))&Lua_Mob::RunTo)
|
||||
.def("WalkTo", (void(Lua_Mob::*)(double, double, double))&Lua_Mob::WalkTo)
|
||||
.def("NavigateTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::NavigateTo)
|
||||
.def("StopNavigation", (void(Lua_Mob::*)(void))&Lua_Mob::StopNavigation)
|
||||
.def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance)
|
||||
.def("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo)
|
||||
.def("SendToFixZ", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendToFixZ)
|
||||
|
||||
+4
-2
@@ -240,8 +240,10 @@ public:
|
||||
void FaceTarget(Lua_Mob target);
|
||||
void SetHeading(double in);
|
||||
double CalculateHeadingToTarget(double in_x, double in_y);
|
||||
bool CalculateNewPosition(double x, double y, double z, double speed);
|
||||
bool CalculateNewPosition(double x, double y, double z, double speed, bool check_z);
|
||||
void RunTo(double x, double y, double z);
|
||||
void WalkTo(double x, double y, double z);
|
||||
void NavigateTo(double x, double y, double z);
|
||||
void StopNavigation();
|
||||
float CalculateDistance(double x, double y, double z);
|
||||
void SendTo(double x, double y, double z);
|
||||
void SendToFixZ(double x, double y, double z);
|
||||
|
||||
+3
-9
@@ -308,14 +308,9 @@ void Lua_NPC::NextGuardPosition() {
|
||||
self->NextGuardPosition();
|
||||
}
|
||||
|
||||
void Lua_NPC::SaveGuardSpot() {
|
||||
void Lua_NPC::SaveGuardSpot(float x, float y, float z, float heading) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SaveGuardSpot();
|
||||
}
|
||||
|
||||
void Lua_NPC::SaveGuardSpot(bool clear) {
|
||||
Lua_Safe_Call_Void();
|
||||
self->SaveGuardSpot(clear);
|
||||
self->SaveGuardSpot(glm::vec4(x, y, z, heading));
|
||||
}
|
||||
|
||||
bool Lua_NPC::IsGuarding() {
|
||||
@@ -597,8 +592,7 @@ luabind::scope lua_register_npc() {
|
||||
.def("PauseWandering", (void(Lua_NPC::*)(int))&Lua_NPC::PauseWandering)
|
||||
.def("MoveTo", (void(Lua_NPC::*)(float,float,float,float,bool))&Lua_NPC::MoveTo)
|
||||
.def("NextGuardPosition", (void(Lua_NPC::*)(void))&Lua_NPC::NextGuardPosition)
|
||||
.def("SaveGuardSpot", (void(Lua_NPC::*)(void))&Lua_NPC::SaveGuardSpot)
|
||||
.def("SaveGuardSpot", (void(Lua_NPC::*)(bool))&Lua_NPC::SaveGuardSpot)
|
||||
.def("SaveGuardSpot", (void(Lua_NPC::*)(float,float,float,float))&Lua_NPC::SaveGuardSpot)
|
||||
.def("IsGuarding", (bool(Lua_NPC::*)(void))&Lua_NPC::IsGuarding)
|
||||
.def("AI_SetRoambox", (void(Lua_NPC::*)(float,float,float,float,float))&Lua_NPC::AI_SetRoambox)
|
||||
.def("AI_SetRoambox", (void(Lua_NPC::*)(float,float,float,float,float,uint32,uint32))&Lua_NPC::AI_SetRoambox)
|
||||
|
||||
+1
-2
@@ -87,8 +87,7 @@ public:
|
||||
void PauseWandering(int pause_time);
|
||||
void MoveTo(float x, float y, float z, float h, bool save);
|
||||
void NextGuardPosition();
|
||||
void SaveGuardSpot();
|
||||
void SaveGuardSpot(bool clear);
|
||||
void SaveGuardSpot(float x, float y, float z, float heading);
|
||||
bool IsGuarding();
|
||||
void AI_SetRoambox(float dist, float max_x, float min_x, float max_y, float min_y);
|
||||
void AI_SetRoambox(float dist, float max_x, float min_x, float max_y, float min_y, uint32 delay, uint32 mindelay);
|
||||
|
||||
+35
-65
@@ -29,7 +29,7 @@ extern volatile bool is_zone_loaded;
|
||||
#endif
|
||||
|
||||
Merc::Merc(const NPCType* d, float x, float y, float z, float heading)
|
||||
: NPC(d, nullptr, glm::vec4(x, y, z, heading), 0, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000)
|
||||
: NPC(d, nullptr, glm::vec4(x, y, z, heading), GravityBehavior::Water, false), endupkeep_timer(1000), rest_timer(1), confidence_timer(6000), check_target_timer(2000)
|
||||
{
|
||||
base_hp = d->max_hp;
|
||||
base_mana = d->Mana;
|
||||
@@ -859,14 +859,14 @@ int32 Merc::CalcMaxHP() {
|
||||
|
||||
max_hp += max_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f);
|
||||
|
||||
if (cur_hp > max_hp)
|
||||
cur_hp = max_hp;
|
||||
if (current_hp > max_hp)
|
||||
current_hp = max_hp;
|
||||
|
||||
int hp_perc_cap = spellbonuses.HPPercCap[0];
|
||||
if(hp_perc_cap) {
|
||||
int curHP_cap = (max_hp * hp_perc_cap) / 100;
|
||||
if (cur_hp > curHP_cap || (spellbonuses.HPPercCap[1] && cur_hp > spellbonuses.HPPercCap[1]))
|
||||
cur_hp = curHP_cap;
|
||||
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1]))
|
||||
current_hp = curHP_cap;
|
||||
}
|
||||
|
||||
return max_hp;
|
||||
@@ -1271,7 +1271,7 @@ bool Merc::Process()
|
||||
//6 seconds, or whatever the rule is set to has passed, send this position to everyone to avoid ghosting
|
||||
if(!IsMoving() && !IsEngaged())
|
||||
{
|
||||
SendPosition();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
if(IsSitting()) {
|
||||
if(!rest_timer.Enabled()) {
|
||||
rest_timer.Start(RuleI(Character, RestRegenTimeToActivate) * 1000);
|
||||
@@ -1465,35 +1465,15 @@ void Merc::AI_Process() {
|
||||
|
||||
if(moved) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (!CheckLosFN(GetTarget())) {
|
||||
if (RuleB(Mercs, MercsUsePathing) && zone->pathing) {
|
||||
bool WaypointChanged, NodeReached;
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
GetTarget()->GetX(),
|
||||
GetTarget()->GetY(),
|
||||
GetTarget()->GetZ(),
|
||||
GetRunspeed(),
|
||||
WaypointChanged,
|
||||
NodeReached
|
||||
);
|
||||
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetRunspeed());
|
||||
}
|
||||
else {
|
||||
Mob* follow = entity_list.GetMob(GetFollowID());
|
||||
if (follow)
|
||||
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed());
|
||||
}
|
||||
auto Goal = GetTarget()->GetPosition();
|
||||
RunTo(Goal.x, Goal.y, Goal.z);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1527,7 +1507,7 @@ void Merc::AI_Process() {
|
||||
SetRunAnimSpeed(0);
|
||||
|
||||
if(moved) {
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1559,7 +1539,7 @@ void Merc::AI_Process() {
|
||||
float newZ = 0;
|
||||
FaceTarget(GetTarget());
|
||||
if (PlotPositionAroundTarget(this, newX, newY, newZ)) {
|
||||
CalculateNewPosition(newX, newY, newZ, GetRunspeed());
|
||||
RunTo(newX, newY, newZ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1571,7 +1551,7 @@ void Merc::AI_Process() {
|
||||
float newY = 0;
|
||||
float newZ = 0;
|
||||
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
|
||||
CalculateNewPosition(newX, newY, newZ, GetRunspeed());
|
||||
RunTo(newX, newY, newZ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1582,16 +1562,16 @@ void Merc::AI_Process() {
|
||||
float newY = 0;
|
||||
float newZ = 0;
|
||||
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
|
||||
CalculateNewPosition(newX, newY, newZ, GetRunspeed());
|
||||
RunTo(newX, newY, newZ);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsMoving())
|
||||
SendPositionUpdate();
|
||||
else
|
||||
SendPosition();
|
||||
//if (IsMoving())
|
||||
// SendPositionUpdate();
|
||||
//else
|
||||
// SendPosition();
|
||||
}
|
||||
|
||||
if(!IsMercCaster() && GetTarget() && !IsStunned() && !IsMezzed() && (GetAppearance() != eaDead))
|
||||
@@ -1709,14 +1689,14 @@ void Merc::AI_Process() {
|
||||
{
|
||||
if(!IsRooted()) {
|
||||
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
|
||||
CalculateNewPosition(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed());
|
||||
RunTo(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ());
|
||||
return;
|
||||
}
|
||||
|
||||
if(IsMoving())
|
||||
SendPositionUpdate();
|
||||
else
|
||||
SendPosition();
|
||||
//if(IsMoving())
|
||||
// SendPositionUpdate();
|
||||
//else
|
||||
// SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
}
|
||||
} // end not in combat range
|
||||
|
||||
@@ -1764,27 +1744,19 @@ void Merc::AI_Process() {
|
||||
|
||||
if (follow) {
|
||||
float dist = DistanceSquared(m_Position, follow->GetPosition());
|
||||
int speed = GetRunspeed();
|
||||
bool running = true;
|
||||
|
||||
if (dist < GetFollowDistance() + 1000)
|
||||
speed = GetWalkspeed();
|
||||
running = false;
|
||||
|
||||
SetRunAnimSpeed(0);
|
||||
|
||||
if (dist > GetFollowDistance()) {
|
||||
if (RuleB(Mercs, MercsUsePathing) && zone->pathing) {
|
||||
bool WaypointChanged, NodeReached;
|
||||
|
||||
glm::vec3 Goal = UpdatePath(follow->GetX(), follow->GetY(), follow->GetZ(),
|
||||
speed, WaypointChanged, NodeReached);
|
||||
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
|
||||
if (running) {
|
||||
RunTo(follow->GetX(), follow->GetY(), follow->GetZ());
|
||||
}
|
||||
else {
|
||||
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
|
||||
WalkTo(follow->GetX(), follow->GetY(), follow->GetZ());
|
||||
}
|
||||
|
||||
if (rest_timer.Enabled())
|
||||
@@ -1793,7 +1765,7 @@ void Merc::AI_Process() {
|
||||
else {
|
||||
if (moved) {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1819,8 +1791,7 @@ void Merc::AI_Start(int32 iMoveDelay) {
|
||||
}
|
||||
|
||||
SendTo(GetX(), GetY(), GetZ());
|
||||
SetChanged();
|
||||
SaveGuardSpot();
|
||||
SaveGuardSpot(GetPosition());
|
||||
}
|
||||
|
||||
void Merc::AI_Stop() {
|
||||
@@ -2019,10 +1990,10 @@ bool Merc::AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDon
|
||||
|| dist2 <= GetActSpellRange(spellid, spells[spellid].range)*GetActSpellRange(spellid, spells[spellid].range)) && (mana_cost <= GetMana() || GetMana() == GetMaxMana()))
|
||||
{
|
||||
SetRunAnimSpeed(0);
|
||||
SendPosition();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
SetMoving(false);
|
||||
|
||||
result = CastSpell(spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0);
|
||||
result = CastSpell(spellid, tar->GetID(), EQEmu::spells::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0);
|
||||
|
||||
if(IsCasting() && IsSitting())
|
||||
Stand();
|
||||
@@ -4074,7 +4045,7 @@ bool Merc::UseDiscipline(int32 spell_id, int32 target) {
|
||||
if(IsCasting())
|
||||
InterruptSpell();
|
||||
|
||||
CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline);
|
||||
CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline);
|
||||
|
||||
return(true);
|
||||
}
|
||||
@@ -4389,9 +4360,8 @@ void Merc::Sit() {
|
||||
if(IsMoving()) {
|
||||
moved = false;
|
||||
// SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||
SendPosition();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
SetMoving(false);
|
||||
tar_ndx = 0;
|
||||
}
|
||||
|
||||
SetAppearance(eaSitting);
|
||||
@@ -4979,7 +4949,7 @@ void Merc::ScaleStats(int scalepercent, bool setmax) {
|
||||
max_hp = (int)((float)base_hp * scalerate);
|
||||
base_hp = max_hp;
|
||||
if (setmax)
|
||||
cur_hp = max_hp;
|
||||
current_hp = max_hp;
|
||||
}
|
||||
|
||||
if (base_mana)
|
||||
@@ -5158,7 +5128,7 @@ bool Merc::Spawn(Client *owner) {
|
||||
|
||||
entity_list.AddMerc(this, true, true);
|
||||
|
||||
SendPosition();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
|
||||
Log(Logs::General, Logs::Mercenaries, "Spawn Mercenary %s.", GetName());
|
||||
|
||||
|
||||
+311
-621
File diff suppressed because it is too large
Load Diff
+130
-145
@@ -49,6 +49,7 @@ class Aura;
|
||||
struct AuraRecord;
|
||||
struct NewSpawn_Struct;
|
||||
struct PlayerPositionUpdateServer_Struct;
|
||||
class MobMovementManager;
|
||||
|
||||
const int COLLISION_BOX_SIZE = 8;
|
||||
|
||||
@@ -106,70 +107,67 @@ public:
|
||||
AuraMgr() : count(0) { }
|
||||
};
|
||||
|
||||
Mob(const char* in_name,
|
||||
const char* in_lastname,
|
||||
int32 in_cur_hp,
|
||||
int32 in_max_hp,
|
||||
uint8 in_gender,
|
||||
uint16 in_race,
|
||||
uint8 in_class,
|
||||
bodyType in_bodytype,
|
||||
uint8 in_deity,
|
||||
uint8 in_level,
|
||||
uint32 in_npctype_id,
|
||||
float in_size,
|
||||
float in_runspeed,
|
||||
const glm::vec4& position,
|
||||
uint8 in_light,
|
||||
uint8 in_texture,
|
||||
uint8 in_helmtexture,
|
||||
uint16 in_ac,
|
||||
uint16 in_atk,
|
||||
uint16 in_str,
|
||||
uint16 in_sta,
|
||||
uint16 in_dex,
|
||||
uint16 in_agi,
|
||||
uint16 in_int,
|
||||
uint16 in_wis,
|
||||
uint16 in_cha,
|
||||
uint8 in_haircolor,
|
||||
uint8 in_beardcolor,
|
||||
uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye?
|
||||
uint8 in_eyecolor2,
|
||||
uint8 in_hairstyle,
|
||||
uint8 in_luclinface,
|
||||
uint8 in_beard,
|
||||
uint32 in_drakkin_heritage,
|
||||
uint32 in_drakkin_tattoo,
|
||||
uint32 in_drakkin_details,
|
||||
EQEmu::TintProfile in_armor_tint,
|
||||
uint8 in_aa_title,
|
||||
uint8 in_see_invis, // see through invis
|
||||
uint8 in_see_invis_undead, // see through invis vs. undead
|
||||
uint8 in_see_hide,
|
||||
uint8 in_see_improved_hide,
|
||||
int32 in_hp_regen,
|
||||
int32 in_mana_regen,
|
||||
uint8 in_qglobal,
|
||||
uint8 in_maxlevel,
|
||||
uint32 in_scalerate,
|
||||
uint8 in_armtexture,
|
||||
uint8 in_bracertexture,
|
||||
uint8 in_handtexture,
|
||||
uint8 in_legtexture,
|
||||
uint8 in_feettexture
|
||||
Mob(
|
||||
const char *in_name,
|
||||
const char *in_lastname,
|
||||
int32 in_cur_hp,
|
||||
int32 in_max_hp,
|
||||
uint8 in_gender,
|
||||
uint16 in_race,
|
||||
uint8 in_class,
|
||||
bodyType in_bodytype,
|
||||
uint8 in_deity,
|
||||
uint8 in_level,
|
||||
uint32 in_npctype_id,
|
||||
float in_size,
|
||||
float in_runspeed,
|
||||
const glm::vec4 &position,
|
||||
uint8 in_light,
|
||||
uint8 in_texture,
|
||||
uint8 in_helmtexture,
|
||||
uint16 in_ac,
|
||||
uint16 in_atk,
|
||||
uint16 in_str,
|
||||
uint16 in_sta,
|
||||
uint16 in_dex,
|
||||
uint16 in_agi,
|
||||
uint16 in_int,
|
||||
uint16 in_wis,
|
||||
uint16 in_cha,
|
||||
uint8 in_haircolor,
|
||||
uint8 in_beardcolor,
|
||||
uint8 in_eyecolor1, // the eyecolors always seem to be the same, maybe left and right eye?
|
||||
uint8 in_eyecolor2,
|
||||
uint8 in_hairstyle,
|
||||
uint8 in_luclinface,
|
||||
uint8 in_beard,
|
||||
uint32 in_drakkin_heritage,
|
||||
uint32 in_drakkin_tattoo,
|
||||
uint32 in_drakkin_details,
|
||||
EQEmu::TintProfile in_armor_tint,
|
||||
uint8 in_aa_title,
|
||||
uint8 in_see_invis, // see through invis
|
||||
uint8 in_see_invis_undead, // see through invis vs. undead
|
||||
uint8 in_see_hide,
|
||||
uint8 in_see_improved_hide,
|
||||
int32 in_hp_regen,
|
||||
int32 in_mana_regen,
|
||||
uint8 in_qglobal,
|
||||
uint8 in_maxlevel,
|
||||
uint32 in_scalerate,
|
||||
uint8 in_armtexture,
|
||||
uint8 in_bracertexture,
|
||||
uint8 in_handtexture,
|
||||
uint8 in_legtexture,
|
||||
uint8 in_feettexture
|
||||
);
|
||||
virtual ~Mob();
|
||||
|
||||
inline virtual bool IsMob() const { return true; }
|
||||
inline virtual bool InZone() const { return true; }
|
||||
|
||||
bool is_distance_roamer;
|
||||
|
||||
void DisplayInfo(Mob *mob);
|
||||
|
||||
public:
|
||||
|
||||
//Somewhat sorted: needs documenting!
|
||||
|
||||
//Attack
|
||||
@@ -240,34 +238,47 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
//Appearance
|
||||
void SendLevelAppearance();
|
||||
void SendStunAppearance();
|
||||
void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5,
|
||||
Client *specific_target=nullptr);
|
||||
void SendTargetable(bool on, Client *specific_target = nullptr);
|
||||
virtual void SendArmorAppearance(Client *one_client = nullptr);
|
||||
virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr);
|
||||
virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0,
|
||||
uint32 unknown06 = 0, uint32 unknown18 = 0);
|
||||
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint);
|
||||
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0);
|
||||
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
|
||||
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0,
|
||||
float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, EQEmu::skills::SkillType skillInUse = EQEmu::skills::SkillArchery);
|
||||
void ChangeSize(float in_size, bool bNoRestriction = false);
|
||||
inline uint8 SeeInvisible() const { return see_invis; }
|
||||
inline bool SeeInvisibleUndead() const { return see_invis_undead; }
|
||||
/**
|
||||
************************************************
|
||||
* Appearance
|
||||
************************************************
|
||||
*/
|
||||
|
||||
EQEmu::InternalTextureProfile mob_texture_profile = {};
|
||||
|
||||
bool IsInvisible(Mob* other = 0) const;
|
||||
|
||||
EQEmu::skills::SkillType AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse = EQEmu::skills::Skill1HBlunt);
|
||||
|
||||
inline bool GetSeeInvisible(uint8 see_invis);
|
||||
inline bool SeeHide() const { return see_hide; }
|
||||
inline bool SeeImprovedHide() const { return see_improved_hide; }
|
||||
inline bool GetSeeInvisible(uint8 see_invis);
|
||||
bool IsInvisible(Mob* other = 0) const;
|
||||
inline bool SeeInvisibleUndead() const { return see_invis_undead; }
|
||||
inline uint8 SeeInvisible() const { return see_invis; }
|
||||
|
||||
int32 GetTextureProfileMaterial(uint8 material_slot) const;
|
||||
int32 GetTextureProfileColor(uint8 material_slot) const;
|
||||
int32 GetTextureProfileHeroForgeModel(uint8 material_slot) const;
|
||||
|
||||
virtual void SendArmorAppearance(Client *one_client = nullptr);
|
||||
virtual void SendTextureWC(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0, uint32 unknown06 = 0, uint32 unknown18 = 0);
|
||||
virtual void SendWearChange(uint8 material_slot, Client *one_client = nullptr);
|
||||
virtual void SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint);
|
||||
virtual void WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model = 0);
|
||||
|
||||
void ChangeSize(float in_size, bool bNoRestriction = false);
|
||||
void DoAnim(const int animnum, int type=0, bool ackreq = true, eqFilterType filter = FilterNone);
|
||||
void ProjectileAnimation(Mob* to, int item_id, bool IsArrow = false, float speed = 0, float angle = 0, float tilt = 0, float arc = 0, const char *IDFile = nullptr, EQEmu::skills::SkillType skillInUse = EQEmu::skills::SkillArchery);
|
||||
void SendAppearanceEffect(uint32 parm1, uint32 parm2, uint32 parm3, uint32 parm4, uint32 parm5, Client *specific_target=nullptr);
|
||||
void SendLevelAppearance();
|
||||
void SendStunAppearance();
|
||||
void SendTargetable(bool on, Client *specific_target = nullptr);
|
||||
void SetInvisible(uint8 state);
|
||||
EQEmu::skills::SkillType AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse = EQEmu::skills::Skill1HBlunt);
|
||||
void SetMobTextureProfile(uint8 material_slot, uint16 texture, uint32 color = 0, uint32 hero_forge_model = 0);
|
||||
|
||||
//Song
|
||||
bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1);
|
||||
bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::CastingSlot slot);
|
||||
bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::spells::CastingSlot slot);
|
||||
void BardPulse(uint16 spell_id, Mob *caster);
|
||||
|
||||
//Spell
|
||||
@@ -298,24 +309,24 @@ public:
|
||||
void SendSpellBarEnable(uint16 spellid);
|
||||
void ZeroCastingVars();
|
||||
virtual void SpellProcess();
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1,
|
||||
virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1,
|
||||
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
|
||||
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 *resist_adjust = nullptr,
|
||||
uint32 aa_id = 0);
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1,
|
||||
virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1,
|
||||
int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF,
|
||||
uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0,
|
||||
uint32 aa_id = 0);
|
||||
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::CastingSlot slot, uint16 mana_used,
|
||||
void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::spells::CastingSlot slot, uint16 mana_used,
|
||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0);
|
||||
bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, uint16 mana_used = 0,
|
||||
bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, uint16 mana_used = 0,
|
||||
uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||
void SendBeginCast(uint16 spell_id, uint32 casttime);
|
||||
virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false,
|
||||
bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1);
|
||||
virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1);
|
||||
virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center,
|
||||
CastAction_type &CastAction, EQEmu::CastingSlot slot, bool isproc = false);
|
||||
CastAction_type &CastAction, EQEmu::spells::CastingSlot slot, bool isproc = false);
|
||||
virtual bool CheckFizzle(uint16 spell_id);
|
||||
virtual bool CheckSpellLevelRestriction(uint16 spell_id);
|
||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||
@@ -413,7 +424,7 @@ public:
|
||||
bool CanFacestab() { return can_facestab; }
|
||||
void SetFacestab(bool val) { can_facestab = val; }
|
||||
virtual uint16 GetSkill(EQEmu::skills::SkillType skill_num) const { return 0; }
|
||||
virtual uint32 GetEquipment(uint8 material_slot) const { return(0); }
|
||||
virtual uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const { return(0); }
|
||||
virtual int32 GetEquipmentMaterial(uint8 material_slot) const;
|
||||
virtual int32 GetHerosForgeModel(uint8 material_slot) const;
|
||||
virtual uint32 GetEquipmentColor(uint8 material_slot) const;
|
||||
@@ -423,12 +434,12 @@ public:
|
||||
virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) = 0;
|
||||
virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill,
|
||||
bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None) = 0;
|
||||
inline virtual void SetHP(int32 hp) { if (hp >= max_hp) cur_hp = max_hp; else cur_hp = hp;}
|
||||
inline virtual void SetHP(int32 hp) { if (hp >= max_hp) current_hp = max_hp; else current_hp = hp;}
|
||||
bool ChangeHP(Mob* other, int32 amount, uint16 spell_id = 0, int8 buffslot = -1, bool iBuffTic = false);
|
||||
inline void SetOOCRegen(int32 newoocregen) {ooc_regen = newoocregen;}
|
||||
virtual void Heal();
|
||||
virtual void HealDamage(uint32 ammount, Mob* caster = nullptr, uint16 spell_id = SPELL_UNKNOWN);
|
||||
virtual void SetMaxHP() { cur_hp = max_hp; }
|
||||
virtual void SetMaxHP() { current_hp = max_hp; }
|
||||
virtual inline uint16 GetBaseRace() const { return base_race; }
|
||||
virtual inline uint8 GetBaseGender() const { return base_gender; }
|
||||
virtual inline uint16 GetDeity() const { return deity; }
|
||||
@@ -474,8 +485,8 @@ public:
|
||||
inline Mob* GetTarget() const { return target; }
|
||||
virtual void SetTarget(Mob* mob);
|
||||
inline bool HasTargetReflection() const { return (target && target != this && target->target == this); }
|
||||
virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)cur_hp/max_hp*100); }
|
||||
virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast<int>(cur_hp * 100 / max_hp); }
|
||||
virtual inline float GetHPRatio() const { return max_hp == 0 ? 0 : ((float)current_hp/max_hp*100); }
|
||||
virtual inline int GetIntHPRatio() const { return max_hp == 0 ? 0 : static_cast<int>(current_hp * 100 / max_hp); }
|
||||
inline int32 GetAC() const { return AC; }
|
||||
inline virtual int32 GetATK() const { return ATK + itembonuses.ATK + spellbonuses.ATK; }
|
||||
inline virtual int32 GetATKBonus() const { return itembonuses.ATK + spellbonuses.ATK; }
|
||||
@@ -524,7 +535,7 @@ public:
|
||||
inline virtual int32 GetMaxCR() const { return 255; }
|
||||
inline virtual int32 GetMaxFR() const { return 255; }
|
||||
inline virtual int32 GetDelayDeath() const { return 0; }
|
||||
inline int32 GetHP() const { return cur_hp; }
|
||||
inline int32 GetHP() const { return current_hp; }
|
||||
inline int32 GetMaxHP() const { return max_hp; }
|
||||
virtual int32 CalcMaxHP();
|
||||
inline int32 GetMaxMana() const { return max_mana; }
|
||||
@@ -541,21 +552,14 @@ public:
|
||||
uint32 GetNPCTypeID() const { return npctype_id; }
|
||||
void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; }
|
||||
inline const glm::vec4& GetPosition() const { return m_Position; }
|
||||
inline void SetPosition(const float x, const float y, const float z) { m_Position.x = x; m_Position.y = y; m_Position.z = z; }
|
||||
inline const float GetX() const { return m_Position.x; }
|
||||
inline const float GetY() const { return m_Position.y; }
|
||||
inline const float GetZ() const { return m_Position.z; }
|
||||
inline const float GetHeading() const { return m_Position.w; }
|
||||
inline const float GetSize() const { return size; }
|
||||
inline const float GetBaseSize() const { return base_size; }
|
||||
inline const float GetTarX() const { return m_TargetLocation.x; }
|
||||
inline const float GetTarY() const { return m_TargetLocation.y; }
|
||||
inline const float GetTarZ() const { return m_TargetLocation.z; }
|
||||
inline const float GetTarVX() const { return m_TargetV.x; }
|
||||
inline const float GetTarVY() const { return m_TargetV.y; }
|
||||
inline const float GetTarVZ() const { return m_TargetV.z; }
|
||||
inline const float GetTarVector() const { return tar_vector; }
|
||||
inline const uint8 GetTarNDX() const { return tar_ndx; }
|
||||
inline const int8 GetFlyMode() const { return static_cast<const int8>(flymode); }
|
||||
inline const GravityBehavior GetFlyMode() const { return flymode; }
|
||||
bool IsBoat() const;
|
||||
|
||||
//Group
|
||||
@@ -568,14 +572,12 @@ public:
|
||||
virtual inline int32 GetPrimaryFaction() const { return 0; }
|
||||
|
||||
//Movement
|
||||
void Warp(const glm::vec3& location);
|
||||
inline bool IsMoving() const { return moving; }
|
||||
virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); }
|
||||
virtual void GoToBind(uint8 bindnum = 0) { }
|
||||
virtual void Gate(uint8 bindnum = 0);
|
||||
int GetWalkspeed() const { return(_GetWalkSpeed()); }
|
||||
int GetRunspeed() const { return(_GetRunSpeed()); }
|
||||
void SetCurrentSpeed(int in);
|
||||
int GetBaseRunspeed() const { return base_runspeed; }
|
||||
int GetBaseWalkspeed() const { return base_walkspeed; }
|
||||
int GetBaseFearSpeed() const { return base_fearspeed; }
|
||||
@@ -584,26 +586,24 @@ public:
|
||||
void SetRunning(bool val) { m_is_running = val; }
|
||||
virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true);
|
||||
void SetDelta(const glm::vec4& delta);
|
||||
void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; }
|
||||
void SendPositionUpdateToClient(Client *client);
|
||||
void SendPositionUpdate(uint8 iSendToSelf = 0);
|
||||
void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu);
|
||||
void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu);
|
||||
void SendPosition();
|
||||
void SentPositionPacket(float dx, float dy, float dz, float dh, int anim, bool send_to_self = false);
|
||||
void StopMoving();
|
||||
void StopMoving(float new_heading);
|
||||
void SetSpawned() { spawned = true; };
|
||||
bool Spawned() { return spawned; };
|
||||
virtual bool ShouldISpawnFor(Client *c) { return true; }
|
||||
void SetFlyMode(uint8 flymode);
|
||||
inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y;
|
||||
m_Position.z = NewPosition.z; };
|
||||
void SetFlyMode(GravityBehavior flymode);
|
||||
void Teleport(const glm::vec3 &pos);
|
||||
void Teleport(const glm::vec4 &pos);
|
||||
void TryMoveAlong(float distance, float angle, bool send = true);
|
||||
void ProcessForcedMovement();
|
||||
inline void IncDeltaX(float in) { m_Delta.x += in; }
|
||||
inline void IncDeltaY(float in) { m_Delta.y += in; }
|
||||
inline void IncDeltaZ(float in) { m_Delta.z += in; }
|
||||
inline void SetForcedMovement(int in) { ForcedMovement = in; }
|
||||
void SetHeading(float iHeading) { m_Position.w = iHeading; }
|
||||
|
||||
//AI
|
||||
static uint32 GetLevelCon(uint8 mylevel, uint8 iOtherLevel);
|
||||
@@ -630,8 +630,6 @@ public:
|
||||
void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; }
|
||||
bool HateSummon();
|
||||
void FaceTarget(Mob* mob_to_face = 0);
|
||||
void SetHeading(float iHeading) { if(m_Position.w != iHeading) { pLastChange = Timer::GetCurrentTime();
|
||||
m_Position.w = iHeading; } }
|
||||
void WipeHateList();
|
||||
void AddFeignMemory(Client* attacker);
|
||||
void RemoveFromFeignMemory(Client* attacker);
|
||||
@@ -642,8 +640,6 @@ public:
|
||||
bool CheckLosFN(Mob* other);
|
||||
bool CheckLosFN(float posX, float posY, float posZ, float mobSize);
|
||||
static bool CheckLosFN(glm::vec3 posWatcher, float sizeWatcher, glm::vec3 posTarget, float sizeTarget);
|
||||
inline void SetChanged() { pLastChange = Timer::GetCurrentTime(); }
|
||||
inline const uint32 LastChange() const { return pLastChange; }
|
||||
inline void SetLastLosState(bool value) { last_los_check = value; }
|
||||
inline bool CheckLastLosState() const { return last_los_check; }
|
||||
|
||||
@@ -833,8 +829,10 @@ public:
|
||||
void SendAppearancePacket(uint32 type, uint32 value, bool WholeZone = true, bool iIgnoreSelf = false, Client *specific_target=nullptr);
|
||||
void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true);
|
||||
inline EmuAppearance GetAppearance() const { return _appearance; }
|
||||
inline const int GetAnimation() const { return animation; }
|
||||
inline void SetAnimation(int a) { animation = a; }
|
||||
inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; }
|
||||
inline void SetRunAnimSpeed(int8 in) { if (pRunAnimSpeed != in) { pRunAnimSpeed = in; pLastChange = Timer::GetCurrentTime(); } }
|
||||
inline void SetRunAnimSpeed(int8 in) { pRunAnimSpeed = in; }
|
||||
bool IsDestructibleObject() { return destructibleobject; }
|
||||
void SetDestructibleObject(bool in) { destructibleobject = in; }
|
||||
|
||||
@@ -1000,7 +998,13 @@ public:
|
||||
|
||||
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
|
||||
float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); }
|
||||
virtual bool CalculateNewPosition(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true);
|
||||
void WalkTo(float x, float y, float z);
|
||||
void RunTo(float x, float y, float z);
|
||||
void NavigateTo(float x, float y, float z);
|
||||
void RotateTo(float new_heading);
|
||||
void RotateToWalking(float new_heading);
|
||||
void RotateToRunning(float new_heading);
|
||||
void StopNavigation();
|
||||
float CalculateDistance(float x, float y, float z);
|
||||
float GetGroundZ(float new_x, float new_y, float z_offset=0.0);
|
||||
void SendTo(float new_x, float new_y, float new_z);
|
||||
@@ -1008,8 +1012,9 @@ public:
|
||||
float GetZOffset() const;
|
||||
float GetDefaultRaceSize() const;
|
||||
void FixZ(int32 z_find_offset = 5, bool fix_client_z = false);
|
||||
float GetFixedZ(glm::vec3 destination, int32 z_find_offset = 5);
|
||||
|
||||
float GetFixedZ(const glm::vec3 &destination, int32 z_find_offset = 5);
|
||||
virtual int GetStuckBehavior() const { return 0; }
|
||||
|
||||
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
|
||||
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
|
||||
inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; }
|
||||
@@ -1088,6 +1093,7 @@ public:
|
||||
void SetCurrentWP(uint16 waypoint) { cur_wp = waypoint; }
|
||||
virtual FACTION_VALUE GetReverseFactionCon(Mob* iOther) { return FACTION_INDIFFERENT; }
|
||||
|
||||
virtual const bool IsUnderwaterOnly() const { return false; }
|
||||
inline bool IsTrackable() const { return(trackable); }
|
||||
Timer* GetAIThinkTimer() { return AI_think_timer.get(); }
|
||||
Timer* GetAIMovementTimer() { return AI_movement_timer.get(); }
|
||||
@@ -1189,7 +1195,6 @@ protected:
|
||||
int _GetWalkSpeed() const;
|
||||
int _GetRunSpeed() const;
|
||||
int _GetFearSpeed() const;
|
||||
virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z = true, bool calculate_heading = true);
|
||||
|
||||
virtual bool AI_EngagedCastCheck() { return(false); }
|
||||
virtual bool AI_PursueCastCheck() { return(false); }
|
||||
@@ -1240,7 +1245,7 @@ protected:
|
||||
int targeted;
|
||||
bool findable;
|
||||
bool trackable;
|
||||
int32 cur_hp;
|
||||
int32 current_hp;
|
||||
int32 max_hp;
|
||||
int32 base_hp;
|
||||
int32 current_mana;
|
||||
@@ -1283,10 +1288,8 @@ protected:
|
||||
uint8 level;
|
||||
uint8 orig_level;
|
||||
uint32 npctype_id;
|
||||
glm::vec4 m_Position;
|
||||
/* Used to determine when an NPC has traversed so many units - to send a zone wide pos update */
|
||||
glm::vec4 last_major_update_position;
|
||||
|
||||
glm::vec4 m_Position;
|
||||
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
|
||||
float base_size;
|
||||
float size;
|
||||
@@ -1299,7 +1302,6 @@ protected:
|
||||
int current_speed;
|
||||
eSpecialAttacks m_specialattacks;
|
||||
|
||||
uint32 pLastChange;
|
||||
bool held;
|
||||
bool gheld;
|
||||
bool nocast;
|
||||
@@ -1329,8 +1331,6 @@ protected:
|
||||
void CalculateNewFearpoint();
|
||||
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
|
||||
float FindDestGroundZ(glm::vec3 dest, float z_offset=0.0);
|
||||
glm::vec3 UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
|
||||
glm::vec3 HandleStuckPath(const glm::vec3 &To, const glm::vec3 &From);
|
||||
|
||||
virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0);
|
||||
int16 GetSympatheticSpellProcRate(uint16 spell_id);
|
||||
@@ -1375,7 +1375,7 @@ protected:
|
||||
int attacked_count;
|
||||
bool delaytimer;
|
||||
uint16 casting_spell_targetid;
|
||||
EQEmu::CastingSlot casting_spell_slot;
|
||||
EQEmu::spells::CastingSlot casting_spell_slot;
|
||||
uint16 casting_spell_mana;
|
||||
uint32 casting_spell_inventory_slot;
|
||||
uint32 casting_spell_timer;
|
||||
@@ -1385,7 +1385,7 @@ protected:
|
||||
uint32 casting_spell_aa_id;
|
||||
bool casting_spell_checks;
|
||||
uint16 bardsong;
|
||||
EQEmu::CastingSlot bardsong_slot;
|
||||
EQEmu::spells::CastingSlot bardsong_slot;
|
||||
uint32 bardsong_target_id;
|
||||
|
||||
bool ActiveProjectileATK;
|
||||
@@ -1467,7 +1467,6 @@ protected:
|
||||
std::unique_ptr<Timer> AI_think_timer;
|
||||
std::unique_ptr<Timer> AI_movement_timer;
|
||||
std::unique_ptr<Timer> AI_target_check_timer;
|
||||
bool movetimercompleted;
|
||||
int8 ForcedMovement; // push
|
||||
bool permarooted;
|
||||
std::unique_ptr<Timer> AI_scan_area_timer;
|
||||
@@ -1491,8 +1490,6 @@ protected:
|
||||
|
||||
bool flee_mode;
|
||||
Timer flee_timer;
|
||||
Timer fix_z_timer;
|
||||
Timer fix_z_timer_engaged;
|
||||
Timer attack_anim_timer;
|
||||
Timer position_update_melee_push_timer;
|
||||
|
||||
@@ -1518,15 +1515,8 @@ protected:
|
||||
glm::vec3 m_FearWalkTarget;
|
||||
bool currently_fleeing;
|
||||
|
||||
// Pathing
|
||||
//
|
||||
glm::vec3 PathingDestination;
|
||||
IPathfinder::IPath Route;
|
||||
std::unique_ptr<Timer> PathRecalcTimer;
|
||||
bool pause_timer_complete;
|
||||
bool DistractedFromGrid;
|
||||
glm::vec3 PathingLastPosition;
|
||||
int PathingLoopCount;
|
||||
|
||||
uint32 pDontHealMeBefore;
|
||||
uint32 pDontBuffMeBefore;
|
||||
uint32 pDontDotMeBefore;
|
||||
@@ -1545,18 +1535,11 @@ protected:
|
||||
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;
|
||||
uint8 tar_ndx;
|
||||
float tar_vector;
|
||||
glm::vec3 m_TargetV;
|
||||
float test_vector;
|
||||
|
||||
glm::vec3 m_TargetRing;
|
||||
|
||||
// we might want to do this differently, we gotta do max NPC buffs ... which is 97
|
||||
uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting
|
||||
int flymode;
|
||||
uint32 m_spellHitsLeft[EQEmu::spells::TOTAL_BUFFS]; // Used to track which spells will have their numhits incremented when spell finishes casting
|
||||
GravityBehavior flymode;
|
||||
bool m_targetable;
|
||||
int QGVarDuration(const char *fmt);
|
||||
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
|
||||
@@ -1574,6 +1557,8 @@ protected:
|
||||
AuraMgr aura_mgr;
|
||||
AuraMgr trap_mgr;
|
||||
|
||||
MobMovementManager *mMovementManager;
|
||||
|
||||
private:
|
||||
void _StopSong(); //this is not what you think it is
|
||||
Mob* target;
|
||||
|
||||
+129
-346
@@ -375,12 +375,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
|
||||
#endif
|
||||
casting_spell_AIindex = i;
|
||||
|
||||
//stop moving if were casting a spell and were not a bard...
|
||||
if(!IsBardSong(AIspells[i].spellid)) {
|
||||
SetCurrentSpeed(0);
|
||||
}
|
||||
|
||||
return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust));
|
||||
return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::spells::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust));
|
||||
}
|
||||
|
||||
bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) {
|
||||
@@ -520,7 +515,6 @@ void Mob::AI_Start(uint32 iMoveDelay) {
|
||||
|
||||
m_Delta = glm::vec4();
|
||||
pRunAnimSpeed = 0;
|
||||
pLastChange = Timer::GetCurrentTime();
|
||||
}
|
||||
|
||||
void Client::AI_Start(uint32 iMoveDelay) {
|
||||
@@ -556,8 +550,7 @@ void NPC::AI_Start(uint32 iMoveDelay) {
|
||||
}
|
||||
|
||||
SendTo(GetX(), GetY(), GetZ());
|
||||
SetChanged();
|
||||
SaveGuardSpot();
|
||||
SaveGuardSpot(GetPosition());
|
||||
}
|
||||
|
||||
void Mob::AI_Stop() {
|
||||
@@ -695,11 +688,11 @@ void Client::AI_SpellCast()
|
||||
}
|
||||
|
||||
uint32 spell_to_cast = 0xFFFFFFFF;
|
||||
EQEmu::CastingSlot slot_to_use = EQEmu::CastingSlot::Item;
|
||||
EQEmu::spells::CastingSlot slot_to_use = EQEmu::spells::CastingSlot::Item;
|
||||
if(valid_spells.size() == 1)
|
||||
{
|
||||
spell_to_cast = valid_spells[0];
|
||||
slot_to_use = static_cast<EQEmu::CastingSlot>(slots[0]);
|
||||
slot_to_use = static_cast<EQEmu::spells::CastingSlot>(slots[0]);
|
||||
}
|
||||
else if(valid_spells.empty())
|
||||
{
|
||||
@@ -709,7 +702,7 @@ void Client::AI_SpellCast()
|
||||
{
|
||||
uint32 idx = zone->random.Int(0, (valid_spells.size()-1));
|
||||
spell_to_cast = valid_spells[idx];
|
||||
slot_to_use = static_cast<EQEmu::CastingSlot>(slots[idx]);
|
||||
slot_to_use = static_cast<EQEmu::spells::CastingSlot>(slots[idx]);
|
||||
}
|
||||
|
||||
if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast))
|
||||
@@ -722,7 +715,7 @@ void Client::AI_SpellCast()
|
||||
{
|
||||
if(!IsBardSong(spell_to_cast))
|
||||
{
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
CastSpell(spell_to_cast, tar->GetID(), slot_to_use);
|
||||
return;
|
||||
@@ -736,7 +729,7 @@ void Client::AI_SpellCast()
|
||||
{
|
||||
if(!IsBardSong(spell_to_cast))
|
||||
{
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
CastSpell(spell_to_cast, tar->GetID(), slot_to_use);
|
||||
return;
|
||||
@@ -788,50 +781,23 @@ void Client::AI_Process()
|
||||
if (RuleB(Combat, EnableFearPathing)) {
|
||||
if (currently_fleeing) {
|
||||
|
||||
if (fix_z_timer.Check())
|
||||
this->FixZ(5, true);
|
||||
|
||||
if (IsRooted()) {
|
||||
//make sure everybody knows were not moving, for appearance sake
|
||||
if (IsMoving()) {
|
||||
if (GetTarget())
|
||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||
SetCurrentSpeed(0);
|
||||
FaceTarget();
|
||||
StopNavigation();
|
||||
}
|
||||
//continue on to attack code, ensuring that we execute the engaged code
|
||||
engaged = true;
|
||||
}
|
||||
else {
|
||||
if (AI_movement_timer->Check()) {
|
||||
int speed = GetFearSpeed();
|
||||
animation = speed;
|
||||
speed *= 2;
|
||||
SetCurrentSpeed(speed);
|
||||
// Check if we have reached the last fear point
|
||||
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
|
||||
(std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) {
|
||||
// Calculate a new point to run to
|
||||
if(IsPositionEqualWithinCertainZ(glm::vec3(GetX(), GetY(), GetZ()), m_FearWalkTarget, 5.0f)) {
|
||||
CalculateNewFearpoint();
|
||||
}
|
||||
|
||||
if (!RuleB(Pathing, Fear) || !zone->pathing)
|
||||
CalculateNewPosition(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, speed, true);
|
||||
else {
|
||||
bool waypoint_changed, node_reached;
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
m_FearWalkTarget.x,
|
||||
m_FearWalkTarget.y,
|
||||
m_FearWalkTarget.z,
|
||||
speed,
|
||||
waypoint_changed,
|
||||
node_reached
|
||||
);
|
||||
|
||||
if (waypoint_changed)
|
||||
tar_ndx = 20;
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
|
||||
RunTo(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -866,6 +832,10 @@ void Client::AI_Process()
|
||||
bool is_combat_range = CombatRange(GetTarget());
|
||||
|
||||
if (is_combat_range) {
|
||||
if (IsMoving()) {
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
if (charm_class_attacks_timer.Check()) {
|
||||
DoClassAttacks(GetTarget());
|
||||
}
|
||||
@@ -873,10 +843,8 @@ void Client::AI_Process()
|
||||
if (AI_movement_timer->Check()) {
|
||||
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) !=
|
||||
m_Position.w) {
|
||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||
SendPosition();
|
||||
FaceTarget();
|
||||
}
|
||||
SetCurrentSpeed(0);
|
||||
}
|
||||
if (GetTarget() && !IsStunned() && !IsMezzed() && !GetFeigned()) {
|
||||
if (attack_timer.Check()) {
|
||||
@@ -898,29 +866,12 @@ void Client::AI_Process()
|
||||
{
|
||||
if(AI_movement_timer->Check())
|
||||
{
|
||||
int newspeed = GetRunspeed();
|
||||
animation = newspeed;
|
||||
newspeed *= 2;
|
||||
SetCurrentSpeed(newspeed);
|
||||
if(!RuleB(Pathing, Aggro) || !zone->pathing)
|
||||
CalculateNewPosition(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), newspeed);
|
||||
else
|
||||
{
|
||||
bool WaypointChanged, NodeReached;
|
||||
glm::vec3 Goal = UpdatePath(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(),
|
||||
GetRunspeed(), WaypointChanged, NodeReached);
|
||||
|
||||
if(WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, newspeed);
|
||||
}
|
||||
RunTo(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ());
|
||||
}
|
||||
}
|
||||
else if(IsMoving())
|
||||
{
|
||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||
SetCurrentSpeed(0);
|
||||
FaceTarget();
|
||||
}
|
||||
}
|
||||
AI_SpellCast();
|
||||
@@ -953,22 +904,18 @@ void Client::AI_Process()
|
||||
|
||||
float dist = DistanceSquared(m_Position, owner->GetPosition());
|
||||
if (dist >= 202500) { // >= 450 distance
|
||||
Teleport(static_cast<glm::vec3>(owner->GetPosition()));
|
||||
SendPositionUpdate(); // this shouldn't happen a lot (and hard to make it) so lets not rate limit
|
||||
Teleport(owner->GetPosition());
|
||||
} else if (dist >= 400) { // >=20
|
||||
if (AI_movement_timer->Check()) {
|
||||
int nspeed = (dist >= 1225 ? GetRunspeed() : GetWalkspeed()); // >= 35
|
||||
animation = nspeed;
|
||||
nspeed *= 2;
|
||||
SetCurrentSpeed(nspeed);
|
||||
|
||||
CalculateNewPosition(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed);
|
||||
if (dist >= 1225) {
|
||||
RunTo(owner->GetX(), owner->GetY(), owner->GetZ());
|
||||
}
|
||||
else {
|
||||
WalkTo(owner->GetX(), owner->GetY(), owner->GetZ());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (moved) {
|
||||
SetCurrentSpeed(0);
|
||||
moved = false;
|
||||
}
|
||||
StopNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -982,49 +929,49 @@ void Mob::ProcessForcedMovement()
|
||||
if (AI_movement_timer->Check()) {
|
||||
bool bPassed = true;
|
||||
glm::vec3 normal;
|
||||
|
||||
|
||||
// no zone map = fucked
|
||||
if (zone->HasMap()) {
|
||||
// in front
|
||||
m_CollisionBox[0].x = m_Position.x + 3.0f * g_Math.FastSin(0.0f);
|
||||
m_CollisionBox[0].y = m_Position.y + 3.0f * g_Math.FastCos(0.0f);
|
||||
m_CollisionBox[0].z = m_Position.z;
|
||||
|
||||
|
||||
// 45 right front
|
||||
m_CollisionBox[1].x = m_Position.x + 3.0f * g_Math.FastSin(64.0f);
|
||||
m_CollisionBox[1].y = m_Position.y + 3.0f * g_Math.FastCos(64.0f);
|
||||
m_CollisionBox[1].z = m_Position.z;
|
||||
|
||||
|
||||
// to right
|
||||
m_CollisionBox[2].x = m_Position.x + 3.0f * g_Math.FastSin(128.0f);
|
||||
m_CollisionBox[2].y = m_Position.y + 3.0f * g_Math.FastCos(128.0f);
|
||||
m_CollisionBox[2].z = m_Position.z;
|
||||
|
||||
|
||||
// 45 right back
|
||||
m_CollisionBox[3].x = m_Position.x + 3.0f * g_Math.FastSin(192.0f);
|
||||
m_CollisionBox[3].y = m_Position.y + 3.0f * g_Math.FastCos(192.0f);
|
||||
m_CollisionBox[3].z = m_Position.z;
|
||||
|
||||
|
||||
// behind
|
||||
m_CollisionBox[4].x = m_Position.x + 3.0f * g_Math.FastSin(256.0f);
|
||||
m_CollisionBox[4].y = m_Position.y + 3.0f * g_Math.FastCos(256.0f);
|
||||
m_CollisionBox[4].z = m_Position.z;
|
||||
|
||||
|
||||
// 45 left back
|
||||
m_CollisionBox[5].x = m_Position.x + 3.0f * g_Math.FastSin(320.0f);
|
||||
m_CollisionBox[5].y = m_Position.y + 3.0f * g_Math.FastCos(320.0f);
|
||||
m_CollisionBox[5].z = m_Position.z;
|
||||
|
||||
|
||||
// to left
|
||||
m_CollisionBox[6].x = m_Position.x + 3.0f * g_Math.FastSin(384.0f);
|
||||
m_CollisionBox[6].y = m_Position.y + 3.0f * g_Math.FastCos(384.0f);
|
||||
m_CollisionBox[6].z = m_Position.z;
|
||||
|
||||
|
||||
// 45 left front
|
||||
m_CollisionBox[7].x = m_Position.x + 3.0f * g_Math.FastSin(448.0f);
|
||||
m_CollisionBox[7].y = m_Position.y + 3.0f * g_Math.FastCos(448.0f);
|
||||
m_CollisionBox[7].z = m_Position.z;
|
||||
|
||||
|
||||
// collision happened, need to move along the wall
|
||||
float distance = 0.0f, shortest = std::numeric_limits<float>::infinity();
|
||||
glm::vec3 tmp_nrm;
|
||||
@@ -1038,13 +985,12 @@ void Mob::ProcessForcedMovement()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (bPassed) {
|
||||
ForcedMovement = 0;
|
||||
Teleport(m_Position + m_Delta);
|
||||
m_Delta = glm::vec4();
|
||||
SendPositionUpdate();
|
||||
pLastChange = Timer::GetCurrentTime();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0, true);
|
||||
FixZ(); // so we teleport to the ground locally, we want the client to interpolate falling etc
|
||||
} else if (--ForcedMovement) {
|
||||
if (normal.z < -0.15f) // prevent too much wall climbing. ex. OMM's room in anguish
|
||||
@@ -1119,9 +1065,8 @@ void Mob::AI_Process() {
|
||||
!IsPetRegroup()) {
|
||||
//make sure everybody knows were not moving, for appearance sake
|
||||
if (IsMoving()) {
|
||||
if (target)
|
||||
SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY()));
|
||||
SetCurrentSpeed(0);
|
||||
FaceTarget();
|
||||
StopNavigation();
|
||||
moved = false;
|
||||
}
|
||||
//continue on to attack code, ensuring that we execute the engaged code
|
||||
@@ -1130,37 +1075,16 @@ void Mob::AI_Process() {
|
||||
else {
|
||||
if (AI_movement_timer->Check()) {
|
||||
// Check if we have reached the last fear point
|
||||
if ((std::abs(GetX() - m_FearWalkTarget.x) < 0.1) &&
|
||||
(std::abs(GetY() - m_FearWalkTarget.y) < 0.1)) {
|
||||
if (DistanceNoZ(glm::vec3(GetX(), GetY(), GetZ()), m_FearWalkTarget) <= 5.0f) {
|
||||
// Calculate a new point to run to
|
||||
StopNavigation();
|
||||
CalculateNewFearpoint();
|
||||
}
|
||||
if (!RuleB(Pathing, Fear) || !zone->pathing) {
|
||||
CalculateNewPosition(
|
||||
m_FearWalkTarget.x,
|
||||
m_FearWalkTarget.y,
|
||||
m_FearWalkTarget.z,
|
||||
GetFearSpeed(),
|
||||
true
|
||||
);
|
||||
}
|
||||
else {
|
||||
bool WaypointChanged, NodeReached;
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
m_FearWalkTarget.x,
|
||||
m_FearWalkTarget.y,
|
||||
m_FearWalkTarget.z,
|
||||
GetFearSpeed(),
|
||||
WaypointChanged,
|
||||
NodeReached
|
||||
);
|
||||
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetFearSpeed());
|
||||
}
|
||||
RunTo(
|
||||
m_FearWalkTarget.x,
|
||||
m_FearWalkTarget.y,
|
||||
m_FearWalkTarget.z
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1173,26 +1097,6 @@ void Mob::AI_Process() {
|
||||
}
|
||||
|
||||
if (engaged) {
|
||||
|
||||
/* Fix Z when following during pull, not when engaged and stationary */
|
||||
if (moving && fix_z_timer_engaged.Check()) {
|
||||
if (this->GetTarget()) {
|
||||
/* If we are engaged, moving and following client, let's look for best Z more often */
|
||||
float target_distance = DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition());
|
||||
this->FixZ();
|
||||
|
||||
if (target_distance <= 15 && !this->CheckLosFN(this->GetTarget())) {
|
||||
Mob *target = this->GetTarget();
|
||||
|
||||
m_Position.x = target->GetX();
|
||||
m_Position.y = target->GetY();
|
||||
m_Position.z = target->GetZ();
|
||||
m_Position.w = target->GetHeading();
|
||||
SendPosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(m_PlayerState & static_cast<uint32>(PlayerState::Aggressive)))
|
||||
SendAddPlayerState(PlayerState::Aggressive);
|
||||
|
||||
@@ -1275,21 +1179,12 @@ void Mob::AI_Process() {
|
||||
bool is_combat_range = CombatRange(target);
|
||||
|
||||
if (is_combat_range) {
|
||||
if (AI_movement_timer->Check()) {
|
||||
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) {
|
||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||
SendPosition();
|
||||
}
|
||||
SetCurrentSpeed(0);
|
||||
}
|
||||
if (IsMoving()) {
|
||||
if (CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()) != m_Position.w) {
|
||||
SetHeading(CalculateHeadingToTarget(GetTarget()->GetX(), GetTarget()->GetY()));
|
||||
SendPosition();
|
||||
}
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
FaceTarget();
|
||||
|
||||
//casting checked above...
|
||||
if (target && !IsStunned() && !IsMezzed() && GetAppearance() != eaDead && !IsMeleeDisabled()) {
|
||||
|
||||
@@ -1444,26 +1339,6 @@ void Mob::AI_Process() {
|
||||
|
||||
} //end is within combat rangepet
|
||||
else {
|
||||
//we cannot reach our target...
|
||||
//underwater stuff only works with water maps in the zone!
|
||||
if (IsNPC() && CastToNPC()->IsUnderwaterOnly() && zone->HasWaterMap()) {
|
||||
auto targetPosition = glm::vec3(target->GetX(), target->GetY(), target->GetZ());
|
||||
if (!zone->watermap->InLiquid(targetPosition)) {
|
||||
Mob *tar = hate_list.GetEntWithMostHateOnList(this);
|
||||
if (tar == target) {
|
||||
WipeHateList();
|
||||
Heal();
|
||||
BuffFadeAll();
|
||||
AI_walking_timer->Start(100);
|
||||
time_until_can_move = Timer::GetCurrentTime();
|
||||
return;
|
||||
}
|
||||
else if (tar != nullptr) {
|
||||
SetTarget(tar);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See if we can summon the mob to us
|
||||
if (!HateSummon()) {
|
||||
@@ -1474,32 +1349,19 @@ void Mob::AI_Process() {
|
||||
// Now pursue
|
||||
// TODO: Check here for another person on hate list with close hate value
|
||||
if (AI_PursueCastCheck()) {
|
||||
//we did something, so do not process movement.
|
||||
if (IsCasting() && GetClass() != BARD) {
|
||||
StopNavigation();
|
||||
FaceTarget();
|
||||
}
|
||||
}
|
||||
else if (AI_movement_timer->Check() && target) {
|
||||
if (!IsRooted()) {
|
||||
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
|
||||
if (!RuleB(Pathing, Aggro) || !zone->pathing)
|
||||
CalculateNewPosition(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
|
||||
else {
|
||||
bool WaypointChanged, NodeReached;
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
target->GetX(), target->GetY(), target->GetZ(),
|
||||
GetRunspeed(), WaypointChanged, NodeReached
|
||||
);
|
||||
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetRunspeed());
|
||||
}
|
||||
RunTo(target->GetX(), target->GetY(), target->GetZ());
|
||||
|
||||
}
|
||||
else if (IsMoving()) {
|
||||
SetHeading(CalculateHeadingToTarget(target->GetX(), target->GetY()));
|
||||
SetCurrentSpeed(0);
|
||||
|
||||
else {
|
||||
FaceTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1536,7 +1398,9 @@ void Mob::AI_Process() {
|
||||
}
|
||||
}
|
||||
if (AI_IdleCastCheck()) {
|
||||
//we processed a spell action, so do nothing else.
|
||||
if (IsCasting() && GetClass() != BARD) {
|
||||
StopNavigation();
|
||||
}
|
||||
}
|
||||
else if (zone->CanDoCombat() && CastToNPC()->WillAggroNPCs() && AI_scan_area_timer->Check()) {
|
||||
|
||||
@@ -1572,44 +1436,38 @@ void Mob::AI_Process() {
|
||||
|
||||
if (distance_to_owner >= 400 || z_distance > 100) {
|
||||
|
||||
int pet_speed = GetWalkspeed();
|
||||
bool running = false;
|
||||
|
||||
/**
|
||||
* Distance: >= 35 (Run if far away)
|
||||
*/
|
||||
if (distance_to_owner >= 1225) {
|
||||
pet_speed = GetRunspeed();
|
||||
running = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Distance: >= 450 (Snap to owner)
|
||||
*/
|
||||
if (distance_to_owner >= 202500 || z_distance > 100) {
|
||||
m_Position = pet_owner_position;
|
||||
SendPositionUpdate();
|
||||
moved = true;
|
||||
if (running) {
|
||||
RunTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z);
|
||||
}
|
||||
else {
|
||||
WalkTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
bool waypoint_changed, node_reached;
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
owner->GetX(),
|
||||
owner->GetY(),
|
||||
owner->GetZ(),
|
||||
pet_speed,
|
||||
waypoint_changed,
|
||||
node_reached
|
||||
);
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, pet_speed, true);
|
||||
if (running) {
|
||||
RunTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z);
|
||||
}
|
||||
else {
|
||||
WalkTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (moved) {
|
||||
this->FixZ();
|
||||
SetCurrentSpeed(0);
|
||||
moved = false;
|
||||
}
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1647,29 +1505,24 @@ void Mob::AI_Process() {
|
||||
* Default follow distance is 100
|
||||
*/
|
||||
if (distance >= follow_distance) {
|
||||
int speed = GetWalkspeed();
|
||||
|
||||
bool running = false;
|
||||
// maybe we want the NPC to only walk doing follow logic
|
||||
if (GetFollowCanRun() && distance >= follow_distance + 150) {
|
||||
speed = GetRunspeed();
|
||||
running = true;
|
||||
}
|
||||
|
||||
bool waypoint_changed, node_reached;
|
||||
auto &Goal = follow->GetPosition();
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
follow->GetX(),
|
||||
follow->GetY(),
|
||||
follow->GetZ(),
|
||||
speed,
|
||||
waypoint_changed,
|
||||
node_reached
|
||||
);
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed, true);
|
||||
if (running) {
|
||||
RunTo(Goal.x, Goal.y, Goal.z);
|
||||
}
|
||||
else {
|
||||
WalkTo(Goal.x, Goal.y, Goal.z);
|
||||
}
|
||||
}
|
||||
else {
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1776,7 +1629,7 @@ void NPC::AI_DoMovement() {
|
||||
destination.x = roambox_destination_x;
|
||||
destination.y = roambox_destination_y;
|
||||
destination.z = m_Position.z;
|
||||
roambox_destination_z = GetFixedZ(destination) + this->GetZOffset();
|
||||
roambox_destination_z = zone->zonemap ? zone->zonemap->FindClosestZ(destination, nullptr) + this->GetZOffset() : 0;
|
||||
|
||||
Log(Logs::Detail,
|
||||
Logs::NPCRoamBox,
|
||||
@@ -1791,45 +1644,29 @@ void NPC::AI_DoMovement() {
|
||||
roambox_destination_y);
|
||||
}
|
||||
|
||||
/**
|
||||
bool waypoint_changed, node_reached;
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
roambox_destination_x,
|
||||
roambox_destination_y,
|
||||
roambox_destination_z,
|
||||
move_speed,
|
||||
waypoint_changed,
|
||||
node_reached
|
||||
);
|
||||
**/
|
||||
|
||||
CalculateNewPosition(roambox_destination_x, roambox_destination_y, roambox_destination_z, move_speed, true);
|
||||
NavigateTo(roambox_destination_x, roambox_destination_y, roambox_destination_z);
|
||||
|
||||
if (m_Position.x == roambox_destination_x && m_Position.y == roambox_destination_y) {
|
||||
time_until_can_move = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);
|
||||
SetMoving(false);
|
||||
this->FixZ();
|
||||
SendPosition();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (roamer) {
|
||||
if (AI_walking_timer->Check()) {
|
||||
movetimercompleted = true;
|
||||
pause_timer_complete = true;
|
||||
AI_walking_timer->Disable();
|
||||
}
|
||||
|
||||
|
||||
int32 gridno = CastToNPC()->GetGrid();
|
||||
|
||||
|
||||
if (gridno > 0 || cur_wp == -2) {
|
||||
if (movetimercompleted == true) { // time to pause at wp is over
|
||||
if (pause_timer_complete == true) { // time to pause at wp is over
|
||||
AI_SetupNextWaypoint();
|
||||
} // endif (movetimercompleted==true)
|
||||
} // endif (pause_timer_complete==true)
|
||||
else if (!(AI_walking_timer->Enabled())) { // currently moving
|
||||
bool doMove = true;
|
||||
if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY()) { // are we there yet? then stop
|
||||
if(IsPositionEqual(glm::vec2(m_CurrentWayPoint.x, m_CurrentWayPoint.y), glm::vec2(GetX(), GetY()))) {
|
||||
Log(Logs::Detail,
|
||||
Logs::AI,
|
||||
"We have reached waypoint %d (%.3f,%.3f,%.3f) on grid %d",
|
||||
@@ -1838,17 +1675,13 @@ void NPC::AI_DoMovement() {
|
||||
GetY(),
|
||||
GetZ(),
|
||||
GetGrid());
|
||||
|
||||
|
||||
SetWaypointPause();
|
||||
SetAppearance(eaStanding, false);
|
||||
SetMoving(false);
|
||||
if (m_CurrentWayPoint.w >= 0.0) {
|
||||
SetHeading(m_CurrentWayPoint.w);
|
||||
if (cur_wp_pause > 0) {
|
||||
RotateTo(m_CurrentWayPoint.w);
|
||||
}
|
||||
|
||||
this->FixZ();
|
||||
SendPosition();
|
||||
|
||||
|
||||
//kick off event_waypoint arrive
|
||||
char temp[16];
|
||||
sprintf(temp, "%d", cur_wp);
|
||||
@@ -1862,91 +1695,46 @@ void NPC::AI_DoMovement() {
|
||||
if (cur_wp == -2) {
|
||||
AI_SetupNextWaypoint();
|
||||
}
|
||||
|
||||
|
||||
// wipe feign memory since we reached our first waypoint
|
||||
if (cur_wp == 1)
|
||||
ClearFeignMemory();
|
||||
}
|
||||
if (doMove) { // not at waypoint yet or at 0 pause WP, so keep moving
|
||||
if (!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0))
|
||||
CalculateNewPosition(
|
||||
m_CurrentWayPoint.x,
|
||||
m_CurrentWayPoint.y,
|
||||
m_CurrentWayPoint.z,
|
||||
move_speed,
|
||||
true
|
||||
);
|
||||
else {
|
||||
bool WaypointChanged;
|
||||
bool NodeReached;
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
m_CurrentWayPoint.x,
|
||||
m_CurrentWayPoint.y,
|
||||
m_CurrentWayPoint.z,
|
||||
move_speed,
|
||||
WaypointChanged,
|
||||
NodeReached
|
||||
);
|
||||
if (WaypointChanged)
|
||||
tar_ndx = 20;
|
||||
|
||||
if (NodeReached)
|
||||
entity_list.OpenDoorsNear(CastToNPC());
|
||||
|
||||
CalculateNewPosition(Goal.x, Goal.y, Goal.z, move_speed, true);
|
||||
if (cur_wp_pause == 0) {
|
||||
pause_timer_complete = true;
|
||||
AI_SetupNextWaypoint();
|
||||
doMove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (doMove) { // not at waypoint yet or at 0 pause WP, so keep moving
|
||||
NavigateTo(
|
||||
m_CurrentWayPoint.x,
|
||||
m_CurrentWayPoint.y,
|
||||
m_CurrentWayPoint.z
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
} // endif (gridno > 0)
|
||||
// handle new quest grid command processing
|
||||
else if (gridno < 0) { // this mob is under quest control
|
||||
if (movetimercompleted == true) { // time to pause has ended
|
||||
if (pause_timer_complete == true) { // time to pause has ended
|
||||
SetGrid(0 - GetGrid()); // revert to AI control
|
||||
Log(Logs::Detail, Logs::Pathing, "Quest pathing is finished. Resuming on grid %d", GetGrid());
|
||||
|
||||
|
||||
SetAppearance(eaStanding, false);
|
||||
|
||||
|
||||
CalculateNewWaypoint();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (IsGuarding()) {
|
||||
bool CP2Moved;
|
||||
if (!RuleB(Pathing, Guard) || !zone->pathing) {
|
||||
CP2Moved = CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, move_speed);
|
||||
}
|
||||
else {
|
||||
if (!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) &&
|
||||
(m_Position.z == m_GuardPoint.z))) {
|
||||
else if (IsGuarding()) {
|
||||
bool at_gp = IsPositionEqualWithinCertainZ(m_Position, m_GuardPoint, 15.0f);
|
||||
|
||||
bool WaypointChanged, NodeReached;
|
||||
if (at_gp) {
|
||||
|
||||
glm::vec3 Goal = UpdatePath(
|
||||
m_GuardPoint.x,
|
||||
m_GuardPoint.y,
|
||||
m_GuardPoint.z,
|
||||
move_speed,
|
||||
WaypointChanged,
|
||||
NodeReached
|
||||
);
|
||||
if (WaypointChanged) {
|
||||
tar_ndx = 20;
|
||||
}
|
||||
|
||||
if (NodeReached) {
|
||||
entity_list.OpenDoorsNear(CastToNPC());
|
||||
}
|
||||
|
||||
CP2Moved = CalculateNewPosition(Goal.x, Goal.y, Goal.z, move_speed);
|
||||
}
|
||||
else {
|
||||
CP2Moved = false;
|
||||
}
|
||||
|
||||
}
|
||||
if (!CP2Moved) {
|
||||
if (moved) {
|
||||
Log(Logs::Detail,
|
||||
Logs::AI,
|
||||
@@ -1958,15 +1746,17 @@ void NPC::AI_DoMovement() {
|
||||
ClearFeignMemory();
|
||||
moved = false;
|
||||
if (GetTarget() == nullptr || DistanceSquared(m_Position, GetTarget()->GetPosition()) >= 5 * 5) {
|
||||
SetHeading(m_GuardPoint.w);
|
||||
RotateTo(m_GuardPoint.w);
|
||||
}
|
||||
else {
|
||||
FaceTarget(GetTarget());
|
||||
}
|
||||
SetCurrentSpeed(0);
|
||||
SetAppearance(GetGuardPointAnim());
|
||||
}
|
||||
}
|
||||
else {
|
||||
NavigateTo(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1998,27 +1788,26 @@ void NPC::AI_SetupNextWaypoint() {
|
||||
found_spawn->SetNPCPointerNull();
|
||||
}
|
||||
else {
|
||||
movetimercompleted = false;
|
||||
|
||||
pause_timer_complete = false;
|
||||
Log(Logs::Detail, Logs::Pathing, "We are departing waypoint %d.", cur_wp);
|
||||
|
||||
|
||||
//if we were under quest control (with no grid), we are done now..
|
||||
if (cur_wp == -2) {
|
||||
Log(Logs::Detail, Logs::Pathing, "Non-grid quest mob has reached its quest ordered waypoint. Leaving pathing mode.");
|
||||
roamer = false;
|
||||
cur_wp = 0;
|
||||
}
|
||||
|
||||
|
||||
SetAppearance(eaStanding, false);
|
||||
|
||||
entity_list.OpenDoorsNear(CastToNPC());
|
||||
|
||||
|
||||
entity_list.OpenDoorsNear(this);
|
||||
|
||||
if (!DistractedFromGrid) {
|
||||
//kick off event_waypoint depart
|
||||
char temp[16];
|
||||
sprintf(temp, "%d", cur_wp);
|
||||
parse->EventNPC(EVENT_WAYPOINT_DEPART, CastToNPC(), nullptr, temp, 0);
|
||||
|
||||
|
||||
//setup our next waypoint, if we are still on our normal grid
|
||||
//remember that the quest event above could have done anything it wanted with our grid
|
||||
if (GetGrid() > 0) {
|
||||
@@ -2083,20 +1872,14 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) {
|
||||
void Mob::AI_Event_NoLongerEngaged() {
|
||||
if (!IsAIControlled())
|
||||
return;
|
||||
this->AI_walking_timer->Start(RandomTimer(3000,20000));
|
||||
AI_walking_timer->Start(RandomTimer(3000,20000));
|
||||
time_until_can_move = Timer::GetCurrentTime();
|
||||
if (minLastFightingDelayMoving == maxLastFightingDelayMoving)
|
||||
time_until_can_move += minLastFightingDelayMoving;
|
||||
else
|
||||
time_until_can_move += zone->random.Int(minLastFightingDelayMoving, maxLastFightingDelayMoving);
|
||||
// So mobs don't keep running as a ghost until AIwalking_timer fires
|
||||
// if they were moving prior to losing all hate
|
||||
// except if we're a pet, then we might run into some issues with pets backing off when they should immediately be moving
|
||||
if(!IsPet())
|
||||
{
|
||||
SetRunAnimSpeed(0);
|
||||
SendPosition();
|
||||
}
|
||||
|
||||
StopNavigation();
|
||||
ClearRampage();
|
||||
|
||||
if(IsNPC())
|
||||
|
||||
@@ -0,0 +1,548 @@
|
||||
/**
|
||||
* EQEmulator: Everquest Server Emulator
|
||||
* Copyright (C) 2001-2018 EQEmulator Development Team (https://github.com/EQEmu/Server)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
* are required to give you total support for your newly bought product;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../common/eqemu_logsys.h"
|
||||
|
||||
#include "../common/misc_functions.h"
|
||||
#include "../common/spdat.h"
|
||||
#include "../common/string_util.h"
|
||||
|
||||
#include "mob.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "zonedb.h"
|
||||
|
||||
#ifdef BOTS
|
||||
#include "bot.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Stores internal representation of mob texture by material slot
|
||||
*
|
||||
* @param material_slot
|
||||
* @param texture
|
||||
* @param color
|
||||
* @param hero_forge_model
|
||||
*/
|
||||
void Mob::SetMobTextureProfile(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model)
|
||||
{
|
||||
Log(Logs::Detail, Logs::MobAppearance,
|
||||
"Mob::SetMobTextureProfile [%s] material_slot: %u texture: %u color: %u hero_forge_model: %u",
|
||||
this->GetCleanName(),
|
||||
material_slot,
|
||||
texture,
|
||||
color,
|
||||
hero_forge_model
|
||||
);
|
||||
|
||||
switch (material_slot) {
|
||||
case EQEmu::textures::armorHead:
|
||||
mob_texture_profile.Head.Material = texture;
|
||||
mob_texture_profile.Head.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Head.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::armorChest:
|
||||
mob_texture_profile.Chest.Material = texture;
|
||||
mob_texture_profile.Chest.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Chest.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::armorArms:
|
||||
mob_texture_profile.Arms.Material = texture;
|
||||
mob_texture_profile.Arms.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Arms.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::armorWrist:
|
||||
mob_texture_profile.Wrist.Material = texture;
|
||||
mob_texture_profile.Wrist.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Wrist.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::armorHands:
|
||||
mob_texture_profile.Hands.Material = texture;
|
||||
mob_texture_profile.Hands.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Hands.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::armorLegs:
|
||||
mob_texture_profile.Legs.Material = texture;
|
||||
mob_texture_profile.Legs.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Legs.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::armorFeet:
|
||||
mob_texture_profile.Feet.Material = texture;
|
||||
mob_texture_profile.Feet.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Feet.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::weaponPrimary:
|
||||
mob_texture_profile.Primary.Material = texture;
|
||||
mob_texture_profile.Primary.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Primary.Color = color;
|
||||
break;
|
||||
case EQEmu::textures::weaponSecondary:
|
||||
mob_texture_profile.Secondary.Material = texture;
|
||||
mob_texture_profile.Secondary.HerosForgeModel = hero_forge_model;
|
||||
mob_texture_profile.Secondary.Color = color;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns internal representation of mob texture by material
|
||||
*
|
||||
* @param material_slot
|
||||
* @return
|
||||
*/
|
||||
int32 Mob::GetTextureProfileMaterial(uint8 material_slot) const
|
||||
{
|
||||
switch (material_slot) {
|
||||
case EQEmu::textures::armorHead:
|
||||
return mob_texture_profile.Head.Material;
|
||||
case EQEmu::textures::armorChest:
|
||||
return mob_texture_profile.Chest.Material;
|
||||
case EQEmu::textures::armorArms:
|
||||
return mob_texture_profile.Arms.Material;
|
||||
case EQEmu::textures::armorWrist:
|
||||
return mob_texture_profile.Wrist.Material;
|
||||
case EQEmu::textures::armorHands:
|
||||
return mob_texture_profile.Hands.Material;
|
||||
case EQEmu::textures::armorLegs:
|
||||
return mob_texture_profile.Legs.Material;
|
||||
case EQEmu::textures::armorFeet:
|
||||
return mob_texture_profile.Feet.Material;
|
||||
case EQEmu::textures::weaponPrimary:
|
||||
return mob_texture_profile.Primary.Material;
|
||||
case EQEmu::textures::weaponSecondary:
|
||||
return mob_texture_profile.Secondary.Material;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns internal representation of mob texture by color
|
||||
*
|
||||
* @param material_slot
|
||||
* @return
|
||||
*/
|
||||
int32 Mob::GetTextureProfileColor(uint8 material_slot) const
|
||||
{
|
||||
switch (material_slot) {
|
||||
case EQEmu::textures::armorHead:
|
||||
return mob_texture_profile.Head.Color;
|
||||
case EQEmu::textures::armorChest:
|
||||
return mob_texture_profile.Chest.Color;
|
||||
case EQEmu::textures::armorArms:
|
||||
return mob_texture_profile.Arms.Color;
|
||||
case EQEmu::textures::armorWrist:
|
||||
return mob_texture_profile.Wrist.Color;
|
||||
case EQEmu::textures::armorHands:
|
||||
return mob_texture_profile.Hands.Color;
|
||||
case EQEmu::textures::armorLegs:
|
||||
return mob_texture_profile.Legs.Color;
|
||||
case EQEmu::textures::armorFeet:
|
||||
return mob_texture_profile.Feet.Color;
|
||||
case EQEmu::textures::weaponPrimary:
|
||||
return mob_texture_profile.Primary.Color;
|
||||
case EQEmu::textures::weaponSecondary:
|
||||
return mob_texture_profile.Secondary.Color;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns internal representation of mob texture by HerosForgeModel
|
||||
*
|
||||
* @param material_slot
|
||||
* @return
|
||||
*/
|
||||
int32 Mob::GetTextureProfileHeroForgeModel(uint8 material_slot) const
|
||||
{
|
||||
switch (material_slot) {
|
||||
case EQEmu::textures::armorHead:
|
||||
return mob_texture_profile.Head.HerosForgeModel;
|
||||
case EQEmu::textures::armorChest:
|
||||
return mob_texture_profile.Chest.HerosForgeModel;
|
||||
case EQEmu::textures::armorArms:
|
||||
return mob_texture_profile.Arms.HerosForgeModel;
|
||||
case EQEmu::textures::armorWrist:
|
||||
return mob_texture_profile.Wrist.HerosForgeModel;
|
||||
case EQEmu::textures::armorHands:
|
||||
return mob_texture_profile.Hands.HerosForgeModel;
|
||||
case EQEmu::textures::armorLegs:
|
||||
return mob_texture_profile.Legs.HerosForgeModel;
|
||||
case EQEmu::textures::armorFeet:
|
||||
return mob_texture_profile.Feet.HerosForgeModel;
|
||||
case EQEmu::textures::weaponPrimary:
|
||||
return mob_texture_profile.Primary.HerosForgeModel;
|
||||
case EQEmu::textures::weaponSecondary:
|
||||
return mob_texture_profile.Secondary.HerosForgeModel;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the material or texture for a slot (leather / plate etc.)
|
||||
*
|
||||
* @param material_slot
|
||||
* @return
|
||||
*/
|
||||
int32 Mob::GetEquipmentMaterial(uint8 material_slot) const
|
||||
{
|
||||
uint32 equipment_material = 0;
|
||||
int32 ornamentation_augment_type = RuleI(Character, OrnamentationAugmentType);
|
||||
|
||||
int32 texture_profile_material = GetTextureProfileMaterial(material_slot);
|
||||
|
||||
Log(Logs::Detail, Logs::MobAppearance,
|
||||
"Mob::GetEquipmentMaterial [%s] material_slot: %u texture_profile_material: %i",
|
||||
this->clean_name,
|
||||
material_slot,
|
||||
texture_profile_material
|
||||
);
|
||||
|
||||
if (texture_profile_material > 0) {
|
||||
return texture_profile_material;
|
||||
}
|
||||
|
||||
auto item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
|
||||
|
||||
if (item != nullptr) {
|
||||
|
||||
/**
|
||||
* Handle primary / secondary texture
|
||||
*/
|
||||
bool is_primary_or_secondary_weapon =
|
||||
material_slot == EQEmu::textures::weaponPrimary ||
|
||||
material_slot == EQEmu::textures::weaponSecondary;
|
||||
|
||||
if (is_primary_or_secondary_weapon) {
|
||||
if (this->IsClient()) {
|
||||
|
||||
int16 inventory_slot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot);
|
||||
if (inventory_slot == INVALID_INDEX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EQEmu::ItemInstance *item_instance = CastToClient()->m_inv[inventory_slot];
|
||||
if (item_instance) {
|
||||
if (item_instance->GetOrnamentationAug(ornamentation_augment_type)) {
|
||||
item = item_instance->GetOrnamentationAug(ornamentation_augment_type)->GetItem();
|
||||
if (item && strlen(item->IDFile) > 2) {
|
||||
equipment_material = atoi(&item->IDFile[2]);
|
||||
}
|
||||
}
|
||||
else if (item_instance->GetOrnamentationIDFile()) {
|
||||
equipment_material = item_instance->GetOrnamentationIDFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (equipment_material == 0 && strlen(item->IDFile) > 2) {
|
||||
equipment_material = atoi(&item->IDFile[2]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
equipment_material = item->Material;
|
||||
}
|
||||
}
|
||||
|
||||
return equipment_material;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material_slot
|
||||
* @return
|
||||
*/
|
||||
uint32 Mob::GetEquipmentColor(uint8 material_slot) const
|
||||
{
|
||||
const EQEmu::ItemData *item = nullptr;
|
||||
|
||||
if (armor_tint.Slot[material_slot].Color) {
|
||||
return armor_tint.Slot[material_slot].Color;
|
||||
}
|
||||
|
||||
item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
|
||||
if (item != nullptr) {
|
||||
return item->Color;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material_slot
|
||||
* @return
|
||||
*/
|
||||
int32 Mob::GetHerosForgeModel(uint8 material_slot) const
|
||||
{
|
||||
uint32 hero_model = 0;
|
||||
if (material_slot >= 0 && material_slot < EQEmu::textures::weaponPrimary) {
|
||||
uint32 ornamentation_aug_type = RuleI(Character, OrnamentationAugmentType);
|
||||
|
||||
const EQEmu::ItemData *item = database.GetItem(GetEquippedItemFromTextureSlot(material_slot));
|
||||
int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot);
|
||||
|
||||
if (item != nullptr && invslot != INVALID_INDEX) {
|
||||
if (IsClient()) {
|
||||
const EQEmu::ItemInstance *inst = CastToClient()->m_inv[invslot];
|
||||
if (inst) {
|
||||
if (inst->GetOrnamentationAug(ornamentation_aug_type)) {
|
||||
item = inst->GetOrnamentationAug(ornamentation_aug_type)->GetItem();
|
||||
hero_model = item->HerosForgeModel;
|
||||
}
|
||||
else if (inst->GetOrnamentHeroModel()) {
|
||||
hero_model = inst->GetOrnamentHeroModel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hero_model == 0) {
|
||||
hero_model = item->HerosForgeModel;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsNPC()) {
|
||||
hero_model = CastToNPC()->GetHeroForgeModel();
|
||||
|
||||
/**
|
||||
* Robes require full model number, and should only be sent to chest, arms, wrists, and legs slots
|
||||
*/
|
||||
if (hero_model > 1000 && material_slot != 1 && material_slot != 2 && material_slot != 3 &&
|
||||
material_slot != 5) {
|
||||
hero_model = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-Convert Hero Model to match the slot
|
||||
*
|
||||
* Otherwise, use the exact Model if model is > 999
|
||||
* Robes for example are 11607 to 12107 in RoF
|
||||
*/
|
||||
if (hero_model > 0 && hero_model < 1000) {
|
||||
hero_model *= 100;
|
||||
hero_model += material_slot;
|
||||
}
|
||||
|
||||
return hero_model;
|
||||
}
|
||||
|
||||
uint32 NPC::GetEquippedItemFromTextureSlot(uint8 material_slot) const
|
||||
{
|
||||
if (material_slot > 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 inventory_slot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot);
|
||||
if (inventory_slot == INVALID_INDEX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return equipment[inventory_slot];
|
||||
}
|
||||
|
||||
/**
|
||||
* NPCs typically use this function for sending appearance
|
||||
* @param one_client
|
||||
*/
|
||||
void Mob::SendArmorAppearance(Client *one_client)
|
||||
{
|
||||
/**
|
||||
* one_client of 0 means sent to all clients
|
||||
*
|
||||
* Despite the fact that OP_NewSpawn and OP_ZoneSpawns include the
|
||||
* armor being worn and its mats, the client doesn't update the display
|
||||
* on arrival of these packets reliably.
|
||||
*
|
||||
* Send Wear changes if mob is a PC race and item is an armor slot.
|
||||
* The other packets work for primary/secondary.
|
||||
*/
|
||||
|
||||
Log(Logs::Detail, Logs::MobAppearance, "Mob::SendArmorAppearance [%s]",
|
||||
this->GetCleanName()
|
||||
);
|
||||
|
||||
if (IsPlayerRace(race)) {
|
||||
if (!IsClient()) {
|
||||
for (uint8 i = 0; i <= EQEmu::textures::materialCount; ++i) {
|
||||
const EQEmu::ItemData *item = database.GetItem(GetEquippedItemFromTextureSlot(i));
|
||||
if (item != nullptr) {
|
||||
SendWearChange(i, one_client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i <= EQEmu::textures::materialCount; ++i) {
|
||||
if (GetTextureProfileMaterial(i)) {
|
||||
SendWearChange(i, one_client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material_slot
|
||||
* @param one_client
|
||||
*/
|
||||
void Mob::SendWearChange(uint8 material_slot, Client *one_client)
|
||||
{
|
||||
auto packet = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
|
||||
auto *wear_change = (WearChange_Struct *) packet->pBuffer;
|
||||
|
||||
Log(Logs::Detail, Logs::MobAppearance, "Mob::SendWearChange [%s]",
|
||||
this->GetCleanName()
|
||||
);
|
||||
|
||||
wear_change->spawn_id = GetID();
|
||||
wear_change->material = static_cast<uint32>(GetEquipmentMaterial(material_slot));
|
||||
wear_change->elite_material = IsEliteMaterialItem(material_slot);
|
||||
wear_change->hero_forge_model = static_cast<uint32>(GetHerosForgeModel(material_slot));
|
||||
|
||||
#ifdef BOTS
|
||||
if (IsBot()) {
|
||||
auto item_inst = CastToBot()->GetBotItem(EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot));
|
||||
if (item_inst)
|
||||
wear_change->color.Color = item_inst->GetColor();
|
||||
else
|
||||
wear_change->color.Color = 0;
|
||||
}
|
||||
else {
|
||||
wear_change->color.Color = GetEquipmentColor(material_slot);
|
||||
}
|
||||
#else
|
||||
wear_change->color.Color = GetEquipmentColor(material_slot);
|
||||
#endif
|
||||
|
||||
wear_change->wear_slot_id = material_slot;
|
||||
|
||||
if (!one_client) {
|
||||
entity_list.QueueClients(this, packet);
|
||||
}
|
||||
else {
|
||||
one_client->QueuePacket(packet, false, Client::CLIENT_CONNECTED);
|
||||
}
|
||||
|
||||
safe_delete(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param slot
|
||||
* @param texture
|
||||
* @param hero_forge_model
|
||||
* @param elite_material
|
||||
* @param unknown06
|
||||
* @param unknown18
|
||||
*/
|
||||
void Mob::SendTextureWC(
|
||||
uint8 slot,
|
||||
uint16 texture,
|
||||
uint32 hero_forge_model,
|
||||
uint32 elite_material,
|
||||
uint32 unknown06,
|
||||
uint32 unknown18
|
||||
)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
|
||||
auto *wear_change = (WearChange_Struct *) outapp->pBuffer;
|
||||
|
||||
if (this->IsClient()) {
|
||||
wear_change->color.Color = GetEquipmentColor(slot);
|
||||
}
|
||||
else {
|
||||
wear_change->color.Color = this->GetArmorTint(slot);
|
||||
}
|
||||
|
||||
wear_change->spawn_id = this->GetID();
|
||||
wear_change->material = texture;
|
||||
wear_change->wear_slot_id = slot;
|
||||
wear_change->unknown06 = unknown06;
|
||||
wear_change->elite_material = elite_material;
|
||||
wear_change->hero_forge_model = hero_forge_model;
|
||||
wear_change->unknown18 = unknown18;
|
||||
|
||||
SetMobTextureProfile(slot, texture, wear_change->color.Color, hero_forge_model);
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material_slot
|
||||
* @param red_tint
|
||||
* @param green_tint
|
||||
* @param blue_tint
|
||||
*/
|
||||
void Mob::SetSlotTint(uint8 material_slot, uint8 red_tint, uint8 green_tint, uint8 blue_tint)
|
||||
{
|
||||
uint32 color;
|
||||
color = (red_tint & 0xFF) << 16;
|
||||
color |= (green_tint & 0xFF) << 8;
|
||||
color |= (blue_tint & 0xFF);
|
||||
color |= (color) ? (0xFF << 24) : 0;
|
||||
armor_tint.Slot[material_slot].Color = color;
|
||||
|
||||
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
|
||||
auto *wc = (WearChange_Struct *) outapp->pBuffer;
|
||||
|
||||
wc->spawn_id = this->GetID();
|
||||
wc->material = GetEquipmentMaterial(material_slot);
|
||||
wc->hero_forge_model = GetHerosForgeModel(material_slot);
|
||||
wc->color.Color = color;
|
||||
wc->wear_slot_id = material_slot;
|
||||
|
||||
SetMobTextureProfile(material_slot, texture, color);
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param material_slot
|
||||
* @param texture
|
||||
* @param color
|
||||
* @param hero_forge_model
|
||||
*/
|
||||
void Mob::WearChange(uint8 material_slot, uint16 texture, uint32 color, uint32 hero_forge_model)
|
||||
{
|
||||
armor_tint.Slot[material_slot].Color = color;
|
||||
|
||||
/**
|
||||
* Change internal values
|
||||
*/
|
||||
SetMobTextureProfile(material_slot, texture, color, hero_forge_model);
|
||||
|
||||
/**
|
||||
* Packet update
|
||||
*/
|
||||
auto outapp = new EQApplicationPacket(OP_WearChange, sizeof(WearChange_Struct));
|
||||
auto *wear_change = (WearChange_Struct *) outapp->pBuffer;
|
||||
|
||||
wear_change->spawn_id = this->GetID();
|
||||
wear_change->material = texture;
|
||||
wear_change->hero_forge_model = hero_forge_model;
|
||||
wear_change->color.Color = color;
|
||||
wear_change->wear_slot_id = material_slot;
|
||||
|
||||
entity_list.QueueClients(this, outapp);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
+5
-1
@@ -618,6 +618,10 @@ inline void NPCCommandsMenu(Client* client, NPC* npc)
|
||||
menu_commands += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#npcloot show", false, "Loot") + "] ";
|
||||
}
|
||||
|
||||
if (npc->IsProximitySet()) {
|
||||
menu_commands += "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#proximity show", false, "Proximity") + "] ";
|
||||
}
|
||||
|
||||
if (menu_commands.length() > 0) {
|
||||
std::string dev_menu = "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#devtools", false, "DevTools") + "] ";;
|
||||
client->Message(0, "| %s [Show Commands] %s", dev_menu.c_str(), menu_commands.c_str());
|
||||
@@ -813,7 +817,7 @@ void Mob::DisplayInfo(Mob *mob)
|
||||
NPCCommandsMenu(client, npc);
|
||||
}
|
||||
|
||||
std::cout << "Window Length: " << window_text.length() << std::endl;
|
||||
// std::cout << "Window Length: " << window_text.length() << std::endl;
|
||||
|
||||
if (client->GetDisplayMobInfoWindow()) {
|
||||
client->SendFullPopup(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include <memory>
|
||||
|
||||
class Mob;
|
||||
class Client;
|
||||
|
||||
struct RotateCommand;
|
||||
struct MovementCommand;
|
||||
struct MobMovementEntry;
|
||||
struct PlayerPositionUpdateServer_Struct;
|
||||
|
||||
enum ClientRange : int
|
||||
{
|
||||
ClientRangeNone = 0,
|
||||
ClientRangeClose = 1,
|
||||
ClientRangeMedium = 2,
|
||||
ClientRangeCloseMedium = 3,
|
||||
ClientRangeLong = 4,
|
||||
ClientRangeCloseLong = 5,
|
||||
ClientRangeMediumLong = 6,
|
||||
ClientRangeAny = 7
|
||||
};
|
||||
|
||||
enum MobMovementMode : int
|
||||
{
|
||||
MovementWalking = 0,
|
||||
MovementRunning = 1
|
||||
};
|
||||
|
||||
enum MobStuckBehavior : int
|
||||
{
|
||||
RunToTarget,
|
||||
WarpToTarget,
|
||||
TakeNoAction,
|
||||
EvadeCombat,
|
||||
MaxStuckBehavior
|
||||
};
|
||||
|
||||
class MobMovementManager
|
||||
{
|
||||
public:
|
||||
~MobMovementManager();
|
||||
void Process();
|
||||
void AddMob(Mob *m);
|
||||
void RemoveMob(Mob *m);
|
||||
void AddClient(Client *c);
|
||||
void RemoveClient(Client *c);
|
||||
|
||||
void RotateTo(Mob *who, float to, MobMovementMode mode = MovementRunning);
|
||||
void Teleport(Mob *who, float x, float y, float z, float heading);
|
||||
void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
|
||||
void StopNavigation(Mob *who);
|
||||
void SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range);
|
||||
float FixHeading(float in);
|
||||
void DumpStats(Client *to);
|
||||
void ClearStats();
|
||||
|
||||
static MobMovementManager &Get() {
|
||||
static MobMovementManager inst;
|
||||
return inst;
|
||||
}
|
||||
|
||||
private:
|
||||
MobMovementManager();
|
||||
MobMovementManager(const MobMovementManager&);
|
||||
MobMovementManager& operator=(const MobMovementManager&);
|
||||
|
||||
void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim);
|
||||
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
|
||||
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
|
||||
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode);
|
||||
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode);
|
||||
void PushStopMoving(MobMovementEntry &ent);
|
||||
void PushEvadeCombat(MobMovementEntry &ent);
|
||||
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode);
|
||||
|
||||
struct Implementation;
|
||||
std::unique_ptr<Implementation> _impl;
|
||||
};
|
||||
+8
-5
@@ -110,7 +110,7 @@ EQEmuLogSys LogSys;
|
||||
const SPDat_Spell_Struct* spells;
|
||||
int32 SPDAT_RECORDS = -1;
|
||||
const ZoneConfig *Config;
|
||||
uint64_t frame_time = 0;
|
||||
double frame_time = 0.0;
|
||||
|
||||
void Shutdown();
|
||||
extern void MapOpcodes();
|
||||
@@ -362,18 +362,21 @@ int main(int argc, char** argv) {
|
||||
std::string tmp;
|
||||
if (database.GetVariable("RuleSet", tmp)) {
|
||||
Log(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp.c_str());
|
||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
||||
Log(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, "default")) {
|
||||
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||
Log(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules");
|
||||
}
|
||||
else {
|
||||
Log(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
EQEmu::InitializeDynamicLookups();
|
||||
Log(Logs::General, Logs::Zone_Server, "Initialized dynamic dictionary entries");
|
||||
}
|
||||
|
||||
#ifdef BOTS
|
||||
@@ -453,7 +456,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
//Calculate frame time
|
||||
std::chrono::time_point<std::chrono::system_clock> frame_now = std::chrono::system_clock::now();
|
||||
frame_time = std::chrono::duration_cast<std::chrono::milliseconds>(frame_now - frame_prev).count();
|
||||
frame_time = std::chrono::duration_cast<std::chrono::duration<double>>(frame_now - frame_prev).count();
|
||||
frame_prev = frame_now;
|
||||
|
||||
if (!eqsf_open && Config->ZonePort != 0) {
|
||||
@@ -680,4 +683,4 @@ void UpdateWindowTitle(char* iNewTitle) {
|
||||
}
|
||||
SetConsoleTitle(tmp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
+135
-75
@@ -39,6 +39,7 @@
|
||||
#include "spawn2.h"
|
||||
#include "zone.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "water_map.h"
|
||||
#include "npc_scale_manager.h"
|
||||
|
||||
#include <cctype>
|
||||
@@ -58,7 +59,7 @@ extern Zone* zone;
|
||||
extern volatile bool is_zone_loaded;
|
||||
extern EntityList entity_list;
|
||||
|
||||
NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &position, int iflymode, bool IsCorpse)
|
||||
NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &position, GravityBehavior iflymode, bool IsCorpse)
|
||||
: Mob(
|
||||
npc_type_data->name,
|
||||
npc_type_data->lastname,
|
||||
@@ -506,7 +507,7 @@ void NPC::SetTarget(Mob* mob) {
|
||||
|
||||
if (owner) {
|
||||
auto client = owner->CastToClient();
|
||||
if (client->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) {
|
||||
if (client->ClientVersionBit() & EQEmu::versions::maskUFAndLater) {
|
||||
auto app = new EQApplicationPacket(OP_PetHoTT, sizeof(ClientTarget_Struct));
|
||||
auto ct = (ClientTarget_Struct *)app->pBuffer;
|
||||
ct->new_target = mob ? mob->GetID() : 0;
|
||||
@@ -803,9 +804,8 @@ bool NPC::Process()
|
||||
DoGravityEffect();
|
||||
}
|
||||
|
||||
if(reface_timer->Check() && !IsEngaged() && (m_GuardPoint.x == GetX() && m_GuardPoint.y == GetY() && m_GuardPoint.z == GetZ())) {
|
||||
SetHeading(m_GuardPoint.w);
|
||||
SendPosition();
|
||||
if(reface_timer->Check() && !IsEngaged() && IsPositionEqualWithinCertainZ(m_Position, m_GuardPoint, 5.0f)) {
|
||||
RotateTo(m_GuardPoint.w);
|
||||
reface_timer->Disable();
|
||||
}
|
||||
|
||||
@@ -973,7 +973,7 @@ bool NPC::SpawnZoneController()
|
||||
memset(npc_type, 0, sizeof(NPCType));
|
||||
|
||||
strncpy(npc_type->name, "zone_controller", 60);
|
||||
npc_type->cur_hp = 2000000000;
|
||||
npc_type->current_hp = 2000000000;
|
||||
npc_type->max_hp = 2000000000;
|
||||
npc_type->hp_regen = 100000000;
|
||||
npc_type->race = 240;
|
||||
@@ -1009,7 +1009,7 @@ bool NPC::SpawnZoneController()
|
||||
point.y = 1000;
|
||||
point.z = 500;
|
||||
|
||||
auto npc = new NPC(npc_type, nullptr, point, FlyMode3);
|
||||
auto npc = new NPC(npc_type, nullptr, point, GravityBehavior::Flying);
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
|
||||
entity_list.AddNPC(npc);
|
||||
@@ -1024,7 +1024,7 @@ NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32
|
||||
sprintf(npc_type->name, "%u_%u", grid_id, grid_number);
|
||||
sprintf(npc_type->lastname, "Number: %u Grid: %u Pause: %u", grid_number, grid_id, pause);
|
||||
|
||||
npc_type->cur_hp = 4000000;
|
||||
npc_type->current_hp = 4000000;
|
||||
npc_type->max_hp = 4000000;
|
||||
npc_type->race = 2254;
|
||||
npc_type->gender = 2;
|
||||
@@ -1037,22 +1037,50 @@ NPC * NPC::SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32
|
||||
npc_type->light = 1;
|
||||
npc_type->size = 1;
|
||||
npc_type->runspeed = 0;
|
||||
npc_type->merchanttype = 1;
|
||||
npc_type->bodytype = 1;
|
||||
npc_type->show_name = true;
|
||||
npc_type->findable = true;
|
||||
|
||||
auto node_position = glm::vec4(position.x, position.y, position.z, position.w);
|
||||
auto npc = new NPC(npc_type, nullptr, node_position, GravityBehavior::Flying);
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
|
||||
entity_list.AddNPC(npc, true, true);
|
||||
|
||||
return npc;
|
||||
}
|
||||
|
||||
NPC * NPC::SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position) {
|
||||
auto npc_type = new NPCType;
|
||||
memset(npc_type, 0, sizeof(NPCType));
|
||||
|
||||
sprintf(npc_type->name, "%s", name.c_str());
|
||||
sprintf(npc_type->lastname, "%s", last_name.c_str());
|
||||
|
||||
npc_type->current_hp = 4000000;
|
||||
npc_type->max_hp = 4000000;
|
||||
npc_type->race = 2254;
|
||||
npc_type->gender = 2;
|
||||
npc_type->class_ = 9;
|
||||
npc_type->deity = 1;
|
||||
npc_type->level = 200;
|
||||
npc_type->npc_id = 0;
|
||||
npc_type->loottable_id = 0;
|
||||
npc_type->texture = 1;
|
||||
npc_type->light = 1;
|
||||
npc_type->size = 3;
|
||||
npc_type->d_melee_texture1 = 1;
|
||||
npc_type->d_melee_texture2 = 1;
|
||||
npc_type->merchanttype = 1;
|
||||
npc_type->bodytype = 1;
|
||||
npc_type->show_name = true;
|
||||
npc_type->STR = 150;
|
||||
npc_type->STA = 150;
|
||||
npc_type->DEX = 150;
|
||||
npc_type->AGI = 150;
|
||||
npc_type->INT = 150;
|
||||
npc_type->WIS = 150;
|
||||
npc_type->CHA = 150;
|
||||
npc_type->findable = true;
|
||||
npc_type->runspeed = 1.25;
|
||||
|
||||
auto node_position = glm::vec4(position.x, position.y, position.z, position.w);
|
||||
auto npc = new NPC(npc_type, nullptr, node_position, FlyMode1);
|
||||
auto npc = new NPC(npc_type, nullptr, node_position, GravityBehavior::Flying);
|
||||
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
|
||||
entity_list.AddNPC(npc, true, true);
|
||||
@@ -1067,33 +1095,45 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
|
||||
else {
|
||||
Seperator sep(spawncommand);
|
||||
//Lets see if someone didn't fill out the whole #spawn function properly
|
||||
if (!sep.IsNumber(1))
|
||||
sprintf(sep.arg[1],"1");
|
||||
if (!sep.IsNumber(2))
|
||||
sprintf(sep.arg[2],"1");
|
||||
if (!sep.IsNumber(3))
|
||||
sprintf(sep.arg[3],"0");
|
||||
if (atoi(sep.arg[4]) > 2100000000 || atoi(sep.arg[4]) <= 0)
|
||||
sprintf(sep.arg[4]," ");
|
||||
if (!strcmp(sep.arg[5],"-"))
|
||||
sprintf(sep.arg[5]," ");
|
||||
if (!sep.IsNumber(5))
|
||||
sprintf(sep.arg[5]," ");
|
||||
if (!sep.IsNumber(6))
|
||||
sprintf(sep.arg[6],"1");
|
||||
if (!sep.IsNumber(8))
|
||||
sprintf(sep.arg[8],"0");
|
||||
if (!sep.IsNumber(9))
|
||||
if (!sep.IsNumber(1)) {
|
||||
sprintf(sep.arg[1], "1");
|
||||
}
|
||||
if (!sep.IsNumber(2)) {
|
||||
sprintf(sep.arg[2], "1");
|
||||
}
|
||||
if (!sep.IsNumber(3)) {
|
||||
sprintf(sep.arg[3], "0");
|
||||
}
|
||||
if (atoi(sep.arg[4]) > 2100000000 || atoi(sep.arg[4]) <= 0) {
|
||||
sprintf(sep.arg[4], " ");
|
||||
}
|
||||
if (!strcmp(sep.arg[5], "-")) {
|
||||
sprintf(sep.arg[5], " ");
|
||||
}
|
||||
if (!sep.IsNumber(5)) {
|
||||
sprintf(sep.arg[5], " ");
|
||||
}
|
||||
if (!sep.IsNumber(6)) {
|
||||
sprintf(sep.arg[6], "1");
|
||||
}
|
||||
if (!sep.IsNumber(8)) {
|
||||
sprintf(sep.arg[8], "0");
|
||||
}
|
||||
if (!sep.IsNumber(9)) {
|
||||
sprintf(sep.arg[9], "0");
|
||||
if (!sep.IsNumber(7))
|
||||
sprintf(sep.arg[7],"0");
|
||||
if (!strcmp(sep.arg[4],"-"))
|
||||
sprintf(sep.arg[4]," ");
|
||||
if (!sep.IsNumber(10)) // bodytype
|
||||
}
|
||||
if (!sep.IsNumber(7)) {
|
||||
sprintf(sep.arg[7], "0");
|
||||
}
|
||||
if (!strcmp(sep.arg[4], "-")) {
|
||||
sprintf(sep.arg[4], " ");
|
||||
}
|
||||
if (!sep.IsNumber(10)) { // bodytype
|
||||
sprintf(sep.arg[10], "0");
|
||||
}
|
||||
//Calc MaxHP if client neglected to enter it...
|
||||
if (!sep.IsNumber(4)) {
|
||||
sep.arg[4] = 0;
|
||||
if (sep.arg[4] && !sep.IsNumber(4)) {
|
||||
sprintf(sep.arg[4], "0");
|
||||
}
|
||||
|
||||
// Autoselect NPC Gender
|
||||
@@ -1106,7 +1146,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
|
||||
memset(npc_type, 0, sizeof(NPCType));
|
||||
|
||||
strncpy(npc_type->name, sep.arg[0], 60);
|
||||
npc_type->cur_hp = atoi(sep.arg[4]);
|
||||
npc_type->current_hp = atoi(sep.arg[4]);
|
||||
npc_type->max_hp = atoi(sep.arg[4]);
|
||||
npc_type->race = atoi(sep.arg[1]);
|
||||
npc_type->gender = atoi(sep.arg[5]);
|
||||
@@ -1136,7 +1176,7 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
|
||||
npc_type->prim_melee_type = 28;
|
||||
npc_type->sec_melee_type = 28;
|
||||
|
||||
auto npc = new NPC(npc_type, nullptr, position, FlyMode3);
|
||||
auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Water);
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
|
||||
entity_list.AddNPC(npc);
|
||||
@@ -1348,7 +1388,7 @@ uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32
|
||||
uint32 spawngroupID = 0;
|
||||
|
||||
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' "
|
||||
"AND version = %u AND spawngroupID = %i",
|
||||
"AND (version = %u OR version = -1) AND spawngroupID = %i",
|
||||
zone, zone_version, spawn->GetSp2());
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
@@ -1459,38 +1499,49 @@ uint32 ZoneDatabase::NPCSpawnDB(uint8 command, const char* zone, uint32 zone_ver
|
||||
|
||||
int32 NPC::GetEquipmentMaterial(uint8 material_slot) const
|
||||
{
|
||||
if (material_slot >= EQEmu::textures::materialCount)
|
||||
int32 texture_profile_material = GetTextureProfileMaterial(material_slot);
|
||||
|
||||
Log(Logs::Detail, Logs::MobAppearance, "NPC::GetEquipmentMaterial [%s] material_slot: %u",
|
||||
this->clean_name,
|
||||
material_slot
|
||||
);
|
||||
|
||||
if (texture_profile_material > 0) {
|
||||
return texture_profile_material;
|
||||
}
|
||||
|
||||
if (material_slot >= EQEmu::textures::materialCount) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16 invslot = EQEmu::InventoryProfile::CalcSlotFromMaterial(material_slot);
|
||||
if (invslot == INVALID_INDEX)
|
||||
if (invslot == INVALID_INDEX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (equipment[invslot] == 0)
|
||||
{
|
||||
switch(material_slot)
|
||||
{
|
||||
case EQEmu::textures::armorHead:
|
||||
return helmtexture;
|
||||
case EQEmu::textures::armorChest:
|
||||
return texture;
|
||||
case EQEmu::textures::armorArms:
|
||||
return armtexture;
|
||||
case EQEmu::textures::armorWrist:
|
||||
return bracertexture;
|
||||
case EQEmu::textures::armorHands:
|
||||
return handtexture;
|
||||
case EQEmu::textures::armorLegs:
|
||||
return legtexture;
|
||||
case EQEmu::textures::armorFeet:
|
||||
return feettexture;
|
||||
case EQEmu::textures::weaponPrimary:
|
||||
return d_melee_texture1;
|
||||
case EQEmu::textures::weaponSecondary:
|
||||
return d_melee_texture2;
|
||||
default:
|
||||
//they have nothing in the slot, and its not a special slot... they get nothing.
|
||||
return(0);
|
||||
if (equipment[invslot] == 0) {
|
||||
switch (material_slot) {
|
||||
case EQEmu::textures::armorHead:
|
||||
return helmtexture;
|
||||
case EQEmu::textures::armorChest:
|
||||
return texture;
|
||||
case EQEmu::textures::armorArms:
|
||||
return armtexture;
|
||||
case EQEmu::textures::armorWrist:
|
||||
return bracertexture;
|
||||
case EQEmu::textures::armorHands:
|
||||
return handtexture;
|
||||
case EQEmu::textures::armorLegs:
|
||||
return legtexture;
|
||||
case EQEmu::textures::armorFeet:
|
||||
return feettexture;
|
||||
case EQEmu::textures::weaponPrimary:
|
||||
return d_melee_texture1;
|
||||
case EQEmu::textures::weaponSecondary:
|
||||
return d_melee_texture2;
|
||||
default:
|
||||
//they have nothing in the slot, and its not a special slot... they get nothing.
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2136,8 +2187,8 @@ void NPC::ModifyNPCStat(const char *identifier, const char *new_value)
|
||||
base_hp = atoi(val.c_str());
|
||||
|
||||
CalcMaxHP();
|
||||
if (cur_hp > max_hp) {
|
||||
cur_hp = max_hp;
|
||||
if (current_hp > max_hp) {
|
||||
current_hp = max_hp;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -2318,14 +2369,14 @@ void NPC::LevelScale() {
|
||||
base_hp += (random_level - level) * 100;
|
||||
}
|
||||
|
||||
cur_hp = max_hp;
|
||||
current_hp = max_hp;
|
||||
max_dmg += (random_level - level) * 2;
|
||||
} else {
|
||||
uint8 scale_adjust = 1;
|
||||
|
||||
base_hp += (int)(base_hp * scaling);
|
||||
max_hp += (int)(max_hp * scaling);
|
||||
cur_hp = max_hp;
|
||||
current_hp = max_hp;
|
||||
|
||||
if (max_dmg) {
|
||||
max_dmg += (int)(max_dmg * scaling / scale_adjust);
|
||||
@@ -2366,7 +2417,7 @@ void NPC::LevelScale() {
|
||||
ATK += (int)(ATK * scaling);
|
||||
base_hp += (int)(base_hp * scaling);
|
||||
max_hp += (int)(max_hp * scaling);
|
||||
cur_hp = max_hp;
|
||||
current_hp = max_hp;
|
||||
STR += (int)(STR * scaling / scale_adjust);
|
||||
STA += (int)(STA * scaling / scale_adjust);
|
||||
AGI += (int)(AGI * scaling / scale_adjust);
|
||||
@@ -2849,3 +2900,12 @@ float NPC::GetProximityMaxZ()
|
||||
{
|
||||
return proximity->max_z;
|
||||
}
|
||||
|
||||
bool NPC::IsProximitySet()
|
||||
{
|
||||
if (proximity && proximity->proximity_set) {
|
||||
return proximity->proximity_set;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
+10
-7
@@ -51,6 +51,7 @@ typedef struct {
|
||||
float min_z;
|
||||
float max_z;
|
||||
bool say;
|
||||
bool proximity_set;
|
||||
} NPCProximity;
|
||||
|
||||
struct AISpells_Struct {
|
||||
@@ -106,10 +107,11 @@ public:
|
||||
static bool SpawnZoneController();
|
||||
static int8 GetAILevel(bool iForceReRead = false);
|
||||
|
||||
NPC(const NPCType* npc_type_data, Spawn2* respawn, const glm::vec4& position, int iflymode, bool IsCorpse = false);
|
||||
NPC(const NPCType* npc_type_data, Spawn2* respawn, const glm::vec4& position, GravityBehavior iflymode, bool IsCorpse = false);
|
||||
|
||||
virtual ~NPC();
|
||||
|
||||
static NPC *SpawnNodeNPC(std::string name, std::string last_name, const glm::vec4 &position);
|
||||
static NPC *SpawnGridNodeNPC(std::string name, const glm::vec4 &position, uint32 grid_id, uint32 grid_number, uint32 pause);
|
||||
|
||||
//abstract virtual function implementations requird by base abstract class
|
||||
@@ -226,9 +228,6 @@ public:
|
||||
EmuAppearance GetGuardPointAnim() const { return guard_anim; }
|
||||
void SaveGuardPointAnim(EmuAppearance anim) { guard_anim = anim; }
|
||||
|
||||
void SetFlyMode(uint8 FlyMode){ flymode=FlyMode; }
|
||||
uint32 GetFlyMode() const { return flymode; }
|
||||
|
||||
uint8 GetPrimSkill() const { return prim_melee_type; }
|
||||
uint8 GetSecSkill() const { return sec_melee_type; }
|
||||
uint8 GetRangedSkill() const { return ranged_type; }
|
||||
@@ -312,11 +311,11 @@ public:
|
||||
void MoveTo(const glm::vec4& position, bool saveguardspot);
|
||||
void GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::vec3& location);
|
||||
|
||||
uint32 GetEquipment(uint8 material_slot) const; // returns item id
|
||||
uint32 GetEquippedItemFromTextureSlot(uint8 material_slot) const; // returns item id
|
||||
int32 GetEquipmentMaterial(uint8 material_slot) const;
|
||||
|
||||
void NextGuardPosition();
|
||||
void SaveGuardSpot(bool iClearGuardSpot = false);
|
||||
void SaveGuardSpot(const glm::vec4 &pos);
|
||||
inline bool IsGuarding() const { return(m_GuardPoint.w != 0); }
|
||||
void SaveGuardSpotCharm();
|
||||
|
||||
@@ -358,6 +357,7 @@ public:
|
||||
float GetProximityMaxY();
|
||||
float GetProximityMinZ();
|
||||
float GetProximityMaxZ();
|
||||
bool IsProximitySet();
|
||||
|
||||
ItemList itemlist; //kathgar - why is this public? Doing other things or I would check the code
|
||||
|
||||
@@ -402,7 +402,7 @@ public:
|
||||
/* Only allows players that killed corpse to loot */
|
||||
const bool HasPrivateCorpse() const { return NPCTypedata->private_corpse; }
|
||||
|
||||
const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
|
||||
virtual const bool IsUnderwaterOnly() const { return NPCTypedata->underwater; }
|
||||
const char* GetRawNPCTypeName() const { return NPCTypedata->name; }
|
||||
|
||||
void ChangeLastName(const char* in_lastname);
|
||||
@@ -466,6 +466,9 @@ public:
|
||||
|
||||
std::unique_ptr<Timer> AIautocastspell_timer;
|
||||
|
||||
virtual int GetStuckBehavior() const { return NPCTypedata_ours ? NPCTypedata_ours->stuck_behavior : NPCTypedata->stuck_behavior; }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
const NPCType* NPCTypedata;
|
||||
|
||||
@@ -100,7 +100,7 @@ void NpcScaleManager::ScaleNPC(NPC * npc)
|
||||
if (npc->GetPhR() == 0) {
|
||||
npc->ModifyNPCStat("pr", std::to_string(scale_data.physical_resist).c_str());
|
||||
}
|
||||
if (npc->GetMinDMG() == 0) {
|
||||
if (npc->GetMinDMG() == 0 && npc->GetMaxDMG() == 0) {
|
||||
int min_dmg = scale_data.min_dmg;
|
||||
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
|
||||
int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass());
|
||||
|
||||
@@ -8,15 +8,10 @@
|
||||
|
||||
IPathfinder *IPathfinder::Load(const std::string &zone) {
|
||||
struct stat statbuffer;
|
||||
std::string waypoint_path = fmt::format("maps/path/{0}.path", zone);
|
||||
std::string navmesh_path = fmt::format("maps/nav/{0}.nav", zone);
|
||||
if (stat(navmesh_path.c_str(), &statbuffer) == 0) {
|
||||
return new PathfinderNavmesh(navmesh_path);
|
||||
}
|
||||
|
||||
if (stat(waypoint_path.c_str(), &statbuffer) == 0) {
|
||||
return new PathfinderWaypoint(waypoint_path);
|
||||
}
|
||||
|
||||
return new PathfinderNull();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,50 @@
|
||||
class Client;
|
||||
class Seperator;
|
||||
|
||||
enum PathingPolyFlags
|
||||
{
|
||||
PathingNormal = 1,
|
||||
PathingWater = 2,
|
||||
PathingLava = 4,
|
||||
PathingZoneLine = 8,
|
||||
PathingPvP = 16,
|
||||
PathingSlime = 32,
|
||||
PathingIce = 64,
|
||||
PathingVWater = 128,
|
||||
PathingGeneralArea = 256,
|
||||
PathingPortal = 512,
|
||||
PathingPrefer = 1024,
|
||||
PathingDisabled = 2048,
|
||||
PathingAll = 65535,
|
||||
PathingNotDisabled = PathingAll ^ PathingDisabled
|
||||
};
|
||||
|
||||
struct PathfinderOptions
|
||||
{
|
||||
PathfinderOptions() {
|
||||
flags = PathingNotDisabled;
|
||||
smooth_path = true;
|
||||
step_size = 10.0f;
|
||||
flag_cost[0] = 1.0f;
|
||||
flag_cost[1] = 3.0f;
|
||||
flag_cost[2] = 5.0f;
|
||||
flag_cost[3] = 1.0f;
|
||||
flag_cost[4] = 2.0f;
|
||||
flag_cost[5] = 2.0f;
|
||||
flag_cost[6] = 4.0f;
|
||||
flag_cost[7] = 1.0f;
|
||||
flag_cost[8] = 0.1f;
|
||||
flag_cost[9] = 0.1f;
|
||||
offset = 3.25f;
|
||||
}
|
||||
|
||||
int flags;
|
||||
bool smooth_path;
|
||||
float step_size;
|
||||
float flag_cost[10];
|
||||
float offset;
|
||||
};
|
||||
|
||||
class IPathfinder
|
||||
{
|
||||
public:
|
||||
@@ -29,8 +73,9 @@ public:
|
||||
IPathfinder() { }
|
||||
virtual ~IPathfinder() { }
|
||||
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck) = 0;
|
||||
virtual glm::vec3 GetRandomLocation() = 0;
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags = PathingNotDisabled) = 0;
|
||||
virtual IPath FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions& opts) = 0;
|
||||
virtual glm::vec3 GetRandomLocation(const glm::vec3 &start) = 0;
|
||||
virtual void DebugCommand(Client *c, const Seperator *sep) = 0;
|
||||
|
||||
static IPathfinder *Load(const std::string &zone);
|
||||
|
||||
+279
-25
@@ -1,9 +1,9 @@
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <DetourNavMesh.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
#include "pathfinder_nav_mesh.h"
|
||||
#include <DetourCommon.h>
|
||||
#include <DetourNavMeshQuery.h>
|
||||
|
||||
#include "zone.h"
|
||||
#include "water_map.h"
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
extern Zone *zone;
|
||||
|
||||
const int MaxNavmeshNodes = 4092;
|
||||
const int MaxNavmeshNodes = 4096;
|
||||
|
||||
struct PathfinderNavmesh::Implementation
|
||||
{
|
||||
@@ -33,7 +33,7 @@ PathfinderNavmesh::~PathfinderNavmesh()
|
||||
Clear();
|
||||
}
|
||||
|
||||
IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck)
|
||||
IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags)
|
||||
{
|
||||
partial = false;
|
||||
|
||||
@@ -43,14 +43,14 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
|
||||
|
||||
if (!m_impl->query) {
|
||||
m_impl->query = dtAllocNavMeshQuery();
|
||||
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
|
||||
}
|
||||
|
||||
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
|
||||
glm::vec3 current_location(start.x, start.z, start.y);
|
||||
glm::vec3 dest_location(end.x, end.z, end.y);
|
||||
|
||||
dtQueryFilter filter;
|
||||
filter.setIncludeFlags(65535U ^ 2048);
|
||||
filter.setIncludeFlags(flags);
|
||||
filter.setAreaCost(0, 1.0f); //Normal
|
||||
filter.setAreaCost(1, 3.0f); //Water
|
||||
filter.setAreaCost(2, 5.0f); //Lava
|
||||
@@ -131,10 +131,184 @@ IPathfinder::IPath PathfinderNavmesh::FindRoute(const glm::vec3 &start, const gl
|
||||
return Route;
|
||||
}
|
||||
|
||||
glm::vec3 PathfinderNavmesh::GetRandomLocation()
|
||||
IPathfinder::IPath PathfinderNavmesh::FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions &opts)
|
||||
{
|
||||
partial = false;
|
||||
|
||||
if (!m_impl->nav_mesh) {
|
||||
return glm::vec3();
|
||||
return IPath();
|
||||
}
|
||||
|
||||
if (!m_impl->query) {
|
||||
m_impl->query = dtAllocNavMeshQuery();
|
||||
}
|
||||
|
||||
m_impl->query->init(m_impl->nav_mesh, MaxNavmeshNodes);
|
||||
glm::vec3 current_location(start.x, start.z, start.y);
|
||||
glm::vec3 dest_location(end.x, end.z, end.y);
|
||||
|
||||
dtQueryFilter filter;
|
||||
filter.setIncludeFlags(opts.flags);
|
||||
filter.setAreaCost(0, opts.flag_cost[0]); //Normal
|
||||
filter.setAreaCost(1, opts.flag_cost[1]); //Water
|
||||
filter.setAreaCost(2, opts.flag_cost[2]); //Lava
|
||||
filter.setAreaCost(4, opts.flag_cost[3]); //PvP
|
||||
filter.setAreaCost(5, opts.flag_cost[4]); //Slime
|
||||
filter.setAreaCost(6, opts.flag_cost[5]); //Ice
|
||||
filter.setAreaCost(7, opts.flag_cost[6]); //V Water (Frigid Water)
|
||||
filter.setAreaCost(8, opts.flag_cost[7]); //General Area
|
||||
filter.setAreaCost(9, opts.flag_cost[8]); //Portal
|
||||
filter.setAreaCost(10, opts.flag_cost[9]); //Prefer
|
||||
|
||||
static const int max_polys = 256;
|
||||
dtPolyRef start_ref;
|
||||
dtPolyRef end_ref;
|
||||
glm::vec3 ext(5.0f, 100.0f, 5.0f);
|
||||
|
||||
m_impl->query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0);
|
||||
m_impl->query->findNearestPoly(&dest_location[0], &ext[0], &filter, &end_ref, 0);
|
||||
|
||||
if (!start_ref || !end_ref) {
|
||||
return IPath();
|
||||
}
|
||||
|
||||
int npoly = 0;
|
||||
dtPolyRef path[max_polys] = { 0 };
|
||||
m_impl->query->findPath(start_ref, end_ref, ¤t_location[0], &dest_location[0], &filter, path, &npoly, max_polys);
|
||||
|
||||
if (npoly) {
|
||||
glm::vec3 epos = dest_location;
|
||||
if (path[npoly - 1] != end_ref) {
|
||||
m_impl->query->closestPointOnPoly(path[npoly - 1], &dest_location[0], &epos[0], 0);
|
||||
partial = true;
|
||||
|
||||
auto dist = DistanceSquared(epos, current_location);
|
||||
if (dist < 10000.0f) {
|
||||
stuck = true;
|
||||
}
|
||||
}
|
||||
|
||||
int n_straight_polys;
|
||||
glm::vec3 straight_path[max_polys];
|
||||
unsigned char straight_path_flags[max_polys];
|
||||
dtPolyRef straight_path_polys[max_polys];
|
||||
|
||||
auto status = m_impl->query->findStraightPath(¤t_location[0], &epos[0], path, npoly,
|
||||
(float*)&straight_path[0], straight_path_flags,
|
||||
straight_path_polys, &n_straight_polys, 2048, DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS);
|
||||
|
||||
if (dtStatusFailed(status)) {
|
||||
return IPath();
|
||||
}
|
||||
|
||||
if (n_straight_polys) {
|
||||
if (opts.smooth_path) {
|
||||
IPath Route;
|
||||
|
||||
//Add the first point
|
||||
{
|
||||
auto &flag = straight_path_flags[0];
|
||||
if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) {
|
||||
auto &p = straight_path[0];
|
||||
|
||||
Route.push_back(glm::vec3(p.x, p.z, p.y));
|
||||
}
|
||||
else {
|
||||
auto &p = straight_path[0];
|
||||
|
||||
float h = 0.0f;
|
||||
if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, p, &h))) {
|
||||
p.y = h + opts.offset;
|
||||
}
|
||||
|
||||
Route.push_back(glm::vec3(p.x, p.z, p.y));
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_straight_polys - 1; ++i)
|
||||
{
|
||||
auto &flag = straight_path_flags[i];
|
||||
|
||||
if (flag & DT_STRAIGHTPATH_OFFMESH_CONNECTION) {
|
||||
auto &poly = straight_path_polys[i];
|
||||
|
||||
auto &p2 = straight_path[i + 1];
|
||||
glm::vec3 node(p2.x, p2.z, p2.y);
|
||||
Route.push_back(node);
|
||||
|
||||
unsigned short pflag = 0;
|
||||
if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &pflag))) {
|
||||
if (pflag & 512) {
|
||||
Route.push_back(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto &p1 = straight_path[i];
|
||||
auto &p2 = straight_path[i + 1];
|
||||
auto dist = glm::distance(p1, p2);
|
||||
auto dir = glm::normalize(p2 - p1);
|
||||
float total = 0.0f;
|
||||
glm::vec3 previous_pt = p1;
|
||||
|
||||
while (total < dist) {
|
||||
glm::vec3 current_pt;
|
||||
float dist_to_move = opts.step_size;
|
||||
float ff = opts.step_size / 2.0f;
|
||||
|
||||
if (total + dist_to_move + ff >= dist) {
|
||||
current_pt = p2;
|
||||
total = dist;
|
||||
}
|
||||
else {
|
||||
total += dist_to_move;
|
||||
current_pt = p1 + dir * total;
|
||||
}
|
||||
|
||||
float h = 0.0f;
|
||||
if (dtStatusSucceed(GetPolyHeightOnPath(path, npoly, current_pt, &h))) {
|
||||
current_pt.y = h + opts.offset;
|
||||
}
|
||||
|
||||
Route.push_back(glm::vec3(current_pt.x, current_pt.z, current_pt.y));
|
||||
previous_pt = current_pt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Route;
|
||||
}
|
||||
else {
|
||||
IPath Route;
|
||||
for (int i = 0; i < n_straight_polys; ++i)
|
||||
{
|
||||
auto ¤t = straight_path[i];
|
||||
glm::vec3 node(current.x, current.z, current.y);
|
||||
Route.push_back(node);
|
||||
|
||||
unsigned short flag = 0;
|
||||
if (dtStatusSucceed(m_impl->nav_mesh->getPolyFlags(straight_path_polys[i], &flag))) {
|
||||
if (flag & 512) {
|
||||
Route.push_back(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Route;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IPath();
|
||||
}
|
||||
|
||||
glm::vec3 PathfinderNavmesh::GetRandomLocation(const glm::vec3 &start)
|
||||
{
|
||||
if (start.x == 0.0f && start.y == 0.0)
|
||||
return glm::vec3(0.f);
|
||||
|
||||
if (!m_impl->nav_mesh) {
|
||||
return glm::vec3(0.f);
|
||||
}
|
||||
|
||||
if (!m_impl->query) {
|
||||
@@ -143,19 +317,38 @@ glm::vec3 PathfinderNavmesh::GetRandomLocation()
|
||||
}
|
||||
|
||||
dtQueryFilter filter;
|
||||
filter.setIncludeFlags(65535U);
|
||||
filter.setIncludeFlags(65535U ^ 2048);
|
||||
filter.setAreaCost(0, 1.0f); //Normal
|
||||
filter.setAreaCost(1, 3.0f); //Water
|
||||
filter.setAreaCost(2, 5.0f); //Lava
|
||||
filter.setAreaCost(4, 1.0f); //PvP
|
||||
filter.setAreaCost(5, 2.0f); //Slime
|
||||
filter.setAreaCost(6, 2.0f); //Ice
|
||||
filter.setAreaCost(7, 4.0f); //V Water (Frigid Water)
|
||||
filter.setAreaCost(8, 1.0f); //General Area
|
||||
filter.setAreaCost(9, 0.1f); //Portal
|
||||
filter.setAreaCost(10, 0.1f); //Prefer
|
||||
|
||||
dtPolyRef randomRef;
|
||||
float point[3];
|
||||
|
||||
if (dtStatusSucceed(m_impl->query->findRandomPoint(&filter, []() {
|
||||
return (float)zone->random.Real(0.0, 1.0);
|
||||
}, &randomRef, point)))
|
||||
dtPolyRef start_ref;
|
||||
glm::vec3 current_location(start.x, start.z, start.y);
|
||||
glm::vec3 ext(5.0f, 100.0f, 5.0f);
|
||||
|
||||
m_impl->query->findNearestPoly(¤t_location[0], &ext[0], &filter, &start_ref, 0);
|
||||
|
||||
if (!start_ref)
|
||||
{
|
||||
return glm::vec3(0.f);
|
||||
}
|
||||
|
||||
if (dtStatusSucceed(m_impl->query->findRandomPointAroundCircle(start_ref, ¤t_location[0], 100.f, &filter, []() { return (float)zone->random.Real(0.0, 1.0); }, &randomRef, point)))
|
||||
{
|
||||
return glm::vec3(point[0], point[2], point[1]);
|
||||
}
|
||||
|
||||
return glm::vec3();
|
||||
return glm::vec3(0.f);
|
||||
}
|
||||
|
||||
void PathfinderNavmesh::DebugCommand(Client *c, const Seperator *sep)
|
||||
@@ -288,24 +481,85 @@ void PathfinderNavmesh::Load(const std::string &path)
|
||||
|
||||
void PathfinderNavmesh::ShowPath(Client * c, const glm::vec3 &start, const glm::vec3 &end)
|
||||
{
|
||||
auto &list = entity_list.GetNPCList();
|
||||
|
||||
for (auto &iter : list) {
|
||||
auto npc = iter.second;
|
||||
auto name = npc->GetName();
|
||||
|
||||
if (strstr(name, "PathNode") != nullptr) {
|
||||
npc->Depop();
|
||||
}
|
||||
}
|
||||
|
||||
PathfinderOptions opts;
|
||||
opts.smooth_path = true;
|
||||
opts.step_size = RuleR(Pathing, NavmeshStepSize);
|
||||
bool partial = false;
|
||||
bool stuck = false;
|
||||
auto path = FindRoute(start, end, partial, stuck);
|
||||
std::vector<FindPerson_Point> points;
|
||||
auto path = FindPath(start, end, partial, stuck, opts);
|
||||
|
||||
if (!partial) {
|
||||
FindPerson_Point p;
|
||||
for (auto &node : path)
|
||||
for (auto &node : path) {
|
||||
if (!node.teleport) {
|
||||
NPC::SpawnNPC("PathNode 2253 1 0 1 2 1", glm::vec4(node.pos, 1.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dtStatus PathfinderNavmesh::GetPolyHeightNoConnections(dtPolyRef ref, const float *pos, float *height) const
|
||||
{
|
||||
auto *m_nav = m_impl->nav_mesh;
|
||||
|
||||
if (!m_nav) {
|
||||
return DT_FAILURE;
|
||||
}
|
||||
|
||||
const dtMeshTile* tile = 0;
|
||||
const dtPoly* poly = 0;
|
||||
if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) {
|
||||
return DT_FAILURE | DT_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (poly->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) {
|
||||
const unsigned int ip = (unsigned int)(poly - tile->polys);
|
||||
const dtPolyDetail* pd = &tile->detailMeshes[ip];
|
||||
for (int j = 0; j < pd->triCount; ++j)
|
||||
{
|
||||
if (!node.teleport) {
|
||||
p.x = node.pos.x;
|
||||
p.y = node.pos.y;
|
||||
p.z = node.pos.z;
|
||||
|
||||
points.push_back(p);
|
||||
const unsigned char* t = &tile->detailTris[(pd->triBase + j) * 4];
|
||||
const float* v[3];
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
if (t[k] < poly->vertCount)
|
||||
v[k] = &tile->verts[poly->verts[t[k]] * 3];
|
||||
else
|
||||
v[k] = &tile->detailVerts[(pd->vertBase + (t[k] - poly->vertCount)) * 3];
|
||||
}
|
||||
float h;
|
||||
if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h))
|
||||
{
|
||||
if (height)
|
||||
*height = h;
|
||||
return DT_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c->SendPathPacket(points);
|
||||
return DT_FAILURE | DT_INVALID_PARAM;
|
||||
}
|
||||
|
||||
dtStatus PathfinderNavmesh::GetPolyHeightOnPath(const dtPolyRef *path, const int path_len, const glm::vec3 &pos, float *h) const
|
||||
{
|
||||
if (!path || !path_len) {
|
||||
return DT_FAILURE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < path_len; ++i) {
|
||||
dtPolyRef ref = path[i];
|
||||
|
||||
if (dtStatusSucceed(GetPolyHeightNoConnections(ref, &pos[0], h))) {
|
||||
return DT_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return DT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "pathfinder_interface.h"
|
||||
#include <string>
|
||||
#include <DetourNavMesh.h>
|
||||
|
||||
class PathfinderNavmesh : public IPathfinder
|
||||
{
|
||||
@@ -9,15 +10,18 @@ public:
|
||||
PathfinderNavmesh(const std::string &path);
|
||||
virtual ~PathfinderNavmesh();
|
||||
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck);
|
||||
virtual glm::vec3 GetRandomLocation();
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags = PathingNotDisabled);
|
||||
virtual IPath FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions& opts);
|
||||
virtual glm::vec3 GetRandomLocation(const glm::vec3 &start);
|
||||
virtual void DebugCommand(Client *c, const Seperator *sep);
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
void Load(const std::string &path);
|
||||
void ShowPath(Client *c, const glm::vec3 &start, const glm::vec3 &end);
|
||||
dtStatus GetPolyHeightNoConnections(dtPolyRef ref, const float *pos, float *height) const;
|
||||
dtStatus GetPolyHeightOnPath(const dtPolyRef *path, const int path_len, const glm::vec3 &pos, float *h) const;
|
||||
|
||||
struct Implementation;
|
||||
std::unique_ptr<Implementation> m_impl;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "pathfinder_null.h"
|
||||
|
||||
IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck)
|
||||
IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags)
|
||||
{
|
||||
partial = false;
|
||||
stuck = false;
|
||||
@@ -10,7 +10,17 @@ IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::
|
||||
return ret;
|
||||
}
|
||||
|
||||
glm::vec3 PathfinderNull::GetRandomLocation()
|
||||
IPathfinder::IPath PathfinderNull::FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions &opts)
|
||||
{
|
||||
return glm::vec3();
|
||||
partial = false;
|
||||
stuck = false;
|
||||
IPath ret;
|
||||
ret.push_back(start);
|
||||
ret.push_back(end);
|
||||
return ret;
|
||||
}
|
||||
|
||||
glm::vec3 PathfinderNull::GetRandomLocation(const glm::vec3 &start)
|
||||
{
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ public:
|
||||
PathfinderNull() { }
|
||||
virtual ~PathfinderNull() { }
|
||||
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck);
|
||||
virtual glm::vec3 GetRandomLocation();
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags = PathingNotDisabled);
|
||||
virtual IPath FindPath(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, const PathfinderOptions& opts);
|
||||
virtual glm::vec3 GetRandomLocation(const glm::vec3 &start);
|
||||
virtual void DebugCommand(Client *c, const Seperator *sep) { }
|
||||
};
|
||||
};
|
||||
|
||||
@@ -114,7 +114,7 @@ PathfinderWaypoint::~PathfinderWaypoint()
|
||||
{
|
||||
}
|
||||
|
||||
IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck)
|
||||
IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags)
|
||||
{
|
||||
stuck = false;
|
||||
partial = false;
|
||||
@@ -184,7 +184,7 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g
|
||||
return IPath();
|
||||
}
|
||||
|
||||
glm::vec3 PathfinderWaypoint::GetRandomLocation()
|
||||
glm::vec3 PathfinderWaypoint::GetRandomLocation(const glm::vec3 &start)
|
||||
{
|
||||
if (m_impl->Nodes.size() > 0) {
|
||||
auto idx = zone->random.Int(0, (int)m_impl->Nodes.size() - 1);
|
||||
@@ -529,7 +529,7 @@ void PathfinderWaypoint::ShowNode(const Node &n) {
|
||||
|
||||
sprintf(npc_type->name, "%s", DigitToWord(n.id).c_str());
|
||||
sprintf(npc_type->lastname, "%i", n.id);
|
||||
npc_type->cur_hp = 4000000;
|
||||
npc_type->current_hp = 4000000;
|
||||
npc_type->max_hp = 4000000;
|
||||
npc_type->race = 2254;
|
||||
npc_type->gender = 2;
|
||||
@@ -557,7 +557,7 @@ void PathfinderWaypoint::ShowNode(const Node &n) {
|
||||
|
||||
npc_type->findable = 1;
|
||||
auto position = glm::vec4(n.v.x, n.v.y, n.v.z, 0.0f);
|
||||
auto npc = new NPC(npc_type, nullptr, position, FlyMode1);
|
||||
auto npc = new NPC(npc_type, nullptr, position, GravityBehavior::Flying);
|
||||
npc->GiveNPCTypeData(npc_type);
|
||||
|
||||
entity_list.AddNPC(npc, true, true);
|
||||
|
||||
@@ -11,8 +11,8 @@ public:
|
||||
PathfinderWaypoint(const std::string &path);
|
||||
virtual ~PathfinderWaypoint();
|
||||
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck);
|
||||
virtual glm::vec3 GetRandomLocation();
|
||||
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end, bool &partial, bool &stuck, int flags = PathingNotDisabled);
|
||||
virtual glm::vec3 GetRandomLocation(const glm::vec3 &start);
|
||||
virtual void DebugCommand(Client *c, const Seperator *sep);
|
||||
|
||||
private:
|
||||
@@ -28,4 +28,4 @@ private:
|
||||
|
||||
struct Implementation;
|
||||
std::unique_ptr<Implementation> m_impl;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -7,207 +7,6 @@
|
||||
|
||||
extern Zone *zone;
|
||||
|
||||
void AdjustRoute(std::list<IPathfinder::IPathNode> &nodes, int flymode, float offset) {
|
||||
if (!zone->HasMap() || !zone->HasWaterMap()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &node : nodes) {
|
||||
if (flymode == 0 || !zone->watermap->InLiquid(node.pos)) {
|
||||
auto best_z = zone->zonemap->FindBestZ(node.pos, nullptr);
|
||||
if (best_z != BEST_Z_INVALID) {
|
||||
node.pos.z = best_z + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged, bool &NodeReached)
|
||||
{
|
||||
glm::vec3 To(ToX, ToY, ToZ);
|
||||
if (Speed <= 0) {
|
||||
return To;
|
||||
}
|
||||
|
||||
glm::vec3 From(GetX(), GetY(), GetZ());
|
||||
|
||||
if (DistanceSquared(To, From) < 1.0f) {
|
||||
WaypointChanged = false;
|
||||
NodeReached = true;
|
||||
Route.clear();
|
||||
return To;
|
||||
}
|
||||
|
||||
if (Route.empty()) {
|
||||
bool partial = false;
|
||||
bool stuck = false;
|
||||
Route = zone->pathing->FindRoute(From, To, partial, stuck);
|
||||
AdjustRoute(Route, flymode, GetZOffset());
|
||||
|
||||
PathingDestination = To;
|
||||
WaypointChanged = true;
|
||||
NodeReached = false;
|
||||
if (stuck) {
|
||||
return HandleStuckPath(To, From);
|
||||
}
|
||||
|
||||
if (Route.empty()) {
|
||||
return To;
|
||||
}
|
||||
else {
|
||||
return (*Route.begin()).pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (PathRecalcTimer->Check()) {
|
||||
bool SameDestination = DistanceSquared(To, PathingDestination) < 100.0f;
|
||||
if (!SameDestination) {
|
||||
//We had a route but our target position moved too much
|
||||
bool partial = false;
|
||||
bool stuck = false;
|
||||
Route = zone->pathing->FindRoute(From, To, partial, stuck);
|
||||
AdjustRoute(Route, flymode, GetZOffset());
|
||||
|
||||
PathingDestination = To;
|
||||
WaypointChanged = true;
|
||||
NodeReached = false;
|
||||
|
||||
if (stuck) {
|
||||
return HandleStuckPath(To, From);
|
||||
}
|
||||
|
||||
if (Route.empty()) {
|
||||
return To;
|
||||
}
|
||||
else {
|
||||
return (*Route.begin()).pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsRooted()) {
|
||||
bool AtPrevNode = DistanceSquared(From, PathingLastPosition) < 1.0f;
|
||||
if (AtPrevNode) {
|
||||
PathingLoopCount++;
|
||||
auto front = (*Route.begin()).pos;
|
||||
|
||||
if (PathingLoopCount > 5) {
|
||||
Teleport(front);
|
||||
SendPosition();
|
||||
Route.pop_front();
|
||||
|
||||
WaypointChanged = true;
|
||||
NodeReached = true;
|
||||
PathingLoopCount = 0;
|
||||
}
|
||||
|
||||
return front;
|
||||
}
|
||||
else {
|
||||
PathingLastPosition = From;
|
||||
PathingLoopCount = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PathingLastPosition = From;
|
||||
PathingLoopCount = 0;
|
||||
}
|
||||
|
||||
bool AtNextNode = false;
|
||||
if (flymode == 1) {
|
||||
AtNextNode = DistanceSquared(From, (*Route.begin()).pos) < 4.0f;
|
||||
}
|
||||
else {
|
||||
float z_dist = From.z - (*Route.begin()).pos.z;
|
||||
z_dist *= z_dist;
|
||||
AtNextNode = DistanceSquaredNoZ(From, (*Route.begin()).pos) < 4.0f && z_dist < 25.0f;
|
||||
}
|
||||
|
||||
if (AtNextNode) {
|
||||
WaypointChanged = false;
|
||||
NodeReached = true;
|
||||
|
||||
Route.pop_front();
|
||||
|
||||
if (Route.empty()) {
|
||||
bool partial = false;
|
||||
bool stuck = false;
|
||||
Route = zone->pathing->FindRoute(From, To, partial, stuck);
|
||||
AdjustRoute(Route, flymode, GetZOffset());
|
||||
PathingDestination = To;
|
||||
WaypointChanged = true;
|
||||
|
||||
if (stuck) {
|
||||
return HandleStuckPath(To, From);
|
||||
}
|
||||
|
||||
if(Route.empty()) {
|
||||
return To;
|
||||
}
|
||||
else {
|
||||
return (*Route.begin()).pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto node = *Route.begin();
|
||||
if (node.teleport) {
|
||||
Route.pop_front();
|
||||
|
||||
if (Route.empty()) {
|
||||
return To;
|
||||
}
|
||||
|
||||
auto nextNode = *Route.begin();
|
||||
|
||||
Teleport(nextNode.pos);
|
||||
|
||||
Route.pop_front();
|
||||
|
||||
if (Route.empty()) {
|
||||
return To;
|
||||
}
|
||||
|
||||
return (*Route.begin()).pos;
|
||||
}
|
||||
|
||||
return node.pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
WaypointChanged = false;
|
||||
NodeReached = false;
|
||||
return (*Route.begin()).pos;
|
||||
}
|
||||
}
|
||||
|
||||
return To;
|
||||
}
|
||||
|
||||
glm::vec3 Mob::HandleStuckPath(const glm::vec3 &To, const glm::vec3 &From)
|
||||
{
|
||||
bool partial = false;
|
||||
bool stuck = false;
|
||||
auto r = zone->pathing->FindRoute(To, From, partial, stuck);
|
||||
Route.clear();
|
||||
|
||||
if (r.size() < 1) {
|
||||
Teleport(To);
|
||||
return To;
|
||||
}
|
||||
|
||||
auto iter = r.rbegin();
|
||||
auto final_node = (*iter);
|
||||
Teleport(final_node.pos);
|
||||
|
||||
if (r.size() < 2) {
|
||||
return final_node.pos;
|
||||
}
|
||||
else {
|
||||
iter++;
|
||||
return (*iter).pos;
|
||||
}
|
||||
}
|
||||
|
||||
void CullPoints(std::vector<FindPerson_Point> &points) {
|
||||
if (!zone->HasMap()) {
|
||||
return;
|
||||
|
||||
+265
-211
@@ -6126,6 +6126,59 @@ XS(XS_Client_Popup2) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Client_SetPrimaryWeaponOrnamentation); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_SetPrimaryWeaponOrnamentation)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2) {
|
||||
Perl_croak(aTHX_ "Usage: Client::SetPrimaryWeaponOrnamentation(THIS, model_id)");
|
||||
}
|
||||
{
|
||||
Client *THIS;
|
||||
uint32 model_id = (uint32) SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Client")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
THIS = INT2PTR(Client *, tmp);
|
||||
}
|
||||
else {
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
}
|
||||
if (THIS == nullptr) {
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
}
|
||||
|
||||
THIS->SetPrimaryWeaponOrnamentation(model_id);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Client_SetSecondaryWeaponOrnamentation); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Client_SetSecondaryWeaponOrnamentation)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 2) {
|
||||
Perl_croak(aTHX_ "Usage: Client::SetSecondaryWeaponOrnamentation(THIS, model_id)");
|
||||
}
|
||||
{
|
||||
Client *THIS;
|
||||
uint32 model_id = (uint32) SvUV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Client")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
THIS = INT2PTR(Client *, tmp);
|
||||
}
|
||||
else {
|
||||
Perl_croak(aTHX_ "THIS is not of type Client");
|
||||
}
|
||||
if (THIS == nullptr) {
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
}
|
||||
|
||||
THIS->SetSecondaryWeaponOrnamentation(model_id);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@@ -6147,240 +6200,241 @@ XS(boot_Client) {
|
||||
|
||||
XS_VERSION_BOOTCHECK;
|
||||
|
||||
newXSproto(strcpy(buf, "SendSound"), XS_Client_SendSound, file, "$");
|
||||
newXSproto(strcpy(buf, "Save"), XS_Client_Save, file, "$$");
|
||||
newXSproto(strcpy(buf, "SaveBackup"), XS_Client_SaveBackup, file, "$");
|
||||
newXSproto(strcpy(buf, "AccountID"), XS_Client_AccountID, file, "$");
|
||||
newXSproto(strcpy(buf, "AccountName"), XS_Client_AccountName, file, "$");
|
||||
newXSproto(strcpy(buf, "AddAAPoints"), XS_Client_AddAAPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddAlternateCurrencyValue"), XS_Client_AddAlternateCurrencyValue, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddCrystals"), XS_Client_AddCrystals, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddEXP"), XS_Client_AddEXP, file, "$$;$$");
|
||||
newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "AddMoneyToPP"), XS_Client_AddMoneyToPP, file, "$$$$$$");
|
||||
newXSproto(strcpy(buf, "AddPVPPoints"), XS_Client_AddPVPPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddSkill"), XS_Client_AddSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "Admin"), XS_Client_Admin, file, "$");
|
||||
newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "AssignToInstance"), XS_Client_AssignToInstance, file, "$$");
|
||||
newXSproto(strcpy(buf, "AutoSplitEnabled"), XS_Client_AutoSplitEnabled, file, "$");
|
||||
newXSproto(strcpy(buf, "BreakInvis"), XS_Client_BreakInvis, file, "$");
|
||||
newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$");
|
||||
newXSproto(strcpy(buf, "CalcPriceMod"), XS_Client_CalcPriceMod, file, "$;$$");
|
||||
newXSproto(strcpy(buf, "CanHaveSkill"), XS_Client_CanHaveSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "ChangeLastName"), XS_Client_ChangeLastName, file, "$$");
|
||||
newXSproto(strcpy(buf, "CharacterID"), XS_Client_CharacterID, file, "$");
|
||||
newXSproto(strcpy(buf, "CheckIncreaseSkill"), XS_Client_CheckIncreaseSkill, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "CheckSpecializeIncrease"), XS_Client_CheckSpecializeIncrease, file, "$$");
|
||||
newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$");
|
||||
newXSproto(strcpy(buf, "ClearZoneFlag"), XS_Client_ClearZoneFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "Connected"), XS_Client_Connected, file, "$");
|
||||
newXSproto(strcpy(buf, "InZone"), XS_Client_InZone, file, "$");
|
||||
newXSproto(strcpy(buf, "Kick"), XS_Client_Kick, file, "$");
|
||||
newXSproto(strcpy(buf, "DecreaseByID"), XS_Client_DecreaseByID, file, "$$$");
|
||||
newXSproto(strcpy(buf, "DeleteItemInInventory"), XS_Client_DeleteItemInInventory, file, "$$;$$");
|
||||
newXSproto(strcpy(buf, "Disconnect"), XS_Client_Disconnect, file, "$");
|
||||
newXSproto(strcpy(buf, "IsLD"), XS_Client_IsLD, file, "$");
|
||||
newXSproto(strcpy(buf, "WorldKick"), XS_Client_WorldKick, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAnon"), XS_Client_GetAnon, file, "$");
|
||||
newXSproto(strcpy(buf, "DropItem"), XS_Client_DropItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "Duck"), XS_Client_Duck, file, "$");
|
||||
newXSproto(strcpy(buf, "Stand"), XS_Client_Stand, file, "$");
|
||||
newXSproto(strcpy(buf, "SetGM"), XS_Client_SetGM, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetPVP"), XS_Client_SetPVP, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetPVP"), XS_Client_GetPVP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetGM"), XS_Client_GetGM, file, "$");
|
||||
newXSproto(strcpy(buf, "SetBaseClass"), XS_Client_SetBaseClass, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBaseRace"), XS_Client_SetBaseRace, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBaseGender"), XS_Client_SetBaseGender, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBaseFace"), XS_Client_GetBaseFace, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLanguageSkill"), XS_Client_GetLanguageSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLastName"), XS_Client_GetLastName, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNPointsTheme"), XS_Client_GetLDoNPointsTheme, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseSTR"), XS_Client_GetBaseSTR, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseSTA"), XS_Client_GetBaseSTA, file, "$");
|
||||
newXSproto(strcpy(buf, "Escape"), XS_Client_Escape, file, "$");
|
||||
newXSproto(strcpy(buf, "ExpeditionMessage"), XS_Client_ExpeditionMessage, file, "$$$");
|
||||
newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$");
|
||||
newXSproto(strcpy(buf, "ForageItem"), XS_Client_ForageItem, file, "$");
|
||||
newXSproto(strcpy(buf, "Freeze"), XS_Client_Freeze, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAAPoints"), XS_Client_GetAAPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAccountFlag"), XS_Client_GetAccountFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAggroCount"), XS_Client_GetAggroCount, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAllMoney"), XS_Client_GetAllMoney, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAnon"), XS_Client_GetAnon, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAugmentAt"), XS_Client_GetAugmentAt, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetAugmentIDAt"), XS_Client_GetAugmentIDAt, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetBaseAGI"), XS_Client_GetBaseAGI, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseCHA"), XS_Client_GetBaseCHA, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseDEX"), XS_Client_GetBaseDEX, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseFace"), XS_Client_GetBaseFace, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseINT"), XS_Client_GetBaseINT, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseAGI"), XS_Client_GetBaseAGI, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseSTA"), XS_Client_GetBaseSTA, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseSTR"), XS_Client_GetBaseSTR, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBaseWIS"), XS_Client_GetBaseWIS, file, "$");
|
||||
newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$");
|
||||
newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$");
|
||||
newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddEXP"), XS_Client_AddEXP, file, "$$;$$");
|
||||
newXSproto(strcpy(buf, "SetEXP"), XS_Client_SetEXP, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$$");
|
||||
newXSproto(strcpy(buf, "GetBecomeNPCLevel"), XS_Client_GetBecomeNPCLevel, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBindHeading"), XS_Client_GetBindHeading, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBindX"), XS_Client_GetBindX, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBindY"), XS_Client_GetBindY, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBindZ"), XS_Client_GetBindZ, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBindHeading"), XS_Client_GetBindHeading, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetBindZoneID"), XS_Client_GetBindZoneID, file, "$$");
|
||||
newXSproto(strcpy(buf, "MovePC"), XS_Client_MovePC, file, "$$$$$$");
|
||||
newXSproto(strcpy(buf, "MovePCInstance"), XS_Client_MovePCInstance, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "ChangeLastName"), XS_Client_ChangeLastName, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetFactionLevel"), XS_Client_GetFactionLevel, file, "$$$$$$$$");
|
||||
newXSproto(strcpy(buf, "SetFactionLevel"), XS_Client_SetFactionLevel, file, "$$$$$$");
|
||||
newXSproto(strcpy(buf, "SetFactionLevel2"), XS_Client_SetFactionLevel2, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "GetRawItemAC"), XS_Client_GetRawItemAC, file, "$");
|
||||
newXSproto(strcpy(buf, "AccountID"), XS_Client_AccountID, file, "$");
|
||||
newXSproto(strcpy(buf, "AccountName"), XS_Client_AccountName, file, "$");
|
||||
newXSproto(strcpy(buf, "Admin"), XS_Client_Admin, file, "$");
|
||||
newXSproto(strcpy(buf, "CharacterID"), XS_Client_CharacterID, file, "$");
|
||||
newXSproto(strcpy(buf, "UpdateAdmin"), XS_Client_UpdateAdmin, file, "$;$");
|
||||
newXSproto(strcpy(buf, "UpdateWho"), XS_Client_UpdateWho, file, "$;$");
|
||||
newXSproto(strcpy(buf, "GuildRank"), XS_Client_GuildRank, file, "$");
|
||||
newXSproto(strcpy(buf, "GuildID"), XS_Client_GuildID, file, "$");
|
||||
newXSproto(strcpy(buf, "GetFace"), XS_Client_GetFace, file, "$");
|
||||
newXSproto(strcpy(buf, "TakeMoneyFromPP"), XS_Client_TakeMoneyFromPP, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "AddMoneyToPP"), XS_Client_AddMoneyToPP, file, "$$$$$$");
|
||||
newXSproto(strcpy(buf, "TGB"), XS_Client_TGB, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSkillPoints"), XS_Client_GetSkillPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "SetSkillPoints"), XS_Client_SetSkillPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "IncreaseSkill"), XS_Client_IncreaseSkill, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "IncreaseLanguageSkill"), XS_Client_IncreaseLanguageSkill, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "GetSkill"), XS_Client_GetSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetRawSkill"), XS_Client_GetRawSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "HasSkill"), XS_Client_HasSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "CanHaveSkill"), XS_Client_CanHaveSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetSkill"), XS_Client_SetSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddSkill"), XS_Client_AddSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "CheckSpecializeIncrease"), XS_Client_CheckSpecializeIncrease, file, "$$");
|
||||
newXSproto(strcpy(buf, "CheckIncreaseSkill"), XS_Client_CheckIncreaseSkill, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "SetLanguageSkill"), XS_Client_SetLanguageSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "MaxSkill"), XS_Client_MaxSkill, file, "$$;$$");
|
||||
newXSproto(strcpy(buf, "GMKill"), XS_Client_GMKill, file, "$");
|
||||
newXSproto(strcpy(buf, "IsMedding"), XS_Client_IsMedding, file, "$");
|
||||
newXSproto(strcpy(buf, "GetDuelTarget"), XS_Client_GetDuelTarget, file, "$");
|
||||
newXSproto(strcpy(buf, "IsDueling"), XS_Client_IsDueling, file, "$");
|
||||
newXSproto(strcpy(buf, "SetDuelTarget"), XS_Client_SetDuelTarget, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetDueling"), XS_Client_SetDueling, file, "$$");
|
||||
newXSproto(strcpy(buf, "ResetAA"), XS_Client_ResetAA, file, "$");
|
||||
newXSproto(strcpy(buf, "MemSpell"), XS_Client_MemSpell, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "UnmemSpell"), XS_Client_UnmemSpell, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "UnmemSpellBySpellID"), XS_Client_UnmemSpellBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "UnmemSpellAll"), XS_Client_UnmemSpellAll, file, "$;$");
|
||||
newXSproto(strcpy(buf, "ScribeSpell"), XS_Client_ScribeSpell, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "UnscribeSpell"), XS_Client_UnscribeSpell, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "UnscribeSpellAll"), XS_Client_UnscribeSpellAll, file, "$;$");
|
||||
newXSproto(strcpy(buf, "TrainDiscBySpellID"), XS_Client_TrainDiscBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetDiscSlotBySpellID"), XS_Client_GetDiscSlotBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "UntrainDisc"), XS_Client_UntrainDisc, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "UntrainDiscAll"), XS_Client_UntrainDiscAll, file, "$;$");
|
||||
newXSproto(strcpy(buf, "IsSitting"), XS_Client_IsSitting, file, "$");
|
||||
newXSproto(strcpy(buf, "IsBecomeNPC"), XS_Client_IsBecomeNPC, file, "$");
|
||||
newXSproto(strcpy(buf, "GetBecomeNPCLevel"), XS_Client_GetBecomeNPCLevel, file, "$");
|
||||
newXSproto(strcpy(buf, "SetBecomeNPC"), XS_Client_SetBecomeNPC, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBecomeNPCLevel"), XS_Client_SetBecomeNPCLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetFeigned"), XS_Client_SetFeigned, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetFeigned"), XS_Client_GetFeigned, file, "$");
|
||||
newXSproto(strcpy(buf, "AutoSplitEnabled"), XS_Client_AutoSplitEnabled, file, "$");
|
||||
newXSproto(strcpy(buf, "SetHorseId"), XS_Client_SetHorseId, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetHorseId"), XS_Client_GetHorseId, file, "$");
|
||||
newXSproto(strcpy(buf, "NukeItem"), XS_Client_NukeItem, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "SetTint"), XS_Client_SetTint, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetMaterial"), XS_Client_SetMaterial, file, "$$$");
|
||||
newXSproto(strcpy(buf, "Undye"), XS_Client_Undye, file, "$");
|
||||
newXSproto(strcpy(buf, "GetItemIDAt"), XS_Client_GetItemIDAt, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAugmentIDAt"), XS_Client_GetAugmentIDAt, file, "$$$");
|
||||
newXSproto(strcpy(buf, "DeleteItemInInventory"), XS_Client_DeleteItemInInventory, file, "$$;$$");
|
||||
newXSproto(strcpy(buf, "SummonItem"), XS_Client_SummonItem, file, "$$;$$$$$$$$");
|
||||
newXSproto(strcpy(buf, "SetStats"), XS_Client_SetStats, file, "$$$");
|
||||
newXSproto(strcpy(buf, "IncStats"), XS_Client_IncStats, file, "$$$");
|
||||
newXSproto(strcpy(buf, "DropItem"), XS_Client_DropItem, file, "$$");
|
||||
newXSproto(strcpy(buf, "BreakInvis"), XS_Client_BreakInvis, file, "$");
|
||||
newXSproto(strcpy(buf, "GetGroup"), XS_Client_GetGroup, file, "$");
|
||||
newXSproto(strcpy(buf, "LeaveGroup"), XS_Client_LeaveGroup, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRaid"), XS_Client_GetRaid, file, "$");
|
||||
newXSproto(strcpy(buf, "IsGrouped"), XS_Client_IsGrouped, file, "$");
|
||||
newXSproto(strcpy(buf, "IsRaidGrouped"), XS_Client_IsRaidGrouped, file, "$");
|
||||
newXSproto(strcpy(buf, "Hungry"), XS_Client_Hungry, file, "$");
|
||||
newXSproto(strcpy(buf, "Thirsty"), XS_Client_Thirsty, file, "$");
|
||||
newXSproto(strcpy(buf, "GetInstrumentMod"), XS_Client_GetInstrumentMod, file, "$$");
|
||||
newXSproto(strcpy(buf, "DecreaseByID"), XS_Client_DecreaseByID, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SlotConvert2"), XS_Client_SlotConvert2, file, "$$");
|
||||
newXSproto(strcpy(buf, "Escape"), XS_Client_Escape, file, "$");
|
||||
newXSproto(strcpy(buf, "RemoveNoRent"), XS_Client_RemoveNoRent, file, "$");
|
||||
newXSproto(strcpy(buf, "GoFish"), XS_Client_GoFish, file, "$");
|
||||
newXSproto(strcpy(buf, "ForageItem"), XS_Client_ForageItem, file, "$");
|
||||
newXSproto(strcpy(buf, "CalcPriceMod"), XS_Client_CalcPriceMod, file, "$;$$");
|
||||
newXSproto(strcpy(buf, "ResetTrade"), XS_Client_ResetTrade, file, "$");
|
||||
newXSproto(strcpy(buf, "UseDiscipline"), XS_Client_UseDiscipline, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetCarriedMoney"), XS_Client_GetCarriedMoney, file, "$");
|
||||
newXSproto(strcpy(buf, "GetCharacterFactionLevel"), XS_Client_GetCharacterFactionLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetZoneFlag"), XS_Client_SetZoneFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "ClearZoneFlag"), XS_Client_ClearZoneFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "HasZoneFlag"), XS_Client_HasZoneFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "SendZoneFlagInfo"), XS_Client_SendZoneFlagInfo, file, "$$");
|
||||
newXSproto(strcpy(buf, "LoadZoneFlags"), XS_Client_LoadZoneFlags, file, "$");
|
||||
newXSproto(strcpy(buf, "SetAATitle"), XS_Client_SetAATitle, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "GetClientVersion"), XS_Client_GetClientVersion, file, "$");
|
||||
newXSproto(strcpy(buf, "GetClientVersionBit"), XS_Client_GetClientVersionBit, file, "$");
|
||||
newXSproto(strcpy(buf, "SetTitleSuffix"), XS_Client_SetTitleSuffix, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "SetAAPoints"), XS_Client_SetAAPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAAPoints"), XS_Client_GetAAPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetSpentAA"), XS_Client_GetSpentAA, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddAAPoints"), XS_Client_AddAAPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "RefundAA"), XS_Client_RefundAA, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetModCharacterFactionLevel"), XS_Client_GetModCharacterFactionLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLDoNWins"), XS_Client_GetLDoNWins, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNLosses"), XS_Client_GetLDoNLosses, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNWinsTheme"), XS_Client_GetLDoNWinsTheme, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLDoNLossesTheme"), XS_Client_GetLDoNLossesTheme, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetItemAt"), XS_Client_GetItemAt, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAugmentAt"), XS_Client_GetAugmentAt, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetStartZone"), XS_Client_GetStartZone, file, "$");
|
||||
newXSproto(strcpy(buf, "SetStartZone"), XS_Client_SetStartZone, file, "$$");
|
||||
newXSproto(strcpy(buf, "KeyRingAdd"), XS_Client_KeyRingAdd, file, "$$");
|
||||
newXSproto(strcpy(buf, "KeyRingCheck"), XS_Client_KeyRingCheck, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddPVPPoints"), XS_Client_AddPVPPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "AddCrystals"), XS_Client_AddCrystals, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetPVPPoints"), XS_Client_GetPVPPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRadiantCrystals"), XS_Client_GetRadiantCrystals, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEbonCrystals"), XS_Client_GetEbonCrystals, file, "$");
|
||||
newXSproto(strcpy(buf, "ReadBook"), XS_Client_ReadBook, file, "$$$");
|
||||
newXSproto(strcpy(buf, "UpdateGroupAAs"), XS_Client_UpdateGroupAAs, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetGroupPoints"), XS_Client_GetGroupPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRaidPoints"), XS_Client_GetRaidPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "LearnRecipe"), XS_Client_LearnRecipe, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetEndurance"), XS_Client_GetEndurance, file, "$");
|
||||
newXSproto(strcpy(buf, "GetMaxEndurance"), XS_Client_GetMaxEndurance, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEnduranceRatio"), XS_Client_GetEnduranceRatio, file, "$");
|
||||
newXSproto(strcpy(buf, "SetEndurance"), XS_Client_SetEndurance, file, "$$");
|
||||
newXSproto(strcpy(buf, "SendOPTranslocateConfirm"), XS_Client_SendOPTranslocateConfirm, file, "$$$");
|
||||
newXSproto(strcpy(buf, "NPCSpawn"), XS_Client_NPCSpawn, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "GetIP"), XS_Client_GetIP, file, "$");
|
||||
newXSproto(strcpy(buf, "AddLevelBasedExp"), XS_Client_AddLevelBasedExp, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "IncrementAA"), XS_Client_IncrementAA, file, "$$");
|
||||
newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file,
|
||||
"$$$;$");
|
||||
newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "ClearCompassMark"), XS_Client_ClearCompassMark, file, "$");
|
||||
newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$");
|
||||
newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$");
|
||||
newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetTaskActivityDoneCount"), XS_Client_GetTaskActivityDoneCount, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetCorpseCount"), XS_Client_GetCorpseCount, file, "$");
|
||||
newXSproto(strcpy(buf, "GetCorpseID"), XS_Client_GetCorpseID, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetCorpseItemAt"), XS_Client_GetCorpseItemAt, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AssignToInstance"), XS_Client_AssignToInstance, file, "$$");
|
||||
newXSproto(strcpy(buf, "Freeze"), XS_Client_Freeze, file, "$");
|
||||
newXSproto(strcpy(buf, "UnFreeze"), XS_Client_UnFreeze, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAggroCount"), XS_Client_GetAggroCount, file, "$");
|
||||
newXSproto(strcpy(buf, "GetCarriedMoney"), XS_Client_GetCarriedMoney, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAllMoney"), XS_Client_GetAllMoney, file, "$");
|
||||
newXSproto(strcpy(buf, "GetItemInInventory"), XS_Client_GetItemInInventory, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetCustomItemData"), XS_Client_SetCustomItemData, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "GetCustomItemData"), XS_Client_GetCustomItemData, file, "$$$");
|
||||
newXSproto(strcpy(buf, "OpenLFGuildWindow"), XS_Client_OpenLFGuildWindow, file, "$");
|
||||
newXSproto(strcpy(buf, "SignalClient"), XS_Client_SignalClient, file, "$");
|
||||
newXSproto(strcpy(buf, "AddAlternateCurrencyValue"), XS_Client_AddAlternateCurrencyValue, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SendWebLink"), XS_Client_SendWebLink, file, "$:$");
|
||||
newXSproto(strcpy(buf, "GetInstanceID"), XS_Client_GetInstanceID, file, "$$");
|
||||
newXSproto(strcpy(buf, "HasSpellScribed"), XS_Client_HasSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetAccountFlag"), XS_Client_SetAccountFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetAccountFlag"), XS_Client_GetAccountFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetDiscSlotBySpellID"), XS_Client_GetDiscSlotBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetDuelTarget"), XS_Client_GetDuelTarget, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEbonCrystals"), XS_Client_GetEbonCrystals, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEndurance"), XS_Client_GetEndurance, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEnduranceRatio"), XS_Client_GetEnduranceRatio, file, "$");
|
||||
newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetFace"), XS_Client_GetFace, file, "$");
|
||||
newXSproto(strcpy(buf, "GetFactionLevel"), XS_Client_GetFactionLevel, file, "$$$$$$$$");
|
||||
newXSproto(strcpy(buf, "GetFeigned"), XS_Client_GetFeigned, file, "$");
|
||||
newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$");
|
||||
newXSproto(strcpy(buf, "GetGM"), XS_Client_GetGM, file, "$");
|
||||
newXSproto(strcpy(buf, "GetGroup"), XS_Client_GetGroup, file, "$");
|
||||
newXSproto(strcpy(buf, "GetGroupPoints"), XS_Client_GetGroupPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "GetHorseId"), XS_Client_GetHorseId, file, "$");
|
||||
newXSproto(strcpy(buf, "GetHunger"), XS_Client_GetHunger, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetThirst"), XS_Client_GetThirst, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetHunger"), XS_Client_SetHunger, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetThirst"), XS_Client_SetThirst, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetConsumption"), XS_Client_SetConsumption, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SilentMessage"), XS_Client_SilentMessage, file, "$$");
|
||||
newXSproto(strcpy(buf, "PlayMP3"), XS_Client_PlayMP3, file, "$;$");
|
||||
newXSproto(strcpy(buf, "SendTargetCommand"), XS_Client_SendTargetCommand, file, "$$");
|
||||
newXSproto(strcpy(buf, "ExpeditionMessage"), XS_Client_ExpeditionMessage, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetInstanceID"), XS_Client_GetInstanceID, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetInstrumentMod"), XS_Client_GetInstrumentMod, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetIP"), XS_Client_GetIP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetItemAt"), XS_Client_GetItemAt, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetItemIDAt"), XS_Client_GetItemIDAt, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetItemInInventory"), XS_Client_GetItemInInventory, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLanguageSkill"), XS_Client_GetLanguageSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLastName"), XS_Client_GetLastName, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNLosses"), XS_Client_GetLDoNLosses, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNLossesTheme"), XS_Client_GetLDoNLossesTheme, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetLDoNPointsTheme"), XS_Client_GetLDoNPointsTheme, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNWins"), XS_Client_GetLDoNWins, file, "$");
|
||||
newXSproto(strcpy(buf, "GetLDoNWinsTheme"), XS_Client_GetLDoNWinsTheme, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetMaxEndurance"), XS_Client_GetMaxEndurance, file, "$");
|
||||
newXSproto(strcpy(buf, "GetModCharacterFactionLevel"), XS_Client_GetModCharacterFactionLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetPVP"), XS_Client_GetPVP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetPVPPoints"), XS_Client_GetPVPPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRadiantCrystals"), XS_Client_GetRadiantCrystals, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRaid"), XS_Client_GetRaid, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRaidPoints"), XS_Client_GetRaidPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRawItemAC"), XS_Client_GetRawItemAC, file, "$");
|
||||
newXSproto(strcpy(buf, "GetRawSkill"), XS_Client_GetRawSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetSkill"), XS_Client_GetSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetSkillPoints"), XS_Client_GetSkillPoints, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetSpentAA"), XS_Client_GetSpentAA, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetStartZone"), XS_Client_GetStartZone, file, "$");
|
||||
newXSproto(strcpy(buf, "GetTargetRingX"), XS_Client_GetTargetRingX, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetTargetRingY"), XS_Client_GetTargetRingY, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetTargetRingZ"), XS_Client_GetTargetRingZ, file, "$$");
|
||||
newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$");
|
||||
newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$");
|
||||
newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$");
|
||||
newXSproto(strcpy(buf, "GetTaskActivityDoneCount"), XS_Client_GetTaskActivityDoneCount, file, "$$$");
|
||||
newXSproto(strcpy(buf, "GetThirst"), XS_Client_GetThirst, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetTotalSecondsPlayed"), XS_Client_GetTotalSecondsPlayed, file, "$");
|
||||
newXSproto(strcpy(buf, "GetWeight"), XS_Client_GetWeight, file, "$");
|
||||
newXSproto(strcpy(buf, "GMKill"), XS_Client_GMKill, file, "$");
|
||||
newXSproto(strcpy(buf, "GoFish"), XS_Client_GoFish, file, "$");
|
||||
newXSproto(strcpy(buf, "GrantAlternateAdvancementAbility"), XS_Client_GrantAlternateAdvancementAbility, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "GuildID"), XS_Client_GuildID, file, "$");
|
||||
newXSproto(strcpy(buf, "GuildRank"), XS_Client_GuildRank, file, "$");
|
||||
newXSproto(strcpy(buf, "HasSkill"), XS_Client_HasSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "HasSpellScribed"), XS_Client_HasSkill, file, "$$");
|
||||
newXSproto(strcpy(buf, "HasZoneFlag"), XS_Client_HasZoneFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "Hungry"), XS_Client_Hungry, file, "$");
|
||||
newXSproto(strcpy(buf, "IncreaseLanguageSkill"), XS_Client_IncreaseLanguageSkill, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "IncreaseSkill"), XS_Client_IncreaseSkill, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "IncrementAA"), XS_Client_IncrementAA, file, "$$");
|
||||
newXSproto(strcpy(buf, "IncStats"), XS_Client_IncStats, file, "$$$");
|
||||
newXSproto(strcpy(buf, "InZone"), XS_Client_InZone, file, "$");
|
||||
newXSproto(strcpy(buf, "IsBecomeNPC"), XS_Client_IsBecomeNPC, file, "$");
|
||||
newXSproto(strcpy(buf, "IsDueling"), XS_Client_IsDueling, file, "$");
|
||||
newXSproto(strcpy(buf, "IsGrouped"), XS_Client_IsGrouped, file, "$");
|
||||
newXSproto(strcpy(buf, "IsLD"), XS_Client_IsLD, file, "$");
|
||||
newXSproto(strcpy(buf, "IsMedding"), XS_Client_IsMedding, file, "$");
|
||||
newXSproto(strcpy(buf, "IsRaidGrouped"), XS_Client_IsRaidGrouped, file, "$");
|
||||
newXSproto(strcpy(buf, "IsSitting"), XS_Client_IsSitting, file, "$");
|
||||
newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$");
|
||||
newXSproto(strcpy(buf, "IsTaskActivityActive"), XS_Client_IsTaskActivityActive, file, "$$$");
|
||||
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
|
||||
newXSproto(strcpy(buf, "KeyRingAdd"), XS_Client_KeyRingAdd, file, "$$");
|
||||
newXSproto(strcpy(buf, "KeyRingCheck"), XS_Client_KeyRingCheck, file, "$$");
|
||||
newXSproto(strcpy(buf, "Kick"), XS_Client_Kick, file, "$");
|
||||
newXSproto(strcpy(buf, "LearnRecipe"), XS_Client_LearnRecipe, file, "$$");
|
||||
newXSproto(strcpy(buf, "LeaveGroup"), XS_Client_LeaveGroup, file, "$");
|
||||
newXSproto(strcpy(buf, "LoadZoneFlags"), XS_Client_LoadZoneFlags, file, "$");
|
||||
newXSproto(strcpy(buf, "MarkCompassLoc"), XS_Client_MarkCompassLoc, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "MaxSkill"), XS_Client_MaxSkill, file, "$$;$$");
|
||||
newXSproto(strcpy(buf, "MemSpell"), XS_Client_MemSpell, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "MovePC"), XS_Client_MovePC, file, "$$$$$$");
|
||||
newXSproto(strcpy(buf, "MovePCInstance"), XS_Client_MovePCInstance, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "NPCSpawn"), XS_Client_NPCSpawn, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "NukeItem"), XS_Client_NukeItem, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "OpenLFGuildWindow"), XS_Client_OpenLFGuildWindow, file, "$");
|
||||
newXSproto(strcpy(buf, "PlayMP3"), XS_Client_PlayMP3, file, "$;$");
|
||||
newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$");
|
||||
newXSproto(strcpy(buf, "QuestReward"), XS_Client_QuestReward, file, "$$;$$$$$$$");
|
||||
newXSproto(strcpy(buf, "ReadBook"), XS_Client_ReadBook, file, "$$$");
|
||||
newXSproto(strcpy(buf, "RefundAA"), XS_Client_RefundAA, file, "$$");
|
||||
newXSproto(strcpy(buf, "RemoveNoRent"), XS_Client_RemoveNoRent, file, "$");
|
||||
newXSproto(strcpy(buf, "ResetAA"), XS_Client_ResetAA, file, "$");
|
||||
newXSproto(strcpy(buf, "ResetTrade"), XS_Client_ResetTrade, file, "$");
|
||||
newXSproto(strcpy(buf, "Save"), XS_Client_Save, file, "$$");
|
||||
newXSproto(strcpy(buf, "SaveBackup"), XS_Client_SaveBackup, file, "$");
|
||||
newXSproto(strcpy(buf, "ScribeSpell"), XS_Client_ScribeSpell, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "SendColoredText"), XS_Client_SendColoredText, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "SendOPTranslocateConfirm"), XS_Client_SendOPTranslocateConfirm, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SendSound"), XS_Client_SendSound, file, "$");
|
||||
newXSproto(strcpy(buf, "SendSpellAnim"), XS_Client_SendSpellAnim, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SendTargetCommand"), XS_Client_SendTargetCommand, file, "$$");
|
||||
newXSproto(strcpy(buf, "SendWebLink"), XS_Client_SendWebLink, file, "$:$");
|
||||
newXSproto(strcpy(buf, "SendZoneFlagInfo"), XS_Client_SendZoneFlagInfo, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetAAPoints"), XS_Client_SetAAPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetAATitle"), XS_Client_SetAATitle, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "SetAccountFlag"), XS_Client_SetAccountFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBaseClass"), XS_Client_SetBaseClass, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBaseGender"), XS_Client_SetBaseGender, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBaseRace"), XS_Client_SetBaseRace, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBecomeNPC"), XS_Client_SetBecomeNPC, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBecomeNPCLevel"), XS_Client_SetBecomeNPCLevel, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetBindPoint"), XS_Client_SetBindPoint, file, "$;$$$$$");
|
||||
newXSproto(strcpy(buf, "SetConsumption"), XS_Client_SetConsumption, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetCustomItemData"), XS_Client_SetCustomItemData, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "SetDeity"), XS_Client_SetDeity, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetDueling"), XS_Client_SetDueling, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetDuelTarget"), XS_Client_SetDuelTarget, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetEndurance"), XS_Client_SetEndurance, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetEXP"), XS_Client_SetEXP, file, "$$$;$");
|
||||
newXSproto(strcpy(buf, "SetFactionLevel"), XS_Client_SetFactionLevel, file, "$$$$$$");
|
||||
newXSproto(strcpy(buf, "SetFactionLevel2"), XS_Client_SetFactionLevel2, file, "$$$$$$$");
|
||||
newXSproto(strcpy(buf, "SetFeigned"), XS_Client_SetFeigned, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetGM"), XS_Client_SetGM, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetHorseId"), XS_Client_SetHorseId, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetHunger"), XS_Client_SetHunger, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetLanguageSkill"), XS_Client_SetLanguageSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetMaterial"), XS_Client_SetMaterial, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetPrimaryWeaponOrnamentation"), XS_Client_SetPrimaryWeaponOrnamentation, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetPVP"), XS_Client_SetPVP, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetSecondaryWeaponOrnamentation"), XS_Client_SetSecondaryWeaponOrnamentation, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetSkill"), XS_Client_SetSkill, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetSkillPoints"), XS_Client_SetSkillPoints, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetStartZone"), XS_Client_SetStartZone, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetStats"), XS_Client_SetStats, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetThirst"), XS_Client_SetThirst, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetTint"), XS_Client_SetTint, file, "$$$");
|
||||
newXSproto(strcpy(buf, "SetTitleSuffix"), XS_Client_SetTitleSuffix, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "SetZoneFlag"), XS_Client_SetZoneFlag, file, "$$");
|
||||
newXSproto(strcpy(buf, "SignalClient"), XS_Client_SignalClient, file, "$");
|
||||
newXSproto(strcpy(buf, "SilentMessage"), XS_Client_SilentMessage, file, "$$");
|
||||
newXSproto(strcpy(buf, "SlotConvert2"), XS_Client_SlotConvert2, file, "$$");
|
||||
newXSproto(strcpy(buf, "Stand"), XS_Client_Stand, file, "$");
|
||||
newXSproto(strcpy(buf, "SummonItem"), XS_Client_SummonItem, file, "$$;$$$$$$$$");
|
||||
newXSproto(strcpy(buf, "TakeMoneyFromPP"), XS_Client_TakeMoneyFromPP, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "TGB"), XS_Client_TGB, file, "$");
|
||||
newXSproto(strcpy(buf, "Thirsty"), XS_Client_Thirsty, file, "$");
|
||||
newXSproto(strcpy(buf, "TrainDiscBySpellID"), XS_Client_TrainDiscBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "Undye"), XS_Client_Undye, file, "$");
|
||||
newXSproto(strcpy(buf, "UnFreeze"), XS_Client_UnFreeze, file, "$");
|
||||
newXSproto(strcpy(buf, "UnmemSpell"), XS_Client_UnmemSpell, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "UnmemSpellAll"), XS_Client_UnmemSpellAll, file, "$;$");
|
||||
newXSproto(strcpy(buf, "UnmemSpellBySpellID"), XS_Client_UnmemSpellBySpellID, file, "$$");
|
||||
newXSproto(strcpy(buf, "UnscribeSpell"), XS_Client_UnscribeSpell, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "UnscribeSpellAll"), XS_Client_UnscribeSpellAll, file, "$;$");
|
||||
newXSproto(strcpy(buf, "UntrainDisc"), XS_Client_UntrainDisc, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "UntrainDiscAll"), XS_Client_UntrainDiscAll, file, "$;$");
|
||||
newXSproto(strcpy(buf, "UpdateAdmin"), XS_Client_UpdateAdmin, file, "$;$");
|
||||
newXSproto(strcpy(buf, "UpdateGroupAAs"), XS_Client_UpdateGroupAAs, file, "$$$");
|
||||
newXSproto(strcpy(buf, "UpdateLDoNPoints"), XS_Client_UpdateLDoNPoints, file, "$$$");
|
||||
newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$");
|
||||
newXSproto(strcpy(buf, "UpdateWho"), XS_Client_UpdateWho, file, "$;$");
|
||||
newXSproto(strcpy(buf, "UseDiscipline"), XS_Client_UseDiscipline, file, "$$$");
|
||||
newXSproto(strcpy(buf, "WorldKick"), XS_Client_WorldKick, file, "$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
@@ -1355,7 +1355,7 @@ XS(XS_EntityList_OpenDoorsNear) {
|
||||
Perl_croak(aTHX_ "Usage: EntityList::OpenDoorsNear(THIS, NPC* opener)");
|
||||
{
|
||||
EntityList *THIS;
|
||||
NPC *opener;
|
||||
Mob *opener;
|
||||
|
||||
if (sv_derived_from(ST(0), "EntityList")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
@@ -1365,11 +1365,11 @@ XS(XS_EntityList_OpenDoorsNear) {
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
if (sv_derived_from(ST(1), "NPC")) {
|
||||
if (sv_derived_from(ST(1), "Mob")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(1)));
|
||||
opener = INT2PTR(NPC *, tmp);
|
||||
opener = INT2PTR(Mob *, tmp);
|
||||
} else
|
||||
Perl_croak(aTHX_ "opener is not of type NPC");
|
||||
Perl_croak(aTHX_ "opener is not of type Mob");
|
||||
if (opener == nullptr)
|
||||
Perl_croak(aTHX_ "opener is nullptr, avoiding crash.");
|
||||
|
||||
|
||||
+95
-98
@@ -639,7 +639,7 @@ XS(XS_Mob_GetEquipment) {
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetEquipment(material_slot);
|
||||
RETVAL = THIS->GetEquippedItemFromTextureSlot(material_slot);
|
||||
XSprePUSH;
|
||||
PUSHi((IV) RETVAL);
|
||||
}
|
||||
@@ -1166,55 +1166,6 @@ XS(XS_Mob_GMMove) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_SendPosUpdate); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_SendPosUpdate) {
|
||||
dXSARGS;
|
||||
if (items < 1 || items > 2)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SendPosUpdate(THIS, [uint8 send_to_self = 0])");
|
||||
{
|
||||
Mob *THIS;
|
||||
uint8 iSendToSelf;
|
||||
|
||||
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.");
|
||||
|
||||
if (items < 2)
|
||||
iSendToSelf = 0;
|
||||
else {
|
||||
iSendToSelf = (uint8) SvUV(ST(1));
|
||||
}
|
||||
|
||||
THIS->SendPositionUpdate(iSendToSelf);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_SendPosition); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_SendPosition) {
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SendPosition(THIS)");
|
||||
{
|
||||
Mob *THIS;
|
||||
|
||||
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.");
|
||||
|
||||
THIS->SendPosition();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_HasProcs); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_HasProcs) {
|
||||
dXSARGS;
|
||||
@@ -3786,7 +3737,7 @@ XS(XS_Mob_CastSpell) {
|
||||
Mob *THIS;
|
||||
uint16 spell_id = (uint16) SvUV(ST(1));
|
||||
uint16 target_id = (uint16) SvUV(ST(2));
|
||||
EQEmu::CastingSlot slot;
|
||||
EQEmu::spells::CastingSlot slot;
|
||||
int32 casttime;
|
||||
int32 mana_cost;
|
||||
int16 resist_adjust;
|
||||
@@ -3800,9 +3751,9 @@ XS(XS_Mob_CastSpell) {
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
if (items < 4)
|
||||
slot = EQEmu::CastingSlot::Item;
|
||||
slot = EQEmu::spells::CastingSlot::Item;
|
||||
else {
|
||||
slot = static_cast<EQEmu::CastingSlot>(SvUV(ST(3)));
|
||||
slot = static_cast<EQEmu::spells::CastingSlot>(SvUV(ST(3)));
|
||||
}
|
||||
|
||||
if (items < 5)
|
||||
@@ -3876,7 +3827,7 @@ XS(XS_Mob_SpellFinished) {
|
||||
resist_diff = spells[spell_id].ResistDiff;
|
||||
}
|
||||
|
||||
THIS->SpellFinished(spell_id, spell_target, EQEmu::CastingSlot::Item, mana_cost, -1, resist_diff);
|
||||
THIS->SpellFinished(spell_id, spell_target, EQEmu::spells::CastingSlot::Item, mana_cost, -1, resist_diff);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
@@ -5526,20 +5477,71 @@ XS(XS_Mob_CalculateHeadingToTarget) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_Mob_CalculateNewPosition); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_CalculateNewPosition) {
|
||||
XS(XS_Mob_RunTo); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_RunTo) {
|
||||
dXSARGS;
|
||||
if (items < 5 || items > 6)
|
||||
if (items < 4 || items > 5)
|
||||
Perl_croak(aTHX_
|
||||
"Usage: Mob::CalculateNewPosition(THIS, float x, float y, float z, float speed, [bool check_z = false])");
|
||||
"Usage: Mob::RunTo(THIS, float x, float y, float z)");
|
||||
{
|
||||
Mob *THIS;
|
||||
float x = (float)SvNV(ST(1));
|
||||
float y = (float)SvNV(ST(2));
|
||||
float z = (float)SvNV(ST(3));
|
||||
|
||||
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.");
|
||||
|
||||
|
||||
THIS->RunTo(x, y, z);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_WalkTo); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_WalkTo) {
|
||||
dXSARGS;
|
||||
if (items < 4 || items > 5)
|
||||
Perl_croak(aTHX_
|
||||
"Usage: Mob::WalkTo(THIS, float x, float y, float z)");
|
||||
{
|
||||
Mob *THIS;
|
||||
float x = (float)SvNV(ST(1));
|
||||
float y = (float)SvNV(ST(2));
|
||||
float z = (float)SvNV(ST(3));
|
||||
|
||||
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.");
|
||||
|
||||
|
||||
THIS->WalkTo(x, y, z);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_NavigateTo); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_NavigateTo) {
|
||||
dXSARGS;
|
||||
if (items < 4 || items > 5)
|
||||
Perl_croak(aTHX_
|
||||
"Usage: Mob::NavigateTo(THIS, float x, float y, float z)");
|
||||
{
|
||||
Mob *THIS;
|
||||
bool RETVAL;
|
||||
float x = (float) SvNV(ST(1));
|
||||
float y = (float) SvNV(ST(2));
|
||||
float z = (float) SvNV(ST(3));
|
||||
float speed = (float) SvNV(ST(4));
|
||||
bool checkZ;
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
@@ -5549,17 +5551,34 @@ XS(XS_Mob_CalculateNewPosition) {
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
if (items < 6)
|
||||
checkZ = false;
|
||||
else {
|
||||
checkZ = (bool) SvTRUE(ST(5));
|
||||
}
|
||||
|
||||
RETVAL = THIS->CalculateNewPosition(x, y, z, speed, checkZ);
|
||||
ST(0) = boolSV(RETVAL);
|
||||
sv_2mortal(ST(0));
|
||||
THIS->NavigateTo(x, y, z);
|
||||
}
|
||||
XSRETURN(1);
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_StopNavigation); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_StopNavigation) {
|
||||
dXSARGS;
|
||||
if (items < 5 || items > 6)
|
||||
Perl_croak(aTHX_
|
||||
"Usage: Mob::StopNavigation(THIS)");
|
||||
{
|
||||
Mob *THIS;
|
||||
|
||||
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.");
|
||||
|
||||
|
||||
THIS->StopNavigation();
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_CalculateDistance); /* prototype to pass -Wmissing-prototypes */
|
||||
@@ -6652,10 +6671,10 @@ XS(XS_Mob_SetFlyMode); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_SetFlyMode) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SetFlyMode(THIS, uint8 flymode[0|1|2|3])");
|
||||
Perl_croak(aTHX_ "Usage: Mob::SetFlyMode(THIS, uint8 flymode[0|1|2|3|4|5])");
|
||||
{
|
||||
Mob *THIS;
|
||||
uint8 flymode = (uint8) SvIV(ST(1));
|
||||
GravityBehavior flymode = (GravityBehavior) SvIV(ST(1));
|
||||
|
||||
if (sv_derived_from(ST(0), "Mob")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
@@ -7275,28 +7294,6 @@ XS(XS_Mob_SetLD) {
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_SetTargetDestSteps); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_SetTargetDestSteps) {
|
||||
dXSARGS;
|
||||
if (items != 2)
|
||||
Perl_croak(aTHX_ "Usage: Mob::SetTargetDestSteps(THIS, uint8 target_steps)");
|
||||
{
|
||||
Mob *THIS;
|
||||
uint8 target_steps = (uint8) SvIV(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.");
|
||||
|
||||
THIS->SetTargetDestSteps(target_steps);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_Mob_SetTargetable); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_Mob_SetTargetable) {
|
||||
dXSARGS;
|
||||
@@ -8556,8 +8553,6 @@ XS(boot_Mob) {
|
||||
newXSproto(strcpy(buf, "DoAnim"), XS_Mob_DoAnim, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "ChangeSize"), XS_Mob_ChangeSize, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "GMMove"), XS_Mob_GMMove, file, "$$$$;$");
|
||||
newXSproto(strcpy(buf, "SendPosUpdate"), XS_Mob_SendPosUpdate, file, "$;$");
|
||||
newXSproto(strcpy(buf, "SendPosition"), XS_Mob_SendPosition, file, "$");
|
||||
newXSproto(strcpy(buf, "HasProcs"), XS_Mob_HasProcs, file, "$");
|
||||
newXSproto(strcpy(buf, "IsInvisible"), XS_Mob_IsInvisible, file, "$;$");
|
||||
newXSproto(strcpy(buf, "SetInvisible"), XS_Mob_SetInvisible, file, "$$");
|
||||
@@ -8718,7 +8713,10 @@ XS(boot_Mob) {
|
||||
newXSproto(strcpy(buf, "WipeHateList"), XS_Mob_WipeHateList, file, "$");
|
||||
newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$");
|
||||
newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, file, "$$$");
|
||||
newXSproto(strcpy(buf, "CalculateNewPosition"), XS_Mob_CalculateNewPosition, file, "$$$$$;$");
|
||||
newXSproto(strcpy(buf, "RunTo"), XS_Mob_RunTo, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "WalkTo"), XS_Mob_WalkTo, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "NavigateTo"), XS_Mob_NavigateTo, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "StopNavigation"), XS_Mob_StopNavigation, file, "$");
|
||||
newXSproto(strcpy(buf, "CalculateDistance"), XS_Mob_CalculateDistance, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$");
|
||||
@@ -8781,7 +8779,6 @@ XS(boot_Mob) {
|
||||
newXSproto(strcpy(buf, "SetBodyType"), XS_Mob_SetBodyType, file, "$$;$");
|
||||
newXSproto(strcpy(buf, "SetDeltas"), XS_Mob_SetDeltas, file, "$$$$$");
|
||||
newXSproto(strcpy(buf, "SetLD"), XS_Mob_SetLD, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetTargetDestSteps"), XS_Mob_SetTargetDestSteps, file, "$$");
|
||||
newXSproto(strcpy(buf, "SetTargetable"), XS_Mob_SetTargetable, file, "$$");
|
||||
newXSproto(strcpy(buf, "MakeTempPet"), XS_Mob_MakeTempPet, file, "$$;$$$$");
|
||||
newXSproto(strcpy(buf, "ModSkillDmgTaken"), XS_Mob_ModSkillDmgTaken, file, "$$$");
|
||||
|
||||
+8
-11
@@ -1341,11 +1341,14 @@ XS(XS_NPC_NextGuardPosition) {
|
||||
XS(XS_NPC_SaveGuardSpot); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_SaveGuardSpot) {
|
||||
dXSARGS;
|
||||
if (items < 1 || items > 2)
|
||||
Perl_croak(aTHX_ "Usage: NPC::SaveGuardSpot(THIS, [bool clear_guard_spot = false])");
|
||||
if (items != 5)
|
||||
Perl_croak(aTHX_ "Usage: NPC::SaveGuardSpot(THIS, x, y, z, heading)");
|
||||
{
|
||||
NPC *THIS;
|
||||
bool iClearGuardSpot;
|
||||
float x = (float)SvNV(ST(1));
|
||||
float y = (float)SvNV(ST(2));
|
||||
float z = (float)SvNV(ST(3));
|
||||
float heading = (float)SvNV(ST(4));
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV *) SvRV(ST(0)));
|
||||
@@ -1355,13 +1358,7 @@ XS(XS_NPC_SaveGuardSpot) {
|
||||
if (THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
if (items < 2)
|
||||
iClearGuardSpot = false;
|
||||
else {
|
||||
iClearGuardSpot = (bool) SvTRUE(ST(1));
|
||||
}
|
||||
|
||||
THIS->SaveGuardSpot(iClearGuardSpot);
|
||||
THIS->SaveGuardSpot(glm::vec4(x, y, z, heading));
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
@@ -2449,7 +2446,7 @@ XS(boot_NPC) {
|
||||
newXSproto(strcpy(buf, "PauseWandering"), XS_NPC_PauseWandering, file, "$$");
|
||||
newXSproto(strcpy(buf, "MoveTo"), XS_NPC_MoveTo, file, "$$$$");
|
||||
newXSproto(strcpy(buf, "NextGuardPosition"), XS_NPC_NextGuardPosition, file, "$");
|
||||
newXSproto(strcpy(buf, "SaveGuardSpot"), XS_NPC_SaveGuardSpot, file, "$;$");
|
||||
newXSproto(strcpy(buf, "SaveGuardSpot"), XS_NPC_SaveGuardSpot, file, "$$$$$");
|
||||
newXSproto(strcpy(buf, "IsGuarding"), XS_NPC_IsGuarding, file, "$");
|
||||
newXSproto(strcpy(buf, "AI_SetRoambox"), XS_NPC_AI_SetRoambox, file, "$$$$$$;$$");
|
||||
newXSproto(strcpy(buf, "GetNPCSpellsID"), XS_NPC_GetNPCSpellsID, file, "$");
|
||||
|
||||
+3
-3
@@ -240,7 +240,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
||||
if(scale_power > 0)
|
||||
{
|
||||
npc_type->max_hp *= (1 + scale_power);
|
||||
npc_type->cur_hp = npc_type->max_hp;
|
||||
npc_type->current_hp = npc_type->max_hp;
|
||||
npc_type->AC *= (1 + scale_power);
|
||||
npc_type->level += 1 + ((int)act_power / 25) > npc_type->level + RuleR(Pets, PetPowerLevelCap) ? RuleR(Pets, PetPowerLevelCap) : 1 + ((int)act_power / 25); // gains an additional level for every 25 pet power
|
||||
npc_type->min_dmg = (npc_type->min_dmg * (1 + (scale_power / 2)));
|
||||
@@ -255,7 +255,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
||||
|
||||
if (MaxHP){
|
||||
npc_type->max_hp += (npc_type->max_hp*MaxHP)/100;
|
||||
npc_type->cur_hp = npc_type->max_hp;
|
||||
npc_type->current_hp = npc_type->max_hp;
|
||||
}
|
||||
|
||||
//TODO: think about regen (engaged vs. not engaged)
|
||||
@@ -425,7 +425,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
|
||||
into walls or objects (+10), this sometimes creates the "ghost" effect. I changed to +2 (as close as I
|
||||
could get while it still looked good). I also noticed this can happen if an NPC is spawned on the same spot of another or in a related bad spot.*/
|
||||
Pet::Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power)
|
||||
: NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), FlyMode3)
|
||||
: NPC(type_data, 0, owner->GetPosition() + glm::vec4(2.0f, 2.0f, 0.0f, 0.0f), GravityBehavior::Water)
|
||||
{
|
||||
GiveNPCTypeData(type_data);
|
||||
typeofpet = type;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <cmath>
|
||||
#include "../common/string_util.h"
|
||||
|
||||
static const float position_eps = 0.0001f;
|
||||
|
||||
std::string to_string(const glm::vec4 &position) {
|
||||
return StringFormat("(%.3f, %.3f, %.3f, %.3f)", position.x,position.y,position.z,position.w);
|
||||
}
|
||||
@@ -160,3 +162,94 @@ float GetReciprocalHeading(const float heading)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool IsHeadingEqual(const float h1, const float h2)
|
||||
{
|
||||
return std::abs(h2 - h1) < 0.01f;
|
||||
}
|
||||
|
||||
bool IsPositionEqual(const glm::vec2 &p1, const glm::vec2 &p2)
|
||||
{
|
||||
return std::abs(p1.x - p2.x) < position_eps && std::abs(p1.y - p2.y) < position_eps;
|
||||
}
|
||||
|
||||
bool IsPositionEqual(const glm::vec3 &p1, const glm::vec3 &p2)
|
||||
{
|
||||
return std::abs(p1.x - p2.x) < position_eps && std::abs(p1.y - p2.y) < position_eps && std::abs(p1.z - p2.z) < position_eps;
|
||||
}
|
||||
|
||||
bool IsPositionEqual(const glm::vec4 &p1, const glm::vec4 &p2)
|
||||
{
|
||||
return std::abs(p1.x - p2.x) < position_eps && std::abs(p1.y - p2.y) < position_eps && std::abs(p1.z - p2.z) < position_eps;
|
||||
}
|
||||
|
||||
bool IsPositionEqualWithinCertainZ(const glm::vec3 &p1, const glm::vec3 &p2, float z_eps) {
|
||||
return std::abs(p1.x - p2.x) < position_eps && std::abs(p1.y - p2.y) < position_eps && std::abs(p1.z - p2.z) < z_eps;
|
||||
}
|
||||
|
||||
bool IsPositionEqualWithinCertainZ(const glm::vec4 &p1, const glm::vec4 &p2, float z_eps) {
|
||||
return std::abs(p1.x - p2.x) < position_eps && std::abs(p1.y - p2.y) < position_eps && std::abs(p1.z - p2.z) < z_eps;
|
||||
}
|
||||
|
||||
bool IsPositionWithinSimpleCylinder(const glm::vec3 &p1, const glm::vec3 &cylinder_center, float cylinder_radius, float cylinder_height)
|
||||
{
|
||||
//If we're outside the height of cylinder then we're not in it (duh)
|
||||
auto d = std::abs(p1.z - cylinder_center.z);
|
||||
if (d > cylinder_height / 2.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec2 p1d(p1.x, p1.y);
|
||||
glm::vec2 ccd(cylinder_center.x, cylinder_center.y);
|
||||
|
||||
//If we're outside the radius of the cylinder then we're not in it (also duh)
|
||||
d = Distance(p1d, ccd);
|
||||
if (d > cylinder_radius) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsPositionWithinSimpleCylinder(const glm::vec4 &p1, const glm::vec4 &cylinder_center, float cylinder_radius, float cylinder_height)
|
||||
{
|
||||
//If we're outside the height of cylinder then we're not in it (duh)
|
||||
auto d = std::abs(p1.z - cylinder_center.z);
|
||||
if (d > cylinder_height / 2.0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
glm::vec2 p1d(p1.x, p1.y);
|
||||
glm::vec2 ccd(cylinder_center.x, cylinder_center.y);
|
||||
|
||||
//If we're outside the radius of the cylinder then we're not in it (also duh)
|
||||
d = Distance(p1d, ccd);
|
||||
if (d > cylinder_radius) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
float CalculateHeadingAngleBetweenPositions(float x1, float y1, float x2, float y2)
|
||||
{
|
||||
float y_diff = std::abs(y1 - y2);
|
||||
float x_diff = std::abs(x1 - x2);
|
||||
if (y_diff < 0.0000009999999974752427)
|
||||
y_diff = 0.0000009999999974752427;
|
||||
|
||||
float angle = atan2(x_diff, y_diff) * 180.0f * 0.3183099014828645f; // angle, nice "pi"
|
||||
|
||||
// return the right thing based on relative quadrant
|
||||
// I'm sure this could be improved for readability, but whatever
|
||||
if (y1 >= y2) {
|
||||
if (x2 >= x1)
|
||||
return (90.0f - angle + 90.0f) * 511.5f * 0.0027777778f;
|
||||
if (x2 <= x1)
|
||||
return (angle + 180.0f) * 511.5f * 0.0027777778f;
|
||||
}
|
||||
if (y1 > y2 || x2 > x1)
|
||||
return angle * 511.5f * 0.0027777778f;
|
||||
else
|
||||
return (90.0f - angle + 270.0f) * 511.5f * 0.0027777778f;
|
||||
}
|
||||
|
||||
@@ -50,4 +50,17 @@ float DistanceSquaredNoZ(const glm::vec4& point1, const glm::vec4& point2);
|
||||
float GetReciprocalHeading(const glm::vec4& point1);
|
||||
float GetReciprocalHeading(const float heading);
|
||||
|
||||
bool IsHeadingEqual(const float h1, const float h2);
|
||||
|
||||
bool IsPositionEqual(const glm::vec2 &p1, const glm::vec2 &p2);
|
||||
bool IsPositionEqual(const glm::vec3 &p1, const glm::vec3 &p2);
|
||||
bool IsPositionEqual(const glm::vec4 &p1, const glm::vec4 &p2);
|
||||
bool IsPositionEqualWithinCertainZ(const glm::vec3 &p1, const glm::vec3 &p2, float z_eps);
|
||||
bool IsPositionEqualWithinCertainZ(const glm::vec4 &p1, const glm::vec4 &p2, float z_eps);
|
||||
|
||||
bool IsPositionWithinSimpleCylinder(const glm::vec3 &p1, const glm::vec3 &cylinder_center, float cylinder_radius, float cylinder_height);
|
||||
bool IsPositionWithinSimpleCylinder(const glm::vec4 &p1, const glm::vec4 &cylinder_center, float cylinder_radius, float cylinder_height);
|
||||
|
||||
float CalculateHeadingAngleBetweenPositions(float x1, float y1, float x2, float y2);
|
||||
|
||||
#endif
|
||||
|
||||
+40
-43
@@ -208,7 +208,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p
|
||||
const NPCType* tmp = 0;
|
||||
if (tmp = database.LoadNPCTypesData(npc_type))
|
||||
{
|
||||
auto npc = new NPC(tmp, nullptr, position, FlyMode3);
|
||||
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water);
|
||||
npc->AddLootTable();
|
||||
if (npc->DropsGlobalLoot())
|
||||
npc->CheckGlobalLootTables();
|
||||
@@ -217,7 +217,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p
|
||||
{
|
||||
npc->AssignWaypoints(grid);
|
||||
}
|
||||
npc->SendPositionUpdate();
|
||||
|
||||
return npc;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -232,7 +232,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
|
||||
const NPCType* tmp = 0;
|
||||
if (tmp = database.LoadNPCTypesData(npc_type))
|
||||
{
|
||||
auto npc = new NPC(tmp, nullptr, position, FlyMode3);
|
||||
auto npc = new NPC(tmp, nullptr, position, GravityBehavior::Water);
|
||||
npc->AddLootTable();
|
||||
if (npc->DropsGlobalLoot())
|
||||
npc->CheckGlobalLootTables();
|
||||
@@ -241,7 +241,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v
|
||||
{
|
||||
npc->AssignWaypoints(grid);
|
||||
}
|
||||
npc->SendPositionUpdate();
|
||||
|
||||
return npc;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -308,22 +308,22 @@ Mob* QuestManager::spawn_from_spawn2(uint32 spawn2_id)
|
||||
found_spawn->SetCurrentNPCID(npcid);
|
||||
|
||||
auto position = glm::vec4(found_spawn->GetX(), found_spawn->GetY(), found_spawn->GetZ(), found_spawn->GetHeading());
|
||||
auto npc = new NPC(tmp, found_spawn, position, FlyMode3);
|
||||
auto npc = new NPC(tmp, found_spawn, position, GravityBehavior::Water);
|
||||
|
||||
found_spawn->SetNPCPointer(npc);
|
||||
npc->AddLootTable();
|
||||
if (npc->DropsGlobalLoot())
|
||||
npc->CheckGlobalLootTables();
|
||||
npc->SetSp2(found_spawn->SpawnGroupID());
|
||||
entity_list.AddNPC(npc);
|
||||
entity_list.LimitAddNPC(npc);
|
||||
found_spawn->SetNPCPointer(npc);
|
||||
npc->AddLootTable();
|
||||
if (npc->DropsGlobalLoot())
|
||||
npc->CheckGlobalLootTables();
|
||||
npc->SetSp2(found_spawn->SpawnGroupID());
|
||||
entity_list.AddNPC(npc);
|
||||
entity_list.LimitAddNPC(npc);
|
||||
|
||||
if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay &&
|
||||
sg->min_delay)
|
||||
npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3],
|
||||
sg->delay, sg->min_delay);
|
||||
if (zone->InstantGrids()) {
|
||||
found_spawn->LoadGrid();
|
||||
if (sg->roamdist && sg->roambox[0] && sg->roambox[1] && sg->roambox[2] && sg->roambox[3] && sg->delay &&
|
||||
sg->min_delay)
|
||||
npc->AI_SetRoambox(sg->roamdist, sg->roambox[0], sg->roambox[1], sg->roambox[2], sg->roambox[3],
|
||||
sg->delay, sg->min_delay);
|
||||
if (zone->InstantGrids()) {
|
||||
found_spawn->LoadGrid();
|
||||
}
|
||||
|
||||
return npc;
|
||||
@@ -371,14 +371,14 @@ void QuestManager::castspell(int spell_id, int target_id) {
|
||||
if (owner) {
|
||||
Mob *tgt = entity_list.GetMob(target_id);
|
||||
if(tgt != nullptr)
|
||||
owner->SpellFinished(spell_id, tgt, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
owner->SpellFinished(spell_id, tgt, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
|
||||
void QuestManager::selfcast(int spell_id) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (initiator)
|
||||
initiator->SpellFinished(spell_id, initiator, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
initiator->SpellFinished(spell_id, initiator, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
|
||||
void QuestManager::addloot(int item_id, int charges, bool equipitem, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) {
|
||||
@@ -985,7 +985,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) {
|
||||
bool SpellBucketCheckResult = 0;
|
||||
|
||||
|
||||
for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot))
|
||||
for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < EQEmu::spells::SPELLBOOK_SIZE; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot))
|
||||
{
|
||||
if
|
||||
(
|
||||
@@ -1706,32 +1706,33 @@ void QuestManager::respawn(int npcTypeID, int grid) {
|
||||
const NPCType* npcType = nullptr;
|
||||
if ((npcType = database.LoadNPCTypesData(npcTypeID)))
|
||||
{
|
||||
owner = new NPC(npcType, nullptr, owner->GetPosition(), FlyMode3);
|
||||
owner = new NPC(npcType, nullptr, owner->GetPosition(), GravityBehavior::Water);
|
||||
owner->CastToNPC()->AddLootTable();
|
||||
if (owner->CastToNPC()->DropsGlobalLoot())
|
||||
owner->CastToNPC()->CheckGlobalLootTables();
|
||||
entity_list.AddNPC(owner->CastToNPC(),true,true);
|
||||
if(grid > 0)
|
||||
owner->CastToNPC()->AssignWaypoints(grid);
|
||||
|
||||
owner->SendPositionUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void QuestManager::set_proximity(float minx, float maxx, float miny, float maxy, float minz, float maxz, bool bSay) {
|
||||
void QuestManager::set_proximity(float minx, float maxx, float miny, float maxy, float minz, float maxz, bool bSay)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
if (!owner || !owner->IsNPC())
|
||||
if (!owner || !owner->IsNPC()) {
|
||||
return;
|
||||
}
|
||||
|
||||
entity_list.AddProximity(owner->CastToNPC());
|
||||
|
||||
owner->CastToNPC()->proximity->min_x = minx;
|
||||
owner->CastToNPC()->proximity->max_x = maxx;
|
||||
owner->CastToNPC()->proximity->min_y = miny;
|
||||
owner->CastToNPC()->proximity->max_y = maxy;
|
||||
owner->CastToNPC()->proximity->min_z = minz;
|
||||
owner->CastToNPC()->proximity->max_z = maxz;
|
||||
owner->CastToNPC()->proximity->say = bSay;
|
||||
owner->CastToNPC()->proximity->min_x = minx;
|
||||
owner->CastToNPC()->proximity->max_x = maxx;
|
||||
owner->CastToNPC()->proximity->min_y = miny;
|
||||
owner->CastToNPC()->proximity->max_y = maxy;
|
||||
owner->CastToNPC()->proximity->min_z = minz;
|
||||
owner->CastToNPC()->proximity->max_z = maxz;
|
||||
owner->CastToNPC()->proximity->say = bSay;
|
||||
owner->CastToNPC()->proximity->proximity_set = true;
|
||||
}
|
||||
|
||||
void QuestManager::clear_proximity() {
|
||||
@@ -2823,22 +2824,18 @@ bool QuestManager::IsRunning()
|
||||
return owner->IsRunning();
|
||||
}
|
||||
|
||||
void QuestManager::FlyMode(uint8 flymode)
|
||||
void QuestManager::FlyMode(GravityBehavior flymode)
|
||||
{
|
||||
QuestManagerCurrentQuestVars();
|
||||
if(initiator)
|
||||
{
|
||||
if (flymode >= 0 && flymode < 3) {
|
||||
initiator->SendAppearancePacket(AT_Levitate, flymode);
|
||||
return;
|
||||
}
|
||||
initiator->SendAppearancePacket(AT_Levitate, static_cast<int>(flymode));
|
||||
initiator->SetFlyMode(flymode);
|
||||
}
|
||||
if(owner)
|
||||
else if(owner)
|
||||
{
|
||||
if (flymode >= 0 && flymode < 3) {
|
||||
owner->SendAppearancePacket(AT_Levitate, flymode);
|
||||
return;
|
||||
}
|
||||
owner->SendAppearancePacket(AT_Levitate, static_cast<int>(flymode));
|
||||
owner->SetFlyMode(flymode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -252,7 +252,7 @@ public:
|
||||
const char* getguildnamebyid(int guild_id);
|
||||
void SetRunning(bool val);
|
||||
bool IsRunning();
|
||||
void FlyMode(uint8 flymode);
|
||||
void FlyMode(GravityBehavior flymode);
|
||||
uint8 FactionValue();
|
||||
void wearchange(uint8 slot, uint16 texture, uint32 hero_forge_model = 0, uint32 elite_material = 0);
|
||||
void voicetell(const char *str, int macronum, int racenum, int gendernum);
|
||||
|
||||
+3
-3
@@ -255,7 +255,7 @@ bool Spawn2::Process() {
|
||||
}
|
||||
|
||||
currentnpcid = npcid;
|
||||
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), FlyMode3);
|
||||
NPC *npc = new NPC(tmp, this, glm::vec4(x, y, z, heading), GravityBehavior::Water);
|
||||
|
||||
npc->mod_prespawn(this);
|
||||
|
||||
@@ -488,7 +488,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList<Spawn2*>
|
||||
"animation "
|
||||
"FROM "
|
||||
"spawn2 "
|
||||
"WHERE zone = '%s' AND version = %u",
|
||||
"WHERE zone = '%s' AND (version = %u OR version = -1) ",
|
||||
zone_name,
|
||||
version
|
||||
);
|
||||
@@ -592,7 +592,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
|
||||
"animation "
|
||||
"FROM "
|
||||
"spawn2 "
|
||||
"WHERE zone = '%s' AND version = %u",
|
||||
"WHERE zone = '%s' AND (version = %u OR version = -1)",
|
||||
zone_name,
|
||||
version
|
||||
);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
extern uint64_t frame_time;
|
||||
extern double frame_time;
|
||||
|
||||
int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target)
|
||||
{
|
||||
@@ -197,7 +197,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
}
|
||||
|
||||
@@ -1033,7 +1033,7 @@ void Mob::ProjectileAttack()
|
||||
ProjectileAtk[i].skill = 0;
|
||||
ProjectileAtk[i].speed_mod = 0.0f;
|
||||
} else {
|
||||
ProjectileAtk[i].increment += frame_time;
|
||||
ProjectileAtk[i].increment += 1000 * frame_time;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2156,7 +2156,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills:
|
||||
IsValidSpell(aabonuses.SkillAttackProc[2])) {
|
||||
float chance = aabonuses.SkillAttackProc[0] / 1000.0f;
|
||||
if (zone->random.Roll(chance))
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1,
|
||||
SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::spells::CastingSlot::Item, 0, -1,
|
||||
spells[aabonuses.SkillAttackProc[2]].ResistDiff);
|
||||
}
|
||||
|
||||
|
||||
+16
-75
@@ -149,7 +149,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
if (spells[spell_id].EndurUpkeep > 0)
|
||||
SetEndurUpkeep(true);
|
||||
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater)
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::maskUFAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
@@ -826,9 +826,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#endif
|
||||
if(IsClient())
|
||||
{
|
||||
CastToClient()->SetSenseExemption(true);
|
||||
|
||||
if (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater)
|
||||
if (CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoDAndLater)
|
||||
{
|
||||
bodyType bt = BT_Undead;
|
||||
|
||||
@@ -853,7 +851,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
SetHeading(CalculateHeadingToTarget(ClosestMob->GetX(), ClosestMob->GetY()));
|
||||
SetTarget(ClosestMob);
|
||||
CastToClient()->SendTargetCommand(ClosestMob->GetID());
|
||||
SendPositionUpdate(2);
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0, true);
|
||||
}
|
||||
else
|
||||
Message_StringID(clientMessageError, SENSE_NOTHING);
|
||||
@@ -1246,7 +1244,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
// Will fix buttons for now
|
||||
if (IsClient()) {
|
||||
auto c = CastToClient();
|
||||
if (c->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) {
|
||||
if (c->ClientVersionBit() & EQEmu::versions::maskUFAndLater) {
|
||||
c->SetPetCommandState(PET_BUTTON_SIT, 0);
|
||||
c->SetPetCommandState(PET_BUTTON_STOP, 0);
|
||||
c->SetPetCommandState(PET_BUTTON_REGROUP, 0);
|
||||
@@ -1665,7 +1663,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
#endif
|
||||
// This is handled by the client prior to SoD.
|
||||
//
|
||||
if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater))
|
||||
if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoDAndLater))
|
||||
CastToClient()->LocateCorpse();
|
||||
|
||||
break;
|
||||
@@ -2472,7 +2470,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
case SE_FcTimerRefresh:
|
||||
{
|
||||
if(IsClient()) {
|
||||
for(unsigned int i =0 ; i < MAX_PP_MEMSPELL; ++i) {
|
||||
for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) {
|
||||
if(IsValidSpell(CastToClient()->m_pp.mem_spells[i])) {
|
||||
if (CalcFocusEffect(focusFcTimerRefresh, spell_id, CastToClient()->m_pp.mem_spells[i])){
|
||||
CastToClient()->m_pp.spellSlotRefresh[i] = 1;
|
||||
@@ -2741,7 +2739,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
|
||||
|
||||
if (caster && IsValidSpell(spells[spell_id].base2[i])){
|
||||
if(zone->random.Roll(spells[spell_id].base[i]))
|
||||
caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3404,7 +3402,7 @@ void Mob::BuffProcess()
|
||||
Log(Logs::Detail, Logs::Spells, "Buff %d in slot %d has %d tics remaining.", buffs[buffs_i].spellid, buffs_i, buffs[buffs_i].ticsremaining);
|
||||
}
|
||||
}
|
||||
else if (IsClient() && !(CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoFAndLater))
|
||||
else if (IsClient() && !(CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater))
|
||||
{
|
||||
buffs[buffs_i].UpdateClient = true;
|
||||
}
|
||||
@@ -3664,14 +3662,14 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster)
|
||||
case SE_CastOnFadeEffectNPC:
|
||||
case SE_CastOnFadeEffectAlways: {
|
||||
if (buff.ticsremaining == 0) {
|
||||
SpellFinished(spells[buff.spellid].base[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base[i]].ResistDiff);
|
||||
SpellFinished(spells[buff.spellid].base[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base[i]].ResistDiff);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SE_LocateCorpse: {
|
||||
// This is handled by the client prior to SoD.
|
||||
|
||||
if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater))
|
||||
if (IsClient() && (CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoDAndLater))
|
||||
CastToClient()->LocateCorpse();
|
||||
}
|
||||
|
||||
@@ -4038,63 +4036,6 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||
SetLevel(GetOrigLevel());
|
||||
break;
|
||||
}
|
||||
|
||||
case SE_MovementSpeed:
|
||||
{
|
||||
if(IsClient())
|
||||
{
|
||||
Client *my_c = CastToClient();
|
||||
uint32 cur_time = Timer::GetCurrentTime();
|
||||
if((cur_time - my_c->m_TimeSinceLastPositionCheck) > 1000)
|
||||
{
|
||||
float speed = (my_c->m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - my_c->m_TimeSinceLastPositionCheck);
|
||||
float runs = my_c->GetRunspeed();
|
||||
if(speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
if(!my_c->GetGMSpeed() && (runs >= my_c->GetBaseRunspeed() || (speed > (my_c->GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor)))))
|
||||
{
|
||||
printf("%s %i moving too fast! moved: %.2f in %ims, speed %.2f\n", __FILE__, __LINE__,
|
||||
my_c->m_DistanceSinceLastPositionCheck, (cur_time - my_c->m_TimeSinceLastPositionCheck), speed);
|
||||
if(my_c->IsShadowStepExempted())
|
||||
{
|
||||
if(my_c->m_DistanceSinceLastPositionCheck > 800)
|
||||
{
|
||||
my_c->CheatDetected(MQWarpShadowStep, my_c->GetX(), my_c->GetY(), my_c->GetZ());
|
||||
}
|
||||
}
|
||||
else if(my_c->IsKnockBackExempted())
|
||||
{
|
||||
//still potential to trigger this if you're knocked back off a
|
||||
//HUGE fall that takes > 2.5 seconds
|
||||
if(speed > 30.0f)
|
||||
{
|
||||
my_c->CheatDetected(MQWarpKnockBack, my_c->GetX(), my_c->GetY(), my_c->GetZ());
|
||||
}
|
||||
}
|
||||
else if(!my_c->IsPortExempted())
|
||||
{
|
||||
if(!my_c->IsMQExemptedArea(zone->GetZoneID(), my_c->GetX(), my_c->GetY(), my_c->GetZ()))
|
||||
{
|
||||
if(speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor)))
|
||||
{
|
||||
my_c->m_TimeSinceLastPositionCheck = cur_time;
|
||||
my_c->m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
my_c->CheatDetected(MQWarp, my_c->GetX(), my_c->GetY(), my_c->GetZ());
|
||||
//my_c->Death(my_c, 10000000, SPELL_UNKNOWN, _1H_BLUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_c->CheatDetected(MQWarpLight, my_c->GetX(), my_c->GetY(), my_c->GetZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
my_c->m_TimeSinceLastPositionCheck = cur_time;
|
||||
my_c->m_DistanceSinceLastPositionCheck = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4144,7 +4085,7 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket();
|
||||
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater);
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::maskSoDAndLater);
|
||||
if(IsClient() && GetTarget() == this) {
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
}
|
||||
@@ -4154,11 +4095,11 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
||||
|
||||
if (IsNPC()) {
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket();
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater, true);
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::maskSoDAndLater, true);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::bit_UFAndLater)
|
||||
if (IsClient() && CastToClient()->ClientVersionBit() & EQEmu::versions::maskUFAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket(false);
|
||||
CastToClient()->FastQueuePacket(&outapp);
|
||||
@@ -5159,7 +5100,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
||||
|
||||
if (Caston_spell_id) {
|
||||
if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id))
|
||||
SpellFinished(Caston_spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff);
|
||||
SpellFinished(Caston_spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff);
|
||||
}
|
||||
|
||||
return (value * lvlModifier / 100);
|
||||
@@ -6722,10 +6663,10 @@ void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){
|
||||
if (IsValidSpell(spell_id)) {
|
||||
|
||||
if (IsBeneficialSpell(spell_id))
|
||||
SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
|
||||
else if(attacker)
|
||||
SpellFinished(spell_id, attacker, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
SpellFinished(spell_id, attacker, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-63
@@ -107,7 +107,7 @@ extern volatile bool is_zone_loaded;
|
||||
extern WorldServer worldserver;
|
||||
extern FastMath g_Math;
|
||||
|
||||
using EQEmu::CastingSlot;
|
||||
using EQEmu::spells::CastingSlot;
|
||||
|
||||
// this is run constantly for every mob
|
||||
void Mob::SpellProcess()
|
||||
@@ -305,8 +305,9 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
|
||||
}
|
||||
|
||||
//To prevent NPC ghosting when spells are cast from scripts
|
||||
if (IsNPC() && IsMoving() && cast_time > 0)
|
||||
SendPosition();
|
||||
if (IsNPC() && IsMoving() && cast_time > 0) {
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
if(resist_adjust)
|
||||
{
|
||||
@@ -2665,23 +2666,6 @@ void Mob::BardPulse(uint16 spell_id, Mob *caster) {
|
||||
|
||||
action->effect_flag = 4;
|
||||
|
||||
if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f)
|
||||
{
|
||||
if(IsClient())
|
||||
{
|
||||
if(!IsBuffSpell(spell_id))
|
||||
{
|
||||
CastToClient()->SetKnockBackExemption(true);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep))
|
||||
{
|
||||
CastToClient()->SetShadowStepExemption(true);
|
||||
}
|
||||
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||
{
|
||||
CastToClient()->QueuePacket(packet);
|
||||
@@ -3333,7 +3317,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket();
|
||||
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater);
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::maskSoDAndLater);
|
||||
|
||||
if(IsClient() && GetTarget() == this)
|
||||
CastToClient()->QueuePacket(outapp);
|
||||
@@ -3343,7 +3327,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
|
||||
if (IsNPC()) {
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket();
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::bit_SoDAndLater, true);
|
||||
entity_list.QueueClientsByTarget(this, outapp, false, nullptr, true, false, EQEmu::versions::maskSoDAndLater, true);
|
||||
safe_delete(outapp);
|
||||
}
|
||||
|
||||
@@ -3947,13 +3931,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
|
||||
if(spells[spell_id].pushback != 0.0f || spells[spell_id].pushup != 0.0f)
|
||||
{
|
||||
if(spelltar->IsClient())
|
||||
{
|
||||
if(!IsBuffSpell(spell_id))
|
||||
{
|
||||
spelltar->CastToClient()->SetKnockBackExemption(true);
|
||||
}
|
||||
} else if (RuleB(Spells, NPCSpellPush) && !spelltar->IsRooted() && spelltar->ForcedMovement == 0) {
|
||||
if (RuleB(Spells, NPCSpellPush) && !spelltar->IsRooted() && spelltar->ForcedMovement == 0) {
|
||||
spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading);
|
||||
spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading);
|
||||
spelltar->m_Delta.z += action->hit_pitch;
|
||||
@@ -3961,11 +3939,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r
|
||||
}
|
||||
}
|
||||
|
||||
if(spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep))
|
||||
{
|
||||
spelltar->CastToClient()->SetShadowStepExemption(true);
|
||||
}
|
||||
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||
{
|
||||
if(spelltar != this && spelltar->IsClient()) // send to target
|
||||
@@ -4929,12 +4902,11 @@ void Client::UnStun() {
|
||||
|
||||
void NPC::Stun(int duration) {
|
||||
Mob::Stun(duration);
|
||||
SetCurrentSpeed(0);
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
void NPC::UnStun() {
|
||||
Mob::UnStun();
|
||||
SetCurrentSpeed(GetRunspeed());
|
||||
}
|
||||
|
||||
void Mob::Mesmerize()
|
||||
@@ -4944,18 +4916,7 @@ void Mob::Mesmerize()
|
||||
if (casting_spell_id)
|
||||
InterruptSpell();
|
||||
|
||||
SendPosition();
|
||||
/* this stuns the client for max time, with no way to break it
|
||||
if (this->IsClient()){
|
||||
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Stun, sizeof(Stun_Struct));
|
||||
Stun_Struct* stunon = (Stun_Struct*) outapp->pBuffer;
|
||||
stunon->duration = 0xFFFF;
|
||||
this->CastToClient()->QueuePacket(outapp);
|
||||
safe_delete(outapp);
|
||||
} else {
|
||||
SetRunAnimSpeed(0);
|
||||
}
|
||||
*/
|
||||
StopNavigation();
|
||||
}
|
||||
|
||||
void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)
|
||||
@@ -5007,7 +4968,7 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message)
|
||||
|
||||
void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
|
||||
{
|
||||
if(slot >= MAX_PP_MEMSPELL || slot < 0)
|
||||
if(slot >= EQEmu::spells::SPELL_GEM_COUNT || slot < 0)
|
||||
return;
|
||||
|
||||
if(update_client)
|
||||
@@ -5029,7 +4990,7 @@ void Client::MemSpell(uint16 spell_id, int slot, bool update_client)
|
||||
|
||||
void Client::UnmemSpell(int slot, bool update_client)
|
||||
{
|
||||
if(slot > MAX_PP_MEMSPELL || slot < 0)
|
||||
if(slot > EQEmu::spells::SPELL_GEM_COUNT || slot < 0)
|
||||
return;
|
||||
|
||||
Log(Logs::Detail, Logs::Spells, "Spell %d forgotten from slot %d", m_pp.mem_spells[slot], slot);
|
||||
@@ -5045,7 +5006,7 @@ void Client::UnmemSpell(int slot, bool update_client)
|
||||
|
||||
void Client::UnmemSpellBySpellID(int32 spell_id)
|
||||
{
|
||||
for(int i = 0; i < MAX_PP_MEMSPELL; i++) {
|
||||
for(int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) {
|
||||
if(m_pp.mem_spells[i] == spell_id) {
|
||||
UnmemSpell(i, true);
|
||||
break;
|
||||
@@ -5057,14 +5018,14 @@ void Client::UnmemSpellAll(bool update_client)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_PP_MEMSPELL; i++)
|
||||
for(i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++)
|
||||
if(m_pp.mem_spells[i] != 0xFFFFFFFF)
|
||||
UnmemSpell(i, update_client);
|
||||
}
|
||||
|
||||
void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client)
|
||||
{
|
||||
if(slot >= MAX_PP_SPELLBOOK || slot < 0)
|
||||
if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0)
|
||||
return;
|
||||
|
||||
if(update_client)
|
||||
@@ -5085,7 +5046,7 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client)
|
||||
|
||||
void Client::UnscribeSpell(int slot, bool update_client)
|
||||
{
|
||||
if(slot >= MAX_PP_SPELLBOOK || slot < 0)
|
||||
if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0)
|
||||
return;
|
||||
|
||||
Log(Logs::Detail, Logs::Spells, "Spell %d erased from spell book slot %d", m_pp.spell_book[slot], slot);
|
||||
@@ -5107,7 +5068,7 @@ void Client::UnscribeSpellAll(bool update_client)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_PP_SPELLBOOK; i++)
|
||||
for(i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++)
|
||||
{
|
||||
if(m_pp.spell_book[i] != 0xFFFFFFFF)
|
||||
UnscribeSpell(i, update_client);
|
||||
@@ -5141,7 +5102,7 @@ void Client::UntrainDiscAll(bool update_client)
|
||||
}
|
||||
|
||||
int Client::GetNextAvailableSpellBookSlot(int starting_slot) {
|
||||
for (int i = starting_slot; i < MAX_PP_SPELLBOOK; i++) { //using starting_slot should help speed this up when we're iterating through a bunch of spells
|
||||
for (int i = starting_slot; i < EQEmu::spells::SPELLBOOK_SIZE; i++) { //using starting_slot should help speed this up when we're iterating through a bunch of spells
|
||||
if (!IsValidSpell(GetSpellByBookSlot(i)))
|
||||
return i;
|
||||
}
|
||||
@@ -5150,7 +5111,7 @@ int Client::GetNextAvailableSpellBookSlot(int starting_slot) {
|
||||
}
|
||||
|
||||
int Client::FindSpellBookSlotBySpellID(uint16 spellid) {
|
||||
for(int i = 0; i < MAX_PP_SPELLBOOK; i++) {
|
||||
for(int i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) {
|
||||
if(m_pp.spell_book[i] == spellid)
|
||||
return i;
|
||||
}
|
||||
@@ -5208,7 +5169,7 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) {
|
||||
std::string spell_bucket_name;
|
||||
int spell_bucket_value;
|
||||
int bucket_value;
|
||||
std::string query = StringFormat("SELECT key, value FROM spell_buckets WHERE spellid = %i", spell_id);
|
||||
std::string query = StringFormat("SELECT `key`, value FROM spell_buckets WHERE spellid = %i", spell_id);
|
||||
auto results = database.QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return false;
|
||||
@@ -5222,7 +5183,7 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) {
|
||||
if (spell_bucket_name.empty())
|
||||
return true;
|
||||
|
||||
query = StringFormat("SELECT value FROM data_buckets WHERE key = '%i-%s'", char_id, spell_bucket_name.c_str());
|
||||
query = StringFormat("SELECT value FROM data_buckets WHERE `key` = '%i-%s'", char_id, spell_bucket_name.c_str());
|
||||
results = database.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
Log(Logs::General, Logs::Error, "Spell bucket %s for spell ID %i for char ID %i failed.", spell_bucket_name.c_str(), spell_id, char_id);
|
||||
@@ -5449,7 +5410,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot)
|
||||
spell_id != SPELL_UNKNOWN &&
|
||||
slot != -1 &&
|
||||
GetClass() == BARD &&
|
||||
slot <= MAX_PP_MEMSPELL &&
|
||||
slot <= EQEmu::spells::SPELL_GEM_COUNT &&
|
||||
IsBardSong(spell_id)
|
||||
);
|
||||
}
|
||||
@@ -5570,7 +5531,7 @@ void Mob::SendBuffsToClient(Client *c)
|
||||
if(!c)
|
||||
return;
|
||||
|
||||
if (c->ClientVersionBit() & EQEmu::versions::bit_SoDAndLater)
|
||||
if (c->ClientVersionBit() & EQEmu::versions::maskSoDAndLater)
|
||||
{
|
||||
EQApplicationPacket *outapp = MakeBuffsPacket();
|
||||
c->FastQueuePacket(&outapp);
|
||||
@@ -5658,12 +5619,12 @@ int Client::GetCurrentBuffSlots() const
|
||||
numbuffs++;
|
||||
if (GetLevel() > 74)
|
||||
numbuffs++;
|
||||
return EQEmu::ClampUpper(numbuffs, EQEmu::constants::Lookup(m_ClientVersion)->LongBuffs);
|
||||
return EQEmu::ClampUpper(numbuffs, EQEmu::spells::StaticLookup(m_ClientVersion)->LongBuffs);
|
||||
}
|
||||
|
||||
int Client::GetCurrentSongSlots() const
|
||||
{
|
||||
return EQEmu::constants::Lookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this
|
||||
return EQEmu::spells::StaticLookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this
|
||||
}
|
||||
|
||||
void Client::InitializeBuffSlots()
|
||||
|
||||
+1
-1
@@ -2700,7 +2700,7 @@ void TaskManager::SendTaskActivityShort(Client *c, int TaskID, int ActivityID, i
|
||||
|
||||
TaskActivityShort_Struct* tass;
|
||||
|
||||
if (c->ClientVersionBit() & EQEmu::versions::bit_RoFAndLater)
|
||||
if (c->ClientVersionBit() & EQEmu::versions::maskRoFAndLater)
|
||||
{
|
||||
auto outapp = new EQApplicationPacket(OP_TaskActivity, 25);
|
||||
outapp->WriteUInt32(ClientTaskIndex);
|
||||
|
||||
+5
-5
@@ -135,7 +135,7 @@ void Trap::Trigger(Mob* trigger)
|
||||
entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str());
|
||||
}
|
||||
if(hiddenTrigger){
|
||||
hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff);
|
||||
hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::spells::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff);
|
||||
}
|
||||
break;
|
||||
case trapTypeAlarm:
|
||||
@@ -166,7 +166,7 @@ void Trap::Trigger(Mob* trigger)
|
||||
{
|
||||
auto randomOffset = glm::vec4(zone->random.Int(-5, 5),zone->random.Int(-5, 5),zone->random.Int(-5, 5), zone->random.Int(0, 249));
|
||||
auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f);
|
||||
auto new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3);
|
||||
auto new_npc = new NPC(tmp, nullptr, spawnPosition, GravityBehavior::Flying);
|
||||
new_npc->AddLootTable();
|
||||
if (new_npc->DropsGlobalLoot())
|
||||
new_npc->CheckGlobalLootTables();
|
||||
@@ -191,7 +191,7 @@ void Trap::Trigger(Mob* trigger)
|
||||
{
|
||||
auto randomOffset = glm::vec4(zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(-2, 2), zone->random.Int(0, 249));
|
||||
auto spawnPosition = randomOffset + glm::vec4(m_Position, 0.0f);
|
||||
auto new_npc = new NPC(tmp, nullptr, spawnPosition, FlyMode3);
|
||||
auto new_npc = new NPC(tmp, nullptr, spawnPosition, GravityBehavior::Flying);
|
||||
new_npc->AddLootTable();
|
||||
if (new_npc->DropsGlobalLoot())
|
||||
new_npc->CheckGlobalLootTables();
|
||||
@@ -456,7 +456,7 @@ void Trap::CreateHiddenTrigger()
|
||||
auto make_npc = new NPCType;
|
||||
memcpy(make_npc, base_type, sizeof(NPCType));
|
||||
make_npc->max_hp = 100000;
|
||||
make_npc->cur_hp = 100000;
|
||||
make_npc->current_hp = 100000;
|
||||
strcpy(make_npc->name, "a_trap");
|
||||
make_npc->runspeed = 0.0f;
|
||||
make_npc->bodytype = BT_Special;
|
||||
@@ -469,7 +469,7 @@ void Trap::CreateHiddenTrigger()
|
||||
make_npc->trackable = 0;
|
||||
make_npc->level = level;
|
||||
strcpy(make_npc->special_abilities, "19,1^20,1^24,1^25,1");
|
||||
NPC* npca = new NPC(make_npc, nullptr, glm::vec4(m_Position, 0.0f), FlyMode3);
|
||||
NPC* npca = new NPC(make_npc, nullptr, glm::vec4(m_Position, 0.0f), GravityBehavior::Flying);
|
||||
npca->GiveNPCTypeData(make_npc);
|
||||
entity_list.AddNPC(npca);
|
||||
|
||||
|
||||
@@ -14,25 +14,30 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) {
|
||||
std::transform(zone_name.begin(), zone_name.end(), zone_name.begin(), ::tolower);
|
||||
|
||||
std::string file_path = Config->MapDir + "water/" + zone_name + std::string(".wtr");
|
||||
Log(Logs::General, Logs::Debug, "Attempting to load water map with path %s", file_path.c_str());
|
||||
FILE *f = fopen(file_path.c_str(), "rb");
|
||||
if(f) {
|
||||
char magic[10];
|
||||
uint32 version;
|
||||
if(fread(magic, 10, 1, f) != 1) {
|
||||
Log(Logs::General, Logs::Debug, "Failed to load water map, error reading magic string in header.");
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(strncmp(magic, "EQEMUWATER", 10)) {
|
||||
Log(Logs::General, Logs::Debug, "Failed to load water map, bad magic string in header.");
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if(fread(&version, sizeof(version), 1, f) != 1) {
|
||||
Log(Logs::General, Logs::Debug, "Failed to load water map, error reading version.");
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Log(Logs::General, Logs::Debug, "Attempting to V%u load water map %s.", version, file_path.c_str());
|
||||
if(version == 1) {
|
||||
auto wm = new WaterMapV1();
|
||||
if(!wm->Load(f)) {
|
||||
@@ -56,10 +61,12 @@ WaterMap* WaterMap::LoadWaterMapfile(std::string zone_name) {
|
||||
fclose(f);
|
||||
return wm;
|
||||
} else {
|
||||
Log(Logs::General, Logs::Debug, "Failed to load water map, unsupported version V%u.", version);
|
||||
fclose(f);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Log(Logs::General, Logs::Debug, "Failed to load water map, could not open file for reading %s.", file_path.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
+68
-214
@@ -30,6 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "quest_parser_collection.h"
|
||||
#include "water_map.h"
|
||||
#include "fastmath.h"
|
||||
#include "mob_movement_manager.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
@@ -92,7 +93,7 @@ void NPC::StopWandering()
|
||||
{ // stops a mob from wandering, takes him off grid and sends him back to spawn point
|
||||
roamer = false;
|
||||
CastToNPC()->SetGrid(0);
|
||||
SendPosition();
|
||||
StopNavigation();
|
||||
Log(Logs::Detail, Logs::Pathing, "Stop Wandering requested.");
|
||||
return;
|
||||
}
|
||||
@@ -149,7 +150,7 @@ void NPC::PauseWandering(int pausetime)
|
||||
moving = false;
|
||||
DistractedFromGrid = true;
|
||||
Log(Logs::Detail, Logs::Pathing, "Paused Wandering requested. Grid %d. Resuming in %d ms (0=not until told)", GetGrid(), pausetime);
|
||||
SendPosition();
|
||||
StopNavigation();
|
||||
if (pausetime < 1) { // negative grid number stops him dead in his tracks until ResumeWandering()
|
||||
SetGrid(0 - GetGrid());
|
||||
}
|
||||
@@ -332,8 +333,6 @@ void NPC::CalculateNewWaypoint()
|
||||
}
|
||||
}
|
||||
|
||||
tar_ndx = 52;
|
||||
|
||||
// Preserve waypoint setting for quest controlled NPCs
|
||||
if (cur_wp < 0)
|
||||
cur_wp = old_wp;
|
||||
@@ -391,13 +390,8 @@ void NPC::SetWaypointPause()
|
||||
{
|
||||
//Declare time to wait on current WP
|
||||
|
||||
if (cur_wp_pause == 0) {
|
||||
AI_walking_timer->Start(100);
|
||||
AI_walking_timer->Trigger();
|
||||
}
|
||||
else
|
||||
if(cur_wp_pause > 0)
|
||||
{
|
||||
|
||||
switch (pausetype)
|
||||
{
|
||||
case 0: //Random Half
|
||||
@@ -413,31 +407,22 @@ void NPC::SetWaypointPause()
|
||||
}
|
||||
}
|
||||
|
||||
void NPC::SaveGuardSpot(bool iClearGuardSpot) {
|
||||
if (iClearGuardSpot) {
|
||||
Log(Logs::Detail, Logs::AI, "Clearing guard order.");
|
||||
m_GuardPoint = glm::vec4();
|
||||
}
|
||||
else {
|
||||
m_GuardPoint = m_Position;
|
||||
void NPC::SaveGuardSpot(const glm::vec4 &pos)
|
||||
{
|
||||
m_GuardPoint = pos;
|
||||
|
||||
if (m_GuardPoint.w == 0)
|
||||
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
|
||||
Log(Logs::Detail, Logs::AI, "Setting guard position to %s", to_string(static_cast<glm::vec3>(m_GuardPoint)).c_str());
|
||||
}
|
||||
if (m_GuardPoint.w == 0)
|
||||
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
|
||||
LogF(Logs::Detail, Logs::AI, "Setting guard position to {0}", to_string(static_cast<glm::vec3>(m_GuardPoint)));
|
||||
}
|
||||
|
||||
void NPC::NextGuardPosition() {
|
||||
if (!CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed())) {
|
||||
SetHeading(m_GuardPoint.w);
|
||||
Log(Logs::Detail, Logs::AI, "Unable to move to next guard position. Probably rooted.");
|
||||
}
|
||||
else if ((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z))
|
||||
NavigateTo(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z);
|
||||
if (IsPositionEqualWithinCertainZ(m_Position, m_GuardPoint, 5.0f))
|
||||
{
|
||||
if (moved)
|
||||
{
|
||||
moved = false;
|
||||
SetCurrentSpeed(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -446,179 +431,48 @@ float Mob::CalculateDistance(float x, float y, float z) {
|
||||
return (float)sqrtf(((m_Position.x - x)*(m_Position.x - x)) + ((m_Position.y - y)*(m_Position.y - y)) + ((m_Position.z - z)*(m_Position.z - z)));
|
||||
}
|
||||
|
||||
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, bool check_z, bool calculate_heading) {
|
||||
if (GetID() == 0)
|
||||
return true;
|
||||
|
||||
if (speed <= 0) {
|
||||
SetCurrentSpeed(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((m_Position.x - x == 0) && (m_Position.y - y == 0)) { //spawn is at target coords
|
||||
return false;
|
||||
}
|
||||
else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) {
|
||||
if (IsNPC()) {
|
||||
entity_list.ProcessMove(CastToNPC(), x, y, z);
|
||||
}
|
||||
|
||||
m_Position.x = x;
|
||||
m_Position.y = y;
|
||||
m_Position.z = z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int compare_steps = 20;
|
||||
if (tar_ndx < compare_steps && m_TargetLocation.x == x && m_TargetLocation.y == y) {
|
||||
|
||||
float new_x = m_Position.x + m_TargetV.x * tar_vector;
|
||||
float new_y = m_Position.y + m_TargetV.y * tar_vector;
|
||||
float new_z = m_Position.z + m_TargetV.z * tar_vector;
|
||||
|
||||
if (IsNPC()) {
|
||||
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
||||
}
|
||||
|
||||
m_Position.x = new_x;
|
||||
m_Position.y = new_y;
|
||||
m_Position.z = new_z;
|
||||
|
||||
if (check_z && fix_z_timer.Check() && (!this->IsEngaged() || flee_mode || currently_fleeing)) {
|
||||
this->FixZ();
|
||||
}
|
||||
|
||||
tar_ndx++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tar_ndx > 50) {
|
||||
tar_ndx--;
|
||||
}
|
||||
else {
|
||||
tar_ndx = 0;
|
||||
}
|
||||
|
||||
m_TargetLocation = glm::vec3(x, y, z);
|
||||
|
||||
float nx = this->m_Position.x;
|
||||
float ny = this->m_Position.y;
|
||||
float nz = this->m_Position.z;
|
||||
// float nh = this->heading;
|
||||
|
||||
m_TargetV.x = x - nx;
|
||||
m_TargetV.y = y - ny;
|
||||
m_TargetV.z = z - nz;
|
||||
SetCurrentSpeed((int8)speed);
|
||||
pRunAnimSpeed = speed;
|
||||
#ifdef BOTS
|
||||
if (IsClient() || IsBot())
|
||||
#else
|
||||
if (IsClient())
|
||||
#endif
|
||||
{
|
||||
animation = speed / 2;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// 2: get unit vector
|
||||
// --------------------------------------------------------------------------
|
||||
float mag = sqrtf(m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z);
|
||||
tar_vector = (float)speed / mag;
|
||||
|
||||
// mob move fix
|
||||
int numsteps = (int)(mag * 13.5f / (float)speed + 0.5f);
|
||||
|
||||
|
||||
// mob move fix
|
||||
|
||||
if (numsteps < 20) {
|
||||
if (numsteps > 1) {
|
||||
tar_vector = 1.0f;
|
||||
m_TargetV.x = m_TargetV.x / (float) numsteps;
|
||||
m_TargetV.y = m_TargetV.y / (float) numsteps;
|
||||
m_TargetV.z = m_TargetV.z / (float) numsteps;
|
||||
|
||||
float new_x = m_Position.x + m_TargetV.x;
|
||||
float new_y = m_Position.y + m_TargetV.y;
|
||||
float new_z = m_Position.z + m_TargetV.z;
|
||||
if (IsNPC()) {
|
||||
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
||||
}
|
||||
|
||||
m_Position.x = new_x;
|
||||
m_Position.y = new_y;
|
||||
m_Position.z = new_z;
|
||||
if (calculate_heading) {
|
||||
m_Position.w = CalculateHeadingToTarget(x, y);
|
||||
}
|
||||
tar_ndx = 20 - numsteps;
|
||||
}
|
||||
else {
|
||||
if (IsNPC()) {
|
||||
entity_list.ProcessMove(CastToNPC(), x, y, z);
|
||||
}
|
||||
|
||||
m_Position.x = x;
|
||||
m_Position.y = y;
|
||||
m_Position.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
tar_vector /= 13.5f;
|
||||
float dur = Timer::GetCurrentTime() - pLastChange;
|
||||
if (dur < 0.0f) {
|
||||
dur = 0.0f;
|
||||
}
|
||||
|
||||
if (dur > 100.f) {
|
||||
dur = 100.f;
|
||||
}
|
||||
|
||||
tar_vector *= (dur / 100.0f);
|
||||
|
||||
float new_x = m_Position.x + m_TargetV.x * tar_vector;
|
||||
float new_y = m_Position.y + m_TargetV.y * tar_vector;
|
||||
float new_z = m_Position.z + m_TargetV.z * tar_vector;
|
||||
|
||||
if (IsNPC()) {
|
||||
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
|
||||
}
|
||||
|
||||
m_Position.x = new_x;
|
||||
m_Position.y = new_y;
|
||||
m_Position.z = new_z;
|
||||
if (calculate_heading) {
|
||||
m_Position.w = CalculateHeadingToTarget(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
if (check_z && fix_z_timer.Check() && !this->IsEngaged())
|
||||
this->FixZ();
|
||||
|
||||
SetMoving(true);
|
||||
moved = true;
|
||||
|
||||
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
|
||||
|
||||
if (IsClient()) {
|
||||
SendPositionUpdate(1);
|
||||
CastToClient()->ResetPositionTimer();
|
||||
}
|
||||
else {
|
||||
SendPositionUpdate();
|
||||
SetAppearance(eaStanding, false);
|
||||
}
|
||||
|
||||
pLastChange = Timer::GetCurrentTime();
|
||||
return true;
|
||||
void Mob::WalkTo(float x, float y, float z)
|
||||
{
|
||||
mMovementManager->NavigateTo(this, x, y, z, MovementWalking);
|
||||
}
|
||||
|
||||
bool Mob::CalculateNewPosition(float x, float y, float z, float speed, bool check_z, bool calculate_heading) {
|
||||
return MakeNewPositionAndSendUpdate(x, y, z, speed, check_z);
|
||||
void Mob::RunTo(float x, float y, float z)
|
||||
{
|
||||
mMovementManager->NavigateTo(this, x, y, z, MovementRunning);
|
||||
}
|
||||
|
||||
void Mob::NavigateTo(float x, float y, float z)
|
||||
{
|
||||
if (IsRunning()) {
|
||||
RunTo(x, y, z);
|
||||
}
|
||||
else {
|
||||
WalkTo(x, y, z);
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::RotateTo(float new_heading)
|
||||
{
|
||||
if (IsRunning()) {
|
||||
RotateToRunning(new_heading);
|
||||
}
|
||||
else {
|
||||
RotateToWalking(new_heading);
|
||||
}
|
||||
}
|
||||
|
||||
void Mob::RotateToWalking(float new_heading)
|
||||
{
|
||||
mMovementManager->RotateTo(this, new_heading, MovementWalking);
|
||||
}
|
||||
|
||||
void Mob::RotateToRunning(float new_heading)
|
||||
{
|
||||
mMovementManager->RotateTo(this, new_heading, MovementRunning);
|
||||
}
|
||||
|
||||
void Mob::StopNavigation() {
|
||||
mMovementManager->StopNavigation(this);
|
||||
}
|
||||
|
||||
void NPC::AssignWaypoints(int32 grid)
|
||||
@@ -683,9 +537,6 @@ void NPC::AssignWaypoints(int32 grid)
|
||||
|
||||
if (wandertype == 1 || wandertype == 2 || wandertype == 5)
|
||||
CalculateNewWaypoint();
|
||||
|
||||
if (wandertype == 1 || wandertype == 2 || wandertype == 5)
|
||||
CalculateNewWaypoint();
|
||||
}
|
||||
|
||||
void Mob::SendTo(float new_x, float new_y, float new_z) {
|
||||
@@ -698,7 +549,7 @@ void Mob::SendTo(float new_x, float new_y, float new_z) {
|
||||
m_Position.z = new_z;
|
||||
Log(Logs::Detail, Logs::AI, "Sent To (%.3f, %.3f, %.3f)", new_x, new_y, new_z);
|
||||
|
||||
if (flymode == FlyMode1)
|
||||
if (flymode == GravityBehavior::Flying)
|
||||
return;
|
||||
|
||||
//fix up pathing Z, this shouldent be needed IF our waypoints
|
||||
@@ -748,21 +599,18 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) {
|
||||
}
|
||||
}
|
||||
|
||||
float Mob::GetFixedZ(glm::vec3 destination, int32 z_find_offset) {
|
||||
float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
|
||||
BenchTimer timer;
|
||||
timer.reset();
|
||||
|
||||
float new_z = destination.z;
|
||||
|
||||
if (zone->HasMap() && RuleB(Map, FixZWhenMoving)) {
|
||||
if (zone->HasMap()) {
|
||||
|
||||
if (flymode == 1 || flymode == 2)
|
||||
if (flymode == GravityBehavior::Flying)
|
||||
return new_z;
|
||||
|
||||
if (this->IsBoat())
|
||||
return new_z;
|
||||
|
||||
if (zone->HasWaterMap() && zone->watermap->InWater(glm::vec3(m_Position)))
|
||||
if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position)))
|
||||
return new_z;
|
||||
|
||||
/*
|
||||
@@ -794,11 +642,19 @@ float Mob::GetFixedZ(glm::vec3 destination, int32 z_find_offset) {
|
||||
}
|
||||
|
||||
void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) {
|
||||
glm::vec3 current_loc(m_Position);
|
||||
|
||||
if (IsClient() && !fix_client_z)
|
||||
if (IsClient() && !fix_client_z) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flymode == GravityBehavior::Flying) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (zone->watermap && zone->watermap->InLiquid(m_Position)) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec3 current_loc(m_Position);
|
||||
float new_z = GetFixedZ(current_loc, z_find_offset);
|
||||
|
||||
if (new_z == m_Position.z)
|
||||
@@ -958,8 +814,6 @@ void Mob::TryMoveAlong(float distance, float angle, bool send)
|
||||
|
||||
new_pos.z = GetFixedZ(new_pos);
|
||||
Teleport(new_pos);
|
||||
if (send)
|
||||
SendPositionUpdate();
|
||||
}
|
||||
|
||||
int ZoneDatabase::GetHighestGrid(uint32 zoneid) {
|
||||
|
||||
@@ -1772,7 +1772,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
zone->GetLongName(),
|
||||
zone->GetInstanceID()
|
||||
);
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset());
|
||||
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadLogs: {
|
||||
|
||||
+17
-9
@@ -53,6 +53,8 @@
|
||||
#include "worldserver.h"
|
||||
#include "zone.h"
|
||||
#include "zone_config.h"
|
||||
#include "mob_movement_manager.h"
|
||||
#include "npc_scale_manager.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <ctime>
|
||||
@@ -64,8 +66,6 @@
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
extern bool staticzone;
|
||||
extern NetConnection net;
|
||||
extern PetitionList petition_list;
|
||||
@@ -73,6 +73,7 @@ extern QuestParserCollection* parse;
|
||||
extern uint32 numclients;
|
||||
extern WorldServer worldserver;
|
||||
extern Zone* zone;
|
||||
extern NpcScaleManager* npc_scale_manager;
|
||||
|
||||
Mutex MZoneShutdown;
|
||||
|
||||
@@ -861,6 +862,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
||||
|
||||
m_ucss_available = false;
|
||||
m_last_ucss_update = 0;
|
||||
|
||||
mMovementManager = &MobMovementManager::Get();
|
||||
}
|
||||
|
||||
Zone::~Zone() {
|
||||
@@ -901,7 +904,7 @@ bool Zone::Init(bool iStaticZone) {
|
||||
std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset);
|
||||
if(r_name.size() > 0)
|
||||
{
|
||||
RuleManager::Instance()->LoadRules(&database, r_name.c_str());
|
||||
RuleManager::Instance()->LoadRules(&database, r_name.c_str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1296,6 +1299,8 @@ bool Zone::Process() {
|
||||
|
||||
if(hotzone_timer.Check()) { UpdateHotzone(); }
|
||||
|
||||
mMovementManager->Process();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1504,18 +1509,22 @@ void Zone::RepopClose(const glm::vec4& client_position, uint32 repop_distance)
|
||||
mod_repop();
|
||||
}
|
||||
|
||||
void Zone::Repop(uint32 delay) {
|
||||
void Zone::Repop(uint32 delay)
|
||||
{
|
||||
|
||||
if(!Depop())
|
||||
if (!Depop()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LinkedListIterator<Spawn2*> iterator(spawn2_list);
|
||||
LinkedListIterator<Spawn2 *> iterator(spawn2_list);
|
||||
|
||||
iterator.Reset();
|
||||
while (iterator.MoreElements()) {
|
||||
iterator.RemoveCurrent();
|
||||
}
|
||||
|
||||
npc_scale_manager->LoadScaleData();
|
||||
|
||||
entity_list.ClearTrapPointers();
|
||||
|
||||
quest_manager.ClearAllTimers();
|
||||
@@ -1632,8 +1641,7 @@ ZonePoint* Zone::GetClosestZonePoint(const glm::vec3& location, uint32 to, Clien
|
||||
// this shouldn't open up any exploits since those situations are detected later on
|
||||
if ((zone->HasWaterMap() && !zone->watermap->InZoneLine(glm::vec3(client->GetPosition()))) || (!zone->HasWaterMap() && closest_dist > 400.0f && closest_dist < max_distance2))
|
||||
{
|
||||
if(client)
|
||||
client->CheatDetected(MQZoneUnknownDest, location.x, location.y, location.z); // Someone is trying to use /zone
|
||||
//TODO cheat detection
|
||||
Log(Logs::General, Logs::Status, "WARNING: Closest zone point for zone id %d is %f, you might need to update your zone_points table if you dont arrive at the right spot.", to, closest_dist);
|
||||
Log(Logs::General, Logs::Status, "<Real Zone Points>. %s", to_string(location).c_str());
|
||||
}
|
||||
@@ -2242,7 +2250,7 @@ void Zone::DoAdventureActions()
|
||||
const NPCType* tmp = database.LoadNPCTypesData(ds->data_id);
|
||||
if(tmp)
|
||||
{
|
||||
NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), FlyMode3);
|
||||
NPC* npc = new NPC(tmp, nullptr, glm::vec4(ds->assa_x, ds->assa_y, ds->assa_z, ds->assa_h), GravityBehavior::Water);
|
||||
npc->AddLootTable();
|
||||
if (npc->DropsGlobalLoot())
|
||||
npc->CheckGlobalLootTables();
|
||||
|
||||
@@ -79,6 +79,7 @@ class WaterMap;
|
||||
extern EntityList entity_list;
|
||||
struct NPCType;
|
||||
struct ServerZoneIncomingClient_Struct;
|
||||
class MobMovementManager;
|
||||
|
||||
class Zone
|
||||
{
|
||||
@@ -362,6 +363,8 @@ private:
|
||||
|
||||
bool m_ucss_available;
|
||||
uint32 m_last_ucss_update;
|
||||
|
||||
MobMovementManager *mMovementManager;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+11
-9
@@ -1204,12 +1204,12 @@ bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_
|
||||
auto results = database.QueryDatabase(query);
|
||||
int i = 0;
|
||||
/* Initialize Spells */
|
||||
for (i = 0; i < MAX_PP_MEMSPELL; i++){
|
||||
for (i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++){
|
||||
pp->mem_spells[i] = 0xFFFFFFFF;
|
||||
}
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
i = atoi(row[0]);
|
||||
if (i < MAX_PP_MEMSPELL && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
if (i < EQEmu::spells::SPELL_GEM_COUNT && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
pp->mem_spells[i] = atoi(row[1]);
|
||||
}
|
||||
}
|
||||
@@ -1227,12 +1227,12 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str
|
||||
auto results = database.QueryDatabase(query);
|
||||
int i = 0;
|
||||
/* Initialize Spells */
|
||||
for (i = 0; i < MAX_PP_SPELLBOOK; i++){
|
||||
for (i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++){
|
||||
pp->spell_book[i] = 0xFFFFFFFF;
|
||||
}
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
i = atoi(row[0]);
|
||||
if (i < MAX_PP_SPELLBOOK && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
if (i < EQEmu::spells::SPELLBOOK_SIZE && atoi(row[1]) <= SPDAT_RECORDS){
|
||||
pp->spell_book[i] = atoi(row[1]);
|
||||
}
|
||||
}
|
||||
@@ -1535,7 +1535,7 @@ bool ZoneDatabase::SaveCharacterTribute(uint32 character_id, PlayerProfile_Struc
|
||||
QueryDatabase(query);
|
||||
/* Save Tributes only if we have values... */
|
||||
for (int i = 0; i < EQEmu::invtype::TRIBUTE_SIZE; i++){
|
||||
if (pp->tributes[i].tribute > 0 && pp->tributes[i].tribute != TRIBUTE_NONE){
|
||||
if (pp->tributes[i].tribute >= 0 && pp->tributes[i].tribute != TRIBUTE_NONE){
|
||||
std::string query = StringFormat("REPLACE INTO `character_tribute` (id, tier, tribute) VALUES (%u, %u, %u)", character_id, pp->tributes[i].tier, pp->tributes[i].tribute);
|
||||
QueryDatabase(query);
|
||||
Log(Logs::General, Logs::None, "ZoneDatabase::SaveCharacterTribute for character ID: %i, tier:%u tribute:%u done", character_id, pp->tributes[i].tier, pp->tributes[i].tribute);
|
||||
@@ -2471,7 +2471,8 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
||||
"npc_types.charm_avoidance_rating, "
|
||||
"npc_types.charm_atk, "
|
||||
"npc_types.skip_global_loot, "
|
||||
"npc_types.rare_spawn "
|
||||
"npc_types.rare_spawn, "
|
||||
"npc_types.stuck_behavior "
|
||||
"FROM npc_types %s",
|
||||
where_condition.c_str()
|
||||
);
|
||||
@@ -2494,7 +2495,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
||||
temp_npctype_data->race = atoi(row[3]);
|
||||
temp_npctype_data->class_ = atoi(row[4]);
|
||||
temp_npctype_data->max_hp = atoi(row[5]);
|
||||
temp_npctype_data->cur_hp = temp_npctype_data->max_hp;
|
||||
temp_npctype_data->current_hp = temp_npctype_data->max_hp;
|
||||
temp_npctype_data->Mana = atoi(row[6]);
|
||||
temp_npctype_data->gender = atoi(row[7]);
|
||||
temp_npctype_data->texture = atoi(row[8]);
|
||||
@@ -2660,6 +2661,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
|
||||
|
||||
temp_npctype_data->skip_global_loot = atoi(row[107]) != 0;
|
||||
temp_npctype_data->rare_spawn = atoi(row[108]) != 0;
|
||||
temp_npctype_data->stuck_behavior = atoi(row[109]);
|
||||
|
||||
// If NPC with duplicate NPC id already in table,
|
||||
// free item we attempted to add.
|
||||
@@ -2775,7 +2777,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client
|
||||
tmpNPCType->race = atoi(row[3]);
|
||||
tmpNPCType->class_ = atoi(row[4]);
|
||||
tmpNPCType->max_hp = atoi(row[5]);
|
||||
tmpNPCType->cur_hp = tmpNPCType->max_hp;
|
||||
tmpNPCType->current_hp = tmpNPCType->max_hp;
|
||||
tmpNPCType->Mana = atoi(row[6]);
|
||||
tmpNPCType->gender = atoi(row[7]);
|
||||
tmpNPCType->texture = atoi(row[8]);
|
||||
@@ -3644,7 +3646,7 @@ void ZoneDatabase::LoadBuffs(Client *client)
|
||||
}
|
||||
|
||||
// We load up to the most our client supports
|
||||
max_slots = EQEmu::constants::Lookup(client->ClientVersion())->LongBuffs;
|
||||
max_slots = EQEmu::spells::StaticLookup(client->ClientVersion())->LongBuffs;
|
||||
for (int index = 0; index < max_slots; ++index) {
|
||||
if (!IsValidSpell(buffs[index].spellid))
|
||||
continue;
|
||||
|
||||
+41
-39
@@ -271,7 +271,12 @@ public:
|
||||
void DeleteBuyLines(uint32 CharID);
|
||||
void UpdateBuyLine(uint32 CharID, uint32 BuySlot, uint32 Quantity);
|
||||
|
||||
/* General Character Related Stuff */
|
||||
/**
|
||||
************************************************
|
||||
* Character
|
||||
************************************************
|
||||
*/
|
||||
|
||||
bool SetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
|
||||
uint32 GetServerFilters(char* name, ServerSideFilters_Struct *ssfs);
|
||||
|
||||
@@ -284,46 +289,43 @@ public:
|
||||
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);
|
||||
bool LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool DeleteCharacterAAs(uint32 character_id);
|
||||
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
|
||||
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
|
||||
bool DeleteCharacterDye(uint32 character_id);
|
||||
bool DeleteCharacterLeadershipAAs(uint32 character_id);
|
||||
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
|
||||
/* Character Data Saves */
|
||||
bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num);
|
||||
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges);
|
||||
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
|
||||
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
|
||||
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
|
||||
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
|
||||
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
|
||||
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
|
||||
bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterBandolier(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterBindPoint(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterData(uint32 character_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
bool LoadCharacterDisciplines(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterFactionValues(uint32 character_id, faction_map & val_list);
|
||||
bool LoadCharacterLanguages(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterMaterialColor(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterPotions(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterSkills(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool LoadCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
|
||||
/* Character Data Deletes */
|
||||
bool DeleteCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool DeleteCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool DeleteCharacterDisc(uint32 character_id, uint32 slot_id);
|
||||
bool DeleteCharacterBandolier(uint32 character_id, uint32 band_id);
|
||||
bool DeleteCharacterLeadershipAAs(uint32 character_id);
|
||||
bool DeleteCharacterAAs(uint32 character_id);
|
||||
bool DeleteCharacterDye(uint32 character_id);
|
||||
bool SaveCharacterAA(uint32 character_id, uint32 aa_id, uint32 current_level, uint32 charges);
|
||||
bool SaveCharacterBandolier(uint32 character_id, uint8 bandolier_id, uint8 bandolier_slot, uint32 item_id, uint32 icon, const char* bandolier_name);
|
||||
bool SaveCharacterBindPoint(uint32 character_id, const BindStruct &bind, uint32 bind_num);
|
||||
bool SaveCharacterCurrency(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp);
|
||||
bool SaveCharacterDisc(uint32 character_id, uint32 slot_id, uint32 disc_id);
|
||||
bool SaveCharacterLanguage(uint32 character_id, uint32 lang_id, uint32 value);
|
||||
bool SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
bool SaveCharacterMaterialColor(uint32 character_id, uint32 slot_id, uint32 color);
|
||||
bool SaveCharacterMemorizedSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool SaveCharacterPotionBelt(uint32 character_id, uint8 potion_id, uint32 item_id, uint32 icon);
|
||||
bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value);
|
||||
bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id);
|
||||
bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp);
|
||||
|
||||
/* Character Inventory */
|
||||
bool NoRentExpired(const char* name);
|
||||
|
||||
+2
-1
@@ -36,7 +36,7 @@ struct NPCType
|
||||
{
|
||||
char name[64];
|
||||
char lastname[70];
|
||||
int32 cur_hp;
|
||||
int32 current_hp;
|
||||
int32 max_hp;
|
||||
float size;
|
||||
float runspeed;
|
||||
@@ -143,6 +143,7 @@ struct NPCType
|
||||
bool untargetable;
|
||||
bool skip_global_loot;
|
||||
bool rare_spawn;
|
||||
int8 stuck_behavior;
|
||||
};
|
||||
|
||||
namespace player_lootitem {
|
||||
|
||||
+5
-10
@@ -95,7 +95,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
//unable to find a zone point... is there anything else
|
||||
//that can be a valid un-zolicited zone request?
|
||||
|
||||
CheatDetected(MQZone, zc->x, zc->y, zc->z);
|
||||
//Todo cheat detection
|
||||
Message(13, "Invalid unsolicited zone request.");
|
||||
Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
|
||||
SendZoneCancel(zc);
|
||||
@@ -130,7 +130,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
//then we assume this is invalid.
|
||||
if(!zone_point || zone_point->target_zone_id != target_zone_id) {
|
||||
Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%d'.", GetName(), target_zone_id);
|
||||
CheatDetected(MQGate, zc->x, zc->y, zc->z);
|
||||
//todo cheat detection
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
}
|
||||
@@ -252,7 +252,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
//for now, there are no other cases...
|
||||
|
||||
//could not find a valid reason for them to be zoning, stop it.
|
||||
CheatDetected(MQZoneUnknownDest, 0.0, 0.0, 0.0);
|
||||
//todo cheat detection
|
||||
Log(Logs::General, Logs::Error, "Zoning %s: Invalid unsolicited zone request to zone id '%s'. Not near a zone point.", GetName(), target_zone_name);
|
||||
SendZoneCancel(zc);
|
||||
return;
|
||||
@@ -296,7 +296,6 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||
void Client::SendZoneCancel(ZoneChange_Struct *zc) {
|
||||
//effectively zone them right back to where they were
|
||||
//unless we find a better way to stop the zoning process.
|
||||
SetPortExemption(true);
|
||||
EQApplicationPacket *outapp = nullptr;
|
||||
outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct));
|
||||
ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer;
|
||||
@@ -316,8 +315,6 @@ void Client::SendZoneError(ZoneChange_Struct *zc, int8 err)
|
||||
{
|
||||
Log(Logs::General, Logs::Error, "Zone %i is not available because target wasn't found or character insufficent level", zc->zoneID);
|
||||
|
||||
SetPortExemption(true);
|
||||
|
||||
EQApplicationPacket *outapp = nullptr;
|
||||
outapp = new EQApplicationPacket(OP_ZoneChange, sizeof(ZoneChange_Struct));
|
||||
ZoneChange_Struct *zc2 = (ZoneChange_Struct*)outapp->pBuffer;
|
||||
@@ -488,8 +485,6 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
||||
pShortZoneName = database.GetZoneName(zoneID);
|
||||
database.GetZoneLongName(pShortZoneName, &pZoneName);
|
||||
|
||||
SetPortExemption(true);
|
||||
|
||||
if(!pZoneName) {
|
||||
Message(13, "Invalid zone number specified");
|
||||
safe_delete_array(pZoneName);
|
||||
@@ -593,7 +588,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
||||
// If we are SoF and later and are respawning from hover, we want the real zone ID, else zero to use the old hack.
|
||||
//
|
||||
if(zone->GetZoneID() == zoneID) {
|
||||
if ((ClientVersionBit() & EQEmu::versions::bit_SoFAndLater) && (!RuleB(Character, RespawnFromHover) || !IsHoveringForRespawn()))
|
||||
if ((ClientVersionBit() & EQEmu::versions::maskSoFAndLater) && (!RuleB(Character, RespawnFromHover) || !IsHoveringForRespawn()))
|
||||
gmg->bind_zone_id = 0;
|
||||
else
|
||||
gmg->bind_zone_id = zoneID;
|
||||
@@ -669,7 +664,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
||||
m_Proximity = glm::vec3(m_Position);
|
||||
|
||||
//send out updates to people in zone.
|
||||
SendPosition();
|
||||
SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0);
|
||||
}
|
||||
|
||||
auto outapp =
|
||||
|
||||
Reference in New Issue
Block a user