Ejemplo n.º 1
0
int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum)
{
	/*  if an invalid bind point is specified, use the primary bind */
	if (bindnum > 4)
	{
		bindnum = 0;
	}

	std::string query = StringFormat("SELECT zone_id, instance_id, x, y, z FROM character_bind WHERE id = %u AND slot = %u LIMIT 1", CharID, bindnum);
	auto results = database.QueryDatabase(query);
	if(!results.Success() || results.RowCount() == 0) {
		return 0;
	}

	int zone_id, instance_id;
	double x, y, z, heading;
	for (auto row = results.begin(); row != results.end(); ++row) {
		zone_id = atoi(row[0]);
		instance_id = atoi(row[1]);
		x = atof(row[2]);
		y = atof(row[3]);
		z = atof(row[4]);
		heading = atof(row[5]);
	}

	query = StringFormat("UPDATE character_data SET zone_id = '%d', zone_instance = '%d', x = '%f', y = '%f', z = '%f', heading = '%f' WHERE id = %u", 
						 zone_id, instance_id, x, y, z, heading, CharID);

	results = database.QueryDatabase(query);
	if(!results.Success()) {
		return 0;
	}

	return zone_id;
}
Ejemplo n.º 2
0
// the current stuff is at the bottom of this function
void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **outApp, uint32 clientVersionBit)
{
	/* Set Character Creation Limit */
	ClientVersion client_version = ClientVersionFromBit(clientVersionBit);
	size_t character_limit = EQLimits::CharacterCreationLimit(client_version);
	
	// Validate against absolute server max
	if (character_limit > EmuConstants::CHARACTER_CREATION_LIMIT)
		character_limit = EmuConstants::CHARACTER_CREATION_LIMIT;

	// Force Titanium clients to use '8'
	if (client_version == ClientVersion::Titanium)
		character_limit = 8;
	
	/* Get Character Info */
	std::string cquery = StringFormat(
		"SELECT                     "
		"`id`,                      "  // 0
		"name,                      "  // 1
		"gender,                    "  // 2
		"race,                      "  // 3
		"class,                     "  // 4
		"`level`,                   "  // 5
		"deity,                     "  // 6
		"last_login,                "  // 7
		"time_played,               "  // 8
		"hair_color,                "  // 9
		"beard_color,               "  // 10
		"eye_color_1,               "  // 11
		"eye_color_2,               "  // 12
		"hair_style,                "  // 13
		"beard,                     "  // 14
		"face,                      "  // 15
		"drakkin_heritage,          "  // 16
		"drakkin_tattoo,            "  // 17
		"drakkin_details,           "  // 18
		"zone_id		            "  // 19
		"FROM                       "
		"character_data             "
		"WHERE `account_id` = %i ORDER BY `name` LIMIT %u", accountID, character_limit);
	auto results = database.QueryDatabase(cquery);

	size_t character_count = results.RowCount();
	if (character_count == 0) {
		*outApp = new EQApplicationPacket(OP_SendCharInfo, sizeof(CharacterSelect_Struct));
		CharacterSelect_Struct *cs = (CharacterSelect_Struct *)(*outApp)->pBuffer;
		cs->CharCount = 0;
		cs->TotalChars = character_limit;
		return;
	}

	size_t packet_size = sizeof(CharacterSelect_Struct) + (sizeof(CharacterSelectEntry_Struct) * character_count);
	*outApp = new EQApplicationPacket(OP_SendCharInfo, packet_size);

	unsigned char *buff_ptr = (*outApp)->pBuffer;
	CharacterSelect_Struct *cs = (CharacterSelect_Struct *)buff_ptr;

	cs->CharCount = character_count;
	cs->TotalChars = character_limit;

	buff_ptr += sizeof(CharacterSelect_Struct);
	for (auto row = results.begin(); row != results.end(); ++row) {
		CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr;
		PlayerProfile_Struct pp;
		Inventory inv;
		uint32 character_id = (uint32)atoi(row[0]);
		uint8 has_home = 0;
		uint8 has_bind = 0;

		memset(&pp, 0, sizeof(PlayerProfile_Struct));
		
		/* Fill CharacterSelectEntry_Struct */
		memset(cse->Name, 0, sizeof(cse->Name));
		strcpy(cse->Name, row[1]);
		cse->Class = (uint8)atoi(row[4]);
		cse->Race = (uint32)atoi(row[3]);
		cse->Level = (uint8)atoi(row[5]);
		cse->ShroudClass = cse->Class;
		cse->ShroudRace = cse->Race;
		cse->Zone = (uint16)atoi(row[19]);
		cse->Instance = 0;
		cse->Gender = (uint8)atoi(row[2]);
		cse->Face = (uint8)atoi(row[15]);

		for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) {	// Processed below
			cse->Equip[matslot].Material = 0;
			cse->Equip[matslot].Unknown1 = 0;
			cse->Equip[matslot].EliteMaterial = 0;
			cse->Equip[matslot].HeroForgeModel = 0;
			cse->Equip[matslot].Material2 = 0;
			cse->Equip[matslot].Color.Color = 0;
		}						

		cse->Unknown15 = 0xFF;
		cse->Unknown19 = 0xFF;
		cse->DrakkinTattoo = (uint32)atoi(row[17]);
		cse->DrakkinDetails = (uint32)atoi(row[18]);
		cse->Deity = (uint32)atoi(row[6]);
		cse->PrimaryIDFile = 0;							// Processed Below
		cse->SecondaryIDFile = 0;						// Processed Below
		cse->HairColor = (uint8)atoi(row[9]);
		cse->BeardColor = (uint8)atoi(row[10]);
		cse->EyeColor1 = (uint8)atoi(row[11]);
		cse->EyeColor2 = (uint8)atoi(row[12]);
		cse->HairStyle = (uint8)atoi(row[13]);
		cse->Beard = (uint8)atoi(row[14]);
		cse->GoHome = 0;								// Processed Below
		cse->Tutorial = 0;								// Processed Below
		cse->DrakkinHeritage = (uint32)atoi(row[16]);
		cse->Unknown1 = 0;
		cse->Enabled = 1;
		cse->LastLogin = (uint32)atoi(row[7]);			// RoF2 value: 1212696584
		cse->Unknown2 = 0;
		/* Fill End */

		if (RuleB(World, EnableReturnHomeButton)) {
			int now = time(nullptr);
			if ((now - atoi(row[7])) >= RuleI(World, MinOfflineTimeToReturnHome))
				cse->GoHome = 1;
		}

		if (RuleB(World, EnableTutorialButton) && (cse->Level <= RuleI(World, MaxLevelForTutorial))) {
			cse->Tutorial = 1;
		}

		/* Set Bind Point Data for any character that may possibly be missing it for any reason */
		cquery = StringFormat("SELECT `zone_id`, `instance_id`, `x`, `y`, `z`, `heading`, `slot` FROM `character_bind`  WHERE `id` = %i LIMIT 5", character_id);
		auto results_bind = database.QueryDatabase(cquery);
		for (auto row_b = results_bind.begin(); row_b != results_bind.end(); ++row_b) {
			if (row_b[6] && atoi(row_b[6]) == 4){ has_home = 1; }
			if (row_b[6] && atoi(row_b[6]) == 0){ has_bind = 1; }
		}

		if (has_home == 0 || has_bind == 0) {
			cquery = StringFormat("SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
				cse->Class, cse->Deity, cse->Race);
			auto results_bind = database.QueryDatabase(cquery);
			for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
				/* If a bind_id is specified, make them start there */
				if (atoi(row_d[1]) != 0) {
					pp.binds[4].zoneId = (uint32)atoi(row_d[1]);
					GetSafePoints(pp.binds[4].zoneId, 0, &pp.binds[4].x, &pp.binds[4].y, &pp.binds[4].z);
				}
				/* Otherwise, use the zone and coordinates given */
				else {
					pp.binds[4].zoneId = (uint32)atoi(row_d[0]);
					float x = atof(row_d[2]);
					float y = atof(row_d[3]);
					float z = atof(row_d[4]);
					if (x == 0 && y == 0 && z == 0){ GetSafePoints(pp.binds[4].zoneId, 0, &x, &y, &z); }
					pp.binds[4].x = x; pp.binds[4].y = y; pp.binds[4].z = z;
				}
			}
			pp.binds[0] = pp.binds[4];
			/* If no home bind set, set it */
			if (has_home == 0) {
				std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
					" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
					character_id, pp.binds[4].zoneId, 0, pp.binds[4].x, pp.binds[4].y, pp.binds[4].z, pp.binds[4].heading, 4);
				auto results_bset = QueryDatabase(query);
			}
			/* If no regular bind set, set it */
			if (has_bind == 0) {
				std::string query = StringFormat("REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
					" VALUES (%u, %u, %u, %f, %f, %f, %f, %i)",
					character_id, pp.binds[0].zoneId, 0, pp.binds[0].x, pp.binds[0].y, pp.binds[0].z, pp.binds[0].heading, 0);
				auto results_bset = QueryDatabase(query);
			}
		}
		/* Bind End */

		/* Load Character Material Data for Char Select */
		cquery = StringFormat("SELECT slot, red, green, blue, use_tint, color FROM `character_material` WHERE `id` = %u", character_id);
		auto results_b = database.QueryDatabase(cquery); uint8 slot = 0;
		for (auto row_b = results_b.begin(); row_b != results_b.end(); ++row_b) {
			slot = atoi(row_b[0]);
			pp.item_tint[slot].RGB.Red = atoi(row_b[1]);
			pp.item_tint[slot].RGB.Green = atoi(row_b[2]);
			pp.item_tint[slot].RGB.Blue = atoi(row_b[3]);
			pp.item_tint[slot].RGB.UseTint = atoi(row_b[4]);
		}
		/* Character Material Data End */

		/* Load Inventory */
		// If we ensure that the material data is updated appropriately, we can do away with inventory loads
		if (GetInventory(accountID, cse->Name, &inv)) {
			const Item_Struct* item = nullptr;
			const ItemInst* inst = nullptr;
			int16 invslot = 0;

			for (uint32 matslot = 0; matslot < _MaterialCount; matslot++) {
				invslot = Inventory::CalcSlotFromMaterial(matslot);
				if (invslot == INVALID_INDEX) { continue; }
				inst = inv.GetItem(invslot);
				if (inst == nullptr) { continue; }
				item = inst->GetItem();
				if (item == nullptr) { continue; }

				if (matslot > 6) {
					uint32 idfile = 0;
					// Weapon Models 
					if (inst->GetOrnamentationIDFile() != 0) {
						idfile = inst->GetOrnamentationIDFile();
						cse->Equip[matslot].Material = idfile;
					}
					else {
						if (strlen(item->IDFile) > 2) {
							idfile = atoi(&item->IDFile[2]);
							cse->Equip[matslot].Material = idfile;
						}
					}
					if (matslot == MaterialPrimary) {
						cse->PrimaryIDFile = idfile;
					}
					else {
						cse->SecondaryIDFile = idfile;
					}
				}
				else {
					uint32 color = 0;
					if (pp.item_tint[matslot].RGB.UseTint) {
						color = pp.item_tint[matslot].Color;
					}
					else {
						color = inst->GetColor();
					}

					// Armor Materials/Models
					cse->Equip[matslot].Material = item->Material;
					cse->Equip[matslot].EliteMaterial = item->EliteMaterial;
					cse->Equip[matslot].HeroForgeModel = inst->GetOrnamentHeroModel(matslot);
					cse->Equip[matslot].Color.Color = color;
				}
			}
		}
		else {
			printf("Error loading inventory for %s\n", cse->Name);
		}
		/* Load Inventory End */

		buff_ptr += sizeof(CharacterSelectEntry_Struct);
	}
}