CharacterComponent::CharacterComponent(Entity &entity, MessageIn &msg): mClient(NULL), mConnected(true), mTransactionHandler(NULL), mSpecialUpdateNeeded(false), mDatabaseID(-1), mHairStyle(0), mHairColor(0), mLevel(1), mLevelProgress(0), mUpdateLevelProgress(false), mRecalculateLevel(true), mParty(0), mTransaction(TRANS_NONE), mTalkNpcId(0), mNpcThread(0), mKnuckleAttackInfo(0), mBaseEntity(&entity) { auto *beingComponent = entity.getComponent<BeingComponent>(); const AttributeManager::AttributeScope &attributes = attributeManager->getAttributeScope(CharacterScope); LOG_DEBUG("Character creation: initialisation of " << attributes.size() << " attributes."); for (auto attributeScope : attributes) beingComponent->createAttribute(attributeScope.first, *attributeScope.second); auto *actorComponent = entity.getComponent<ActorComponent>(); actorComponent->setWalkMask(Map::BLOCKMASK_WALL); actorComponent->setBlockType(BLOCKTYPE_CHARACTER); actorComponent->setSize(16); CombatComponent *combatcomponent = new CombatComponent(entity); entity.addComponent(combatcomponent); combatcomponent->getAttacks().attack_added.connect( sigc::mem_fun(this, &CharacterComponent::attackAdded)); combatcomponent->getAttacks().attack_removed.connect( sigc::mem_fun(this, &CharacterComponent::attackRemoved)); // Default knuckle attack int damageBase = beingComponent->getModifiedAttribute(ATTR_STR); int damageDelta = damageBase / 2; Damage knuckleDamage; knuckleDamage.skill = skillManager->getDefaultSkillId(); knuckleDamage.base = damageBase; knuckleDamage.delta = damageDelta; knuckleDamage.cth = 2; knuckleDamage.element = ELEMENT_NEUTRAL; knuckleDamage.type = DAMAGE_PHYSICAL; knuckleDamage.range = DEFAULT_TILE_LENGTH; mKnuckleAttackInfo = new AttackInfo(0, knuckleDamage, 7, 3, 0); combatcomponent->addAttack(mKnuckleAttackInfo); // Get character data. mDatabaseID = msg.readInt32(); beingComponent->setName(msg.readString()); CharacterData characterData(&entity, this); deserializeCharacterData(characterData, msg); Inventory(&entity, mPossessions).initialize(); modifiedAllAttributes(entity);; beingComponent->signal_attribute_changed.connect(sigc::mem_fun( this, &CharacterComponent::attributeChanged)); }
void CLobbyServerPlayer::ProcessGetCharacters(const PacketData& packetData) { CLog::GetInstance().LogMessage(LOG_NAME, "GetCharacters"); if(m_dbConnection.IsEmpty()) { CLog::GetInstance().LogMessage(LOG_NAME, "No database connection available. Bailing."); m_disconnect = true; return; } PacketData outgoingPacket(std::begin(g_characterListPacket), std::end(g_characterListPacket)); CCharacter character; try { auto query = string_format("SELECT * FROM ffxiv_characters WHERE userId = %d", m_userId); auto result = m_dbConnection.Query(query.c_str()); if(result.GetRowCount() != 0) { character = CCharacter(result); } } catch(const std::exception& exception) { CLog::GetInstance().LogError(LOG_NAME, "Failed to fetch characters for user (id = %d): %s", m_userId, exception.what()); m_disconnect = true; return; } PacketData characterData(std::begin(g_characterData), std::end(g_characterData)); characterData[0x21] = CCharacter::GetModelFromTribe(character.tribe); characterData[0x9F] = character.tribe; characterData[0xC7] = character.guardian; characterData[0xC8] = character.birthMonth; characterData[0xC9] = character.birthDay; characterData[0xE8] = character.allegiance; *reinterpret_cast<uint32*>(&characterData[0x25]) = character.size; //size *reinterpret_cast<uint32*>(&characterData[0x29]) = character.GetColorInfo(); //hairColor + skinColor *reinterpret_cast<uint32*>(&characterData[0x2D]) = character.GetFaceInfo(); //face Stuff? *reinterpret_cast<uint32*>(&characterData[0x31]) = character.hairStyle << 10; //hair model *reinterpret_cast<uint32*>(&characterData[0x35]) = character.voice; //voice *reinterpret_cast<uint32*>(&characterData[0x39]) = character.weapon1; //weapon1 *reinterpret_cast<uint32*>(&characterData[0x3D]) = character.weapon2; //weapon2 *reinterpret_cast<uint32*>(&characterData[0x55]) = character.headGear; //headGear *reinterpret_cast<uint32*>(&characterData[0x59]) = character.bodyGear; //bodyGear *reinterpret_cast<uint32*>(&characterData[0x5D]) = character.legsGear; //legsGear *reinterpret_cast<uint32*>(&characterData[0x61]) = character.handsGear; //handsGear *reinterpret_cast<uint32*>(&characterData[0x65]) = character.feetGear; //feetGear *reinterpret_cast<uint32*>(&characterData[0x69]) = character.waistGear; //waistGear // *reinterpret_cast<uint32*>(&characterData[0x6D]) = 0; //??? *reinterpret_cast<uint32*>(&characterData[0x71]) = character.rightEarGear; //rightEarGear *reinterpret_cast<uint32*>(&characterData[0x75]) = character.leftEarGear; //leftEarGear // *reinterpret_cast<uint32*>(&characterData[0x79]) = 0; //??? // *reinterpret_cast<uint32*>(&characterData[0x7D]) = 0; //??? *reinterpret_cast<uint32*>(&characterData[0x81]) = character.rightFingerGear; //rightFingerGear *reinterpret_cast<uint32*>(&characterData[0x85]) = character.leftFingerGear; //leftFingerGear auto encodedCharacterData = Framework::ToBase64(characterData.data(), characterData.size()); std::replace(std::begin(encodedCharacterData), std::end(encodedCharacterData), '+', '-'); std::replace(std::begin(encodedCharacterData), std::end(encodedCharacterData), '/', '_'); static const uint32 characterInfoBase = 0x860; if(character.active) { for(unsigned int i = 0; i < encodedCharacterData.size(); i++) { outgoingPacket[characterInfoBase + 0x40 + i] = encodedCharacterData[i]; } *reinterpret_cast<uint32*>(&outgoingPacket[characterInfoBase + 0x00]) = 0x0158E7FC; *reinterpret_cast<uint32*>(&outgoingPacket[characterInfoBase + 0x04]) = character.id; *reinterpret_cast<uint32*>(&outgoingPacket[characterInfoBase + 0x0C]) = 0x000000F4; //Insert character name for(unsigned int i = 0; i < character.name.size(); i++) { outgoingPacket[characterInfoBase + 0x10 + i] = character.name[i]; } outgoingPacket[characterInfoBase + 0x10 + character.name.size()] = 0; } CPacketUtils::EncryptPacket(outgoingPacket); QueuePacket(outgoingPacket); }