mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-14 20:12:26 +00:00
Merge from master
This commit is contained in:
commit
5cbd741358
@ -1,5 +1,22 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 12/20/2014 ==
|
||||
Akkadius: Updated #cvs to display RoF2 Client Stream count
|
||||
|
||||
== 12/19/2014 ==
|
||||
Trevius: (RoF2) Fixed Leadership AA Purchasing and Recipe Search by correcting opcodes.
|
||||
Trevius: Fixed Armor Tinting (players and NPCs) that was broken during a previous update.
|
||||
Trevius: (RoF2) Fixed Rest Timer, Show Helm Option, Auto-Consent Options, and identified Krono in the PP.
|
||||
Trevius: Fixed Selling for Alternate Currency Merchants for RoF and RoF2.
|
||||
|
||||
== 12/18/2014 ==
|
||||
Trevius: Finished lining up the RoF2 Player Profile Struct. Zone times are now normal, and everything from the PP is accurate in game now.
|
||||
Trevius: Fixed zoning after death for RoF2.
|
||||
|
||||
== 12/17/2014 ==
|
||||
demonstar55: Use vectors for route stuff, should be more CPU cache friendly so faster
|
||||
Secrets: EQStream changes as recommended by a community member in private.
|
||||
|
||||
== 12/15/2014 ==
|
||||
Trevius: (RoF+) Implemented the 6th Augment Slot for Items.
|
||||
Trevius: Player Corpses now saved attuned settings for Items.
|
||||
|
||||
@ -548,6 +548,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
|
||||
},
|
||||
{ // local[MapBank]
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ NOT_USED,
|
||||
/*Titanium*/ Titanium::consts::MAP_BANK_SIZE,
|
||||
/*SoF*/ EmuConstants::MAP_BANK_SIZE,
|
||||
/*SoD*/ EmuConstants::MAP_BANK_SIZE,
|
||||
@ -697,6 +698,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
|
||||
},
|
||||
{ // local[MapCorpse]
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ NOT_USED,
|
||||
/*Titanium*/ Titanium::consts::MAP_CORPSE_SIZE,
|
||||
/*SoF*/ SoF::consts::MAP_CORPSE_SIZE,
|
||||
/*SoD*/ SoD::consts::MAP_CORPSE_SIZE,
|
||||
@ -726,6 +728,7 @@ uint16 EQLimits::InventoryMapSize(int16 map, uint32 version) {
|
||||
},
|
||||
{ // local[MapInspect]
|
||||
/*Unknown*/ NOT_USED,
|
||||
/*62*/ NOT_USED,
|
||||
/*Titanium*/ Titanium::consts::MAP_INSPECT_SIZE,
|
||||
/*SoF*/ SoF::consts::MAP_INSPECT_SIZE,
|
||||
/*SoD*/ SoD::consts::MAP_INSPECT_SIZE,
|
||||
@ -1003,6 +1006,7 @@ uint64 EQLimits::CursorBitmask(uint32 version) {
|
||||
bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
|
||||
static const bool local[_EmuClientCount] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ false,
|
||||
/*Titanium*/ Titanium::limits::ALLOWS_EMPTY_BAG_IN_BAG,
|
||||
/*SoF*/ SoF::limits::ALLOWS_EMPTY_BAG_IN_BAG,
|
||||
/*SoD*/ SoD::limits::ALLOWS_EMPTY_BAG_IN_BAG,
|
||||
@ -1023,6 +1027,8 @@ bool EQLimits::AllowsEmptyBagInBag(uint32 version) {
|
||||
bool EQLimits::AllowsClickCastFromBag(uint32 version) {
|
||||
static const bool local[_EmuClientCount] = {
|
||||
/*Unknown*/ false,
|
||||
/*62*/ false,
|
||||
/*Titanium*/ Titanium::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*SoF*/ SoF::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*SoD*/ SoD::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
/*Underfoot*/ Underfoot::limits::ALLOWS_CLICK_CAST_FROM_BAG,
|
||||
@ -1082,6 +1088,7 @@ uint16 EQLimits::ItemContainerSize(uint32 version) {
|
||||
bool EQLimits::CoinHasWeight(uint32 version) {
|
||||
static const bool local[_EmuClientCount] = {
|
||||
/*Unknown*/ true,
|
||||
/*62*/ true,
|
||||
/*Titanium*/ Titanium::limits::COIN_HAS_WEIGHT,
|
||||
/*SoF*/ SoF::limits::COIN_HAS_WEIGHT,
|
||||
/*SoD*/ SoD::limits::COIN_HAS_WEIGHT,
|
||||
|
||||
@ -1380,19 +1380,19 @@ struct PlayerPositionUpdateServer_Struct
|
||||
struct PlayerPositionUpdateClient_Struct
|
||||
{
|
||||
/*0000*/ uint16 spawn_id;
|
||||
/*0022*/ uint16 sequence; //increments one each packet
|
||||
/*0002*/ uint16 sequence; //increments one each packet
|
||||
/*0004*/ float y_pos; // y coord
|
||||
/*0008*/ float delta_z; // Change in z
|
||||
/*0016*/ float delta_x; // Change in x
|
||||
/*0012*/ float delta_y; // Change in y
|
||||
/*0012*/ float delta_x; // Change in x
|
||||
/*0016*/ float delta_y; // Change in y
|
||||
/*0020*/ int32 animation:10, // animation
|
||||
delta_heading:10, // change in heading
|
||||
padding0020:12; // ***Placeholder (mostly 1)
|
||||
/*0024*/ float x_pos; // x coord
|
||||
/*0028*/ float z_pos; // z coord
|
||||
/*0034*/ uint16 heading:12, // Directional heading
|
||||
/*0032*/ uint16 heading:12, // Directional heading
|
||||
padding0004:4; // ***Placeholder
|
||||
/*0032*/ uint8 unknown0006[2]; // ***Placeholder
|
||||
/*0034*/ uint8 unknown0006[2]; // ***Placeholder
|
||||
/*0036*/
|
||||
};
|
||||
|
||||
|
||||
@ -47,7 +47,13 @@
|
||||
|
||||
uint16 EQStream::MaxWindowSize=2048;
|
||||
|
||||
void EQStream::init() {
|
||||
void EQStream::init(bool resetSession) {
|
||||
// we only reset these statistics if it is a 'new' connection
|
||||
if ( resetSession )
|
||||
{
|
||||
streamactive = false;
|
||||
sessionAttempts = 0;
|
||||
}
|
||||
active_users = 0;
|
||||
Session=0;
|
||||
Key=0;
|
||||
@ -313,18 +319,22 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
|
||||
}
|
||||
#ifndef COLLECTOR
|
||||
if (GetState()==ESTABLISHED) {
|
||||
_log(NET__ERROR, _L "Received OP_SessionRequest in ESTABLISHED state (%d)" __L, GetState());
|
||||
_log(NET__ERROR, _L "Received OP_SessionRequest in ESTABLISHED state (%d) streamactive (%i) attempt (%i)" __L, GetState(),streamactive,sessionAttempts);
|
||||
|
||||
/*RemoveData();
|
||||
init();
|
||||
State=UNESTABLISHED;*/
|
||||
_SendDisconnect();
|
||||
SetState(CLOSED);
|
||||
break;
|
||||
// client seems to try a max of 30 times (initial+3 retries) then gives up, giving it a few more attempts just in case
|
||||
// streamactive means we identified the opcode for the stream, we cannot re-establish this connection
|
||||
if ( streamactive || ( sessionAttempts > MAX_SESSION_RETRIES ) )
|
||||
{
|
||||
_SendDisconnect();
|
||||
SetState(CLOSED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
//std::cout << "Got OP_SessionRequest" << std::endl;
|
||||
init();
|
||||
sessionAttempts++;
|
||||
// we set established below, so statistics will not be reset for session attempts/stream active.
|
||||
init(GetState()!=ESTABLISHED);
|
||||
OutboundQueueClear();
|
||||
SessionRequest *Request=(SessionRequest *)p->pBuffer;
|
||||
Session=ntohl(Request->Session);
|
||||
|
||||
@ -49,6 +49,10 @@ class EQProtocolPacket;
|
||||
#define RETRANSMIT_ACKED_PACKETS true
|
||||
#endif
|
||||
|
||||
#ifndef MAX_SESSION_RETRIES
|
||||
#define MAX_SESSION_RETRIES 30
|
||||
#endif
|
||||
|
||||
#pragma pack(1)
|
||||
struct SessionRequest {
|
||||
uint32 UnknownA;
|
||||
@ -104,6 +108,9 @@ class EQStream : public EQStreamInterface {
|
||||
uint32 retransmittimer;
|
||||
uint32 retransmittimeout;
|
||||
|
||||
uint16 sessionAttempts;
|
||||
bool streamactive;
|
||||
|
||||
//uint32 buffer_len;
|
||||
|
||||
uint32 Session, Key;
|
||||
@ -197,9 +204,9 @@ class EQStream : public EQStreamInterface {
|
||||
|
||||
void _SendDisconnect();
|
||||
|
||||
void init();
|
||||
void init(bool resetSession=true);
|
||||
public:
|
||||
EQStream() { init(); remote_ip = 0; remote_port = 0; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); }
|
||||
EQStream() { init(); remote_ip = 0; remote_port = 0; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); sessionAttempts = 0; streamactive=false; }
|
||||
EQStream(sockaddr_in addr) { init(); remote_ip=addr.sin_addr.s_addr; remote_port=addr.sin_port; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); }
|
||||
virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
|
||||
void SetMaxLen(uint32 length) { MaxLen=length; }
|
||||
@ -224,6 +231,9 @@ class EQStream : public EQStreamInterface {
|
||||
void SetLastPacketTime(uint32 t) {LastPacket=t;}
|
||||
void Write(int eq_fd);
|
||||
|
||||
// whether or not the stream has been assigned (we passed our stream match)
|
||||
void SetActive(bool val) { streamactive = val; }
|
||||
|
||||
//
|
||||
inline bool IsInUse() { bool flag; MInUse.lock(); flag=(active_users>0); MInUse.unlock(); return flag; }
|
||||
inline void PutInUse() { MInUse.lock(); active_users++; MInUse.unlock(); }
|
||||
|
||||
@ -110,6 +110,9 @@ void EQStreamIdentifier::Process() {
|
||||
|
||||
_log(NET__IDENTIFY, "Identified stream %s:%d with signature %s", long2ip(r->stream->GetRemoteIP()).c_str(), ntohs(r->stream->GetRemotePort()), p->name.c_str());
|
||||
|
||||
// before we assign the eqstream to an interface, let the stream recognize it is in use and the session should not be reset any further
|
||||
r->stream->SetActive(true);
|
||||
|
||||
//might want to do something less-specific here... some day..
|
||||
EQStreamInterface *s = new EQStreamProxy(r->stream, p->structs, p->opcodes);
|
||||
m_identified.push(s);
|
||||
|
||||
@ -205,7 +205,7 @@ namespace RoF
|
||||
SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct);
|
||||
|
||||
OUT(merchant_entity_id);
|
||||
eq->slot_id = ServerToRoFSlot(emu->slot_id);
|
||||
eq->slot_id = ServerToRoFMainInvSlot(emu->slot_id);
|
||||
OUT(charges);
|
||||
OUT(cost);
|
||||
|
||||
@ -2045,15 +2045,6 @@ namespace RoF
|
||||
outapp->WriteUInt32(emu->skills[r]);
|
||||
}
|
||||
|
||||
// deprecated
|
||||
// Write zeroes for the rest of the skills
|
||||
/*
|
||||
for(uint32 r = 0; r < structs::MAX_PP_SKILL - MAX_PP_SKILL; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->skills[r]);
|
||||
}
|
||||
*/
|
||||
|
||||
outapp->WriteUInt32(25); // Unknown count
|
||||
|
||||
for (uint32 r = 0; r < 25; r++)
|
||||
@ -2130,18 +2121,6 @@ namespace RoF
|
||||
|
||||
outapp->WriteUInt32(structs::BUFF_COUNT);
|
||||
|
||||
//*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise
|
||||
//*001*/ float unknown004; // Seen 1 for no buff
|
||||
//*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
//*009*/ uint32 unknown016;
|
||||
//*013*/ uint8 bard_modifier;
|
||||
//*014*/ uint32 duration;
|
||||
//*018*/ uint8 level;
|
||||
//*019*/ uint32 spellid;
|
||||
//*023*/ uint32 counters;
|
||||
//*027*/ uint8 unknown0028[53];
|
||||
//*080*/
|
||||
|
||||
for (uint32 r = 0; r < BUFF_COUNT; r++)
|
||||
{
|
||||
float instrument_mod = 0.0f;
|
||||
@ -3902,7 +3881,7 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct);
|
||||
|
||||
IN(merchant_entity_id);
|
||||
emu->slot_id = RoFToServerSlot(eq->slot_id);
|
||||
emu->slot_id = RoFToServerMainInvSlot(eq->slot_id);
|
||||
IN(charges);
|
||||
IN(cost);
|
||||
|
||||
@ -3915,7 +3894,7 @@ namespace RoF
|
||||
SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct);
|
||||
|
||||
IN(merchant_entity_id);
|
||||
emu->slot_id = RoFToServerSlot(eq->slot_id);
|
||||
emu->slot_id = RoFToServerMainInvSlot(eq->slot_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@ -4878,7 +4857,8 @@ namespace RoF
|
||||
uint16 ornaIcon = 0;
|
||||
int32 heroModel = 0;
|
||||
/*
|
||||
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
|
||||
if (inst->GetOrnamentationAug(ornamentationAugtype))
|
||||
{
|
||||
const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
//Mainhand
|
||||
ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
|
||||
@ -5081,11 +5061,6 @@ namespace RoF
|
||||
isbs.augslots[x].unknown = item->AugSlotUnk2[x];
|
||||
}
|
||||
|
||||
// Increased to 6 max aug slots
|
||||
//isbs.augslots[5].type = 0;
|
||||
//isbs.augslots[5].visible = 1;
|
||||
//isbs.augslots[5].unknown = 0;
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
isbs.ldontheme = item->LDoNTheme;
|
||||
isbs.ldonprice = item->LDoNPrice;
|
||||
|
||||
@ -205,7 +205,7 @@ namespace RoF2
|
||||
SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct);
|
||||
|
||||
OUT(merchant_entity_id);
|
||||
eq->slot_id = ServerToRoF2Slot(emu->slot_id);
|
||||
eq->slot_id = ServerToRoF2MainInvSlot(emu->slot_id);
|
||||
OUT(charges);
|
||||
OUT(cost);
|
||||
|
||||
@ -1696,6 +1696,8 @@ namespace RoF2
|
||||
eq->unknown932 = -1; // Set from PoK Example
|
||||
eq->unknown936 = -1; // Set from PoK Example
|
||||
eq->unknown944 = 1.0; // Set from PoK Example
|
||||
eq->unknown948 = 0; // New on Live as of Dec 15 2014
|
||||
eq->unknown952 = 100; // New on Live as of Dec 15 2014
|
||||
|
||||
FINISH_ENCODE();
|
||||
}
|
||||
@ -2121,18 +2123,6 @@ namespace RoF2
|
||||
|
||||
outapp->WriteUInt32(structs::BUFF_COUNT);
|
||||
|
||||
//*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise
|
||||
//*001*/ float unknown004; // Seen 1 for no buff
|
||||
//*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages
|
||||
//*009*/ uint32 unknown016;
|
||||
//*013*/ uint8 bard_modifier;
|
||||
//*014*/ uint32 duration;
|
||||
//*018*/ uint8 level;
|
||||
//*019*/ uint32 spellid;
|
||||
//*023*/ uint32 counters;
|
||||
//*027*/ uint8 unknown0028[53];
|
||||
//*080*/
|
||||
|
||||
for (uint32 r = 0; r < BUFF_COUNT; r++)
|
||||
{
|
||||
float instrument_mod = 0.0f;
|
||||
@ -2172,7 +2162,6 @@ namespace RoF2
|
||||
// 80 bytes of zeroes
|
||||
for (uint32 j = 0; j < 20; ++j)
|
||||
outapp->WriteUInt32(0);
|
||||
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(emu->platinum);
|
||||
@ -2197,8 +2186,8 @@ namespace RoF2
|
||||
|
||||
outapp->WriteUInt32(emu->aapoints_spent);
|
||||
|
||||
outapp->WriteUInt32(5); // AA Points count ??
|
||||
outapp->WriteUInt32(1234); // AA Points assigned
|
||||
outapp->WriteUInt32(5); // AA Window Tab Count
|
||||
outapp->WriteUInt32(0); // AA Points assigned ?
|
||||
outapp->WriteUInt32(0); // AA Points in General ?
|
||||
outapp->WriteUInt32(0); // AA Points in Class ?
|
||||
outapp->WriteUInt32(0); // AA Points in Archetype ?
|
||||
@ -2326,36 +2315,31 @@ namespace RoF2
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
outapp->WriteUInt8(emu->gm);
|
||||
outapp->WriteUInt32(emu->guild_id);
|
||||
outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet.
|
||||
outapp->WriteUInt32(0); // Unknown - observed 1 in a live packet.
|
||||
outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet.
|
||||
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
outapp->WriteUInt64(emu->exp);
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
outapp->WriteUInt64(emu->exp); // int32 in client
|
||||
|
||||
outapp->WriteUInt8(0); // Unknown - Seen 5 on Live
|
||||
|
||||
outapp->WriteUInt32(emu->platinum_bank);
|
||||
outapp->WriteUInt32(emu->gold_bank);
|
||||
outapp->WriteUInt32(emu->silver_bank);
|
||||
outapp->WriteUInt32(emu->copper_bank);
|
||||
|
||||
// Commenting out for RoF Test
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
outapp->WriteUInt32(42); // The meaning of life ?
|
||||
|
||||
for (uint32 r = 0; r < 42; r++)
|
||||
{
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
outapp->WriteSInt32(-1); // Unknown
|
||||
outapp->WriteSInt32(-1); // Unknown
|
||||
|
||||
outapp->WriteUInt32(emu->career_tribute_points);
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(emu->tribute_points);
|
||||
@ -2386,18 +2370,12 @@ namespace RoF2
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
/*
|
||||
|
||||
// Begin RoF2 Test
|
||||
for (uint32 r = 0; r < 1000; r++)
|
||||
|
||||
for (uint32 r = 0; r < 125; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
// End RoF2 Test
|
||||
|
||||
// Block of 121 unknown bytes
|
||||
for (uint32 r = 0; r < 121; r++)
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(emu->currentRadCrystals);
|
||||
@ -2411,7 +2389,9 @@ namespace RoF2
|
||||
// Unknown String ?
|
||||
outapp->WriteUInt32(64); // Unknown
|
||||
for (uint32 r = 0; r < 64; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
@ -2439,22 +2419,30 @@ namespace RoF2
|
||||
// Unknown String ?
|
||||
outapp->WriteUInt32(64); // Unknown
|
||||
for (uint32 r = 0; r < 64; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
// Unknown String ?
|
||||
outapp->WriteUInt32(64); // Unknown
|
||||
for (uint32 r = 0; r < 64; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
// Block of 320 unknown bytes
|
||||
for (uint32 r = 0; r < 320; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
// Block of 343 unknown bytes
|
||||
for (uint32 r = 0; r < 343; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
@ -2479,10 +2467,14 @@ namespace RoF2
|
||||
outapp->WriteUInt32(64); // Group of 64 int32s follow Group/Raid Leadership abilities ?
|
||||
|
||||
for (uint32 r = 0; r < MAX_LEADERSHIP_AA_ARRAY; r++)
|
||||
{
|
||||
outapp->WriteUInt32(emu->leader_abilities.ranks[r]);
|
||||
}
|
||||
|
||||
for (uint32 r = 0; r < 64 - MAX_LEADERSHIP_AA_ARRAY; r++)
|
||||
{
|
||||
outapp->WriteUInt32(0); // Unused/unsupported Leadership abilities
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(emu->air_remaining); // ?
|
||||
|
||||
@ -2535,33 +2527,31 @@ namespace RoF2
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
*/
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Krono - itemid 88888 Hard coded in client?
|
||||
|
||||
outapp->WriteUInt8(emu->groupAutoconsent);
|
||||
outapp->WriteUInt8(emu->raidAutoconsent);
|
||||
outapp->WriteUInt8(emu->guildAutoconsent);
|
||||
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
|
||||
outapp->WriteUInt32(emu->level); // Level3 ?
|
||||
outapp->WriteUInt32(emu->level); // Level3 ?
|
||||
|
||||
outapp->WriteUInt8(emu->showhelm);
|
||||
|
||||
outapp->WriteUInt32(emu->RestTimer);
|
||||
|
||||
outapp->WriteUInt32(1024); // Unknown Count
|
||||
|
||||
// Block of 1024 unknown bytes
|
||||
outapp->WriteUInt8(31); // Unknown
|
||||
|
||||
for (uint32 r = 0; r < 1023; r++)
|
||||
for (uint32 r = 0; r < 1024; r++)
|
||||
{
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
}
|
||||
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
outapp->WriteUInt32(0); // Unknown
|
||||
|
||||
// Think we need 1 byte of padding at the end
|
||||
|
||||
outapp->WriteUInt8(0); // Unknown
|
||||
|
||||
_log(NET__STRUCTS, "Player Profile Packet is %i bytes", outapp->GetWritePosition());
|
||||
@ -3887,6 +3877,7 @@ namespace RoF2
|
||||
}
|
||||
|
||||
// DECODE methods
|
||||
|
||||
DECODE(OP_AdventureMerchantSell)
|
||||
{
|
||||
DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct);
|
||||
@ -3906,7 +3897,7 @@ namespace RoF2
|
||||
SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct);
|
||||
|
||||
IN(merchant_entity_id);
|
||||
emu->slot_id = RoF2ToServerSlot(eq->slot_id);
|
||||
emu->slot_id = RoF2ToServerMainInvSlot(eq->slot_id);
|
||||
IN(charges);
|
||||
IN(cost);
|
||||
|
||||
@ -3919,7 +3910,7 @@ namespace RoF2
|
||||
SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct);
|
||||
|
||||
IN(merchant_entity_id);
|
||||
emu->slot_id = RoF2ToServerSlot(eq->slot_id);
|
||||
emu->slot_id = RoF2ToServerMainInvSlot(eq->slot_id);
|
||||
|
||||
FINISH_DIRECT_DECODE();
|
||||
}
|
||||
@ -4860,8 +4851,8 @@ namespace RoF2
|
||||
hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges);
|
||||
hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0;
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 7300 + Inventory::CalcMaterialFromSlot(slot_id_in); //0;
|
||||
hdr.unknown052 = 7300 + Inventory::CalcMaterialFromSlot(slot_id_in); //0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0;
|
||||
ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader));
|
||||
|
||||
@ -5085,11 +5076,6 @@ namespace RoF2
|
||||
isbs.augslots[x].unknown = item->AugSlotUnk2[x];
|
||||
}
|
||||
|
||||
// Increased to 6 max aug slots
|
||||
//isbs.augslots[5].type = 0;
|
||||
//isbs.augslots[5].visible = 1;
|
||||
//isbs.augslots[5].unknown = 0;
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
isbs.ldontheme = item->LDoNTheme;
|
||||
isbs.ldonprice = item->LDoNPrice;
|
||||
@ -5325,13 +5311,8 @@ namespace RoF2
|
||||
iqbs.SpellDmg = item->SpellDmg;
|
||||
iqbs.clairvoyance = item->Clairvoyance;
|
||||
iqbs.unknown28 = 0;
|
||||
|
||||
|
||||
// Begin RoF2 Test
|
||||
iqbs.unknown_TEST1 = 0;
|
||||
// End RoF2 Test
|
||||
|
||||
iqbs.unknown30 = 0;
|
||||
iqbs.unknown37a = 0;
|
||||
iqbs.unknown39 = 1;
|
||||
|
||||
iqbs.subitem_count = 0;
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
// incoming packets that require a DECODE translation:
|
||||
// Begin RoF2 Decodes
|
||||
|
||||
|
||||
// End RoF2 Encodes/Decodes
|
||||
|
||||
// These require Encodes/Decodes for RoF, so they do for RoF2 as well
|
||||
|
||||
@ -520,72 +520,73 @@ struct ServerZoneEntry_Struct //Adjusted from SEQ Everquest.h Struct
|
||||
|
||||
//New Zone Struct - Size: 948
|
||||
struct NewZone_Struct {
|
||||
/*0000*/ char char_name[64]; // Character Name
|
||||
/*0064*/ char zone_short_name[32]; // Zone Short Name
|
||||
/*0096*/ char unknown0096[96];
|
||||
/*0192*/ char zone_long_name[278]; // Zone Long Name
|
||||
/*0470*/ uint8 ztype; // Zone type (usually FF)
|
||||
/*0471*/ uint8 fog_red[4]; // Zone fog (red)
|
||||
/*0475*/ uint8 fog_green[4]; // Zone fog (green)
|
||||
/*0479*/ uint8 fog_blue[4]; // Zone fog (blue)
|
||||
/*0483*/ uint8 unknown323;
|
||||
/*0484*/ float fog_minclip[4];
|
||||
/*0500*/ float fog_maxclip[4];
|
||||
/*0516*/ float gravity;
|
||||
/*0520*/ uint8 time_type;
|
||||
/*0521*/ uint8 rain_chance[4];
|
||||
/*0525*/ uint8 rain_duration[4];
|
||||
/*0529*/ uint8 snow_chance[4];
|
||||
/*0533*/ uint8 snow_duration[4];
|
||||
/*0537*/ uint8 unknown537[33];
|
||||
/*0570*/ uint8 sky; // Sky Type
|
||||
/*0571*/ uint8 unknown571[13]; // ***Placeholder
|
||||
/*0584*/ float zone_exp_multiplier; // Experience Multiplier
|
||||
/*0588*/ float safe_y; // Zone Safe Y
|
||||
/*0592*/ float safe_x; // Zone Safe X
|
||||
/*0596*/ float safe_z; // Zone Safe Z
|
||||
/*0600*/ float min_z; // Guessed - NEW - Seen 0
|
||||
/*0604*/ float max_z; // Guessed
|
||||
/*0608*/ float underworld; // Underworld, min z (Not Sure?)
|
||||
/*0612*/ float minclip; // Minimum View Distance
|
||||
/*0616*/ float maxclip; // Maximum View DIstance
|
||||
/*0620*/ uint8 unknown620[84]; // ***Placeholder
|
||||
/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version.
|
||||
/*0800*/ int32 unknown800; //seen -1
|
||||
/*0804*/ char unknown804[40]; //
|
||||
/*0844*/ int32 unknown844; //seen 600
|
||||
/*0848*/ int32 unknown848;
|
||||
/*0852*/ uint16 zone_id;
|
||||
/*0854*/ uint16 zone_instance;
|
||||
/*0856*/ char unknown856[20];
|
||||
/*0876*/ uint32 SuspendBuffs;
|
||||
/*0880*/ uint32 unknown880; // Seen 50
|
||||
/*0884*/ uint32 unknown884; // Seen 10
|
||||
/*0888*/ uint8 unknown888; // Seen 1
|
||||
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
|
||||
/*0890*/ uint8 unknown890; // Seen 1
|
||||
/*0891*/ uint8 unknown891; // Seen 0
|
||||
/*0892*/ uint8 unknown892; // Seen 0
|
||||
/*0893*/ uint8 unknown893; // Seen 0 - 00
|
||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||
/*0895*/ uint8 unknown895; // Seen 0 - 00
|
||||
/*0896*/ uint32 unknown896; // Seen 180
|
||||
/*0900*/ uint32 unknown900; // Seen 180
|
||||
/*0904*/ uint32 unknown904; // Seen 180
|
||||
/*0908*/ uint32 unknown908; // Seen 2
|
||||
/*0912*/ uint32 unknown912; // Seen 2
|
||||
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
|
||||
/*0920*/ uint32 unknown920; // Seen 0
|
||||
/*0924*/ uint32 unknown924; // Seen 0
|
||||
/*0928*/ uint32 unknown928; // Seen 0
|
||||
/*0932*/ int32 unknown932; // Seen -1
|
||||
/*0936*/ int32 unknown936; // Seen -1
|
||||
/*0940*/ uint32 unknown940; // Seen 0
|
||||
/*0944*/ float unknown944; // Seen 1.0
|
||||
/*0948*/
|
||||
/*0000*/ char char_name[64]; // Character Name
|
||||
/*0064*/ char zone_short_name[32]; // Zone Short Name
|
||||
/*0096*/ char unknown0096[96];
|
||||
/*0192*/ char zone_long_name[278]; // Zone Long Name
|
||||
/*0470*/ uint8 ztype; // Zone type (usually FF)
|
||||
/*0471*/ uint8 fog_red[4]; // Zone fog (red)
|
||||
/*0475*/ uint8 fog_green[4]; // Zone fog (green)
|
||||
/*0479*/ uint8 fog_blue[4]; // Zone fog (blue)
|
||||
/*0483*/ uint8 unknown323;
|
||||
/*0484*/ float fog_minclip[4];
|
||||
/*0500*/ float fog_maxclip[4];
|
||||
/*0516*/ float gravity;
|
||||
/*0520*/ uint8 time_type;
|
||||
/*0521*/ uint8 rain_chance[4];
|
||||
/*0525*/ uint8 rain_duration[4];
|
||||
/*0529*/ uint8 snow_chance[4];
|
||||
/*0533*/ uint8 snow_duration[4];
|
||||
/*0537*/ uint8 unknown537[33];
|
||||
/*0570*/ uint8 sky; // Sky Type
|
||||
/*0571*/ uint8 unknown571[13]; // ***Placeholder
|
||||
/*0584*/ float zone_exp_multiplier; // Experience Multiplier
|
||||
/*0588*/ float safe_y; // Zone Safe Y
|
||||
/*0592*/ float safe_x; // Zone Safe X
|
||||
/*0596*/ float safe_z; // Zone Safe Z
|
||||
/*0600*/ float min_z; // Guessed - NEW - Seen 0
|
||||
/*0604*/ float max_z; // Guessed
|
||||
/*0608*/ float underworld; // Underworld, min z (Not Sure?)
|
||||
/*0612*/ float minclip; // Minimum View Distance
|
||||
/*0616*/ float maxclip; // Maximum View DIstance
|
||||
/*0620*/ uint8 unknown620[84]; // ***Placeholder
|
||||
/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version.
|
||||
/*0800*/ int32 unknown800; //seen -1
|
||||
/*0804*/ char unknown804[40]; //
|
||||
/*0844*/ int32 unknown844; //seen 600
|
||||
/*0848*/ int32 unknown848;
|
||||
/*0852*/ uint16 zone_id;
|
||||
/*0854*/ uint16 zone_instance;
|
||||
/*0856*/ char unknown856[20];
|
||||
/*0876*/ uint32 SuspendBuffs;
|
||||
/*0880*/ uint32 unknown880; // Seen 50
|
||||
/*0884*/ uint32 unknown884; // Seen 10
|
||||
/*0888*/ uint8 unknown888; // Seen 1
|
||||
/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj)
|
||||
/*0890*/ uint8 unknown890; // Seen 1
|
||||
/*0891*/ uint8 unknown891; // Seen 0
|
||||
/*0892*/ uint8 unknown892; // Seen 0
|
||||
/*0893*/ uint8 unknown893; // Seen 0 - 00
|
||||
/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off
|
||||
/*0895*/ uint8 unknown895; // Seen 0 - 00
|
||||
/*0896*/ uint32 unknown896; // Seen 180
|
||||
/*0900*/ uint32 unknown900; // Seen 180
|
||||
/*0904*/ uint32 unknown904; // Seen 180
|
||||
/*0908*/ uint32 unknown908; // Seen 2
|
||||
/*0912*/ uint32 unknown912; // Seen 2
|
||||
/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16
|
||||
/*0920*/ uint32 unknown920; // Seen 0
|
||||
/*0924*/ uint32 unknown924; // Seen 0
|
||||
/*0928*/ uint32 unknown928; // Seen 0
|
||||
/*0932*/ int32 unknown932; // Seen -1
|
||||
/*0936*/ int32 unknown936; // Seen -1
|
||||
/*0940*/ uint32 unknown940; // Seen 0
|
||||
/*0944*/ float unknown944; // Seen 1.0
|
||||
/*0948*/ uint32 unknown948; // Seen 0 - New on Live as of Dec 15 2014
|
||||
/*0952*/ uint32 unknown952; // Seen 100 - New on Live as of Dec 15 2014
|
||||
/*0956*/
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Memorize Spell Struct
|
||||
** Length: 16 Bytes
|
||||
@ -1598,23 +1599,24 @@ struct RespawnWindow_Struct {
|
||||
*/
|
||||
struct PlayerPositionUpdateServer_Struct
|
||||
{
|
||||
uint16 spawn_id;
|
||||
uint16 spawnId2;
|
||||
signed padding0004:12;
|
||||
signed y_pos:19; // y coord
|
||||
unsigned padding:1;
|
||||
signed delta_z:13; // change in z
|
||||
signed delta_x:13; // change in x
|
||||
signed padding0008:6;
|
||||
signed x_pos:19; // x coord
|
||||
unsigned heading:12; // heading
|
||||
signed padding0016:1;
|
||||
signed delta_heading:10; // change in heading
|
||||
signed z_pos:19; // z coord
|
||||
signed padding0020:3;
|
||||
signed animation:10; // animation
|
||||
signed delta_y:13; // change in y
|
||||
signed padding0024:9;
|
||||
/*0000*/ uint16 spawn_id;
|
||||
/*0002*/ uint16 spawnId2;
|
||||
/*0004*/ signed padding0004 : 12;
|
||||
signed y_pos : 19; // y coord
|
||||
unsigned padding : 1;
|
||||
/*0008*/ signed delta_z : 13; // change in z
|
||||
signed delta_x : 13; // change in x
|
||||
signed padding0008 : 6;
|
||||
/*0012*/ signed x_pos : 19; // x coord
|
||||
unsigned heading : 12; // heading
|
||||
signed padding0016 : 1;
|
||||
/*0016*/ signed delta_heading : 10; // change in heading
|
||||
signed z_pos : 19; // z coord
|
||||
signed padding0020 : 3;
|
||||
/*0020*/ signed animation : 10; // animation
|
||||
signed delta_y : 13; // change in y
|
||||
signed padding0024 : 9;
|
||||
/*0024*/
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1625,21 +1627,22 @@ struct PlayerPositionUpdateServer_Struct
|
||||
*/
|
||||
struct PlayerPositionUpdateClient_Struct
|
||||
{
|
||||
uint16 sequence; // increments one each packet - Verified
|
||||
uint16 spawn_id; // Player's spawn id
|
||||
uint8 unknown0004[6]; // ***Placeholder
|
||||
float delta_x; // Change in x
|
||||
unsigned heading:12; // Directional heading
|
||||
unsigned padding0040:20; // ***Placeholder
|
||||
float x_pos; // x coord (2nd loc value)
|
||||
float delta_z; // Change in z
|
||||
float z_pos; // z coord (3rd loc value)
|
||||
float y_pos; // y coord (1st loc value)
|
||||
unsigned animation:10; // ***Placeholder
|
||||
unsigned padding0024:22; // animation
|
||||
float delta_y; // Change in y
|
||||
signed delta_heading:10; // change in heading
|
||||
unsigned padding0041:22; // ***Placeholder
|
||||
/*0000*/ uint16 sequence; // increments one each packet - Verified
|
||||
/*0002*/ uint16 spawn_id; // Player's spawn id
|
||||
/*0004*/ uint8 unknown0004[6]; // ***Placeholder
|
||||
/*0010*/ float delta_x; // Change in x
|
||||
/*0014*/ unsigned heading : 12; // Directional heading
|
||||
unsigned padding0040 : 20; // ***Placeholder
|
||||
/*0018*/ float x_pos; // x coord (2nd loc value)
|
||||
/*0022*/ float delta_z; // Change in z
|
||||
/*0026*/ float z_pos; // z coord (3rd loc value)
|
||||
/*0030*/ float y_pos; // y coord (1st loc value)
|
||||
/*0034*/ unsigned animation : 10; // ***Placeholder
|
||||
unsigned padding0024 : 22; // animation
|
||||
/*0038*/ float delta_y; // Change in y
|
||||
/*0042*/ signed delta_heading : 10; // change in heading
|
||||
unsigned padding0041 : 22; // ***Placeholder
|
||||
/*0046*/
|
||||
};
|
||||
|
||||
/*
|
||||
@ -2177,8 +2180,8 @@ struct AltCurrencyUpdate_Struct {
|
||||
//When an item is selected while the alt currency merchant window is open
|
||||
struct AltCurrencySelectItem_Struct {
|
||||
/*000*/ uint32 merchant_entity_id;
|
||||
/*004*/ MainInvItemSlotStruct slot_id;
|
||||
/*004*/ //uint32 slot_id;
|
||||
ItemSlotStruct slot_id;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/ uint32 unknown012;
|
||||
/*016*/ uint32 unknown016;
|
||||
@ -2235,10 +2238,10 @@ struct AltCurrencyReclaim_Struct {
|
||||
|
||||
struct AltCurrencySellItem_Struct {
|
||||
/*000*/ uint32 merchant_entity_id;
|
||||
/*004*/ MainInvItemSlotStruct slot_id;
|
||||
/*004*/ //uint32 slot_id;
|
||||
ItemSlotStruct slot_id;
|
||||
/*008*/ uint32 charges;
|
||||
/*012*/ uint32 cost;
|
||||
/*016*/ uint32 charges;
|
||||
/*020*/ uint32 cost;
|
||||
};
|
||||
|
||||
struct Adventure_Purchase_Struct {
|
||||
@ -2258,14 +2261,14 @@ struct Adventure_Sell_Struct {
|
||||
};
|
||||
|
||||
struct AdventurePoints_Update_Struct {
|
||||
/*000*/ uint32 ldon_available_points; // Total available points
|
||||
/*004*/ uint8 unkown_apu004[20];
|
||||
/*024*/ uint32 ldon_guk_points; // Earned Deepest Guk points
|
||||
/*028*/ uint32 ldon_mirugal_points; // Earned Mirugal' Mebagerie points
|
||||
/*032*/ uint32 ldon_mistmoore_points; // Earned Mismoore Catacombs Points
|
||||
/*036*/ uint32 ldon_rujarkian_points; // Earned Rujarkian Hills points
|
||||
/*040*/ uint32 ldon_takish_points; // Earned Takish points
|
||||
/*044*/ uint8 unknown_apu042[216];
|
||||
/*000*/ uint32 ldon_available_points; // Total available points
|
||||
/*004*/ uint8 unkown_apu004[20];
|
||||
/*024*/ uint32 ldon_guk_points; // Earned Deepest Guk points
|
||||
/*028*/ uint32 ldon_mirugal_points; // Earned Mirugal' Mebagerie points
|
||||
/*032*/ uint32 ldon_mistmoore_points; // Earned Mismoore Catacombs Points
|
||||
/*036*/ uint32 ldon_rujarkian_points; // Earned Rujarkian Hills points
|
||||
/*040*/ uint32 ldon_takish_points; // Earned Takish points
|
||||
/*044*/ uint8 unknown_apu042[216];
|
||||
};
|
||||
|
||||
|
||||
@ -4687,11 +4690,7 @@ struct ItemQuaternaryBodyStruct
|
||||
uint32 unknown37;
|
||||
uint32 unknown_RoF27;
|
||||
uint32 unknown_RoF28;
|
||||
|
||||
// Begin RoF2 Test
|
||||
uint8 unknown_TEST1;
|
||||
// End RoF2 Test
|
||||
|
||||
uint8 unknown37a; // (guessed position) New to RoF2
|
||||
uint8 unknown38; // 0
|
||||
uint8 unknown39; // 1
|
||||
uint32 subitem_count;
|
||||
|
||||
@ -2174,8 +2174,7 @@ struct AltCurrencyUpdate_Struct {
|
||||
//When an item is selected while the alt currency merchant window is open
|
||||
struct AltCurrencySelectItem_Struct {
|
||||
/*000*/ uint32 merchant_entity_id;
|
||||
/*004*/ //uint32 slot_id;
|
||||
ItemSlotStruct slot_id;
|
||||
/*004*/ MainInvItemSlotStruct slot_id;
|
||||
/*008*/ uint32 unknown008;
|
||||
/*012*/ uint32 unknown012;
|
||||
/*016*/ uint32 unknown016;
|
||||
@ -2232,8 +2231,7 @@ struct AltCurrencyReclaim_Struct {
|
||||
|
||||
struct AltCurrencySellItem_Struct {
|
||||
/*000*/ uint32 merchant_entity_id;
|
||||
/*004*/ //uint32 slot_id;
|
||||
ItemSlotStruct slot_id;
|
||||
/*004*/ MainInvItemSlotStruct slot_id;
|
||||
/*008*/ uint32 charges;
|
||||
/*012*/ uint32 cost;
|
||||
};
|
||||
|
||||
@ -4365,8 +4365,8 @@ struct AltCurrencySelectItem_Struct {
|
||||
struct AltCurrencySellItem_Struct {
|
||||
/*000*/ uint32 merchant_entity_id;
|
||||
/*004*/ uint32 slot_id;
|
||||
/*006*/ uint32 charges;
|
||||
/*010*/ uint32 cost;
|
||||
/*008*/ uint32 charges;
|
||||
/*012*/ uint32 cost;
|
||||
};
|
||||
|
||||
struct AltCurrencyPopulateEntry_Struct
|
||||
|
||||
@ -1234,6 +1234,9 @@ ItemInst* SharedDatabase::CreateBaseItem(const Item_Struct* item, int16 charges)
|
||||
// set it to 1 charge so that it is usable on creation
|
||||
if (charges == 0 && item->MaxCharges == -1)
|
||||
charges = 1;
|
||||
// Stackable items need a minimum charge of 1 to remain moveable.
|
||||
if(charges <= 0 && item->Stackable)
|
||||
charges = 1;
|
||||
|
||||
inst = new ItemInst(item, charges);
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ OP_ClientUpdate=0x7dfc
|
||||
OP_ClientReady=0x345d
|
||||
OP_SetServerFilter=0x444d
|
||||
|
||||
# Guild Opcodes - Disabled until crashes are resolved in RoF
|
||||
# Guild Opcodes
|
||||
OP_GetGuildMOTD=0x36e0
|
||||
OP_GetGuildMOTDReply=0x4f1f
|
||||
OP_GuildMemberUpdate=0x69b9
|
||||
@ -121,7 +121,6 @@ OP_GuildInvite=0x7099
|
||||
OP_GuildRemove=0x1444
|
||||
OP_GuildPeace=0x67e3
|
||||
OP_SetGuildMOTD=0x0b0b
|
||||
OP_GuildList=0x6279
|
||||
OP_GuildWar=0x1ffb
|
||||
OP_GuildLeader=0x7e09
|
||||
OP_GuildDelete=0x3708
|
||||
@ -212,7 +211,7 @@ OP_ChannelMessage=0x2b2d
|
||||
OP_Assist=0x4478
|
||||
OP_AssistGroup=0x27f8
|
||||
OP_MoveCoin=0x0bcf
|
||||
OP_ZonePlayerToBind=0x0ecb
|
||||
OP_ZonePlayerToBind=0x08d8
|
||||
OP_KeyRing=0x6857
|
||||
OP_WhoAllRequest=0x674b
|
||||
OP_WhoAllResponse=0x578c
|
||||
@ -257,9 +256,9 @@ OP_MoveDoor=0x08e8
|
||||
OP_RemoveAllDoors=0x700c
|
||||
OP_EnvDamage=0x51fd
|
||||
OP_BoardBoat=0x4211
|
||||
OP_Forage=0x5306
|
||||
OP_LeaveBoat=0x7617
|
||||
OP_ControlBoat=0x0ae7
|
||||
OP_Forage=0x5306
|
||||
OP_SafeFallSuccess=0x2219
|
||||
OP_RezzComplete=0x760d
|
||||
OP_RezzRequest=0x3c21
|
||||
@ -287,16 +286,16 @@ OP_ReadBook=0x72df
|
||||
OP_Dye=0x23b9
|
||||
OP_InterruptCast=0x048c
|
||||
OP_AAAction=0x424e
|
||||
OP_LeadershipExpToggle=0x6c55
|
||||
OP_LeadershipExpToggle=0x74bd
|
||||
OP_LeadershipExpUpdate=0x2797
|
||||
OP_PurchaseLeadershipAA=0x0026
|
||||
OP_UpdateLeadershipAA=0x026
|
||||
OP_MarkNPC=0x5a58
|
||||
OP_MarkRaidNPC=0x74bd #unimplemented
|
||||
OP_PurchaseLeadershipAA=0x6c55
|
||||
OP_UpdateLeadershipAA=0x0026
|
||||
OP_MarkNPC=0x1fb5
|
||||
OP_MarkRaidNPC=0x5a58 #unimplemented
|
||||
OP_ClearNPCMarks=0x2003
|
||||
OP_ClearRaidNPCMarks=0x20d3 #unimplemented
|
||||
OP_DelegateAbility=0x76b8
|
||||
OP_SetGroupTarget=0x2814
|
||||
OP_DelegateAbility=0x4c9d
|
||||
OP_SetGroupTarget=0x026
|
||||
OP_Charm=0x5d92
|
||||
OP_Stun=0x36a4
|
||||
OP_SendFindableNPCs=0x4613
|
||||
@ -318,7 +317,7 @@ OP_PVPLeaderBoardReply=0x071f
|
||||
OP_PVPLeaderBoardDetailsRequest=0x3707
|
||||
OP_PVPLeaderBoardDetailsReply=0x25b7
|
||||
OP_RestState=0x000f
|
||||
OP_RespawnWindow=0x28bc
|
||||
OP_RespawnWindow=0x0ecb
|
||||
OP_LDoNButton=0x5327
|
||||
OP_SetStartCity=0x6326
|
||||
OP_VoiceMacroIn=0x17fd
|
||||
@ -367,7 +366,7 @@ OP_DzExpeditionInfo=0x4f7e
|
||||
OP_DzExpeditionList=0x9119
|
||||
OP_DzMemberStatus=0xb2e3
|
||||
OP_DzLeaderStatus=0x32f0
|
||||
OP_DzExpeditionEndsWarning=0x7e94
|
||||
OP_DzExpeditionEndsWarning=0x383c
|
||||
OP_DzMemberList=0x3de9
|
||||
OP_DzCompass=0x3e0e
|
||||
OP_DzChooseZone=0x0b7d
|
||||
@ -445,11 +444,11 @@ OP_ShopDelItem=0x724f
|
||||
OP_ClickObject=0x4aa1
|
||||
OP_ClickObjectAction=0x0c1e
|
||||
OP_ClearObject=0x7a11
|
||||
OP_RecipeDetails=0x40d7
|
||||
OP_RecipeDetails=0x6e02
|
||||
OP_RecipesFavorite=0x71b1
|
||||
OP_RecipesSearch=0x1db6
|
||||
OP_RecipeReply=0x6e02
|
||||
OP_RecipeAutoCombine=0x6261
|
||||
OP_RecipesSearch=0x6290
|
||||
OP_RecipeReply=0x1db6
|
||||
OP_RecipeAutoCombine=0x40d7
|
||||
OP_TradeSkillCombine=0x579a
|
||||
|
||||
# Tribute Packets:
|
||||
@ -501,7 +500,7 @@ OP_GroupDisbandOther=0x74da
|
||||
OP_GroupLeaderChange=0x21b4
|
||||
OP_GroupRoles=0x70e2
|
||||
OP_GroupMakeLeader=0x4229
|
||||
OP_DoGroupLeadershipAbility=0x1fb5
|
||||
OP_DoGroupLeadershipAbility=0x6eae
|
||||
OP_GroupLeadershipAAUpdate=0x02cf
|
||||
OP_GroupMentor=0x3342
|
||||
OP_InspectBuffs=0x486c
|
||||
|
||||
@ -1301,6 +1301,8 @@ void ClientList::SendClientVersionSummary(const char *Name)
|
||||
uint32 ClientSoDCount = 0;
|
||||
uint32 ClientUnderfootCount = 0;
|
||||
uint32 ClientRoFCount = 0;
|
||||
uint32 ClientRoF2Count = 0;
|
||||
|
||||
|
||||
LinkedListIterator<ClientListEntry*> Iterator(clientlist);
|
||||
|
||||
@ -1343,6 +1345,11 @@ void ClientList::SendClientVersionSummary(const char *Name)
|
||||
++ClientRoFCount;
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
++ClientRoF2Count;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1352,7 +1359,7 @@ void ClientList::SendClientVersionSummary(const char *Name)
|
||||
|
||||
}
|
||||
|
||||
zoneserver_list.SendEmoteMessage(Name, 0, 0, 13, "There are %i Titanium, %i SoF, %i SoD, %i UF, %i RoF clients currently connected.",
|
||||
ClientTitaniumCount, ClientSoFCount, ClientSoDCount, ClientUnderfootCount, ClientRoFCount);
|
||||
zoneserver_list.SendEmoteMessage(Name, 0, 0, 13, "There are %i Titanium, %i SoF, %i SoD, %i UF, %i RoF, %i RoF2 clients currently connected.",
|
||||
ClientTitaniumCount, ClientSoFCount, ClientSoDCount, ClientUnderfootCount, ClientRoFCount, ClientRoF2Count);
|
||||
}
|
||||
|
||||
|
||||
@ -213,11 +213,21 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, CharacterSelect_Struct*
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 color = 0;
|
||||
if (pp.item_tint[matslot].rgb.use_tint)
|
||||
{
|
||||
color = pp.item_tint[matslot].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = inst->GetColor();
|
||||
}
|
||||
|
||||
// Armor Materials/Models
|
||||
cs->equip[char_num][matslot].material = item->Material;
|
||||
cs->equip[char_num][matslot].elitematerial = item->EliteMaterial;
|
||||
cs->equip[char_num][matslot].heroforgemodel = inst->GetOrnamentHeroModel(matslot);
|
||||
cs->equip[char_num][matslot].color.color = inst->GetColor();
|
||||
cs->equip[char_num][matslot].color.color = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2107,6 +2107,18 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillUseTypes attack
|
||||
#endif //BOTS
|
||||
}
|
||||
|
||||
if(give_exp && give_exp->IsTempPet() && give_exp->IsPetOwnerClient()) {
|
||||
|
||||
if (give_exp->IsNPC() && give_exp->CastToNPC()->GetSwarmOwner()){
|
||||
Mob* temp_owner = nullptr;
|
||||
temp_owner = entity_list.GetMobID(give_exp->CastToNPC()->GetSwarmOwner());
|
||||
|
||||
if (temp_owner)
|
||||
give_exp = temp_owner;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int PlayerCount = 0; // QueryServ Player Counting
|
||||
|
||||
Client *give_exp_client = nullptr;
|
||||
@ -3937,6 +3949,11 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DivineAura()) {
|
||||
mlog(COMBAT__PROCS, "Procs canceled, Divine Aura is in effect.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!weapon_g) {
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, on);
|
||||
return;
|
||||
|
||||
@ -538,9 +538,9 @@ void Client::AddItemBonuses(const ItemInst *inst, StatBonuses* newbon, bool isAu
|
||||
}
|
||||
|
||||
void Client::CalcEdibleBonuses(StatBonuses* newbon) {
|
||||
#if EQDEBUG >= 11
|
||||
std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<<std::endl;
|
||||
#endif
|
||||
//#if EQDEBUG >= 11
|
||||
// std::cout<<"Client::CalcEdibleBonuses(StatBonuses* newbon)"<<std::endl;
|
||||
//#endif
|
||||
// Search player slots for skill=14(food) and skill=15(drink)
|
||||
uint32 i;
|
||||
|
||||
|
||||
@ -11276,7 +11276,7 @@ void Bot::ProcessBotCommands(Client *c, const Seperator *sep) {
|
||||
if(!results.Success())
|
||||
return;
|
||||
|
||||
int slotmaterial = Inventory::CalcMaterialFromSlot(setslot);
|
||||
uint8 slotmaterial = Inventory::CalcMaterialFromSlot(setslot);
|
||||
c->GetTarget()->CastToBot()->SendWearChange(slotmaterial);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -2685,8 +2685,11 @@ void Client::SetMaterial(int16 in_slot, uint32 item_id) {
|
||||
const Item_Struct* item = database.GetItem(item_id);
|
||||
if (item && (item->ItemClass==ItemClassCommon))
|
||||
{
|
||||
uint32 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
m_pp.item_material[matslot] = GetEquipmentMaterial(matslot);
|
||||
uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
if (matslot != _MaterialInvalid)
|
||||
{
|
||||
m_pp.item_material[matslot] = GetEquipmentMaterial(matslot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3016,31 +3019,14 @@ void Client::SetTint(int16 in_slot, uint32 color) {
|
||||
|
||||
// Still need to reconcile bracer01 versus bracer02
|
||||
void Client::SetTint(int16 in_slot, Color_Struct& color) {
|
||||
if (in_slot==MainHead)
|
||||
m_pp.item_tint[MaterialHead].color=color.color;
|
||||
else if (in_slot==MainArms)
|
||||
m_pp.item_tint[MaterialArms].color=color.color;
|
||||
else if (in_slot==MainWrist1)
|
||||
m_pp.item_tint[MaterialWrist].color=color.color;
|
||||
/*
|
||||
// non-live behavior
|
||||
else if (in_slot==SLOT_BRACER02)
|
||||
m_pp.item_tint[MaterialWrist].color=color.color;
|
||||
*/
|
||||
else if (in_slot==MainHands)
|
||||
m_pp.item_tint[MaterialHands].color=color.color;
|
||||
else if (in_slot==MainPrimary)
|
||||
m_pp.item_tint[MaterialPrimary].color=color.color;
|
||||
else if (in_slot==MainSecondary)
|
||||
m_pp.item_tint[MaterialSecondary].color=color.color;
|
||||
else if (in_slot==MainChest)
|
||||
m_pp.item_tint[MaterialChest].color=color.color;
|
||||
else if (in_slot==MainLegs)
|
||||
m_pp.item_tint[MaterialLegs].color=color.color;
|
||||
else if (in_slot==MainFeet)
|
||||
m_pp.item_tint[MaterialFeet].color=color.color;
|
||||
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
|
||||
uint8 matslot = Inventory::CalcMaterialFromSlot(in_slot);
|
||||
if (matslot != _MaterialInvalid)
|
||||
{
|
||||
m_pp.item_tint[matslot].color = color.color;
|
||||
database.SaveCharacterMaterialColor(this->CharacterID(), in_slot, color.color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Client::SetHideMe(bool flag)
|
||||
|
||||
@ -1428,8 +1428,12 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
|
||||
/* Set item material tint */
|
||||
for (int i = EmuConstants::MATERIAL_BEGIN; i <= EmuConstants::MATERIAL_END; i++)
|
||||
if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255)
|
||||
m_pp.item_tint[i].rgb.use_tint = 0xFF;
|
||||
{
|
||||
if (m_pp.item_tint[i].rgb.use_tint == 1 || m_pp.item_tint[i].rgb.use_tint == 255)
|
||||
{
|
||||
m_pp.item_tint[i].rgb.use_tint = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (level){ level = m_pp.level; }
|
||||
|
||||
@ -5745,7 +5749,7 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::list<int> pathlist = zone->pathing->FindRoute(Start, End);
|
||||
std::deque<int> pathlist = zone->pathing->FindRoute(Start, End);
|
||||
|
||||
if (pathlist.size() == 0)
|
||||
{
|
||||
@ -5784,7 +5788,7 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
||||
p.z = GetZ();
|
||||
points.push_back(p);
|
||||
|
||||
for (std::list<int>::iterator Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
|
||||
for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
|
||||
{
|
||||
if ((*Iterator) == -1) // Teleporter
|
||||
{
|
||||
|
||||
@ -2664,7 +2664,7 @@ void EntityList::FindPathsToAllNPCs()
|
||||
while (it != npc_list.end()) {
|
||||
Map::Vertex Node0 = zone->pathing->GetPathNodeCoordinates(0, false);
|
||||
Map::Vertex Dest(it->second->GetX(), it->second->GetY(), it->second->GetZ());
|
||||
std::list<int> Route = zone->pathing->FindRoute(Node0, Dest);
|
||||
std::deque<int> Route = zone->pathing->FindRoute(Node0, Dest);
|
||||
if (Route.size() == 0)
|
||||
printf("Unable to find a route to %s\n", it->second->GetName());
|
||||
else
|
||||
|
||||
@ -158,7 +158,7 @@ void Mob::CalculateNewFearpoint()
|
||||
|
||||
Map::Vertex CurrentPosition(GetX(), GetY(), GetZ());
|
||||
|
||||
std::list<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
|
||||
std::deque<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc);
|
||||
|
||||
if(Route.size() > 0)
|
||||
{
|
||||
|
||||
179
zone/mob.cpp
179
zone/mob.cpp
@ -542,6 +542,8 @@ float Mob::_GetMovementSpeed(int mod) const
|
||||
// http://everquest.allakhazam.com/db/item.html?item=1721;page=1;howmany=50#m10822246245352
|
||||
if (IsRooted())
|
||||
return 0.0f;
|
||||
else if (IsPseudoRooted())
|
||||
return 0.00001f;
|
||||
|
||||
float speed_mod = runspeed;
|
||||
|
||||
@ -2795,10 +2797,17 @@ uint32 Mob::GetEquipmentColor(uint8 material_slot) const
|
||||
{
|
||||
const Item_Struct *item;
|
||||
|
||||
item = database.GetItem(GetEquipment(material_slot));
|
||||
if(item != 0)
|
||||
if (armor_tint[material_slot])
|
||||
{
|
||||
return item->Color;
|
||||
return armor_tint[material_slot];
|
||||
}
|
||||
else
|
||||
{
|
||||
item = database.GetItem(GetEquipment(material_slot));
|
||||
if (item != 0)
|
||||
{
|
||||
return item->Color;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -5323,98 +5332,98 @@ int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot)
|
||||
}
|
||||
|
||||
if (slot < 16){
|
||||
if (id == "classes") {stat = spells[spell_id].classes[slot]; }
|
||||
else if (id == "dieties") {stat = spells[spell_id].deities[slot];}
|
||||
if (id == "classes") {return spells[spell_id].classes[slot]; }
|
||||
else if (id == "dieties") {return spells[spell_id].deities[slot];}
|
||||
}
|
||||
|
||||
if (slot < 12){
|
||||
if (id == "base") {stat = spells[spell_id].base[slot];}
|
||||
else if (id == "base2") {stat = spells[spell_id].base2[slot];}
|
||||
else if (id == "max") {stat = spells[spell_id].max[slot];}
|
||||
else if (id == "formula") {spells[spell_id].formula[slot];}
|
||||
else if (id == "effectid") {spells[spell_id].effectid[slot];}
|
||||
if (id == "base") {return spells[spell_id].base[slot];}
|
||||
else if (id == "base2") {return spells[spell_id].base2[slot];}
|
||||
else if (id == "max") {return spells[spell_id].max[slot];}
|
||||
else if (id == "formula") {return spells[spell_id].formula[slot];}
|
||||
else if (id == "effectid") {return spells[spell_id].effectid[slot];}
|
||||
}
|
||||
|
||||
if (slot < 4){
|
||||
if (id == "components") { spells[spell_id].components[slot];}
|
||||
else if (id == "component_counts") {spells[spell_id].component_counts[slot];}
|
||||
else if (id == "NoexpendReagent") {spells[spell_id].NoexpendReagent[slot];}
|
||||
if (id == "components") { return spells[spell_id].components[slot];}
|
||||
else if (id == "component_counts") { return spells[spell_id].component_counts[slot];}
|
||||
else if (id == "NoexpendReagent") {return spells[spell_id].NoexpendReagent[slot];}
|
||||
}
|
||||
|
||||
if (id == "range") {stat = static_cast<int32>(spells[spell_id].range); }
|
||||
else if (id == "aoerange") {stat = static_cast<int32>(spells[spell_id].aoerange);}
|
||||
else if (id == "pushback") {stat = static_cast<int32>(spells[spell_id].pushback);}
|
||||
else if (id == "pushup") {stat = static_cast<int32>(spells[spell_id].pushup);}
|
||||
else if (id == "cast_time") {stat = spells[spell_id].cast_time;}
|
||||
else if (id == "recovery_time") {stat = spells[spell_id].recovery_time;}
|
||||
else if (id == "recast_time") {stat = spells[spell_id].recast_time;}
|
||||
else if (id == "buffdurationformula") {stat = spells[spell_id].buffdurationformula;}
|
||||
else if (id == "buffduration") {stat = spells[spell_id].buffduration;}
|
||||
else if (id == "AEDuration") {stat = spells[spell_id].AEDuration;}
|
||||
else if (id == "mana") {stat = spells[spell_id].mana;}
|
||||
if (id == "range") {return static_cast<int32>(spells[spell_id].range); }
|
||||
else if (id == "aoerange") {return static_cast<int32>(spells[spell_id].aoerange);}
|
||||
else if (id == "pushback") {return static_cast<int32>(spells[spell_id].pushback);}
|
||||
else if (id == "pushup") {return static_cast<int32>(spells[spell_id].pushup);}
|
||||
else if (id == "cast_time") {return spells[spell_id].cast_time;}
|
||||
else if (id == "recovery_time") {return spells[spell_id].recovery_time;}
|
||||
else if (id == "recast_time") {return spells[spell_id].recast_time;}
|
||||
else if (id == "buffdurationformula") {return spells[spell_id].buffdurationformula;}
|
||||
else if (id == "buffduration") {return spells[spell_id].buffduration;}
|
||||
else if (id == "AEDuration") {return spells[spell_id].AEDuration;}
|
||||
else if (id == "mana") {return spells[spell_id].mana;}
|
||||
//else if (id == "LightType") {stat = spells[spell_id].LightType;} - Not implemented
|
||||
else if (id == "goodEffect") {stat = spells[spell_id].goodEffect;}
|
||||
else if (id == "Activated") {stat = spells[spell_id].Activated;}
|
||||
else if (id == "resisttype") {stat = spells[spell_id].resisttype;}
|
||||
else if (id == "targettype") {stat = spells[spell_id].targettype;}
|
||||
else if (id == "basedeiff") {stat = spells[spell_id].basediff;}
|
||||
else if (id == "skill") {stat = spells[spell_id].skill;}
|
||||
else if (id == "zonetype") {stat = spells[spell_id].zonetype;}
|
||||
else if (id == "EnvironmentType") {stat = spells[spell_id].EnvironmentType;}
|
||||
else if (id == "TimeOfDay") {stat = spells[spell_id].TimeOfDay;}
|
||||
else if (id == "CastingAnim") {stat = spells[spell_id].CastingAnim;}
|
||||
else if (id == "SpellAffectIndex") {stat = spells[spell_id].SpellAffectIndex; }
|
||||
else if (id == "disallow_sit") {stat = spells[spell_id].disallow_sit; }
|
||||
else if (id == "goodEffect") {return spells[spell_id].goodEffect;}
|
||||
else if (id == "Activated") {return spells[spell_id].Activated;}
|
||||
else if (id == "resisttype") {return spells[spell_id].resisttype;}
|
||||
else if (id == "targettype") {return spells[spell_id].targettype;}
|
||||
else if (id == "basedeiff") {return spells[spell_id].basediff;}
|
||||
else if (id == "skill") {return spells[spell_id].skill;}
|
||||
else if (id == "zonetype") {return spells[spell_id].zonetype;}
|
||||
else if (id == "EnvironmentType") {return spells[spell_id].EnvironmentType;}
|
||||
else if (id == "TimeOfDay") {return spells[spell_id].TimeOfDay;}
|
||||
else if (id == "CastingAnim") {return spells[spell_id].CastingAnim;}
|
||||
else if (id == "SpellAffectIndex") {return spells[spell_id].SpellAffectIndex; }
|
||||
else if (id == "disallow_sit") {return spells[spell_id].disallow_sit; }
|
||||
//else if (id == "spellanim") {stat = spells[spell_id].spellanim; } - Not implemented
|
||||
else if (id == "uninterruptable") {stat = spells[spell_id].uninterruptable; }
|
||||
else if (id == "ResistDiff") {stat = spells[spell_id].ResistDiff; }
|
||||
else if (id == "dot_stacking_exemp") {stat = spells[spell_id].dot_stacking_exempt; }
|
||||
else if (id == "RecourseLink") {stat = spells[spell_id].RecourseLink; }
|
||||
else if (id == "no_partial_resist") {stat = spells[spell_id].no_partial_resist; }
|
||||
else if (id == "short_buff_box") {stat = spells[spell_id].short_buff_box; }
|
||||
else if (id == "descnum") {stat = spells[spell_id].descnum; }
|
||||
else if (id == "effectdescnum") {stat = spells[spell_id].effectdescnum; }
|
||||
else if (id == "npc_no_los") {stat = spells[spell_id].npc_no_los; }
|
||||
else if (id == "reflectable") {stat = spells[spell_id].reflectable; }
|
||||
else if (id == "bonushate") {stat = spells[spell_id].bonushate; }
|
||||
else if (id == "EndurCost") {stat = spells[spell_id].EndurCost; }
|
||||
else if (id == "EndurTimerIndex") {stat = spells[spell_id].EndurTimerIndex; }
|
||||
else if (id == "IsDisciplineBuf") {stat = spells[spell_id].IsDisciplineBuff; }
|
||||
else if (id == "HateAdded") {stat = spells[spell_id].HateAdded; }
|
||||
else if (id == "EndurUpkeep") {stat = spells[spell_id].EndurUpkeep; }
|
||||
else if (id == "numhitstype") {stat = spells[spell_id].numhitstype; }
|
||||
else if (id == "numhits") {stat = spells[spell_id].numhits; }
|
||||
else if (id == "pvpresistbase") {stat = spells[spell_id].pvpresistbase; }
|
||||
else if (id == "pvpresistcalc") {stat = spells[spell_id].pvpresistcalc; }
|
||||
else if (id == "pvpresistcap") {stat = spells[spell_id].pvpresistcap; }
|
||||
else if (id == "spell_category") {stat = spells[spell_id].spell_category; }
|
||||
else if (id == "can_mgb") {stat = spells[spell_id].can_mgb; }
|
||||
else if (id == "dispel_flag") {stat = spells[spell_id].dispel_flag; }
|
||||
else if (id == "MinResist") {stat = spells[spell_id].MinResist; }
|
||||
else if (id == "MaxResist") {stat = spells[spell_id].MaxResist; }
|
||||
else if (id == "viral_targets") {stat = spells[spell_id].viral_targets; }
|
||||
else if (id == "viral_timer") {stat = spells[spell_id].viral_timer; }
|
||||
else if (id == "NimbusEffect") {stat = spells[spell_id].NimbusEffect; }
|
||||
else if (id == "directional_start") {stat = static_cast<int32>(spells[spell_id].directional_start); }
|
||||
else if (id == "directional_end") {stat = static_cast<int32>(spells[spell_id].directional_end); }
|
||||
else if (id == "not_extendable") {stat = spells[spell_id].not_extendable; }
|
||||
else if (id == "suspendable") {stat = spells[spell_id].suspendable; }
|
||||
else if (id == "viral_range") {stat = spells[spell_id].viral_range; }
|
||||
else if (id == "spellgroup") {stat = spells[spell_id].spellgroup; }
|
||||
else if (id == "rank") {stat = spells[spell_id].rank; }
|
||||
else if (id == "powerful_flag") {stat = spells[spell_id].powerful_flag; }
|
||||
else if (id == "CastRestriction") {stat = spells[spell_id].CastRestriction; }
|
||||
else if (id == "AllowRest") {stat = spells[spell_id].AllowRest; }
|
||||
else if (id == "InCombat") {stat = spells[spell_id].InCombat; }
|
||||
else if (id == "OutofCombat") {stat = spells[spell_id].OutofCombat; }
|
||||
else if (id == "aemaxtargets") {stat = spells[spell_id].aemaxtargets; }
|
||||
else if (id == "maxtargets") {stat = spells[spell_id].maxtargets; }
|
||||
else if (id == "persistdeath") {stat = spells[spell_id].persistdeath; }
|
||||
else if (id == "min_dist") {stat = static_cast<int32>(spells[spell_id].min_dist); }
|
||||
else if (id == "min_dist_mod") {stat = static_cast<int32>(spells[spell_id].min_dist_mod); }
|
||||
else if (id == "max_dist") {stat = static_cast<int32>(spells[spell_id].max_dist); }
|
||||
else if (id == "min_range") {stat = static_cast<int32>(spells[spell_id].min_range); }
|
||||
else if (id == "DamageShieldType") {stat = spells[spell_id].DamageShieldType; }
|
||||
else if (id == "uninterruptable") {return spells[spell_id].uninterruptable; }
|
||||
else if (id == "ResistDiff") {return spells[spell_id].ResistDiff; }
|
||||
else if (id == "dot_stacking_exemp") {return spells[spell_id].dot_stacking_exempt; }
|
||||
else if (id == "RecourseLink") {return spells[spell_id].RecourseLink; }
|
||||
else if (id == "no_partial_resist") {return spells[spell_id].no_partial_resist; }
|
||||
else if (id == "short_buff_box") {return spells[spell_id].short_buff_box; }
|
||||
else if (id == "descnum") {return spells[spell_id].descnum; }
|
||||
else if (id == "effectdescnum") {return spells[spell_id].effectdescnum; }
|
||||
else if (id == "npc_no_los") {return spells[spell_id].npc_no_los; }
|
||||
else if (id == "reflectable") {return spells[spell_id].reflectable; }
|
||||
else if (id == "bonushate") {return spells[spell_id].bonushate; }
|
||||
else if (id == "EndurCost") {return spells[spell_id].EndurCost; }
|
||||
else if (id == "EndurTimerIndex") {return spells[spell_id].EndurTimerIndex; }
|
||||
else if (id == "IsDisciplineBuf") {return spells[spell_id].IsDisciplineBuff; }
|
||||
else if (id == "HateAdded") {return spells[spell_id].HateAdded; }
|
||||
else if (id == "EndurUpkeep") {return spells[spell_id].EndurUpkeep; }
|
||||
else if (id == "numhitstype") {return spells[spell_id].numhitstype; }
|
||||
else if (id == "numhits") {return spells[spell_id].numhits; }
|
||||
else if (id == "pvpresistbase") {return spells[spell_id].pvpresistbase; }
|
||||
else if (id == "pvpresistcalc") {return spells[spell_id].pvpresistcalc; }
|
||||
else if (id == "pvpresistcap") {return spells[spell_id].pvpresistcap; }
|
||||
else if (id == "spell_category") {return spells[spell_id].spell_category; }
|
||||
else if (id == "can_mgb") {return spells[spell_id].can_mgb; }
|
||||
else if (id == "dispel_flag") {return spells[spell_id].dispel_flag; }
|
||||
else if (id == "MinResist") {return spells[spell_id].MinResist; }
|
||||
else if (id == "MaxResist") {return spells[spell_id].MaxResist; }
|
||||
else if (id == "viral_targets") {return spells[spell_id].viral_targets; }
|
||||
else if (id == "viral_timer") {return spells[spell_id].viral_timer; }
|
||||
else if (id == "NimbusEffect") {return spells[spell_id].NimbusEffect; }
|
||||
else if (id == "directional_start") {return static_cast<int32>(spells[spell_id].directional_start); }
|
||||
else if (id == "directional_end") {return static_cast<int32>(spells[spell_id].directional_end); }
|
||||
else if (id == "not_extendable") {return spells[spell_id].not_extendable; }
|
||||
else if (id == "suspendable") {return spells[spell_id].suspendable; }
|
||||
else if (id == "viral_range") {return spells[spell_id].viral_range; }
|
||||
else if (id == "spellgroup") {return spells[spell_id].spellgroup; }
|
||||
else if (id == "rank") {return spells[spell_id].rank; }
|
||||
else if (id == "powerful_flag") {return spells[spell_id].powerful_flag; }
|
||||
else if (id == "CastRestriction") {return spells[spell_id].CastRestriction; }
|
||||
else if (id == "AllowRest") {return spells[spell_id].AllowRest; }
|
||||
else if (id == "InCombat") {return spells[spell_id].InCombat; }
|
||||
else if (id == "OutofCombat") {return spells[spell_id].OutofCombat; }
|
||||
else if (id == "aemaxtargets") {return spells[spell_id].aemaxtargets; }
|
||||
else if (id == "maxtargets") {return spells[spell_id].maxtargets; }
|
||||
else if (id == "persistdeath") {return spells[spell_id].persistdeath; }
|
||||
else if (id == "min_dist") {return static_cast<int32>(spells[spell_id].min_dist); }
|
||||
else if (id == "min_dist_mod") {return static_cast<int32>(spells[spell_id].min_dist_mod); }
|
||||
else if (id == "max_dist") {return static_cast<int32>(spells[spell_id].max_dist); }
|
||||
else if (id == "min_range") {return static_cast<int32>(spells[spell_id].min_range); }
|
||||
else if (id == "DamageShieldType") {return spells[spell_id].DamageShieldType; }
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
@ -1225,7 +1225,7 @@ protected:
|
||||
Map::Vertex PathingLastPosition;
|
||||
int PathingLoopCount;
|
||||
int PathingLastNodeVisited;
|
||||
std::list<int> Route;
|
||||
std::deque<int> Route;
|
||||
LOSType PathingLOSState;
|
||||
Timer *PathingLOSCheckTimer;
|
||||
Timer *PathingRouteUpdateTimerShort;
|
||||
|
||||
@ -2751,7 +2751,7 @@ DBnpcspells_Struct* ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID) {
|
||||
npc_spells_cache[iDBSpellsID]->attack_proc = tmpattack_proc;
|
||||
npc_spells_cache[iDBSpellsID]->proc_chance = tmpproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->range_proc = tmprange_proc;
|
||||
npc_spells_cache[iDBSpellsID]->rproc_chance = tmpdproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->rproc_chance = tmprproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->defensive_proc = tmpdefensive_proc;
|
||||
npc_spells_cache[iDBSpellsID]->dproc_chance = tmpdproc_chance;
|
||||
npc_spells_cache[iDBSpellsID]->fail_recast = tmppfail_recast;
|
||||
|
||||
@ -476,7 +476,7 @@ void NPC::CheckMinMaxLevel(Mob *them)
|
||||
if(themlevel < (*cur)->min_level || themlevel > (*cur)->max_level)
|
||||
{
|
||||
material = Inventory::CalcMaterialFromSlot((*cur)->equip_slot);
|
||||
if(material != 0xFF)
|
||||
if (material != _MaterialInvalid)
|
||||
SendWearChange(material);
|
||||
|
||||
cur = itemlist.erase(cur);
|
||||
@ -1942,6 +1942,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue)
|
||||
else if(id == "special_attacks") { NPCSpecialAttacks(val.c_str(), 0, 1); return; }
|
||||
else if(id == "special_abilities") { ProcessSpecialAbilities(val.c_str()); return; }
|
||||
else if(id == "attack_speed") { attack_speed = (float)atof(val.c_str()); CalcBonuses(); return; }
|
||||
else if(id == "attack_delay") { attack_delay = atoi(val.c_str()); CalcBonuses(); return; }
|
||||
else if(id == "atk") { ATK = atoi(val.c_str()); return; }
|
||||
else if(id == "accuracy") { accuracy_rating = atoi(val.c_str()); return; }
|
||||
else if(id == "avoidance") { avoidance_rating = atoi(val.c_str()); return; }
|
||||
|
||||
@ -155,6 +155,7 @@ public:
|
||||
virtual void RangedAttack(Mob* other);
|
||||
virtual void ThrowingAttack(Mob* other) { }
|
||||
int32 GetNumberOfAttacks() const { return attack_count; }
|
||||
void DoRangedAttackDmg(Mob* other, bool Launch=true, int16 damage_mod=0, int16 chance_mod=0, SkillUseTypes skill=SkillArchery, float speed=4.0f, const char *IDFile = nullptr);
|
||||
|
||||
bool DatabaseCastAccepted(int spell_id);
|
||||
bool IsFactionListAlly(uint32 other_faction);
|
||||
@ -259,6 +260,7 @@ public:
|
||||
uint32 GetMinDMG() const {return min_dmg;}
|
||||
int16 GetSlowMitigation() const {return slow_mitigation;}
|
||||
float GetAttackSpeed() const {return attack_speed;}
|
||||
uint8 GetAttackDelay() const {return attack_delay;}
|
||||
bool IsAnimal() const { return(bodytype == BT_Animal); }
|
||||
uint16 GetPetSpellID() const {return pet_spell_id;}
|
||||
void SetPetSpellID(uint16 amt) {pet_spell_id = amt;}
|
||||
|
||||
@ -205,15 +205,15 @@ Map::Vertex PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ)
|
||||
|
||||
}
|
||||
|
||||
std::list<int> PathManager::FindRoute(int startID, int endID)
|
||||
std::deque<int> PathManager::FindRoute(int startID, int endID)
|
||||
{
|
||||
_log(PATHING__DEBUG, "FindRoute from node %i to %i", startID, endID);
|
||||
|
||||
memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount);
|
||||
|
||||
std::list<AStarNode> OpenList, ClosedList;
|
||||
std::deque<AStarNode> OpenList, ClosedList;
|
||||
|
||||
std::list<int>Route;
|
||||
std::deque<int>Route;
|
||||
|
||||
AStarNode AStarEntry, CurrentNode;
|
||||
|
||||
@ -251,7 +251,7 @@ std::list<int> PathManager::FindRoute(int startID, int endID)
|
||||
|
||||
Route.push_back(endID);
|
||||
|
||||
std::list<AStarNode>::iterator RouteIterator;
|
||||
std::deque<AStarNode>::iterator RouteIterator;
|
||||
|
||||
while(CurrentNode.PathNodeID != startID)
|
||||
{
|
||||
@ -300,7 +300,7 @@ std::list<int> PathManager::FindRoute(int startID, int endID)
|
||||
|
||||
bool AlreadyInOpenList = false;
|
||||
|
||||
std::list<AStarNode>::iterator OpenListIterator, InsertionPoint = OpenList.end();
|
||||
std::deque<AStarNode>::iterator OpenListIterator, InsertionPoint = OpenList.end();
|
||||
|
||||
for(OpenListIterator = OpenList.begin(); OpenListIterator != OpenList.end(); ++OpenListIterator)
|
||||
{
|
||||
@ -350,11 +350,11 @@ bool SortPathNodesByDistance(PathNodeSortStruct n1, PathNodeSortStruct n2)
|
||||
return n1.Distance < n2.Distance;
|
||||
}
|
||||
|
||||
std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
std::deque<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
{
|
||||
_log(PATHING__DEBUG, "FindRoute(%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f)", Start.x, Start.y, Start.z, End.x, End.y, End.z);
|
||||
|
||||
std::list<int> noderoute;
|
||||
std::deque<int> noderoute;
|
||||
|
||||
float CandidateNodeRangeXY = RuleR(Pathing, CandidateNodeRangeXY);
|
||||
|
||||
@ -365,7 +365,7 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
//
|
||||
int ClosestPathNodeToStart = -1;
|
||||
|
||||
std::list<PathNodeSortStruct> SortedByDistance;
|
||||
std::deque<PathNodeSortStruct> SortedByDistance;
|
||||
|
||||
PathNodeSortStruct TempNode;
|
||||
|
||||
@ -382,9 +382,9 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
}
|
||||
}
|
||||
|
||||
SortedByDistance.sort(SortPathNodesByDistance);
|
||||
std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance);
|
||||
|
||||
for(std::list<PathNodeSortStruct>::iterator Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
{
|
||||
_log(PATHING__DEBUG, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
|
||||
|
||||
@ -420,9 +420,9 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
}
|
||||
}
|
||||
|
||||
SortedByDistance.sort(SortPathNodesByDistance);
|
||||
std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance);
|
||||
|
||||
for(std::list<PathNodeSortStruct>::iterator Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
{
|
||||
_log(PATHING__DEBUG, "Checking Reachability of Node %i from End Position.", PathNodes[(*Iterator).id].id);
|
||||
_log(PATHING__DEBUG, " (%8.3f, %8.3f, %8.3f) to (%8.3f, %8.3f, %8.3f)",
|
||||
@ -456,7 +456,7 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
{
|
||||
int CulledNodes = 0;
|
||||
|
||||
std::list<int>::iterator First, Second;
|
||||
std::deque<int>::iterator First, Second;
|
||||
|
||||
while((noderoute.size() >= 2) && (CulledNodes < NodesToAttemptToCull))
|
||||
{
|
||||
@ -487,7 +487,7 @@ std::list<int> PathManager::FindRoute(Map::Vertex Start, Map::Vertex End)
|
||||
{
|
||||
int CulledNodes = 0;
|
||||
|
||||
std::list<int>::iterator First, Second;
|
||||
std::deque<int>::iterator First, Second;
|
||||
|
||||
while((noderoute.size() >= 2) && (CulledNodes < NodesToAttemptToCull))
|
||||
{
|
||||
@ -611,7 +611,7 @@ void PathManager::MeshTest()
|
||||
if(j == i)
|
||||
continue;
|
||||
|
||||
std::list<int> Route = FindRoute(PathNodes[i].id, PathNodes[j].id);
|
||||
std::deque<int> Route = FindRoute(PathNodes[i].id, PathNodes[j].id);
|
||||
|
||||
if(Route.size() == 0)
|
||||
{
|
||||
@ -638,7 +638,7 @@ void PathManager::SimpleMeshTest()
|
||||
|
||||
for(uint32 j = 1; j < Head.PathNodeCount; ++j)
|
||||
{
|
||||
std::list<int> Route = FindRoute(PathNodes[0].id, PathNodes[j].id);
|
||||
std::deque<int> Route = FindRoute(PathNodes[0].id, PathNodes[j].id);
|
||||
|
||||
if(Route.size() == 0)
|
||||
{
|
||||
@ -1103,7 +1103,7 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
|
||||
|
||||
int ClosestPathNodeToStart = -1;
|
||||
|
||||
std::list<PathNodeSortStruct> SortedByDistance;
|
||||
std::deque<PathNodeSortStruct> SortedByDistance;
|
||||
|
||||
PathNodeSortStruct TempNode;
|
||||
|
||||
@ -1120,9 +1120,9 @@ int PathManager::FindNearestPathNode(Map::Vertex Position)
|
||||
}
|
||||
}
|
||||
|
||||
SortedByDistance.sort(SortPathNodesByDistance);
|
||||
std::sort(SortedByDistance.begin(), SortedByDistance.end(), SortPathNodesByDistance);
|
||||
|
||||
for(std::list<PathNodeSortStruct>::iterator Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator)
|
||||
{
|
||||
_log(PATHING__DEBUG, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id);
|
||||
|
||||
@ -1262,9 +1262,7 @@ void Mob::PrintRoute()
|
||||
|
||||
printf("Route is : ");
|
||||
|
||||
std::list<int>::iterator Iterator;
|
||||
|
||||
for(Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
|
||||
for(auto Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
|
||||
{
|
||||
printf("%i, ", (*Iterator));
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
#include "map.h"
|
||||
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
class Client;
|
||||
class Mob;
|
||||
@ -60,8 +60,8 @@ public:
|
||||
static PathManager *LoadPathFile(const char *ZoneName);
|
||||
bool loadPaths(FILE *fp);
|
||||
void PrintPathing();
|
||||
std::list<int> FindRoute(Map::Vertex Start, Map::Vertex End);
|
||||
std::list<int> FindRoute(int startID, int endID);
|
||||
std::deque<int> FindRoute(Map::Vertex Start, Map::Vertex End);
|
||||
std::deque<int> FindRoute(int startID, int endID);
|
||||
|
||||
Map::Vertex GetPathNodeCoordinates(int NodeNumber, bool BestZ = true);
|
||||
bool CheckLosFN(Map::Vertex a, Map::Vertex b);
|
||||
|
||||
@ -2119,6 +2119,32 @@ XS(XS_NPC_GetAttackSpeed)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetAttackDelay); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetAttackDelay)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetAttackDelay(THIS)");
|
||||
{
|
||||
NPC * THIS;
|
||||
float RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetAttackDelay();
|
||||
XSprePUSH; PUSHn((double)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetAccuracyRating); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetAccuracyRating)
|
||||
{
|
||||
@ -2145,6 +2171,32 @@ XS(XS_NPC_GetAccuracyRating)
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetAvoidanceRating); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetAvoidanceRating)
|
||||
{
|
||||
dXSARGS;
|
||||
if (items != 1)
|
||||
Perl_croak(aTHX_ "Usage: NPC::GetAvoidanceyRating(THIS)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int32 RETVAL;
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == nullptr)
|
||||
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
|
||||
|
||||
RETVAL = THIS->GetAvoidanceRating();
|
||||
XSprePUSH; PUSHu((UV)RETVAL);
|
||||
}
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_GetSpawnKillCount); /* prototype to pass -Wmissing-prototypes */
|
||||
XS(XS_NPC_GetSpawnKillCount)
|
||||
{
|
||||
@ -2245,6 +2297,81 @@ XS(XS_NPC_GetMerchantProbability) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_NPC_AddMeleeProc);
|
||||
XS(XS_NPC_AddMeleeProc) {
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: NPC::AddMeleeProc(THIS,spellid,chance)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int spell_id = (int)SvIV(ST(1));
|
||||
int chance = (int)SvIV(ST(2));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddProcToWeapon(spell_id, true, chance);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_NPC_AddRangedProc);
|
||||
XS(XS_NPC_AddRangedProc) {
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: NPC::AddRangedProc(THIS,spellid,chance)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int spell_id = (int)SvIV(ST(1));
|
||||
int chance = (int)SvIV(ST(2));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddDefensiveProc(spell_id,chance);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
XS(XS_NPC_AddDefensiveProc);
|
||||
XS(XS_NPC_AddDefensiveProc) {
|
||||
dXSARGS;
|
||||
if (items != 3)
|
||||
Perl_croak(aTHX_ "Usage: NPC::AddDefensiveProc(THIS,spellid,chance)");
|
||||
{
|
||||
NPC * THIS;
|
||||
int spell_id = (int)SvIV(ST(1));
|
||||
int chance = (int)SvIV(ST(2));
|
||||
dXSTARG;
|
||||
|
||||
if (sv_derived_from(ST(0), "NPC")) {
|
||||
IV tmp = SvIV((SV*)SvRV(ST(0)));
|
||||
THIS = INT2PTR(NPC *,tmp);
|
||||
}
|
||||
else
|
||||
Perl_croak(aTHX_ "THIS is not of type NPC");
|
||||
if(THIS == NULL)
|
||||
Perl_croak(aTHX_ "THIS is NULL, avoiding crash.");
|
||||
|
||||
THIS->AddProcToWeapon(spell_id, true, chance);
|
||||
}
|
||||
XSRETURN_EMPTY;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
@ -2342,11 +2469,16 @@ XS(boot_NPC)
|
||||
newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAttackDelay"), XS_NPC_GetAttackDelay, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$");
|
||||
newXSproto(strcpy(buf, "GetAvoidanceRating"), XS_NPC_GetAvoidanceRating, file, "$");
|
||||
newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$");
|
||||
newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$");
|
||||
newXSproto(strcpy(buf, "SetMerchantProbability"), XS_NPC_SetMerchantProbability, file, "$$");
|
||||
newXSproto(strcpy(buf, "GetMerchantProbability"), XS_NPC_GetMerchantProbability, file, "$");
|
||||
newXSproto(strcpy(buf, "AddMeleeProc"), XS_NPC_AddMeleeProc, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddRangedProc"), XS_NPC_AddRangedProc, file, "$$$");
|
||||
newXSproto(strcpy(buf, "AddDefensiveProc"), XS_NPC_AddDefensiveProc, file, "$$$");
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
@ -103,6 +103,9 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
||||
if (!who)
|
||||
return;
|
||||
|
||||
if(who->GetInvul() || who->GetSpecialAbility(IMMUNE_MELEE) || who->GetSpecialAbility(IMMUNE_MELEE_EXCEPT_BANE))
|
||||
return; //-5?
|
||||
|
||||
int32 hate = max_damage;
|
||||
if(hate_override > -1)
|
||||
hate = hate_override;
|
||||
@ -1059,8 +1062,8 @@ bool Mob::TryProjectileAttack(Mob* other, const Item_Struct *item, SkillUseTypes
|
||||
|
||||
if(item)
|
||||
SendItemAnimation(other, item, skillInUse, speed);
|
||||
else if (IsNPC())
|
||||
ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse);
|
||||
//else if (IsNPC())
|
||||
//ProjectileAnimation(other, 0,false,speed,0,0,0,CastToNPC()->GetAmmoIDfile(),skillInUse);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1097,12 +1100,19 @@ void Mob::ProjectileAttack()
|
||||
if (ProjectileAtk[i].hit_increment <= ProjectileAtk[i].increment){
|
||||
|
||||
if (target){
|
||||
if (ProjectileAtk[i].skill == SkillArchery)
|
||||
DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillThrowing)
|
||||
DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg))
|
||||
SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true);
|
||||
|
||||
if (IsNPC())
|
||||
CastToNPC()->DoRangedAttackDmg(target, false, ProjectileAtk[i].wpn_dmg,0, static_cast<SkillUseTypes>(ProjectileAtk[i].skill));
|
||||
|
||||
else
|
||||
{
|
||||
if (ProjectileAtk[i].skill == SkillArchery)
|
||||
DoArcheryAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0,ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_id, nullptr, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillThrowing)
|
||||
DoThrowingAttackDmg(target, nullptr, nullptr,ProjectileAtk[i].wpn_dmg,0,0,0, ProjectileAtk[i].ranged_id, ProjectileAtk[i].ammo_slot);
|
||||
else if (ProjectileAtk[i].skill == SkillConjuration && IsValidSpell(ProjectileAtk[i].wpn_dmg))
|
||||
SpellOnTarget(ProjectileAtk[i].wpn_dmg, target, false, true, spells[ProjectileAtk[i].wpn_dmg].ResistDiff, true);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectileAtk[i].increment = 0;
|
||||
@ -1187,14 +1197,8 @@ void NPC::RangedAttack(Mob* other)
|
||||
attacks = attacks > 0 ? attacks : 1;
|
||||
for(int i = 0; i < attacks; ++i) {
|
||||
|
||||
//if we have SPECATK_RANGED_ATK set then we range attack without weapon or ammo
|
||||
const Item_Struct* weapon = nullptr;
|
||||
const Item_Struct* ammo = nullptr;
|
||||
if(!GetSpecialAbility(SPECATK_RANGED_ATK))
|
||||
{
|
||||
//find our bow and ammo return if we can't find them...
|
||||
return;
|
||||
}
|
||||
|
||||
int sa_min_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 4); //Min Range of NPC attack
|
||||
int sa_max_range = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 1); //Max Range of NPC attack
|
||||
@ -1208,16 +1212,11 @@ void NPC::RangedAttack(Mob* other)
|
||||
if (sa_min_range)
|
||||
min_range = static_cast<float>(sa_min_range);
|
||||
|
||||
mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", max_range);
|
||||
max_range *= max_range;
|
||||
if(DistNoRootNoZ(*other) > max_range) {
|
||||
mlog(COMBAT__RANGED, "Ranged attack out of range...%.2f vs %.2f", DistNoRootNoZ(*other), max_range);
|
||||
//target is out of range, client does a message
|
||||
if(DistNoRoot(*other) > max_range)
|
||||
return;
|
||||
}
|
||||
else if(DistNoRootNoZ(*other) < (min_range * min_range))
|
||||
else if(DistNoRoot(*other) < (min_range * min_range))
|
||||
return;
|
||||
|
||||
|
||||
if(!other || !IsAttackAllowed(other) ||
|
||||
IsCasting() ||
|
||||
@ -1229,74 +1228,100 @@ void NPC::RangedAttack(Mob* other)
|
||||
return;
|
||||
}
|
||||
|
||||
SkillUseTypes skillinuse = SkillArchery;
|
||||
skillinuse = static_cast<SkillUseTypes>(GetRangedSkill());
|
||||
|
||||
if(!ammo && !GetAmmoIDfile())
|
||||
ammo = database.GetItem(8005);
|
||||
|
||||
if(ammo)
|
||||
SendItemAnimation(other, ammo, SkillArchery);
|
||||
else
|
||||
ProjectileAnimation(other, 0,false,0,0,0,0,GetAmmoIDfile(),skillinuse);
|
||||
|
||||
FaceTarget(other);
|
||||
|
||||
if (!other->CheckHitChance(this, skillinuse, MainRange, GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2)))
|
||||
{
|
||||
mlog(COMBAT__RANGED, "Ranged attack missed %s.", other->GetName());
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, skillinuse);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16 WDmg = GetWeaponDamage(other, weapon);
|
||||
int16 ADmg = GetWeaponDamage(other, ammo);
|
||||
int32 TotalDmg = 0;
|
||||
if(WDmg > 0 || ADmg > 0)
|
||||
{
|
||||
mlog(COMBAT__RANGED, "Ranged attack hit %s.", other->GetName());
|
||||
|
||||
int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
||||
int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier);
|
||||
|
||||
if(RuleB(Combat, UseIntervalAC))
|
||||
TotalDmg = MaxDmg;
|
||||
else
|
||||
TotalDmg = zone->random.Int(MinDmg, MaxDmg);
|
||||
|
||||
TotalDmg += TotalDmg * GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3) / 100; //Damage modifier
|
||||
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
other->MeleeMitigation(this, TotalDmg, MinDmg);
|
||||
if (TotalDmg > 0)
|
||||
CommonOutgoingHitSuccess(other, TotalDmg, skillinuse);
|
||||
}
|
||||
|
||||
else
|
||||
TotalDmg = -5;
|
||||
|
||||
if (TotalDmg > 0)
|
||||
other->AddToHateList(this, TotalDmg, 0, false);
|
||||
else
|
||||
other->AddToHateList(this, 0, 0, false);
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillinuse);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, true, MainRange);
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
if(other && !other->HasDied())
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange);
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied())
|
||||
TrySkillProc(other, skillinuse, 0, false, MainRange);
|
||||
DoRangedAttackDmg(other);
|
||||
|
||||
CommonBreakInvisible();
|
||||
}
|
||||
}
|
||||
|
||||
void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, SkillUseTypes skill, float speed, const char *IDFile) {
|
||||
|
||||
if ((other == nullptr ||
|
||||
(other->HasDied())) ||
|
||||
HasDied() ||
|
||||
(!IsAttackAllowed(other)) ||
|
||||
(other->GetInvul() ||
|
||||
other->GetSpecialAbility(IMMUNE_MELEE)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SkillUseTypes skillInUse = static_cast<SkillUseTypes>(GetRangedSkill());
|
||||
|
||||
if (skill != skillInUse)
|
||||
skillInUse = skill;
|
||||
|
||||
if (Launch)
|
||||
{
|
||||
const char *ammo = "IT10";
|
||||
|
||||
if (IDFile != nullptr)
|
||||
ammo = IDFile;
|
||||
else if (GetAmmoIDfile())
|
||||
ammo = GetAmmoIDfile();
|
||||
|
||||
ProjectileAnimation(other, 0,false,speed,0,0,0,ammo,skillInUse);
|
||||
|
||||
if (RuleB(Combat, ProjectileDmgOnImpact))
|
||||
{
|
||||
TryProjectileAttack(other, nullptr, skillInUse, damage_mod, nullptr, nullptr, 0, speed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!chance_mod)
|
||||
chance_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 2);
|
||||
|
||||
if (!other->CheckHitChance(this, skillInUse, MainRange, chance_mod))
|
||||
{
|
||||
other->Damage(this, 0, SPELL_UNKNOWN, skillInUse);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 TotalDmg = 0;
|
||||
int32 MaxDmg = max_dmg * RuleR(Combat, ArcheryNPCMultiplier); // should add a field to npc_types
|
||||
int32 MinDmg = min_dmg * RuleR(Combat, ArcheryNPCMultiplier);
|
||||
|
||||
if(RuleB(Combat, UseIntervalAC))
|
||||
TotalDmg = MaxDmg;
|
||||
else
|
||||
TotalDmg = zone->random.Int(MinDmg, MaxDmg);
|
||||
|
||||
|
||||
if (!damage_mod)
|
||||
damage_mod = GetSpecialAbilityParam(SPECATK_RANGED_ATK, 3);//Damage modifier
|
||||
|
||||
TotalDmg += TotalDmg * damage_mod / 100;
|
||||
|
||||
other->AvoidDamage(this, TotalDmg, false);
|
||||
other->MeleeMitigation(this, TotalDmg, MinDmg);
|
||||
|
||||
if (TotalDmg > 0)
|
||||
CommonOutgoingHitSuccess(other, TotalDmg, skillInUse);
|
||||
else
|
||||
TotalDmg = -5;
|
||||
|
||||
if (TotalDmg > 0)
|
||||
other->AddToHateList(this, TotalDmg, 0, false);
|
||||
else
|
||||
other->AddToHateList(this, 0, 0, false);
|
||||
|
||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, skillInUse);
|
||||
|
||||
if (TotalDmg > 0 && HasSkillProcSuccess() && !other->HasDied())
|
||||
TrySkillProc(other, skillInUse, 0, true, MainRange);
|
||||
}
|
||||
|
||||
//try proc on hits and misses
|
||||
if(other && !other->HasDied())
|
||||
TrySpellProc(nullptr, (const Item_Struct*)nullptr, other, MainRange);
|
||||
|
||||
if (HasSkillProcs() && other && !other->HasDied())
|
||||
TrySkillProc(other, skillInUse, 0, false, MainRange);
|
||||
}
|
||||
|
||||
uint16 Mob::GetThrownDamage(int16 wDmg, int32& TotalDmg, int& minDmg) {
|
||||
uint16 MaxDmg = (((2 * wDmg) * GetDamageTable(SkillThrowing)) / 100);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user