2019-07-07 20:56:15 +00:00
# include <StdAfx.h>
2018-04-27 21:03:39 -07:00
# include "easylogging++.h"
2018-05-19 00:03:18 -07:00
# include "InferredPortalData.h"
2018-03-29 17:01:57 -04:00
# include "Client.h"
# include "ClientEvents.h"
# include "Config.h"
2018-06-23 18:10:44 +01:00
# include <chrono>
2018-03-29 17:01:57 -04:00
// Network access
# include "Network.h"
# include "PacketController.h"
# include "BinaryReader.h"
# include "BinaryWriter.h"
// Database access
# include "Database.h"
# include "Database2.h"
# include "DatabaseIO.h"
# include "WeenieFactory.h"
// World access
# include "World.h"
// Player access
# include "WeenieObject.h"
# include "Monster.h"
# include "Player.h"
// Command access
# include "ClientCommands.h"
# include "ChatMsgs.h"
# include "AllegianceManager.h"
2018-05-19 00:03:18 -07:00
# include "Util.h"
2019-04-13 18:18:16 +00:00
# include "House.h"
2019-07-07 20:56:15 +00:00
# include "HouseManager.h"
2018-03-29 17:01:57 -04:00
// CClient - for client/server interaction
CClient : : CClient ( SOCKADDR_IN * peer , WORD slot , AccountInformation_t & accountInfo )
{
memcpy ( & m_vars . addr , peer , sizeof ( SOCKADDR_IN ) ) ;
m_AccountInfo = accountInfo ;
m_vars . slot = slot ;
m_vars . account = accountInfo . username ;
m_pPC = new CPacketController ( this ) ;
m_pEvents = new CClientEvents ( this ) ;
}
CClient : : ~ CClient ( )
{
SafeDelete ( m_pEvents ) ;
SafeDelete ( m_pPC ) ;
}
void CClient : : IncomingBlob ( BlobPacket_s * blob , double recvTime )
{
if ( ! IsAlive ( ) )
return ;
m_pPC - > IncomingBlob ( blob , recvTime ) ;
}
void CClient : : Think ( )
{
if ( ! IsAlive ( ) )
return ;
WorldThink ( ) ;
m_pPC - > Think ( ) ;
// packet control can signal to kill
if ( ! m_pPC - > IsAlive ( ) )
Kill ( __FILE__ , __LINE__ ) ;
}
void CClient : : ThinkOutbound ( )
{
if ( ! IsAlive ( ) )
return ;
2019-02-26 22:24:48 +00:00
if ( m_pPC & & m_pPC - > IsAlive ( ) )
2018-03-29 17:01:57 -04:00
{
m_pPC - > ThinkOutbound ( ) ;
}
}
void CClient : : WorldThink ( )
{
if ( ! m_vars . bInWorld )
{
if ( m_vars . bNeedChars )
{
UpdateLoginScreen ( ) ;
m_vars . bNeedChars = false ;
}
}
m_pEvents - > Think ( ) ;
}
const AccountInformation_t & CClient : : GetAccountInfo ( )
{
return m_AccountInfo ;
}
const std : : list < CharacterDesc_t > & CClient : : GetCharacters ( )
{
return m_Characters ;
}
2019-07-07 20:56:15 +00:00
bool CClient : : HasCharacter ( uint32_t character_weenie_id )
2018-03-29 17:01:57 -04:00
{
for ( auto & character : m_Characters )
{
if ( character . weenie_id = = character_weenie_id )
return true ;
}
return false ;
}
2019-07-07 20:56:15 +00:00
uint32_t CClient : : IncCharacterInstanceTS ( uint32_t character_weenie_id )
2018-03-29 17:01:57 -04:00
{
WORD newInstanceTS = 0 ;
// just make this work
m_Characters = g_pDBIO - > GetCharacterList ( m_AccountInfo . id ) ;
for ( auto & character : m_Characters )
{
if ( character . weenie_id = = character_weenie_id )
{
newInstanceTS = character . instance_ts + 1 ;
g_pDBIO - > SetCharacterInstanceTS ( character . weenie_id , newInstanceTS ) ;
}
}
// just make this work
m_Characters = g_pDBIO - > GetCharacterList ( m_AccountInfo . id ) ;
return newInstanceTS ;
}
2020-08-07 10:58:05 -07:00
bool CClient : : RemoveCharacterGag ( unsigned int character_id )
{
for ( auto & character : m_Characters )
{
if ( character . weenie_id = = character_id )
{
character . gag_timer = 0 ;
}
}
for ( auto & character : m_CharactersSent )
{
if ( character . weenie_id = = character_id )
{
character . gag_timer = 0 ;
}
}
return false ;
}
bool CClient : : IsCharacterGagged ( unsigned int character_id )
{
for ( auto & character : m_Characters )
{
if ( character . weenie_id = = character_id & & character . gag_timer ! = 0 )
{
return true ;
}
}
return false ;
}
2018-03-29 17:01:57 -04:00
void CClient : : UpdateLoginScreen ( )
{
m_CharactersSent = m_Characters = g_pDBIO - > GetCharacterList ( m_AccountInfo . id ) ;
BinaryWriter CharacterList ;
2019-07-07 20:56:15 +00:00
CharacterList . Write < uint32_t > ( 0xF658 ) ;
CharacterList . Write < uint32_t > ( 0 ) ; // check what this is
CharacterList . Write < uint32_t > ( m_Characters . size ( ) ) ;
2018-03-29 17:01:57 -04:00
for ( auto & character : m_Characters )
{
2019-07-07 20:56:15 +00:00
CharacterList . Write < uint32_t > ( character . weenie_id ) ;
2018-03-29 17:01:57 -04:00
CharacterList . WriteString ( character . name ) ;
2019-11-23 20:34:53 +00:00
CharacterList . Write < uint32_t > ( character . ts_deleted ) ;
2018-03-29 17:01:57 -04:00
}
2019-07-07 20:56:15 +00:00
CharacterList . Write < uint32_t > ( 0 ) ;
CharacterList . Write < uint32_t > ( 11 ) ; // max characters I'm assuming
2018-03-29 17:01:57 -04:00
CharacterList . WriteString ( m_AccountInfo . username ) ;
2019-07-07 20:56:15 +00:00
CharacterList . Write < uint32_t > ( 1 ) ; // what are these
CharacterList . Write < uint32_t > ( 1 ) ; // what are these
2018-03-29 17:01:57 -04:00
SendNetMessage ( CharacterList . GetData ( ) , CharacterList . GetSize ( ) , PRIVATE_MSG ) ;
BinaryWriter ServerName ;
2019-07-07 20:56:15 +00:00
ServerName . Write < uint32_t > ( 0xF7E1 ) ;
ServerName . Write < uint32_t > ( g_pWorld - > GetNumPlayers ( ) ) ; // num connections
ServerName . Write < uint32_t > ( - 1 ) ; // Max connections
2018-03-29 17:01:57 -04:00
ServerName . WriteString ( g_pConfig - > WorldName ( ) ) ;
SendNetMessage ( ServerName . GetData ( ) , ServerName . GetSize ( ) , PRIVATE_MSG ) ;
BinaryWriter DDD_InterrogationMessage ;
2019-07-07 20:56:15 +00:00
DDD_InterrogationMessage . Write < uint32_t > ( 0xF7E5 ) ;
DDD_InterrogationMessage . Write < uint32_t > ( 1 ) ; // servers region
DDD_InterrogationMessage . Write < uint32_t > ( 1 ) ; // name rule language
DDD_InterrogationMessage . Write < uint32_t > ( 1 ) ; // product id
DDD_InterrogationMessage . Write < uint32_t > ( 2 ) ; // supports languages (2)
DDD_InterrogationMessage . Write < uint32_t > ( 0 ) ; // language #1
DDD_InterrogationMessage . Write < uint32_t > ( 1 ) ; // language #2
2018-03-29 17:01:57 -04:00
SendNetMessage ( DDD_InterrogationMessage . GetData ( ) , DDD_InterrogationMessage . GetSize ( ) , EVENT_MSG ) ;
}
void CClient : : EnterWorld ( )
{
2019-07-07 20:56:15 +00:00
uint32_t EnterWorld = 0xF7DF ; // 0xF7C7;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
SendNetMessage ( & EnterWorld , sizeof ( uint32_t ) , 9 ) ;
2018-04-27 21:03:39 -07:00
SERVER_INFO < < " Client " < < m_vars . slot < < " is entering the world. " ;
2018-03-29 17:01:57 -04:00
m_vars . bInWorld = TRUE ;
BinaryWriter setChatChannels ;
2019-07-07 20:56:15 +00:00
setChatChannels . Write < uint32_t > ( 0x295 ) ;
setChatChannels . Write < uint32_t > ( Allegiance_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( General_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( Trade_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( LFG_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( Roleplay_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( Olthoi_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( Society_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( SocietyCelHan_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( SocietyEldWeb_ChatChannel ) ;
setChatChannels . Write < uint32_t > ( SocietyRadBlo_ChatChannel ) ;
2018-03-29 17:01:57 -04:00
SendNetMessage ( & setChatChannels , PRIVATE_MSG , FALSE , FALSE ) ;
}
void CClient : : ExitWorld ( )
{
2019-07-07 20:56:15 +00:00
uint32_t ExitWorld = 0xF653 ;
SendNetMessage ( & ExitWorld , sizeof ( uint32_t ) , PRIVATE_MSG ) ;
2018-04-27 21:03:39 -07:00
SERVER_INFO < < " Client " < < m_vars . slot < < " is exiting the world. " ;
2018-03-29 17:01:57 -04:00
m_pPC - > ResetEvent ( ) ;
UpdateLoginScreen ( ) ;
m_vars . bInWorld = FALSE ;
}
2019-05-12 09:21:34 -07:00
void CClient : : SendNetMessage ( BinaryWriter * pMessage , WORD group , BOOL event , BOOL del , bool ephemeral )
2018-03-29 17:01:57 -04:00
{
if ( ! pMessage )
return ;
2019-05-12 09:21:34 -07:00
SendNetMessage ( pMessage - > GetData ( ) , pMessage - > GetSize ( ) , group , event , del , ephemeral ) ;
2018-03-29 17:01:57 -04:00
if ( del )
delete pMessage ;
}
2019-07-07 20:56:15 +00:00
void CClient : : SendNetMessage ( void * data , uint32_t length , WORD group , BOOL game_event , BOOL del , bool ephemeral )
2018-03-29 17:01:57 -04:00
{
if ( ! IsAlive ( ) )
return ;
if ( ! data | | ! length )
return ;
2019-05-12 09:21:34 -07:00
m_pPC - > QueueNetMessage ( data , length , group , game_event ? GetEvents ( ) - > GetPlayerID ( ) : 0 , ephemeral ) ;
2018-03-29 17:01:57 -04:00
}
2018-05-19 00:03:18 -07:00
BOOL CClient : : CheckBadName ( const std : : string name )
{
string ps = name ;
std : : transform ( ps . begin ( ) , ps . end ( ) , ps . begin ( ) , : : tolower ) ;
ps = ReplaceInString ( ps , " " , " " ) ;
2018-07-12 23:21:30 +00:00
ps = ReplaceInString ( ps , " - " , " " ) ;
ps = ReplaceInString ( ps , " ' " , " " ) ;
ps = ReplaceInString ( ps , " \" " , " " ) ;
2018-05-19 00:03:18 -07:00
2019-07-07 20:56:15 +00:00
for ( auto const & value : g_pPortalDataEx - > GetBannedwords ( ) )
2018-05-19 00:03:18 -07:00
{
if ( ps . find ( value ) ! = std : : string : : npos )
return false ;
}
return true ;
}
2018-03-29 17:01:57 -04:00
BOOL CClient : : CheckNameValidity ( const char * name , int access , std : : string & resultName )
{
resultName = " " ;
if ( ! strncmp ( name , " Contributor " , strlen ( " Contributor " ) ) )
{
if ( access > = ADVOCATE_ACCESS )
{
resultName = " +Contributor " ;
name + = strlen ( " Contributor " ) ;
}
else
return FALSE ;
}
int len = ( int ) strlen ( name ) ;
if ( ( len < 3 ) | | ( len > 32 ) )
return FALSE ;
int i = 0 ;
while ( i < len )
{
char letter = name [ i ] ;
if ( ! ( letter > = ' A ' & & letter < = ' Z ' ) & & ! ( letter > = ' a ' | | letter < = ' z ' ) & & ! ( letter = = ' \' ' ) & & ! ( letter = = ' ' ) & & ! ( letter = = ' - ' ) )
break ;
i + + ;
}
if ( i = = len )
{
resultName + = name ;
return TRUE ;
}
return FALSE ;
}
void CClient : : DeleteCharacter ( BinaryReader * pReader )
{
std : : string account_name = pReader - > ReadString ( ) ; // account
if ( strcmp ( account_name . c_str ( ) , m_vars . account . c_str ( ) ) )
return ;
int slot = pReader - > Read < int > ( ) ;
if ( slot < 0 | | slot > = m_Characters . size ( ) | | slot > = m_CharactersSent . size ( ) )
return ; // out of range
auto entry = m_CharactersSent . begin ( ) ;
std : : advance ( entry , slot ) ;
2019-05-28 14:45:19 +00:00
std : : list < CharacterDesc_t > friendsof = g_pDBIO - > GetFriendsOf ( entry - > weenie_id ) ;
for ( auto it : friendsof )
{
CPlayerWeenie * myfriend = g_pWorld - > FindPlayer ( it . weenie_id ) ;
if ( myfriend )
{
myfriend - > RemoveFriend ( entry - > weenie_id ) ;
}
}
2019-11-23 20:34:53 +00:00
g_pDBIO - > DeleteCharFriends ( entry - > weenie_id ) ;
2019-05-28 14:45:19 +00:00
2018-03-29 17:01:57 -04:00
g_pAllegianceManager - > BreakAllAllegiance ( entry - > weenie_id ) ;
2019-04-13 18:18:16 +00:00
g_pHouseManager - > RemoveHouseFromAccount ( entry - > weenie_id ) ;
2018-03-29 17:01:57 -04:00
g_pDBIO - > DeleteCharacter ( entry - > weenie_id ) ;
2019-11-23 20:34:53 +00:00
UpdateLoginScreen ( ) ;
}
void CClient : : RestoreCharacter ( BinaryReader * pReader )
{
uint32_t character_id = pReader - > Read < uint32_t > ( ) ;
if ( ! HasCharacter ( character_id ) )
{
m_pPC - > EvilClient ( NULL , NULL , true ) ;
}
if ( ! g_pDBIO - > IsCharacterDeleting ( character_id ) )
{
m_pPC - > EvilClient ( NULL , NULL , true ) ;
}
g_pDBIO - > RestoreCharacter ( character_id ) ;
UpdateLoginScreen ( ) ;
2018-03-29 17:01:57 -04:00
}
void CClient : : CreateCharacter ( BinaryReader * pReader )
{
2019-07-07 20:56:15 +00:00
auto badData = [ & ] ( uint32_t err = CG_VERIFICATION_RESPONSE_CORRUPT )
{
BinaryWriter response ;
response . Write < uint32_t > ( 0xF643 ) ;
response . Write < uint32_t > ( err ) ;
SendNetMessage ( response . GetData ( ) , response . GetSize ( ) , PRIVATE_MSG ) ;
} ;
//uint32_t errorCode = CG_VERIFICATION_RESPONSE_CORRUPT;
2018-03-29 17:01:57 -04:00
std : : string account_name = pReader - > ReadString ( ) ;
if ( strcmp ( account_name . c_str ( ) , m_vars . account . c_str ( ) ) )
return ;
ACCharGenResult cg ;
cg . UnPack ( pReader ) ;
std : : string resultName ;
if ( pReader - > GetLastError ( ) )
2019-07-07 20:56:15 +00:00
{
badData ( ) ;
return ;
}
2018-03-29 17:01:57 -04:00
cg . strength = max ( min ( cg . strength , 100 ) , 10 ) ;
cg . endurance = max ( min ( cg . endurance , 100 ) , 10 ) ;
cg . coordination = max ( min ( cg . coordination , 100 ) , 10 ) ;
cg . quickness = max ( min ( cg . quickness , 100 ) , 10 ) ;
cg . focus = max ( min ( cg . focus , 100 ) , 10 ) ;
cg . self = max ( min ( cg . self , 100 ) , 10 ) ;
int totalAttribs = cg . strength + cg . endurance + cg . coordination + cg . quickness + cg . focus + cg . self ;
if ( totalAttribs > 330 )
{
2019-07-07 20:56:15 +00:00
badData ( ) ;
return ;
2018-03-29 17:01:57 -04:00
}
//if (cg.heritageGroup <= 0 || cg.heritageGroup >= 14)
2018-11-15 20:53:36 -06:00
if ( cg . heritageGroup < = 0 | | cg . heritageGroup > = 12 & & ! g_pConfig - > AllowOlthoi ( ) )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
badData ( ) ;
2018-03-29 17:01:57 -04:00
BinaryWriter popupString ;
2019-07-07 20:56:15 +00:00
popupString . Write < uint32_t > ( 4 ) ;
2018-03-29 22:32:36 -07:00
popupString . WriteString ( " No Olthoi at this time. " ) ;
2018-03-29 17:01:57 -04:00
SendNetMessage ( & popupString , PRIVATE_MSG , FALSE , FALSE ) ;
return ;
}
if ( cg . gender < 0 | | cg . gender > = 3 ) // allow invalid gender? not sure
{
2019-07-07 20:56:15 +00:00
badData ( ) ;
return ;
2018-03-29 17:01:57 -04:00
}
SkillTable * pSkillTable = SkillSystem : : GetSkillTable ( ) ;
int numCreditsUsed = 0 ;
cg . numSkills = max ( 0 , min ( 100 , cg . numSkills ) ) ;
ACCharGenData * cgd = CachedCharGenData ;
assert ( cgd ! = NULL ) ;
HeritageGroup_CG * heritageGroup = cgd - > mHeritageGroupList . lookup ( cg . heritageGroup ) ;
Sex_CG * scg = NULL ;
2019-07-07 20:56:15 +00:00
for ( uint32_t i = 0 ; i < cg . numSkills ; i + + )
2018-03-29 17:01:57 -04:00
{
switch ( cg . skillAdvancementClasses [ i ] )
{
case SKILL_ADVANCEMENT_CLASS : : UNDEF_SKILL_ADVANCEMENT_CLASS :
case SKILL_ADVANCEMENT_CLASS : : UNTRAINED_SKILL_ADVANCEMENT_CLASS :
case SKILL_ADVANCEMENT_CLASS : : TRAINED_SKILL_ADVANCEMENT_CLASS :
case SKILL_ADVANCEMENT_CLASS : : SPECIALIZED_SKILL_ADVANCEMENT_CLASS :
break ;
default :
2019-07-07 20:56:15 +00:00
badData ( ) ;
return ;
2018-03-29 17:01:57 -04:00
}
2018-03-29 22:32:36 -07:00
const SkillBase * pSkillBase = pSkillTable - > GetSkillBaseRaw ( SkillTable : : OldToNewSkill ( ( STypeSkill ) i ) ) ;
2018-03-29 17:01:57 -04:00
if ( pSkillBase ! = NULL )
{
//first we check our heritage specific skill costs.
bool found = false ;
2019-07-07 20:56:15 +00:00
for ( uint32_t j = 0 ; j < heritageGroup - > mSkillList . num_used ; j + + )
2018-03-29 17:01:57 -04:00
{
if ( heritageGroup - > mSkillList . array_data [ j ] . skillNum = = i )
{
if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : TRAINED_SKILL_ADVANCEMENT_CLASS )
numCreditsUsed + = heritageGroup - > mSkillList . array_data [ j ] . normalCost ;
else if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : SPECIALIZED_SKILL_ADVANCEMENT_CLASS )
numCreditsUsed + = heritageGroup - > mSkillList . array_data [ j ] . primaryCost ;
found = true ;
break ;
}
}
//then if not found check regular skill costs.
if ( ! found )
{
if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : TRAINED_SKILL_ADVANCEMENT_CLASS )
numCreditsUsed + = pSkillBase - > _trained_cost ;
else if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : SPECIALIZED_SKILL_ADVANCEMENT_CLASS )
numCreditsUsed + = pSkillBase - > _specialized_cost ;
}
}
else
{
if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : TRAINED_SKILL_ADVANCEMENT_CLASS | |
cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : SPECIALIZED_SKILL_ADVANCEMENT_CLASS )
{
2019-07-07 20:56:15 +00:00
badData ( ) ;
return ;
2018-03-29 17:01:57 -04:00
}
}
}
2018-03-29 23:10:14 -07:00
if ( numCreditsUsed > 56 )
2018-03-29 17:01:57 -04:00
{
2019-07-07 20:56:15 +00:00
badData ( ) ;
return ;
2018-03-29 17:01:57 -04:00
}
// need to reformat name here...
if ( ! CheckNameValidity ( cg . name . c_str ( ) , GetAccessLevel ( ) , resultName ) )
{
2019-07-07 20:56:15 +00:00
badData ( CG_VERIFICATION_RESPONSE_NAME_BANNED ) ;
return ;
2018-05-19 00:03:18 -07:00
}
if ( ! CheckBadName ( cg . name ) )
{
2019-07-07 20:56:15 +00:00
badData ( CG_VERIFICATION_RESPONSE_NAME_BANNED ) ;
return ;
2018-03-29 17:01:57 -04:00
}
// should check variables to make sure everythings within restriction
// wHairTextures[m_wGender][m_wHairStyle];
// WORD wHairTextures[2][4] = { { 0x10B8, 0x10B8, 0x10B8, 0x10B7 }, { 0x11FD, 0x11FD, 0x11FD, 0x10B7 } };
// group 4, 0x0000F643, 0x00000001, <guid>, <char name[str]>, 0x00000000
{
// check if name exists
if ( g_pDBIO - > IsCharacterNameOpen ( resultName . c_str ( ) ) )
{
const int MIN_PLAYER_GUID = 0x50000000 ;
2018-08-22 22:31:27 -05:00
const int MAX_PLAYER_GUID = 0x5FFFFFFF ;
2018-03-29 17:01:57 -04:00
unsigned int newCharacterGUID = g_pDBIO - > GetHighestWeenieID ( MIN_PLAYER_GUID , MAX_PLAYER_GUID ) + 1 ;
if ( g_pDBIO - > CreateCharacter ( m_AccountInfo . id , newCharacterGUID , resultName . c_str ( ) ) )
{
m_Characters = g_pDBIO - > GetCharacterList ( m_AccountInfo . id ) ;
// start pReader Zaikhil
Position startPos ;
// startPos = Position(0x7D64001D, Vector(74.748657f, 97.934601f, 12.004999f), Quaternion(0.926898f, 0.000000f, 0.000000f, -0.375314f)); // zaikhil
// startPos = Position(0x9722003A, Vector(168.354004f, 24.618000f, 102.005005f), Quaternion(-0.922790f, 0.000000f, 0.000000f, -0.385302f));
startPos = Position ( 0xD3380005 , Vector ( 5.500000f , 109.800003f , 168.463333f ) , Quaternion ( 1.000000f , 0.000000f , 0.000000f , 0.000000f ) ) ;
// WCID "1" is always a player weenie
2018-07-12 14:41:21 -07:00
CWeenieObject * weenie = g_pWeenieFactory - > CreateWeenieByClassID ( 1 , & startPos , false ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
if ( ! weenie )
{
badData ( ) ;
return ;
}
2018-03-29 17:01:57 -04:00
weenie - > SetID ( newCharacterGUID ) ;
// alter parameters for character creation here
weenie - > SetName ( resultName . c_str ( ) ) ;
weenie - > m_Qualities . SetInt ( HERITAGE_GROUP_INT , cg . heritageGroup ) ;
weenie - > m_Qualities . SetInt ( GENDER_INT , cg . gender ) ;
weenie - > m_Qualities . SetAttribute ( STRENGTH_ATTRIBUTE , cg . strength ) ;
weenie - > m_Qualities . SetAttribute ( ENDURANCE_ATTRIBUTE , cg . endurance ) ;
weenie - > m_Qualities . SetAttribute ( COORDINATION_ATTRIBUTE , cg . coordination ) ;
weenie - > m_Qualities . SetAttribute ( QUICKNESS_ATTRIBUTE , cg . quickness ) ;
weenie - > m_Qualities . SetAttribute ( FOCUS_ATTRIBUTE , cg . focus ) ;
weenie - > m_Qualities . SetAttribute ( SELF_ATTRIBUTE , cg . self ) ;
2019-02-10 01:02:56 +00:00
weenie - > m_Qualities . SetInt ( CHARACTER_TITLE_ID_INT , 1 ) ;
2018-03-29 17:01:57 -04:00
if ( heritageGroup )
{
weenie - > m_Qualities . SetString ( HERITAGE_GROUP_STRING , heritageGroup - > name . c_str ( ) ) ;
if ( cg . templateNum > = 0 & & cg . templateNum < heritageGroup - > mTemplateList . num_used )
weenie - > m_Qualities . SetString ( TEMPLATE_STRING , heritageGroup - > mTemplateList . array_data [ cg . templateNum ] . name . c_str ( ) ) ;
scg = heritageGroup - > mGenderList . lookup ( cg . gender ) ;
if ( scg )
{
weenie - > m_Qualities . SetDataID ( PALETTE_BASE_DID , scg - > basePalette ) ;
weenie - > m_Qualities . SetDataID ( ICON_DID , scg - > iconImage ) ;
weenie - > m_Qualities . SetDataID ( SOUND_TABLE_DID , scg - > soundTable ) ;
weenie - > m_Qualities . SetDataID ( MOTION_TABLE_DID , scg - > motionTable ) ;
weenie - > m_Qualities . SetDataID ( COMBAT_TABLE_DID , scg - > combatTable ) ;
weenie - > m_Qualities . SetDataID ( PHYSICS_EFFECT_TABLE_DID , scg - > physicsTable ) ;
weenie - > m_Qualities . SetDataID ( SETUP_DID , scg - > setup ) ;
2018-11-15 20:53:36 -06:00
weenie - > m_Qualities . SetFloat ( DEFAULT_SCALE_FLOAT , scg - > scaling / 100 ) ;
2019-01-26 23:53:53 -06:00
weenie - > m_ObjDescOverride = scg - > objDesc ;
2018-03-29 17:01:57 -04:00
//weenie->m_ObjDesc = scg->objDesc;
//weenie->m_ObjDesc.paletteID = scg->basePalette;
2018-08-27 15:47:05 -05:00
cg . hairStyle = max ( 0 , min ( ( int ) scg - > mHairStyleList . num_used - 1 , cg . hairStyle ) ) ;
2018-03-29 17:01:57 -04:00
HairStyle_CG * hairStyle = & scg - > mHairStyleList . array_data [ cg . hairStyle ] ;
2019-01-26 23:53:53 -06:00
weenie - > m_ObjDescOverride + = hairStyle - > objDesc ;
2018-03-29 17:01:57 -04:00
//weenie->m_ObjDesc += hairStyle->objDesc;
2019-01-26 23:53:53 -06:00
AnimPartChange * change = hairStyle - > objDesc . GetAnimPartChange ( CharacterPartIndex : : Head ) ;
if ( change )
weenie - > m_Qualities . SetDataID ( HEAD_OBJECT_DID , change - > part_id ) ;
//if (hairStyle->objDesc.firstAPChange)
// weenie->m_Qualities.SetDataID(HEAD_OBJECT_DID, hairStyle->objDesc.firstAPChange->part_id);
2018-03-29 17:01:57 -04:00
2018-11-15 20:53:36 -06:00
if ( hairStyle - > alternateSetup )
weenie - > m_Qualities . SetDataID ( SETUP_DID , hairStyle - > alternateSetup ) ;
// fix Gearknight and olthoi head_object_did
2019-01-26 23:53:53 -06:00
//if (cg.heritageGroup == Gearknight_HeritageGroup)
// weenie->m_Qualities.SetDataID(HEAD_OBJECT_DID, hairStyle->objDesc.lastAPChange->part_id);
//if (cg.heritageGroup == Olthoi_HeritageGroup)
// weenie->m_Qualities.SetDataID(HEAD_OBJECT_DID, 0x010045f0);
//if (cg.heritageGroup == OlthoiAcid_HeritageGroup)
// weenie->m_Qualities.SetDataID(HEAD_OBJECT_DID, 0x01004616);
2018-11-15 20:53:36 -06:00
2018-03-29 17:01:57 -04:00
if ( cg . eyesStrip ! = - 1 )
{
2018-08-27 15:47:05 -05:00
cg . eyesStrip = max ( 0 , min ( ( int ) scg - > mEyeStripList . num_used - 1 , cg . eyesStrip ) ) ;
2018-03-29 17:01:57 -04:00
EyesStrip_CG * eyesStrip = & scg - > mEyeStripList . array_data [ cg . eyesStrip ] ;
if ( eyesStrip )
{
if ( hairStyle - > bald )
{
//weenie->m_ObjDesc += eyesStrip->objDesc_Bald;
weenie - > m_Qualities . SetDataID ( DEFAULT_EYES_TEXTURE_DID , eyesStrip - > objDesc_Bald . firstTMChange - > old_tex_id ) ;
weenie - > m_Qualities . SetDataID ( EYES_TEXTURE_DID , eyesStrip - > objDesc_Bald . firstTMChange - > new_tex_id ) ;
}
else
{
//weenie->m_ObjDesc += eyesStrip->objDesc;
weenie - > m_Qualities . SetDataID ( DEFAULT_EYES_TEXTURE_DID , eyesStrip - > objDesc . firstTMChange - > old_tex_id ) ;
weenie - > m_Qualities . SetDataID ( EYES_TEXTURE_DID , eyesStrip - > objDesc . firstTMChange - > new_tex_id ) ;
}
}
}
if ( cg . noseStrip ! = - 1 )
{
2018-08-27 15:47:05 -05:00
cg . noseStrip = max ( 0 , min ( ( int ) scg - > mNoseStripList . num_used - 1 , cg . noseStrip ) ) ;
2018-03-29 17:01:57 -04:00
FaceStrip_CG * faceStrip = & scg - > mNoseStripList . array_data [ cg . noseStrip ] ;
if ( faceStrip )
{
//weenie->m_ObjDesc += faceStrip->objDesc;
weenie - > m_Qualities . SetDataID ( DEFAULT_NOSE_TEXTURE_DID , faceStrip - > objDesc . firstTMChange - > old_tex_id ) ;
weenie - > m_Qualities . SetDataID ( NOSE_TEXTURE_DID , faceStrip - > objDesc . firstTMChange - > new_tex_id ) ;
}
}
if ( cg . mouthStrip ! = - 1 )
{
2018-08-27 15:47:05 -05:00
cg . mouthStrip = max ( 0 , min ( ( int ) scg - > mMouthStripList . num_used - 1 , cg . mouthStrip ) ) ;
2018-03-29 17:01:57 -04:00
FaceStrip_CG * faceStrip = & scg - > mMouthStripList . array_data [ cg . mouthStrip ] ;
if ( faceStrip )
{
// weenie->m_ObjDesc += faceStrip->objDesc;
weenie - > m_Qualities . SetDataID ( DEFAULT_MOUTH_TEXTURE_DID , faceStrip - > objDesc . firstTMChange - > old_tex_id ) ;
weenie - > m_Qualities . SetDataID ( MOUTH_TEXTURE_DID , faceStrip - > objDesc . firstTMChange - > new_tex_id ) ;
}
}
PalSet * ps ;
if ( ps = PalSet : : Get ( scg - > skinPalSet ) )
{
2019-07-07 20:56:15 +00:00
uint32_t skinPalette = ps - > GetPaletteID ( cg . skinShade ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . SetDataID ( SKIN_PALETTE_DID , skinPalette ) ;
//weenie->m_ObjDesc.AddSubpalette(new Subpalette(skinPalette, 0 << 3, 0x18 << 3));
PalSet : : Release ( ps ) ;
}
2018-08-27 15:47:05 -05:00
cg . hairColor = max ( 0 , min ( ( int ) scg - > mHairColorList . num_used - 1 , cg . hairColor ) ) ;
2018-03-29 17:01:57 -04:00
if ( ps = PalSet : : Get ( scg - > mHairColorList . array_data [ cg . hairColor ] ) )
{
2019-07-07 20:56:15 +00:00
uint32_t hairPalette = ps - > GetPaletteID ( cg . hairShade ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . SetDataID ( HAIR_PALETTE_DID , hairPalette ) ;
//weenie->m_ObjDesc.AddSubpalette(new Subpalette(hairPalette, 0x18 << 3, 0x8 << 3));
PalSet : : Release ( ps ) ;
}
if ( cg . eyeColor ! = - 1 )
{
2018-08-27 15:47:05 -05:00
cg . eyeColor = max ( 0 , min ( ( int ) scg - > mEyeColorList . num_used - 1 , cg . eyeColor ) ) ;
2019-07-07 20:56:15 +00:00
uint32_t eyesPalette = scg - > mEyeColorList . array_data [ cg . eyeColor ] ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . SetDataID ( EYES_PALETTE_DID , eyesPalette ) ;
//weenie->m_ObjDesc.AddSubpalette(new Subpalette(eyesPalette, 0x20 << 3, 0x8 << 3));
}
/*
EYES_TEXTURE_DID ,
NOSE_TEXTURE_DID ,
MOUTH_TEXTURE_DID ,
DEFAULT_EYES_TEXTURE_DID ,
DEFAULT_NOSE_TEXTURE_DID ,
DEFAULT_MOUTH_TEXTURE_DID ,
HAIR_PALETTE_DID ,
EYES_PALETTE_DID ,
SKIN_PALETTE_DID ,
HEAD_OBJECT_DID ,
*/
}
}
2019-07-07 20:56:15 +00:00
for ( uint32_t i = 0 ; i < cg . numSkills ; i + + )
2018-03-29 17:01:57 -04:00
{
2018-03-29 22:32:36 -07:00
weenie - > m_Qualities . SetSkillAdvancementClass ( SkillTable : : OldToNewSkill ( ( STypeSkill ) i ) , cg . skillAdvancementClasses [ i ] ) ;
2018-04-03 21:16:39 -05:00
if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : SPECIALIZED_SKILL_ADVANCEMENT_CLASS )
weenie - > m_Qualities . SetSkillLevel ( ( STypeSkill ) i , 10 ) ;
else if ( cg . skillAdvancementClasses [ i ] = = SKILL_ADVANCEMENT_CLASS : : TRAINED_SKILL_ADVANCEMENT_CLASS )
2018-11-12 00:31:10 -06:00
{
Skill trained ;
weenie - > m_Qualities . InqSkill ( ( STypeSkill ) i , trained ) ;
trained . _init_level = 0 ;
trained . _level_from_pp = 5 ;
trained . _pp = 526 ;
weenie - > m_Qualities . SetSkill ( ( STypeSkill ) i , trained ) ;
}
2018-03-29 17:01:57 -04:00
}
2018-07-11 04:53:32 +00:00
time_t t = chrono : : system_clock : : to_time_t ( std : : chrono : : system_clock : : now ( ) ) ;
std : : stringstream ss ;
ss < < std : : put_time ( std : : localtime ( & t ) , " %m/%d/%y %I:%M:%S %p. " ) ; // convert time to a string of format '01/01/18 11:59:59 AM.'
std : : string str = ss . str ( ) ;
weenie - > m_Qualities . SetInt ( CREATION_TIMESTAMP_INT , t ) ;
weenie - > m_Qualities . SetString ( DATE_OF_BIRTH_STRING , ss . str ( ) ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . SetInt ( AGE_INT , 0 ) ;
2018-07-19 18:48:42 -05:00
if ( weenie - > m_Qualities . GetInt ( HERITAGE_GROUP_INT , 0 ) = = Lugian_HeritageGroup )
weenie - > m_Qualities . SetDataID ( MOTION_TABLE_DID , 0x9000216 ) ;
2018-03-29 17:01:57 -04:00
/*
cg . startArea = max ( 0 , min ( cgd - > mStartAreaList . num_used - 1 , cg . startArea ) ) ;
assert ( cgd - > mStartAreaList . array_data [ cg . startArea ] . mPositionList . num_used > = 1 ) ;
startPos = cgd - > mStartAreaList . array_data [ cg . startArea ] . mPositionList . array_data [ 0 ] ;
weenie - > SetInitialPosition ( startPos ) ;
*/
startPos = Position ( 0xA9B00006 , Vector ( 24.258204f , 123.777000f , 63.060749f ) , Quaternion ( 1 , 0 , 0 , 0 ) ) ; // holtburg
switch ( cg . startArea )
{
default :
case 0 :
// Holtburg
startPos = Position ( g_pConfig - > HoltburgStartPosition ( ) ) ;
if ( ! startPos . objcell_id )
{
2018-06-14 18:32:07 -07:00
startPos = Position ( 0x870301AD , Vector ( 12.319900f , - 28.482000f , 0.005000f ) , Quaternion ( 0.315322f , 0 , 0 , 0.948985f ) ) ;
2018-03-29 17:01:57 -04:00
//startPos = Position(0xA9B00006, Vector(24.258204f, 123.777000f, 63.060749f), Quaternion(1, 0, 0, 0));
2019-01-15 21:32:44 +00:00
weenie - > m_Qualities . SetBool ( RECALLS_DISABLED_BOOL , 1 ) ; // Cannot use recalls out of the training academy.
2018-03-29 17:01:57 -04:00
}
break ;
case 1 :
// Shoushi
startPos = Position ( g_pConfig - > ShoushiStartPosition ( ) ) ;
if ( ! startPos . objcell_id )
{
2018-06-14 18:32:07 -07:00
startPos = Position ( 0x800401AD , Vector ( 12.319900f , - 28.482000f , 0.005000f ) , Quaternion ( 0.315322f , 0.0 , 0.0 , 0.948985f ) ) ;
2018-03-29 17:01:57 -04:00
//startPos = Position(0xDE51000C, Vector(26.712753f, 89.279999f, 17.778936f), Quaternion(0.931082f, 0.0, 0.0, -0.364811f));
2019-01-15 21:32:44 +00:00
weenie - > m_Qualities . SetBool ( RECALLS_DISABLED_BOOL , 1 ) ;
2018-03-29 17:01:57 -04:00
}
break ;
case 2 :
// Yaraq
startPos = Position ( g_pConfig - > YaraqStartPosition ( ) ) ;
if ( ! startPos . objcell_id )
{
2018-06-14 18:32:07 -07:00
startPos = Position ( 0x8C0401AD , Vector ( 12.319900f , - 28.482000f , 0.005000f ) , Quaternion ( 0.315322f , 0.0 , 0.0 , 0.948985f ) ) ;
2018-03-29 17:01:57 -04:00
//startPos = Position(0x7D680019, Vector(79.102280f, 19.573767f, 12.821287f), Quaternion(-0.656578f, 0.0, 0.0, 0.754258f));
2019-01-15 21:32:44 +00:00
weenie - > m_Qualities . SetBool ( RECALLS_DISABLED_BOOL , 1 ) ;
2018-03-29 17:01:57 -04:00
}
break ;
case 3 :
// Sanamar
startPos = Position ( g_pConfig - > SanamarStartPosition ( ) ) ;
if ( ! startPos . objcell_id )
{
2018-12-18 17:02:31 -06:00
startPos = Position ( 0x7203026C , Vector ( 11.66688f , - 28.831614f , 0.005f ) , Quaternion ( 0 , 0 , 0 , 1.0f ) ) ;
2018-03-29 17:01:57 -04:00
//startPos = Position(0xA9B00006, Vector(24.258204f, 123.777000f, 63.060749f), Quaternion(1, 0, 0, 0));
2019-01-15 21:32:44 +00:00
weenie - > m_Qualities . SetBool ( RECALLS_DISABLED_BOOL , 1 ) ;
2018-03-29 17:01:57 -04:00
}
2018-11-15 20:53:36 -06:00
break ;
case 4 :
// Olthoi Island
startPos = Position ( g_pConfig - > OlthoiStartPosition ( ) ) ;
if ( ! startPos . objcell_id )
{
startPos = Position ( 0xE6D3000E , Vector ( 40.57f , 138.16f , 218.00f ) , Quaternion ( 0 , 0 , 0 , 1 ) ) ;
}
2018-03-29 17:01:57 -04:00
break ;
}
weenie - > SetInitialPosition ( startPos ) ;
weenie - > m_Qualities . SetPosition ( SANCTUARY_POSITION , startPos ) ;
2018-03-31 17:15:05 -04:00
weenie - > m_Qualities . SetInt ( AVAILABLE_SKILL_CREDITS_INT , 52 - max ( 0 , min ( 52 , numCreditsUsed ) ) ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . SetInt ( CONTAINERS_CAPACITY_INT , 7 ) ;
weenie - > SetMaxVitals ( false ) ;
weenie - > m_Qualities . _create_list - > clear ( ) ; //Clear the create list as we don't want what's in it.
2018-08-04 17:24:12 -07:00
if ( ! g_pWorld - > CreateEntity ( weenie ) )
return ; ; //Briefly add the weenie to the world so we don't get errors when adding the starting gear.
2018-03-29 17:01:57 -04:00
//add starter gear
GenerateStarterGear ( weenie , cg , scg ) ;
2018-11-15 20:53:36 -06:00
// Set Olthoi starting stats/skills
if ( cg . heritageGroup = = Olthoi_HeritageGroup )
{
weenie - > m_Qualities . SetInt ( LEVEL_INT , 180 ) ;
weenie - > m_Qualities . SetAttribute ( STRENGTH_ATTRIBUTE , 350 ) ;
weenie - > m_Qualities . SetAttribute ( ENDURANCE_ATTRIBUTE , 350 ) ;
weenie - > m_Qualities . SetAttribute ( COORDINATION_ATTRIBUTE , 300 ) ;
weenie - > m_Qualities . SetAttribute ( QUICKNESS_ATTRIBUTE , 350 ) ;
weenie - > m_Qualities . SetAttribute ( FOCUS_ATTRIBUTE , 200 ) ;
weenie - > m_Qualities . SetAttribute ( SELF_ATTRIBUTE , 200 ) ;
weenie - > m_Qualities . SetAttribute2nd ( HEALTH_ATTRIBUTE_2ND , 325 ) ;
weenie - > m_Qualities . SetAttribute2nd ( STAMINA_ATTRIBUTE_2ND , 325 ) ;
weenie - > m_Qualities . SetInt ( PLAYER_KILLER_STATUS_INT , PK_PKStatus ) ; // Olthoi are always Red
}
if ( cg . heritageGroup = = OlthoiAcid_HeritageGroup )
{
weenie - > m_Qualities . SetInt ( LEVEL_INT , 180 ) ;
weenie - > m_Qualities . SetAttribute ( STRENGTH_ATTRIBUTE , 200 ) ;
weenie - > m_Qualities . SetAttribute ( ENDURANCE_ATTRIBUTE , 200 ) ;
weenie - > m_Qualities . SetAttribute ( COORDINATION_ATTRIBUTE , 300 ) ;
weenie - > m_Qualities . SetAttribute ( QUICKNESS_ATTRIBUTE , 250 ) ;
weenie - > m_Qualities . SetAttribute ( FOCUS_ATTRIBUTE , 400 ) ;
weenie - > m_Qualities . SetAttribute ( SELF_ATTRIBUTE , 400 ) ;
weenie - > m_Qualities . SetAttribute2nd ( HEALTH_ATTRIBUTE_2ND , 400 ) ;
weenie - > m_Qualities . SetAttribute2nd ( STAMINA_ATTRIBUTE_2ND , 400 ) ;
weenie - > m_Qualities . SetAttribute2nd ( MANA_ATTRIBUTE_2ND , 400 ) ;
weenie - > m_Qualities . SetInt ( PLAYER_KILLER_STATUS_INT , PK_PKStatus ) ; // Olthoi are always Red
}
2018-11-12 00:31:10 -06:00
// add racial augmentations
switch ( cg . heritageGroup )
{
case Shadowbound_HeritageGroup :
case Penumbraen_HeritageGroup :
weenie - > m_Qualities . SetInt ( AUGMENTATION_CRITICAL_EXPERTISE_INT , 1 ) ; break ;
case Gearknight_HeritageGroup :
weenie - > m_Qualities . SetInt ( AUGMENTATION_DAMAGE_REDUCTION_INT , 1 ) ; break ;
case Tumerok_HeritageGroup :
weenie - > m_Qualities . SetInt ( AUGMENTATION_CRITICAL_POWER_INT , 1 ) ; break ;
case Lugian_HeritageGroup :
weenie - > m_Qualities . SetInt ( AUGMENTATION_INCREASED_CARRYING_CAPACITY_INT , 1 ) ; break ;
case Empyrean_HeritageGroup :
weenie - > m_Qualities . SetInt ( AUGMENTATION_INFUSED_LIFE_MAGIC_INT , 1 ) ; break ;
case Undead_HeritageGroup :
weenie - > m_Qualities . SetInt ( AUGMENTATION_CRITICAL_DEFENSE_INT , 1 ) ; break ;
case Olthoi_HeritageGroup :
case OlthoiAcid_HeritageGroup :
break ; // none
default : // sho, aluv, gharu, viamont
weenie - > m_Qualities . SetInt ( AUGMENTATION_JACK_OF_ALL_TRADES_INT , 1 ) ; break ;
}
2018-03-29 17:01:57 -04:00
weenie - > Save ( ) ;
g_pWorld - > RemoveEntity ( weenie ) ;
//delete weenie; //RemoveEntity already performs the deletion.
BinaryWriter response ;
2019-07-07 20:56:15 +00:00
response . Write < uint32_t > ( 0xF643 ) ;
response . Write < uint32_t > ( 1 ) ;
response . Write < uint32_t > ( newCharacterGUID ) ;
2018-03-29 17:01:57 -04:00
response . WriteString ( cg . name . c_str ( ) ) ;
2019-07-07 20:56:15 +00:00
response . Write < uint32_t > ( 0 ) ;
2018-03-29 17:01:57 -04:00
SendNetMessage ( response . GetData ( ) , response . GetSize ( ) , PRIVATE_MSG ) ;
}
else
{
2018-04-27 21:03:39 -07:00
SERVER_ERROR < < " Failed to create character. " ;
2019-07-07 20:56:15 +00:00
badData ( CG_VERIFICATION_RESPONSE_DATABASE_DOWN ) ;
2018-03-29 17:01:57 -04:00
}
}
else
{
2018-04-27 21:03:39 -07:00
SERVER_INFO < < " Character name already exists. " ;
2019-07-07 20:56:15 +00:00
badData ( CG_VERIFICATION_RESPONSE_NAME_IN_USE ) ;
2018-03-29 17:01:57 -04:00
}
}
return ;
}
2019-09-09 10:49:47 -05:00
void CClient : : GenerateStarterGear ( CWeenieObject * weenieObject , ACCharGenResult & cg , Sex_CG * scg )
2018-03-29 17:01:57 -04:00
{
2018-08-04 17:24:12 -07:00
if ( ! weenieObject )
return ;
2018-07-12 14:41:21 -07:00
CMonsterWeenie * weenie = weenieObject - > AsMonster ( ) ;
2018-03-29 17:01:57 -04:00
if ( weenie = = NULL )
return ;
2018-11-15 20:53:36 -06:00
if ( cg . heritageGroup ! = Gearknight_HeritageGroup & & cg . heritageGroup < 12 ) // Gearknights and olthoi don't get clothes to start.
{
if ( cg . headgearStyle ! = UINT_MAX )
weenie - > SpawnWielded ( cg . headgearStyle , scg - > mHeadgearList , cg . headgearColor , scg - > mClothingColorsList , cg . headgearShade ) ;
weenie - > SpawnWielded ( cg . shirtStyle , scg - > mShirtList , cg . shirtColor , scg - > mClothingColorsList , cg . shirtShade ) ;
weenie - > SpawnWielded ( cg . trousersStyle , scg - > mPantsList , cg . trousersColor , scg - > mClothingColorsList , cg . trousersShade ) ;
weenie - > SpawnWielded ( cg . footwearStyle , scg - > mFootwearList , cg . footwearColor , scg - > mClothingColorsList , cg . footwearShade ) ;
}
if ( cg . heritageGroup < 12 ) // Olthoi get their own set of starting items.
{
//weenie->m_Qualities.SetInt(COIN_VALUE_INT, GetAccessLevel() >= ADMIN_ACCESS ? 500000000 : 10000);
weenie - > SpawnInContainer ( W_COINSTACK_CLASS , 500 ) ;
weenie - > SpawnInContainer ( W_TUTORIALBOOK_CLASS , 1 ) ;
weenie - > SpawnInContainer ( W_TINKERINGTOOL_CLASS , 1 ) ;
weenie - > SpawnInContainer ( W_SACK_CLASS , 1 ) ;
weenie - > SpawnInContainer ( W_CALLINGSTONE_CLASS , 1 ) ;
weenie - > SpawnInContainer ( 33613 , 1 ) ; // Pathwarden Token
}
2018-03-29 22:32:36 -07:00
2018-11-15 20:53:36 -06:00
weenie - > SpawnInContainer ( 31000 , 1 ) ; // Blackmoor's Favor
2018-03-29 17:01:57 -04:00
2019-09-09 10:49:47 -05:00
CContainerWeenie * sack = weenie ;
for ( auto pack : weenie - > m_Packs )
{
if ( pack - > AsContainer ( ) )
{
sack = pack - > AsContainer ( ) ;
break ;
}
}
weenie - > RecalculateCoinAmount ( W_COINSTACK_CLASS ) ;
// heritage items regardless of skill
switch ( cg . heritageGroup )
{
case Invalid_HeritageGroup :
case Aluvian_HeritageGroup :
2019-09-18 01:43:10 +00:00
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGALU_CLASS ) ;
2019-09-09 10:49:47 -05:00
weenie - > SpawnInContainer ( W_BREAD_CLASS , 1 ) ;
break ;
case Gharundim_HeritageGroup :
2019-09-18 01:43:10 +00:00
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGGHA_CLASS ) ;
2019-09-09 10:49:47 -05:00
weenie - > SpawnInContainer ( W_CHEESE_CLASS , 1 ) ;
break ;
2019-09-18 01:43:10 +00:00
case Sho_HeritageGroup :
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGSHO_CLASS ) ;
break ;
case Viamontian_HeritageGroup :
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGVIA_CLASS ) ;
break ;
2019-09-09 10:49:47 -05:00
case Olthoi_HeritageGroup :
weenie - > SpawnInContainer ( 43701 , 1 ) ; // Olthoi Fibrous Healing Tissue
weenie - > SpawnInContainer ( 43634 , 10 ) ; // Acidic Infusions
case OlthoiAcid_HeritageGroup :
weenie - > SpawnInContainer ( 43701 , 1 ) ; // Olthoi Fibrous Healing Tissue
weenie - > SpawnInContainer ( 43634 , 10 ) ; // Acidic Infusions
weenie - > SpawnInContainer ( 43489 , 1 ) ; // Salivatory Goo
weenie - > SpawnInContainer ( 43637 , 100 ) ; // Saliva Invigorator
weenie - > SpawnInContainer ( W_PACKWARESSENCE_CLASS , 1 ) ;
break ;
2019-09-18 01:43:10 +00:00
case Penumbraen_HeritageGroup :
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGSHA_CLASS ) ;
break ;
case Shadowbound_HeritageGroup :
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGSHA_CLASS ) ;
break ;
2019-09-09 10:49:47 -05:00
case Gearknight_HeritageGroup :
2019-09-18 01:43:10 +00:00
weenie - > SpawnInContainer ( W_NOTELETTERGREETINGGEA_CLASS ) ;
2019-09-09 10:49:47 -05:00
weenie - > SpawnInContainer ( 43022 , 1 ) ; // Core Plating Deintegrator
weenie - > SpawnInContainer ( 42979 , 1 ) ; // Core Plating Integrator
default :
weenie - > SpawnInContainer ( W_APPLE_CLASS , 1 ) ;
break ;
}
if ( cg . numSkills < = 0 )
return ;
if ( cg . trained ( ALCHEMY_SKILL ) )
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_MORTARANDPESTLE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( ALCHEMY_SKILL ) )
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_GEMAZURITE_CLASS , 3 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( COOKING_SKILL ) )
2018-03-29 17:01:57 -04:00
{
weenie - > SpawnInContainer ( W_FLOUR_CLASS , 6 ) ;
weenie - > SpawnInContainer ( W_WATER_CLASS , 6 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FLETCHING_SKILL ) )
2018-03-29 17:01:57 -04:00
{
weenie - > SpawnInContainer ( W_ARROWHEAD_CLASS , 30 ) ;
weenie - > SpawnInContainer ( W_ARROWSHAFT_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEALING_SKILL ) )
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_HEALINGKITCRUDE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( HEALING_SKILL ) )
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_HEALINGKITCRUDE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LOCKPICK_SKILL ) )
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_LOCKPICKCRUDE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( ITEM_APPRAISAL_SKILL ) | |
cg . trained ( ARMOR_APPRAISAL_SKILL ) | |
cg . trained ( WEAPON_APPRAISAL_SKILL ) | |
cg . trained ( MAGIC_ITEM_APPRAISAL_SKILL ) )
2018-03-29 17:01:57 -04:00
{
weenie - > SpawnInContainer ( W_TINKERINGTOOL_CLASS , 1 ) ;
}
switch ( cg . heritageGroup )
{
2019-07-07 20:56:15 +00:00
case Invalid_HeritageGroup :
2018-03-29 17:01:57 -04:00
case Aluvian_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 19:02:11 -07:00
weenie - > SpawnInContainer ( W_TRAININGDAGGER_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 19:02:11 -07:00
weenie - > SpawnInContainer ( W_DAGGERTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-14 19:02:11 -07:00
weenie - > SpawnInContainer ( W_TRAININGKNIFE_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
break ;
case Gharundim_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 19:02:11 -07:00
weenie - > SpawnInContainer ( W_TRAININGSTAFF_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 19:02:11 -07:00
weenie - > SpawnInContainer ( W_STAFFTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-14 19:02:11 -07:00
weenie - > SpawnInContainer ( W_TRAININGBASTONE_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Sho_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGKNUCKLES_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_CESTUSTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGHANDWRAPS_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
break ;
2018-03-29 22:32:36 -07:00
case Viamontian_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGBROADSWORD_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_SWORDTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGSHORTSWORD_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Lugian_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGCLUB_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_MACETRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGDABUS_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Tumerok_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGSPEAR_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_SPEARTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGBUDIAQ_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Empyrean_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGBROADSWORD_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_SWORDTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGSHORTSWORD_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Undead_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGHANDAXE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_AXETRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGTUNGI_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Gearknight_HeritageGroup :
weenie - > SpawnInContainer ( W_APPLE_CLASS , 1 ) ;
2018-11-15 20:53:36 -06:00
weenie - > SpawnInContainer ( 43022 , 1 ) ; // Core Plating Deintegrator
weenie - > SpawnInContainer ( 42979 , 1 ) ; // Core Plating Integrator
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGCLUB_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_MACETRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGDABUS_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Penumbraen_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGKNUCKLES_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_CESTUSTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGHANDWRAPS_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
break ;
case Shadowbound_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_TRAININGKNUCKLES_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( TWO_HANDED_COMBAT_SKILL ) )
2018-06-26 17:56:12 -04:00
weenie - > SpawnInContainer ( W_TRAININGSPADONE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( MISSILE_WEAPONS_SKILL ) )
2018-03-29 22:32:36 -07:00
{
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_BOWTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_ARROW_CLASS , 30 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-06-14 20:16:19 -07:00
weenie - > SpawnInContainer ( W_CESTUSTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_TRAININGHANDWRAPS_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | |
cg . trained ( ITEM_ENCHANTMENT_SKILL ) | |
cg . trained ( LIFE_MAGIC_SKILL ) | |
cg . trained ( WAR_MAGIC_SKILL ) | |
cg . trained ( VOID_MAGIC_SKILL ) )
2018-06-25 17:31:54 -04:00
weenie - > SpawnInContainer ( W_WANDTRAINING_CLASS , 1 ) ;
2018-03-29 22:32:36 -07:00
2018-11-15 20:53:36 -06:00
break ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) | | cg . trained ( ITEM_ENCHANTMENT_SKILL ) | | cg . trained ( LIFE_MAGIC_SKILL ) | | cg . trained ( WAR_MAGIC_SKILL ) | | cg . trained ( VOID_MAGIC_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-11-12 00:31:10 -06:00
sack - > SpawnInContainer ( W_SCARABLEAD_CLASS , 5 ) ;
weenie - > SpawnInContainer ( W_TAPERPRISMATIC_CLASS , 25 ) ;
}
2018-03-29 17:01:57 -04:00
2019-09-09 10:49:47 -05:00
if ( cg . trained ( CREATURE_ENCHANTMENT_SKILL ) )
2018-11-12 00:31:10 -06:00
{
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( FocusSelf1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( InvulnerabilityOther1_SpellID ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . AddSpell ( InvulnerabilitySelf1_SpellID ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_PACKCREATUREESSENCE_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( CREATURE_ENCHANTMENT_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( FocusSelf1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( ManaMasterySelf1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( WillpowerSelf1_SpellID ) ;
2018-03-29 22:32:36 -07:00
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( ITEM_ENCHANTMENT_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-11-12 00:31:10 -06:00
weenie - > m_Qualities . AddSpell ( BloodDrinker1_SpellID ) ;
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( BludgeonBane1_SpellID ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . AddSpell ( Impenetrability1_SpellID ) ;
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( SwiftKiller1_SpellID ) ;
2018-03-29 22:32:36 -07:00
weenie - > SpawnInContainer ( W_PACKITEMESSENCE_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( ITEM_ENCHANTMENT_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( Defender1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( Impenetrability1_SpellID ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIFE_MAGIC_SKILL ) )
2018-03-29 17:01:57 -04:00
{
weenie - > m_Qualities . AddSpell ( ArmorOther1_SpellID ) ;
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( ArmorSelf1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( HealOther1_SpellID ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . AddSpell ( HealSelf1_SpellID ) ;
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( ImperilOther1_SpellID ) ;
2018-03-29 22:32:36 -07:00
2018-11-12 00:31:10 -06:00
if ( cg . heritageGroup ! = Empyrean_HeritageGroup ) // Empyreans get the Life magic aug on creation
weenie - > SpawnInContainer ( W_PACKLIFEESSENCE_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( LIFE_MAGIC_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( DrainHealth1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( HarmOther1_SpellID ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( WAR_MAGIC_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2018-03-29 22:32:36 -07:00
weenie - > m_Qualities . AddSpell ( FlameBolt1_SpellID ) ;
2018-03-29 17:01:57 -04:00
weenie - > m_Qualities . AddSpell ( ForceBolt1_SpellID ) ;
2018-03-29 22:32:36 -07:00
weenie - > m_Qualities . AddSpell ( FrostBolt1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( ShockWave1_SpellID ) ;
weenie - > SpawnInContainer ( W_PACKWARESSENCE_CLASS , 1 ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( WAR_MAGIC_SKILL ) )
2018-03-29 17:01:57 -04:00
{
2019-07-21 06:58:50 -07:00
weenie - > m_Qualities . AddSpell ( LightningBolt1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( WhirlingBlade1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( AcidStream1_SpellID ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( VOID_MAGIC_SKILL ) )
2019-07-21 06:58:50 -07:00
{
weenie - > m_Qualities . AddSpell ( netherbolt1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( CurseDestructionOther1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( FesterOther1_SpellID ) ;
2018-03-29 22:32:36 -07:00
2019-07-21 06:58:50 -07:00
weenie - > SpawnInContainer ( 43173 , 1 ) ;
}
2019-09-09 10:49:47 -05:00
if ( cg . specialized ( VOID_MAGIC_SKILL ) )
2019-07-21 06:58:50 -07:00
{
weenie - > m_Qualities . AddSpell ( Corrosion1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( Corruption1_SpellID ) ;
weenie - > m_Qualities . AddSpell ( CurseWeakness1_SpellID ) ;
2018-03-29 17:01:57 -04:00
}
2019-09-09 10:49:47 -05:00
if ( cg . trained ( DUAL_WIELD_SKILL ) )
2018-11-12 06:34:41 -06:00
{
switch ( cg . heritageGroup )
{
case Default :
case Aluvian_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGDAGGER_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_DAGGERTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGKNIFE_CLASS , 1 ) ;
break ;
case Gharundim_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGSTAFF_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_STAFFTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGBASTONE_CLASS , 1 ) ;
break ;
case Penumbraen_HeritageGroup :
case Shadowbound_HeritageGroup :
case Sho_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGKNUCKLES_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_CESTUSTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGHANDWRAPS_CLASS , 1 ) ;
break ;
case Empyrean_HeritageGroup :
case Viamontian_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGBROADSWORD_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_SWORDTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGSHORTSWORD_CLASS , 1 ) ;
break ;
case Gearknight_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGCLUB_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_MACETRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGDABUS_CLASS , 1 ) ;
break ;
case Tumerok_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGSPEAR_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_SPEARTRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGBUDIAQ_CLASS , 1 ) ;
break ;
case Lugian_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGCLUB_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_MACETRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGDABUS_CLASS , 1 ) ;
break ;
case Undead_HeritageGroup :
2019-09-09 10:49:47 -05:00
if ( cg . trained ( LIGHT_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGHANDAXE_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( HEAVY_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_AXETRAINING_CLASS , 1 ) ;
2019-09-09 10:49:47 -05:00
if ( cg . trained ( FINESSE_WEAPONS_SKILL ) )
2018-11-12 06:34:41 -06:00
weenie - > SpawnInContainer ( W_TRAININGTUNGI_CLASS , 1 ) ;
break ;
case Olthoi_HeritageGroup :
case OlthoiAcid_HeritageGroup :
break ; // none
}
}
2018-03-29 17:01:57 -04:00
}
2019-07-07 20:56:15 +00:00
void CClient : : SendLandblock ( uint32_t dwFileID )
2018-03-29 17:01:57 -04:00
{
TURBINEFILE * pLandData = g_pCell - > GetFile ( dwFileID ) ;
if ( ! pLandData )
{
if ( m_pEvents )
{
m_pEvents - > SendText ( csprintf ( " Your client is requesting cell data (0x%08X) that this server does not have! " , dwFileID ) , LTT_DEFAULT ) ;
m_pEvents - > SendText ( " If you are stuck in portal mode, type /render radius 5 to escape. The server administrator should reconfigure the server with a FULL cell.dat file! " , LTT_DEFAULT ) ;
}
return ;
}
if ( ( dwFileID & 0xFFFF ) ! = 0xFFFF )
{
2018-04-27 21:03:39 -07:00
SERVER_WARN < < " Client requested Landblock " < < dwFileID < < " -should end pReader 0xFFFF " ;
2018-03-29 17:01:57 -04:00
}
if ( pLandData )
{
BinaryWriter BlockPackage ;
2019-07-07 20:56:15 +00:00
BlockPackage . Write < uint32_t > ( 0xF7E2 ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
uint32_t dwFileSize = pLandData - > GetLength ( ) ;
2018-03-29 17:01:57 -04:00
BYTE * pbFileData = pLandData - > GetData ( ) ;
2019-07-07 20:56:15 +00:00
uLongf dwPackageSize = ( uint32_t ) ( ( dwFileSize * 1.02f ) + 12 + 1 ) ;
2018-03-29 17:01:57 -04:00
BYTE * pbPackageData = new BYTE [ dwPackageSize ] ;
if ( Z_OK ! = compress2 ( pbPackageData , & dwPackageSize , pbFileData , dwFileSize , Z_BEST_COMPRESSION ) )
{
2018-04-27 21:03:39 -07:00
SERVER_ERROR < < " Error compressing LandBlock package! " ;
2018-03-29 17:01:57 -04:00
}
2019-07-07 20:56:15 +00:00
BlockPackage . Write < uint32_t > ( 1 ) ; //the resource type: 1 for 0xFFFF, 2 for 0xFFFE, 3 for 0x100
BlockPackage . Write < uint32_t > ( 2 ) ; //1 = client_portal / 2 = client_cell_1 / 3 = client_local_English
BlockPackage . Write < uint32_t > ( 1 ) ; //?
BlockPackage . Write < uint32_t > ( dwFileID ) ; //the resource ID number
BlockPackage . Write < uint32_t > ( 1 ) ; //the file version number
2018-03-29 17:01:57 -04:00
BlockPackage . Write < BYTE > ( 1 ) ; // 0 = uncompressed / 1 = compressed
2019-07-07 20:56:15 +00:00
BlockPackage . Write < uint32_t > ( 2 ) ; //?
BlockPackage . Write < uint32_t > ( dwPackageSize + sizeof ( uint32_t ) * 2 ) ; //the number of bytes required for the remainder of this message, including this uint32_t
BlockPackage . Write < uint32_t > ( dwFileSize ) ; //the size of the uncompressed file
2018-03-29 17:01:57 -04:00
BlockPackage . Write ( pbPackageData , dwPackageSize ) ; //bytes of zlib compressed file data
BlockPackage . Align ( ) ;
delete [ ] pbPackageData ;
delete pLandData ;
SendNetMessage ( BlockPackage . GetData ( ) , BlockPackage . GetSize ( ) , EVENT_MSG , FALSE ) ;
}
}
2019-07-07 20:56:15 +00:00
void CClient : : SendLandblockInfo ( uint32_t dwFileID )
2018-03-29 17:01:57 -04:00
{
if ( ( dwFileID & 0xFFFF ) ! = 0xFFFE )
{
2018-04-27 21:03:39 -07:00
SERVER_WARN < < " Client requested LandblockInfo " < < dwFileID < < " should end pReader 0xFFFE " ;
2018-03-29 17:01:57 -04:00
return ;
}
TURBINEFILE * pObjData = g_pCell - > GetFile ( dwFileID ) ;
if ( ! pObjData )
{
return ;
}
if ( pObjData )
{
BinaryWriter BlockInfoPackage ;
2019-07-07 20:56:15 +00:00
BlockInfoPackage . Write < uint32_t > ( 0xF7E2 ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
uint32_t dwFileSize = pObjData - > GetLength ( ) ;
2018-03-29 17:01:57 -04:00
BYTE * pbFileData = pObjData - > GetData ( ) ;
2019-07-07 20:56:15 +00:00
uLongf dwPackageSize = ( uint32_t ) ( ( dwFileSize * 1.02f ) + 12 + 1 ) ;
2018-03-29 17:01:57 -04:00
BYTE * pbPackageData = new BYTE [ dwPackageSize ] ;
if ( Z_OK ! = compress2 ( pbPackageData , & dwPackageSize , pbFileData , dwFileSize , Z_BEST_COMPRESSION ) )
{
2018-04-27 21:03:39 -07:00
SERVER_ERROR < < " Error compressing LandBlockInfo package! " ;
2018-03-29 17:01:57 -04:00
}
2019-07-07 20:56:15 +00:00
BlockInfoPackage . Write < uint32_t > ( 2 ) ; // 1 for 0xFFFF, 2 for 0xFFFE, 3 for 0x100
BlockInfoPackage . Write < uint32_t > ( 2 ) ;
BlockInfoPackage . Write < uint32_t > ( 1 ) ;
BlockInfoPackage . Write < uint32_t > ( dwFileID ) ;
BlockInfoPackage . Write < uint32_t > ( 1 ) ;
2018-03-29 17:01:57 -04:00
BlockInfoPackage . Write < BYTE > ( 1 ) ;
2019-07-07 20:56:15 +00:00
BlockInfoPackage . Write < uint32_t > ( 2 ) ;
BlockInfoPackage . Write < uint32_t > ( dwPackageSize + sizeof ( uint32_t ) * 2 ) ;
BlockInfoPackage . Write < uint32_t > ( dwFileSize ) ;
2018-03-29 17:01:57 -04:00
BlockInfoPackage . Write ( pbPackageData , dwPackageSize ) ;
BlockInfoPackage . Align ( ) ;
delete [ ] pbPackageData ;
delete pObjData ;
SendNetMessage ( BlockInfoPackage . GetData ( ) , BlockInfoPackage . GetSize ( ) , EVENT_MSG , FALSE ) ;
}
}
2019-07-07 20:56:15 +00:00
void CClient : : SendLandcell ( uint32_t dwFileID )
2018-03-29 17:01:57 -04:00
{
TURBINEFILE * pCellData = g_pCell - > GetFile ( dwFileID ) ;
if ( ! pCellData )
{
if ( m_pEvents )
{
m_pEvents - > SendText ( csprintf ( " Your client is requesting cell data (#%08X) that this server does not have! " , dwFileID ) , LTT_DEFAULT ) ;
m_pEvents - > SendText ( " If you are stuck in portal mode, type /render radius 5 to escape. The server administrator should reconfigure the server with a FULL cell.dat file! " , LTT_DEFAULT ) ;
}
return ;
}
if ( pCellData )
{
BinaryWriter CellPackage ;
2019-07-07 20:56:15 +00:00
CellPackage . Write < uint32_t > ( 0xF7E2 ) ;
2018-03-29 17:01:57 -04:00
2019-07-07 20:56:15 +00:00
uint32_t dwFileSize = pCellData - > GetLength ( ) ;
2018-03-29 17:01:57 -04:00
BYTE * pbFileData = pCellData - > GetData ( ) ;
2019-07-07 20:56:15 +00:00
uLongf dwPackageSize = ( uint32_t ) ( ( dwFileSize * 1.02f ) + 12 + 1 ) ;
2018-03-29 17:01:57 -04:00
BYTE * pbPackageData = new BYTE [ dwPackageSize ] ;
if ( Z_OK ! = compress2 ( pbPackageData , & dwPackageSize , pbFileData , dwFileSize , Z_BEST_COMPRESSION ) )
{
// These are CEnvCell if I recall correctly
2018-04-27 21:03:39 -07:00
SERVER_ERROR < < " Error compressing landcell package! " ;
2018-03-29 17:01:57 -04:00
}
2019-07-07 20:56:15 +00:00
CellPackage . Write < uint32_t > ( 3 ) ; // 1 for 0xFFFF, 2 for 0xFFFE, 3 for 0x100
CellPackage . Write < uint32_t > ( 2 ) ;
CellPackage . Write < uint32_t > ( 1 ) ;
CellPackage . Write < uint32_t > ( dwFileID ) ;
CellPackage . Write < uint32_t > ( 1 ) ;
2018-03-29 17:01:57 -04:00
CellPackage . Write < BYTE > ( 1 ) ;
2019-07-07 20:56:15 +00:00
CellPackage . Write < uint32_t > ( 2 ) ;
CellPackage . Write < uint32_t > ( dwPackageSize + sizeof ( uint32_t ) * 2 ) ;
CellPackage . Write < uint32_t > ( dwFileSize ) ;
2018-03-29 17:01:57 -04:00
CellPackage . Write ( pbPackageData , dwPackageSize ) ;
CellPackage . Align ( ) ;
delete [ ] pbPackageData ;
delete pCellData ;
//LOG(Temp, Normal, "Sent cell %08X ..\n", dwFileID);
SendNetMessage ( CellPackage . GetData ( ) , CellPackage . GetSize ( ) , EVENT_MSG , FALSE ) ;
}
//if (m_pEvents)
// m_pEvents->SendText(csprintf("The server has sent you cell #%04X!", dwFileID >> 16), LTT_DEFAULT);
}
2019-07-07 20:56:15 +00:00
void CClient : : ProcessMessage ( BYTE * data , uint32_t length , WORD group )
2018-03-29 17:01:57 -04:00
{
if ( g_bDebugToggle )
{
2018-04-27 21:03:39 -07:00
NETWORK_DEBUG < < " Received response(group " < < group < < " ) " ;
NETWORK_DEBUG < < data ;
2018-03-29 17:01:57 -04:00
}
BinaryReader in ( data , length ) ;
2019-07-07 20:56:15 +00:00
uint32_t dwMessageCode = in . ReadUInt32 ( ) ;
2018-03-29 17:01:57 -04:00
# ifdef _DEBUG
// LOG(Client, Normal, "Processing response 0x%X (size %d):\n", dwMessageCode, length);
# endif
if ( in . GetLastError ( ) )
{
2018-04-27 21:03:39 -07:00
NETWORK_ERROR < < " Error processing response. " < < dwMessageCode ;
2018-03-29 17:01:57 -04:00
return ;
}
switch ( dwMessageCode )
{
case 0xF653 :
{
if ( m_vars . bInWorld )
{
2018-11-23 03:37:34 -06:00
m_pEvents - > ForceLogout ( ) ;
2018-03-29 17:01:57 -04:00
}
break ;
}
case 0xF655 : // Delete Character
if ( ! m_vars . bInWorld )
{
DeleteCharacter ( & in ) ;
}
break ;
case 0xF656 : // Create Character
{
if ( ! m_vars . bInWorld )
{
CreateCharacter ( & in ) ;
}
break ;
}
2019-11-23 20:34:53 +00:00
case 0xF7D9 : // Restore Character
{
if ( ! m_vars . bInWorld )
{
RestoreCharacter ( & in ) ;
}
break ;
}
2018-03-29 17:01:57 -04:00
case 0xF6EA : // Request Object
{
if ( m_vars . bInWorld )
{
2019-07-07 20:56:15 +00:00
uint32_t dwEID = in . ReadUInt32 ( ) ;
2018-03-29 17:01:57 -04:00
if ( in . GetLastError ( ) ) break ;
2018-07-12 14:41:21 -07:00
CPlayerWeenie * pPlayer ;
2018-03-29 17:01:57 -04:00
if ( ( m_pEvents ) & & ( pPlayer = m_pEvents - > GetPlayer ( ) ) )
{
2018-07-12 14:41:21 -07:00
CWeenieObject * pTarget = g_pWorld - > FindWithinPVS ( pPlayer , dwEID ) ;
2018-03-29 17:01:57 -04:00
if ( pTarget )
2019-10-04 18:02:31 -07:00
pPlayer - > MakeAware ( pTarget , true ) ;
2018-03-29 17:01:57 -04:00
else
{
pTarget = g_pWorld - > FindObject ( dwEID ) ;
if ( pTarget )
{
// LOG(Temp, Normal, "Player %s is requesting info on %s it shouldn't know about.\n", pPlayer->GetName().c_str(), pTarget->GetName().c_str());
}
}
}
}
break ;
}
case 0xF7E6 : //DDD_InterrogationResponseMessage
{
2019-07-07 20:56:15 +00:00
uint32_t clientLanguage = in . ReadUInt32 ( ) ;
2019-04-13 18:18:28 +00:00
int32_t fileCount = in . ReadInt32 ( ) ;
bool allMatch = true ;
for ( int i = 0 ; i < fileCount ; i + + )
{
// file info contains
// int int <file 0xffff0001>
// dataset datasubset <file 0xffff0001>
int32_t ds = in . ReadInt32 ( ) ;
int32_t dss = in . ReadInt32 ( ) ;
BYTE * itr = in . GetDataPtr ( ) ;
int match = 0 ;
in . SetOffset ( in . GetOffset ( ) + sizeof ( int32_t ) * 3 ) ;
switch ( ds )
{
case 0 :
// portal
if ( dss = = 1 )
match = g_pPortal - > CompareIteration ( itr ) ;
break ;
case 1 :
switch ( dss )
{
case 2 : // cell
match = g_pCell - > CompareIteration ( itr ) ;
break ;
case 3 : // local_english
break ;
}
break ;
}
if ( match ! = 0 )
{
allMatch = false ;
// NETWORK_DEBUG << "Client DAT Mismatch: " << ds << dss;
}
}
if ( ! allMatch )
{
// error with wrong version
GetPacketController ( ) - > SendCriticalError ( ST_SERVER_ERRORS , STR_LOGIN_CLIENT_VERSION ) ;
}
// ends with 0
2019-07-07 20:56:15 +00:00
//PackableList<uint32_t> fileIds;
2019-04-13 18:18:28 +00:00
//fileIds.UnPack(&in);
2018-03-29 17:01:57 -04:00
if ( in . GetLastError ( ) )
break ;
BinaryWriter EndDDD ;
2019-07-07 20:56:15 +00:00
EndDDD . Write < int32_t > ( 0xF7EA ) ;
2018-03-29 17:01:57 -04:00
SendNetMessage ( EndDDD . GetData ( ) , EndDDD . GetSize ( ) , EVENT_MSG ) ;
break ;
}
case 0xF7EA : //DDD_OnEndDDD
{
//BinaryWriter EndDDD;
2019-07-07 20:56:15 +00:00
//EndDDD.Write<uint32_t>(0xF7EA);
2018-03-29 17:01:57 -04:00
//SendNetMessage(EndDDD.GetData(), EndDDD.GetSize(), EVENT_MSG);
break ;
}
case 0xF7E3 : //DDD_RequestDataMessage
{
if ( m_vars . bInWorld )
{
2019-07-07 20:56:15 +00:00
uint32_t dwFileClass = in . ReadUInt32 ( ) ;
uint32_t dwFileID = in . ReadUInt32 ( ) ;
2018-03-29 17:01:57 -04:00
if ( in . GetLastError ( ) ) break ;
//disabled downloading files.
m_pEvents - > SendText ( " Your client is requesting map data from the server. This feature is disabled to preserve bandwidth " , LTT_DEFAULT ) ;
m_pEvents - > SendText ( " If you are stuck in portal mode, type /render radius 5 to escape. Make sure you are using the approppriate cell.dat file! " , LTT_DEFAULT ) ;
//switch (dwFileClass)
//{
//default:
// LOG(Client, Warning, "Unknown download request: %08X %d\n", dwFileID, dwFileClass);
// break;
//case 1:
//{
// SendLandblock(dwFileID); // 1 is landblock 0xFFFF
// break;
//}
//case 2:
// SendLandblockInfo(dwFileID); // 2 is landblock environemnt 0xFFFE
// break;
//case 3:
// SendLandcell(dwFileID); // 0x100+
// break;
//}
}
break ;
}
case 0xF7B1 :
{
//should check the sequence
if ( m_vars . bInWorld )
{
m_pEvents - > ProcessEvent ( & in ) ;
}
break ;
}
case 0xF7C8 :
{
if ( ! m_vars . bInWorld )
{
EnterWorld ( ) ;
}
break ;
}
case 0xF657 :
{
if ( m_vars . bInWorld )
{
2019-07-07 20:56:15 +00:00
uint32_t dwGUID = in . ReadUInt32 ( ) ;
2018-03-29 17:01:57 -04:00
char * szName = in . ReadString ( ) ;
if ( in . GetLastError ( ) ) break ;
m_pEvents - > LoginCharacter ( dwGUID , /*szName*/ GetAccount ( ) ) ;
}
break ;
}
// modified cmoski code
case 0xF7DE :
{ //Gets data from /general here to rebroadcast as a world message below \o/
2019-07-07 20:56:15 +00:00
uint32_t size = in . ReadUInt32 ( ) ;
uint32_t TurbineChatType = in . ReadUInt32 ( ) ; //0x1 Inbound, 0x3 Outbound, 0x5 Outbound Ack
uint32_t unk1 = in . ReadUInt32 ( ) ;
uint32_t unk2 = in . ReadUInt32 ( ) ;
uint32_t unk3 = in . ReadUInt32 ( ) ;
uint32_t unk4 = in . ReadUInt32 ( ) ;
uint32_t unk5 = in . ReadUInt32 ( ) ;
uint32_t unk6 = in . ReadUInt32 ( ) ;
uint32_t payload = in . ReadUInt32 ( ) ;
2018-03-29 17:01:57 -04:00
if ( in . GetLastError ( ) )
break ;
if ( TurbineChatType = = 0x3 ) //0x3 Outbound
{
if ( ! m_pEvents - > GetPlayer ( ) | | ! m_pEvents - > CheckForChatSpam ( ) )
break ;
2019-07-07 20:56:15 +00:00
uint32_t serial = in . ReadUInt32 ( ) ; // serial of this character's chat
uint32_t channel_unk = in . ReadUInt32 ( ) ;
uint32_t channel_unk2 = in . ReadUInt32 ( ) ;
uint32_t listening_channel = in . ReadUInt32 ( ) ; // ListeningChannel in SetTurbineChatChannels (0x000BEEF0-9)
//std::string message = in.ReadWStringToString();
std : : u16string message = in . ReadString16 ( ) ;
uint32_t payloadSize = in . ReadUInt32 ( ) ;
uint32_t playerGUID = in . ReadUInt32 ( ) ;
uint32_t ob_unknown = in . ReadUInt32 ( ) ; //Always 0?
uint32_t ob_unknown2 = in . ReadUInt32 ( ) ;
std : : u16string filteredText = FilterBadChatCharacters ( message ) ;
2018-03-29 17:01:57 -04:00
if ( in . GetLastError ( ) | | ! filteredText . size ( ) )
break ;
BinaryWriter chatAck ;
2019-07-07 20:56:15 +00:00
chatAck . Write < uint32_t > ( 0xF7DE ) ;
chatAck . Write < uint32_t > ( 0x30 ) ; // Size
chatAck . Write < uint32_t > ( 0x05 ) ; // Type 05 - ACK
chatAck . Write < uint32_t > ( 0x02 ) ; // ??
chatAck . Write < uint32_t > ( 0x01 ) ; // ??
chatAck . Write < uint32_t > ( 0xB0045 ) ; // bitfield?
chatAck . Write < uint32_t > ( 0x01 ) ;
chatAck . Write < uint32_t > ( 0xB0045 ) ; // bitfield?
chatAck . Write < uint32_t > ( 0x00 ) ;
chatAck . Write < uint32_t > ( 0x10 ) ; // Payload size
chatAck . Write < uint32_t > ( serial ) ; // serial
chatAck . Write < uint32_t > ( 0x02 ) ;
chatAck . Write < uint32_t > ( 0x02 ) ;
chatAck . Write < uint32_t > ( 0x00 ) ;
2018-03-29 17:01:57 -04:00
SendNetMessage ( & chatAck , 0x04 , FALSE , FALSE ) ;
if ( filteredText . c_str ( ) [ 0 ] = = ' ! ' | | filteredText . c_str ( ) [ 0 ] = = ' @ ' | | filteredText . c_str ( ) [ 0 ] = = ' / ' )
{
CommandBase : : Execute ( ( char * ) filteredText . erase ( 0 , 1 ) . c_str ( ) , m_pEvents - > GetPlayer ( ) - > GetClient ( ) ) ;
}
else
{
2018-09-21 06:16:42 -07:00
if ( ! m_pEvents - > GetPlayer ( ) - > IsPlayerSquelched ( playerGUID ) )
2018-03-29 17:01:57 -04:00
{
2018-08-22 02:46:47 -05:00
2018-09-21 06:16:42 -07:00
switch ( listening_channel )
{
case General_ChatChannel :
case Trade_ChatChannel :
case LFG_ChatChannel :
case Roleplay_ChatChannel :
case Allegiance_ChatChannel :
2020-08-07 10:58:05 -07:00
// case Olthoi_ChatChannel:
case Society_ChatChannel :
2018-09-21 06:16:42 -07:00
if ( listening_channel > 1 & & ! g_pConfig - > AllowGeneralChat ( ) )
break ;
2020-08-07 10:58:05 -07:00
if ( m_pEvents - > IsServerGagged ( ) & & listening_channel ! = Allegiance_ChatChannel )
break ;
if ( m_pEvents - > IsAllegGagged ( ) & & listening_channel = = Allegiance_ChatChannel )
break ;
2018-09-21 06:16:42 -07:00
g_pWorld - > BroadcastChatChannel ( listening_channel , m_pEvents - > GetPlayer ( ) , filteredText ) ;
break ;
}
2018-03-29 17:01:57 -04:00
}
}
}
break ;
}
default :
2018-04-27 21:03:39 -07:00
SERVER_INFO < < " Unhandled response " < < dwMessageCode < < " from the client. " ;
2018-03-29 17:01:57 -04:00
break ;
}
//if ( dwMessageCode != 0xF7B1 )
// LOG(Temp, Normal, "Received response %04X\n", dwMessageCode);
}
BOOL CClient : : CheckAccount ( const char * cmp )
{
2019-07-07 20:56:15 +00:00
return ! stricmp ( m_vars . account . c_str ( ) , cmp ) ;
2018-03-29 17:01:57 -04:00
}
int CClient : : GetAccessLevel ( )
{
return m_AccountInfo . access ;
}
void CClient : : SetAccessLevel ( unsigned int access )
{
m_AccountInfo . access = access ;
}
BOOL CClient : : CheckAddress ( SOCKADDR_IN * peer )
{
2019-12-16 18:25:30 -05:00
return ! memcmp ( & GetHostAddress ( ) - > sin_addr , & peer - > sin_addr , sizeof ( in_addr ) ) ;
2018-03-29 17:01:57 -04:00
}
WORD CClient : : GetSlot ( )
{
return m_vars . slot ;
}
const char * CClient : : GetAccount ( )
{
return m_vars . account . c_str ( ) ;
}
const char * CClient : : GetDescription ( )
{
// Must lead with index or the kick/ban feature won't function.
return csprintf ( " #%u %s \" %s \" " , m_vars . slot , inet_ntoa ( m_vars . addr . sin_addr ) , m_vars . account . c_str ( ) ) ;
}
2019-07-07 20:56:15 +00:00
void CClient : : SetLoginData ( uint32_t dwUnixTime , uint32_t dwPortalStamp , uint32_t dwCellStamp )
2018-03-29 17:01:57 -04:00
{
m_vars . fLoginTime = g_pGlobals - > Time ( ) ;
m_vars . ClientLoginUnixTime = dwUnixTime ;
m_vars . PortalStamp = dwPortalStamp ;
m_vars . CellStamp = dwCellStamp ;
m_vars . bInitDats = FALSE ;
}
SOCKADDR_IN * CClient : : GetHostAddress ( )
{
return & m_vars . addr ;
}