2020-08-20 15:43:37 +00:00
# include "CNShardServer.hpp"
# include "CNStructs.hpp"
# include "NanoManager.hpp"
# include "PlayerManager.hpp"
2020-09-18 07:10:30 +00:00
# include "NPCManager.hpp"
2020-09-18 16:37:26 +00:00
# include "MobManager.hpp"
2020-09-26 01:48:45 +00:00
# include "MissionManager.hpp"
2020-10-09 00:01:35 +00:00
# include "GroupManager.hpp"
2020-08-20 15:43:37 +00:00
2020-09-15 14:46:52 +00:00
namespace NanoManager {
// active powers
std : : set < int > StunPowers = { 1 , 13 , 42 , 59 , 78 , 103 } ;
2020-10-04 23:54:08 +00:00
std : : set < int > HealPowers = { 7 , 12 , 38 , 53 , 92 , 98 } ;
std : : set < int > GroupHealPowers = { 2 , 61 , 82 } ;
2020-09-15 14:46:52 +00:00
std : : set < int > RecallPowers = { 5 , 25 , 66 , 69 , 75 , 87 } ;
std : : set < int > DrainPowers = { 10 , 34 , 37 , 56 , 93 , 97 } ;
std : : set < int > SnarePowers = { 17 , 18 , 27 , 41 , 43 , 47 , 90 , 96 , 106 } ;
std : : set < int > DamagePowers = { 19 , 21 , 33 , 45 , 46 , 52 , 101 , 105 , 108 } ;
std : : set < int > GroupRevivePowers = { 20 , 63 , 91 } ;
std : : set < int > LeechPowers = { 24 , 51 , 89 } ;
std : : set < int > SleepPowers = { 28 , 30 , 32 , 49 , 70 , 71 , 81 , 85 , 94 } ;
// passive powers
2020-10-21 15:04:20 +00:00
std : : set < int > ScavengePowers = { 3 , 50 , 99 } ;
2020-10-04 23:54:08 +00:00
std : : set < int > RunPowers = { 4 , 68 , 86 } ;
std : : set < int > GroupRunPowers = { 8 , 62 , 73 } ;
2020-09-15 14:46:52 +00:00
std : : set < int > BonusPowers = { 6 , 54 , 104 } ;
std : : set < int > GuardPowers = { 9 , 57 , 76 } ;
std : : set < int > RadarPowers = { 11 , 67 , 95 } ;
2020-09-18 16:37:26 +00:00
std : : set < int > AntidotePowers = { 14 , 58 , 102 } ;
2020-10-04 23:54:08 +00:00
std : : set < int > FreedomPowers = { 31 , 39 , 107 } ;
std : : set < int > GroupFreedomPowers = { 15 , 55 , 77 } ;
std : : set < int > JumpPowers = { 16 , 44 , 88 } ;
std : : set < int > GroupJumpPowers = { 35 , 60 , 100 } ;
2020-10-21 15:04:20 +00:00
std : : set < int > SelfRevivePowers = { 22 , 48 , 84 } ;
2020-10-04 23:54:08 +00:00
std : : set < int > SneakPowers = { 29 , 72 , 80 } ;
2020-10-21 15:04:20 +00:00
std : : set < int > GroupSneakPowers = { 23 , 65 , 83 } ;
2020-09-15 14:46:52 +00:00
std : : set < int > TreasureFinderPowers = { 26 , 40 , 74 } ;
/*
* The active nano power table is down below activePower < > ( ) and its
* worker functions so we don ' t have to have unsightly function declarations .
*/
} ; // namespace
2020-09-25 21:05:36 +00:00
std : : map < int32_t , NanoData > NanoManager : : NanoTable ;
2020-10-24 20:28:35 +00:00
std : : map < int32_t , NanoTuning > NanoManager : : NanoTunings ;
2020-09-25 21:05:36 +00:00
2020-08-20 15:43:37 +00:00
void NanoManager : : init ( ) {
2020-08-21 00:37:34 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_NANO_ACTIVE , nanoSummonHandler ) ;
2020-08-22 18:02:08 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_NANO_EQUIP , nanoEquipHandler ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_NANO_UNEQUIP , nanoUnEquipHandler ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_GIVE_NANO , nanoGMGiveHandler ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_NANO_TUNE , nanoSkillSetHandler ) ;
2020-09-09 01:15:25 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_GIVE_NANO_SKILL , nanoSkillSetGMHandler ) ;
2020-08-22 18:02:08 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_NANO_SKILL_USE , nanoSkillUseHandler ) ;
2020-09-18 07:10:30 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_WARP_USE_RECALL , nanoRecallHandler ) ;
2020-09-25 05:35:27 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_CHARGE_NANO_STAMINA , nanoPotionHandler ) ;
2020-08-22 18:02:08 +00:00
}
void NanoManager : : nanoEquipHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_NANO_EQUIP ) )
return ; // malformed packet
sP_CL2FE_REQ_NANO_EQUIP * nano = ( sP_CL2FE_REQ_NANO_EQUIP * ) data - > buf ;
2020-08-23 00:26:18 +00:00
INITSTRUCT ( sP_FE2CL_REP_NANO_EQUIP_SUCC , resp ) ;
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-08-22 18:02:08 +00:00
2020-09-28 18:11:13 +00:00
// sanity checks
if ( plr = = nullptr | | nano - > iNanoSlotNum > 2 | | nano - > iNanoSlotNum < 0 )
2020-08-23 03:15:27 +00:00
return ;
2020-08-22 23:31:09 +00:00
resp . iNanoID = nano - > iNanoID ;
resp . iNanoSlotNum = nano - > iNanoSlotNum ;
2020-08-23 00:52:54 +00:00
// Update player
2020-08-24 22:02:07 +00:00
plr - > equippedNanos [ nano - > iNanoSlotNum ] = nano - > iNanoID ;
2020-08-23 00:52:54 +00:00
2020-08-25 18:30:20 +00:00
// unsummon nano if replaced
if ( plr - > activeNano = = plr - > equippedNanos [ nano - > iNanoSlotNum ] )
summonNano ( sock , - 1 ) ;
2020-08-22 23:31:09 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_NANO_EQUIP_SUCC , sizeof ( sP_FE2CL_REP_NANO_EQUIP_SUCC ) ) ;
2020-08-22 18:02:08 +00:00
}
void NanoManager : : nanoUnEquipHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_NANO_UNEQUIP ) )
return ; // malformed packet
sP_CL2FE_REQ_NANO_UNEQUIP * nano = ( sP_CL2FE_REQ_NANO_UNEQUIP * ) data - > buf ;
2020-08-23 00:26:18 +00:00
INITSTRUCT ( sP_FE2CL_REP_NANO_UNEQUIP_SUCC , resp ) ;
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-08-22 23:31:09 +00:00
2020-08-25 18:30:20 +00:00
// sanity check
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr | | nano - > iNanoSlotNum > 2 | | nano - > iNanoSlotNum < 0 )
2020-08-23 03:15:27 +00:00
return ;
2020-08-22 23:31:09 +00:00
resp . iNanoSlotNum = nano - > iNanoSlotNum ;
2020-08-22 18:02:08 +00:00
2020-08-25 18:30:20 +00:00
// unsummon nano if removed
if ( plr - > equippedNanos [ nano - > iNanoSlotNum ] = = plr - > activeNano )
summonNano ( sock , - 1 ) ;
2020-08-23 00:52:54 +00:00
// update player
2020-08-24 22:02:07 +00:00
plr - > equippedNanos [ nano - > iNanoSlotNum ] = 0 ;
2020-08-23 00:52:54 +00:00
2020-08-22 23:31:09 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_NANO_UNEQUIP_SUCC , sizeof ( sP_FE2CL_REP_NANO_UNEQUIP_SUCC ) ) ;
2020-08-22 18:02:08 +00:00
}
void NanoManager : : nanoGMGiveHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_GIVE_NANO ) )
return ; // ignore the malformed packet
// Cmd: /nano <nanoId>
sP_CL2FE_REQ_PC_GIVE_NANO * nano = ( sP_CL2FE_REQ_PC_GIVE_NANO * ) data - > buf ;
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-08-22 18:02:08 +00:00
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-08-22 18:02:08 +00:00
// Add nano to player
addNano ( sock , nano - > iNanoID , 0 ) ;
DEBUGLOG (
2020-08-24 22:02:07 +00:00
std : : cout < < U16toU8 ( plr - > PCStyle . szFirstName ) < < U16toU8 ( plr - > PCStyle . szLastName ) < < " requested to add nano id: " < < nano - > iNanoID < < std : : endl ;
2020-08-22 18:02:08 +00:00
)
2020-08-20 15:43:37 +00:00
}
void NanoManager : : nanoSummonHandler ( CNSocket * sock , CNPacketData * data ) {
2020-08-21 00:37:34 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_NANO_ACTIVE ) )
2020-08-20 23:50:30 +00:00
return ; // malformed packet
2020-08-23 00:52:54 +00:00
sP_CL2FE_REQ_NANO_ACTIVE * pkt = ( sP_CL2FE_REQ_NANO_ACTIVE * ) data - > buf ;
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-08-20 15:43:37 +00:00
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-08-25 18:30:20 +00:00
summonNano ( sock , pkt - > iNanoSlotNum ) ;
2020-08-23 00:52:54 +00:00
2020-08-25 18:30:20 +00:00
// Send to client
2020-08-22 18:02:08 +00:00
DEBUGLOG (
2020-08-24 22:02:07 +00:00
std : : cout < < U16toU8 ( plr - > PCStyle . szFirstName ) < < U16toU8 ( plr - > PCStyle . szLastName ) < < " requested to summon nano slot: " < < pkt - > iNanoSlotNum < < std : : endl ;
2020-08-22 18:02:08 +00:00
)
}
void NanoManager : : nanoSkillUseHandler ( CNSocket * sock , CNPacketData * data ) {
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-09-18 07:10:30 +00:00
int16_t nanoId = plr - > activeNano ;
int16_t skillId = plr - > Nanos [ nanoId ] . iSkillID ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
DEBUGLOG (
std : : cout < < U16toU8 ( plr - > PCStyle . szFirstName ) < < U16toU8 ( plr - > PCStyle . szLastName ) < < " requested to summon nano skill " < < std : : endl ;
)
2020-09-15 14:46:52 +00:00
for ( auto & pwr : ActivePowers )
if ( pwr . powers . count ( skillId ) ) // std::set's contains method is C++20 only...
pwr . handle ( sock , data , nanoId , skillId ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
// Group Revive is handled separately (XXX: move into table?)
if ( GroupRevivePowers . find ( skillId ) = = GroupRevivePowers . end ( ) )
return ;
2020-08-24 22:02:07 +00:00
2020-10-04 23:54:08 +00:00
Player * leader = PlayerManager : : getPlayerFromID ( plr - > iIDGroup ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( leader = = nullptr )
return ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
for ( int i = 0 ; i < leader - > groupCnt ; i + + ) {
Player * varPlr = PlayerManager : : getPlayerFromID ( leader - > groupIDs [ i ] ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( varPlr = = nullptr )
return ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( varPlr - > HP < = 0 )
revivePlayer ( varPlr ) ;
}
2020-08-22 18:02:08 +00:00
}
void NanoManager : : nanoSkillSetHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_NANO_TUNE ) )
return ; // malformed packet
sP_CL2FE_REQ_NANO_TUNE * skill = ( sP_CL2FE_REQ_NANO_TUNE * ) data - > buf ;
2020-10-24 20:28:35 +00:00
setNanoSkill ( sock , skill ) ;
2020-08-22 18:02:08 +00:00
}
2020-09-09 01:15:25 +00:00
void NanoManager : : nanoSkillSetGMHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_GIVE_NANO_SKILL ) )
return ; // malformed packet
sP_CL2FE_REQ_NANO_TUNE * skillGM = ( sP_CL2FE_REQ_NANO_TUNE * ) data - > buf ;
2020-10-24 20:28:35 +00:00
setNanoSkill ( sock , skillGM ) ;
2020-09-09 01:15:25 +00:00
}
2020-09-18 07:10:30 +00:00
void NanoManager : : nanoRecallHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_WARP_USE_RECALL ) )
return ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
INITSTRUCT ( sP_FE2CL_REP_WARP_USE_RECALL_FAIL , resp ) ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_WARP_USE_RECALL_FAIL , sizeof ( sP_FE2CL_REP_WARP_USE_RECALL_FAIL ) ) ;
// stubbed for now
}
2020-09-25 05:35:27 +00:00
void NanoManager : : nanoPotionHandler ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_CHARGE_NANO_STAMINA ) )
return ;
2020-10-05 00:03:13 +00:00
2020-09-25 05:35:27 +00:00
Player * player = PlayerManager : : getPlayer ( sock ) ;
2020-10-05 00:03:13 +00:00
2020-09-28 18:11:13 +00:00
// sanity checks
if ( player = = nullptr | | player - > activeNano = = - 1 | | player - > batteryN = = 0 )
2020-09-25 05:35:27 +00:00
return ;
sNano nano = player - > Nanos [ player - > activeNano ] ;
int difference = 150 - nano . iStamina ;
if ( player - > batteryN < difference )
difference = player - > batteryN ;
if ( difference = = 0 )
return ;
INITSTRUCT ( sP_FE2CL_REP_CHARGE_NANO_STAMINA , response ) ;
response . iNanoID = nano . iID ;
response . iNanoStamina = nano . iStamina + difference ;
response . iBatteryN = player - > batteryN - difference ;
sock - > sendPacket ( ( void * ) & response , P_FE2CL_REP_CHARGE_NANO_STAMINA , sizeof ( sP_FE2CL_REP_CHARGE_NANO_STAMINA ) ) ;
2020-10-19 17:26:14 +00:00
// now update serverside
2020-09-25 05:35:27 +00:00
player - > batteryN - = difference ;
player - > Nanos [ nano . iID ] . iStamina + = difference ;
}
2020-08-22 18:02:08 +00:00
# pragma region Helper methods
2020-09-26 01:48:45 +00:00
void NanoManager : : addNano ( CNSocket * sock , int16_t nanoId , int16_t slot , bool spendfm ) {
2020-08-23 03:15:27 +00:00
if ( nanoId > 36 )
return ;
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-08-22 18:02:08 +00:00
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-09-12 20:43:04 +00:00
int level = nanoId < plr - > level ? plr - > level : nanoId ;
2020-09-26 01:48:45 +00:00
/*
* Spend the necessary Fusion Matter .
* Note the use of the not - yet - incremented plr - > level as opposed to level .
* Doing it the other way always leaves the FM at 0. Jade totally called it .
*/
2020-09-29 21:27:48 +00:00
plr - > level = level ;
2020-10-05 00:03:13 +00:00
2020-09-26 01:48:45 +00:00
if ( spendfm )
2020-09-29 21:27:48 +00:00
MissionManager : : updateFusionMatter ( sock , - ( int ) MissionManager : : AvatarGrowth [ plr - > level - 1 ] [ " m_iReqBlob_NanoCreate " ] ) ;
2020-09-26 01:48:45 +00:00
2020-08-22 18:02:08 +00:00
// Send to client
2020-08-23 00:26:18 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_NANO_CREATE_SUCC , resp ) ;
2020-08-22 23:31:09 +00:00
resp . Nano . iID = nanoId ;
resp . Nano . iStamina = 150 ;
resp . iQuestItemSlotNum = slot ;
2020-09-12 20:43:04 +00:00
resp . iPC_Level = level ;
2020-09-26 01:48:45 +00:00
resp . iPC_FusionMatter = plr - > fusionmatter ;
2020-08-22 18:02:08 +00:00
2020-09-29 21:27:48 +00:00
if ( plr - > activeNano > 0 & & plr - > activeNano = = nanoId )
summonNano ( sock , - 1 ) ; // just unsummon the nano to prevent infinite buffs
2020-10-05 00:03:13 +00:00
2020-08-22 18:02:08 +00:00
// Update player
2020-08-24 22:02:07 +00:00
plr - > Nanos [ nanoId ] = resp . Nano ;
2020-09-12 20:43:04 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_NANO_CREATE_SUCC , sizeof ( sP_FE2CL_REP_PC_NANO_CREATE_SUCC ) ) ;
/*
* iPC_Level in NANO_CREATE_SUCC sets the player ' s level .
* Other players must be notified of the change as well . Both P_FE2CL_REP_PC_NANO_CREATE and
* P_FE2CL_REP_PC_CHANGE_LEVEL appear to play the same animation , but only the latter affects
* the other player ' s displayed level .
*/
2020-09-14 13:53:48 +00:00
2020-09-10 16:51:52 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_CHANGE_LEVEL , resp2 ) ;
resp2 . iPC_ID = plr - > iID ;
2020-09-12 20:43:04 +00:00
resp2 . iPC_Level = level ;
2020-09-10 16:51:52 +00:00
2020-09-12 20:43:04 +00:00
// Update other players' perception of the player's level
2020-09-17 22:45:43 +00:00
PlayerManager : : sendToViewable ( sock , ( void * ) & resp2 , P_FE2CL_REP_PC_CHANGE_LEVEL , sizeof ( sP_FE2CL_REP_PC_CHANGE_LEVEL ) ) ;
2020-08-22 18:02:08 +00:00
}
2020-08-25 18:30:20 +00:00
void NanoManager : : summonNano ( CNSocket * sock , int slot ) {
INITSTRUCT ( sP_FE2CL_REP_NANO_ACTIVE_SUCC , resp ) ;
resp . iActiveNanoSlotNum = slot ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr | | slot > 2 | | slot < - 1 )
2020-09-12 18:21:36 +00:00
return ; // sanity check
2020-08-25 18:30:20 +00:00
2020-09-18 16:37:26 +00:00
int16_t nanoId = slot = = - 1 ? - 1 : plr - > equippedNanos [ slot ] ;
2020-08-25 18:30:20 +00:00
2020-09-14 13:20:55 +00:00
if ( nanoId > 36 | | nanoId < - 1 )
2020-08-25 18:30:20 +00:00
return ; // sanity check
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
int16_t skillId = 0 ;
2020-10-05 00:03:13 +00:00
2020-09-18 16:37:26 +00:00
if ( plr - > activeNano > 0 )
for ( auto & pwr : PassivePowers )
2020-09-29 21:27:48 +00:00
if ( pwr . powers . count ( plr - > Nanos [ plr - > activeNano ] . iSkillID ) ) { // std::set's contains method is C++20 only...
2020-10-04 23:54:08 +00:00
nanoUnbuff ( sock , pwr . iCBFlag , pwr . eCharStatusTimeBuffID , pwr . iValue , pwr . groupPower ) ;
2020-09-29 21:27:48 +00:00
plr - > passiveNanoOut = false ;
}
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
sNano nano = plr - > Nanos [ nanoId ] ;
skillId = nano . iSkillID ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
if ( slot > - 1 ) {
plr - > activeNano = nanoId ;
2020-10-05 00:03:13 +00:00
2020-09-18 16:37:26 +00:00
for ( auto & pwr : PassivePowers )
if ( pwr . powers . count ( skillId ) ) { // std::set's contains method is C++20 only...
resp . eCSTB___Add = 1 ;
2020-10-04 23:54:08 +00:00
nanoBuff ( sock , nanoId , skillId , pwr . eSkillType , pwr . iCBFlag , pwr . eCharStatusTimeBuffID , pwr . iValue , pwr . groupPower ) ;
2020-09-29 21:27:48 +00:00
plr - > passiveNanoOut = true ;
2020-09-18 16:37:26 +00:00
}
2020-09-18 07:10:30 +00:00
} else
plr - > activeNano = 0 ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_NANO_ACTIVE_SUCC , sizeof ( sP_FE2CL_REP_NANO_ACTIVE_SUCC ) ) ;
2020-10-05 00:03:13 +00:00
2020-08-25 18:30:20 +00:00
// Send to other players
INITSTRUCT ( sP_FE2CL_NANO_ACTIVE , pkt1 ) ;
pkt1 . iPC_ID = plr - > iID ;
2020-10-05 00:03:13 +00:00
2020-09-14 13:20:55 +00:00
if ( nanoId = = - 1 )
memset ( & pkt1 . Nano , 0 , sizeof ( pkt1 . Nano ) ) ;
else
pkt1 . Nano = plr - > Nanos [ nanoId ] ;
2020-08-25 18:30:20 +00:00
2020-09-17 22:45:43 +00:00
PlayerManager : : sendToViewable ( sock , ( void * ) & pkt1 , P_FE2CL_NANO_ACTIVE , sizeof ( sP_FE2CL_NANO_ACTIVE ) ) ;
2020-08-25 18:30:20 +00:00
// update player
plr - > activeNano = nanoId ;
}
2020-10-24 20:28:35 +00:00
void NanoManager : : setNanoSkill ( CNSocket * sock , sP_CL2FE_REQ_NANO_TUNE * skill ) {
if ( skill - > iNanoID > 36 )
2020-08-23 03:15:27 +00:00
return ;
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-10-05 00:03:13 +00:00
2020-10-24 20:28:35 +00:00
if ( plr - > activeNano > 0 & & plr - > activeNano = = skill - > iNanoID )
2020-09-29 21:27:48 +00:00
summonNano ( sock , - 1 ) ; // just unsummon the nano to prevent infinite buffs
2020-10-05 00:03:13 +00:00
2020-10-24 20:28:35 +00:00
sNano nano = plr - > Nanos [ skill - > iNanoID ] ;
nano . iSkillID = skill - > iTuneID ;
plr - > Nanos [ skill - > iNanoID ] = nano ;
2020-08-22 18:02:08 +00:00
// Send to client
2020-08-23 00:26:18 +00:00
INITSTRUCT ( sP_FE2CL_REP_NANO_TUNE_SUCC , resp ) ;
2020-10-24 20:28:35 +00:00
resp . iNanoID = skill - > iNanoID ;
resp . iSkillID = skill - > iTuneID ;
2020-09-26 01:48:45 +00:00
resp . iPC_FusionMatter = plr - > fusionmatter ;
2020-10-24 20:28:35 +00:00
resp . aItem [ 9 ] = plr - > Inven [ 0 ] ; // quick fix to make sure item in slot 0 doesn't get yeeted by default
// check if there's any garbage in the item slot array (this'll happen when a nano station isn't used)
for ( int i = 0 ; i < 10 ; i + + ) {
if ( skill - > aiNeedItemSlotNum [ i ] < 0 | | skill - > aiNeedItemSlotNum [ i ] > = AINVEN_COUNT ) {
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_NANO_TUNE_SUCC , sizeof ( sP_FE2CL_REP_NANO_TUNE_SUCC ) ) ;
return ; // stop execution, don't run consumption logic
}
}
if ( plr - > fusionmatter < ( int ) MissionManager : : AvatarGrowth [ plr - > level ] [ " m_iReqBlob_NanoTune " ] ) // sanity check
return ;
plr - > fusionmatter - = ( int ) MissionManager : : AvatarGrowth [ plr - > level ] [ " m_iReqBlob_NanoTune " ] ;
int reqItemCount = NanoTunings [ skill - > iTuneID ] . reqItemCount ;
int reqItemID = NanoTunings [ skill - > iTuneID ] . reqItems ;
int i = 0 ;
while ( reqItemCount > 0 & & i < 10 ) {
sItemBase & item = plr - > Inven [ skill - > aiNeedItemSlotNum [ i ] ] ;
if ( item . iType = = 7 & & item . iID = = reqItemID ) {
if ( item . iOpt > reqItemCount ) {
item . iOpt - = reqItemCount ;
reqItemCount = 0 ;
}
else {
reqItemCount - = item . iOpt ;
item . iID = 0 ;
item . iType = 0 ;
item . iOpt = 0 ;
}
}
i + + ; // next slot
}
resp . iPC_FusionMatter = plr - > fusionmatter ; // update fusion matter in packet
// update items clientside
for ( int i = 0 ; i < 10 ; i + + ) {
if ( skill - > aiNeedItemSlotNum [ i ] ) { // non-zero check
resp . aItem [ i ] = plr - > Inven [ skill - > aiNeedItemSlotNum [ i ] ] ;
resp . aiItemSlotNum [ i ] = skill - > aiNeedItemSlotNum [ i ] ;
}
}
2020-08-22 18:02:08 +00:00
2020-08-22 23:31:09 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_NANO_TUNE_SUCC , sizeof ( sP_FE2CL_REP_NANO_TUNE_SUCC ) ) ;
2020-08-22 18:02:08 +00:00
DEBUGLOG (
2020-10-24 20:28:35 +00:00
std : : cout < < U16toU8 ( plr - > PCStyle . szFirstName ) < < U16toU8 ( plr - > PCStyle . szLastName ) < < " set skill id " < < skill - > iTuneID < < " for nano: " < < skill - > iNanoID < < std : : endl ;
2020-08-22 18:02:08 +00:00
)
}
void NanoManager : : resetNanoSkill ( CNSocket * sock , int16_t nanoId ) {
2020-08-23 03:15:27 +00:00
if ( nanoId > 36 )
return ;
2020-08-24 21:04:56 +00:00
2020-08-24 22:02:07 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-10-05 00:03:13 +00:00
2020-08-24 22:02:07 +00:00
sNano nano = plr - > Nanos [ nanoId ] ;
2020-08-22 18:02:08 +00:00
2020-08-24 21:04:56 +00:00
// 0 is reset
2020-08-22 18:02:08 +00:00
nano . iSkillID = 0 ;
2020-08-24 22:02:07 +00:00
plr - > Nanos [ nanoId ] = nano ;
2020-08-21 00:37:34 +00:00
}
2020-09-15 14:46:52 +00:00
# pragma endregion
2020-09-18 07:10:30 +00:00
2020-09-15 14:46:52 +00:00
# pragma region Active Powers
namespace NanoManager {
2020-09-18 07:10:30 +00:00
2020-09-18 16:37:26 +00:00
bool doDebuff ( CNSocket * sock , int32_t * pktdata , sSkillResult_Damage_N_Debuff * respdata , int i , int32_t iCBFlag , int32_t amount ) {
if ( MobManager : : Mobs . find ( pktdata [ i ] ) = = MobManager : : Mobs . end ( ) ) {
2020-09-15 14:46:52 +00:00
// not sure how to best handle this
std : : cout < < " [WARN] nanoDebuffEnemy: mob ID not found " < < std : : endl ;
return false ;
2020-09-18 07:10:30 +00:00
}
2020-09-18 16:37:26 +00:00
Mob * mob = MobManager : : Mobs [ pktdata [ i ] ] ;
2020-10-05 00:03:13 +00:00
2020-10-17 17:26:09 +00:00
int damage = MobManager : : hitMob ( sock , mob , 0 ) ; // using amount for something else
2020-10-05 00:03:13 +00:00
2020-09-15 14:46:52 +00:00
respdata [ i ] . eCT = 4 ;
2020-09-25 00:00:26 +00:00
respdata [ i ] . iDamage = damage ;
2020-09-18 16:37:26 +00:00
respdata [ i ] . iID = mob - > appearanceData . iNPC_ID ;
respdata [ i ] . iHP = mob - > appearanceData . iHP ;
2020-09-22 20:22:10 +00:00
respdata [ i ] . iConditionBitFlag = mob - > appearanceData . iConditionBitFlag | = iCBFlag ;
2020-10-17 17:26:09 +00:00
mob - > unbuffTimes [ iCBFlag ] = getTime ( ) + amount ;
2020-09-18 16:37:26 +00:00
std : : cout < < ( int ) mob - > appearanceData . iNPC_ID < < " was debuffed " < < std : : endl ;
return true ;
}
bool doBuff ( CNSocket * sock , int32_t * pktdata , sSkillResult_Buff * respdata , int i , int32_t iCBFlag , int32_t amount ) {
if ( MobManager : : Mobs . find ( pktdata [ i ] ) = = MobManager : : Mobs . end ( ) ) {
// not sure how to best handle this
std : : cout < < " [WARN] nanoBuffEnemy: mob ID not found " < < std : : endl ;
return false ;
}
Mob * mob = MobManager : : Mobs [ pktdata [ i ] ] ;
2020-10-17 17:26:09 +00:00
MobManager : : hitMob ( sock , mob , 0 ) ;
2020-10-05 00:03:13 +00:00
2020-09-18 16:37:26 +00:00
respdata [ i ] . eCT = 4 ;
respdata [ i ] . iID = mob - > appearanceData . iNPC_ID ;
2020-09-22 20:22:10 +00:00
respdata [ i ] . iConditionBitFlag = mob - > appearanceData . iConditionBitFlag | = iCBFlag ;
2020-10-17 17:26:09 +00:00
mob - > unbuffTimes [ iCBFlag ] = getTime ( ) + amount ;
2020-09-15 14:46:52 +00:00
2020-09-18 16:37:26 +00:00
std : : cout < < ( int ) mob - > appearanceData . iNPC_ID < < " was debuffed " < < std : : endl ;
2020-09-15 14:46:52 +00:00
return true ;
}
2020-09-18 16:37:26 +00:00
bool doHeal ( CNSocket * sock , int32_t * pktdata , sSkillResult_Heal_HP * respdata , int i , int32_t iCBFlag , int32_t amount ) {
2020-09-15 14:46:52 +00:00
Player * plr = nullptr ;
for ( auto & pair : PlayerManager : : players ) {
if ( pair . second . plr - > iID = = pktdata [ i ] ) {
plr = pair . second . plr ;
break ;
}
2020-09-18 07:10:30 +00:00
}
2020-09-15 14:46:52 +00:00
2020-09-21 16:03:25 +00:00
// player not found
2020-09-15 14:46:52 +00:00
if ( plr = = nullptr )
return false ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
int healedAmount = PC_MAXHEALTH ( plr - > level ) * amount / 100 ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
plr - > HP + = healedAmount ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
if ( plr - > HP > PC_MAXHEALTH ( plr - > level ) )
2020-09-15 14:46:52 +00:00
plr - > HP = PC_MAXHEALTH ( plr - > level ) ;
respdata [ i ] . eCT = 1 ;
respdata [ i ] . iID = plr - > iID ;
respdata [ i ] . iHP = plr - > HP ;
2020-09-29 21:27:48 +00:00
respdata [ i ] . iHealHP = healedAmount ;
2020-10-05 00:03:13 +00:00
2020-09-15 14:46:52 +00:00
std : : cout < < ( int ) plr - > iID < < " was healed " < < std : : endl ;
return true ;
}
2020-10-04 23:54:08 +00:00
bool doGroupHeal ( CNSocket * sock , int32_t * pktdata , sSkillResult_Heal_HP * respdata , int i , int32_t iCBFlag , int32_t amount ) {
Player * plr = nullptr ;
for ( auto & pair : PlayerManager : : players ) {
if ( pair . second . plr - > iID = = pktdata [ 0 ] ) {
plr = pair . second . plr ;
break ;
}
}
// player not found
if ( plr = = nullptr )
return false ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
Player * leader = PlayerManager : : getPlayer ( sock ) ;
// player not found
if ( leader = = nullptr )
return false ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
int healedAmount = PC_MAXHEALTH ( plr - > level ) * amount / 100 ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
leader - > HP + = healedAmount ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( leader - > HP > PC_MAXHEALTH ( leader - > level ) )
leader - > HP = PC_MAXHEALTH ( leader - > level ) ;
respdata [ i ] . eCT = 1 ;
respdata [ i ] . iID = plr - > iID ;
respdata [ i ] . iHP = plr - > HP ;
respdata [ i ] . iHealHP = healedAmount ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
std : : cout < < ( int ) plr - > iID < < " was healed " < < std : : endl ;
return true ;
}
2020-09-18 16:37:26 +00:00
bool doDamage ( CNSocket * sock , int32_t * pktdata , sSkillResult_Damage * respdata , int i , int32_t iCBFlag , int32_t amount ) {
if ( MobManager : : Mobs . find ( pktdata [ i ] ) = = MobManager : : Mobs . end ( ) ) {
2020-09-15 14:46:52 +00:00
// not sure how to best handle this
std : : cout < < " [WARN] nanoDebuffEnemy: mob ID not found " < < std : : endl ;
return false ;
}
2020-09-18 16:37:26 +00:00
Mob * mob = MobManager : : Mobs [ pktdata [ i ] ] ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
if ( plr = = nullptr )
return false ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
int damage = MobManager : : hitMob ( sock , mob , PC_MAXHEALTH ( plr - > level ) * amount / 100 ) ;
2020-09-22 20:22:10 +00:00
2020-09-15 14:46:52 +00:00
respdata [ i ] . eCT = 4 ;
2020-09-25 00:00:26 +00:00
respdata [ i ] . iDamage = damage ;
2020-09-18 16:37:26 +00:00
respdata [ i ] . iID = mob - > appearanceData . iNPC_ID ;
respdata [ i ] . iHP = mob - > appearanceData . iHP ;
2020-09-15 14:46:52 +00:00
2020-09-18 16:37:26 +00:00
std : : cout < < ( int ) mob - > appearanceData . iNPC_ID < < " was damaged " < < std : : endl ;
2020-09-15 14:46:52 +00:00
return true ;
}
/*
* NOTE : Leech is specially encoded .
*
* It manages to fit inside the activePower < > ( ) mold with only a slight hack ,
* but it really is it ' s own thing . There is a hard assumption that players
* will only every leech a single mob , and the sanity check that enforces that
* assumption is critical .
*/
2020-09-18 16:37:26 +00:00
bool doLeech ( CNSocket * sock , int32_t * pktdata , sSkillResult_Heal_HP * healdata , int i , int32_t iCBFlag , int32_t amount ) {
2020-09-15 14:46:52 +00:00
// this sanity check is VERY important
if ( i ! = 0 ) {
std : : cout < < " [WARN] Player attempted to leech more than one mob! " < < std : : endl ;
return false ;
2020-09-18 07:10:30 +00:00
}
2020-09-15 14:46:52 +00:00
sSkillResult_Damage * damagedata = ( sSkillResult_Damage * ) ( ( ( uint8_t * ) healdata ) + sizeof ( sSkillResult_Heal_HP ) ) ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return false ;
2020-09-29 21:27:48 +00:00
int healedAmount = PC_MAXHEALTH ( plr - > level ) * amount / 100 ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
plr - > HP + = healedAmount ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
if ( plr - > HP > PC_MAXHEALTH ( plr - > level ) )
2020-09-15 14:46:52 +00:00
plr - > HP = PC_MAXHEALTH ( plr - > level ) ;
healdata - > eCT = 1 ;
healdata - > iID = plr - > iID ;
healdata - > iHP = plr - > HP ;
2020-09-29 21:27:48 +00:00
healdata - > iHealHP = healedAmount ;
2020-09-15 14:46:52 +00:00
2020-09-18 16:37:26 +00:00
if ( MobManager : : Mobs . find ( pktdata [ i ] ) = = MobManager : : Mobs . end ( ) ) {
2020-09-15 14:46:52 +00:00
// not sure how to best handle this
std : : cout < < " [WARN] doLeech: mob ID not found " < < std : : endl ;
return false ;
}
2020-09-18 16:37:26 +00:00
Mob * mob = MobManager : : Mobs [ pktdata [ i ] ] ;
2020-10-05 00:03:13 +00:00
2020-09-29 21:27:48 +00:00
int damage = MobManager : : hitMob ( sock , mob , PC_MAXHEALTH ( plr - > level ) * amount / 100 ) ;
2020-10-05 00:03:13 +00:00
2020-09-15 14:46:52 +00:00
damagedata - > eCT = 4 ;
2020-09-25 00:00:26 +00:00
damagedata - > iDamage = damage ;
2020-09-18 16:37:26 +00:00
damagedata - > iID = mob - > appearanceData . iNPC_ID ;
damagedata - > iHP = mob - > appearanceData . iHP ;
2020-09-15 14:46:52 +00:00
2020-09-18 16:37:26 +00:00
std : : cout < < ( int ) mob - > appearanceData . iNPC_ID < < " was leeched " < < std : : endl ;
2020-09-15 14:46:52 +00:00
return true ;
2020-09-18 07:10:30 +00:00
}
2020-10-04 23:54:08 +00:00
// XXX: Special flags. This is still pretty dirty.
enum {
NONE ,
LEECH ,
GHEAL
} ;
2020-09-15 14:46:52 +00:00
template < class sPAYLOAD ,
2020-10-04 23:54:08 +00:00
bool ( * work ) ( CNSocket * , int32_t * , sPAYLOAD * , int , int32_t , int32_t ) ,
int specialCase = NONE >
2020-09-15 14:46:52 +00:00
void activePower ( CNSocket * sock , CNPacketData * data ,
2020-09-18 16:37:26 +00:00
int16_t nanoId , int16_t skillId , int16_t eSkillType ,
2020-09-15 14:46:52 +00:00
int32_t iCBFlag , int32_t amount ) {
2020-09-18 07:10:30 +00:00
sP_CL2FE_REQ_NANO_SKILL_USE * pkt = ( sP_CL2FE_REQ_NANO_SKILL_USE * ) data - > buf ;
2020-09-15 14:46:52 +00:00
// validate request check
2020-09-18 07:10:30 +00:00
if ( ! validInVarPacket ( sizeof ( sP_CL2FE_REQ_NANO_SKILL_USE ) , pkt - > iTargetCnt , sizeof ( int32_t ) , data - > size ) ) {
2020-09-15 14:46:52 +00:00
std : : cout < < " [WARN] bad sP_CL2FE_REQ_NANO_SKILL_USE packet size " < < std : : endl ;
2020-09-18 07:10:30 +00:00
return ;
}
int32_t * pktdata = ( int32_t * ) ( ( uint8_t * ) data - > buf + sizeof ( sP_CL2FE_REQ_NANO_SKILL_USE ) ) ;
2020-10-04 23:54:08 +00:00
size_t resplen ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
Player * otherPlr = plr ;
if ( plr = = nullptr )
return ;
// special case since leech is atypically encoded
if constexpr ( specialCase = = LEECH )
resplen = sizeof ( sP_FE2CL_NANO_SKILL_USE_SUCC ) + sizeof ( sSkillResult_Heal_HP ) + sizeof ( sSkillResult_Damage ) ;
else if constexpr ( specialCase = = GHEAL ) {
otherPlr = PlayerManager : : getPlayerFromID ( plr - > iIDGroup ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( otherPlr = = nullptr )
return ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
pkt - > iTargetCnt = otherPlr - > groupCnt ;
2020-10-14 21:15:02 +00:00
resplen = sizeof ( sP_FE2CL_NANO_SKILL_USE_SUCC ) + pkt - > iTargetCnt * sizeof ( sPAYLOAD ) ;
} else
resplen = sizeof ( sP_FE2CL_NANO_SKILL_USE_SUCC ) + pkt - > iTargetCnt * sizeof ( sPAYLOAD ) ;
2020-10-05 00:03:13 +00:00
2020-09-15 14:46:52 +00:00
// validate response packet
if ( ! validOutVarPacket ( sizeof ( sP_FE2CL_NANO_SKILL_USE_SUCC ) , pkt - > iTargetCnt , sizeof ( sPAYLOAD ) ) ) {
std : : cout < < " [WARN] bad sP_FE2CL_NANO_SKILL_USE packet size " < < std : : endl ;
2020-09-18 07:10:30 +00:00
return ;
}
2020-09-15 14:46:52 +00:00
uint8_t respbuf [ CN_PACKET_BUFFER_SIZE ] ;
2020-09-18 07:10:30 +00:00
memset ( respbuf , 0 , resplen ) ;
2020-09-15 14:46:52 +00:00
sP_FE2CL_NANO_SKILL_USE_SUCC * resp = ( sP_FE2CL_NANO_SKILL_USE_SUCC * ) respbuf ;
sPAYLOAD * respdata = ( sPAYLOAD * ) ( respbuf + sizeof ( sP_FE2CL_NANO_SKILL_USE_SUCC ) ) ;
2020-09-28 18:11:13 +00:00
2020-09-26 22:16:15 +00:00
plr - > Nanos [ plr - > activeNano ] . iStamina - = 40 ;
2020-10-04 23:54:08 +00:00
if ( plr - > Nanos [ plr - > activeNano ] . iStamina < 0 )
plr - > Nanos [ plr - > activeNano ] . iStamina = 0 ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
resp - > iPC_ID = plr - > iID ;
resp - > iSkillID = skillId ;
resp - > iNanoID = nanoId ;
2020-09-26 22:16:15 +00:00
resp - > iNanoStamina = plr - > Nanos [ plr - > activeNano ] . iStamina ;
2020-09-18 16:37:26 +00:00
resp - > eST = eSkillType ;
2020-09-18 07:10:30 +00:00
resp - > iTargetCnt = pkt - > iTargetCnt ;
2020-09-15 14:46:52 +00:00
2020-10-04 23:54:08 +00:00
CNSocket * workSock = sock ;
2020-10-05 00:03:13 +00:00
2020-09-15 14:46:52 +00:00
for ( int i = 0 ; i < pkt - > iTargetCnt ; i + + ) {
2020-10-04 23:54:08 +00:00
if constexpr ( specialCase = = GHEAL )
workSock = PlayerManager : : getSockFromID ( otherPlr - > groupIDs [ i ] ) ;
if ( ! work ( workSock , pktdata , respdata , i , iCBFlag , amount ) )
2020-09-15 14:46:52 +00:00
return ;
2020-09-18 07:10:30 +00:00
}
sock - > sendPacket ( ( void * ) & respbuf , P_FE2CL_NANO_SKILL_USE_SUCC , resplen ) ;
2020-09-18 16:37:26 +00:00
PlayerManager : : sendToViewable ( sock , ( void * ) & respbuf , P_FE2CL_NANO_SKILL_USE , resplen ) ;
2020-09-18 07:10:30 +00:00
}
2020-09-15 14:46:52 +00:00
// active nano power dispatch table
std : : vector < ActivePower > ActivePowers = {
2020-10-17 17:26:09 +00:00
ActivePower ( StunPowers , activePower < sSkillResult_Damage_N_Debuff , doDebuff > , EST_STUN , CSB_BIT_STUN , 2250 ) ,
2020-10-21 05:24:51 +00:00
ActivePower ( HealPowers , activePower < sSkillResult_Heal_HP , doHeal > , EST_HEAL_HP , CSB_BIT_NONE , 35 ) ,
ActivePower ( GroupHealPowers , activePower < sSkillResult_Heal_HP , doGroupHeal , GHEAL > , EST_HEAL_HP , CSB_BIT_NONE , 20 ) ,
2020-09-15 14:46:52 +00:00
// TODO: Recall
2020-10-17 17:26:09 +00:00
ActivePower ( DrainPowers , activePower < sSkillResult_Buff , doBuff > , EST_BOUNDINGBALL , CSB_BIT_BOUNDINGBALL , 3000 ) ,
ActivePower ( SnarePowers , activePower < sSkillResult_Damage_N_Debuff , doDebuff > , EST_SNARE , CSB_BIT_DN_MOVE_SPEED , 4500 ) ,
2020-09-29 21:27:48 +00:00
ActivePower ( DamagePowers , activePower < sSkillResult_Damage , doDamage > , EST_DAMAGE , CSB_BIT_NONE , 12 ) ,
2020-10-04 23:54:08 +00:00
ActivePower ( LeechPowers , activePower < sSkillResult_Heal_HP , doLeech , LEECH > , EST_BLOODSUCKING , CSB_BIT_NONE , 18 ) ,
2020-10-17 17:26:09 +00:00
ActivePower ( SleepPowers , activePower < sSkillResult_Damage_N_Debuff , doDebuff > , EST_SLEEP , CSB_BIT_MEZ , 4500 ) ,
2020-09-15 14:46:52 +00:00
} ;
} ; // namespace
# pragma endregion
# pragma region Passive Powers
2020-10-04 23:54:08 +00:00
void NanoManager : : nanoBuff ( CNSocket * sock , int16_t nanoId , int skillId , int16_t eSkillType , int32_t iCBFlag , int16_t eCharStatusTimeBuffID , int16_t iValue , bool groupPower ) {
2020-09-18 07:10:30 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-10-19 17:26:14 +00:00
2020-10-04 23:54:08 +00:00
int pktCnt = 1 ;
2020-10-09 00:01:35 +00:00
Player * leader = plr ;
plr - > iConditionBitFlag | = iCBFlag ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( groupPower ) {
plr - > iGroupConditionBitFlag | = iCBFlag ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( plr - > iID ! = plr - > iIDGroup )
leader = PlayerManager : : getPlayerFromID ( plr - > iIDGroup ) ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( leader = = nullptr )
return ;
2020-10-19 17:26:14 +00:00
2020-10-05 00:03:13 +00:00
pktCnt = leader - > groupCnt ;
2020-10-09 00:01:35 +00:00
}
2020-09-28 18:11:13 +00:00
2020-10-09 00:01:35 +00:00
if ( leader = = nullptr )
return ;
2020-10-19 17:26:14 +00:00
2020-10-04 23:54:08 +00:00
if ( ! validOutVarPacket ( sizeof ( sP_FE2CL_NANO_SKILL_USE ) , pktCnt , sizeof ( sSkillResult_Buff ) ) ) {
2020-09-18 07:10:30 +00:00
std : : cout < < " [WARN] bad sP_FE2CL_NANO_SKILL_USE packet size \n " ;
return ;
}
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
size_t resplen = sizeof ( sP_FE2CL_NANO_SKILL_USE ) + pktCnt * sizeof ( sSkillResult_Buff ) ;
2020-09-15 14:46:52 +00:00
uint8_t respbuf [ CN_PACKET_BUFFER_SIZE ] ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
memset ( respbuf , 0 , resplen ) ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
sP_FE2CL_NANO_SKILL_USE * resp = ( sP_FE2CL_NANO_SKILL_USE * ) respbuf ;
sSkillResult_Buff * respdata = ( sSkillResult_Buff * ) ( respbuf + sizeof ( sP_FE2CL_NANO_SKILL_USE ) ) ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
resp - > iPC_ID = plr - > iID ;
resp - > iSkillID = skillId ;
resp - > iNanoID = nanoId ;
2020-09-26 22:16:15 +00:00
resp - > iNanoStamina = plr - > Nanos [ plr - > activeNano ] . iStamina ;
2020-09-15 14:46:52 +00:00
resp - > eST = eSkillType ;
2020-10-04 23:54:08 +00:00
resp - > iTargetCnt = pktCnt ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
int bitFlag = GroupManager : : getGroupFlags ( leader ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
for ( int i = 0 ; i < pktCnt ; i + + ) {
Player * varPlr ;
CNSocket * sockTo ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( plr - > iID = = leader - > groupIDs [ i ] ) {
varPlr = plr ;
sockTo = sock ;
} else {
varPlr = PlayerManager : : getPlayerFromID ( leader - > groupIDs [ i ] ) ;
sockTo = PlayerManager : : getSockFromID ( leader - > groupIDs [ i ] ) ;
}
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( varPlr = = nullptr | | sockTo = = nullptr )
2020-10-09 00:01:35 +00:00
continue ;
2020-10-19 17:26:14 +00:00
2020-09-18 07:10:30 +00:00
respdata [ i ] . eCT = 1 ;
2020-10-04 23:54:08 +00:00
respdata [ i ] . iID = varPlr - > iID ;
2020-09-18 07:10:30 +00:00
respdata [ i ] . iConditionBitFlag = iCBFlag ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
INITSTRUCT ( sP_FE2CL_PC_BUFF_UPDATE , pkt1 ) ;
2020-10-19 17:26:14 +00:00
pkt1 . eCSTB = eCharStatusTimeBuffID ; // eCharStatusTimeBuffID
pkt1 . eTBU = 1 ; // eTimeBuffUpdate
pkt1 . eTBT = 1 ; // eTimeBuffType 1 means nano
2020-10-09 00:01:35 +00:00
pkt1 . iConditionBitFlag = bitFlag | varPlr - > iConditionBitFlag ;
2020-10-05 00:03:13 +00:00
2020-09-18 07:10:30 +00:00
if ( iValue > 0 )
pkt1 . TimeBuff . iValue = iValue ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
sockTo - > sendPacket ( ( void * ) & pkt1 , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
2020-09-18 07:10:30 +00:00
}
sock - > sendPacket ( ( void * ) & respbuf , P_FE2CL_NANO_SKILL_USE_SUCC , resplen ) ;
2020-09-18 16:37:26 +00:00
PlayerManager : : sendToViewable ( sock , ( void * ) & respbuf , P_FE2CL_NANO_SKILL_USE , resplen ) ;
2020-09-18 07:10:30 +00:00
}
2020-10-04 23:54:08 +00:00
void NanoManager : : nanoUnbuff ( CNSocket * sock , int32_t iCBFlag , int16_t eCharStatusTimeBuffID , int16_t iValue , bool groupPower ) {
2020-09-18 07:10:30 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
if ( plr = = nullptr )
return ;
2020-10-19 17:26:14 +00:00
2020-10-04 23:54:08 +00:00
int pktCnt = 1 ;
2020-10-09 00:01:35 +00:00
Player * leader = plr ;
plr - > iConditionBitFlag & = ~ iCBFlag ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( groupPower ) {
plr - > iGroupConditionBitFlag & = ~ iCBFlag ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( plr - > iID ! = plr - > iIDGroup )
leader = PlayerManager : : getPlayerFromID ( plr - > iIDGroup ) ;
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( leader = = nullptr )
return ;
2020-10-19 17:26:14 +00:00
2020-10-05 00:03:13 +00:00
pktCnt = leader - > groupCnt ;
2020-10-09 00:01:35 +00:00
}
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
int bitFlag = GroupManager : : getGroupFlags ( leader ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
for ( int i = 0 ; i < pktCnt ; i + + ) {
Player * varPlr ;
CNSocket * sockTo ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( plr - > iID = = leader - > groupIDs [ i ] ) {
varPlr = plr ;
sockTo = sock ;
} else {
varPlr = PlayerManager : : getPlayerFromID ( leader - > groupIDs [ i ] ) ;
sockTo = PlayerManager : : getSockFromID ( leader - > groupIDs [ i ] ) ;
}
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
INITSTRUCT ( sP_FE2CL_PC_BUFF_UPDATE , resp1 ) ;
2020-10-19 17:26:14 +00:00
resp1 . eCSTB = eCharStatusTimeBuffID ; // eCharStatusTimeBuffID
resp1 . eTBU = 2 ; // eTimeBuffUpdate
resp1 . eTBT = 1 ; // eTimeBuffType 1 means nano
2020-10-09 00:01:35 +00:00
resp1 . iConditionBitFlag = bitFlag | varPlr - > iConditionBitFlag ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
if ( iValue > 0 )
resp1 . TimeBuff . iValue = iValue ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
sockTo - > sendPacket ( ( void * ) & resp1 , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
}
2020-09-18 07:10:30 +00:00
}
2020-09-25 05:35:27 +00:00
// 0=A 1=B 2=C -1=Not found
int NanoManager : : nanoStyle ( int nanoId ) {
2020-10-09 00:01:35 +00:00
if ( nanoId < 1 | | nanoId > = ( int ) NanoTable . size ( ) )
2020-09-25 05:35:27 +00:00
return - 1 ;
return NanoTable [ nanoId ] . style ;
}
2020-09-18 16:37:26 +00:00
namespace NanoManager {
std : : vector < PassivePower > PassivePowers = {
2020-10-21 15:04:20 +00:00
PassivePower ( ScavengePowers , EST_REWARDBLOB , CSB_BIT_REWARD_BLOB , ECSB_REWARD_BLOB , 0 , false ) ,
2020-10-04 23:54:08 +00:00
PassivePower ( RunPowers , EST_RUN , CSB_BIT_UP_MOVE_SPEED , ECSB_UP_MOVE_SPEED , 200 , false ) ,
PassivePower ( GroupRunPowers , EST_RUN , CSB_BIT_UP_MOVE_SPEED , ECSB_UP_MOVE_SPEED , 200 , true ) ,
PassivePower ( BonusPowers , EST_REWARDCASH , CSB_BIT_REWARD_CASH , ECSB_REWARD_CASH , 0 , false ) ,
PassivePower ( GuardPowers , EST_PROTECTBATTERY , CSB_BIT_PROTECT_BATTERY , ECSB_PROTECT_BATTERY , 0 , false ) ,
PassivePower ( RadarPowers , EST_MINIMAPENEMY , CSB_BIT_MINIMAP_ENEMY , ECSB_MINIMAP_ENEMY , 0 , false ) ,
PassivePower ( AntidotePowers , EST_PROTECTINFECTION , CSB_BIT_PROTECT_INFECTION , ECSB_PROTECT_INFECTION , 0 , false ) ,
PassivePower ( FreedomPowers , EST_FREEDOM , CSB_BIT_FREEDOM , ECSB_FREEDOM , 0 , false ) ,
PassivePower ( GroupFreedomPowers , EST_FREEDOM , CSB_BIT_FREEDOM , ECSB_FREEDOM , 0 , true ) ,
PassivePower ( JumpPowers , EST_JUMP , CSB_BIT_UP_JUMP_HEIGHT , ECSB_UP_JUMP_HEIGHT , 400 , false ) ,
PassivePower ( GroupJumpPowers , EST_JUMP , CSB_BIT_UP_JUMP_HEIGHT , ECSB_UP_JUMP_HEIGHT , 400 , true ) ,
PassivePower ( SelfRevivePowers , EST_PHOENIX , CSB_BIT_PHOENIX , ECSB_PHOENIX , 0 , false ) ,
PassivePower ( SneakPowers , EST_STEALTH , CSB_BIT_UP_STEALTH , ECSB_UP_STEALTH , 0 , false ) ,
PassivePower ( GroupSneakPowers , EST_STEALTH , CSB_BIT_UP_STEALTH , ECSB_UP_STEALTH , 0 , true ) ,
PassivePower ( TreasureFinderPowers , EST_MINIMAPTRESURE , CSB_BIT_MINIMAP_TRESURE , ECSB_MINIMAP_TRESURE , 0 , false ) ,
2020-09-18 16:37:26 +00:00
} ;
} ; // namespace
2020-10-04 23:54:08 +00:00
void NanoManager : : revivePlayer ( Player * plr ) {
CNSocket * sock = PlayerManager : : getSockFromID ( plr - > iID ) ;
INITSTRUCT ( sP_FE2CL_REP_PC_REGEN_SUCC , response ) ;
INITSTRUCT ( sP_FE2CL_PC_REGEN , resp2 ) ;
plr - > HP = PC_MAXHEALTH ( plr - > level ) ;
2020-10-05 00:03:13 +00:00
2020-10-04 23:54:08 +00:00
// Nanos
int activeSlot = - 1 ;
2020-10-09 00:01:35 +00:00
for ( int i = 0 ; i < 3 ; i + + ) {
int nanoID = plr - > equippedNanos [ i ] ;
2020-10-04 23:54:08 +00:00
if ( plr - > activeNano = = nanoID ) {
2020-10-09 00:01:35 +00:00
activeSlot = i ;
2020-10-04 23:54:08 +00:00
}
2020-10-09 00:01:35 +00:00
response . PCRegenData . Nanos [ i ] = plr - > Nanos [ nanoID ] ;
2020-10-04 23:54:08 +00:00
}
// Response parameters
response . PCRegenData . iActiveNanoSlotNum = activeSlot ;
response . PCRegenData . iX = plr - > x ;
response . PCRegenData . iY = plr - > y ;
response . PCRegenData . iZ = plr - > z ;
response . PCRegenData . iHP = plr - > HP ;
response . iFusionMatter = plr - > fusionmatter ;
response . bMoveLocation = 0 ;
response . PCRegenData . iMapNum = 0 ;
sock - > sendPacket ( ( void * ) & response , P_FE2CL_REP_PC_REGEN_SUCC , sizeof ( sP_FE2CL_REP_PC_REGEN_SUCC ) ) ;
// Update other players
resp2 . PCRegenDataForOtherPC . iPC_ID = plr - > iID ;
resp2 . PCRegenDataForOtherPC . iX = plr - > x ;
resp2 . PCRegenDataForOtherPC . iY = plr - > y ;
resp2 . PCRegenDataForOtherPC . iZ = plr - > z ;
resp2 . PCRegenDataForOtherPC . iHP = plr - > HP ;
resp2 . PCRegenDataForOtherPC . iAngle = plr - > angle ;
resp2 . PCRegenDataForOtherPC . Nano = plr - > Nanos [ plr - > activeNano ] ;
PlayerManager : : sendToViewable ( sock , ( void * ) & resp2 , P_FE2CL_PC_REGEN , sizeof ( sP_FE2CL_PC_REGEN ) ) ;
}
2020-10-09 00:01:35 +00:00
void NanoManager : : nanoChangeBuff ( CNSocket * sock , Player * plr , int32_t cbFrom , int32_t cbTo ) {
bool sentPacket = false ;
INITSTRUCT ( sP_FE2CL_PC_BUFF_UPDATE , resp ) ;
resp . eTBU = 3 ;
resp . eTBT = 1 ;
resp . iConditionBitFlag = cbTo ;
2020-10-19 17:26:14 +00:00
if ( ! ( cbFrom & CSB_BIT_UP_MOVE_SPEED ) & & ( cbTo & CSB_BIT_UP_MOVE_SPEED ) ) {
2020-10-09 00:01:35 +00:00
resp . eCSTB = ECSB_UP_MOVE_SPEED ;
resp . eTBU = 1 ;
resp . TimeBuff . iValue = 200 ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
sentPacket = true ;
} else if ( ( cbFrom & CSB_BIT_UP_MOVE_SPEED ) & & ! ( cbTo & CSB_BIT_UP_MOVE_SPEED ) ) {
resp . eCSTB = ECSB_UP_MOVE_SPEED ;
resp . eTBU = 2 ;
resp . TimeBuff . iValue = 200 ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
sentPacket = true ;
}
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( ! ( cbFrom & CSB_BIT_UP_JUMP_HEIGHT ) & & ( cbTo & CSB_BIT_UP_JUMP_HEIGHT ) ) {
resp . eCSTB = ECSB_UP_JUMP_HEIGHT ;
resp . eTBU = 1 ;
resp . TimeBuff . iValue = 400 ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
sentPacket = true ;
} else if ( ( cbFrom & CSB_BIT_UP_JUMP_HEIGHT ) & & ! ( cbTo & CSB_BIT_UP_JUMP_HEIGHT ) ) {
resp . eCSTB = ECSB_UP_JUMP_HEIGHT ;
resp . eTBU = 2 ;
resp . TimeBuff . iValue = 400 ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
sentPacket = true ;
}
2020-10-19 17:26:14 +00:00
2020-10-09 00:01:35 +00:00
if ( ! sentPacket )
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_PC_BUFF_UPDATE , sizeof ( sP_FE2CL_PC_BUFF_UPDATE ) ) ;
}
2020-08-23 00:52:54 +00:00
# pragma endregion