mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-18 15:31:33 +00:00
Merge branch 'master' into lsid
This commit is contained in:
commit
3fdfc82ca0
@ -340,6 +340,7 @@ N(OP_MOTD),
|
|||||||
N(OP_MoveCoin),
|
N(OP_MoveCoin),
|
||||||
N(OP_MoveDoor),
|
N(OP_MoveDoor),
|
||||||
N(OP_MoveItem),
|
N(OP_MoveItem),
|
||||||
|
N(OP_MoveMultipleItems),
|
||||||
N(OP_MoveLogDisregard),
|
N(OP_MoveLogDisregard),
|
||||||
N(OP_MoveLogRequest),
|
N(OP_MoveLogRequest),
|
||||||
N(OP_MultiLineMsg),
|
N(OP_MultiLineMsg),
|
||||||
|
|||||||
@ -1827,6 +1827,20 @@ struct MoveItem_Struct
|
|||||||
/*0028*/
|
/*0028*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItemSub_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ InventorySlot_Struct from_slot;
|
||||||
|
/*0012*/ InventorySlot_Struct to_slot;
|
||||||
|
/*0024*/ uint32 number_in_stack;
|
||||||
|
/*0028*/ uint8 unknown[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItem_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ uint32 count;
|
||||||
|
/*0004*/ MultiMoveItemSub_Struct moves[0];
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// from_slot/to_slot
|
// from_slot/to_slot
|
||||||
// -1 - destroy
|
// -1 - destroy
|
||||||
|
|||||||
@ -52,6 +52,25 @@ struct EnterWorld_Struct {
|
|||||||
struct WorldObjectsSent_Struct {
|
struct WorldObjectsSent_Struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// yep, even SoF had a version of the new inventory system, used by OP_MoveMultipleItems
|
||||||
|
struct InventorySlot_Struct
|
||||||
|
{
|
||||||
|
/*000*/ int32 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Trade = 3, World = 4, Limbo = 5
|
||||||
|
/*004*/ int32 Slot;
|
||||||
|
/*008*/ int32 SubIndex;
|
||||||
|
/*012*/ int32 AugIndex;
|
||||||
|
/*016*/ int32 Unknown01;
|
||||||
|
};
|
||||||
|
|
||||||
|
// unsure if they have a version of this, completeness though
|
||||||
|
struct TypelessInventorySlot_Struct
|
||||||
|
{
|
||||||
|
/*000*/ int32 Slot;
|
||||||
|
/*004*/ int32 SubIndex;
|
||||||
|
/*008*/ int32 AugIndex;
|
||||||
|
/*012*/ int32 Unknown01;
|
||||||
|
};
|
||||||
|
|
||||||
/* Name Approval Struct */
|
/* Name Approval Struct */
|
||||||
/* Len: */
|
/* Len: */
|
||||||
/* Opcode: 0x8B20*/
|
/* Opcode: 0x8B20*/
|
||||||
@ -1557,6 +1576,19 @@ struct MoveItem_Struct
|
|||||||
/*0012*/
|
/*0012*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItemSub_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ InventorySlot_Struct from_slot;
|
||||||
|
/*0020*/ uint32 number_in_stack; // so the amount we are moving from the source
|
||||||
|
/*0024*/ InventorySlot_Struct to_slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItem_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ uint32 count;
|
||||||
|
/*0004*/ MultiMoveItemSub_Struct moves[0];
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// from_slot/to_slot
|
// from_slot/to_slot
|
||||||
// -1 - destroy
|
// -1 - destroy
|
||||||
|
|||||||
@ -48,6 +48,23 @@ struct EnterWorld_Struct {
|
|||||||
/*068*/ uint32 return_home; // 01 on "Return Home", 00 if not
|
/*068*/ uint32 return_home; // 01 on "Return Home", 00 if not
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// yep, even tit had a version of the new inventory system, used by OP_MoveMultipleItems
|
||||||
|
struct InventorySlot_Struct
|
||||||
|
{
|
||||||
|
/*000*/ int32 Type; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Trade = 3, World = 4, Limbo = 5
|
||||||
|
/*004*/ int32 Slot;
|
||||||
|
/*008*/ int32 SubIndex; // no aug index in Tit
|
||||||
|
/*012*/ int32 Unknown01;
|
||||||
|
};
|
||||||
|
|
||||||
|
// unsure if they have a version of this, completeness though
|
||||||
|
struct TypelessInventorySlot_Struct
|
||||||
|
{
|
||||||
|
/*000*/ int32 Slot;
|
||||||
|
/*004*/ int32 SubIndex; // no aug index in Tit
|
||||||
|
/*008*/ int32 Unknown01;
|
||||||
|
};
|
||||||
|
|
||||||
/* Name Approval Struct */
|
/* Name Approval Struct */
|
||||||
/* Len: */
|
/* Len: */
|
||||||
/* Opcode: 0x8B20*/
|
/* Opcode: 0x8B20*/
|
||||||
@ -1329,6 +1346,19 @@ struct MoveItem_Struct
|
|||||||
/*0012*/
|
/*0012*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItemSub_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ InventorySlot_Struct from_slot;
|
||||||
|
/*0016*/ uint32 number_in_stack; // so the amount we are moving from the source
|
||||||
|
/*0020*/ InventorySlot_Struct to_slot;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MultiMoveItem_Struct
|
||||||
|
{
|
||||||
|
/*0000*/ uint32 count;
|
||||||
|
/*0004*/ MultiMoveItemSub_Struct moves[0];
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// from_slot/to_slot
|
// from_slot/to_slot
|
||||||
// -1 - destroy
|
// -1 - destroy
|
||||||
|
|||||||
@ -44,6 +44,7 @@ RULE_INT(Character, DeathExpLossMaxLevel, 255) // Any level greater than this wi
|
|||||||
RULE_INT(Character, DeathItemLossLevel, 10)
|
RULE_INT(Character, DeathItemLossLevel, 10)
|
||||||
RULE_INT(Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost
|
RULE_INT(Character, DeathExpLossMultiplier, 3) //Adjust how much exp is lost
|
||||||
RULE_BOOL(Character, UseDeathExpLossMult, false) //Adjust to use the above multiplier or to use code default.
|
RULE_BOOL(Character, UseDeathExpLossMult, false) //Adjust to use the above multiplier or to use code default.
|
||||||
|
RULE_BOOL(Character, UseOldRaceRezEffects, false) // older clients had ID 757 for races with high starting STR, but it doesn't seem used anymore
|
||||||
RULE_INT(Character, CorpseDecayTimeMS, 10800000)
|
RULE_INT(Character, CorpseDecayTimeMS, 10800000)
|
||||||
RULE_INT(Character, CorpseResTimeMS, 10800000) // time before cant res corpse(3 hours)
|
RULE_INT(Character, CorpseResTimeMS, 10800000) // time before cant res corpse(3 hours)
|
||||||
RULE_BOOL(Character, LeaveCorpses, true)
|
RULE_BOOL(Character, LeaveCorpses, true)
|
||||||
|
|||||||
@ -248,6 +248,7 @@ OP_AutoAttack=0x0d14
|
|||||||
OP_AutoAttack2=0x3912
|
OP_AutoAttack2=0x3912
|
||||||
OP_Consume=0x4692
|
OP_Consume=0x4692
|
||||||
OP_MoveItem=0x62a2
|
OP_MoveItem=0x62a2
|
||||||
|
OP_MoveMultipleItems=0x55ef
|
||||||
OP_DeleteItem=0x3eb5
|
OP_DeleteItem=0x3eb5
|
||||||
OP_DeleteCharge=0x2d5b
|
OP_DeleteCharge=0x2d5b
|
||||||
OP_ItemPacket=0x5e0e
|
OP_ItemPacket=0x5e0e
|
||||||
|
|||||||
@ -247,6 +247,7 @@ OP_AutoAttack=0x109d
|
|||||||
OP_AutoAttack2=0x3526
|
OP_AutoAttack2=0x3526
|
||||||
OP_Consume=0x4b70
|
OP_Consume=0x4b70
|
||||||
OP_MoveItem=0x32ee
|
OP_MoveItem=0x32ee
|
||||||
|
OP_MoveMultipleItems=0x5623
|
||||||
OP_DeleteItem=0x18ad
|
OP_DeleteItem=0x18ad
|
||||||
OP_DeleteCharge=0x01b8
|
OP_DeleteCharge=0x01b8
|
||||||
OP_ItemPacket=0x368e
|
OP_ItemPacket=0x368e
|
||||||
|
|||||||
@ -241,6 +241,7 @@ OP_AutoAttack=0x3d86 # C
|
|||||||
OP_AutoAttack2=0x4ca1 # C
|
OP_AutoAttack2=0x4ca1 # C
|
||||||
OP_Consume=0x7ce4 # C
|
OP_Consume=0x7ce4 # C
|
||||||
OP_MoveItem=0x7f56 # C
|
OP_MoveItem=0x7f56 # C
|
||||||
|
OP_MoveMultipleItems=0x4572
|
||||||
OP_DeleteItem=0x36f8 # C
|
OP_DeleteItem=0x36f8 # C
|
||||||
OP_DeleteCharge=0x1df9 # C
|
OP_DeleteCharge=0x1df9 # C
|
||||||
OP_ItemPacket=0x34f8 # C
|
OP_ItemPacket=0x34f8 # C
|
||||||
|
|||||||
@ -237,6 +237,7 @@ OP_AutoAttack=0x3427 #Trevius 01/20/09
|
|||||||
OP_AutoAttack2=0x6017 #Trevius 01/20/09
|
OP_AutoAttack2=0x6017 #Trevius 01/20/09
|
||||||
OP_Consume=0x729a #Trevius 02/08/09
|
OP_Consume=0x729a #Trevius 02/08/09
|
||||||
OP_MoveItem=0x14B3 #Trevius 02/08/09
|
OP_MoveItem=0x14B3 #Trevius 02/08/09
|
||||||
|
OP_MoveMultipleItems=0x2d3e
|
||||||
OP_DeleteItem=0x7DD4 #Xinu 03/08/09 0x41EE 0x018E 0x070C
|
OP_DeleteItem=0x7DD4 #Xinu 03/08/09 0x41EE 0x018E 0x070C
|
||||||
OP_DeleteCharge=0x32e2 #Trevius 03/23/09
|
OP_DeleteCharge=0x32e2 #Trevius 03/23/09
|
||||||
OP_ItemPacket=0x78Cd #Trevius 02/08/09
|
OP_ItemPacket=0x78Cd #Trevius 02/08/09
|
||||||
|
|||||||
@ -198,6 +198,7 @@ OP_Split=0x4848 # ShowEQ 10/27/05
|
|||||||
OP_Surname=0x4668 # ShowEQ 10/27/05
|
OP_Surname=0x4668 # ShowEQ 10/27/05
|
||||||
OP_ClearSurname=0x6cdb
|
OP_ClearSurname=0x6cdb
|
||||||
OP_MoveItem=0x420f # ShowEQ 10/27/05
|
OP_MoveItem=0x420f # ShowEQ 10/27/05
|
||||||
|
OP_MoveMultipleItems=0x463b
|
||||||
OP_FaceChange=0x0f8e # ShowEQ 10/27/05
|
OP_FaceChange=0x0f8e # ShowEQ 10/27/05
|
||||||
OP_ItemPacket=0x3397 # ShowEQ 10/27/05
|
OP_ItemPacket=0x3397 # ShowEQ 10/27/05
|
||||||
OP_ItemLinkResponse=0x667c # ShowEQ 10/27/05
|
OP_ItemLinkResponse=0x667c # ShowEQ 10/27/05
|
||||||
|
|||||||
@ -251,6 +251,7 @@ OP_AutoAttack=0x1df9 # C
|
|||||||
OP_AutoAttack2=0x517b # C
|
OP_AutoAttack2=0x517b # C
|
||||||
OP_Consume=0x24c5 # V
|
OP_Consume=0x24c5 # V
|
||||||
OP_MoveItem=0x2641 # C
|
OP_MoveItem=0x2641 # C
|
||||||
|
OP_MoveMultipleItems=0x40e8
|
||||||
OP_DeleteItem=0x66e0 # C
|
OP_DeleteItem=0x66e0 # C
|
||||||
OP_DeleteCharge=0x4ca1 # C
|
OP_DeleteCharge=0x4ca1 # C
|
||||||
OP_ItemPacket=0x7b6e # C
|
OP_ItemPacket=0x7b6e # C
|
||||||
|
|||||||
@ -369,6 +369,7 @@
|
|||||||
9113|2017_07_19_show_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'show_name'|empty|
|
9113|2017_07_19_show_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'show_name'|empty|
|
||||||
9114|2017_07_22_aura.sql|SHOW TABLES LIKE 'auras'|empty|
|
9114|2017_07_22_aura.sql|SHOW TABLES LIKE 'auras'|empty|
|
||||||
9115|2017_10_28_traps.sql|SHOW COLUMNS FROM `traps` LIKE 'triggered_number'|empty|
|
9115|2017_10_28_traps.sql|SHOW COLUMNS FROM `traps` LIKE 'triggered_number'|empty|
|
||||||
|
9116|2017_12_16_GroundSpawn_Respawn_Timer.sql|SHOW COLUMNS FROM `ground_spawns` WHERE Field = 'respawn_timer' AND Type = 'int(11) unsigned'|empty|
|
||||||
|
|
||||||
# Upgrade conditions:
|
# Upgrade conditions:
|
||||||
# This won't be needed after this system is implemented, but it is used database that are not
|
# This won't be needed after this system is implemented, but it is used database that are not
|
||||||
|
|||||||
@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE `ground_spawns` MODIFY `respawn_timer` int(11) unsigned NOT NULL default 300;
|
||||||
|
UPDATE `ground_spawns` SET `respawn_timer` = `respawn_timer` / 1000;
|
||||||
@ -852,16 +852,56 @@ int Mob::ACSum()
|
|||||||
return ac;
|
return ac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Mob::GetBestMeleeSkill()
|
||||||
|
{
|
||||||
|
int bestSkill=0;
|
||||||
|
EQEmu::skills::SkillType meleeSkills[]=
|
||||||
|
{ EQEmu::skills::Skill1HBlunt,
|
||||||
|
EQEmu::skills::Skill1HSlashing,
|
||||||
|
EQEmu::skills::Skill2HBlunt,
|
||||||
|
EQEmu::skills::Skill2HSlashing,
|
||||||
|
EQEmu::skills::SkillHandtoHand,
|
||||||
|
EQEmu::skills::Skill1HPiercing,
|
||||||
|
EQEmu::skills::Skill2HPiercing,
|
||||||
|
EQEmu::skills::SkillCount
|
||||||
|
};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; meleeSkills[i] != EQEmu::skills::SkillCount; ++i) {
|
||||||
|
int value;
|
||||||
|
value = GetSkill(meleeSkills[i]);
|
||||||
|
bestSkill = std::max(value, bestSkill);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestSkill;
|
||||||
|
}
|
||||||
|
|
||||||
int Mob::offense(EQEmu::skills::SkillType skill)
|
int Mob::offense(EQEmu::skills::SkillType skill)
|
||||||
{
|
{
|
||||||
int offense = GetSkill(skill);
|
int offense = GetSkill(skill);
|
||||||
int stat_bonus = 0;
|
int stat_bonus = GetSTR();
|
||||||
if (skill == EQEmu::skills::SkillArchery || skill == EQEmu::skills::SkillThrowing)
|
|
||||||
|
switch (skill) {
|
||||||
|
case EQEmu::skills::SkillArchery:
|
||||||
|
case EQEmu::skills::SkillThrowing:
|
||||||
stat_bonus = GetDEX();
|
stat_bonus = GetDEX();
|
||||||
else
|
break;
|
||||||
stat_bonus = GetSTR();
|
|
||||||
|
// Mobs with no weapons default to H2H.
|
||||||
|
// Since H2H is capped at 100 for many many classes,
|
||||||
|
// lets not handicap mobs based on not spawning with a
|
||||||
|
// weapon.
|
||||||
|
//
|
||||||
|
// Maybe we tweak this if Disarm is actually implemented.
|
||||||
|
|
||||||
|
case EQEmu::skills::SkillHandtoHand:
|
||||||
|
offense = GetBestMeleeSkill();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (stat_bonus >= 75)
|
if (stat_bonus >= 75)
|
||||||
offense += (2 * stat_bonus - 150) / 3;
|
offense += (2 * stat_bonus - 150) / 3;
|
||||||
|
|
||||||
offense += GetATK();
|
offense += GetATK();
|
||||||
return offense;
|
return offense;
|
||||||
}
|
}
|
||||||
@ -2676,9 +2716,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b
|
|||||||
// owner must get on list, but he's not actually gained any hate yet
|
// owner must get on list, but he's not actually gained any hate yet
|
||||||
if (!owner->GetSpecialAbility(IMMUNE_AGGRO))
|
if (!owner->GetSpecialAbility(IMMUNE_AGGRO))
|
||||||
{
|
{
|
||||||
hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
|
|
||||||
if (owner->IsClient() && !CheckAggro(owner))
|
if (owner->IsClient() && !CheckAggro(owner))
|
||||||
owner->CastToClient()->AddAutoXTarget(this);
|
owner->CastToClient()->AddAutoXTarget(this);
|
||||||
|
hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5250,12 +5290,23 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell)
|
|||||||
// extra off hand non-sense, can only double with skill of 150 or above
|
// extra off hand non-sense, can only double with skill of 150 or above
|
||||||
// or you have any amount of GiveDoubleAttack
|
// or you have any amount of GiveDoubleAttack
|
||||||
if (candouble && hand == EQEmu::inventory::slotSecondary)
|
if (candouble && hand == EQEmu::inventory::slotSecondary)
|
||||||
candouble = GetSkill(EQEmu::skills::SkillDoubleAttack) > 149 || (aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0;
|
candouble =
|
||||||
|
GetSkill(EQEmu::skills::SkillDoubleAttack) > 149 ||
|
||||||
|
(aabonuses.GiveDoubleAttack + spellbonuses.GiveDoubleAttack + itembonuses.GiveDoubleAttack) > 0;
|
||||||
|
|
||||||
if (candouble) {
|
if (candouble) {
|
||||||
CheckIncreaseSkill(EQEmu::skills::SkillDoubleAttack, target, -10);
|
CheckIncreaseSkill(EQEmu::skills::SkillDoubleAttack, target, -10);
|
||||||
if (CheckDoubleAttack()) {
|
if (CheckDoubleAttack()) {
|
||||||
Attack(target, hand, false, false, IsFromSpell);
|
Attack(target, hand, false, false, IsFromSpell);
|
||||||
|
|
||||||
|
// Modern AA description: Increases your chance of ... performing one additional hit with a 2-handed weapon when double attacking by 2%.
|
||||||
|
if (hand == EQEmu::inventory::slotPrimary) {
|
||||||
|
auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance +
|
||||||
|
itembonuses.ExtraAttackChance;
|
||||||
|
if (extraattackchance && HasTwoHanderEquipped() && zone->random.Roll(extraattackchance))
|
||||||
|
Attack(target, hand, false, false, IsFromSpell);
|
||||||
|
}
|
||||||
|
|
||||||
// you can only triple from the main hand
|
// you can only triple from the main hand
|
||||||
if (hand == EQEmu::inventory::slotPrimary && CanThisClassTripleAttack()) {
|
if (hand == EQEmu::inventory::slotPrimary && CanThisClassTripleAttack()) {
|
||||||
CheckIncreaseSkill(EQEmu::skills::SkillTripleAttack, target, -10);
|
CheckIncreaseSkill(EQEmu::skills::SkillTripleAttack, target, -10);
|
||||||
@ -5273,12 +5324,6 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hand == EQEmu::inventory::slotPrimary) {
|
|
||||||
auto extraattackchance = aabonuses.ExtraAttackChance + spellbonuses.ExtraAttackChance + itembonuses.ExtraAttackChance;
|
|
||||||
if (extraattackchance && HasTwoHanderEquipped() && zone->random.Roll(extraattackchance))
|
|
||||||
Attack(target, hand, false, false, IsFromSpell);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::CheckDualWield()
|
bool Mob::CheckDualWield()
|
||||||
|
|||||||
@ -291,6 +291,7 @@ void MapOpcodes()
|
|||||||
ConnectedOpcodes[OP_MercenaryTimerRequest] = &Client::Handle_OP_MercenaryTimerRequest;
|
ConnectedOpcodes[OP_MercenaryTimerRequest] = &Client::Handle_OP_MercenaryTimerRequest;
|
||||||
ConnectedOpcodes[OP_MoveCoin] = &Client::Handle_OP_MoveCoin;
|
ConnectedOpcodes[OP_MoveCoin] = &Client::Handle_OP_MoveCoin;
|
||||||
ConnectedOpcodes[OP_MoveItem] = &Client::Handle_OP_MoveItem;
|
ConnectedOpcodes[OP_MoveItem] = &Client::Handle_OP_MoveItem;
|
||||||
|
ConnectedOpcodes[OP_MoveMultipleItems] = &Client::Handle_OP_MoveMultipleItems;
|
||||||
ConnectedOpcodes[OP_OpenContainer] = &Client::Handle_OP_OpenContainer;
|
ConnectedOpcodes[OP_OpenContainer] = &Client::Handle_OP_OpenContainer;
|
||||||
ConnectedOpcodes[OP_OpenGuildTributeMaster] = &Client::Handle_OP_OpenGuildTributeMaster;
|
ConnectedOpcodes[OP_OpenGuildTributeMaster] = &Client::Handle_OP_OpenGuildTributeMaster;
|
||||||
ConnectedOpcodes[OP_OpenInventory] = &Client::Handle_OP_OpenInventory;
|
ConnectedOpcodes[OP_OpenInventory] = &Client::Handle_OP_OpenInventory;
|
||||||
@ -9856,6 +9857,11 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::Handle_OP_MoveMultipleItems(const EQApplicationPacket *app)
|
||||||
|
{
|
||||||
|
Kick(); // TODO: lets not desync though
|
||||||
|
}
|
||||||
|
|
||||||
void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app)
|
void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app)
|
||||||
{
|
{
|
||||||
// Does not exist in Ti client
|
// Does not exist in Ti client
|
||||||
|
|||||||
@ -204,6 +204,7 @@
|
|||||||
void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app);
|
void Handle_OP_MercenaryTimerRequest(const EQApplicationPacket *app);
|
||||||
void Handle_OP_MoveCoin(const EQApplicationPacket *app);
|
void Handle_OP_MoveCoin(const EQApplicationPacket *app);
|
||||||
void Handle_OP_MoveItem(const EQApplicationPacket *app);
|
void Handle_OP_MoveItem(const EQApplicationPacket *app);
|
||||||
|
void Handle_OP_MoveMultipleItems(const EQApplicationPacket *app);
|
||||||
void Handle_OP_OpenContainer(const EQApplicationPacket *app);
|
void Handle_OP_OpenContainer(const EQApplicationPacket *app);
|
||||||
void Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app);
|
void Handle_OP_OpenGuildTributeMaster(const EQApplicationPacket *app);
|
||||||
void Handle_OP_OpenInventory(const EQApplicationPacket *app);
|
void Handle_OP_OpenInventory(const EQApplicationPacket *app);
|
||||||
|
|||||||
@ -269,8 +269,16 @@ bool Client::Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (force_spawn_updates && mob != this && distance <= client_update_range)
|
if (force_spawn_updates && mob != this) {
|
||||||
|
|
||||||
|
if (mob->is_distance_roamer) {
|
||||||
mob->SendPositionUpdateToClient(this);
|
mob->SendPositionUpdateToClient(this);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance <= client_update_range)
|
||||||
|
mob->SendPositionUpdateToClient(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1055,7 +1063,8 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
|
|||||||
SetMana(0);
|
SetMana(0);
|
||||||
SetHP(GetMaxHP()/5);
|
SetHP(GetMaxHP()/5);
|
||||||
int rez_eff = 756;
|
int rez_eff = 756;
|
||||||
if (GetRace() == BARBARIAN || GetRace() == DWARF || GetRace() == TROLL || GetRace() == OGRE)
|
if (RuleB(Character, UseOldRaceRezEffects) &&
|
||||||
|
(GetRace() == BARBARIAN || GetRace() == DWARF || GetRace() == TROLL || GetRace() == OGRE))
|
||||||
rez_eff = 757;
|
rez_eff = 757;
|
||||||
SpellOnTarget(rez_eff, this); // Rezz effects
|
SpellOnTarget(rez_eff, this); // Rezz effects
|
||||||
}
|
}
|
||||||
|
|||||||
@ -376,6 +376,7 @@ int command_init(void)
|
|||||||
command_add("task", "(subcommand) - Task system commands", 150, command_task) ||
|
command_add("task", "(subcommand) - Task system commands", 150, command_task) ||
|
||||||
command_add("tattoo", "- Change the tattoo of your target (Drakkin Only)", 80, command_tattoo) ||
|
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("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("texture", "[texture] [helmtexture] - Change your or your target's appearance, use 255 to show equipment", 10, command_texture) ||
|
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("time", "[HH] [MM] - Set EQ time", 90, command_time) ||
|
||||||
command_add("timers", "- Display persistent timers for target", 200, command_timers) ||
|
command_add("timers", "- Display persistent timers for target", 200, command_timers) ||
|
||||||
@ -4168,6 +4169,26 @@ void command_tempname(Client *c, const Seperator *sep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void command_petname(Client *c, const Seperator *sep)
|
||||||
|
{
|
||||||
|
Mob *target;
|
||||||
|
target = c->GetTarget();
|
||||||
|
|
||||||
|
if(!target)
|
||||||
|
c->Message(0, "Usage: #petname newname (requires a target)");
|
||||||
|
else if(target->IsPet() && (target->GetOwnerID() == c->GetID()) && strlen(sep->arg[1]) > 0)
|
||||||
|
{
|
||||||
|
char *oldname = strdup(target->GetName());
|
||||||
|
target->TempName(sep->arg[1]);
|
||||||
|
c->Message(0, "Renamed %s to %s", oldname, sep->arg[1]);
|
||||||
|
free(oldname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
target->TempName();
|
||||||
|
c->Message(0, "Restored the original name");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void command_npcspecialattk(Client *c, const Seperator *sep)
|
void command_npcspecialattk(Client *c, const Seperator *sep)
|
||||||
{
|
{
|
||||||
if (c->GetTarget()==0 || c->GetTarget()->IsClient() || strlen(sep->arg[1]) <= 0 || strlen(sep->arg[2]) <= 0)
|
if (c->GetTarget()==0 || c->GetTarget()->IsClient() || strlen(sep->arg[1]) <= 0 || strlen(sep->arg[2]) <= 0)
|
||||||
|
|||||||
@ -287,6 +287,7 @@ void command_synctod(Client *c, const Seperator *sep);
|
|||||||
void command_task(Client *c, const Seperator *sep);
|
void command_task(Client *c, const Seperator *sep);
|
||||||
void command_tattoo(Client *c, const Seperator *sep);
|
void command_tattoo(Client *c, const Seperator *sep);
|
||||||
void command_tempname(Client *c, const Seperator *sep);
|
void command_tempname(Client *c, const Seperator *sep);
|
||||||
|
void command_petname(Client *c, const Seperator *sep);
|
||||||
void command_testspawn(Client *c, const Seperator *sep);
|
void command_testspawn(Client *c, const Seperator *sep);
|
||||||
void command_testspawnkill(Client *c, const Seperator *sep);
|
void command_testspawnkill(Client *c, const Seperator *sep);
|
||||||
void command_texture(Client *c, const Seperator *sep);
|
void command_texture(Client *c, const Seperator *sep);
|
||||||
|
|||||||
@ -611,6 +611,10 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the client does this check before calling CastSpell, should prevent discs being eaten
|
||||||
|
if (spell.buffdurationformula != 0 && spell.targettype == ST_Self && HasDiscBuff())
|
||||||
|
return false;
|
||||||
|
|
||||||
//Check the disc timer
|
//Check the disc timer
|
||||||
pTimerType DiscTimer = pTimerDisciplineReuseStart + spell.EndurTimerIndex;
|
pTimerType DiscTimer = pTimerDisciplineReuseStart + spell.EndurTimerIndex;
|
||||||
if(!p_timers.Expired(&database, DiscTimer, false)) { // lets not set the reuse timer in case CastSpell fails (or we would have to turn off the timer, but CastSpell will set it as well)
|
if(!p_timers.Expired(&database, DiscTimer, false)) { // lets not set the reuse timer in case CastSpell fails (or we would have to turn off the timer, but CastSpell will set it as well)
|
||||||
|
|||||||
@ -327,8 +327,7 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
|
|||||||
aatotalmod *= zone->newzone_data.zone_exp_multiplier;
|
aatotalmod *= zone->newzone_data.zone_exp_multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shouldn't race not affect AA XP?
|
||||||
|
|
||||||
if(RuleB(Character,UseRaceClassExpBonuses))
|
if(RuleB(Character,UseRaceClassExpBonuses))
|
||||||
{
|
{
|
||||||
if(GetBaseRace() == HALFLING){
|
if(GetBaseRace() == HALFLING){
|
||||||
@ -340,6 +339,12 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// why wasn't this here? Where should it be?
|
||||||
|
if(zone->IsHotzone())
|
||||||
|
{
|
||||||
|
aatotalmod += RuleR(Zone, HotZoneBonus);
|
||||||
|
}
|
||||||
|
|
||||||
if(RuleB(Zone, LevelBasedEXPMods)){
|
if(RuleB(Zone, LevelBasedEXPMods)){
|
||||||
if(zone->level_exp_mod[GetLevel()].ExpMod){
|
if(zone->level_exp_mod[GetLevel()].ExpMod){
|
||||||
add_exp *= zone->level_exp_mod[GetLevel()].ExpMod;
|
add_exp *= zone->level_exp_mod[GetLevel()].ExpMod;
|
||||||
|
|||||||
72
zone/mob.cpp
72
zone/mob.cpp
@ -75,7 +75,6 @@ Mob::Mob(const char* in_name,
|
|||||||
uint32 in_drakkin_tattoo,
|
uint32 in_drakkin_tattoo,
|
||||||
uint32 in_drakkin_details,
|
uint32 in_drakkin_details,
|
||||||
EQEmu::TintProfile in_armor_tint,
|
EQEmu::TintProfile in_armor_tint,
|
||||||
|
|
||||||
uint8 in_aa_title,
|
uint8 in_aa_title,
|
||||||
uint8 in_see_invis, // see through invis/ivu
|
uint8 in_see_invis, // see through invis/ivu
|
||||||
uint8 in_see_invis_undead,
|
uint8 in_see_invis_undead,
|
||||||
@ -98,14 +97,14 @@ Mob::Mob(const char* in_name,
|
|||||||
tic_timer(6000),
|
tic_timer(6000),
|
||||||
mana_timer(2000),
|
mana_timer(2000),
|
||||||
spellend_timer(0),
|
spellend_timer(0),
|
||||||
rewind_timer(30000), //Timer used for determining amount of time between actual player position updates for /rewind.
|
rewind_timer(30000),
|
||||||
bindwound_timer(10000),
|
bindwound_timer(10000),
|
||||||
stunned_timer(0),
|
stunned_timer(0),
|
||||||
spun_timer(0),
|
spun_timer(0),
|
||||||
bardsong_timer(6000),
|
bardsong_timer(6000),
|
||||||
gravity_timer(1000),
|
gravity_timer(1000),
|
||||||
viral_timer(0),
|
viral_timer(0),
|
||||||
m_FearWalkTarget(-999999.0f,-999999.0f,-999999.0f),
|
m_FearWalkTarget(-999999.0f, -999999.0f, -999999.0f),
|
||||||
m_TargetLocation(glm::vec3()),
|
m_TargetLocation(glm::vec3()),
|
||||||
m_TargetV(glm::vec3()),
|
m_TargetV(glm::vec3()),
|
||||||
flee_timer(FLEE_CHECK_TIMER),
|
flee_timer(FLEE_CHECK_TIMER),
|
||||||
@ -119,30 +118,29 @@ Mob::Mob(const char* in_name,
|
|||||||
position_update_melee_push_timer(1000)
|
position_update_melee_push_timer(1000)
|
||||||
{
|
{
|
||||||
targeted = 0;
|
targeted = 0;
|
||||||
tar_ndx=0;
|
tar_ndx = 0;
|
||||||
tar_vector=0;
|
tar_vector = 0;
|
||||||
currently_fleeing = false;
|
currently_fleeing = false;
|
||||||
|
|
||||||
last_z = 0;
|
|
||||||
|
|
||||||
last_major_update_position = m_Position;
|
last_major_update_position = m_Position;
|
||||||
|
is_distance_roamer = false;
|
||||||
|
|
||||||
AI_Init();
|
AI_Init();
|
||||||
SetMoving(false);
|
SetMoving(false);
|
||||||
moved=false;
|
moved = false;
|
||||||
m_RewindLocation = glm::vec3();
|
m_RewindLocation = glm::vec3();
|
||||||
|
|
||||||
_egnode = nullptr;
|
_egnode = nullptr;
|
||||||
name[0]=0;
|
name[0] = 0;
|
||||||
orig_name[0]=0;
|
orig_name[0] = 0;
|
||||||
clean_name[0]=0;
|
clean_name[0] = 0;
|
||||||
lastname[0]=0;
|
lastname[0] = 0;
|
||||||
if(in_name) {
|
if (in_name) {
|
||||||
strn0cpy(name,in_name,64);
|
strn0cpy(name, in_name, 64);
|
||||||
strn0cpy(orig_name,in_name,64);
|
strn0cpy(orig_name, in_name, 64);
|
||||||
}
|
}
|
||||||
if(in_lastname)
|
if (in_lastname)
|
||||||
strn0cpy(lastname,in_lastname,64);
|
strn0cpy(lastname, in_lastname, 64);
|
||||||
cur_hp = in_cur_hp;
|
cur_hp = in_cur_hp;
|
||||||
max_hp = in_max_hp;
|
max_hp = in_max_hp;
|
||||||
base_hp = in_max_hp;
|
base_hp = in_max_hp;
|
||||||
@ -172,7 +170,8 @@ Mob::Mob(const char* in_name,
|
|||||||
fearspeed = 0.625f;
|
fearspeed = 0.625f;
|
||||||
base_fearspeed = 25;
|
base_fearspeed = 25;
|
||||||
// npcs
|
// npcs
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
base_walkspeed = base_runspeed * 100 / 265;
|
base_walkspeed = base_runspeed * 100 / 265;
|
||||||
walkspeed = ((float)base_walkspeed) * 0.025f;
|
walkspeed = ((float)base_walkspeed) * 0.025f;
|
||||||
base_fearspeed = base_runspeed * 100 / 127;
|
base_fearspeed = base_runspeed * 100 / 127;
|
||||||
@ -230,10 +229,10 @@ Mob::Mob(const char* in_name,
|
|||||||
SpellPowerDistanceMod = 0;
|
SpellPowerDistanceMod = 0;
|
||||||
last_los_check = false;
|
last_los_check = false;
|
||||||
|
|
||||||
if(in_aa_title>0)
|
if (in_aa_title > 0)
|
||||||
aa_title = in_aa_title;
|
aa_title = in_aa_title;
|
||||||
else
|
else
|
||||||
aa_title =0xFF;
|
aa_title = 0xFF;
|
||||||
AC = in_ac;
|
AC = in_ac;
|
||||||
ATK = in_atk;
|
ATK = in_atk;
|
||||||
STR = in_str;
|
STR = in_str;
|
||||||
@ -264,7 +263,7 @@ Mob::Mob(const char* in_name,
|
|||||||
improved_hidden = false;
|
improved_hidden = false;
|
||||||
invulnerable = false;
|
invulnerable = false;
|
||||||
IsFullHP = (cur_hp == max_hp);
|
IsFullHP = (cur_hp == max_hp);
|
||||||
qglobal=0;
|
qglobal = 0;
|
||||||
spawned = false;
|
spawned = false;
|
||||||
|
|
||||||
InitializeBuffSlots();
|
InitializeBuffSlots();
|
||||||
@ -376,13 +375,13 @@ Mob::Mob(const char* in_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
destructibleobject = false;
|
destructibleobject = false;
|
||||||
wandertype=0;
|
wandertype = 0;
|
||||||
pausetype=0;
|
pausetype = 0;
|
||||||
cur_wp = 0;
|
cur_wp = 0;
|
||||||
m_CurrentWayPoint = glm::vec4();
|
m_CurrentWayPoint = glm::vec4();
|
||||||
cur_wp_pause = 0;
|
cur_wp_pause = 0;
|
||||||
patrol=0;
|
patrol = 0;
|
||||||
follow=0;
|
follow = 0;
|
||||||
follow_dist = 100; // Default Distance for Follow
|
follow_dist = 100; // Default Distance for Follow
|
||||||
no_target_hotkey = false;
|
no_target_hotkey = false;
|
||||||
flee_mode = false;
|
flee_mode = false;
|
||||||
@ -396,7 +395,7 @@ Mob::Mob(const char* in_name,
|
|||||||
rooted = false;
|
rooted = false;
|
||||||
charmed = false;
|
charmed = false;
|
||||||
has_virus = false;
|
has_virus = false;
|
||||||
for (i=0; i<MAX_SPELL_TRIGGER*2; i++) {
|
for (i = 0; i < MAX_SPELL_TRIGGER * 2; i++) {
|
||||||
viral_spells[i] = 0;
|
viral_spells[i] = 0;
|
||||||
}
|
}
|
||||||
pStandingPetOrder = SPO_Follow;
|
pStandingPetOrder = SPO_Follow;
|
||||||
@ -444,7 +443,7 @@ Mob::Mob(const char* in_name,
|
|||||||
m_AllowBeneficial = false;
|
m_AllowBeneficial = false;
|
||||||
m_DisableMelee = false;
|
m_DisableMelee = false;
|
||||||
for (int i = 0; i < EQEmu::skills::HIGHEST_SKILL + 2; i++) { SkillDmgTaken_Mod[i] = 0; }
|
for (int i = 0; i < EQEmu::skills::HIGHEST_SKILL + 2; i++) { SkillDmgTaken_Mod[i] = 0; }
|
||||||
for (int i = 0; i < HIGHEST_RESIST+2; i++) { Vulnerability_Mod[i] = 0; }
|
for (int i = 0; i < HIGHEST_RESIST + 2; i++) { Vulnerability_Mod[i] = 0; }
|
||||||
|
|
||||||
emoteid = 0;
|
emoteid = 0;
|
||||||
endur_upkeep = false;
|
endur_upkeep = false;
|
||||||
@ -1447,6 +1446,7 @@ void Mob::SendPosition() {
|
|||||||
if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) {
|
if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) {
|
||||||
entity_list.QueueClients(this, app, true, true);
|
entity_list.QueueClients(this, app, true, true);
|
||||||
last_major_update_position = m_Position;
|
last_major_update_position = m_Position;
|
||||||
|
is_distance_roamer = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false);
|
entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||||
@ -1480,6 +1480,11 @@ void Mob::SendPositionUpdate(uint8 iSendToSelf) {
|
|||||||
CastToClient()->FastQueuePacket(&app, false);
|
CastToClient()->FastQueuePacket(&app, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) {
|
||||||
|
entity_list.QueueClients(this, app, true, true);
|
||||||
|
last_major_update_position = m_Position;
|
||||||
|
is_distance_roamer = true;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
|
entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false);
|
||||||
}
|
}
|
||||||
@ -3444,6 +3449,19 @@ void Mob::SetTarget(Mob* mob) {
|
|||||||
this->GetTarget()->SendHPUpdate(false, true);
|
this->GetTarget()->SendHPUpdate(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For when we want a Ground Z at a location we are not at yet
|
||||||
|
// Like MoveTo.
|
||||||
|
float Mob::FindDestGroundZ(glm::vec3 dest, float z_offset)
|
||||||
|
{
|
||||||
|
float best_z = BEST_Z_INVALID;
|
||||||
|
if (zone->zonemap != nullptr)
|
||||||
|
{
|
||||||
|
dest.z += z_offset;
|
||||||
|
best_z = zone->zonemap->FindBestZ(dest, nullptr);
|
||||||
|
}
|
||||||
|
return best_z;
|
||||||
|
}
|
||||||
|
|
||||||
float Mob::FindGroundZ(float new_x, float new_y, float z_offset)
|
float Mob::FindGroundZ(float new_x, float new_y, float z_offset)
|
||||||
{
|
{
|
||||||
float ret = BEST_Z_INVALID;
|
float ret = BEST_Z_INVALID;
|
||||||
|
|||||||
10
zone/mob.h
10
zone/mob.h
@ -162,6 +162,8 @@ public:
|
|||||||
inline virtual bool IsMob() const { return true; }
|
inline virtual bool IsMob() const { return true; }
|
||||||
inline virtual bool InZone() const { return true; }
|
inline virtual bool InZone() const { return true; }
|
||||||
|
|
||||||
|
bool is_distance_roamer;
|
||||||
|
|
||||||
//Somewhat sorted: needs documenting!
|
//Somewhat sorted: needs documenting!
|
||||||
|
|
||||||
//Attack
|
//Attack
|
||||||
@ -199,6 +201,7 @@ public:
|
|||||||
void ApplyMeleeDamageMods(uint16 skill, int &damage, Mob * defender = nullptr, ExtraAttackOptions *opts = nullptr);
|
void ApplyMeleeDamageMods(uint16 skill, int &damage, Mob * defender = nullptr, ExtraAttackOptions *opts = nullptr);
|
||||||
int ACSum();
|
int ACSum();
|
||||||
int offense(EQEmu::skills::SkillType skill);
|
int offense(EQEmu::skills::SkillType skill);
|
||||||
|
int GetBestMeleeSkill();
|
||||||
void CalcAC() { mitigation_ac = ACSum(); }
|
void CalcAC() { mitigation_ac = ACSum(); }
|
||||||
int GetACSoftcap();
|
int GetACSoftcap();
|
||||||
double GetSoftcapReturns();
|
double GetSoftcapReturns();
|
||||||
@ -278,6 +281,7 @@ public:
|
|||||||
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
|
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
|
||||||
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false,
|
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false,
|
||||||
int level_override = -1);
|
int level_override = -1);
|
||||||
|
int GetResist(uint8 resist_type);
|
||||||
int ResistPhysical(int level_diff, uint8 caster_level);
|
int ResistPhysical(int level_diff, uint8 caster_level);
|
||||||
int ResistElementalWeaponDmg(const EQEmu::ItemInstance *item);
|
int ResistElementalWeaponDmg(const EQEmu::ItemInstance *item);
|
||||||
int CheckBaneDamage(const EQEmu::ItemInstance *item);
|
int CheckBaneDamage(const EQEmu::ItemInstance *item);
|
||||||
@ -349,6 +353,7 @@ public:
|
|||||||
virtual int GetMaxSongSlots() const { return 0; }
|
virtual int GetMaxSongSlots() const { return 0; }
|
||||||
virtual int GetMaxDiscSlots() const { return 0; }
|
virtual int GetMaxDiscSlots() const { return 0; }
|
||||||
virtual int GetMaxTotalSlots() const { return 0; }
|
virtual int GetMaxTotalSlots() const { return 0; }
|
||||||
|
bool HasDiscBuff();
|
||||||
virtual uint32 GetFirstBuffSlot(bool disc, bool song);
|
virtual uint32 GetFirstBuffSlot(bool disc, bool song);
|
||||||
virtual uint32 GetLastBuffSlot(bool disc, bool song);
|
virtual uint32 GetLastBuffSlot(bool disc, bool song);
|
||||||
virtual void InitializeBuffSlots() { buffs = nullptr; current_buff_count = 0; }
|
virtual void InitializeBuffSlots() { buffs = nullptr; current_buff_count = 0; }
|
||||||
@ -955,6 +960,7 @@ public:
|
|||||||
void SendToFixZ(float new_x, float new_y, float new_z);
|
void SendToFixZ(float new_x, float new_y, float new_z);
|
||||||
float GetZOffset() const;
|
float GetZOffset() const;
|
||||||
void FixZ(int32 z_find_offset = 5);
|
void FixZ(int32 z_find_offset = 5);
|
||||||
|
float GetFixedZ(glm::vec3 position, int32 z_find_offset = 5);
|
||||||
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
|
void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false);
|
||||||
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
|
inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; }
|
||||||
inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; }
|
inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; }
|
||||||
@ -1108,8 +1114,6 @@ public:
|
|||||||
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
|
int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item);
|
||||||
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
|
int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr);
|
||||||
|
|
||||||
float last_z;
|
|
||||||
|
|
||||||
// Bots HealRotation methods
|
// Bots HealRotation methods
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
|
bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); }
|
||||||
@ -1226,6 +1230,7 @@ protected:
|
|||||||
glm::vec4 m_Position;
|
glm::vec4 m_Position;
|
||||||
/* Used to determine when an NPC has traversed so many units - to send a zone wide pos update */
|
/* 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 last_major_update_position;
|
||||||
|
|
||||||
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
|
int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f)
|
||||||
float base_size;
|
float base_size;
|
||||||
float size;
|
float size;
|
||||||
@ -1267,6 +1272,7 @@ protected:
|
|||||||
virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
|
virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
|
||||||
void CalculateNewFearpoint();
|
void CalculateNewFearpoint();
|
||||||
float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
|
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 UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
|
||||||
void PrintRoute();
|
void PrintRoute();
|
||||||
|
|
||||||
|
|||||||
@ -503,7 +503,7 @@ void NPC::AI_Start(uint32 iMoveDelay) {
|
|||||||
AIautocastspell_timer->Disable();
|
AIautocastspell_timer->Disable();
|
||||||
} else {
|
} else {
|
||||||
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(750));
|
AIautocastspell_timer = std::unique_ptr<Timer>(new Timer(750));
|
||||||
AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
|
AIautocastspell_timer->Start(RandomTimer(0, 300), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NPCTypedata) {
|
if (NPCTypedata) {
|
||||||
@ -1582,18 +1582,22 @@ void NPC::AI_DoMovement() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->FixZ();
|
this->FixZ();
|
||||||
|
|
||||||
SendPosition();
|
SendPosition();
|
||||||
|
|
||||||
//kick off event_waypoint arrive
|
//kick off event_waypoint arrive
|
||||||
char temp[16];
|
char temp[16];
|
||||||
sprintf(temp, "%d", cur_wp);
|
sprintf(temp, "%d", cur_wp);
|
||||||
parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0);
|
parse->EventNPC(EVENT_WAYPOINT_ARRIVE, CastToNPC(), nullptr, temp, 0);
|
||||||
// start moving directly to next waypoint if we're at a 0 pause waypoint and we didn't get quest halted.
|
// No need to move as we are there. Next loop will
|
||||||
if (!AI_walking_timer->Enabled())
|
// take care of normal grids, even at pause 0.
|
||||||
AI_SetupNextWaypoint();
|
// We do need to call and setup a wp if we're cur_wp=-2
|
||||||
else
|
// as that is where roamer is unset and we don't want
|
||||||
|
// the next trip through to move again based on grid stuff.
|
||||||
doMove = false;
|
doMove = false;
|
||||||
|
if (cur_wp == -2) {
|
||||||
|
AI_SetupNextWaypoint();
|
||||||
|
}
|
||||||
|
|
||||||
// wipe feign memory since we reached our first waypoint
|
// wipe feign memory since we reached our first waypoint
|
||||||
if(cur_wp == 1)
|
if(cur_wp == 1)
|
||||||
ClearFeignMemory();
|
ClearFeignMemory();
|
||||||
@ -2593,7 +2597,7 @@ void NPC::AddSpellToNPCList(int16 iPriority, int16 iSpellID, uint32 iType,
|
|||||||
|
|
||||||
// If we're going from an empty list, we need to start the timer
|
// If we're going from an empty list, we need to start the timer
|
||||||
if (AIspells.size() == 1)
|
if (AIspells.size() == 1)
|
||||||
AIautocastspell_timer->Start(RandomTimer(0, 15000), false);
|
AIautocastspell_timer->Start(RandomTimer(0, 300), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::RemoveSpellFromNPCList(int16 spell_id)
|
void NPC::RemoveSpellFromNPCList(int16 spell_id)
|
||||||
|
|||||||
@ -70,7 +70,7 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object,
|
|||||||
|
|
||||||
//creating a re-ocurring ground spawn.
|
//creating a re-ocurring ground spawn.
|
||||||
Object::Object(const EQEmu::ItemInstance* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer)
|
Object::Object(const EQEmu::ItemInstance* inst, char* name,float max_x,float min_x,float max_y,float min_y,float z,float heading,uint32 respawntimer)
|
||||||
: respawn_timer(respawntimer), decay_timer(300000)
|
: respawn_timer(respawntimer * 1000), decay_timer(300000)
|
||||||
{
|
{
|
||||||
|
|
||||||
user = nullptr;
|
user = nullptr;
|
||||||
|
|||||||
128
zone/spells.cpp
128
zone/spells.cpp
@ -3190,6 +3190,12 @@ uint32 Client::GetLastBuffSlot(bool disc, bool song)
|
|||||||
return GetCurrentBuffSlots();
|
return GetCurrentBuffSlots();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Mob::HasDiscBuff()
|
||||||
|
{
|
||||||
|
int slot = GetFirstBuffSlot(true, false);
|
||||||
|
return buffs[slot].spellid != SPELL_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
// returns the slot the buff was added to, -1 if it wasn't added due to
|
// returns the slot the buff was added to, -1 if it wasn't added due to
|
||||||
// stacking problems, and -2 if this is not a buff
|
// stacking problems, and -2 if this is not a buff
|
||||||
// if caster is null, the buff will be added with the caster level being
|
// if caster is null, the buff will be added with the caster level being
|
||||||
@ -4431,6 +4437,36 @@ bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Mob::GetResist(uint8 resist_type)
|
||||||
|
{
|
||||||
|
switch(resist_type)
|
||||||
|
{
|
||||||
|
case RESIST_FIRE:
|
||||||
|
return GetFR();
|
||||||
|
case RESIST_COLD:
|
||||||
|
return GetCR();
|
||||||
|
case RESIST_MAGIC:
|
||||||
|
return GetMR();
|
||||||
|
case RESIST_DISEASE:
|
||||||
|
return GetDR();
|
||||||
|
case RESIST_POISON:
|
||||||
|
return GetPR();
|
||||||
|
case RESIST_CORRUPTION:
|
||||||
|
return GetCorrup();
|
||||||
|
case RESIST_PRISMATIC:
|
||||||
|
return (GetFR() + GetCR() + GetMR() + GetDR() + GetPR()) / 5;
|
||||||
|
case RESIST_CHROMATIC:
|
||||||
|
return std::min({GetFR(), GetCR(), GetMR(), GetDR(), GetPR()});
|
||||||
|
case RESIST_PHYSICAL:
|
||||||
|
if (IsNPC())
|
||||||
|
return GetPhR();
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Spell resists:
|
// Spell resists:
|
||||||
// returns an effectiveness index from 0 to 100. for most spells, 100 means
|
// returns an effectiveness index from 0 to 100. for most spells, 100 means
|
||||||
@ -4514,68 +4550,16 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
int target_resist;
|
int target_resist = GetResist(resist_type);
|
||||||
switch(resist_type)
|
|
||||||
{
|
|
||||||
case RESIST_FIRE:
|
|
||||||
target_resist = GetFR();
|
|
||||||
break;
|
|
||||||
case RESIST_COLD:
|
|
||||||
target_resist = GetCR();
|
|
||||||
break;
|
|
||||||
case RESIST_MAGIC:
|
|
||||||
target_resist = GetMR();
|
|
||||||
break;
|
|
||||||
case RESIST_DISEASE:
|
|
||||||
target_resist = GetDR();
|
|
||||||
break;
|
|
||||||
case RESIST_POISON:
|
|
||||||
target_resist = GetPR();
|
|
||||||
break;
|
|
||||||
case RESIST_CORRUPTION:
|
|
||||||
target_resist = GetCorrup();
|
|
||||||
break;
|
|
||||||
case RESIST_PRISMATIC:
|
|
||||||
target_resist = (GetFR() + GetCR() + GetMR() + GetDR() + GetPR()) / 5;
|
|
||||||
break;
|
|
||||||
case RESIST_CHROMATIC:
|
|
||||||
{
|
|
||||||
target_resist = GetFR();
|
|
||||||
int temp = GetCR();
|
|
||||||
if(temp < target_resist)
|
|
||||||
{
|
|
||||||
target_resist = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = GetMR();
|
// JULY 24, 2002 changes
|
||||||
if(temp < target_resist)
|
int level = GetLevel();
|
||||||
{
|
if (IsPetOwnerClient() && caster->IsNPC() && !caster->IsPetOwnerClient()) {
|
||||||
target_resist = temp;
|
auto owner = GetOwner();
|
||||||
|
if (owner != nullptr) {
|
||||||
|
target_resist = std::max(target_resist, owner->GetResist(resist_type));
|
||||||
|
level = owner->GetLevel();
|
||||||
}
|
}
|
||||||
|
|
||||||
temp = GetDR();
|
|
||||||
if(temp < target_resist)
|
|
||||||
{
|
|
||||||
target_resist = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp = GetPR();
|
|
||||||
if(temp < target_resist)
|
|
||||||
{
|
|
||||||
target_resist = temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case RESIST_PHYSICAL:
|
|
||||||
{
|
|
||||||
if (IsNPC())
|
|
||||||
target_resist = GetPhR();
|
|
||||||
else
|
|
||||||
target_resist = 0;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
|
|
||||||
target_resist = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Setup our base resist chance.
|
//Setup our base resist chance.
|
||||||
@ -4584,7 +4568,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
|
|
||||||
//Adjust our resist chance based on level modifiers
|
//Adjust our resist chance based on level modifiers
|
||||||
uint8 caster_level = level_override > 0 ? level_override : caster->GetLevel();
|
uint8 caster_level = level_override > 0 ? level_override : caster->GetLevel();
|
||||||
int temp_level_diff = GetLevel() - caster_level;
|
int temp_level_diff = level - caster_level;
|
||||||
|
|
||||||
//Physical Resists are calclated using their own formula derived from extensive parsing.
|
//Physical Resists are calclated using their own formula derived from extensive parsing.
|
||||||
if (resist_type == RESIST_PHYSICAL) {
|
if (resist_type == RESIST_PHYSICAL) {
|
||||||
@ -4593,7 +4577,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if(IsNPC() && GetLevel() >= RuleI(Casting,ResistFalloff))
|
if(IsNPC() && level >= RuleI(Casting,ResistFalloff))
|
||||||
{
|
{
|
||||||
int a = (RuleI(Casting,ResistFalloff)-1) - caster_level;
|
int a = (RuleI(Casting,ResistFalloff)-1) - caster_level;
|
||||||
if(a > 0)
|
if(a > 0)
|
||||||
@ -4606,7 +4590,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsClient() && GetLevel() >= 21 && temp_level_diff > 15)
|
if(IsClient() && level >= 21 && temp_level_diff > 15)
|
||||||
{
|
{
|
||||||
temp_level_diff = 15;
|
temp_level_diff = 15;
|
||||||
}
|
}
|
||||||
@ -4622,16 +4606,16 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
level_mod = -level_mod;
|
level_mod = -level_mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(IsNPC() && (caster_level - GetLevel()) < -20)
|
if(IsNPC() && (caster_level - level) < -20)
|
||||||
{
|
{
|
||||||
level_mod = 1000;
|
level_mod = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Even more level stuff this time dealing with damage spells
|
//Even more level stuff this time dealing with damage spells
|
||||||
if(IsNPC() && IsDamageSpell(spell_id) && GetLevel() >= 17)
|
if(IsNPC() && IsDamageSpell(spell_id) && level >= 17)
|
||||||
{
|
{
|
||||||
int level_diff;
|
int level_diff;
|
||||||
if(GetLevel() >= RuleI(Casting,ResistFalloff))
|
if(level >= RuleI(Casting,ResistFalloff))
|
||||||
{
|
{
|
||||||
level_diff = (RuleI(Casting,ResistFalloff)-1) - caster_level;
|
level_diff = (RuleI(Casting,ResistFalloff)-1) - caster_level;
|
||||||
if(level_diff < 0)
|
if(level_diff < 0)
|
||||||
@ -4641,7 +4625,7 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
level_diff = GetLevel() - caster_level;
|
level_diff = level - caster_level;
|
||||||
}
|
}
|
||||||
level_mod += (2 * level_diff);
|
level_mod += (2 * level_diff);
|
||||||
}
|
}
|
||||||
@ -4752,17 +4736,17 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
|
|
||||||
if(IsNPC())
|
if(IsNPC())
|
||||||
{
|
{
|
||||||
if(GetLevel() > caster_level && GetLevel() >= 17 && caster_level <= 50)
|
if(level > caster_level && level >= 17 && caster_level <= 50)
|
||||||
{
|
{
|
||||||
partial_modifier += 5;
|
partial_modifier += 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetLevel() >= 30 && caster_level < 50)
|
if(level >= 30 && caster_level < 50)
|
||||||
{
|
{
|
||||||
partial_modifier += (caster_level - 25);
|
partial_modifier += (caster_level - 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetLevel() < 15)
|
if(level < 15)
|
||||||
{
|
{
|
||||||
partial_modifier -= 5;
|
partial_modifier -= 5;
|
||||||
}
|
}
|
||||||
@ -4770,9 +4754,9 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
|
|||||||
|
|
||||||
if(caster->IsNPC())
|
if(caster->IsNPC())
|
||||||
{
|
{
|
||||||
if((GetLevel() - caster_level) >= 20)
|
if((level - caster_level) >= 20)
|
||||||
{
|
{
|
||||||
partial_modifier += (GetLevel() - caster_level) * 1.5;
|
partial_modifier += (level - caster_level) * 1.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -176,9 +176,15 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
|
|||||||
cur_wp = -2; // flag as quest controlled w/no grid
|
cur_wp = -2; // flag as quest controlled w/no grid
|
||||||
Log(Logs::Detail, Logs::AI, "MoveTo %s without a grid.", to_string(static_cast<glm::vec3>(position)).c_str());
|
Log(Logs::Detail, Logs::AI, "MoveTo %s without a grid.", to_string(static_cast<glm::vec3>(position)).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 dest(position);
|
||||||
|
|
||||||
|
m_CurrentWayPoint = position;
|
||||||
|
m_CurrentWayPoint.z = GetFixedZ(dest);
|
||||||
|
|
||||||
if (saveguardspot)
|
if (saveguardspot)
|
||||||
{
|
{
|
||||||
m_GuardPoint = position;
|
m_GuardPoint = m_CurrentWayPoint;
|
||||||
|
|
||||||
if (m_GuardPoint.w == 0)
|
if (m_GuardPoint.w == 0)
|
||||||
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
|
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
|
||||||
@ -189,7 +195,6 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
|
|||||||
Log(Logs::Detail, Logs::AI, "Setting guard position to %s", to_string(static_cast<glm::vec3>(m_GuardPoint)).c_str());
|
Log(Logs::Detail, Logs::AI, "Setting guard position to %s", to_string(static_cast<glm::vec3>(m_GuardPoint)).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentWayPoint = position;
|
|
||||||
cur_wp_pause = 0;
|
cur_wp_pause = 0;
|
||||||
pLastFightingDelayMoving = 0;
|
pLastFightingDelayMoving = 0;
|
||||||
if (AI_walking_timer->Enabled())
|
if (AI_walking_timer->Enabled())
|
||||||
@ -838,35 +843,49 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::FixZ(int32 z_find_offset /*= 5*/)
|
float Mob::GetFixedZ(glm::vec3 dest, int32 z_find_offset)
|
||||||
{
|
{
|
||||||
|
|
||||||
BenchTimer timer;
|
BenchTimer timer;
|
||||||
timer.reset();
|
timer.reset();
|
||||||
|
float new_z = dest.z;
|
||||||
|
|
||||||
if (zone->HasMap() && RuleB(Map, FixZWhenMoving) && (flymode != 1 && flymode != 2))
|
if (zone->HasMap() && RuleB(Map, FixZWhenMoving) &&
|
||||||
|
(flymode != 1 && flymode != 2))
|
||||||
{
|
{
|
||||||
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
|
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap()
|
||||||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
|
|| (zone->HasWaterMap() &&
|
||||||
|
!zone->watermap->InWater(glm::vec3(m_Position))))
|
||||||
{
|
{
|
||||||
/* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors */
|
/* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors */
|
||||||
float new_z = this->FindGroundZ(m_Position.x, m_Position.y, z_find_offset);
|
new_z = this->FindDestGroundZ(dest, z_find_offset);
|
||||||
|
if (new_z != BEST_Z_INVALID)
|
||||||
|
{
|
||||||
new_z += this->GetZOffset();
|
new_z += this->GetZOffset();
|
||||||
|
|
||||||
|
// If bad new Z restore old one
|
||||||
|
if (new_z < -2000) {
|
||||||
|
new_z = m_Position.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto duration = timer.elapsed();
|
auto duration = timer.elapsed();
|
||||||
|
|
||||||
Log(
|
Log(Logs::Moderate, Logs::FixZ,
|
||||||
Logs::Moderate,
|
"Mob::GetFixedZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf",
|
||||||
Logs::FixZ,
|
this->GetCleanName(), new_z, dest.x, dest.y, dest.z, duration);
|
||||||
"Mob::FixZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf",
|
}
|
||||||
this->GetCleanName(),
|
|
||||||
new_z,
|
|
||||||
m_Position.x,
|
|
||||||
m_Position.y,
|
|
||||||
m_Position.z,
|
|
||||||
duration
|
|
||||||
);
|
|
||||||
|
|
||||||
|
return new_z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mob::FixZ(int32 z_find_offset /*= 5*/)
|
||||||
|
{
|
||||||
|
glm::vec3 current_loc(m_Position);
|
||||||
|
float new_z = GetFixedZ(current_loc, z_find_offset);
|
||||||
|
|
||||||
|
if (new_z != m_Position.z)
|
||||||
|
{
|
||||||
if ((new_z > -2000) && new_z != BEST_Z_INVALID) {
|
if ((new_z > -2000) && new_z != BEST_Z_INVALID) {
|
||||||
if (RuleB(Map, MobZVisualDebug))
|
if (RuleB(Map, MobZVisualDebug))
|
||||||
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
||||||
@ -877,10 +896,8 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/)
|
|||||||
if (RuleB(Map, MobZVisualDebug))
|
if (RuleB(Map, MobZVisualDebug))
|
||||||
this->SendAppearanceEffect(103, 0, 0, 0, 0);
|
this->SendAppearanceEffect(103, 0, 0, 0, 0);
|
||||||
|
|
||||||
Log(Logs::General, Logs::FixZ, "%s is failing to find Z %f", this->GetCleanName(), std::abs(m_Position.z - new_z));
|
Log(Logs::General, Logs::FixZ, "%s is failing to find Z %f",
|
||||||
}
|
this->GetCleanName(), std::abs(m_Position.z - new_z));
|
||||||
|
|
||||||
last_z = m_Position.z;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user