2021-05-30 03:21:05 +08:00
|
|
|
//
|
|
|
|
|
// Created on: 4/30/21
|
|
|
|
|
|
|
|
|
|
#include "MultiMul.hpp"
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <filesystem>
|
|
|
|
|
#include <algorithm>
|
2022-06-12 16:54:32 -04:00
|
|
|
#include <unordered_map>
|
2022-06-15 11:24:57 -04:00
|
|
|
#include "mapstuff.h"
|
2021-06-04 02:47:37 +08:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
using namespace std::string_literals;
|
2021-06-04 02:47:37 +08:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
// MultiItem_st
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
MultiItem_st::MultiItem_st() : tileId( 0xFFFF ), altitude( 0 ), offsetX( 0 ), offsetY( 0 ), flag( 0 )
|
|
|
|
|
{
|
|
|
|
|
info = nullptr;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
// CollectionItem_st
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - CollectionItem_st::ItemsAt()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - Returns collection of items at given coordinates
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
auto CollectionItem_st::ItemsAt( int offsetX, int offsetY ) -> std::vector<MultiItem_st>
|
|
|
|
|
{
|
|
|
|
|
std::vector<MultiItem_st> rValue;
|
|
|
|
|
for( auto &item : items )
|
|
|
|
|
{
|
|
|
|
|
if(( item.offsetX == static_cast<std::int16_t>( offsetX )) && ( item.offsetY == static_cast<std::int16_t>( offsetY )))
|
|
|
|
|
{
|
|
|
|
|
rValue.push_back( item );
|
2022-06-12 19:54:28 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
return rValue;
|
2022-06-12 19:54:28 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
2022-11-04 17:12:13 -04:00
|
|
|
CollectionItem_st::CollectionItem_st() :minX( 0 ), minY( 0 ), maxX( 0 ), maxY( 0 ), minAlt( 0 ), maxAlt( 0 )
|
2022-10-24 18:39:33 +08:00
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - CollectionItem_st::Name()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - Return name of item in collection
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
auto CollectionItem_st::Name( int multi_id ) -> std::string
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
auto name = collectionNames.at( multi_id );
|
|
|
|
|
return name;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
catch(...)
|
|
|
|
|
{
|
|
|
|
|
return "unknown - "s + std::to_string( multi_id );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//=========================================================
|
2022-10-24 18:39:33 +08:00
|
|
|
const std::unordered_map<int, std::string> CollectionItem_st::collectionNames = {
|
|
|
|
|
{ 0, "Small Boat [north]"s }, { 1, "Small Boat [east]"s },
|
|
|
|
|
{ 2, "Small Boat [south]"s }, { 3, "Small Boat [west]"s },
|
|
|
|
|
{ 4, "Small Dragon Boat [north]"s }, { 5, "Small Dragon Boat [east]"s },
|
|
|
|
|
{ 6, "Small Dragon Boat [south]"s }, { 7, "Small Dragon Boat [west]"s },
|
|
|
|
|
{ 8, "Medium Boat [north]"s }, { 9, "Medium Boat [east]"s },
|
|
|
|
|
{ 10, "Medium Boat [south]"s }, { 11, "Medium Boat [west]"s },
|
|
|
|
|
{ 12, "Medium Dragon Boat [north]"s }, { 13, "Medium Dragon Boat [east]"s },
|
|
|
|
|
{ 14, "Medium Dragon Boat [south]"s }, { 15, "Medium Dragon Boat [west]"s },
|
|
|
|
|
{ 16, "Large Boat [north]"s }, { 17, "Large Boat [east]"s },
|
|
|
|
|
{ 18, "Large Boat [soutch]"s }, { 19, "Large Boat [west]"s },
|
|
|
|
|
{ 20, "Large Dragon Boat [north]"s }, { 21, "Large Dragon Boat [east]"s },
|
|
|
|
|
{ 22, "Large Dragon Boat [south]"s }, { 23, "Large Dragon Boat [west]"s },
|
|
|
|
|
{ 24, "Orcish Galleon [north]"s }, { 25, "Orcish Galleon [east]"s },
|
|
|
|
|
{ 26, "Orcish Galleon [south]"s }, { 27, "Orcish Galleon [west]"s },
|
|
|
|
|
{ 28, "Orcish Galleon [damaged][north]"s }, { 29, "Orcish Galleon [damaged][east]"s },
|
|
|
|
|
{ 30, "Orcish Galleon [damaged][south]"s }, { 31, "Orcish Galleon [damaged][west]"s },
|
|
|
|
|
{ 32, "Orcish Galleon [destroyed][north]"s }, { 33, "Orcish Galleon [destroyed][east]"s },
|
|
|
|
|
{ 34, "Orcish Galleon [destroyed][south]"s }, { 35, "Orcish Galleon [destroyed][west]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 36, "Gargish Galleon [north]"s }, { 37, "Gargish Galleon [east]"s },
|
|
|
|
|
{ 38, "Gargish Galleon [south]"s }, { 39, "Gargish Galleon [west]"s },
|
|
|
|
|
{ 40, "Gargish Galleon [damaged][north]"s }, { 41, "Gargish Galleon [damaged][east]"s },
|
|
|
|
|
{ 42, "Gargish Galleon [damaged][south]"s }, { 43, "Gargish Galleon [damaged][west]"s },
|
|
|
|
|
{ 44, "Gargish Galleon [destroyed][north]"s }, { 45, "Gargish Galleon [destroyed][east]"s },
|
|
|
|
|
{ 46, "Gargish Galleon [destroyed][south]"s }, { 47, "Gargish Galleon [destroyed][west]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 48, "Tokuno Galleon [north]"s }, { 49, "Tokuno Galleon [east]"s },
|
|
|
|
|
{ 50, "Tokuno Galleon [south]"s }, { 51, "Tokuno Galleon [west]"s },
|
|
|
|
|
{ 52, "Tokuno Galleon [damaged][north]"s }, { 53, "Tokuno Galleon [damaged][east]"s },
|
|
|
|
|
{ 54, "Tokuno Galleon [damaged][south]"s }, { 55, "Tokuno Galleon [damaged][west]"s },
|
|
|
|
|
{ 56, "Tokuno Galleon [destroyed][north]"s }, { 57, "Tokuno Galleon [destroyed][east]"s },
|
|
|
|
|
{ 58, "Tokuno Galleon [destroyed][south]"s }, { 59, "Tokuno Galleon [destroyed][west]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 60, "Rowboat [north]"s }, { 61, "Rowboat [east]"s },
|
|
|
|
|
{ 62, "Rowboat [south]"s }, { 63, "Rowboat [west]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 64, "British Galleon [north]"s }, { 65, "British Galleon [east]"s },
|
|
|
|
|
{ 66, "British Galleon [south]"s }, { 67, "British Galleon [west]"s },
|
|
|
|
|
{ 68, "British Galleon [damaged][north]"s }, { 69, "British Galleon [damaged][east]"s },
|
|
|
|
|
{ 70, "British Galleon [damaged][south]"s }, { 71, "British Galleon [damaged][west]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 100, "Small Stone and Plaster House"s }, { 101, "Small Stone and Plaster House"s },
|
|
|
|
|
{ 102, "Small Fieldstone House"s }, { 103, "Small Fieldstone House"s },
|
|
|
|
|
{ 104, "Small Brick House"s }, { 105, "Small Brick House"s },
|
|
|
|
|
{ 106, "Small Wood House"s }, { 107, "Small Wood House"s },
|
|
|
|
|
{ 108, "Small Wood and Plaster House"s }, { 109, "Small Wood and Plaster House"s },
|
|
|
|
|
{ 110, "Small Thatched Roof Cottage"s }, { 111, "Small Thatched Roof Cottage"s },
|
|
|
|
|
{ 112, "Tent [blue]"s }, { 113, "Tent [blue]"s },
|
|
|
|
|
{ 114, "Tent [green]"s }, { 115, "Tent [green]"s },
|
|
|
|
|
{ 116, "Large Brick House"s }, { 117, "Large Brick House"s },
|
|
|
|
|
{ 118, "Two Story Wood and Plaster House"s }, { 119, "Two Story Wood and Plaster House"s },
|
|
|
|
|
{ 120, "Two Story Stone and Plaster House"s }, { 121, "Two Story Stone and Plaster House"s },
|
|
|
|
|
{ 122, "Large Tower"s }, { 123, "Large Tower"s },
|
|
|
|
|
{ 124, "Stone Keep"s }, { 125, "Stone Keep"s },
|
|
|
|
|
{ 126, "Castle"s }, { 127, "Castle"s },
|
|
|
|
|
{ 128, "Large Patio House"s }, { 129, "Large Patio House"s },
|
|
|
|
|
{ 141, "Large Patio House"s }, { 150, "Large Marble Patio House"s },
|
|
|
|
|
{ 152, "Small Tower"s }, { 154, "Log Cabin"s },
|
|
|
|
|
{ 156, "Sandstone Patio House"s }, { 158, "Two-Story Villa"s },
|
|
|
|
|
{ 160, "Small Stone Workshop"s }, { 162, "Small Marble Workshop"s },
|
|
|
|
|
{ 201, "Mine's Elevator"s }, { 202, "Lifting Bridge"s },
|
|
|
|
|
{ 500, "Wandering Healer Camp"s }, { 501, "Wandering Mage Camp"s },
|
|
|
|
|
{ 502, "Wandering Bank Camp"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 1000, "Treasure Pile"s }, { 1001, "Treasure Pile"s },
|
|
|
|
|
{ 1002, "Treasure Pile"s }, { 1003, "Treasure Pile"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 2000, "Wooden Supports"s }, { 2001, "Wooden Supports"s },
|
|
|
|
|
{ 2002, "Wooden Supports"s }, { 2003, "Wooden Supports"s },
|
|
|
|
|
{ 2004, "Wooden Supports"s }, { 2005, "Wooden Supports"s },
|
|
|
|
|
{ 2006, "Wooden Supports"s }, { 2007, "Wooden Supports"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 3000, "Farmer's Cabin"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 4000, "Exodus Generator"s }, { 4001, "Exodus Generator"s },
|
|
|
|
|
{ 4002, "Exodus Control Pylon"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 4003, "Nystul's Tower (stage 1)"s }, { 4004, "Nystul's Tower (stage 2)"s },
|
|
|
|
|
{ 4005, "Nystul's Tower (stage 3)"s }, { 4006, "Nystul's Tower (stage 4)"s },
|
|
|
|
|
{ 4007, "Nystul's Tower (stage 5)"s }, { 4008, "Nystul's Tower (stage 6)"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 4009, "Scaffold and Trailer"s }, { 4010, "Exodus Energy Tower"s },
|
|
|
|
|
{ 4011, "Exodus Barrier"s }, { 4012, "Exodus Control Device"s },
|
|
|
|
|
{ 5000, "Minax Stronghold"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5100, "Foundation [7x7]"s }, { 5101, "Foundation [7x8]"s },
|
|
|
|
|
{ 5102, "Foundation [7x9]"s }, { 5103, "Foundation [7x10]"s },
|
|
|
|
|
{ 5104, "Foundation [7x11]"s }, { 5105, "Foundation [7x12]"s },
|
|
|
|
|
|
|
|
|
|
{ 5112, "Foundation [8x7]"s }, { 5113, "Foundation [8x8]"s },
|
|
|
|
|
{ 5114, "Foundation [8x9]"s }, { 5115, "Foundation [8x10]"s },
|
|
|
|
|
{ 5116, "Foundation [8x11]"s }, { 5117, "Foundation [8x12]"s },
|
|
|
|
|
{ 5118, "Foundation [8x13]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5124, "Foundation [9x7]"s }, { 5125, "Foundation [9x8]"s },
|
|
|
|
|
{ 5126, "Foundation [9x9]"s }, { 5127, "Foundation [9x10]"s },
|
|
|
|
|
{ 5128, "Foundation [9x11]"s }, { 5129, "Foundation [9x12]"s },
|
|
|
|
|
{ 5130, "Foundation [9x13]"s }, { 5131, "Foundation [9x14]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5136, "Foundation [10x7]"s }, { 5137, "Foundation [10x8]"s },
|
|
|
|
|
{ 5138, "Foundation [10x9]"s }, { 5139, "Foundation [10x10]"s },
|
|
|
|
|
{ 5140, "Foundation [10x11]"s }, { 5141, "Foundation [10x12]"s },
|
|
|
|
|
{ 5142, "Foundation [10x13]"s }, { 5143, "Foundation [10x14]"s },
|
|
|
|
|
{ 5144, "Foundation [10x15]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5148, "Foundation [11x7]"s }, { 5149, "Foundation [11x8]"s },
|
|
|
|
|
{ 5150, "Foundation [11x9]"s }, { 5151, "Foundation [11x10]"s },
|
|
|
|
|
{ 5152, "Foundation [11x11]"s }, { 5153, "Foundation [11x12]"s },
|
|
|
|
|
{ 5154, "Foundation [11x13]"s }, { 5155, "Foundation [11x14]"s },
|
|
|
|
|
{ 5156, "Foundation [11x15]"s }, { 5157, "Foundation [11x16]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
|
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5160, "Foundation [12x7]"s }, { 5161, "Foundation [12x8]"s },
|
|
|
|
|
{ 5162, "Foundation [12x9]"s }, { 5163, "Foundation [12x10]"s },
|
|
|
|
|
{ 5164, "Foundation [12x11]"s }, { 5165, "Foundation [12x12]"s },
|
|
|
|
|
{ 5166, "Foundation [12x13]"s }, { 5167, "Foundation [12x14]"s },
|
|
|
|
|
{ 5168, "Foundation [12x15]"s }, { 5169, "Foundation [12x16]"s },
|
|
|
|
|
{ 5170, "Foundation [12x17]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
|
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5173, "Foundation [13x8]"s }, { 5174, "Foundation [13x9]"s },
|
|
|
|
|
{ 5175, "Foundation [13x10]"s }, { 5176, "Foundation [13x11]"s },
|
|
|
|
|
{ 5177, "Foundation [13x12]"s }, { 5178, "Foundation [13x13]"s },
|
|
|
|
|
{ 5179, "Foundation [13x14]"s }, { 5180, "Foundation [13x15]"s },
|
|
|
|
|
{ 5181, "Foundation [13x16]"s }, { 5182, "Foundation [13x17]"s },
|
|
|
|
|
{ 5183, "Foundation [13x18]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5186, "Foundation [14x9]"s }, { 5187, "Foundation [14x10]"s },
|
|
|
|
|
{ 5188, "Foundation [14x11]"s }, { 5189, "Foundation [14x12]"s },
|
|
|
|
|
{ 5190, "Foundation [14x13]"s }, { 5191, "Foundation [14x14]"s },
|
|
|
|
|
{ 5192, "Foundation [14x15]"s }, { 5193, "Foundation [14x16]"s },
|
|
|
|
|
{ 5194, "Foundation [14x17]"s }, { 5195, "Foundation [14x18]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5199, "Foundation [15x10]"s }, { 5200, "Foundation [15x11]"s },
|
|
|
|
|
{ 5201, "Foundation [15x12]"s }, { 5202, "Foundation [15x13]"s },
|
|
|
|
|
{ 5203, "Foundation [15x14]"s }, { 5204, "Foundation [15x15]"s },
|
|
|
|
|
{ 5205, "Foundation [15x16]"s }, { 5206, "Foundation [15x17]"s },
|
|
|
|
|
{ 5207, "Foundation [15x18]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5212, "Foundation [16x11]"s }, { 5213, "Foundation [16x12]"s },
|
|
|
|
|
{ 5214, "Foundation [16x13]"s }, { 5215, "Foundation [16x14]"s },
|
|
|
|
|
{ 5216, "Foundation [16x15]"s }, { 5217, "Foundation [16x16]"s },
|
|
|
|
|
{ 5218, "Foundation [16x17]"s }, { 5219, "Foundation [16x18]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5225, "Foundation [17x12]"s }, { 5226, "Foundation [17x13]"s },
|
|
|
|
|
{ 5227, "Foundation [17x14]"s }, { 5228, "Foundation [17x15]"s },
|
|
|
|
|
{ 5229, "Foundation [17x16]"s }, { 5230, "Foundation [17x17]"s },
|
|
|
|
|
{ 5231, "Foundation [17x18]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 5238, "Foundation [18x13]"s }, { 5239, "Foundation [18x14]"s },
|
|
|
|
|
{ 5240, "Foundation [18x15]"s }, { 5241, "Foundation [18x16]"s },
|
|
|
|
|
{ 5242, "Foundation [18x17]"s }, { 5243, "Foundation [18x18]"s },
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
{ 7500, "New Player Quest Camp"s }
|
2022-06-12 16:54:32 -04:00
|
|
|
};
|
|
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::MultiCollection()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
MultiCollection::MultiCollection( const std::filesystem::path &uodir, TileInfo *info )
|
|
|
|
|
{
|
|
|
|
|
this->info = info;
|
|
|
|
|
if( !uodir.empty() )
|
|
|
|
|
{
|
|
|
|
|
LoadMultiCollection( uodir, info );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::LoadMultiCollection()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - Load Multi MUL data from disk
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
auto MultiCollection::LoadMultiCollection( const std::filesystem::path &uodir, const std::string &housingbin, TileInfo *info ) -> bool
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
_multis.clear();
|
2022-10-24 18:39:33 +08:00
|
|
|
auto multifile = uodir / std::filesystem::path( "MultiCollection.uop" );
|
2022-06-12 16:54:32 -04:00
|
|
|
auto hash = "build/multicollection/%.6u.bin"s;
|
2022-10-24 18:39:33 +08:00
|
|
|
_housingBin = housingbin;
|
|
|
|
|
this->info = info;
|
|
|
|
|
return LoadUop( multifile.string(), 0x10000, hash );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::LoadMul()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - Load Multi MUL data from disk
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
auto MultiCollection::LoadMul( const std::filesystem::path &uodir, TileInfo *info ) -> bool
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
_multis.clear();
|
2022-10-24 18:39:33 +08:00
|
|
|
this->info = info;
|
|
|
|
|
auto rValue = false;
|
|
|
|
|
auto idxfile = uodir / std::filesystem::path( "multi.idx" );
|
|
|
|
|
auto mulfile = uodir / std::filesystem::path( "multi.mul" );
|
|
|
|
|
auto isHS = true;
|
|
|
|
|
if( std::filesystem::exists( mulfile ))
|
|
|
|
|
{
|
|
|
|
|
isHS = ( std::filesystem::file_size( mulfile) >= hsSize ? true : false );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
auto idx = std::ifstream( idxfile, std::ios::binary );
|
|
|
|
|
auto mul = std::ifstream( mulfile, std::ios::binary );
|
|
|
|
|
if( mul.is_open() && idx.is_open() )
|
|
|
|
|
{
|
|
|
|
|
rValue = true;
|
|
|
|
|
auto offset = std::uint32_t( 0 );
|
|
|
|
|
auto length = std::uint32_t( 0 );
|
2022-06-12 16:54:32 -04:00
|
|
|
auto mulid = 0;
|
2022-10-24 18:39:33 +08:00
|
|
|
while( idx.good() && !idx.eof() )
|
|
|
|
|
{
|
|
|
|
|
idx.read( reinterpret_cast<char*>( &offset ), 4 );
|
|
|
|
|
idx.read( reinterpret_cast<char*>( &length ), 4 );
|
|
|
|
|
if( idx.gcount() == 4 )
|
|
|
|
|
{
|
|
|
|
|
idx.seekg( 4, std::ios::cur );
|
|
|
|
|
if(( offset <= 0xFFFFFFFE ) && ( length > 0 ) && ( length < 0xFFFFFFFF ))
|
|
|
|
|
{
|
|
|
|
|
// This is a valid entry;
|
|
|
|
|
mul.seekg( offset, std::ios::beg );
|
|
|
|
|
auto data = std::vector<std::uint8_t>( length, 0 );
|
|
|
|
|
mul.read( reinterpret_cast<char*>( data.data() ), length );
|
|
|
|
|
ProcessData( isHS, mulid, data );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
mulid += 1;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
return rValue;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::LoadMultiCollection()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - Load Multi UOP data from disk
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
auto MultiCollection::LoadMultiCollection( const std::filesystem::path &uodir, TileInfo *info ) -> bool
|
|
|
|
|
{
|
|
|
|
|
auto rValue = false;
|
2022-06-12 16:54:32 -04:00
|
|
|
// First, see if the uop exists?
|
2022-10-24 18:39:33 +08:00
|
|
|
auto multifile = uodir / std::filesystem::path( "MultiCollection.uop" );
|
|
|
|
|
if( std::filesystem::exists( multifile ))
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
// It does, so lets load the uop
|
UOX3 0.99.6-RC6
Removed arbitrary and hidden restrictions on refreshing list of online players shown with 'wholist command
Fixed an issue where player ghosts that get teleported would not see themselves get updated to new location
Fixed a server crash from clients disconnecting while running server in debug mode
Improved how container updates are sent to players; now only sends to clients that have actually opened the container, and who are still within range
Added more information about UO data files being loaded during server startup
Enhanced the GM 'add menu to allow clicking directly on images of items/npcs to add them, and adjusted size of menus to accommodate this
Fixed an issue with fleeing NPCs that could cause them to attempt to flee across time and space, regardless of distance to target/attacker in combat
Added NPC AI that runs away from players if they get too close (even outside combat). Applied to hind, rabbits, squirrels, ferrets and various birds by default:
AI_ANIMAL_SCARED (aitype 12)
Fixed issues with NPCs fleeing forever, or getting stuck in flee/don't flee loop, by introducing max fleeing distance (50 tiles) and cooldown (30 sec) on fleeing
Updated onNameRequest JS Event to include third parameter with origin of name request, so script responses can be tailored appropriately:
onNameRequest( myObj, requestedBy, requestSource )
Potential values for requestSource:
0 - Speech/System Messages
1 - Guild Menus
2 - Stat Window (self)
3 - Stat Window (other)
4 - Tooltip
5 - Paperdoll Journal
6 - Paperdoll
7 - Single Click / All-Names
8 - System
9 - Secure Trade Window
Added Adaptive Performance System (APS) that dynamically adjust how often NPC AI/movement is checked based on overall shard performance. If performance drops below defined threshold, UOX3 gradually slows down checks for NPC AI/movement to prioritize player movement/speech/command responsiveness. If performance climbs back up above threshold, slowdowns are gradually removed. The following UOX.INI options have been added under [system] category to support this system:
APSPERFTHRESHOLD=50 // Performance threshold (measured in simulation cycles/sec) below which the APS kicks in
APSINTERVAL=100 // How often (in milliseconds) the APS checks performance and makes adjustments (if needed) to balance out shard performance
APSDELAYSTEP=50 // How much the delay timer is modified by (in milliseconds) each time APS makes adjustments
APSDELAYMAXCAP=2000 // Max amount of of delay APS can introduce for NPC AI/movement handling when attempting to restore shard performance
Added new JS Methods for Region objects:
.GetOrePrefs( oreType ) // Get ore preference data for ore type found in town region. Returned as an array containing the following data:
orePrefData -> [
oreName, // name of ore
color, // color of ore
minskill, // min skill to mine ore
ingotName, // name of ingot created from ore
makemenu, // makemenu entry for crafting something from ingot
oreChance, // default global chance of finding this ore type
scriptID // script attached to mined ore
],
orePrefChance // Chance of finding this ore type in given town region
.GetOreChance() // Get base chance of finding any ore in town region
Moved Mining skill plus gravedigging feature from hard code to scripts (js/skill/mining.js) to make it easier to maintain and/or customize, and removed hard coded variants
Gravedigging now relies on the ore resource system behind the scenes to restrict how often graves in a given area can be dug up
Fixed some incorrect references to .worldNumber Character property in misc scripts (should be .worldnumber)
Made some "hard-scripted" system messages in misc scripts use dictionary system instead
Added spawn region for banker NPCs in Serpent's Hold (dfndata/spawn/felucca/spawn_town_serpents_hold.dfn, dfndata/spawn/trammel/spawn_town_serpents_hold.dfn)
Fixed region definition of Ocllo to actually cover the entire town (dfndata/regions/regions.dfn)
Added numerous additional locations accessible with 'goplace # command, for key locations in Ilshenar, Malas, Tokuno Islands and Ter Mur (dfndata/location/location.dfn)
Revised travel-menu portion of GM menu (shortcut: 'travel) to include more travel options based on new locations (dfndata/items/travelmenu.dfn and travelmenu.bulk.dfn)
Fixed an issue where NPCs could attempt to attack targets in other worlds/instances
Added new JS Event that triggers for characters who are about to deal damage in combat. Complimentary to onDamage, which triggers for chars receiving damage:
onDamageDeal( dmgDealer, dmgReceiver, damageValue, damageType )
Added new JS Event that can trigger in global script upon creation of new player chars. Note that this will trigger in place of onCreateDFN event for player characters:
onCreatePlayer( pChar )
Added new JS Event that triggers for characters selecting a target with a spell. Complimentary to onSpellTarget, which triggers for targets selected with a spell:
onSpellTargetSelect( caster, target, spellNum )
Updated onCombatStart and onCombatEnd JS Events to also trigger for the other party in combat
Updated onPickup JS Event to include a third parameter - the potential container item was picked up from. Event now also triggers event in scripts attached to said containers:
onPickup( iPickedUp, pChar, iCont )
Added tracking of total playtime per individual character, and per account across all characters, and exposed these properties to JS engine:
.totalPlayTime // Account property, total playtime across all chars
.playTime // Character property, total playtime on given character only
Added new player-accessible command ('playtime) to spit out the playtime of current character/account as a whole (js/commands/playtime.js)
Implemented first version of Young Player System:
Replaced the UNUSED9 account flag with YOUNG, to be used by Young/New Player System
Added new JS Account property that gets/sets whether player account is considered Young:
.isYoung
Added new Char timers:
TIMER_YOUNGHEAL // Restricts how often Young players are healed by NPC healers
TIMER_YOUNGMESSAGE // Restricts how often Young players are warned about dangerous looking monsters in overworld
Updated GM commands 'get and 'set to get/set .isYoung property of player's account (js/commands/targeting/get.js and set.js)
Added new UOX.INI setting to enable/disable Young Player System (enabled by default):
YOUNGPLAYERSYSTEM=1
If Young Player System is enabled, all newly created player accounts are automatically marked with Young flag
Added new script to handle various restrictions and functions related to Young characters (js/player/young_player.js):
Young characters will have [Young] displayed over their head
Young characters will have their Young status checked and verified on every login + every stat/skill gain, to revoke the Young status if any of the following is true:
Account has a total playtime of more than 40 hours
Any character has more than 350 total (base) skill points
Any character has more than 70 skill points in a single skill
Any character has more than 150 total stat points
Any character has more than 80 stat points in a single stat
Young characters can renounce their Young status manually by saying the words "I renounce my young player status"
Young characters get two additional items upon creation:
a new player ticket (can be combined with any other players new player ticket for both players to get a reward)
a sextant (shows Young players directions to nearest moongate/bank regardless of where they are, as long as outdoors)
Young characters cannot target other player characters with hostile spells or skills
Young characters cannot be the target of other player characters' hostile spells or skills
Young characters can only cast beneficial spells upon themselves or other Young characters
Young characters can only be the target of beneficial spells from other Young players
Young players (and their pets/followers) cannot attack or harm any other players (or their pets/followers), nor themselves be attacked or harmed by any other players (or their pets/followers), whether from combat, spells, skills or items
Young players don't lose any of their items on death, and are teleported to the nearest healer upon death with all their items intact
Young players receive a warning upon entering dungeons that monsters there will be hostile
Updated global script (js/server/global.js) to:
Check/Verify Young status of players upon login
Attach young player script on login/creation for players on Young accounts
Give specific items to Young players upon creation
Added new script (js/item/corpse.js) that is assigned to all freshly created corpses. This script handles restrictions related to Young players interactions with corpses, and the interactions of other players with corpses of Young players
Updated JS Method .Carve() to return true/false depending on whether carving a corpse was successful
Updated Healer AI in code to heal nearby injured Young players
Updated Evil AI and Evil Caster AI in code to avoid selecting Young players as targets in combat outside of dungeons
Added a new section to UOX.INI - [young player starting locations] - that can be used to define starting locations for Young players. If only one such location is provided, all players start there. Otherwise, it matches the same starting location setup as the regular one - with one entry per town in Britannia.
Restricted transferring and/or friending of pets (code) and hirelings (hirelings.js) between Young and non-Young players
Restricted Young players from recalling or gating to Felucca facet
Young players can instantly logout from anywhere, at any time
2023-07-01 20:02:40 +08:00
|
|
|
Console << "\t" << uodir.string() << "MultiCollection.uop" << "\t\t";
|
2022-10-24 18:39:33 +08:00
|
|
|
rValue = LoadMultiCollection( uodir, "", info );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
else
|
|
|
|
|
{
|
UOX3 0.99.6-RC6
Removed arbitrary and hidden restrictions on refreshing list of online players shown with 'wholist command
Fixed an issue where player ghosts that get teleported would not see themselves get updated to new location
Fixed a server crash from clients disconnecting while running server in debug mode
Improved how container updates are sent to players; now only sends to clients that have actually opened the container, and who are still within range
Added more information about UO data files being loaded during server startup
Enhanced the GM 'add menu to allow clicking directly on images of items/npcs to add them, and adjusted size of menus to accommodate this
Fixed an issue with fleeing NPCs that could cause them to attempt to flee across time and space, regardless of distance to target/attacker in combat
Added NPC AI that runs away from players if they get too close (even outside combat). Applied to hind, rabbits, squirrels, ferrets and various birds by default:
AI_ANIMAL_SCARED (aitype 12)
Fixed issues with NPCs fleeing forever, or getting stuck in flee/don't flee loop, by introducing max fleeing distance (50 tiles) and cooldown (30 sec) on fleeing
Updated onNameRequest JS Event to include third parameter with origin of name request, so script responses can be tailored appropriately:
onNameRequest( myObj, requestedBy, requestSource )
Potential values for requestSource:
0 - Speech/System Messages
1 - Guild Menus
2 - Stat Window (self)
3 - Stat Window (other)
4 - Tooltip
5 - Paperdoll Journal
6 - Paperdoll
7 - Single Click / All-Names
8 - System
9 - Secure Trade Window
Added Adaptive Performance System (APS) that dynamically adjust how often NPC AI/movement is checked based on overall shard performance. If performance drops below defined threshold, UOX3 gradually slows down checks for NPC AI/movement to prioritize player movement/speech/command responsiveness. If performance climbs back up above threshold, slowdowns are gradually removed. The following UOX.INI options have been added under [system] category to support this system:
APSPERFTHRESHOLD=50 // Performance threshold (measured in simulation cycles/sec) below which the APS kicks in
APSINTERVAL=100 // How often (in milliseconds) the APS checks performance and makes adjustments (if needed) to balance out shard performance
APSDELAYSTEP=50 // How much the delay timer is modified by (in milliseconds) each time APS makes adjustments
APSDELAYMAXCAP=2000 // Max amount of of delay APS can introduce for NPC AI/movement handling when attempting to restore shard performance
Added new JS Methods for Region objects:
.GetOrePrefs( oreType ) // Get ore preference data for ore type found in town region. Returned as an array containing the following data:
orePrefData -> [
oreName, // name of ore
color, // color of ore
minskill, // min skill to mine ore
ingotName, // name of ingot created from ore
makemenu, // makemenu entry for crafting something from ingot
oreChance, // default global chance of finding this ore type
scriptID // script attached to mined ore
],
orePrefChance // Chance of finding this ore type in given town region
.GetOreChance() // Get base chance of finding any ore in town region
Moved Mining skill plus gravedigging feature from hard code to scripts (js/skill/mining.js) to make it easier to maintain and/or customize, and removed hard coded variants
Gravedigging now relies on the ore resource system behind the scenes to restrict how often graves in a given area can be dug up
Fixed some incorrect references to .worldNumber Character property in misc scripts (should be .worldnumber)
Made some "hard-scripted" system messages in misc scripts use dictionary system instead
Added spawn region for banker NPCs in Serpent's Hold (dfndata/spawn/felucca/spawn_town_serpents_hold.dfn, dfndata/spawn/trammel/spawn_town_serpents_hold.dfn)
Fixed region definition of Ocllo to actually cover the entire town (dfndata/regions/regions.dfn)
Added numerous additional locations accessible with 'goplace # command, for key locations in Ilshenar, Malas, Tokuno Islands and Ter Mur (dfndata/location/location.dfn)
Revised travel-menu portion of GM menu (shortcut: 'travel) to include more travel options based on new locations (dfndata/items/travelmenu.dfn and travelmenu.bulk.dfn)
Fixed an issue where NPCs could attempt to attack targets in other worlds/instances
Added new JS Event that triggers for characters who are about to deal damage in combat. Complimentary to onDamage, which triggers for chars receiving damage:
onDamageDeal( dmgDealer, dmgReceiver, damageValue, damageType )
Added new JS Event that can trigger in global script upon creation of new player chars. Note that this will trigger in place of onCreateDFN event for player characters:
onCreatePlayer( pChar )
Added new JS Event that triggers for characters selecting a target with a spell. Complimentary to onSpellTarget, which triggers for targets selected with a spell:
onSpellTargetSelect( caster, target, spellNum )
Updated onCombatStart and onCombatEnd JS Events to also trigger for the other party in combat
Updated onPickup JS Event to include a third parameter - the potential container item was picked up from. Event now also triggers event in scripts attached to said containers:
onPickup( iPickedUp, pChar, iCont )
Added tracking of total playtime per individual character, and per account across all characters, and exposed these properties to JS engine:
.totalPlayTime // Account property, total playtime across all chars
.playTime // Character property, total playtime on given character only
Added new player-accessible command ('playtime) to spit out the playtime of current character/account as a whole (js/commands/playtime.js)
Implemented first version of Young Player System:
Replaced the UNUSED9 account flag with YOUNG, to be used by Young/New Player System
Added new JS Account property that gets/sets whether player account is considered Young:
.isYoung
Added new Char timers:
TIMER_YOUNGHEAL // Restricts how often Young players are healed by NPC healers
TIMER_YOUNGMESSAGE // Restricts how often Young players are warned about dangerous looking monsters in overworld
Updated GM commands 'get and 'set to get/set .isYoung property of player's account (js/commands/targeting/get.js and set.js)
Added new UOX.INI setting to enable/disable Young Player System (enabled by default):
YOUNGPLAYERSYSTEM=1
If Young Player System is enabled, all newly created player accounts are automatically marked with Young flag
Added new script to handle various restrictions and functions related to Young characters (js/player/young_player.js):
Young characters will have [Young] displayed over their head
Young characters will have their Young status checked and verified on every login + every stat/skill gain, to revoke the Young status if any of the following is true:
Account has a total playtime of more than 40 hours
Any character has more than 350 total (base) skill points
Any character has more than 70 skill points in a single skill
Any character has more than 150 total stat points
Any character has more than 80 stat points in a single stat
Young characters can renounce their Young status manually by saying the words "I renounce my young player status"
Young characters get two additional items upon creation:
a new player ticket (can be combined with any other players new player ticket for both players to get a reward)
a sextant (shows Young players directions to nearest moongate/bank regardless of where they are, as long as outdoors)
Young characters cannot target other player characters with hostile spells or skills
Young characters cannot be the target of other player characters' hostile spells or skills
Young characters can only cast beneficial spells upon themselves or other Young characters
Young characters can only be the target of beneficial spells from other Young players
Young players (and their pets/followers) cannot attack or harm any other players (or their pets/followers), nor themselves be attacked or harmed by any other players (or their pets/followers), whether from combat, spells, skills or items
Young players don't lose any of their items on death, and are teleported to the nearest healer upon death with all their items intact
Young players receive a warning upon entering dungeons that monsters there will be hostile
Updated global script (js/server/global.js) to:
Check/Verify Young status of players upon login
Attach young player script on login/creation for players on Young accounts
Give specific items to Young players upon creation
Added new script (js/item/corpse.js) that is assigned to all freshly created corpses. This script handles restrictions related to Young players interactions with corpses, and the interactions of other players with corpses of Young players
Updated JS Method .Carve() to return true/false depending on whether carving a corpse was successful
Updated Healer AI in code to heal nearby injured Young players
Updated Evil AI and Evil Caster AI in code to avoid selecting Young players as targets in combat outside of dungeons
Added a new section to UOX.INI - [young player starting locations] - that can be used to define starting locations for Young players. If only one such location is provided, all players start there. Otherwise, it matches the same starting location setup as the regular one - with one entry per town in Britannia.
Restricted transferring and/or friending of pets (code) and hirelings (hirelings.js) between Young and non-Young players
Restricted Young players from recalling or gating to Felucca facet
Young players can instantly logout from anywhere, at any time
2023-07-01 20:02:40 +08:00
|
|
|
Console << "\t" << uodir.string() << "multi.mul" << " / multi.idx" << "\t\t";
|
2022-10-24 18:39:33 +08:00
|
|
|
rValue = LoadMul( uodir, info );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
return rValue;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::ProcessHash()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - ???
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
2022-11-14 19:24:29 -05:00
|
|
|
auto MultiCollection::ProcessHash( std::uint64_t hash, [[maybe_unused]] std::size_t entry, std::vector<std::uint8_t> &data ) -> bool
|
2022-10-24 18:39:33 +08:00
|
|
|
{
|
|
|
|
|
if( hash == 0x126D1E99DDEDEE0ALL )
|
|
|
|
|
{
|
|
|
|
|
if( !_housingBin.empty() )
|
|
|
|
|
{
|
|
|
|
|
auto output = std::ofstream( _housingBin, std::ios::binary );
|
|
|
|
|
if( output.is_open() )
|
|
|
|
|
{
|
|
|
|
|
output.write( reinterpret_cast<char*>( data.data() ), data.size() );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
return false; // This is the hash for the housing.bin file
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
return true;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::ProcessEntry()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - ???
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
2022-11-14 19:24:29 -05:00
|
|
|
auto MultiCollection::ProcessEntry( [[maybe_unused]] std::size_t entry, std::size_t index, std::vector<std::uint8_t> &data ) -> bool
|
2022-10-24 18:39:33 +08:00
|
|
|
{
|
|
|
|
|
if( data.size() > 8 )
|
|
|
|
|
{
|
|
|
|
|
auto offset = std::uint32_t( 4 );
|
2022-06-12 16:54:32 -04:00
|
|
|
// We skip the first 32 bit word (why offset is 4).
|
2022-10-24 18:39:33 +08:00
|
|
|
// The next 32 bit word is the number of entries in this data;
|
2022-11-04 17:12:13 -04:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
auto count = std::int32_t( 0 );
|
|
|
|
|
std::copy( data.data() + offset, data.data() + offset + 4, reinterpret_cast<std::uint8_t*>( &count ));
|
|
|
|
|
offset += 4;;
|
2022-06-12 16:54:32 -04:00
|
|
|
// we increment offfset now that we have read the count
|
2022-10-24 18:39:33 +08:00
|
|
|
// at this point,we are now looking at the data for each entry;
|
2022-06-12 16:54:32 -04:00
|
|
|
// before we start looping, make some dummy read space we can get data
|
|
|
|
|
// out of the vector
|
2022-10-24 18:39:33 +08:00
|
|
|
auto flag = std::int16_t( 0 );
|
|
|
|
|
auto clilocs = std::uint32_t( 0 );
|
|
|
|
|
auto multi = CollectionItem_st();
|
|
|
|
|
multi.items.resize( count );
|
|
|
|
|
auto first = true;
|
|
|
|
|
for( auto entry = 0; entry < count; ++entry )
|
|
|
|
|
{
|
|
|
|
|
auto item = MultiItem_st();
|
|
|
|
|
// Get the tileId
|
|
|
|
|
std::copy( data.begin() + offset, data.begin() + offset + 2, reinterpret_cast<unsigned char*>( &item.tileId ));
|
|
|
|
|
offset += 2;
|
|
|
|
|
if( info )
|
|
|
|
|
{
|
|
|
|
|
item.info = &info->ArtInfo( item.tileId );
|
2022-06-15 11:24:57 -04:00
|
|
|
}
|
2022-06-12 16:54:32 -04:00
|
|
|
// Now get the xoffset --
|
2022-10-24 18:39:33 +08:00
|
|
|
std::copy( data.begin()+offset, data.begin() + offset + 2, reinterpret_cast<unsigned char*>( &flag ));
|
|
|
|
|
item.offsetX = static_cast<int>(flag);
|
|
|
|
|
offset += 2;
|
2022-06-12 16:54:32 -04:00
|
|
|
// Now get the yoffset
|
2022-10-24 18:39:33 +08:00
|
|
|
std::copy( data.begin()+offset, data.begin() + offset + 2, reinterpret_cast<unsigned char*>( &flag ));
|
|
|
|
|
item.offsetY = static_cast<int>(flag);
|
|
|
|
|
offset += 2;
|
2022-06-12 16:54:32 -04:00
|
|
|
// Now get the z
|
2022-10-24 18:39:33 +08:00
|
|
|
std::copy( data.begin()+offset, data.begin() + offset + 2, reinterpret_cast<unsigned char*>( &flag ));
|
|
|
|
|
item.altitude = static_cast<int>(flag);
|
|
|
|
|
offset += 2;
|
2022-06-12 16:54:32 -04:00
|
|
|
// now we need to get the flag
|
2022-10-24 18:39:33 +08:00
|
|
|
std::copy( data.begin()+offset, data.begin() + offset + 2, reinterpret_cast<unsigned char*>( &flag ));
|
|
|
|
|
offset += 2;
|
|
|
|
|
switch( flag )
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
default:
|
|
|
|
|
case 0:
|
2022-10-24 18:39:33 +08:00
|
|
|
item.flag = 1;
|
2022-06-12 16:54:32 -04:00
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
break;
|
|
|
|
|
case 257:
|
2022-10-24 18:39:33 +08:00
|
|
|
item.flag = 0x800;
|
2022-06-12 16:54:32 -04:00
|
|
|
break;
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
if( flag == 0 )
|
|
|
|
|
{
|
|
|
|
|
if( first )
|
|
|
|
|
{
|
|
|
|
|
multi.maxY = item.offsetY;
|
|
|
|
|
multi.minY = item.offsetY;
|
|
|
|
|
multi.maxX = item.offsetX;
|
|
|
|
|
multi.minX = item.offsetX;
|
|
|
|
|
multi.maxAlt = item.altitude;
|
|
|
|
|
multi.minAlt = item.altitude;
|
|
|
|
|
first = false;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
multi.maxY = std::max( item.offsetY, multi.maxY );
|
|
|
|
|
multi.minY = std::max( item.offsetY, multi.minY );
|
|
|
|
|
multi.maxX = std::max( item.offsetX, multi.maxX );
|
|
|
|
|
multi.minX = std::max( item.offsetX, multi.minX );
|
|
|
|
|
multi.maxAlt = std::max( item.altitude, multi.maxAlt );
|
|
|
|
|
multi.minAlt = std::max( item.altitude, multi.minAlt );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// we now have some clilocs to read past, have to find out how many
|
2022-10-24 18:39:33 +08:00
|
|
|
std::copy( data.begin() + offset, data.begin() + offset + 4, reinterpret_cast<unsigned char*>( &clilocs ));
|
|
|
|
|
offset += 4;
|
2022-06-12 16:54:32 -04:00
|
|
|
// Now skip past them;
|
2022-10-24 18:39:33 +08:00
|
|
|
offset += ( clilocs * 4 );
|
|
|
|
|
multi.items[entry] = std::move( item );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
_multis.insert_or_assign( static_cast<int>( index ), std::move( multi ));
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
return true;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Function - MultiCollection::ProcessData()
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
//| Purpose - ???
|
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
|
|
|
auto MultiCollection::ProcessData( bool isHS, int index, std::vector<std::uint8_t> &data ) -> void
|
|
|
|
|
{
|
|
|
|
|
auto size = ( isHS ? 16 : 12 );
|
|
|
|
|
auto count = static_cast<int>( data.size() ) / size;
|
|
|
|
|
auto multi = CollectionItem_st();
|
|
|
|
|
auto first = true;
|
|
|
|
|
for( auto entry = 0; entry < count; ++entry )
|
|
|
|
|
{
|
|
|
|
|
auto item = MultiItem_st();
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
std::copy( data.data() + ( entry * size ), data.data() + ( entry * size ) + 2, reinterpret_cast<std::uint8_t*>( &item.tileId ));
|
|
|
|
|
if( info )
|
|
|
|
|
{
|
|
|
|
|
item.info = &( info->ArtInfo( item.tileId ));
|
2022-06-15 11:24:57 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
auto value = std::int16_t( 0 );
|
|
|
|
|
std::copy( data.data() + ( entry * size ) + 2, data.data() + ( entry * size ) + 2 + 2, reinterpret_cast<std::uint8_t*>( &value ));
|
|
|
|
|
item.offsetX = value;
|
|
|
|
|
std::copy( data.data() + ( entry * size ) + 4, data.data() + ( entry * size ) + 4 + 2, reinterpret_cast<std::uint8_t*>( &value ));
|
|
|
|
|
item.offsetY = value;
|
|
|
|
|
std::copy( data.data() + ( entry * size ) + 6, data.data() + ( entry * size ) + 6 + 2, reinterpret_cast<std::uint8_t*>( &value ));
|
|
|
|
|
item.altitude = value;
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
if( isHS )
|
|
|
|
|
{
|
|
|
|
|
auto flag = std::uint64_t( 0 );
|
|
|
|
|
std::copy( data.data() + ( entry * size ) + 8, data.data() + ( entry * size ) + 8 + 8, reinterpret_cast<std::uint8_t*>( &flag ));
|
|
|
|
|
item.flag = static_cast<std::uint16_t>( flag );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto flag = std::uint32_t( 0 );
|
0.99.6-RC6x
Added dummy context restore function to additional scripts
Updated 'go command to support specifying location to teleport to by name, mapped to locations from locations.dfn (Thanks Dragon Slayer!)
Updated Smart Turn script for furniture (js/server/misc/furniture_smartturn.js) with more optimized code (Humility)
Fixed latitude/longitude output of GetMapCoordinates helper function (js/server/data/map_coordinates.js), and updated scripts that relied on it
Fixed an issue where trying to craft fletching tools would produce hatchets instead (js/skill/craft/fletching.js)
Updated js/item/bankcheck.js to display value of checks using onTooltip JS Event, or onNameRequest JS Event if tooltips are disabled
Fixed a couple of DFN formatting issues (thanks, punt)
Fixed an issue where blank deeds (and bank checks) would be pileable if dropped on the same container (dfndata/items/tools/inscription.dfn)
Added dedicated [bankcheck] DFN item (dfndata/items/misc/money.dfn)
Updated Banker AI script (js/npc/ai/banker.js) to use dedicated [bankcheck] item instead of blank deeds as base for bank checks, and to have banker NPCs pause and turn towards player when talked to
Fixed an issue with script for Healing/Veterinary (js/skill/healing.js) which incorrectly used Anatomy as supplementary skill for Veterinary instead of Animal Lore, and which checked dex of wrong character when calculating healing slips
Added two missing tile flags to tileflag enum that threw order of such flags added with HS expansion out of order (thanks, punt)
Fixed an issue with travel-commands in GM menu which handled travelling between facets incorrectly
Added region spawners for dungeons, towns and overworld in Ilshenar facet
Enabled Trammel and Ilshenar facet decorations/spawns by default in admin welcome script (js/server/misc/admin_welcome.js)
Reworked portions of admin welcome gump to display optional "addon" decorations per facet, which might be client/era-specific (js/server/misc/admin_welcome.js)
Added new NPCs to dfndata/npc/femalehuman.dfn: f_executioner, f_chaosdragoon, f_chaosdragoonelite, f_gypsybanker
Added new NPCs to dfndata/npc/femalevendors.dfn: f_gypsymaiden, f_gypsyanimaltrainer, f_gypsyfortuneteller, f_vagabond, f_ironworker
Added new NPCs to dfndata/npc/malehuman.dfn: m_executioner, m_chaosdragoon, m_chaosdragoonelite, m_gypsybanker
Added new NPCs to dfndata/npc/malevendors.dfn: m_gypsyanimaltrainer, m_vagabond, m_ironworker
Added new NPC to dfndata/npc/miscmonsters.dfn: darkwisp
Added new NPC to dfndata/npc/undead.dfn: ancientlich
Added new Item DFNs for "camps" that when spawned will create a camp with specific decorations ([ilsh_orc_camp], [ilsh_healer_camp], [ilsh_mage_camp], [ilsh_banker_camp])
Added scripts for camps (js/item/camps/ilsh_banker_camp.js, js/item/camps/ilsh_healer_camp.js, js/item/camps/ilsh_mage_camp.js, js/item/camps/ilsh_orc_camp.js)
Added new colorlist to dfndata/colors/colors.dfn: [RANDOMCOLOR 33] (Bright Primary Colors)
Fixed an issue with gargish cloth chest DFN which prevented LBR version from working properly (dfndata/items/gear/armor/gargish_armor/gargish_cloth.dfn)
Added a bunch of new NPCLISTS in various npclist DFN files to support regional spawns in Ilshenar
Added missing BACKPACK tag to [golem] NPC DFN (dfndata/npc/clockwork.dfn)
Fixed misspelled section header for Fire Elemental NPC - from firele to fireele (dfndata/npc/elementals.dfn)
Murderous brigand NPCs are no longer willing to teach players skills (dfndata/npc/femalehuman.dfn, dfndata/npc/malehuman.dfn)
Corrected coordinates of Rock Dungeon region (dfndata/regions/regions.dfn)
Added regions for Sea Market (Felucca/Trammel), Blackthorn Dungeon (Felucca/Trammel) and Lakeshire (Ilshenar) (dfndata/regions/regions.dfn)
Fixed an issue with 'radditem and 'raddspawner GM commands which would not correctly set the Z of the added item/spawner to match target location (js/commands/custom/repeatingcmds.js)
Added two new repeating commands (js/commands/custom/repeatingcmds.js):
'rmovable # // Repeats bringing up targeting cursor to set movable property on multiple objects
'rnodecay // Repeats bringing up targeting cursor to set decayable property to false on multiple objects
Added new areacommand (js/commands/targeting/areacommand.js):
'areacommand name [string] // Sets name of all objects within targeted area to [string]
Updated 'decorate command script to better handle flags passed in via admin welcome script for things like facet addons (js/commands/decorate.js)
Updated fire breath script (js/npc/special/fire_breath.js) to get fire breath info per NPC based on their sectionID rather than their base body ID
Updated facet ruleset script (js/server/misc/facetRuleset.js) with an override for GMs trying to snoop players even in places where snooping is disallowed
Updated facet ruleset script (js/server/misc/facetRuleset.js) to allow damage that's not coming from a player/NPC source even in Trammel/Ilshenar
Added teleport locations for entering/leaving Blackthorn Dungeon in Felucca/Trammel (js/teleport.scp)
Updated 'remove and 'rremove commands to release any targeted objects from potential multis they are locked in to properly update lockdown count (js/commands/targeting/remove.js, js/commands/custom/repeatingcmds.js)
Updated felucca/ilshenar world templates with decorations (js/jsdata/worldtemplates/felucca_*/ilshenar_*)
Added world templates with decorations for Trammel (js/jsdata/worldtemplates/trammel_*)
Added DFN entry for Power Generators, and spawn entries for these in Ilshenar (dfndata/item/puzzles/puzzles.dfn, dfndata/spawn/ilshenar/spawn_ilshenar_world_general.dfn)
Added script for Power Generators, which initializes random puzzles on creation and rewards player with diamonds/arcane gems/shadow iron ore when solved, or lightning when failing to solve (js/item/power_generator.js)
Added support for overriding newbie-state of items added to players via dfndata/newbie/newbie.dfn. Supported syntax:
PACKITEM=sectionID[, amount[, newbieFlag]] // To use newbieFlag with PACKITEM, amount must also be specified. Flag can be 0/1
EQUIPITEM=sectionID[, itemHue[, newbieFlag] // To use newbieFlag with EQUIPITEM, itemHue must also be specified. Flag can be 0/1
Casting the Earthquake spell will no longer affect the caster, or cause them to become criminal when cast out of town with no impacted targets
Fixed a bug where caster would remain frozen after finishing casting targetless spells like Earthquake
Fixed a bug where caster would remain frozen if spellcast was cancelled half-ways through by picking up or equipping an item
Fixed a bug where caster would remain frozen if spellcast was interrupted by losing concentration from taking melee damage in combat
Fixed a bug where a paralyzed player would remain frozen even if taking magic or poison damage, which releases them from paralyzis
Fixed a bug where target of Paralyze spell would not visually be shown as frozen in target's client
Fixed a bug where a caster frozen while casting a spell could become unfrozen mid-cast because of incoming magic damage
Address overflow issue in MultiMul.cpp (punt)
Address various cast issues (punt)
Corrected jscript project, to not include two files that where for stand alone programs (and resulted in main being added twice in the library (and once was incorrect all ready). (punt)
Replaced RoundNumber with std::round (punt)
The original physical appearance of characters targeted by 'make admin/gm/cns is now kept track of, and restored upon being targeted by 'make player
Fixed an issue where the .HasSpell JS Method was off by 1 when looking for specific spells in player's spellbook, due to 0-based array indexing in code vs 1-based indexing for Spells in DFNs
2023-10-14 05:03:53 +08:00
|
|
|
std::copy( data.data() + ( entry * size ) + 4, data.data() + ( entry * size ) + 4 + 4, reinterpret_cast<std::uint8_t*>( &flag ));
|
2022-10-24 18:39:33 +08:00
|
|
|
item.flag = static_cast<std::uint16_t>( flag );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
if( first )
|
|
|
|
|
{
|
|
|
|
|
multi.maxY = item.offsetY;
|
|
|
|
|
multi.minY = item.offsetY;
|
|
|
|
|
multi.maxX = item.offsetX;
|
|
|
|
|
multi.minX = item.offsetX;
|
|
|
|
|
multi.maxAlt = item.altitude;
|
|
|
|
|
multi.minAlt = item.altitude;
|
|
|
|
|
first = false;
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
multi.maxY = std::max( item.offsetY, multi.maxY );
|
|
|
|
|
multi.minY = std::max( item.offsetY, multi.minY );
|
|
|
|
|
multi.maxX = std::max( item.offsetX, multi.maxX );
|
|
|
|
|
multi.minX = std::max( item.offsetX, multi.minX );
|
|
|
|
|
multi.maxAlt = std::max( item.altitude, multi.maxAlt );
|
|
|
|
|
multi.minAlt = std::max( item.altitude, multi.minAlt );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
2022-11-14 19:24:29 -05:00
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
multi.items.push_back( item );
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
UOX3 0.99.6-RC4
Fixed an issue that prevented onBuyFromVendor() and onBoughtFromVendor() JS Events from triggering when attached to NPC shopkeepers
Fixed an issue with help gump that prevented password management section from working as intended (js/server/misc/helpgump.js)
Fixed an issue where UOX3 would fail to load pre-HS multi.mul files
Added chess board to Misc->Games add menu (dfndata/items/ItemMenu.bulk.dfn)
Fixed an issue with 'move (alias for 'telestuff) command that referenced the wrong variable name (js/commands/targeting/tele.js)
When a player is teleported via the GM 'wholist menu, any pets within range are now also brought along for the ride
Consolidated error-reporting for JS Functions, Object Methods and Object Properties to provide more context (scriptID, filename, line number) when something goes wrong
Added some missing shield IDs (0xA649, 0xA64A, 0xA831, 0xA832) to IsShieldType() function
MAXRANGE item property previously only worked for ranged weapons; now it works for melee weapons too, and potentially allows melee weapons with combat range longer than 1 tile
MAXRANGE item property can now be used to define max combat range for melee weapons
Fixed an issue (non-critical) with .PlaceInPack() JS Method that would cause UOX3 to try adding items marked for deletion to refreshQueue and spam console with errors
Added missing AI scripts to summoned Blade Spirits and Energy Vortexes (dfndata/npc/magicsummon.dfn)
Fixed an issue with weight calculation for hireling backpacks (js/npc/ai/hireling.js)
Fixed an issue with the 'fix command, which would in most cases set character's Z to -1 regardless of location, but now adheres to map elevation instead
Fixed an issue with Pack AI (js/npc/ai/pack_ai.js) that prevented pack members from attacking target correctly (thanks Dragon Slayer)
Fixed an issue with DoesMapBlock JS Function that incorrectly checked for 6 function arguments, when it actually requires 8
Fixed an issue with DoesDynamicBlock JS Function that incorrectly checked for 8 function arguments, when it actually requires 9
Fixed an issue with runebook script (js/item/runebook.js) that prevented players from being able to use recall charges without having spellbook with spell in inventory
Fixed issues with placement of tall items on ground/floor, and with stacking of items in houses
Fixed incorrect alias for woodland armor (dfndata/items/gear/armor/other/armor/wood.dfn - thanks Dragon Slayer)
Fixed a critical issue with script context sometimes changing while executing a script, because of events in other scripts being triggered. Affected scripts can be safeguarded against this by the addition of a dummy callback function anywhere in the script: function _restorecontext_() {}
Fixed an issue with non-animal pets not gaining loyalty when being fed (thanks Dragon Slayer)
Added new JS Object Methods for Chars/Items/Multis to fetch list of custom tags associated with object:
.GetTagMap() // Gets list of persistent custom tags associated with object
.GetTempTagMap() // Gets list of temporary custom tags associated with object
Added new JS commands ('GETTAGMAP and 'GETTEMPTAGMAP) that spits out details of custom tags associated with targeted object (js/commands/custom/misc-cmd.js)
Added new JS command ('USEITEM) that acts as a short-cut for double-clicking on targeted item (js/commands/custom/misc-cmd.js)
Updated 'ADD # and 'ADD ITEM # JS commands to support targeting a container directly and adding the new item inside (js/commands/targeting/add.js)
Updated axe script to only perform lumberjacking skill-check when there's still wood available in a given area, and to play appropriate animations for Gargoyle players (js/item/axe.js)
Updated script for gameboards to make generated pieces newbiefied so they won't appear on ground if board decays (js/item/gameboards.js)
Updated script for stablemasters to avoid relying on global variables (js/npc/ai/stablemaster.js)
Updated names of items crafted with runic hammers to include the material name of the hammers used to craft them (js/skill/craft/crafting_complete.js)
Fixed a small issue with Detect Hidden skill that would return the wrong message if players found anyone hiding nearby (js/skill/detecthidden.js)
Fixed an issue that prevented tile overrides in dfndata/maps/tiles.dfn from loading properly
Added entries for a couple of walls with missing no-shoot flags to tile overrides in dfndata/maps/tiles.dfn
Updated JS Method .SoundEffect() to support optional third argument (creatureSoundNum) to play creature-defined sounds from dfndata/creatures/creatures.dfn. New syntax:
.SoundEffect( soundID, allHear[, creatureSoundNum] ) // 0=SOUND_STARTATTACK, 1=SOUND_IDLE, 2=SOUND_ATTACK, 3=SOUND_DEFEND, 4=SOUND_DIE
Added new Character JS Methods:
.SetRandomName( nameListID ) // apply a random name from specified namelist to character
.FindItemSection( sectionID ) // find item in player's backpack with specified sectionID
Added new Socket JS Method:
.OpenContainer() // Opens specified container for socket
2023-05-30 01:47:26 +08:00
|
|
|
_multis.insert_or_assign( static_cast<int>( index ), std::move( multi ));
|
2022-06-12 16:54:32 -04:00
|
|
|
}
|
|
|
|
|
|
2022-10-24 18:39:33 +08:00
|
|
|
auto MultiCollection::Size() const -> size_t
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
return _multis.size();
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
auto MultiCollection::Multis() const -> const std::unordered_map<int, CollectionItem_st>&
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
return _multis;
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
auto MultiCollection::Multis() -> std::unordered_map<int, CollectionItem_st>&
|
|
|
|
|
{
|
2022-06-12 16:54:32 -04:00
|
|
|
return _multis;
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
auto MultiCollection::Multi( std::uint16_t multiId ) -> CollectionItem_st&
|
|
|
|
|
{
|
|
|
|
|
return _multis.at( static_cast<int>( multiId ));
|
2022-06-12 19:54:28 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
auto MultiCollection::Multi( std::uint16_t multiId ) const -> const CollectionItem_st&
|
|
|
|
|
{
|
|
|
|
|
return _multis.at( static_cast<int>( multiId ));
|
2022-06-12 19:54:28 -04:00
|
|
|
|
|
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
|
|
|
|
|
auto MultiCollection::Exists( std::uint16_t multiId ) const -> bool
|
|
|
|
|
{
|
|
|
|
|
auto rValue = false;
|
|
|
|
|
auto iter = _multis.find( multiId );
|
|
|
|
|
if( iter != _multis.end() )
|
|
|
|
|
{
|
|
|
|
|
rValue = true;;
|
2022-06-12 19:54:28 -04:00
|
|
|
}
|
2022-10-24 18:39:33 +08:00
|
|
|
return rValue;
|
2022-06-12 19:54:28 -04:00
|
|
|
}
|