mirror of
https://github.com/EQEmu/Server.git
synced 2026-09-04 02:06:50 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
+2
-23
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+10
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -648,7 +648,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender)
|
||||
}
|
||||
}
|
||||
|
||||
if (GetLeader() == nullptr)
|
||||
if (!GetLeaderName())
|
||||
{
|
||||
DisbandGroup();
|
||||
return true;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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]);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+12
-6
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user