Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Paul Coene
2017-06-10 11:28:12 -04:00
940 changed files with 237320 additions and 13661 deletions
+2 -23
View File
@@ -232,11 +232,11 @@ ENDIF(EQEMU_DEPOP_INVALIDATES_CACHE)
ADD_EXECUTABLE(zone ${zone_sources} ${zone_headers})
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
ADD_DEFINITIONS(-DZONE)
TARGET_LINK_LIBRARIES(zone common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
TARGET_LINK_LIBRARIES(zone ${SERVER_LIBS})
IF(EQEMU_BUILD_PERL)
TARGET_LINK_LIBRARIES(zone ${PERL_LIBRARY})
@@ -246,25 +246,4 @@ IF(EQEMU_BUILD_LUA)
TARGET_LINK_LIBRARIES(zone luabind ${LUA_LIBRARY})
ENDIF(EQEMU_BUILD_LUA)
IF(MSVC)
SET_TARGET_PROPERTIES(zone PROPERTIES LINK_FLAGS_RELEASE "/OPT:REF /OPT:ICF")
TARGET_LINK_LIBRARIES(zone "Ws2_32.lib")
ENDIF(MSVC)
IF(MINGW)
TARGET_LINK_LIBRARIES(zone "WS2_32")
ENDIF(MINGW)
IF(UNIX)
TARGET_LINK_LIBRARIES(zone "${CMAKE_DL_LIBS}")
TARGET_LINK_LIBRARIES(zone "z")
TARGET_LINK_LIBRARIES(zone "m")
IF(NOT DARWIN)
TARGET_LINK_LIBRARIES(zone "rt")
ENDIF(NOT DARWIN)
TARGET_LINK_LIBRARIES(zone "pthread")
ADD_DEFINITIONS(-fPIC)
ENDIF(UNIX)
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
+14 -1
View File
@@ -46,8 +46,16 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
if (targ != nullptr && targ->IsCorpse())
return;
// yep, even these need pet power!
int act_power = 0;
if (IsClient()) {
act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);
act_power = CastToClient()->mod_pet_power(act_power, spell_id);
}
PetRecord record;
if (!database.GetPetEntry(spells[spell_id].teleport_zone, &record))
if (!database.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record))
{
Log(Logs::General, Logs::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id);
Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone);
@@ -1194,6 +1202,11 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
Message_StringID(MT_SpellFailure, SNEAK_RESTRICT);
return;
}
//
// Modern clients don't require pet targeted for AA casts that are ST_Pet
if (spells[rank->spell].targettype == ST_Pet || spells[rank->spell].targettype == ST_SummonedPet)
target_id = GetPetID();
// 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)) {
+844 -751
View File
File diff suppressed because it is too large Load Diff
+10 -4
View File
@@ -1442,11 +1442,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
newbon->FeignedCastOnChance = base1;
break;
case SE_AddPetCommand:
if (base1 && base2 < PET_MAXCOMMANDS)
newbon->PetCommands[base2] = true;
break;
case SE_FeignedMinion:
if (newbon->FeignedMinionChance < base1)
newbon->FeignedMinionChance = base1;
break;
// to do
case SE_PetDiscipline:
break;
case SE_PetDiscipline2:
break;
case SE_PotionBeltSlots:
break;
case SE_BandolierSlots:
@@ -1465,8 +1473,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon)
break;
case SE_TrapCircumvention:
break;
case SE_FeignedMinion:
break;
// not handled here
case SE_HastenedAASkill:
+2 -2
View File
@@ -3852,8 +3852,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillT
}
//void Bot::AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false)
void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) {
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic);
void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic, bool pet_command) {
Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic, pet_command);
}
bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) {
+1 -1
View File
@@ -325,7 +325,7 @@ public:
bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::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);
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false);
virtual void SetTarget(Mob* mob);
virtual void Zone();
std::vector<AISpells_Struct> GetBotSpells() { return AIspells; }
+74 -15
View File
@@ -697,12 +697,13 @@ bool Client::AddPacket(const EQApplicationPacket *pApp, bool bAckreq) {
//drop the packet because it will never get sent.
return(false);
}
auto c = new CLIENTPACKET;
auto c = std::unique_ptr<CLIENTPACKET>(new CLIENTPACKET);
c->ack_req = bAckreq;
c->app = pApp->Copy();
clientpackets.Append(c);
clientpackets.push_back(std::move(c));
return true;
}
@@ -714,26 +715,23 @@ bool Client::AddPacket(EQApplicationPacket** pApp, bool bAckreq) {
//drop the packet because it will never get sent.
return(false);
}
auto c = new CLIENTPACKET;
auto c = std::unique_ptr<CLIENTPACKET>(new CLIENTPACKET);
c->ack_req = bAckreq;
c->app = *pApp;
*pApp = nullptr;
clientpackets.Append(c);
clientpackets.push_back(std::move(c));
return true;
}
bool Client::SendAllPackets() {
LinkedListIterator<CLIENTPACKET*> iterator(clientpackets);
CLIENTPACKET* cp = nullptr;
iterator.Reset();
while(iterator.MoreElements()) {
cp = iterator.GetData();
while (!clientpackets.empty()) {
cp = clientpackets.front().get();
if(eqs)
eqs->FastQueuePacket((EQApplicationPacket **)&cp->app, cp->ack_req);
iterator.RemoveCurrent();
clientpackets.pop_front();
Log(Logs::Moderate, Logs::Client_Server_Packet, "Transmitting a packet");
}
return true;
@@ -852,7 +850,6 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
if(GetName() != 0)
strcpy(sem->from, GetName());
pack->Deflate();
if(worldserver.Connected())
worldserver.SendPacket(pack);
safe_delete(pack);
@@ -3932,6 +3929,46 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup
safe_delete(outapp);
}
void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Buttons, uint32 Duration, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) {
auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct));
OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer;
if((strlen(Text) > (sizeof(olms->Text)-1)) || (strlen(Title) > (sizeof(olms->Title) - 1)) ) {
safe_delete(outapp);
return;
}
if (ButtonName0 && ButtonName1 && ( (strlen(ButtonName0) > (sizeof(olms->ButtonName0) - 1)) || (strlen(ButtonName1) > (sizeof(olms->ButtonName1) - 1)) ) ) {
safe_delete(outapp);
return;
}
strcpy(olms->Title, Title);
strcpy(olms->Text, Text);
olms->Buttons = Buttons;
if (ButtonName0 == NULL || ButtonName1 == NULL) {
sprintf(olms->ButtonName0, "%s", "Yes");
sprintf(olms->ButtonName1, "%s", "No");
} else {
strcpy(olms->ButtonName0, ButtonName0);
strcpy(olms->ButtonName1, ButtonName1);
}
if(Duration > 0)
olms->Duration = Duration * 1000;
else
olms->Duration = 0xffffffff;
olms->PopupID = PopupID;
olms->NegativeID = NegativeID;
olms->SoundControls = SoundControls;
QueuePacket(outapp);
safe_delete(outapp);
}
void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...) {
va_list argptr;
char buffer[4096];
@@ -5716,6 +5753,20 @@ void Client::SuspendMinion()
Message_StringID(clientMessageTell, SUSPEND_MINION_UNSUSPEND, CurrentPet->GetCleanName());
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) {
SetPetCommandState(PET_BUTTON_SIT, 0);
SetPetCommandState(PET_BUTTON_STOP, 0);
SetPetCommandState(PET_BUTTON_REGROUP, 0);
SetPetCommandState(PET_BUTTON_FOLLOW, 1);
SetPetCommandState(PET_BUTTON_GUARD, 0);
SetPetCommandState(PET_BUTTON_TAUNT, 1);
SetPetCommandState(PET_BUTTON_HOLD, 0);
SetPetCommandState(PET_BUTTON_GHOLD, 0);
SetPetCommandState(PET_BUTTON_FOCUS, 0);
SetPetCommandState(PET_BUTTON_SPELLHOLD, 0);
}
}
else
return;
@@ -6056,7 +6107,6 @@ void Client::LeaveAdventure()
PendingAdventureLeave();
auto pack = new ServerPacket(ServerOP_AdventureLeave, 64);
strcpy((char*)pack->pBuffer, GetName());
pack->Deflate();
worldserver.SendPacket(pack);
delete pack;
}
@@ -8491,7 +8541,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a
if (type == EQEmu::item::ItemTypeFood)
{
int hchange = item->CastTime * cons_mod;
int hchange = item->CastTime_ * cons_mod;
hchange = mod_food_value(item, hchange);
if(hchange < 0) { return; }
@@ -8508,7 +8558,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a
}
else
{
int tchange = item->CastTime * cons_mod;
int tchange = item->CastTime_ * cons_mod;
tchange = mod_drink_value(item, tchange);
if(tchange < 0) { return; }
@@ -8653,7 +8703,7 @@ void Client::QuestReward(Mob* target, uint32 copper, uint32 silver, uint32 gold,
if (exp > 0)
AddEXP(exp);
QueuePacket(outapp, false, Client::CLIENT_CONNECTED);
QueuePacket(outapp, true, Client::CLIENT_CONNECTED);
safe_delete(outapp);
}
@@ -8939,3 +8989,12 @@ void Client::ProcessAggroMeter()
}
}
void Client::SetPetCommandState(int button, int state)
{
auto app = new EQApplicationPacket(OP_PetCommandState, sizeof(PetCommandState_Struct));
auto pcs = (PetCommandState_Struct *)app->pBuffer;
pcs->button_id = button;
pcs->state = state;
FastQueuePacket(&app);
}
+6 -2
View File
@@ -70,6 +70,7 @@ namespace EQEmu
#include <set>
#include <algorithm>
#include <memory>
#include <deque>
#define CLIENT_TIMEOUT 90000
@@ -209,7 +210,7 @@ struct ClientReward
class ClientFactory {
public:
Client *MakeClient(std::shared_ptr<EQStream> ieqs);
Client *MakeClient(std::shared_ptr<EQStreamInterface> ieqs);
};
class Client : public Mob
@@ -351,6 +352,8 @@ public:
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
void SetPetCommandState(int button, int state);
bool CheckAccess(int16 iDBLevel, int16 iDefaultLevel);
void CheckQuests(const char* zonename, const char* message, uint32 npc_id, uint32 item_id, Mob* other);
@@ -942,6 +945,7 @@ public:
inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); }
uint16 GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skillid, uint16 maxSkill);
void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0);
void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0);
void SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...);
bool PendingTranslocate;
time_t TranslocateTime;
@@ -1424,7 +1428,7 @@ private:
bool AddPacket(const EQApplicationPacket *, bool);
bool AddPacket(EQApplicationPacket**, bool);
bool SendAllPackets();
LinkedList<CLIENTPACKET *> clientpackets;
std::deque<std::unique_ptr<CLIENTPACKET>> clientpackets;
//Zoning related stuff
void SendZoneCancel(ZoneChange_Struct *zc);
+867 -690
View File
File diff suppressed because it is too large Load Diff
-12
View File
@@ -172,7 +172,6 @@ int command_init(void)
command_add("chat", "[channel num] [message] - Send a channel message to all zones", 200, command_chat) ||
command_add("checklos", "- Check for line of sight to your target", 50, command_checklos) ||
command_add("clearinvsnapshots", "[use rule] - Clear inventory snapshot history (true - elapsed entries, false - all entries)", 200, command_clearinvsnapshots) ||
command_add("connectworldserver", "- Make zone attempt to connect to worldserver", 200, command_connectworldserver) ||
command_add("corpse", "- Manipulate corpses, use with no arguments for help", 50, command_corpse) ||
command_add("crashtest", "- Crash the zoneserver", 255, command_crashtest) ||
command_add("cvs", "- Summary of client versions currently online.", 200, command_cvs) ||
@@ -820,17 +819,6 @@ void command_setanim(Client *c, const Seperator *sep)
c->Message(0, "Usage: #setanim [animnum]");
}
void command_connectworldserver(Client *c, const Seperator *sep)
{
if(worldserver.Connected())
c->Message(0, "Error: Already connected to world server");
else
{
c->Message(0, "Attempting to connect to world server...");
worldserver.AsyncConnect();
}
}
void command_serverinfo(Client *c, const Seperator *sep)
{
#ifdef _WINDOWS
+51
View File
@@ -56,6 +56,55 @@
//Maximum distance from a zone point if zone was specified
#define ZONEPOINT_ZONE_RANGE 40000.0f
// Defines based on the RoF2 Client
#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window
#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window
#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window
#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window
#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window
#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window
#define PET_SIT 6 // 0x06 - /pet sit or Pet Window
#define PET_SITDOWN 7 // 0x07 - /pet sit on
#define PET_STANDUP 8 // 0x08 - /pet sit off
#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented
#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented
#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented
#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window
#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on
#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off
#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking
#define PET_HOLD_ON 16 // 0x10 - /pet hold on
#define PET_HOLD_OFF 17 // 0x11 - /pet hold off
#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to
#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on
#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off
#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window
#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on
#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off
#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window
#define PET_FOCUS_ON 25 // 0x19 - /pet focus on
#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off
#define PET_FEIGN 27 // 0x1b - /pet feign
#define PET_BACKOFF 28 // 0x1c - /pet back off
#define PET_GETLOST 29 // 0x1d - /pet get lost
#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet
#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list
#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup
#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup
#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1
// can change the state of these buttons with a packet
#define PET_BUTTON_SIT 0
#define PET_BUTTON_STOP 1
#define PET_BUTTON_REGROUP 2
#define PET_BUTTON_FOLLOW 3
#define PET_BUTTON_GUARD 4
#define PET_BUTTON_TAUNT 5
#define PET_BUTTON_HOLD 6
#define PET_BUTTON_GHOLD 7
#define PET_BUTTON_FOCUS 8
#define PET_BUTTON_SPELLHOLD 9
typedef enum { //focus types
focusSpellHaste = 1,
focusSpellDuration,
@@ -485,6 +534,8 @@ struct StatBonuses {
uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill.
int16 NoBreakAESneak; // Percent value
int16 FeignedCastOnChance; // Percent Value
bool PetCommands[PET_MAXCOMMANDS]; // SPA 267
int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD
};
typedef struct
+7 -58
View File
@@ -19,6 +19,7 @@
#include "../common/global_define.h"
#include "../common/eqemu_logsys.h"
#include "../common/spdat.h"
#include "../common/misc_functions.h"
#include "client.h"
#include "entity.h"
@@ -355,67 +356,15 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
cost -= mana_back;
}
// This formula was derived from the following resource:
// http://www.eqsummoners.com/eq1/specialization-library.html
// WildcardX
float PercentManaReduction = 0;
float SpecializeSkill = GetSpecializeSkillValue(spell_id);
int SuccessChance = zone->random.Int(0, 100);
float bonus = 1.0;
switch(GetAA(aaSpellCastingMastery))
{
case 1:
bonus += 0.05;
break;
case 2:
bonus += 0.15;
break;
case 3:
bonus += 0.30;
break;
}
bonus += 0.05f * GetAA(aaAdvancedSpellCastingMastery);
if(SuccessChance <= (SpecializeSkill * 0.3 * bonus))
{
PercentManaReduction = 1 + 0.05f * SpecializeSkill;
switch(GetAA(aaSpellCastingMastery))
{
case 1:
PercentManaReduction += 2.5;
break;
case 2:
PercentManaReduction += 5.0;
break;
case 3:
PercentManaReduction += 10.0;
break;
}
switch(GetAA(aaAdvancedSpellCastingMastery))
{
case 1:
PercentManaReduction += 2.5;
break;
case 2:
PercentManaReduction += 5.0;
break;
case 3:
PercentManaReduction += 10.0;
break;
}
}
int spec = GetSpecializeSkillValue(spell_id);
int PercentManaReduction = 0;
if (spec)
PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now.
int16 focus_redux = GetFocusEffect(focusManaCost, spell_id);
PercentManaReduction += focus_redux;
if(focus_redux > 0)
{
PercentManaReduction += zone->random.Real(1, (double)focus_redux);
}
cost -= (cost * (PercentManaReduction / 100));
cost -= cost * PercentManaReduction / 100;
// Gift of Mana - reduces spell cost to 1 mana
if(focus_redux >= 100) {
+1 -1
View File
@@ -648,7 +648,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender)
}
}
if (GetLeader() == nullptr)
if (!GetLeaderName())
{
DisbandGroup();
return true;
-2
View File
@@ -837,7 +837,6 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd
}
}
qspack->Deflate();
if(worldserver.Connected()) { worldserver.SendPacket(qspack); }
safe_delete(qspack);
}
@@ -2083,7 +2082,6 @@ void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) {
}
if(move_count && worldserver.Connected()) {
qspack->Deflate();
worldserver.SendPacket(qspack);
}
+75
View File
@@ -1340,6 +1340,80 @@ void Lua_Client::QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint3
self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, faction);
}
void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) {
Lua_Safe_Call_Void();
if (luabind::type(reward) != LUA_TTABLE) {
return;
}
uint32 copper = 0;
uint32 silver = 0;
uint32 gold = 0;
uint32 platinum = 0;
uint32 itemid = 0;
uint32 exp = 0;
bool faction = false;
auto cur = reward["copper"];
if (luabind::type(cur) != LUA_TNIL) {
try {
copper = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
}
}
cur = reward["silver"];
if (luabind::type(cur) != LUA_TNIL) {
try {
silver = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
}
}
cur = reward["gold"];
if (luabind::type(cur) != LUA_TNIL) {
try {
gold = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
}
}
cur = reward["platinum"];
if (luabind::type(cur) != LUA_TNIL) {
try {
platinum = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
}
}
cur = reward["itemid"];
if (luabind::type(cur) != LUA_TNIL) {
try {
itemid = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
}
}
cur = reward["exp"];
if (luabind::type(cur) != LUA_TNIL) {
try {
exp = luabind::object_cast<uint32>(cur);
} catch (luabind::cast_failed) {
}
}
cur = reward["faction"];
if (luabind::type(cur) != LUA_TNIL) {
try {
faction = luabind::object_cast<bool>(cur);
} catch (luabind::cast_failed) {
}
}
self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, faction);
}
uint32 Lua_Client::GetMoney(uint8 type, uint8 subtype) {
Lua_Safe_Call_Int();
return self->GetMoney(type, subtype);
@@ -1612,6 +1686,7 @@ luabind::scope lua_register_client() {
.def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward)
.def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward)
.def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Lua_Client::QuestReward)
.def("QuestReward", (void(Lua_Client::*)(Lua_Mob, luabind::adl::object))&Lua_Client::QuestReward)
.def("GetMoney", (uint32(Lua_Client::*)(uint8, uint8))&Lua_Client::GetMoney);
}
+1
View File
@@ -296,6 +296,7 @@ public:
void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid);
void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp);
void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction);
void QuestReward(Lua_Mob target, luabind::adl::object reward);
};
#endif
+2 -2
View File
@@ -4490,7 +4490,7 @@ void Merc::DoClassAttacks(Mob *target) {
if(level >= RuleI(Combat, NPCBashKickLevel)){
if(zone->random.Int(0, 100) > 25) //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
{
DoAnim(animKick);
DoAnim(animKick, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@@ -4502,7 +4502,7 @@ void Merc::DoClassAttacks(Mob *target) {
}
else
{
DoAnim(animTailRake);
DoAnim(animTailRake, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
+25 -1
View File
@@ -18,6 +18,7 @@
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/misc_functions.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
@@ -343,8 +344,11 @@ Mob::Mob(const char* in_name,
typeofpet = petNone; // default to not a pet
petpower = 0;
held = false;
gheld = false;
nocast = false;
focused = false;
pet_stop = false;
pet_regroup = false;
_IsTempPet = false;
pet_owner_client = false;
pet_targetlock_id = 0;
@@ -2131,7 +2135,7 @@ void Mob::SendTargetable(bool on, Client *specific_target) {
entity_list.QueueClients(this, outapp);
}
else if (specific_target->IsClient()) {
specific_target->CastToClient()->QueuePacket(outapp, false);
specific_target->CastToClient()->QueuePacket(outapp);
}
safe_delete(outapp);
}
@@ -3092,6 +3096,26 @@ void Mob::Say_StringID(uint32 type, uint32 string_id, const char *message3, cons
);
}
void Mob::SayTo_StringID(Client *to, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{
if (!to)
return;
auto string_id_str = std::to_string(string_id);
to->Message_StringID(10, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9);
}
void Mob::SayTo_StringID(Client *to, uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{
if (!to)
return;
auto string_id_str = std::to_string(string_id);
to->Message_StringID(type, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9);
}
void Mob::Shout(const char *format, ...)
{
char buf[1000];
+14 -1
View File
@@ -533,7 +533,7 @@ public:
inline uint32 GetLevelCon(uint8 iOtherLevel) const {
return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GRAY; }
virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true,
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN);
bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false);
bool RemoveFromHateList(Mob* mob);
void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);}
void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); }
@@ -642,6 +642,10 @@ public:
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void Say_StringID(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void SayTo_StringID(Client *to, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void SayTo_StringID(Client *to, uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void Shout(const char *format, ...);
void Emote(const char *format, ...);
void QuestJournalledSay(Client *QuestInitiator, const char *str);
@@ -869,10 +873,16 @@ public:
inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; }
inline void SetHeld(bool nState) { held = nState; }
inline const bool IsHeld() const { return held; }
inline void SetGHeld(bool nState) { gheld = nState; }
inline const bool IsGHeld() const { return gheld; }
inline void SetNoCast(bool nState) { nocast = nState; }
inline const bool IsNoCast() const { return nocast; }
inline void SetFocused(bool nState) { focused = nState; }
inline const bool IsFocused() const { return focused; }
inline void SetPetStop(bool nState) { pet_stop = nState; }
inline const bool IsPetStop() const { return pet_stop; }
inline void SetPetRegroup(bool nState) { pet_regroup = nState; }
inline const bool IsPetRegroup() const { return pet_regroup; }
inline const bool IsRoamer() const { return roamer; }
inline const int GetWanderType() const { return wandertype; }
inline const bool IsRooted() const { return rooted || permarooted; }
@@ -1179,8 +1189,11 @@ protected:
uint32 pLastChange;
bool held;
bool gheld;
bool nocast;
bool focused;
bool pet_stop;
bool pet_regroup;
bool spawned;
void CalcSpellBonuses(StatBonuses* newbon);
virtual void CalcBonuses();
+15 -33
View File
@@ -345,7 +345,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain
}
bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) {
if((iSpellTypes&SpellTypes_Detrimental) != 0) {
if((iSpellTypes & SpellTypes_Detrimental) != 0) {
//according to live, you can buff and heal through walls...
//now with PCs, this only applies if you can TARGET the target, but
// according to Rogean, Live NPCs will just cast through walls/floors, no problem..
@@ -374,41 +374,19 @@ bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float
float iRange2 = iRange*iRange;
float t1, t2, t3;
//Only iterate through NPCs
for (auto it = npc_list.begin(); it != npc_list.end(); ++it) {
NPC* mob = it->second;
//Since >90% of mobs will always be out of range, try to
//catch them with simple bounding box checks first. These
//checks are about 6X faster than DistNoRoot on my athlon 1Ghz
t1 = mob->GetX() - caster->GetX();
t2 = mob->GetY() - caster->GetY();
t3 = mob->GetZ() - caster->GetZ();
//cheap ABS()
if(t1 < 0)
t1 = 0 - t1;
if(t2 < 0)
t2 = 0 - t2;
if(t3 < 0)
t3 = 0 - t3;
if (t1 > iRange
|| t2 > iRange
|| t3 > iRange
|| DistanceSquared(mob->GetPosition(), caster->GetPosition()) > iRange2
//this call should seem backwards:
|| !mob->CheckLosFN(caster)
|| mob->GetReverseFactionCon(caster) >= FACTION_KINDLY
) {
if (mob->GetReverseFactionCon(caster) >= FACTION_KINDLY) {
continue;
}
//since we assume these are beneficial spells, which do not
//require LOS, we just go for it.
// we have a winner!
if((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)){
if (DistanceSquared(caster->GetPosition(), mob->GetPosition()) > iRange2) {
continue;
}
if ((iSpellTypes & SpellType_Buff) && !RuleB(NPC, BuffFriends)) {
if (mob != caster)
iSpellTypes = SpellType_Heal;
}
@@ -957,7 +935,7 @@ void Mob::AI_Process() {
bool engaged = IsEngaged();
bool doranged = false;
if (!zone->CanDoCombat()) {
if (!zone->CanDoCombat() || IsPetStop() || IsPetRegroup()) {
engaged = false;
}
@@ -965,7 +943,7 @@ void Mob::AI_Process() {
//
if(RuleB(Combat, EnableFearPathing)){
if(currently_fleeing) {
if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) {
if((IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) && !IsPetStop() && !IsPetRegroup()) {
//make sure everybody knows were not moving, for appearance sake
if(IsMoving())
{
@@ -1322,10 +1300,12 @@ void Mob::AI_Process() {
}
}
else {
if (m_PlayerState & static_cast<uint32>(PlayerState::Aggressive))
SendRemovePlayerState(PlayerState::Aggressive);
if (IsPetStop()) // pet stop won't be engaged, so we will always get here and we want the above branch to execute
return;
if(zone->CanDoCombat() && AI_feign_remember_timer->Check()) {
// 6/14/06
// Improved Feign Death Memory
@@ -1431,6 +1411,8 @@ void Mob::AI_Process() {
break;
}
}
if (IsPetRegroup())
return;
}
/* Entity has been assigned another entity to follow */
else if (GetFollowID())
+169 -180
View File
@@ -1,19 +1,19 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org)
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemu.org)
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 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.
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
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
*/
#define DONT_SHARED_OPCODES
@@ -23,8 +23,6 @@
#include "../common/features.h"
#include "../common/queue.h"
#include "../common/timer.h"
#include "../common/eq_stream.h"
#include "../common/eq_stream_factory.h"
#include "../common/eq_packet_structs.h"
#include "../common/mutex.h"
#include "../common/version.h"
@@ -65,6 +63,10 @@
#include "lua_parser.h"
#include "questmgr.h"
#include "../common/event/event_loop.h"
#include "../common/event/timer.h"
#include "../common/net/eqstream.h"
#include <iostream>
#include <string>
#include <fstream>
@@ -73,31 +75,31 @@
#include <signal.h>
#include <time.h>
#include <ctime>
#include <thread>
#include <chrono>
#ifdef _CRTDBG_MAP_ALLOC
#undef new
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#undef new
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif
#ifdef _WINDOWS
#include <conio.h>
#include <process.h>
#include <conio.h>
#include <process.h>
#else
#include <pthread.h>
#include "../common/unix.h"
#include <pthread.h>
#include "../common/unix.h"
#endif
volatile bool RunLoops = true;
extern volatile bool is_zone_loaded;
TimeoutManager timeout_manager;
NetConnection net;
EntityList entity_list;
WorldServer worldserver;
uint32 numclients = 0;
char errorname[32];
extern Zone* zone;
EQStreamFactory eqsf(ZoneStream);
npcDecayTimes_Struct npcCorpseDecayTimes[100];
TitleManager title_manager;
QueryServ *QServ = 0;
@@ -107,15 +109,16 @@ EQEmuLogSys LogSys;
const SPDat_Spell_Struct* spells;
int32 SPDAT_RECORDS = -1;
const ZoneConfig *Config;
uint64_t frame_time = 0;
void Shutdown();
extern void MapOpcodes();
int main(int argc, char** argv) {
RegisterExecutablePlatform(ExePlatformZone);
RegisterExecutablePlatform(ExePlatformZone);
LogSys.LoadLogSettingsDefaults();
set_exception_handler();
set_exception_handler();
#ifdef USE_MAP_MMFS
if (argc == 3 && strcasecmp(argv[1], "convert_map") == 0) {
@@ -132,7 +135,7 @@ int main(int argc, char** argv) {
auto success = m->Load(filename, true);
delete m;
std::cout << mapfile.c_str() << " conversion " << (success ? "succeeded" : "failed") << std::endl;
return 0;
}
#endif /*USE_MAP_MMFS*/
@@ -140,7 +143,7 @@ int main(int argc, char** argv) {
QServ = new QueryServ;
Log(Logs::General, Logs::Zone_Server, "Loading server configuration..");
if(!ZoneConfig::LoadConfig()) {
if (!ZoneConfig::LoadConfig()) {
Log(Logs::General, Logs::Error, "Loading server configuration failed.");
return 1;
}
@@ -149,74 +152,77 @@ int main(int argc, char** argv) {
const char *zone_name;
uint32 instance_id = 0;
std::string z_name;
if(argc == 4) {
if (argc == 4) {
instance_id = atoi(argv[3]);
worldserver.SetLauncherName(argv[2]);
auto zone_port = SplitString(argv[1], ':');
if(!zone_port.empty()) {
if (!zone_port.empty()) {
z_name = zone_port[0];
}
if(zone_port.size() > 1) {
if (zone_port.size() > 1) {
std::string p_name = zone_port[1];
Config->SetZonePort(atoi(p_name.c_str()));
}
worldserver.SetLaunchedName(z_name.c_str());
if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) {
if (strncmp(z_name.c_str(), "dynamic_", 8) == 0) {
zone_name = ".";
}
else {
zone_name = z_name.c_str();
}
} else if(argc == 3) {
}
else if (argc == 3) {
worldserver.SetLauncherName(argv[2]);
auto zone_port = SplitString(argv[1], ':');
if(!zone_port.empty()) {
if (!zone_port.empty()) {
z_name = zone_port[0];
}
if(zone_port.size() > 1) {
if (zone_port.size() > 1) {
std::string p_name = zone_port[1];
Config->SetZonePort(atoi(p_name.c_str()));
}
worldserver.SetLaunchedName(z_name.c_str());
if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) {
zone_name = ".";
} else {
zone_name = z_name.c_str();
}
} else if (argc == 2) {
worldserver.SetLauncherName("NONE");
auto zone_port = SplitString(argv[1], ':');
if(!zone_port.empty()) {
z_name = zone_port[0];
}
if(zone_port.size() > 1) {
std::string p_name = zone_port[1];
Config->SetZonePort(atoi(p_name.c_str()));
}
worldserver.SetLaunchedName(z_name.c_str());
if(strncmp(z_name.c_str(), "dynamic_", 8) == 0) {
if (strncmp(z_name.c_str(), "dynamic_", 8) == 0) {
zone_name = ".";
}
else {
zone_name = z_name.c_str();
}
} else {
}
else if (argc == 2) {
worldserver.SetLauncherName("NONE");
auto zone_port = SplitString(argv[1], ':');
if (!zone_port.empty()) {
z_name = zone_port[0];
}
if (zone_port.size() > 1) {
std::string p_name = zone_port[1];
Config->SetZonePort(atoi(p_name.c_str()));
}
worldserver.SetLaunchedName(z_name.c_str());
if (strncmp(z_name.c_str(), "dynamic_", 8) == 0) {
zone_name = ".";
}
else {
zone_name = z_name.c_str();
}
}
else {
zone_name = ".";
worldserver.SetLaunchedName(".");
worldserver.SetLauncherName("NONE");
}
worldserver.SetPassword(Config->SharedKey.c_str());
Log(Logs::General, Logs::Zone_Server, "Connecting to MySQL...");
if (!database.Connect(
Config->DatabaseHost.c_str(),
@@ -242,7 +248,7 @@ int main(int argc, char** argv) {
/* Register Log System and Settings */
LogSys.OnLogHookCallBackZone(&Zone::GMSayHookCallBackProcess);
database.LoadLogSettings(LogSys.log_settings);
database.LoadLogSettings(LogSys.log_settings);
LogSys.StartFileLogs();
/* Guilds */
@@ -250,7 +256,7 @@ int main(int argc, char** argv) {
GuildBanks = nullptr;
#ifdef _EQDEBUG
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
Log(Logs::General, Logs::Zone_Server, "CURRENT_VERSION: %s", CURRENT_VERSION);
@@ -258,20 +264,20 @@ int main(int argc, char** argv) {
/*
* Setup nice signal handlers
*/
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
if (signal(SIGINT, CatchSignal) == SIG_ERR) {
Log(Logs::General, Logs::Error, "Could not set signal handler");
return 1;
}
if (signal(SIGTERM, CatchSignal) == SIG_ERR) {
if (signal(SIGTERM, CatchSignal) == SIG_ERR) {
Log(Logs::General, Logs::Error, "Could not set signal handler");
return 1;
}
#ifndef WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
#ifndef WIN32
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
Log(Logs::General, Logs::Error, "Could not set signal handler");
return 1;
}
#endif
#endif
Log(Logs::General, Logs::Zone_Server, "Mapping Incoming Opcodes");
MapOpcodes();
@@ -280,8 +286,8 @@ int main(int argc, char** argv) {
database.LoadVariables();
std::string hotfix_name;
if(database.GetVariable("hotfix_name", hotfix_name)) {
if(!hotfix_name.empty()) {
if (database.GetVariable("hotfix_name", hotfix_name)) {
if (!hotfix_name.empty()) {
Log(Logs::General, Logs::Zone_Server, "Current hotfix in use: '%s'", hotfix_name.c_str());
}
}
@@ -290,75 +296,75 @@ int main(int argc, char** argv) {
database.LoadZoneNames();
Log(Logs::General, Logs::Zone_Server, "Loading items");
if(!database.LoadItems(hotfix_name)) {
if (!database.LoadItems(hotfix_name)) {
Log(Logs::General, Logs::Error, "Loading items FAILED!");
Log(Logs::General, Logs::Error, "Failed. But ignoring error and going on...");
}
Log(Logs::General, Logs::Zone_Server, "Loading npc faction lists");
if(!database.LoadNPCFactionLists(hotfix_name)) {
if (!database.LoadNPCFactionLists(hotfix_name)) {
Log(Logs::General, Logs::Error, "Loading npcs faction lists FAILED!");
return 1;
}
Log(Logs::General, Logs::Zone_Server, "Loading loot tables");
if(!database.LoadLoot(hotfix_name)) {
if (!database.LoadLoot(hotfix_name)) {
Log(Logs::General, Logs::Error, "Loading loot FAILED!");
return 1;
}
Log(Logs::General, Logs::Zone_Server, "Loading skill caps");
if(!database.LoadSkillCaps(std::string(hotfix_name))) {
if (!database.LoadSkillCaps(std::string(hotfix_name))) {
Log(Logs::General, Logs::Error, "Loading skill caps FAILED!");
return 1;
}
Log(Logs::General, Logs::Zone_Server, "Loading spells");
if(!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) {
if (!database.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) {
Log(Logs::General, Logs::Error, "Loading spells FAILED!");
return 1;
}
Log(Logs::General, Logs::Zone_Server, "Loading base data");
if(!database.LoadBaseData(hotfix_name)) {
if (!database.LoadBaseData(hotfix_name)) {
Log(Logs::General, Logs::Error, "Loading base data FAILED!");
return 1;
}
Log(Logs::General, Logs::Zone_Server, "Loading guilds");
guild_mgr.LoadGuilds();
Log(Logs::General, Logs::Zone_Server, "Loading factions");
database.LoadFactionData();
Log(Logs::General, Logs::Zone_Server, "Loading titles");
title_manager.LoadTitles();
Log(Logs::General, Logs::Zone_Server, "Loading tributes");
database.LoadTributes();
Log(Logs::General, Logs::Zone_Server, "Loading corpse timers");
database.GetDecayTimes(npcCorpseDecayTimes);
Log(Logs::General, Logs::Zone_Server, "Loading commands");
int retval=command_init();
if (retval < 0) {
int retval = command_init();
if (retval<0)
Log(Logs::General, Logs::Error, "Command loading FAILED");
}
else {
else
Log(Logs::General, Logs::Zone_Server, "%d commands loaded", retval);
}
//rules:
{
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())) {
Log(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
}
} else {
if(!RuleManager::Instance()->LoadRules(&database, "default")) {
}
else {
if (!RuleManager::Instance()->LoadRules(&database, "default")) {
Log(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules");
} else {
}
else {
Log(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str());
}
}
@@ -367,20 +373,17 @@ int main(int argc, char** argv) {
#ifdef BOTS
Log(Logs::General, Logs::Zone_Server, "Loading bot commands");
int botretval = bot_command_init();
if (botretval < 0) {
if (botretval<0)
Log(Logs::General, Logs::Error, "Bot command loading FAILED");
}
else {
else
Log(Logs::General, Logs::Zone_Server, "%d bot commands loaded", botretval);
}
Log(Logs::General, Logs::Zone_Server, "Loading bot spell casting chances");
if (!botdb.LoadBotSpellCastingChances()) {
if (!botdb.LoadBotSpellCastingChances())
Log(Logs::General, Logs::Error, "Bot spell casting chances loading FAILED");
}
#endif
if(RuleB(TaskSystem, EnableTaskSystem)) {
if (RuleB(TaskSystem, EnableTaskSystem)) {
Log(Logs::General, Logs::Tasks, "[INIT] Loading Tasks");
taskmanager = new TaskManager;
taskmanager->LoadTasks();
@@ -405,20 +408,19 @@ int main(int argc, char** argv) {
Log(Logs::General, Logs::Zone_Server, "Loading quests");
parse->ReloadQuests();
if (!worldserver.Connect()) {
Log(Logs::General, Logs::Error, "Worldserver Connection Failed :: worldserver.Connect()");
}
worldserver.Connect();
Timer InterserverTimer(INTERSERVER_TIMER); // does MySQL pings and auto-reconnect
#ifdef EQPROFILE
#ifdef PROFILE_DUMP_TIME
Timer profile_dump_timer(PROFILE_DUMP_TIME*1000);
Timer profile_dump_timer(PROFILE_DUMP_TIME * 1000);
profile_dump_timer.Start();
#endif
#endif
if (!strlen(zone_name) || !strcmp(zone_name,".")) {
if (!strlen(zone_name) || !strcmp(zone_name, ".")) {
Log(Logs::General, Logs::Zone_Server, "Entering sleep mode");
} else if (!Zone::Bootup(database.GetZoneID(zone_name), instance_id, true)) {
}
else if (!Zone::Bootup(database.GetZoneID(zone_name), instance_id, true)) {
Log(Logs::General, Logs::Error, "Zone Bootup failed :: Zone::Bootup");
zone = 0;
}
@@ -428,52 +430,45 @@ int main(int argc, char** argv) {
RegisterAllPatches(stream_identifier);
#ifndef WIN32
Log(Logs::Detail, Logs::None, "Main thread running with thread id %d", pthread_self());
Log(Logs::Detail, Logs::None, "Main thread running with thread id %d", pthread_self());
#endif
Timer quest_timers(100);
UpdateWindowTitle();
bool worldwasconnected = worldserver.Connected();
std::shared_ptr<EQStream> eqss;
std::shared_ptr<EQStreamInterface> eqss;
EQStreamInterface *eqsi;
uint8 IDLEZONEUPDATE = 200;
uint8 ZONEUPDATE = 10;
Timer zoneupdate_timer(ZONEUPDATE);
zoneupdate_timer.Start();
while(RunLoops) {
{ //profiler block to omit the sleep from times
bool eqsf_open = false;
std::unique_ptr<EQ::Net::EQStreamManager> eqsm;
std::chrono::time_point<std::chrono::system_clock> frame_prev = std::chrono::system_clock::now();
auto loop_fn = [&](EQ::Timer* t) {
//Advance the timer to our current point in time
Timer::SetCurrentTime();
worldserver.Process();
//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_prev = frame_now;
if (!eqsf.IsOpen() && Config->ZonePort != 0) {
if (!eqsf_open && Config->ZonePort != 0) {
Log(Logs::General, Logs::Zone_Server, "Starting EQ Network server on port %d", Config->ZonePort);
if (!eqsf.Open(Config->ZonePort)) {
Log(Logs::General, Logs::Error, "Failed to open port %d", Config->ZonePort);
ZoneConfig::SetZonePort(0);
worldserver.Disconnect();
worldwasconnected = false;
}
}
//check the factory for any new incoming streams.
while ((eqss = eqsf.Pop())) {
//pull the stream out of the factory and give it to the stream identifier
//which will figure out what patch they are running, and set up the dynamic
//structures and opcodes for that patch.
struct in_addr in;
in.s_addr = eqss->GetRemoteIP();
Log(Logs::Detail, Logs::World_Server, "New connection from %s:%d", inet_ntoa(in), ntohs(eqss->GetRemotePort()));
stream_identifier.AddStream(eqss); //takes the stream
EQ::Net::EQStreamManagerOptions opts(Config->ZonePort, false, true);
eqsm.reset(new EQ::Net::EQStreamManager(opts));
eqsf_open = true;
eqsm->OnNewConnection([&stream_identifier](std::shared_ptr<EQ::Net::EQStream> stream) {
stream_identifier.AddStream(stream);
LogF(Logs::Detail, Logs::World_Server, "New connection from IP {0}:{1}", stream->RemoteEndpoint(), ntohs(stream->GetRemotePort()));
});
}
//give the stream identifier a chance to do its work....
stream_identifier.Process();
//check the stream identifier for any now-identified streams
while((eqsi = stream_identifier.PopIdentified())) {
while ((eqsi = stream_identifier.PopIdentified())) {
//now that we know what patch they are running, start up their client object
struct in_addr in;
in.s_addr = eqsi->GetRemoteIP();
@@ -482,86 +477,83 @@ int main(int argc, char** argv) {
entity_list.AddClient(client);
}
if ( numclients < 1 && zoneupdate_timer.GetDuration() != IDLEZONEUPDATE )
zoneupdate_timer.SetTimer(IDLEZONEUPDATE);
else if ( numclients > 0 && zoneupdate_timer.GetDuration() == IDLEZONEUPDATE )
{
zoneupdate_timer.SetTimer(ZONEUPDATE);
zoneupdate_timer.Trigger();
}
//check for timeouts in other threads
timeout_manager.CheckTimeouts();
if (worldserver.Connected()) {
worldwasconnected = true;
}
else {
if (worldwasconnected && is_zone_loaded)
if (worldwasconnected && is_zone_loaded) {
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost");
worldwasconnected = false;
worldwasconnected = false;
}
}
if (is_zone_loaded && zoneupdate_timer.Check()) {
if (is_zone_loaded) {
{
if(net.group_timer.Enabled() && net.group_timer.Check())
if (net.group_timer.Enabled() && net.group_timer.Check())
entity_list.GroupProcess();
if(net.door_timer.Enabled() && net.door_timer.Check())
if (net.door_timer.Enabled() && net.door_timer.Check())
entity_list.DoorProcess();
if(net.object_timer.Enabled() && net.object_timer.Check())
if (net.object_timer.Enabled() && net.object_timer.Check())
entity_list.ObjectProcess();
if(net.corpse_timer.Enabled() && net.corpse_timer.Check())
if (net.corpse_timer.Enabled() && net.corpse_timer.Check())
entity_list.CorpseProcess();
if(net.trap_timer.Enabled() && net.trap_timer.Check())
if (net.trap_timer.Enabled() && net.trap_timer.Check())
entity_list.TrapProcess();
if(net.raid_timer.Enabled() && net.raid_timer.Check())
if (net.raid_timer.Enabled() && net.raid_timer.Check())
entity_list.RaidProcess();
entity_list.Process();
entity_list.MobProcess();
entity_list.Process();
entity_list.MobProcess();
entity_list.BeaconProcess();
entity_list.EncounterProcess();
if (zone) {
if(!zone->Process()) {
if (!zone->Process()) {
Zone::Shutdown();
}
}
if(quest_timers.Check())
if (quest_timers.Check())
quest_manager.Process();
}
}
if (InterserverTimer.Check()) {
InterserverTimer.Start();
database.ping();
// AsyncLoadVariables(dbasync, &database);
entity_list.UpdateWho();
if (worldserver.TryReconnect() && (!worldserver.Connected()))
worldserver.AsyncConnect();
}
};
EQ::Timer process_timer(loop_fn);
process_timer.Start(1000, true);
while (RunLoops) {
bool previous_loaded = is_zone_loaded && numclients > 0;
EQ::EventLoop::Get().Process();
bool current_loaded = is_zone_loaded && numclients > 0;
if (previous_loaded && !current_loaded) {
process_timer.Stop();
process_timer.Start(1000, true);
}
else if (!previous_loaded && current_loaded) {
process_timer.Stop();
process_timer.Start(32, true);
}
#ifdef EQPROFILE
#ifdef PROFILE_DUMP_TIME
if(profile_dump_timer.Check()) {
DumpZoneProfile();
}
#endif
#endif
} //end extra profiler block
if (is_zone_loaded && numclients > 0) {
Sleep(ZoneTimerResolution);
if (current_loaded) {
Sleep(1);
}
else {
Sleep(1000);
Sleep(10);
}
}
entity_list.Clear();
@@ -570,7 +562,7 @@ int main(int argc, char** argv) {
parse->ClearInterfaces();
#ifdef EMBPERL
safe_delete(perl_parser);
safe_delete(perl_parser);
#endif
#ifdef LUA_EQEMU
@@ -582,8 +574,6 @@ int main(int argc, char** argv) {
if (zone != 0)
Zone::Shutdown(true);
//Fix for Linux world server problem.
eqsf.Close();
worldserver.Disconnect();
safe_delete(taskmanager);
command_deinit();
#ifdef BOTS
@@ -606,14 +596,13 @@ void Shutdown()
{
Zone::Shutdown(true);
RunLoops = false;
worldserver.Disconnect();
Log(Logs::General, Logs::Zone_Server, "Shutting down...");
LogSys.CloseFileLogs();
}
uint32 NetConnection::GetIP()
{
char name[255+1];
char name[255 + 1];
size_t len = 0;
hostent* host = 0;
@@ -646,7 +635,7 @@ uint32 NetConnection::GetIP(char* name)
}
NetConnection::NetConnection()
:
:
object_timer(5000),
door_timer(5000),
corpse_timer(2000),
@@ -674,20 +663,20 @@ void UpdateWindowTitle(char* iNewTitle) {
}
else {
if (zone) {
#if defined(GOTFRAGS) || defined(_EQDEBUG)
snprintf(tmp, sizeof(tmp), "%i: %s, %i clients, %i", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients, getpid());
#else
#if defined(GOTFRAGS) || defined(_EQDEBUG)
snprintf(tmp, sizeof(tmp), "%i: %s, %i clients, %i", ZoneConfig::get()->ZonePort, zone->GetShortName(), numclients, getpid());
#else
snprintf(tmp, sizeof(tmp), "%s :: clients: %i inst_id: %i inst_ver: %i :: port: %i", zone->GetShortName(), numclients, zone->GetInstanceID(), zone->GetInstanceVersion(), ZoneConfig::get()->ZonePort);
#endif
#endif
}
else {
#if defined(GOTFRAGS) || defined(_EQDEBUG)
snprintf(tmp, sizeof(tmp), "%i: sleeping, %i", ZoneConfig::get()->ZonePort, getpid());
#else
snprintf(tmp, sizeof(tmp), "%i: sleeping", ZoneConfig::get()->ZonePort);
#endif
#if defined(GOTFRAGS) || defined(_EQDEBUG)
snprintf(tmp, sizeof(tmp), "%i: sleeping, %i", ZoneConfig::get()->ZonePort, getpid());
#else
snprintf(tmp, sizeof(tmp), "%i: sleeping", ZoneConfig::get()->ZonePort);
#endif
}
}
SetConsoleTitle(tmp);
#endif
}
}
+1 -1
View File
@@ -684,7 +684,7 @@ bool NPC::Process()
if(viral_timer.Check()) {
viral_timer_counter++;
for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) {
if(viral_spells[i]) {
if(viral_spells[i] && spells[viral_spells[i]].viral_timer > 0) {
if(viral_timer_counter % spells[viral_spells[i]].viral_timer == 0) {
SpreadVirus(viral_spells[i], viral_spells[i+1]);
}
+42
View File
@@ -6444,6 +6444,47 @@ XS(XS_Client_GetAccountAge) {
XSRETURN(1);
}
XS(XS_Client_Popup2); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_Popup2)
{
dXSARGS;
if (items < 3 || items > 10)
Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, SoundControls)");
{
Client * THIS;
char* Title = (char *)SvPV_nolen(ST(1));
char* Text = (char *)SvPV_nolen(ST(2));
uint32 PopupID = 0;
uint32 NegativeID = 0;
uint32 Buttons = 0;
uint32 Duration = 0;
char* ButtonName0 = 0;
char* ButtonName1 = 0;
uint32 SoundControls = 0;
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.");
if (items > 3) { PopupID = (uint32)SvUV(ST(3)); }
if (items > 4) { NegativeID = (uint32)SvUV(ST(4)); }
if (items > 5) { Buttons = (uint32)SvUV(ST(5)); }
if (items > 6) { Duration = (uint32)SvUV(ST(6)); }
if (items > 7) { ButtonName0 = (char *)SvPV_nolen(ST(7)); }
if (items > 8) { ButtonName1 = (char *)SvPV_nolen(ST(8)); }
if (items > 9) { SoundControls = (uint32)SvUV(ST(9)); }
THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, SoundControls);
}
XSRETURN_EMPTY;
}
#ifdef __cplusplus
extern "C"
@@ -6698,6 +6739,7 @@ XS(boot_Client)
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, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$");
XSRETURN_YES;
}
+2 -2
View File
@@ -706,7 +706,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
// all of the result rows. Check if we have something in the slot
// already. If no, add the item id to the equipment array.
while (curset >= 0 && depth < 5) {
std::string query = StringFormat("SELECT nested_set FROM pets_equipmentset WHERE set_id = '%s'", curset);
std::string query = StringFormat("SELECT nested_set FROM pets_equipmentset WHERE set_id = '%d'", curset);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
@@ -721,7 +721,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
auto row = results.begin();
nextset = atoi(row[0]);
query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%s'", curset);
query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%d'", curset);
results = QueryDatabase(query);
if (results.Success()) {
for (row = results.begin(); row != results.end(); ++row)
-32
View File
@@ -1,38 +1,6 @@
#ifndef PETS_H
#define PETS_H
// Defines based on the RoF2 Client
#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window
#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window
#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window
#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window
#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window
#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window
#define PET_SIT 6 // 0x06 - /pet sit or Pet Window
#define PET_SITDOWN 7 // 0x07 - /pet sit on
#define PET_STANDUP 8 // 0x08 - /pet sit off
#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented
#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented
#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented
#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window
#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on
#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off
#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window
#define PET_HOLD_ON 16 // 0x10 - /pet hold on
#define PET_HOLD_OFF 17 // 0x11 - /pet hold off
#define PET_SLUMBER 18 // 0x12 - What activates this? - define guessed
#define PET_SLUMBER_ON 19 // 0x13 - What activates this? - define guessed
#define PET_SLUMBER_OFF 20 // 0x14 - What activates this? - define guessed
#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window
#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on
#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off
#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window
#define PET_FOCUS_ON 25 // 0x19 - /pet focus on
#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off
#define PET_BACKOFF 28 // 0x1c - /pet back off
#define PET_GETLOST 29 // 0x1d - /pet get lost
#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client
class Mob;
struct NPCType;
+25 -23
View File
@@ -26,6 +26,8 @@
#include <string.h>
extern uint64_t frame_time;
int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target)
{
int base = EQEmu::skills::GetBaseDamage(skill);
@@ -302,7 +304,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
if (GetTarget() != this) {
CheckIncreaseSkill(EQEmu::skills::SkillBash, GetTarget(), 10);
DoAnim(animTailRake);
DoAnim(animTailRake, 0, false);
int32 ht = 0;
if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 &&
@@ -324,7 +326,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10);
int AtkRounds = 1;
int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy, GetTarget());
DoAnim(anim2HSlashing);
DoAnim(anim2HSlashing, 0, false);
max_dmg = mod_frenzy_damage(max_dmg);
@@ -359,7 +361,7 @@ void Client::OPCombatAbility(const CombatAbility_Struct *ca_atk)
break;
if (GetTarget() != this) {
CheckIncreaseSkill(EQEmu::skills::SkillKick, GetTarget(), 10);
DoAnim(animKick);
DoAnim(animKick, 0, false);
int32 ht = 0;
if (GetWeaponDamage(GetTarget(), GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0)
@@ -452,40 +454,40 @@ int Mob::MonkSpecialAttack(Mob *other, uint8 unchecked_type)
skill_type = EQEmu::skills::SkillFlyingKick;
max_dmg = GetBaseSkillDamage(skill_type);
min_dmg = 0; // revamped FK formula is missing the min mod?
DoAnim(animFlyingKick);
DoAnim(animFlyingKick, 0, false);
reuse = FlyingKickReuseTime;
break;
case EQEmu::skills::SkillDragonPunch:
skill_type = EQEmu::skills::SkillDragonPunch;
max_dmg = GetBaseSkillDamage(skill_type);
itemslot = EQEmu::inventory::slotHands;
DoAnim(animTailRake);
DoAnim(animTailRake, 0, false);
reuse = TailRakeReuseTime;
break;
case EQEmu::skills::SkillEagleStrike:
skill_type = EQEmu::skills::SkillEagleStrike;
max_dmg = GetBaseSkillDamage(skill_type);
itemslot = EQEmu::inventory::slotHands;
DoAnim(animEagleStrike);
DoAnim(animEagleStrike, 0, false);
reuse = EagleStrikeReuseTime;
break;
case EQEmu::skills::SkillTigerClaw:
skill_type = EQEmu::skills::SkillTigerClaw;
max_dmg = GetBaseSkillDamage(skill_type);
itemslot = EQEmu::inventory::slotHands;
DoAnim(animTigerClaw);
DoAnim(animTigerClaw, 0, false);
reuse = TigerClawReuseTime;
break;
case EQEmu::skills::SkillRoundKick:
skill_type = EQEmu::skills::SkillRoundKick;
max_dmg = GetBaseSkillDamage(skill_type);
DoAnim(animRoundKick);
DoAnim(animRoundKick, 0, false);
reuse = RoundKickReuseTime;
break;
case EQEmu::skills::SkillKick:
skill_type = EQEmu::skills::SkillKick;
max_dmg = GetBaseSkillDamage(skill_type);
DoAnim(animKick);
DoAnim(animKick, 0, false);
reuse = KickReuseTime;
break;
default:
@@ -604,7 +606,7 @@ void Mob::RogueBackstab(Mob* other, bool min_damage, int ReuseTime)
hate = base_damage;
DoSpecialAttackDamage(other, EQEmu::skills::SkillBackstab, base_damage, 0, hate, ReuseTime);
DoAnim(anim1HPiercing);
DoAnim(anim1HPiercing, 0, false);
}
// assassinate [No longer used for regular assassinate 6-29-14]
@@ -617,7 +619,7 @@ void Mob::RogueAssassinate(Mob* other)
}else{
other->Damage(this, -5, SPELL_UNKNOWN, EQEmu::skills::SkillBackstab);
}
DoAnim(anim1HPiercing); //piercing animation
DoAnim(anim1HPiercing, 0, false); //piercing animation
}
void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
@@ -920,11 +922,11 @@ bool Mob::TryProjectileAttack(Mob *other, const EQEmu::ItemData *item, EQEmu::sk
if (slot < 0)
return false;
float speed_mod = speed * 0.45f;
float speed_mod = speed;
float distance = other->CalculateDistance(GetX(), GetY(), GetZ());
float hit =
60.0f + (distance / speed_mod); // Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4)
1200.0f + (10 * distance / speed_mod); // Calcuation: 60 = Animation Lag, 1.8 = Speed modifier for speed of (4)
ProjectileAtk[slot].increment = 1;
ProjectileAtk[slot].hit_increment = static_cast<uint16>(hit); // This projected hit time if target does NOT MOVE
@@ -977,7 +979,7 @@ void Mob::ProjectileAttack()
ProjectileAtk[i].tlast_y = target->GetY();
float distance = target->CalculateDistance(
ProjectileAtk[i].origin_x, ProjectileAtk[i].origin_y, ProjectileAtk[i].origin_z);
float hit = 60.0f + (distance / ProjectileAtk[i].speed_mod); // Calcuation: 60 =
float hit = 1200.0f + (10 * distance / ProjectileAtk[i].speed_mod); // Calcuation: 60 =
// Animation Lag, 1.8 =
// Speed modifier for speed
// of (4)
@@ -1030,7 +1032,7 @@ void Mob::ProjectileAttack()
ProjectileAtk[i].skill = 0;
ProjectileAtk[i].speed_mod = 0.0f;
} else {
ProjectileAtk[i].increment++;
ProjectileAtk[i].increment += frame_time;
}
}
@@ -1596,7 +1598,7 @@ void NPC::DoClassAttacks(Mob *target) {
case WARRIOR: case WARRIORGM:{
if(level >= RuleI(Combat, NPCBashKickLevel)){
if(zone->random.Roll(75)) { //tested on live, warrior mobs both kick and bash, kick about 75% of the time, casting doesn't seem to make a difference.
DoAnim(animKick);
DoAnim(animKick, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@@ -1607,7 +1609,7 @@ void NPC::DoClassAttacks(Mob *target) {
did_attack = true;
}
else {
DoAnim(animTailRake);
DoAnim(animTailRake, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@@ -1623,7 +1625,7 @@ void NPC::DoClassAttacks(Mob *target) {
case BERSERKER: case BERSERKERGM:{
int AtkRounds = 1;
int32 max_dmg = GetBaseSkillDamage(EQEmu::skills::SkillFrenzy);
DoAnim(anim2HSlashing);
DoAnim(anim2HSlashing, 0, false);
if (GetClass() == BERSERKER) {
int chance = GetLevel() * 2 + GetSkill(EQEmu::skills::SkillFrenzy);
@@ -1646,7 +1648,7 @@ void NPC::DoClassAttacks(Mob *target) {
case BEASTLORD: case BEASTLORDGM: {
//kick
if(level >= RuleI(Combat, NPCBashKickLevel)){
DoAnim(animKick);
DoAnim(animKick, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillKick);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@@ -1662,7 +1664,7 @@ void NPC::DoClassAttacks(Mob *target) {
case SHADOWKNIGHT: case SHADOWKNIGHTGM:
case PALADIN: case PALADINGM:{
if(level >= RuleI(Combat, NPCBashKickLevel)){
DoAnim(animTailRake);
DoAnim(animTailRake, 0, false);
int32 dmg = GetBaseSkillDamage(EQEmu::skills::SkillBash);
if (GetWeaponDamage(target, (const EQEmu::ItemData*)nullptr) <= 0)
@@ -1761,7 +1763,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill_to_use == EQEmu::skills::SkillBash) {
if (ca_target!=this) {
DoAnim(animTailRake);
DoAnim(animTailRake, 0, false);
if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotSecondary)) <= 0 && GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotShoulders)) <= 0)
dmg = DMG_INVULNERABLE;
@@ -1780,7 +1782,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill_to_use == EQEmu::skills::SkillFrenzy) {
CheckIncreaseSkill(EQEmu::skills::SkillFrenzy, GetTarget(), 10);
int AtkRounds = 1;
DoAnim(anim2HSlashing);
DoAnim(anim2HSlashing, 0, false);
ReuseTime = (FrenzyReuseTime - 1) / HasteMod;
@@ -1807,7 +1809,7 @@ void Client::DoClassAttacks(Mob *ca_target, uint16 skill, bool IsRiposte)
if (skill_to_use == EQEmu::skills::SkillKick){
if(ca_target!=this){
DoAnim(animKick);
DoAnim(animKick, 0, false);
if (GetWeaponDamage(ca_target, GetInv().GetItem(EQEmu::inventory::slotFeet)) <= 0)
dmg = DMG_INVULNERABLE;
+39 -18
View File
@@ -25,6 +25,7 @@
#include "../common/skills.h"
#include "../common/spdat.h"
#include "../common/data_verification.h"
#include "../common/misc_functions.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
@@ -1239,6 +1240,23 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
else
{
MakePet(spell_id, spell.teleport_zone);
// TODO: we need to sync the states for these clients ...
// Will fix buttons for now
if (IsClient()) {
auto c = CastToClient();
if (c->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) {
c->SetPetCommandState(PET_BUTTON_SIT, 0);
c->SetPetCommandState(PET_BUTTON_STOP, 0);
c->SetPetCommandState(PET_BUTTON_REGROUP, 0);
c->SetPetCommandState(PET_BUTTON_FOLLOW, 1);
c->SetPetCommandState(PET_BUTTON_GUARD, 0);
c->SetPetCommandState(PET_BUTTON_TAUNT, 1);
c->SetPetCommandState(PET_BUTTON_HOLD, 0);
c->SetPetCommandState(PET_BUTTON_GHOLD, 0);
c->SetPetCommandState(PET_BUTTON_FOCUS, 0);
c->SetPetCommandState(PET_BUTTON_SPELLHOLD, 0);
}
}
}
break;
}
@@ -6611,9 +6629,9 @@ bool Mob::TrySpellProjectile(Mob* spell_target, uint16 spell_id, float speed){
if (CheckLosFN(spell_target)) {
float speed_mod = speed * 0.45f; //Constant for adjusting speeds to match calculated impact time.
float speed_mod = speed; //Constant for adjusting speeds to match calculated impact time.
float distance = spell_target->CalculateDistance(GetX(), GetY(), GetZ());
float hit = 60.0f + (distance / speed_mod);
float hit = 1200.0f + (10 * distance / speed_mod);
ProjectileAtk[slot].increment = 1;
ProjectileAtk[slot].hit_increment = static_cast<uint16>(hit); //This projected hit time if target does NOT MOVE
@@ -6668,23 +6686,26 @@ void Mob::ResourceTap(int32 damage, uint16 spellid)
for (int i = 0; i < EFFECT_COUNT; i++) {
if (spells[spellid].effectid[i] == SE_ResourceTap) {
damage += (damage * spells[spellid].base[i]) / 100;
if (spells[spellid].max[i] && (damage > spells[spellid].max[i]))
damage = spells[spellid].max[i];
if (spells[spellid].base2[i] == 0) { // HP Tap
if (damage > 0)
HealDamage(damage);
else
Damage(this, -damage, 0, EQEmu::skills::SkillEvocation, false);
damage = (damage * spells[spellid].base[i]) / 1000;
if (damage) {
if (spells[spellid].max[i] && (damage > spells[spellid].max[i]))
damage = spells[spellid].max[i];
if (spells[spellid].base2[i] == 0) { // HP Tap
if (damage > 0)
HealDamage(damage);
else
Damage(this, -damage, 0, EQEmu::skills::SkillEvocation, false);
}
if (spells[spellid].base2[i] == 1) // Mana Tap
SetMana(GetMana() + damage);
if (spells[spellid].base2[i] == 2 && IsClient()) // Endurance Tap
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage);
}
if (spells[spellid].base2[i] == 1) // Mana Tap
SetMana(GetMana() + damage);
if (spells[spellid].base2[i] == 2 && IsClient()) // Endurance Tap
CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage);
}
}
}
+28
View File
@@ -76,6 +76,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
#include "../common/spdat.h"
#include "../common/string_util.h"
#include "../common/data_verification.h"
#include "../common/misc_functions.h"
#include "quest_parser_collection.h"
#include "string_ids.h"
@@ -2139,6 +2140,27 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
spell_target->CalcSpellPowerDistanceMod(spell_id, dist2);
}
//AE Duration spells were ignoring distance check from item clickies
if(ae_center != nullptr && ae_center != this) {
//casting a spell on somebody but ourself, make sure they are in range
float dist2 = DistanceSquared(m_Position, ae_center->GetPosition());
float range2 = range * range;
float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range;
if(dist2 > range2) {
//target is out of range.
Log(Logs::Detail, Logs::Spells, "Spell %d: Spell target is out of range (squared: %f > %f)", spell_id, dist2, range2);
Message_StringID(13, TARGET_OUT_OF_RANGE);
return(false);
}
else if (dist2 < min_range2){
//target is too close range.
Log(Logs::Detail, Logs::Spells, "Spell %d: Spell target is too close (squared: %f < %f)", spell_id, dist2, min_range2);
Message_StringID(13, TARGET_TOO_CLOSE);
return(false);
}
ae_center->CalcSpellPowerDistanceMod(spell_id, dist2);
}
//
// Switch #2 - execute the spell
@@ -3037,6 +3059,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
if (IsEffectIgnoredInStacking(effect1))
continue;
// negative AC affects are skipped. Ex. Sun's Corona and Glacier Breath should stack
// There may be more SPAs we need to add here ....
// The client does just check base rather than calculating the affect change value.
if ((effect1 == SE_ArmorClass || effect1 == SE_ACv2) && sp2.base[i] < 0)
continue;
/*
If target is a npc and caster1 and caster2 exist
If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it.
+14
View File
@@ -164,6 +164,12 @@
#define PVP_ON 552 //You are now player kill and follow the ways of Discord.
#define GENERIC_STRINGID_SAY 554 //%1 says '%T2'
#define CANNOT_WAKE 555 //%1 tells you, 'I am unable to wake %2, master.'
#define PET_HOLD_SET_ON 698 //The pet hold mode has been set to on.
#define PET_HOLD_SET_OFF 699 //The pet hold mode has been set to off.
#define PET_FOCUS_SET_ON 700 //The pet focus mode has been set to on.
#define PET_FOCUS_SET_OFF 701 //The pet focus mode has been set to off.
#define PET_SPELLHOLD_SET_ON 702 //The pet spellhold mode has been set to on.
#define PET_SPELLHOLD_SET_OFF 703 //The pet spellhold mode has been set to off.
#define GUILD_NAME_IN_USE 711 //You cannot create a guild with that name, that guild already exists on this server.
#define GM_GAINXP 1002 //[GM] You have gained %1 AXP and %2 EXP (%3).
#define MALE_SLAYUNDEAD 1007 //%1's holy blade cleanses his target!(%2)
@@ -288,6 +294,7 @@
#define CORPSEDRAG_BEGIN 4064 //You begin to drag %1.
#define CORPSEDRAG_STOPALL 4065 //You stop dragging the corpses.
#define CORPSEDRAG_STOP 4066 //You stop dragging the corpse.
#define SOS_KEEPS_HIDDEN 4086 //Your Shroud of Stealth keeps you hidden from watchful eyes.␣␣
#define TARGET_TOO_CLOSE 4602 //You are too close to your target. Get farther away.
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3'
@@ -302,6 +309,7 @@
#define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.'
#define AVOID_STUNNING_BLOW 5753 //You avoid the stunning blow.
#define FATAL_BOW_SHOT 5745 //%1 performs a FATAL BOW SHOT!!
#define SUSPECT_SEES_YOU 5746 //You suspect that this being can see you.
#define MELEE_SILENCE 5806 //You *CANNOT* use this melee ability, you are suffering from amnesia!
#define DISCIPLINE_REUSE_MSG 5807 //You can use the ability %1 again in %2 hour(s) %3 minute(s) %4 seconds.
#define DISCIPLINE_REUSE_MSG2 5808 //You can use the ability %1 again in %2 minute(s) %3 seconds.
@@ -320,6 +328,12 @@
#define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel.
#define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel.
#define IDENTIFY_SPELL 6765 //Item Lore: %1.
#define PET_NOW_HOLDING 6834 //Now holding, Master. I will not start attacks until ordered.
#define PET_ON_GHOLD 6843 //Pet greater hold has been set to on.
#define PET_OFF_GHOLD 6846 //Pet greater hold has been set to off.
#define PET_GHOLD_ON_MSG 6847 //Now greater holding master. I will only attack something new if ordered.
#define PET_ON_REGROUPING 6854 //Now regrouping, master.
#define PET_OFF_REGROUPING 6855 //No longer regrouping, master.
#define BUFF_NOT_BLOCKABLE 7608 //You cannot block this effect.
#define LDON_DONT_KNOW_TRAPPED 7552 //You do not know if this object is trapped.
#define LDON_HAVE_DISARMED 7553 //You have disarmed %1!
+1
View File
@@ -18,6 +18,7 @@
#include "../common/eq_packet_structs.h"
#include "../common/string_util.h"
#include "../common/misc_functions.h"
#include "client.h"
#include "entity.h"
+6
View File
@@ -272,6 +272,12 @@ void Object::HandleCombine(Client* user, const NewCombine_Struct* in_combine, Ob
c_type = worldo->m_type;
inst = worldo->m_inst;
worldcontainer=true;
// if we're a world container with an item, use that too
if (inst) {
const EQEmu::ItemData* item = inst->GetItem();
if (item)
some_id = item->ID;
}
}
else {
inst = user_inv.GetItem(in_combine->container_slot);
+1
View File
@@ -20,6 +20,7 @@
#include "../common/eqemu_logsys.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
#include "../common/misc_functions.h"
#include "client.h"
#include "entity.h"
+191 -201
View File
@@ -1,19 +1,19 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org)
Copyright (C) 2001-2004 EQEMu Development Team (http://eqemu.org)
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 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.
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
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/global_define.h"
#ifdef _EQDEBUG
@@ -40,7 +40,7 @@ struct wp_distance
};
void NPC::AI_SetRoambox(float iDist, float iRoamDist, uint32 iDelay, uint32 iMinDelay) {
AI_SetRoambox(iDist, GetX()+iRoamDist, GetX()-iRoamDist, GetY()+iRoamDist, GetY()-iRoamDist, iDelay, iMinDelay);
AI_SetRoambox(iDist, GetX() + iRoamDist, GetX() - iRoamDist, GetY() + iRoamDist, GetY() - iRoamDist, iDelay, iMinDelay);
}
void NPC::AI_SetRoambox(float iDist, float iMaxX, float iMinX, float iMaxY, float iMinY, uint32 iDelay, uint32 iMinDelay) {
@@ -60,26 +60,26 @@ void NPC::DisplayWaypointInfo(Client *c) {
GetGrid(),
GetSp2(),
GetCurWp(),
GetMaxWp() );
GetMaxWp());
std::vector<wplist>::iterator cur, end;
cur = Waypoints.begin();
end = Waypoints.end();
for(; cur != end; ++cur) {
c->Message(0,"Waypoint %d: (%.2f,%.2f,%.2f,%.2f) pause %d",
cur->index,
cur->x,
cur->y,
cur->z,
cur->heading,
cur->pause );
for (; cur != end; ++cur) {
c->Message(0, "Waypoint %d: (%.2f,%.2f,%.2f,%.2f) pause %d",
cur->index,
cur->x,
cur->y,
cur->z,
cur->heading,
cur->pause);
}
}
void NPC::StopWandering()
{ // stops a mob from wandering, takes him off grid and sends him back to spawn point
roamer=false;
roamer = false;
CastToNPC()->SetGrid(0);
SendPosition();
Log(Logs::Detail, Logs::Pathing, "Stop Wandering requested.");
@@ -88,17 +88,17 @@ void NPC::StopWandering()
void NPC::ResumeWandering()
{ // causes wandering to continue - overrides waypoint pause timer and PauseWandering()
if(!IsNPC())
if (!IsNPC())
return;
if (GetGrid() != 0)
{
if (GetGrid() < 0)
{ // we were paused by a quest
AI_walking_timer->Disable();
SetGrid( 0 - GetGrid());
if (cur_wp==-1)
SetGrid(0 - GetGrid());
if (cur_wp == -1)
{ // got here by a MoveTo()
cur_wp=save_wp;
cur_wp = save_wp;
UpdateWaypoint(cur_wp); // have him head to last destination from here
}
Log(Logs::Detail, Logs::Pathing, "Resume Wandering requested. Grid %d, wp %d", GetGrid(), cur_wp);
@@ -117,7 +117,7 @@ void NPC::ResumeWandering()
if (m_CurrentWayPoint.x == GetX() && m_CurrentWayPoint.y == GetY())
{ // are we we at a waypoint? if so, trigger event and start to next
char temp[100];
itoa(cur_wp,temp,10); //do this before updating to next waypoint
itoa(cur_wp, temp, 10); //do this before updating to next waypoint
CalculateNewWaypoint();
SetAppearance(eaStanding, false);
parse->EventNPC(EVENT_WAYPOINT_DEPART, this, nullptr, temp, 0);
@@ -141,13 +141,14 @@ void NPC::PauseWandering(int pausetime)
SendPosition();
if (pausetime<1)
{ // negative grid number stops him dead in his tracks until ResumeWandering()
SetGrid( 0 - GetGrid());
SetGrid(0 - GetGrid());
}
else
{ // specified waiting time, he'll resume after that
AI_walking_timer->Start(pausetime*1000); // set the timer
AI_walking_timer->Start(pausetime * 1000); // set the timer
}
} else {
}
else {
Log(Logs::General, Logs::Error, "NPC not on grid - can't pause wandering: %lu", (unsigned long)GetNPCTypeID());
}
return;
@@ -159,33 +160,33 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
{ // he is on a grid
if (GetGrid() < 0)
{ // currently stopped by a quest command
SetGrid( 0 - GetGrid()); // get him moving again
SetGrid(0 - GetGrid()); // get him moving again
Log(Logs::Detail, Logs::AI, "MoveTo during quest wandering. Canceling quest wandering and going back to grid %d when MoveTo is done.", GetGrid());
}
AI_walking_timer->Disable(); // disable timer in case he is paused at a wp
if (cur_wp>=0)
if (cur_wp >= 0)
{ // we've not already done a MoveTo()
save_wp=cur_wp; // save the current waypoint
cur_wp=-1; // flag this move as quest controlled
save_wp = cur_wp; // save the current waypoint
cur_wp = -1; // flag this move as quest controlled
}
Log(Logs::Detail, Logs::AI, "MoveTo %s, pausing regular grid wandering. Grid %d, save_wp %d",to_string(static_cast<glm::vec3>(position)).c_str(), -GetGrid(), save_wp);
Log(Logs::Detail, Logs::AI, "MoveTo %s, pausing regular grid wandering. Grid %d, save_wp %d", to_string(static_cast<glm::vec3>(position)).c_str(), -GetGrid(), save_wp);
}
else
{ // not on a grid
roamer=true;
save_wp=0;
cur_wp=-2; // flag as quest controlled w/no grid
roamer = true;
save_wp = 0;
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());
}
if (saveguardspot)
{
m_GuardPoint = position;
if(m_GuardPoint.w == 0)
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
if (m_GuardPoint.w == 0)
m_GuardPoint.w = 0.0001; //hack to make IsGuarding simpler
if(m_GuardPoint.w == -1)
m_GuardPoint.w = this->CalculateHeadingToTarget(position.x, position.y);
if (m_GuardPoint.w == -1)
m_GuardPoint.w = this->CalculateHeadingToTarget(position.x, position.y);
Log(Logs::Detail, Logs::AI, "Setting guard position to %s", to_string(static_cast<glm::vec3>(m_GuardPoint)).c_str());
}
@@ -193,13 +194,13 @@ void NPC::MoveTo(const glm::vec4& position, bool saveguardspot)
m_CurrentWayPoint = position;
cur_wp_pause = 0;
pLastFightingDelayMoving = 0;
if(AI_walking_timer->Enabled())
if (AI_walking_timer->Enabled())
AI_walking_timer->Start(100);
}
void NPC::UpdateWaypoint(int wp_index)
{
if(wp_index >= static_cast<int>(Waypoints.size())) {
if (wp_index >= static_cast<int>(Waypoints.size())) {
Log(Logs::Detail, Logs::AI, "Update to waypoint %d failed. Not found.", wp_index);
return;
}
@@ -212,11 +213,11 @@ void NPC::UpdateWaypoint(int wp_index)
Log(Logs::Detail, Logs::AI, "Next waypoint %d: (%.3f, %.3f, %.3f, %.3f)", wp_index, m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, m_CurrentWayPoint.w);
//fix up pathing Z
if(zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints) && !IsBoat())
if (zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints) && !IsBoat())
{
if(!RuleB(Watermap, CheckForWaterAtWaypoints) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_CurrentWayPoint))))
if (!RuleB(Watermap, CheckForWaterAtWaypoints) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_CurrentWayPoint))))
{
glm::vec3 dest(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z);
@@ -239,7 +240,7 @@ void NPC::CalculateNewWaypoint()
if (cur_wp == 0)
reached_beginning = true;
switch(wandertype)
switch (wandertype)
{
case 0: //circle
{
@@ -254,7 +255,7 @@ void NPC::CalculateNewWaypoint()
std::list<wplist> closest;
GetClosestWaypoint(closest, 10, glm::vec3(GetPosition()));
auto iter = closest.begin();
if(closest.size() != 0)
if (closest.size() != 0)
{
iter = closest.begin();
std::advance(iter, zone->random.Int(0, closest.size() - 1));
@@ -266,18 +267,18 @@ void NPC::CalculateNewWaypoint()
case 2: //random
{
cur_wp = zone->random.Int(0, Waypoints.size() - 1);
if(cur_wp == old_wp)
if (cur_wp == old_wp)
{
if(cur_wp == (Waypoints.size() - 1))
if (cur_wp == (Waypoints.size() - 1))
{
if(cur_wp > 0)
if (cur_wp > 0)
{
cur_wp--;
}
}
else if(cur_wp == 0)
else if (cur_wp == 0)
{
if((Waypoints.size() - 1) > 0)
if ((Waypoints.size() - 1) > 0)
{
cur_wp++;
}
@@ -288,11 +289,11 @@ void NPC::CalculateNewWaypoint()
}
case 3: //patrol
{
if(reached_end)
if (reached_end)
patrol = 1;
else if(reached_beginning)
else if (reached_beginning)
patrol = 0;
if(patrol == 1)
if (patrol == 1)
cur_wp = cur_wp - 1;
else
cur_wp = cur_wp + 1;
@@ -311,9 +312,9 @@ void NPC::CalculateNewWaypoint()
GetClosestWaypoint(closest, 5, glm::vec3(GetPosition()));
auto iter = closest.begin();
while(iter != closest.end())
while (iter != closest.end())
{
if(CheckLosFN((*iter).x, (*iter).y, (*iter).z, GetSize()))
if (CheckLosFN((*iter).x, (*iter).y, (*iter).z, GetSize()))
{
++iter;
}
@@ -323,7 +324,7 @@ void NPC::CalculateNewWaypoint()
}
}
if(closest.size() != 0)
if (closest.size() != 0)
{
iter = closest.begin();
std::advance(iter, zone->random.Int(0, closest.size() - 1));
@@ -352,9 +353,9 @@ bool wp_distance_pred(const wp_distance& left, const wp_distance& right)
void NPC::GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::vec3& location)
{
wp_list.clear();
if(Waypoints.size() <= count)
if (Waypoints.size() <= count)
{
for(int i = 0; i < Waypoints.size(); ++i)
for (int i = 0; i < Waypoints.size(); ++i)
{
wp_list.push_back(Waypoints[i]);
}
@@ -362,7 +363,7 @@ void NPC::GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::v
}
std::list<wp_distance> distances;
for(int i = 0; i < Waypoints.size(); ++i)
for (int i = 0; i < Waypoints.size(); ++i)
{
float cur_x = (Waypoints[i].x - location.x);
cur_x *= cur_x;
@@ -381,7 +382,7 @@ void NPC::GetClosestWaypoint(std::list<wplist> &wp_list, int count, const glm::v
});
auto iter = distances.begin();
for(int i = 0; i < count; ++i)
for (int i = 0; i < count; ++i)
{
wp_list.push_back(Waypoints[(*iter).index]);
++iter;
@@ -401,15 +402,15 @@ void NPC::SetWaypointPause()
switch (pausetype)
{
case 0: //Random Half
AI_walking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause-1)/2)*1000);
break;
case 1: //Full
AI_walking_timer->Start(cur_wp_pause*1000);
break;
case 2: //Random Full
AI_walking_timer->Start(zone->random.Int(0, cur_wp_pause-1)*1000);
break;
case 0: //Random Half
AI_walking_timer->Start((cur_wp_pause - zone->random.Int(0, cur_wp_pause - 1) / 2) * 1000);
break;
case 1: //Full
AI_walking_timer->Start(cur_wp_pause * 1000);
break;
case 2: //Random Full
AI_walking_timer->Start(zone->random.Int(0, cur_wp_pause - 1) * 1000);
break;
}
}
}
@@ -422,7 +423,7 @@ void NPC::SaveGuardSpot(bool iClearGuardSpot) {
else {
m_GuardPoint = m_Position;
if(m_GuardPoint.w == 0)
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());
}
@@ -433,9 +434,9 @@ void NPC::NextGuardPosition() {
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))
else if ((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z))
{
if(moved)
if (moved)
{
moved = false;
SetCurrentSpeed(0);
@@ -444,19 +445,19 @@ void NPC::NextGuardPosition() {
}
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)) );
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)));
}
float Mob::CalculateHeadingToTarget(float in_x, float in_y) {
float angle;
if (in_x-m_Position.x > 0)
angle = - 90 + atan((float)(in_y-m_Position.y) / (float)(in_x-m_Position.x)) * 180 / M_PI;
else if (in_x-m_Position.x < 0)
angle = + 90 + atan((float)(in_y-m_Position.y) / (float)(in_x-m_Position.x)) * 180 / M_PI;
if (in_x - m_Position.x > 0)
angle = -90 + atan((float)(in_y - m_Position.y) / (float)(in_x - m_Position.x)) * 180 / M_PI;
else if (in_x - m_Position.x < 0)
angle = +90 + atan((float)(in_y - m_Position.y) / (float)(in_x - m_Position.x)) * 180 / M_PI;
else // Added?
{
if (in_y-m_Position.y > 0)
if (in_y - m_Position.y > 0)
angle = 0;
else
angle = 180;
@@ -465,31 +466,29 @@ float Mob::CalculateHeadingToTarget(float in_x, float in_y) {
angle += 360;
if (angle > 360)
angle -= 360;
return (256*(360-angle)/360.0f);
return (256 * (360 - angle) / 360.0f);
}
bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ) {
if(GetID()==0)
if (GetID() == 0)
return true;
if(speed <= 0)
if (speed <= 0)
{
SetCurrentSpeed(0);
return true;
}
if ((m_Position.x-x == 0) && (m_Position.y-y == 0)) {//spawn is at target coords
if(m_Position.z-z != 0) {
if ((m_Position.x - x == 0) && (m_Position.y - y == 0)) {//spawn is at target coords
if (m_Position.z - z != 0) {
m_Position.z = z;
Log(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): Jumping pure Z.", x, y, z);
return true;
}
// Log(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f) inWater=%d: We are there.", x, y, z, inWater);
return false;
} else if ((std::abs(m_Position.x - x) < 0.1) && (std::abs(m_Position.y - y) < 0.1)) {
Log(Logs::Detail, Logs::AI, "Calc Position2 (%.3f, %.3f, %.3f): X/Y difference <0.1, Jumping to target.", x, y, z);
if(IsNPC()) {
}
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);
}
@@ -501,12 +500,12 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
bool send_update = false;
int compare_steps = 20;
if(tar_ndx < compare_steps && m_TargetLocation.x==x && m_TargetLocation.y==y) {
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()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
}
@@ -514,34 +513,30 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
m_Position.y = new_y;
m_Position.z = new_z;
Log(Logs::Detail, Logs::AI, "Calculating new position2 to (%.3f, %.3f, %.3f), old vector (%.3f, %.3f, %.3f)", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z);
uint8 NPCFlyMode = 0;
if(IsNPC()) {
if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
if (IsNPC()) {
if (CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
NPCFlyMode = 1;
}
//fix up pathing Z
if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
if (!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
{
if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
{
glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);
float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f;
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z);
if ((newz > -2000) &&
std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
{
if ((std::abs(x - m_Position.x) < 0.5) &&
(std::abs(y - m_Position.y) < 0.5)) {
(std::abs(y - m_Position.y) < 0.5)) {
if (std::abs(z - m_Position.z) <=
RuleR(Map, FixPathingZMaxDeltaMoving))
RuleR(Map, FixPathingZMaxDeltaMoving))
m_Position.z = z;
else
m_Position.z = newz + 1;
@@ -559,15 +554,16 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
if (tar_ndx>50) {
tar_ndx--;
} else {
tar_ndx=0;
}
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;
// float nh = this->heading;
m_TargetV.x = x - nx;
m_TargetV.y = y - ny;
@@ -575,43 +571,39 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
SetCurrentSpeed((int8)speed);
pRunAnimSpeed = speed;
#ifdef BOTS
if(IsClient() || IsBot())
if (IsClient() || IsBot())
#else
if(IsClient())
if (IsClient())
#endif
{
animation = speed / 2;
}
//pRunAnimSpeed = (int8)(speed*NPC_RUNANIM_RATIO);
//speed *= NPC_SPEED_MULTIPLIER;
Log(Logs::Detail, Logs::AI, "Calculating new position2 to (%.3f, %.3f, %.3f), new vector (%.3f, %.3f, %.3f) rate %.3f, RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed);
// --------------------------------------------------------------------------
// 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);
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 * 16.0f / (float)speed + 0.5f);
// mob move fix
int numsteps = (int)(mag * 13.5f / (float)speed + 0.5f);
// mob move fix
// 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;
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()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
}
@@ -620,35 +612,36 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
m_Position.z = new_z;
m_Position.w = CalculateHeadingToTarget(x, y);
tar_ndx = 20 - numsteps;
Log(Logs::Detail, Logs::AI, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", m_Position.x, m_Position.y, m_Position.z, numsteps);
}
else
{
if(IsNPC()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), x, y, z);
}
m_Position.x = x;
m_Position.y = y;
m_Position.z = z;
Log(Logs::Detail, Logs::AI, "Only a single step to get there... jumping.");
}
}
else {
tar_vector/=16.0f;
tar_vector /= 13.5f;
float dur = Timer::GetCurrentTime() - pLastChange;
if(dur < 1.0f) {
dur = 1.0f;
if (dur < 0.0f) {
dur = 0.0f;
}
tar_vector = (tar_vector * AImovement_duration) / 100.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()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
}
@@ -656,30 +649,27 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
m_Position.y = new_y;
m_Position.z = new_z;
m_Position.w = CalculateHeadingToTarget(x, y);
Log(Logs::Detail, Logs::AI, "Next position2 (%.3f, %.3f, %.3f) (%d steps)", m_Position.x, m_Position.y, m_Position.z, numsteps);
}
uint8 NPCFlyMode = 0;
if(IsNPC()) {
if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
if (IsNPC()) {
if (CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
NPCFlyMode = 1;
}
//fix up pathing Z
if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) {
if (!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) {
if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
{
glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);
float newz = zone->zonemap->FindBestZ(dest, nullptr);
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x, m_Position.y, m_Position.z);
if ((newz > -2000) &&
std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
{
if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) {
if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving))
@@ -688,13 +678,13 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
m_Position.z = newz + 1;
}
else
m_Position.z = newz+1;
}
m_Position.z = newz + 1;
}
}
}
SetMoving(true);
moved=true;
moved = true;
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
@@ -718,7 +708,7 @@ bool Mob::CalculateNewPosition2(float x, float y, float z, int speed, bool check
}
bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
if(GetID()==0)
if (GetID() == 0)
return true;
float nx = m_Position.x;
@@ -728,15 +718,15 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ
// if NPC is rooted
if (speed == 0) {
SetHeading(CalculateHeadingToTarget(x, y));
if(moved){
if (moved) {
SetCurrentSpeed(0);
moved=false;
moved = false;
}
Log(Logs::Detail, Logs::AI, "Rooted while calculating new position to (%.3f, %.3f, %.3f)", x, y, z);
return true;
}
float old_test_vector=test_vector;
float old_test_vector = test_vector;
m_TargetV.x = x - nx;
m_TargetV.y = y - ny;
m_TargetV.z = z - nz;
@@ -744,19 +734,19 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ
if (m_TargetV.x == 0 && m_TargetV.y == 0)
return false;
SetCurrentSpeed((int8)(speed)); //*NPC_RUNANIM_RATIO);
//speed *= NPC_SPEED_MULTIPLIER;
//speed *= NPC_SPEED_MULTIPLIER;
Log(Logs::Detail, Logs::AI, "Calculating new position to (%.3f, %.3f, %.3f) vector (%.3f, %.3f, %.3f) rate %.3f RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed);
// --------------------------------------------------------------------------
// 2: get unit vector
// --------------------------------------------------------------------------
test_vector=sqrtf (x*x + y*y + z*z);
tar_vector = speed / sqrtf (m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z);
test_vector = sqrtf(x*x + y*y + z*z);
tar_vector = speed / sqrtf(m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z);
m_Position.w = CalculateHeadingToTarget(x, y);
if (tar_vector >= 1.0) {
if(IsNPC()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), x, y, z);
}
@@ -769,7 +759,7 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ
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()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
}
@@ -781,25 +771,25 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ
uint8 NPCFlyMode = 0;
if(IsNPC()) {
if(CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
if (IsNPC()) {
if (CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2)
NPCFlyMode = 1;
}
//fix up pathing Z
if(!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
if (!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving))
{
if(!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
{
glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);
float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f;
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z);
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz, m_Position.x, m_Position.y, m_Position.z);
if ((newz > -2000) &&
std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check.
{
if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) {
if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving))
@@ -808,16 +798,16 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ
m_Position.z = newz + 1;
}
else
m_Position.z = newz+1;
m_Position.z = newz + 1;
}
}
}
//OP_MobUpdate
if((old_test_vector!=test_vector) || tar_ndx>20){ //send update
tar_ndx=0;
if ((old_test_vector != test_vector) || tar_ndx>20) { //send update
tar_ndx = 0;
this->SetMoving(true);
moved=true;
moved = true;
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
SendPosUpdate();
}
@@ -845,7 +835,7 @@ void NPC::AssignWaypoints(int32 grid)
// Retrieve the wander and pause types for this grid
std::string query = StringFormat("SELECT `type`, `type2` FROM `grid` WHERE `id` = %i AND `zoneid` = %i", grid,
zone->GetZoneID());
zone->GetZoneID());
auto results = database.QueryDatabase(query);
if (!results.Success()) {
return;
@@ -861,10 +851,10 @@ void NPC::AssignWaypoints(int32 grid)
SetGrid(grid); // Assign grid number
// Retrieve all waypoints for this grid
// Retrieve all waypoints for this grid
query = StringFormat("SELECT `x`,`y`,`z`,`pause`,`heading` "
"FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %i "
"ORDER BY `number`", grid, zone->GetZoneID());
"FROM grid_entries WHERE `gridid` = %i AND `zoneid` = %i "
"ORDER BY `number`", grid, zone->GetZoneID());
results = database.QueryDatabase(query);
if (!results.Success()) {
return;
@@ -881,10 +871,10 @@ void NPC::AssignWaypoints(int32 grid)
newwp.y = atof(row[1]);
newwp.z = atof(row[2]);
if(zone->HasMap() && RuleB(Map, FixPathingZWhenLoading) )
if (zone->HasMap() && RuleB(Map, FixPathingZWhenLoading))
{
auto positon = glm::vec3(newwp.x,newwp.y,newwp.z);
if(!RuleB(Watermap, CheckWaypointsInWaterWhenLoading) || !zone->HasWaterMap() ||
auto positon = glm::vec3(newwp.x, newwp.y, newwp.z);
if (!RuleB(Watermap, CheckWaypointsInWaterWhenLoading) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(positon)))
{
glm::vec3 dest(newwp.x, newwp.y, newwp.z);
@@ -911,7 +901,7 @@ void NPC::AssignWaypoints(int32 grid)
}
void Mob::SendTo(float new_x, float new_y, float new_z) {
if(IsNPC()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
}
@@ -920,23 +910,23 @@ 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 == FlyMode1)
return;
//fix up pathing Z, this shouldent be needed IF our waypoints
//are corrected instead
if(zone->HasMap() && RuleB(Map, FixPathingZOnSendTo) )
if (zone->HasMap() && RuleB(Map, FixPathingZOnSendTo))
{
if(!RuleB(Watermap, CheckForWaterOnSendTo) || !zone->HasWaterMap() ||
if (!RuleB(Watermap, CheckForWaterOnSendTo) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
{
glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);
float newz = zone->zonemap->FindBestZ(dest, nullptr);
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z);
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz, m_Position.x, m_Position.y, m_Position.z);
if( (newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaSendTo)) // Sanity check.
if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaSendTo)) // Sanity check.
m_Position.z = newz + 1;
}
}
@@ -945,7 +935,7 @@ void Mob::SendTo(float new_x, float new_y, float new_z) {
}
void Mob::SendToFixZ(float new_x, float new_y, float new_z) {
if(IsNPC()) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z + 0.1);
}
@@ -956,18 +946,18 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) {
//fix up pathing Z, this shouldent be needed IF our waypoints
//are corrected instead
if(zone->HasMap() && RuleB(Map, FixPathingZOnSendTo))
if (zone->HasMap() && RuleB(Map, FixPathingZOnSendTo))
{
if(!RuleB(Watermap, CheckForWaterOnSendTo) || !zone->HasWaterMap() ||
if (!RuleB(Watermap, CheckForWaterOnSendTo) || !zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position))))
{
glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z);
float newz = zone->zonemap->FindBestZ(dest, nullptr);
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz,m_Position.x,m_Position.y,m_Position.z);
Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz, m_Position.x, m_Position.y, m_Position.z);
if( (newz > -2000) && std::abs(newz-dest.z) < RuleR(Map, FixPathingZMaxDeltaSendTo)) // Sanity check.
if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaSendTo)) // Sanity check.
m_Position.z = newz + 1;
}
}
@@ -1011,7 +1001,7 @@ bool ZoneDatabase::GetWaypoints(uint32 grid, uint16 zoneid, uint32 num, wplist*
return false;
std::string query = StringFormat("SELECT x, y, z, pause, heading FROM grid_entries "
"WHERE gridid = %i AND number = %i AND zoneid = %i", grid, num, zoneid);
"WHERE gridid = %i AND number = %i AND zoneid = %i", grid, num, zoneid);
auto results = QueryDatabase(query);
if (!results.Success()) {
return false;
@@ -1058,7 +1048,7 @@ void ZoneDatabase::ModifyGrid(Client *client, bool remove, uint32 id, uint8 type
if (!remove)
{
std::string query = StringFormat("INSERT INTO grid(id, zoneid, type, type2) "
"VALUES (%i, %i, %i, %i)", id, zoneid, type, type2);
"VALUES (%i, %i, %i, %i)", id, zoneid, type, type2);
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
@@ -1080,8 +1070,8 @@ void ZoneDatabase::ModifyGrid(Client *client, bool remove, uint32 id, uint8 type
void ZoneDatabase::AddWP(Client *client, uint32 gridid, uint32 wpnum, const glm::vec4& position, uint32 pause, uint16 zoneid)
{
std::string query = StringFormat("INSERT INTO grid_entries (gridid, zoneid, `number`, x, y, z, pause, heading) "
"VALUES (%i, %i, %i, %f, %f, %f, %i, %f)",
gridid, zoneid, wpnum, position.x, position.y, position.z, pause, position.w);
"VALUES (%i, %i, %i, %f, %f, %f, %i, %f)",
gridid, zoneid, wpnum, position.x, position.y, position.z, pause, position.w);
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
@@ -1102,10 +1092,10 @@ void ZoneDatabase::AddWP(Client *client, uint32 gridid, uint32 wpnum, const glm:
void ZoneDatabase::DeleteWaypoint(Client *client, uint32 grid_num, uint32 wp_num, uint16 zoneid)
{
std::string query = StringFormat("DELETE FROM grid_entries WHERE "
"gridid = %i AND zoneid = %i AND `number` = %i",
grid_num, zoneid, wp_num);
"gridid = %i AND zoneid = %i AND `number` = %i",
grid_num, zoneid, wp_num);
auto results = QueryDatabase(query);
if(!results.Success()) {
if (!results.Success()) {
return;
}
}
@@ -1124,7 +1114,7 @@ uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, const glm::v
uint32 next_wp_num; // The waypoint number we should be assigning to the new waypoint
bool createdNewGrid; // Did we create a new grid in this function?
// See what grid number our spawn is assigned
// See what grid number our spawn is assigned
std::string query = StringFormat("SELECT pathgrid FROM spawn2 WHERE id = %i", spawn2id);
auto results = QueryDatabase(query);
if (!results.Success()) {
@@ -1142,11 +1132,11 @@ uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, const glm::v
{ // Our spawn doesn't have a grid assigned to it -- we need to create a new grid and assign it to the spawn
createdNewGrid = true;
grid_num = GetFreeGrid(zoneid);
if(grid_num == 0) // There are no grids for the current zone -- create Grid #1
if (grid_num == 0) // There are no grids for the current zone -- create Grid #1
grid_num = 1;
query = StringFormat("INSERT INTO grid SET id = '%i', zoneid = %i, type ='%i', type2 = '%i'",
grid_num, zoneid, type1, type2);
grid_num, zoneid, type1, type2);
QueryDatabase(query);
query = StringFormat("UPDATE spawn2 SET pathgrid = '%i' WHERE id = '%i'", grid_num, spawn2id);
@@ -1160,22 +1150,22 @@ uint32 ZoneDatabase::AddWPForSpawn(Client *client, uint32 spawn2id, const glm::v
query = StringFormat("SELECT max(`number`) FROM grid_entries WHERE zoneid = '%i' AND gridid = '%i'", zoneid, grid_num);
results = QueryDatabase(query);
if(!results.Success()) { // Query error
if (!results.Success()) { // Query error
return 0;
}
row = results.begin();
if(row[0] != 0)
if (row[0] != 0)
next_wp_num = atoi(row[0]) + 1;
else // No waypoints in this grid yet
next_wp_num = 1;
query = StringFormat("INSERT INTO grid_entries(gridid, zoneid, `number`, x, y, z, pause, heading) "
"VALUES (%i, %i, %i, %f, %f, %f, %i, %f)",
grid_num, zoneid, next_wp_num, position.x, position.y, position.z, pause, position.w);
"VALUES (%i, %i, %i, %f, %f, %f, %i, %f)",
grid_num, zoneid, next_wp_num, position.x, position.y, position.z, pause, position.w);
results = QueryDatabase(query);
return createdNewGrid? grid_num: 0;
return createdNewGrid ? grid_num : 0;
}
uint32 ZoneDatabase::GetFreeGrid(uint16 zoneid) {
@@ -1198,7 +1188,7 @@ uint32 ZoneDatabase::GetFreeGrid(uint16 zoneid) {
int ZoneDatabase::GetHighestWaypoint(uint32 zoneid, uint32 gridid) {
std::string query = StringFormat("SELECT COALESCE(MAX(number), 0) FROM grid_entries "
"WHERE zoneid = %i AND gridid = %i", zoneid, gridid);
"WHERE zoneid = %i AND gridid = %i", zoneid, gridid);
auto results = QueryDatabase(query);
if (!results.Success()) {
return 0;
@@ -1219,4 +1209,4 @@ void NPC::SaveGuardSpotCharm()
void NPC::RestoreGuardSpotCharm()
{
m_GuardPoint = m_GuardPointSaved;
}
}
+1782 -1790
View File
File diff suppressed because it is too large Load Diff
+12 -6
View File
@@ -18,27 +18,31 @@
#ifndef WORLDSERVER_H
#define WORLDSERVER_H
#include "../common/worldconn.h"
#include "../common/eq_packet_structs.h"
#include "../common/net/servertalk_client_connection.h"
class ServerPacket;
class EQApplicationPacket;
class Client;
class WorldServer : public WorldConnection {
class WorldServer {
public:
WorldServer();
virtual ~WorldServer();
~WorldServer();
virtual void Process();
void Connect();
bool SendPacket(ServerPacket* pack);
std::string GetIP() const;
uint16 GetPort() const;
bool Connected() const;
void HandleMessage(uint16 opcode, const EQ::Net::Packet &p);
void SendGuildJoin(GuildJoin_Struct* gj);
bool SendChannelMessage(Client* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, const char* message, ...);
bool SendEmoteMessage(const char* to, uint32 to_guilddbid, uint32 type, const char* message, ...);
bool SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...);
bool SendVoiceMacro(Client* From, uint32 Type, char* Target, uint32 MacroNumber, uint32 GroupOrRaidID = 0);
void SetZoneData(uint32 iZoneID, uint32 iInstanceID = 0);
uint32 SendGroupIdRequest();
bool RezzPlayer(EQApplicationPacket* rpack, uint32 rezzexp, uint32 dbid, uint16 opcode);
bool IsOOCMuted() const { return(oocmuted); }
@@ -67,6 +71,8 @@ private:
uint32 cur_groupid;
uint32 last_groupid;
std::unique_ptr<EQ::Net::ServertalkClient> m_connection;
};
#endif