mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
Increased world load speed by almost 20% by reducing how often loading progress is written to the console Increased world save speed by almost 50% through the use of binary mode and buffer tweaks for ofstream combined with a cached newline char and std::to_string instead of static_cast Fixed a server crash involving killing NPCs of a specific spawn region using the 'spawnkill # command Fixed a server crash involving moving items from decaying corpses to the ground Fixed a server crash involving carving up human corpses Fixed a server crash related to AreaCharacterFunction JS function, which could trigger for any script that potentially kills any NPC this function iterates over (like explosion potions) Fixed a server crash related to GMs attempting to add items from add-menu while having no backpack Fixed a client crash issue caused by attempting to sell house deeds back to architect NPCs Fixed an issue where players would get incorrect amounts of gold for selling house deeds back to architect NPCs Fixed an issue with characters dying onboard boats which prevented players from packing up the boats later Added new item property in code (via bools bitset) that can be used to enable/disable maker's mark on crafted items. This property can be set to true for items crafted at exceptional quality by GM craftsmen Exposed the new item property to JS engine: .isMarkedByMaker // If true, maker's mark will be displayed Updated default item tooltip to display " of exceptional quality" for items crafted with exceptional quality Updated default item tooltip to display "[Crafted] by [Crafter's Name]" for exceptional quality items crafted by GM craftsmen. The [Crafted] text comes from the MADEWORD defined in dfndata/skills/skills.dfn for the primary skill used to craft the item Updated old-school single-click names for items (when AoS bit is disabled in client/server features) to display exceptional status and/or maker's mark for appropriate items Fixed an issue with the display of titles for NPCs that used dictionary lookups for their title Added new UOX.INI settings under the [settings] section: DISPLAYMAKERSMARK=1/0 // Controls if maker's marks on crafted items are shown on a global level SHOWNPCTITLESOVERHEAD=1/0 // Controls whether NPC titles are shown over their heads SHOWINVULNERABLETAGOVERHEAD=0/1 // Controls whether invulnerable tags are shown overhead GLOBALRESTOCKMULTIPLIER=1.0 // Global multiplier applied to RESTOCK property of items when loaded from DFNs Added new UOX.INI settings under the [combat] section: PETCOMBATTRAINING=1/0 // Controls whether pets can gain skills/stats from combat HIRELINGCOMBATTRAINING=1/0 // Controls whether hirelings can gain skills/stats from combat NPCCOMBATTRAINING=0/1 // Controls whether NPCs in general can gain skills/stats from combat Fixed an issue where a player meeting the exact minimum requirements for crafting an item would always fail Fixed a bug with teleporting off boats to valid nearby locations when double-clicking boat planks while standing on it Updated behaviour of planks on boats: Boat key can unlock plank, but won't automatically open it Boat key used on an open, unlocked plank will lock and automatically close the plank Boat key used on an open, locked plank will unlock the plank and leave it open Player using an unlocked plank now opens it Player using an open plank will disembark (if onboard) or embark (if not) the boat Player can always open a locked plank if they're on the boat, even with no key, to allow disembarking the boat. Planks that are open, but locked cannot be accessed from outside the boat, and will close automatically after five of seconds Updated behaviour of Magic Lock/Unlock spells: Magic Lock cannot be used on objects inside a multi Magic Lock applies difficulty to lock based on caster's Magery skill Magic Lock effect will last between 7 to 50 seconds (depending on caster's Magery skill) Any object that can be locked via Magic Lock spell can also be unlocked via Magic Unlock spell, if caster has high enough Magery skill Fixed a bug where certain JS Functions, Methods and Properties would occasionally pass incorrect values to scripts that called upon them. Scripts that rely on the GetCurrentClock() Function, the .GetTimer() Method, .decayTime, .logTime, .oreTime and .fishTime Properties might need to be updated to account for the fix, which causes larger values to be passed in than before. Fixed a bug related to GetCurrentClock() that caused decay and respawning of dungeon chests from working properly Fixed a bug related to GetCurrentClock() and .logTime/.fishTime that prevented consumption and regeneration of log/fish resources from working properly Added a new JS Function: GetStartTime() // Returns a timestamp for when server started up Fixed a bug related to GetCurrentClock() where server uptime stats in help menu was showing up incorrectly Fixed a bug related to GetCurrentClock() and purging of registrations of visitors in public houses so their visits can be counted again later Fixed a bug related to GetCurrentClock() that caused monster speech to not work properly Fixed a Z-related issue that sometimes prevented players from fishing when standing on the shoreline next to the sea Fixed an issue with Animal Lore skill that would always return a pet's loyalty level as "Wild" Increased max range pets can be from their owner in order to still be included in moongate/teleporter travel from 12 to 24 tiles Fixed an issue where the alchemy bonus damage for explosion potions was off by an order of magnitude Fixed an issue where food IDs from foodlists referenced by other foodlists was not detected as valid food for tamed pets or NPCs Fixed an issue where Alchemy crafting skill did not properly check for the existence of the crafting tool before proceeding with the crafting process Fixed an issue that prevented the Teleport spell from working as intended Fixed an issue where players would still get 1 gold even if STARTGOLD in uox.ini was set to 0 Fixed an issue with mount restrictions script that prevented players from mounting Unicorns, Ki-rins and Cu Sidhes Fixed an issue where aggressive creatures wouldn't stop attacking player after being tamed (js/skill/taming.js) Added a system message to inform the player when they've dropped out of stealth due to taking too many steps Fixed an issue where hunger level of NPCs instantly dropped upon spawning because hunger timer was not active yet Fixed a bug where character corpses would appear with a [unidentified] tag attached Fixed an issue where the [unidentified] tag did not show up for unidentified magic items Added ANIMAL tag to a small bunch of creature definitions (dfndata/creatures/creatures.dfn) Fixed an issue with Bowcraft skill where player could not gain enough skill from crafting bows to reach min requirement for crossbows, and similiarly could not reach min requirement for heavy crossbows from crossbows Updated default value of MURDERDECAYTIMER INI setting from 60 seconds to 28800 seconds (8 hours), to match the amount of time it would take for one (short term) murder count to decay on LBR-era OSI shards.
1021 lines
38 KiB
C++
1021 lines
38 KiB
C++
#include "uox3.h"
|
|
#include "classes.h"
|
|
#include "regions.h"
|
|
#include "StringUtility.hpp"
|
|
#include "ObjectFactory.h"
|
|
#include <filesystem>
|
|
|
|
#define DEBUG_REGIONS 0
|
|
|
|
CMapHandler *MapRegion;
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI32 FileSize( std::string filename )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the filesize of a given file
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI32 FileSize( std::string filename )
|
|
{
|
|
SI32 retVal = 0;
|
|
|
|
try {
|
|
retVal = static_cast<SI32>(std::filesystem::file_size( filename ));
|
|
} catch( ... ) {
|
|
retVal = 0;
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadChar( std::ifstream& readDestination )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a new character object based on data loaded from worldfiles
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void LoadChar( std::ifstream& readDestination )
|
|
{
|
|
CChar *x = static_cast< CChar * >(ObjectFactory::getSingleton().CreateBlankObject( OT_CHAR ));
|
|
if( x == nullptr )
|
|
return;
|
|
if( !x->Load( readDestination ) )
|
|
{
|
|
x->Cleanup();
|
|
ObjectFactory::getSingleton().DestroyObject( x );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadItem( std::ifstream& readDestination )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a new item object based on data loaded from worldfiles
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void LoadItem( std::ifstream& readDestination )
|
|
{
|
|
CItem *x = static_cast< CItem * >(ObjectFactory::getSingleton().CreateBlankObject( OT_ITEM ));
|
|
if( x == nullptr )
|
|
return;
|
|
if( !x->Load( readDestination ) )
|
|
{
|
|
x->Cleanup();
|
|
ObjectFactory::getSingleton().DestroyObject( x );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadMulti( std::ifstream& readDestination )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a new multi object, like a house, based on data loaded from worldfiles
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void LoadMulti( std::ifstream& readDestination )
|
|
{
|
|
CMultiObj *ourHouse = static_cast< CMultiObj * >(ObjectFactory::getSingleton().CreateBlankObject( OT_MULTI ));
|
|
if( !ourHouse->Load( readDestination ) ) // if no load, DELETE
|
|
{
|
|
ourHouse->Cleanup();
|
|
ObjectFactory::getSingleton().DestroyObject( ourHouse );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadBoat( std::ifstream& readDestination )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a new boat object based on data loaded from worldfiles
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void LoadBoat( std::ifstream& readDestination )
|
|
{
|
|
CBoatObj *ourBoat = static_cast< CBoatObj * >(ObjectFactory::getSingleton().CreateBlankObject( OT_BOAT ));
|
|
if( !ourBoat->Load( readDestination ) ) // if no load, DELETE
|
|
{
|
|
ourBoat->Cleanup();
|
|
ObjectFactory::getSingleton().DestroyObject( ourBoat );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadSpawnItem( std::ifstream& readDestination )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a new spawn object based on data loaded from worldfiles
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void LoadSpawnItem( std::ifstream& readDestination )
|
|
{
|
|
CSpawnItem *ourSpawner = static_cast< CSpawnItem * >(ObjectFactory::getSingleton().CreateBlankObject( OT_SPAWNER ));
|
|
if( !ourSpawner->Load( readDestination ) ) // if no load, DELETE
|
|
{
|
|
ourSpawner->Cleanup();
|
|
ObjectFactory::getSingleton().DestroyObject( ourSpawner );
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Functio - void SaveToDisk( std::ofstream& writeDestination )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Save all items and characters inside a subregion reworked SaveChar from WorldMain
|
|
//| to deal with pointer based stuff in region rather than index based stuff in array
|
|
//| Also saves out all data regardless (in preparation for a simple binary save)
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapRegion::SaveToDisk( std::ofstream& writeDestination )
|
|
{
|
|
std::vector<CChar *> removeChar ;
|
|
for (const auto &charToWrite: charData.collection()) {
|
|
if( !ValidateObject( charToWrite ) ){
|
|
removeChar.push_back(charToWrite);
|
|
}
|
|
else {
|
|
#if defined( _MSC_VER )
|
|
#pragma todo( "PlayerHTML Dumping needs to be reimplemented" )
|
|
#endif
|
|
if( charToWrite->ShouldSave() ){
|
|
charToWrite->Save( writeDestination );
|
|
}
|
|
}
|
|
}
|
|
std::for_each(removeChar.begin(), removeChar.end(), [this](CChar *character) {
|
|
charData.Remove(character);
|
|
});
|
|
|
|
std::vector<CItem *> removeItem ;
|
|
for (const auto &itemToWrite: itemData.collection()) {
|
|
if( !ValidateObject( itemToWrite ) ) {
|
|
removeItem.push_back(itemToWrite);
|
|
}
|
|
else {
|
|
if( itemToWrite->ShouldSave() ) {
|
|
if( itemToWrite->GetObjType() == OT_MULTI ) {
|
|
CMultiObj *iMulti = static_cast<CMultiObj *>(itemToWrite);
|
|
iMulti->Save( writeDestination );
|
|
}
|
|
else if( itemToWrite->GetObjType() == OT_BOAT ) {
|
|
CBoatObj *iBoat = static_cast< CBoatObj * >(itemToWrite);
|
|
iBoat->Save( writeDestination );
|
|
}
|
|
else{
|
|
itemToWrite->Save( writeDestination );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
std::for_each(removeItem.begin(), removeItem.end(), [this](CItem *item) {
|
|
itemData.Remove(item);
|
|
});
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - GenericList< CItem * > * GetItemList( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the Item DataList for iteration
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
GenericList< CItem * > * CMapRegion::GetItemList( void )
|
|
{
|
|
return &itemData;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - GenericList< CChar * > * GetCharList( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the Character DataList for iteration
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
GenericList< CChar * > * CMapRegion::GetCharList( void )
|
|
{
|
|
return &charData;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - RegionSerialList< SERIAL > * GetRegionSerialList( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the list of baseobject serials for iteration
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
RegionSerialList* CMapRegion::GetRegionSerialList()
|
|
{
|
|
return ®ionSerialData;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool HasRegionChanged( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns a flag that says whether the region has seen any updates since last save
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapRegion::HasRegionChanged( void )
|
|
{
|
|
return hasRegionChanged;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void HasRegionChanged( void )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Sets a flag that says whether the region has seen any updates since last save
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapRegion::HasRegionChanged( bool newVal )
|
|
{
|
|
hasRegionChanged = newVal;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapWorld Constructor/Destructor
|
|
//| Date - 17 October, 2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Initializes & Clears the MapWorld data
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CMapWorld::CMapWorld() : upperArrayX( 0 ), upperArrayY( 0 ), resourceX( 0 ), resourceY( 0 )
|
|
{
|
|
mapResources.resize( 1 ); // ALWAYS initialize at least one resource region.
|
|
mapRegions.resize( 0 );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapWorld::CMapWorld( UI08 worldNum )
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Initializes resource regions for the given world
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CMapWorld::CMapWorld( UI08 worldNum )
|
|
{
|
|
auto [width,height] = Map->sizeOfMap(worldNum);
|
|
upperArrayX = static_cast<SI16>(width / MapColSize);
|
|
upperArrayY = static_cast<SI16>(height/ MapRowSize);
|
|
resourceX = static_cast<UI16>(width / cwmWorldState->ServerData()->ResourceAreaSize());
|
|
resourceY = static_cast<UI16>(height / cwmWorldState->ServerData()->ResourceAreaSize());
|
|
|
|
size_t resourceSize = (static_cast<size_t>(resourceX) * static_cast<size_t>(resourceY));
|
|
if( resourceSize < 1 ) // ALWAYS initialize at least one resource region.
|
|
resourceSize = 1;
|
|
mapResources.resize( resourceSize );
|
|
|
|
mapRegions.resize( static_cast<size_t>(upperArrayX) * static_cast<size_t>(upperArrayY) );
|
|
}
|
|
|
|
CMapWorld::~CMapWorld()
|
|
{
|
|
mapResources.resize( 0 );
|
|
mapRegions.resize( 0 );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapRegion * GetMapRegion( SI16 xOffset, SI16 yOffset )
|
|
//| Date - 9/13/2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the MapRegion based on its x and y offsets
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CMapRegion * CMapWorld::GetMapRegion( SI16 xOffset, SI16 yOffset )
|
|
{
|
|
CMapRegion *mRegion = nullptr;
|
|
const size_t regionIndex = (static_cast<size_t>(xOffset) * static_cast<size_t>(upperArrayY) + static_cast<size_t>(yOffset));
|
|
|
|
if( xOffset >= 0 && xOffset < upperArrayX && yOffset >= 0 && yOffset < upperArrayY )
|
|
{
|
|
if( regionIndex < mapRegions.size() )
|
|
mRegion = &mapRegions[regionIndex];
|
|
}
|
|
|
|
return mRegion;
|
|
}
|
|
|
|
std::vector< CMapRegion > * CMapWorld::GetMapRegions()
|
|
{
|
|
return &mapRegions;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - MapResource_st& GetResource( SI16 x, SI16 y )
|
|
//| Date - 9/17/2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the Resource region x and y is.
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
MapResource_st& CMapWorld::GetResource( SI16 x, SI16 y )
|
|
{
|
|
const UI16 gridX = (x / cwmWorldState->ServerData()->ResourceAreaSize());
|
|
const UI16 gridY = (y / cwmWorldState->ServerData()->ResourceAreaSize());
|
|
|
|
size_t resIndex = ((static_cast<size_t>(gridX) * static_cast<size_t>(resourceY)) + static_cast<size_t>(gridY));
|
|
|
|
if( gridX >= resourceX || gridY >= resourceY || resIndex > mapResources.size() )
|
|
resIndex = 0;
|
|
|
|
return mapResources[resIndex];
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void SaveResources( UI08 worldNum )
|
|
//| Date - 9/17/2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Saves the Resource data to disk
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapWorld::SaveResources( UI08 worldNum )
|
|
{
|
|
char wBuffer[2];
|
|
const std::string resourceFile = cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + "resource[" + std::to_string( worldNum ) + "].bin";
|
|
std::ofstream toWrite( resourceFile.c_str(), std::ios::out | std::ios::trunc | std::ios::binary );
|
|
|
|
if( toWrite )
|
|
{
|
|
for( std::vector< MapResource_st >::const_iterator mIter = mapResources.begin(); mIter != mapResources.end(); ++mIter )
|
|
{
|
|
wBuffer[0] = static_cast<SI08>((*mIter).oreAmt>>8);
|
|
wBuffer[1] = static_cast<SI08>((*mIter).oreAmt%256);
|
|
toWrite.write( (const char *)&wBuffer, 2 );
|
|
|
|
wBuffer[0] = static_cast<SI08>((*mIter).logAmt>>8);
|
|
wBuffer[1] = static_cast<SI08>((*mIter).logAmt%256);
|
|
toWrite.write( (const char *)&wBuffer, 2 );
|
|
|
|
wBuffer[0] = static_cast<SI08>((*mIter).fishAmt>>8);
|
|
wBuffer[1] = static_cast<SI08>((*mIter).fishAmt%256);
|
|
toWrite.write( (const char *)&wBuffer, 2 );
|
|
}
|
|
toWrite.close();
|
|
}
|
|
else // Can't save resources
|
|
Console.error( "Failed to open resource.bin for writing" );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadResources( UI08 worldNum )
|
|
//| Date - 9/17/2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Loads the Resource data from the disk
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapWorld::LoadResources( UI08 worldNum )
|
|
{
|
|
const SI16 resOre = cwmWorldState->ServerData()->ResOre();
|
|
const SI16 resLog = cwmWorldState->ServerData()->ResLogs();
|
|
const SI16 resFish = cwmWorldState->ServerData()->ResFish();
|
|
const UI32 oreTime = BuildTimeValue( static_cast<R32>(cwmWorldState->ServerData()->ResOreTime()) );
|
|
const UI32 logTime = BuildTimeValue( static_cast<R32>(cwmWorldState->ServerData()->ResLogTime()) );
|
|
const UI32 fishTime = BuildTimeValue( static_cast<R32>(cwmWorldState->ServerData()->ResFishTime()) );
|
|
const std::string resourceFile = cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) + std::string("resource[") + oldstrutil::number( worldNum ) + std::string("].bin");
|
|
|
|
char rBuffer[2];
|
|
std::ifstream toRead ( resourceFile.c_str(), std::ios::in | std::ios::binary );
|
|
|
|
bool fileExists = ( toRead.is_open() );
|
|
|
|
if( fileExists )
|
|
toRead.seekg( 0, std::ios::beg );
|
|
|
|
for( std::vector< MapResource_st >::iterator mIter = mapResources.begin(); mIter != mapResources.end(); ++mIter )
|
|
{
|
|
if( fileExists )
|
|
{
|
|
toRead.read( rBuffer, 2 );
|
|
(*mIter).oreAmt = ( (rBuffer[0]<<8) + rBuffer[1] );
|
|
|
|
toRead.read( rBuffer, 2 );
|
|
(*mIter).logAmt = ( (rBuffer[0]<<8) + rBuffer[1] );
|
|
|
|
toRead.read( rBuffer, 2 );
|
|
(*mIter).fishAmt = ( (rBuffer[0]<<8) + rBuffer[1] );
|
|
|
|
fileExists = toRead.eof();
|
|
}
|
|
else
|
|
{
|
|
(*mIter).oreAmt = resOre;
|
|
(*mIter).logAmt = resLog;
|
|
(*mIter).fishAmt = resFish;
|
|
}
|
|
// No need to preserve time. Do a refresh automatically
|
|
(*mIter).oreTime = oreTime;
|
|
(*mIter).logTime = logTime;
|
|
(*mIter).fishTime = fishTime;
|
|
}
|
|
if( fileExists )
|
|
toRead.close();
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapHandler Constructor/Destructor
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Fills and clears the mapWorlds vector.
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
|
|
auto CMapHandler::startup() ->void {
|
|
UI08 numWorlds = Map->MapCount();
|
|
|
|
mapWorlds.reserve( numWorlds );
|
|
for( UI08 i = 0; i < numWorlds; ++i )
|
|
{
|
|
mapWorlds.push_back( new CMapWorld( i ) );
|
|
}
|
|
|
|
}
|
|
CMapHandler::~CMapHandler()
|
|
{
|
|
for( WORLDLIST_ITERATOR mIter = mapWorlds.begin(); mIter != mapWorlds.end(); ++mIter )
|
|
{
|
|
if( (*mIter) != nullptr )
|
|
{
|
|
delete (*mIter);
|
|
(*mIter) = nullptr;
|
|
}
|
|
}
|
|
mapWorlds.resize( 0 );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool ChangeRegion( CItem *nItem, SI16 x, SI16 y, UI08 worldNum )
|
|
//| Date - February 1, 2006
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Changes an items region ONLY if he has changed regions.
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapHandler::ChangeRegion( CItem *nItem, SI16 x, SI16 y, UI08 worldNum )
|
|
{
|
|
if( !ValidateObject( nItem ) )
|
|
return false;
|
|
|
|
CMapRegion *curCell = GetMapRegion( nItem );
|
|
CMapRegion *newCell = GetMapRegion( GetGridX( x ), GetGridY( y ), worldNum );
|
|
|
|
if( curCell != newCell )
|
|
{
|
|
if( !curCell->GetRegionSerialList()->Remove( nItem->GetSerial() ) || !curCell->GetItemList()->Remove( nItem ) )
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Item 0x%X does not exist in MapRegion, remove failed", nItem->GetSerial() ));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if( nItem->ShouldSave() )
|
|
curCell->HasRegionChanged( true );
|
|
}
|
|
|
|
if( newCell->GetRegionSerialList()->Add( nItem->GetSerial() ))
|
|
{
|
|
newCell->GetItemList()->Add( nItem, false );
|
|
if( nItem->ShouldSave() )
|
|
newCell->HasRegionChanged( true );
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Item 0x%X already exists in MapRegion, add failed", nItem->GetSerial() ));
|
|
#endif
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool ChangeRegion( CChar *nChar, SI16 x, SI16 y, UI08 worldNum )
|
|
//| Date - February 1, 2006
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Changes a characters region ONLY if he has changed regions.
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapHandler::ChangeRegion( CChar *nChar, SI16 x, SI16 y, UI08 worldNum )
|
|
{
|
|
if( !ValidateObject( nChar ) )
|
|
return false;
|
|
|
|
CMapRegion *curCell = GetMapRegion( nChar );
|
|
CMapRegion *newCell = GetMapRegion( GetGridX( x ), GetGridY( y ), worldNum );
|
|
|
|
if( curCell != newCell )
|
|
{
|
|
if( !curCell->GetRegionSerialList()->Remove( nChar->GetSerial() ) || !curCell->GetCharList()->Remove( nChar ) )
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Character 0x%X does not exist in MapRegion, remove failed", nChar->GetSerial() ));
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
if( nChar->ShouldSave() )
|
|
curCell->HasRegionChanged( true );
|
|
}
|
|
|
|
if( newCell->GetRegionSerialList()->Add( nChar->GetSerial() ))
|
|
{
|
|
newCell->GetCharList()->Add( nChar, false );
|
|
if( nChar->ShouldSave() )
|
|
newCell->HasRegionChanged( true );
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Character 0x%X already exists in MapRegion, add failed", nChar->GetSerial() ));
|
|
#endif
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool AddItem( CItem *nItem )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Adds nItem to the proper SubRegion
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapHandler::AddItem( CItem *nItem )
|
|
{
|
|
if( !ValidateObject( nItem ) )
|
|
return false;
|
|
|
|
CMapRegion *cell = GetMapRegion( nItem );
|
|
if( cell->GetRegionSerialList()->Add( nItem->GetSerial() ))
|
|
{
|
|
cell->GetItemList()->Add( nItem, false );
|
|
if( nItem->ShouldSave() )
|
|
cell->HasRegionChanged( true );
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Item 0x%X already exists in MapRegion, add failed", nItem->GetSerial() ));
|
|
#endif
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool RemoveItem( CItem *nItem )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Removes nItem from it's CURRENT SubRegion. Do this before adjusting the location
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapHandler::RemoveItem( CItem *nItem )
|
|
{
|
|
if( !ValidateObject( nItem ) )
|
|
return false;
|
|
CMapRegion *cell = GetMapRegion( nItem );
|
|
if( cell->GetRegionSerialList()->Remove( nItem->GetSerial() ) )
|
|
{
|
|
cell->GetItemList()->Remove( nItem );
|
|
if( nItem->ShouldSave() )
|
|
cell->HasRegionChanged( true );
|
|
}
|
|
else
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Item 0x%X does not exist in MapRegion, remove failed", nItem->GetSerial() ));
|
|
#endif
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool AddChar( CChar *toAdd )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Adds toAdd to the proper SubRegion
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapHandler::AddChar( CChar *toAdd )
|
|
{
|
|
if( !ValidateObject( toAdd ) )
|
|
return false;
|
|
|
|
CMapRegion *cell = GetMapRegion( toAdd );
|
|
if( cell->GetRegionSerialList()->Add( toAdd->GetSerial() ))
|
|
{
|
|
cell->GetCharList()->Add( toAdd, false );
|
|
if( toAdd->ShouldSave() )
|
|
cell->HasRegionChanged( true );
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Character 0x%X already exists in MapRegion, add failed", toAdd->GetSerial() ));
|
|
#endif
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - bool RemoveChar( CChar *toRemove )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Removes toRemove from it's CURRENT SubRegion. Do this before adjusting the location
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
bool CMapHandler::RemoveChar( CChar *toRemove )
|
|
{
|
|
if( !ValidateObject( toRemove ) )
|
|
return false;
|
|
CMapRegion *cell = GetMapRegion( toRemove );
|
|
if( cell->GetRegionSerialList()->Remove( toRemove->GetSerial() ) )
|
|
{
|
|
cell->GetCharList()->Remove( toRemove );
|
|
if( toRemove->ShouldSave() )
|
|
cell->HasRegionChanged( true );
|
|
}
|
|
else
|
|
{
|
|
#if DEBUG_REGIONS
|
|
Console.warning( oldstrutil::format( "Character 0x%X does not exist in MapRegion, remove failed", toRemove->GetSerial() ));
|
|
#endif
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI16 GetGridX( SI16 x )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Find the Column of SubRegion we want based on location
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI16 CMapHandler::GetGridX( SI16 x )
|
|
{
|
|
return static_cast<SI16>(x / MapColSize);
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - SI16 GetGridY( SI16 y )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Finds the Row of SubRegion we want based on location
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
SI16 CMapHandler::GetGridY( SI16 y )
|
|
{
|
|
return static_cast<SI16>(y / MapRowSize);
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapRegion *GetMapRegion( SI16 xOffset, SI16 yOffset, UI08 worldNumber )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the MapRegion based on the offsets
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CMapRegion *CMapHandler::GetMapRegion( SI16 xOffset, SI16 yOffset, UI08 worldNumber )
|
|
{
|
|
CMapRegion * mRegion = mapWorlds[worldNumber]->GetMapRegion( xOffset, yOffset );
|
|
if( mRegion == nullptr )
|
|
mRegion = &overFlow;
|
|
|
|
return mRegion;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapRegion *GetMapRegion( SI16 x, SI16 y )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the subregion that x,y is in
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CMapRegion *CMapHandler::GetMapRegion( CBaseObject *mObj )
|
|
{
|
|
return GetMapRegion( GetGridX( mObj->GetX() ), GetGridY( mObj->GetY() ), mObj->WorldNumber() );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapWorld * GetMapWorld( UI08 worldNum )
|
|
//| Date - 9/13/2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the MapWorld object associated with the worldNumber
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
CMapWorld * CMapHandler::GetMapWorld( UI08 worldNum )
|
|
{
|
|
CMapWorld *mWorld = nullptr;
|
|
if( worldNum > mapWorlds.size() )
|
|
mWorld = mapWorlds[worldNum];
|
|
return mWorld;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - CMapWorld * GetMapWorld( UI08 worldNum )
|
|
//| Date - 9/13/2005
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns the MapWorld object associated with the worldNumber
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
MapResource_st * CMapHandler::GetResource( SI16 x, SI16 y, UI08 worldNum )
|
|
{
|
|
MapResource_st *resData = nullptr;
|
|
if( worldNum < mapWorlds.size() )
|
|
resData = &mapWorlds[worldNum]->GetResource( x, y );
|
|
return resData;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - auto PopulateList( CBaseObject *mObj ) -> std::vector< CMapRegion * >
|
|
//| Date - Unknown
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a list of nearby MapRegions based on the object provided
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
auto CMapHandler::PopulateList( CBaseObject *mObj ) -> std::vector< CMapRegion * > {
|
|
return PopulateList( mObj->GetX(), mObj->GetY(), mObj->WorldNumber() );
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - auto PopulateList( SI16 x, SI16 y, UI08 worldNumber ) -> std::vector< CMapRegion * >
|
|
//| Date - Unknown
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Creates a list of nearby MapRegions based on the coordinates provided
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
auto CMapHandler::PopulateList( SI16 x, SI16 y, UI08 worldNumber ) -> std::vector< CMapRegion * >
|
|
{
|
|
std::vector< CMapRegion * > nearbyRegions;
|
|
const SI16 xOffset = MapRegion->GetGridX( x );
|
|
const SI16 yOffset = MapRegion->GetGridY( y );
|
|
for( SI08 counter1 = -1; counter1 <= 1; ++counter1 )
|
|
{
|
|
for( SI08 counter2 = -1; counter2 <= 1; ++counter2 )
|
|
{
|
|
CMapRegion *MapArea = GetMapRegion( xOffset + counter1, yOffset + counter2, worldNumber );
|
|
if( MapArea == nullptr )
|
|
continue;
|
|
nearbyRegions.push_back( MapArea );
|
|
}
|
|
}
|
|
return nearbyRegions;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void Save( void )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Saves out the MapRegions
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapHandler::Save( void )
|
|
{
|
|
const SI16 AreaX = UpperX / 8; // we're storing 8x8 grid arrays together
|
|
const SI16 AreaY = UpperY / 8;
|
|
std::ofstream writeDestination, houseDestination;
|
|
SI32 onePercent = 0;
|
|
//const SI32 onePercent = (SI32)((R32)(UpperX*UpperY*Map->MapCount())/100.0f);
|
|
UI08 i = 0;
|
|
for( i = 0; i < Map->MapCount(); ++i )
|
|
{
|
|
auto [width,height] = Map->sizeOfMap(i);
|
|
onePercent += static_cast<std::int32_t>((width/MapColSize) * (height/MapRowSize));
|
|
}
|
|
onePercent /= 100.0f;
|
|
const size_t bufferSize = 1024 * 1024;
|
|
char* buffer = (char*)malloc(bufferSize);
|
|
|
|
const char blockDiscriminator[] = "\n\n---REGION---\n\n";
|
|
UI32 count = 0;
|
|
const UI32 s_t = getclock();
|
|
|
|
Console << "Saving Character and Item Map Region data... ";
|
|
Console.TurnYellow();
|
|
Console << "0%";
|
|
|
|
std::string basePath = cwmWorldState->ServerData()->Directory( CSDDP_SHARED );
|
|
|
|
// Legacy - deletes house.wsc on next world save, since house data is now saved in the regional
|
|
// wsc files along with other objects, so we don't want this file loaded again on next startup
|
|
std::filesystem::path houseFilePath = basePath + "house.wsc";
|
|
std::filesystem::remove( houseFilePath );
|
|
|
|
std::string filename = "";
|
|
for( SI16 counter1 = 0; counter1 < AreaX; ++counter1 ) // move left->right
|
|
{
|
|
const SI32 baseX = counter1 * 8;
|
|
for( SI16 counter2 = 0; counter2 < AreaY; ++counter2 ) // move up->down
|
|
{
|
|
const SI32 baseY = counter2 * 8; // calculate x grid offset
|
|
filename = basePath + oldstrutil::number( counter1 ) + std::string(".") + oldstrutil::number( counter2 ) + std::string(".wsc"); // let's name our file
|
|
|
|
bool changesDetected = false;
|
|
for( UI08 xCnt = 0; !changesDetected && xCnt < 8; ++xCnt ) // walk through each part of the 8x8 grid, left->right
|
|
{
|
|
for( UI08 yCnt = 0; !changesDetected && yCnt < 8; ++yCnt ) // walk the row
|
|
{
|
|
for( WORLDLIST_ITERATOR mIter = mapWorlds.begin(); mIter != mapWorlds.end(); ++mIter )
|
|
{
|
|
CMapRegion * mRegion = (*mIter)->GetMapRegion( (baseX+xCnt), (baseY+yCnt) );
|
|
if( mRegion != nullptr )
|
|
{
|
|
// Only save objects mapRegions marked as "changed" by objects updated in said regions
|
|
if( mRegion->HasRegionChanged() )
|
|
{
|
|
changesDetected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !changesDetected )
|
|
continue;
|
|
|
|
writeDestination.open( filename.c_str(), std::ios::binary );
|
|
|
|
if( !writeDestination )
|
|
{
|
|
Console.error( oldstrutil::format("Failed to open %s for writing", filename.c_str()) );
|
|
continue;
|
|
}
|
|
|
|
writeDestination.rdbuf()->pubsetbuf(buffer, bufferSize);
|
|
|
|
for( UI08 xCnt = 0; xCnt < 8; ++xCnt ) // walk through each part of the 8x8 grid, left->right
|
|
{
|
|
for( UI08 yCnt = 0; yCnt < 8; ++yCnt ) // walk the row
|
|
{
|
|
for( WORLDLIST_ITERATOR mIter = mapWorlds.begin(); mIter != mapWorlds.end(); ++mIter )
|
|
{
|
|
++count;
|
|
if( count%onePercent == 0 )
|
|
{
|
|
if( count/onePercent <= 10 )
|
|
Console << "\b\b" << std::to_string(count/onePercent) << "%";
|
|
else if( count/onePercent <= 100 )
|
|
Console << "\b\b\b" << std::to_string(count/onePercent) << "%";
|
|
}
|
|
|
|
CMapRegion * mRegion = (*mIter)->GetMapRegion( (baseX+xCnt), (baseY+yCnt) );
|
|
if( mRegion != nullptr )
|
|
{
|
|
mRegion->SaveToDisk( writeDestination );
|
|
|
|
// Remove "changed" flag from region, to avoid it saving again needlessly on next save
|
|
mRegion->HasRegionChanged( false );
|
|
}
|
|
writeDestination << blockDiscriminator;
|
|
}
|
|
}
|
|
}
|
|
writeDestination.close();
|
|
}
|
|
}
|
|
Console << "\b\b\b\b" << (UI32)(100) << "%";
|
|
|
|
filename = basePath + "overflow.wsc";
|
|
writeDestination.open( filename.c_str() );
|
|
|
|
if( writeDestination.is_open() )
|
|
{
|
|
overFlow.SaveToDisk( writeDestination );
|
|
writeDestination.close();
|
|
}
|
|
else
|
|
{
|
|
Console.error( oldstrutil::format("Failed to open %s for writing", filename.c_str()) );
|
|
return;
|
|
}
|
|
|
|
Console << "\b\b\b\b";
|
|
Console.PrintDone();
|
|
|
|
const UI32 e_t = getclock();
|
|
Console.print( oldstrutil::format("World saved in %.02fsec\n", ((R32)(e_t-s_t))/1000.0f ));
|
|
|
|
i = 0;
|
|
for( WORLDLIST_ITERATOR wIter = mapWorlds.begin(); wIter != mapWorlds.end(); ++wIter )
|
|
{
|
|
(*wIter)->SaveResources( i );
|
|
++i;
|
|
}
|
|
}
|
|
|
|
bool PostLoadFunctor( CBaseObject *a, UI32 &b, void *extraData )
|
|
{
|
|
if( ValidateObject( a ) )
|
|
{
|
|
if( !a->isFree() )
|
|
a->PostLoadProcessing();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void Load( void )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Loads in the MapRegions
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapHandler::Load( void )
|
|
{
|
|
const SI16 AreaX = UpperX / 8; // we're storing 8x8 grid arrays together
|
|
const SI16 AreaY = UpperY / 8;
|
|
// const SI32 onePercent = (SI32)((R32)(AreaX*AreaY)/100.0f);
|
|
UI32 count = 0;
|
|
std::ifstream readDestination;
|
|
Console.TurnYellow();
|
|
Console << "0%";
|
|
UI32 s_t = getclock();
|
|
std::string basePath = cwmWorldState->ServerData()->Directory( CSDDP_SHARED );
|
|
std::string filename;
|
|
|
|
UI32 runningCount = 0;
|
|
SI32 fileSizes[AreaX][AreaY];
|
|
for( SI16 cx = 0; cx < AreaX; ++cx )
|
|
{
|
|
for( SI16 cy = 0; cy < AreaY; ++cy )
|
|
{
|
|
filename = basePath + oldstrutil::number( cx ) + std::string(".") + oldstrutil::number( cy ) + std::string(".wsc"); // let's name our file
|
|
fileSizes[cx][cy] = FileSize( filename );
|
|
runningCount += fileSizes[cx][cy];
|
|
}
|
|
}
|
|
|
|
if( runningCount == 0 )
|
|
runningCount = 1;
|
|
|
|
SI32 runningDone = 0;
|
|
for( SI16 counter1 = 0; counter1 < AreaX; ++counter1 ) // move left->right
|
|
{
|
|
for( SI16 counter2 = 0; counter2 < AreaY; ++counter2 ) // move up->down
|
|
{
|
|
filename = basePath + oldstrutil::number( counter1 ) + std::string(".") + oldstrutil::number( counter2 ) + std::string(".wsc"); // let's name our file
|
|
readDestination.open( filename.c_str()); // let's open it
|
|
readDestination.seekg( 0, std::ios::beg );
|
|
|
|
if( readDestination.eof() || readDestination.fail() )
|
|
{
|
|
readDestination.close();
|
|
readDestination.clear();
|
|
continue;
|
|
}
|
|
|
|
++count;
|
|
LoadFromDisk( readDestination, runningDone, fileSizes[counter1][counter2], runningCount );
|
|
|
|
runningDone += fileSizes[counter1][counter2];
|
|
float tempVal = (R32)runningDone / (R32)runningCount * 100.0f;
|
|
if( tempVal <= 10 )
|
|
Console << "\b\b" << (UI32)(tempVal) << "%";
|
|
else if( tempVal <= 100 )
|
|
Console << "\b\b\b" << (UI32)(tempVal) << "%";
|
|
|
|
readDestination.close();
|
|
readDestination.clear();
|
|
}
|
|
}
|
|
|
|
// If runningDone is still 0, there was nothing to load! 100% it
|
|
if( runningDone == 0 )
|
|
Console << "\b\b" << (UI32)(100) << "%";
|
|
|
|
Console.TurnNormal();
|
|
Console << "\b\b\b";
|
|
Console.PrintDone();
|
|
|
|
filename = basePath + "overflow.wsc";
|
|
std::ifstream flowDestination( filename.c_str() );
|
|
LoadFromDisk( flowDestination, -1, -1, -1 );
|
|
flowDestination.close();
|
|
|
|
filename = basePath + "house.wsc";
|
|
std::ifstream houseDestination( filename.c_str() );
|
|
LoadFromDisk( houseDestination, -1, -1, -1 );
|
|
|
|
UI32 b = 0;
|
|
ObjectFactory::getSingleton().IterateOver( OT_MULTI, b, nullptr, &PostLoadFunctor );
|
|
ObjectFactory::getSingleton().IterateOver( OT_ITEM, b, nullptr, &PostLoadFunctor );
|
|
ObjectFactory::getSingleton().IterateOver( OT_CHAR, b, nullptr, &PostLoadFunctor );
|
|
houseDestination.close();
|
|
|
|
UI32 e_t = getclock();
|
|
Console.print( oldstrutil::format("ASCII world loaded in %.02fsec\n", ((R32)(e_t-s_t))/1000.0f ));
|
|
|
|
UI08 i = 0;
|
|
for( WORLDLIST_ITERATOR wIter = mapWorlds.begin(); wIter != mapWorlds.end(); ++wIter )
|
|
{
|
|
(*wIter)->LoadResources( i );
|
|
++i;
|
|
}
|
|
}
|
|
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Function - void LoadFromDisk( std::ifstream& readDestination, SI32 baseValue, SI32 fileSize, UI32 maxSize )
|
|
//| Date - 23 July, 2000
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
//| Purpose - Loads in objects from specified file
|
|
//o-----------------------------------------------------------------------------------------------o
|
|
void CMapHandler::LoadFromDisk( std::ifstream& readDestination, SI32 baseValue, SI32 fileSize, UI32 maxSize )
|
|
{
|
|
char line[1024];
|
|
R32 basePercent = (R32)baseValue / (R32)maxSize * 100.0f;
|
|
R32 targPercent = (R32)(baseValue + fileSize) / (R32)maxSize * 100.0f;
|
|
R32 diffValue = targPercent - basePercent;
|
|
|
|
SI32 updateCount = 0;
|
|
while( !readDestination.eof() && !readDestination.fail() )
|
|
{
|
|
readDestination.getline(line, 1023);
|
|
line[readDestination.gcount()] = 0;
|
|
std::string sLine(line);
|
|
sLine = oldstrutil::trim( sLine );
|
|
|
|
if( sLine.substr( 0, 1 ) == "[" ) // in a section
|
|
{
|
|
sLine = sLine.substr( 1, sLine.size() - 2 );
|
|
sLine = oldstrutil::upper( oldstrutil::trim( sLine ));
|
|
if( sLine == "CHARACTER" )
|
|
LoadChar( readDestination );
|
|
else if( sLine == "ITEM" )
|
|
LoadItem( readDestination );
|
|
else if( sLine == "HOUSE" )
|
|
LoadMulti( readDestination );
|
|
else if( sLine == "BOAT" )
|
|
LoadBoat( readDestination );
|
|
else if( sLine == "SPAWNITEM" )
|
|
LoadSpawnItem( readDestination );
|
|
|
|
if( fileSize != -1 && (++updateCount)%200 == 0 )
|
|
{
|
|
R32 curPos = readDestination.tellg();
|
|
R32 tempVal = basePercent + ( curPos / fileSize * diffValue );
|
|
if( tempVal <= 10 )
|
|
Console << "\b\b" << (UI32)(tempVal) << "%";
|
|
else
|
|
Console << "\b\b\b" << (UI32)(tempVal) << "%";
|
|
}
|
|
}
|
|
else if( sLine == "---REGION---" ) // end of region
|
|
continue;
|
|
}
|
|
}
|