├── .clang-format ├── .gitignore ├── .gitlab-ci.yml ├── BlackHole.cpp ├── BlackHole.h ├── BlackHolesTableModel.cpp ├── BlackHolesTableModel.h ├── Click1.wav ├── Equipment.cpp ├── Equipment.h ├── EquipmentTableModel.cpp ├── EquipmentTableModel.h ├── FilterHorizontalHeaderView.cpp ├── FilterHorizontalHeaderView.h ├── Galaxy.cpp ├── Galaxy.h ├── GoodsArr.cpp ├── GoodsArr.h ├── HierarchicalHeaderView.cpp ├── HierarchicalHeaderView.h ├── LICENSE ├── MainWindow.cpp ├── MainWindow.h ├── MainWindow.ui ├── Planet.cpp ├── Planet.h ├── PlanetsTableModel.cpp ├── PlanetsTableModel.h ├── README.md ├── README_ru.md ├── SRHDDumpReader.pro ├── SRHDDumpReader.rc ├── SRHDDumpReader_ru.ts ├── SRHD_GUI_2016-05-17.png ├── Ship.cpp ├── Ship.h ├── SortMultiFilterProxyModel.cpp ├── SortMultiFilterProxyModel.h ├── Star.cpp ├── Star.h ├── TradeTableModel.cpp ├── TradeTableModel.h ├── bonus_descriptions.json ├── bonus_descriptions.json.en ├── bonus_descriptions_artifacts.json ├── bonus_descriptions_hulls.json ├── bonus_descriptions_hulls.json.en ├── bonus_descriptions_micromodules.json ├── bonus_descriptions_micromodules.json.ru ├── descriptions.xlsx ├── dump2json.sh ├── en-ru.txt ├── galaxy_magnifying_glass.ico ├── icons.qrc ├── icons ├── all_reports.svg ├── document-open.svgz ├── document-save-as.svgz ├── galaxy_magnifying_glass.png ├── go-next.svgz ├── go-previous.svgz ├── help-about.svgz ├── report.svg └── view-refresh.svgz ├── main.cpp ├── map_colors.json ├── micromodules_ru-en.txt ├── minRowsPreset.json ├── parseJSON.py ├── presets ├── equipment │ ├── rockets.dr.json │ ├── treasure Transmitters all.dr.json │ ├── treasure arts 45p.dr.json │ └── treasure micromodules 45p.dr.json ├── equipmentReport │ ├── Antigrav.dr.json │ ├── BH.dr.json │ ├── BlastLocaliser.dr.json │ ├── Forsage.dr.json │ ├── GiperJump.dr.json │ ├── MPA.dr.json │ ├── Nanitoids.dr.json │ ├── Transmitters.dr.json │ ├── WeaponToSpeed.dr.json │ ├── arts.dr.json │ ├── micromodules I.dr.json │ ├── micromodules II.dr.json │ ├── micromodules III.dr.json │ ├── rocketsA.dr.json │ ├── rocketsB.dr.json │ ├── rocketsC.dr.json │ ├── rocketsD.dr.json │ └── rocketsE.dr.json ├── planets │ ├── huge industrial gaal 30p.dr.json │ └── huge industrial gaal-fei 45p.dr.json └── planetsReport │ └── huge industrial gaal 30p.dr.json ├── scorers.json ├── selection_colors.json └── translate_descriptions.sh /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: LLVM 3 | Language: Cpp 4 | IndentWidth: 8 5 | UseTab: Always 6 | BreakBeforeBraces: Linux 7 | AlwaysBreakBeforeMultilineStrings: true 8 | AllowShortIfStatementsOnASingleLine: false 9 | AllowShortLoopsOnASingleLine: false 10 | AllowShortFunctionsOnASingleLine: false 11 | IndentCaseLabels: false 12 | AlignEscapedNewlinesLeft: false 13 | AlignTrailingComments: true 14 | AllowAllParametersOfDeclarationOnNextLine: false 15 | AlignAfterOpenBracket: true 16 | SpaceAfterCStyleCast: false 17 | MaxEmptyLinesToKeep: 2 18 | BreakBeforeBinaryOperators: NonAssignment 19 | BreakStringLiterals: false 20 | SortIncludes: false 21 | ContinuationIndentWidth: 8 22 | AccessModifierOffset: -8 23 | 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | /build-*/ 3 | *.qm 4 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - compile 3 | - package 4 | 5 | build-ubuntu: 6 | stage: compile 7 | image: burningdaylight/ubuntu-latest-devel 8 | script: 9 | - mkdir build-ubuntu 10 | - cd build-ubuntu; qmake ..; make 11 | artifacts: 12 | paths: 13 | - build-ubuntu/SRHDDumpReader 14 | 15 | build-win64: 16 | stage: compile 17 | image: burningdaylight/mingw-arch:qt 18 | script: 19 | - mkdir build-win64 20 | - cd build-win64; x86_64-w64-mingw32-qmake-qt5 ..; make 21 | artifacts: 22 | paths: 23 | - build-win64/release/SRHDDumpReader.exe 24 | 25 | build-win32: 26 | stage: compile 27 | image: burningdaylight/mingw-arch:qt 28 | script: 29 | - mkdir build-win32 30 | - cd build-win32; i686-w64-mingw32-qmake-qt5 ..; make 31 | artifacts: 32 | paths: 33 | - build-win32/release/SRHDDumpReader.exe 34 | 35 | pack-ubuntu: 36 | stage: package 37 | image: burningdaylight/ubuntu-latest-devel 38 | script: 39 | - mkdir -p ./SRHDDumpReader 40 | - cp build-ubuntu/SRHDDumpReader ./SRHDDumpReader/ 41 | - cp -r presets ./SRHDDumpReader/ 42 | - cp ./*.json ./SRHDDumpReader/ 43 | - cp ./Click1.wav ./SRHDDumpReader/ 44 | artifacts: 45 | name: "SRHDDumpReader_linux_${CI_BUILD_REF_NAME}-${CI_BUILD_REF:0:8}" 46 | paths: 47 | - SRHDDumpReader 48 | 49 | pack-win64: 50 | stage: package 51 | image: burningdaylight/mingw-arch:qt 52 | script: 53 | - mkdir -p ./SRHDDumpReader/platforms/ 54 | - mkdir -p ./SRHDDumpReader/imageformats/ 55 | - cp build-win64/release/SRHDDumpReader.exe ./SRHDDumpReader/ 56 | - cp /usr/x86_64-w64-mingw32/bin/lib{gcc_s_seh-1,ssp-0,bz2-1,iconv-2,pcre-1,pcre2-16-0,winpthread-1,freetype-6,glib-2.0-0,intl-8,png16-16,harfbuzz-0,graphite2,stdc++-6}.dll ./SRHDDumpReader/ 57 | - cp /usr/x86_64-w64-mingw32/bin/{zlib1,Qt5Core,Qt5Network,Qt5Multimedia,Qt5Gui,Qt5Widgets,Qt5Svg}.dll ./SRHDDumpReader/ 58 | - cp /usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/qwindows.dll ./SRHDDumpReader/platforms/ 59 | - cp /usr/x86_64-w64-mingw32/lib/qt/plugins/imageformats/{qsvg,qico,qtiff,qjpeg}.dll ./SRHDDumpReader/imageformats/ 60 | - cp -r presets ./SRHDDumpReader/ 61 | - cp ./*.json ./SRHDDumpReader/ 62 | - cp ./Click1.wav ./SRHDDumpReader/ 63 | artifacts: 64 | name: "SRHDDumpReader_win64_${CI_BUILD_REF_NAME}-${CI_BUILD_REF:0:8}" 65 | paths: 66 | - SRHDDumpReader 67 | 68 | pack-win32: 69 | stage: package 70 | image: burningdaylight/mingw-arch:qt 71 | script: 72 | - mkdir -p ./SRHDDumpReader/platforms/ 73 | - mkdir -p ./SRHDDumpReader/imageformats/ 74 | - cp build-win32/release/SRHDDumpReader.exe ./SRHDDumpReader/ 75 | - cp /usr/i686-w64-mingw32/bin/lib{gcc_s_dw2-1,ssp-0,bz2-1,iconv-2,pcre-1,pcre2-16-0,winpthread-1,freetype-6,glib-2.0-0,intl-8,png16-16,harfbuzz-0,graphite2,stdc++-6}.dll ./SRHDDumpReader/ || true 76 | - cp /usr/i686-w64-mingw32/bin/{zlib1,Qt5Core,Qt5Network,Qt5Multimedia,Qt5Gui,Qt5Widgets,Qt5Svg}.dll ./SRHDDumpReader/ 77 | - cp /usr/i686-w64-mingw32/lib/qt/plugins/platforms/qwindows.dll ./SRHDDumpReader/platforms/ 78 | - cp /usr/i686-w64-mingw32/lib/qt/plugins/imageformats/{qsvg,qico,qtiff,qjpeg}.dll ./SRHDDumpReader/imageformats/ 79 | - cp -r presets ./SRHDDumpReader/ 80 | - cp ./*.json ./SRHDDumpReader/ 81 | - cp ./Click1.wav ./SRHDDumpReader/ 82 | artifacts: 83 | name: "SRHDDumpReader_win32_${CI_BUILD_REF_NAME}-${CI_BUILD_REF:0:8}" 84 | paths: 85 | - SRHDDumpReader 86 | -------------------------------------------------------------------------------- /BlackHole.cpp: -------------------------------------------------------------------------------- 1 | #include "BlackHole.h" 2 | #include "Galaxy.h" 3 | 4 | BlackHole::BlackHole(QTextStream &stream, unsigned id):_id(id) 5 | { 6 | const static QMap bhOptions={ 7 | {"Star1Id",0}, 8 | {"Star2Id",1}, 9 | {"TurnsToClose",2} 10 | }; 11 | 12 | int nesting=0; 13 | QString line = stream.readLine().trimmed(); 14 | while (!line.isNull()) 15 | { 16 | nesting+=line.contains('{'); 17 | nesting-=line.contains('}'); 18 | if(line.startsWith("HoleId")) 19 | { 20 | nesting-=1; 21 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 22 | _id=idRef.toInt(); 23 | } 24 | if(nesting<0) 25 | { 26 | break; 27 | } 28 | QString varname=line.section('=',0,0); 29 | QString value=line.section('=',-1); 30 | 31 | switch(bhOptions.value(varname,-1)) 32 | { 33 | case 0://Star1Id 34 | _star1Id=value.toInt(); 35 | break; 36 | 37 | case 1://Star2Id 38 | _star2Id=value.toInt(); 39 | break; 40 | 41 | case 2://TurnsToClose 42 | _turnsToClose=value.toInt(); 43 | break; 44 | default: 45 | //skip record 46 | break; 47 | } 48 | line = stream.readLine().trimmed(); 49 | } 50 | } 51 | unsigned BlackHole::id() const 52 | { 53 | return _id; 54 | } 55 | 56 | unsigned BlackHole::star1Id() const 57 | { 58 | return _star1Id; 59 | } 60 | 61 | unsigned BlackHole::star2Id() const 62 | { 63 | return _star2Id; 64 | } 65 | 66 | int BlackHole::turnsToClose() const 67 | { 68 | return _turnsToClose; 69 | } 70 | 71 | void readBlackHoles(QTextStream &stream,Galaxy &galaxy) 72 | { 73 | QString line = stream.readLine().trimmed();; 74 | while (!line.isNull()) 75 | { 76 | if(line.contains("HoleId")) 77 | { 78 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 79 | unsigned id=idRef.toInt(); 80 | galaxy.addBlackHole(BlackHole(stream, id)); 81 | } 82 | else if(line.contains('}')) 83 | { 84 | break; 85 | } 86 | line = stream.readLine().trimmed(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /BlackHole.h: -------------------------------------------------------------------------------- 1 | #ifndef BLACKHOLE_H 2 | #define BLACKHOLE_H 3 | #include 4 | class Galaxy; 5 | class BlackHole 6 | { 7 | public: 8 | BlackHole(QTextStream &stream, unsigned id=0); 9 | unsigned id() const; 10 | unsigned star1Id() const; 11 | unsigned star2Id() const; 12 | int turnsToClose() const; 13 | 14 | private: 15 | unsigned _id; 16 | unsigned _star1Id, _star2Id; 17 | int _turnsToClose; 18 | }; 19 | void readBlackHoles(QTextStream &stream, Galaxy &galaxy); 20 | #endif // BLACKHOLE_H 21 | -------------------------------------------------------------------------------- /BlackHolesTableModel.cpp: -------------------------------------------------------------------------------- 1 | #include "BlackHolesTableModel.h" 2 | 3 | 4 | BlackHolesTableModel::BlackHolesTableModel(const Galaxy *galaxy, QObject *parent): 5 | QAbstractTableModel(parent),_galaxy(galaxy) 6 | { 7 | 8 | } 9 | 10 | int BlackHolesTableModel::rowCount(const QModelIndex &parent) const 11 | { 12 | return _galaxy->blackHoleCount(); 13 | } 14 | 15 | int BlackHolesTableModel::columnCount(const QModelIndex &parent) const 16 | { 17 | return 6; 18 | } 19 | 20 | QVariant BlackHolesTableModel::data(const QModelIndex &index, int role) const 21 | { 22 | if (role == Qt::DisplayRole) 23 | { 24 | int col=index.column(); 25 | int row=index.row(); 26 | switch (col) 27 | { 28 | case 0: 29 | return _galaxy->blackHoleStar1(row); 30 | case 1: 31 | return std::round(_galaxy->blackHoleStar1Distance(row)*10.0)*0.1; 32 | case 2: 33 | return _galaxy->blackHoleStar2(row); 34 | case 3: 35 | return std::round(_galaxy->blackHoleStar2Distance(row)*10.0)*0.1; 36 | case 4: 37 | return _galaxy->blackHoleTurnsToClose(row); 38 | case 5: 39 | return _galaxy->blackHoleNextLootChange(row); 40 | default: 41 | return QVariant(); 42 | } 43 | 44 | return index.row()+index.column(); 45 | } 46 | return QVariant(); 47 | } 48 | 49 | QVariant BlackHolesTableModel::headerData(int section, Qt::Orientation orientation, int role) const 50 | { 51 | static const QVector header={tr("Star 1"),tr("Dist."),tr("Star 2"), 52 | tr("Dist."), tr("Days left"),tr("Next loot change")}; 53 | if (role == Qt::DisplayRole) 54 | { 55 | if (orientation == Qt::Vertical) 56 | { 57 | return _galaxy->blackHoleId(section); 58 | } 59 | else if (orientation == Qt::Horizontal) { 60 | return header.at(section); 61 | } 62 | } 63 | return QVariant(); 64 | } 65 | -------------------------------------------------------------------------------- /BlackHolesTableModel.h: -------------------------------------------------------------------------------- 1 | #ifndef BLACKHOLESTABLEMODEL_H 2 | #define BLACKHOLESTABLEMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Galaxy.h" 9 | 10 | class BlackHolesTableModel : public QAbstractTableModel 11 | { 12 | Q_OBJECT 13 | public: 14 | explicit BlackHolesTableModel(const Galaxy* _galaxy, QObject *parent = 0); 15 | int rowCount(const QModelIndex &parent = QModelIndex()) const ; 16 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 17 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 18 | QVariant headerData(int section, Qt::Orientation orientation, int role) const; 19 | void reload() 20 | { 21 | beginResetModel(); 22 | endResetModel(); 23 | } 24 | 25 | signals: 26 | 27 | public slots: 28 | private: 29 | const Galaxy *_galaxy; 30 | }; 31 | 32 | #endif // BLACKHOLESTABLEMODEL_H 33 | -------------------------------------------------------------------------------- /Click1.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/Click1.wav -------------------------------------------------------------------------------- /Equipment.cpp: -------------------------------------------------------------------------------- 1 | #include "Equipment.h" 2 | #include "Ship.h" 3 | #include "Galaxy.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | const QMap Equipment::specialTypesDescriptions=Equipment::loadDescriptions("bonus_descriptions.json"); 12 | const QMap Equipment::specialHullsDescriptions=Equipment::loadDescriptions("bonus_descriptions_hulls.json"); 13 | const QMap Equipment::micromodulesDescriptions=Equipment::loadDescriptions("bonus_descriptions_micromodules.json"); 14 | const QMap Equipment::artifactsDescriptions=Equipment::loadDescriptions("bonus_descriptions_artifacts.json"); 15 | 16 | Equipment::Equipment(QTextStream &stream, Galaxy &galaxy, LocationType locationType, unsigned locationId, unsigned id): 17 | _id(id),_size(0),_cost(0),_durability(0.0),_techLevel(0),_locationType(locationType),_locationId(locationId) 18 | { 19 | const static QMap intToLandType={{0,"water"},{1,"plain"},{2,"mountains"}}; 20 | const static QMap eqOptions={ 21 | {"IName",0},{"IType",1},{"Owner",2},{"Size",3},{"Cost",4}, 22 | {"Durability",5},{"TechLevel",6},{"ISpecialName",7}, 23 | {"LandType",8},{"Depth",9} 24 | 25 | }; 26 | 27 | QString line = stream.readLine().trimmed();; 28 | while (!line.isNull()) 29 | { 30 | if(line[0]=='}') 31 | { 32 | break; 33 | } 34 | else if(line.startsWith("ShipId")) 35 | { 36 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 37 | unsigned shipId=idRef.toInt(); 38 | Ship(stream,galaxy,shipId,0); 39 | } 40 | else if(line.startsWith("ItemId")) 41 | { 42 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 43 | _id=idRef.toInt(); 44 | } 45 | 46 | 47 | int breakPosition=line.indexOf('='); 48 | QString varname=line.left(breakPosition); 49 | QString value=line.mid(breakPosition+1); 50 | 51 | switch(eqOptions.value(varname,-1)) 52 | { 53 | case 0://IName 54 | _name=std::move(value.remove("")); 55 | _name.remove('"'); 56 | _name.remove(QRegularExpression("")); 57 | break; 58 | 59 | case 1://Itype 60 | _type=std::move(value); 61 | break; 62 | 63 | case 2://Owner 64 | _owner=std::move(value); 65 | break; 66 | 67 | case 3://Size 68 | _size=value.toInt(); 69 | break; 70 | 71 | case 4://Cost 72 | _cost=value.toInt(); 73 | break; 74 | 75 | case 5://Durability 76 | value.replace(',','.'); 77 | _durability=value.toDouble(); 78 | break; 79 | 80 | case 6://TechLevel 81 | _techLevel=value.toInt(); 82 | break; 83 | 84 | case 7://ISpecialName 85 | _specialName=std::move(value); 86 | break; 87 | case 8://LandType 88 | extraFields.insert(std::move(varname),intToLandType.value(value.toInt())); 89 | break; 90 | case 9://Depth 91 | extraFields.insert(std::move(varname),value); 92 | break; 93 | default: 94 | //extraFields[varname]=value; 95 | break; 96 | } 97 | line = stream.readLine().trimmed(); 98 | } 99 | galaxy.addEquipment(std::move(*this)); 100 | } 101 | 102 | QString Equipment::locationTypeString() const 103 | { 104 | switch (_locationType) 105 | { 106 | case kShipEq: 107 | return QObject::tr("Ship/equipment"); 108 | case kShipStorage: 109 | return QObject::tr("Ship/storage"); 110 | case kShipShop: 111 | return QObject::tr("Shop"); 112 | case kJunk: 113 | return QObject::tr("Space"); 114 | case kPlanetShop: 115 | return QObject::tr("Shop"); 116 | case kPlanetStorage: 117 | return QObject::tr("Planet/storage"); 118 | case kPlanetTreasure: 119 | return QObject::tr("treasure")+" "+QString("%1") 120 | .arg(extra("Depth").toInt(), 4, 10, QChar('0')) 121 | +'/'+extra("LandType")[0]; 122 | } 123 | return ""; 124 | } 125 | unsigned Equipment::size() const 126 | { 127 | return _size; 128 | } 129 | unsigned Equipment::cost() const 130 | { 131 | return _cost; 132 | } 133 | unsigned Equipment::techLevel() const 134 | { 135 | return _techLevel; 136 | } 137 | double Equipment::durability() const 138 | { 139 | return _durability; 140 | } 141 | QString Equipment::type() const 142 | { 143 | return _type; 144 | } 145 | QString Equipment::owner() const 146 | { 147 | return _owner; 148 | } 149 | 150 | QString Equipment::bonusNote() const 151 | { 152 | if(_type=="Nod") { 153 | return micromodulesDescriptions.value(_name.section(' ',1),"no description"); 154 | } 155 | if(_type.startsWith("Art")) { 156 | return artifactsDescriptions.value(_type,"no description"); 157 | } 158 | if(_specialName.isEmpty()) { 159 | return ""; 160 | } 161 | if(_type.at(0)=='W') {//weapon 162 | return _specialName; 163 | } 164 | 165 | int lvl=0; 166 | if(_name.contains(QRegularExpression(" I($| )"))) { 167 | lvl=1; 168 | } 169 | else if(_name.contains(QRegularExpression(" II($| )"))) { 170 | lvl=2; 171 | } 172 | else if(_name.contains(QRegularExpression(" III($| )"))) { 173 | lvl=3; 174 | } 175 | else if(_name.contains(QRegularExpression(" IV($| )"))) { 176 | lvl=4; 177 | } 178 | 179 | if (lvl==0) 180 | { 181 | return "error parsing"; 182 | } 183 | 184 | QString specialType; 185 | QString bonus; 186 | if(_type=="Hull") { 187 | specialType=_name; 188 | specialType.replace("Корпус ",""); 189 | specialType=specialType.section(' ',0,0); 190 | QString key=specialType+":"+QString::number(lvl); 191 | bonus=specialHullsDescriptions.value(key,"no description"); 192 | } 193 | else {//not Hull 194 | specialType=_name.section(' ',0,0); 195 | QString key=specialType+":"+QString::number(lvl); 196 | bonus=specialTypesDescriptions.value(key,"no description"); 197 | } 198 | 199 | return specialType+' '+QString::number(lvl)+": "+bonus; 200 | } 201 | 202 | QMap mapFromJson(const QJsonArray &array) 203 | { 204 | QMap map; 205 | for(const auto& entry:array) 206 | { 207 | auto obj=entry.toObject(); 208 | map[obj["key"].toString()]=obj["value"].toString(); 209 | } 210 | if(map.empty()) 211 | { 212 | std::cout<<"the Map is empty!"< Equipment::loadDescriptions(const QString &filename) 219 | { 220 | //createDescriptions(); 221 | //createDescriptionsHulls(); 222 | QMap descriptions; 223 | QFile file(filename); 224 | if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){ 225 | std::cerr<<"could not open "< readEqlist(QTextStream &stream, Galaxy& galaxy, Equipment::LocationType locationType, unsigned locationId) 236 | { 237 | std::unordered_set eqIdList; 238 | 239 | int nesting=0; 240 | QString line = stream.readLine().trimmed();; 241 | while (!line.isNull()) 242 | { 243 | nesting+=line.contains('{'); 244 | nesting-=line.contains('}'); 245 | if(line.startsWith("Storage ^{") || line.startsWith("Treasure ^{") || 246 | line.startsWith("EqShop ^{") || line.startsWith("EqList ^{") || 247 | line.startsWith("EqList ^{") || line.startsWith("ArtsList ^{") || line.startsWith("Junk ^{")) 248 | { 249 | nesting-=1; 250 | } 251 | if(nesting<0) 252 | { 253 | break; 254 | } 255 | if(line.startsWith("HiddenItem")) { 256 | Equipment eq(stream, galaxy, locationType, locationId); 257 | eqIdList.insert(eq.id()); 258 | } 259 | if(line.startsWith("ItemId")) 260 | { 261 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 262 | unsigned id=idRef.toInt(); 263 | Equipment eq(stream, galaxy, locationType, locationId, id); 264 | --nesting;//stream wiil be moved after '} ItemId' 265 | eqIdList.insert(eq.id()); 266 | } 267 | line = stream.readLine().trimmed(); 268 | } 269 | return eqIdList; 270 | } 271 | void createDescriptions() 272 | { 273 | QFile file("bonus_descriptions.json.en.example"); 274 | if(file.exists()){ 275 | return; 276 | } 277 | file.open(QIODevice::WriteOnly | QIODevice::Text); 278 | QStringList types={"Myoplasmic","Pygamore","Transcendental", 279 | "Upgraded","Biogenic","Nanobrolite","Ultraalloy"}; 280 | 281 | QJsonArray ar; 282 | for(auto& specialType:types) 283 | for(int lvl=1; lvl<4; lvl++) 284 | { 285 | QJsonObject obj; 286 | obj["key"]=specialType+":"+QString::number(lvl); 287 | QString bonus; 288 | if(specialType=="Myoplasmic") 289 | { 290 | static const int arr[]={2,3,5}; 291 | bonus=QString("energetic dmg +%1, splinter dmg +%2, speed -%3") 292 | .arg(arr[lvl-1]).arg(arr[lvl-1]+1).arg(lvl*10); 293 | } 294 | else if(specialType=="Pygamore") { 295 | static const int arr[]={50,100,250}; 296 | bonus=QString("rocket dmg+%1, defence -%2, radar -%3") 297 | .arg(lvl+1).arg(lvl).arg(arr[lvl-1]); 298 | } 299 | else if(specialType=="Transcendental") { 300 | bonus=QString("defence +%1, mass +%2\%") 301 | .arg(lvl+1).arg(lvl*10); 302 | } 303 | else if(specialType=="Upgraded") { 304 | bonus=QString("hook range +%1, mobility +1, charizm -2") 305 | .arg(lvl*5+5); 306 | } 307 | else if(specialType=="Biogenic") { 308 | static const int arr[]={100,200,200}; 309 | bonus=QString("scaner +%1, radar +%2, technics -2") 310 | .arg(lvl*3).arg(arr[lvl-1]); 311 | } 312 | else if(specialType=="Nanobrolite") { 313 | static const int arr[]={3,5,8}; 314 | bonus=QString("energetic dmg +%1, splinter dmg +%2, weapon range -%3, attack +1, trade -2") 315 | .arg(lvl*2).arg(arr[lvl-1]).arg(10*lvl); 316 | } 317 | else if(specialType=="Ultraalloy") { 318 | static const int drd[]={7,12,15}; 319 | static const int spd[]={10,25,55}; 320 | bonus=QString("droid +%1, engine speed -%2, attack -1, technics +1") 321 | .arg(drd[lvl-1]).arg(spd[lvl-1]); 322 | } 323 | obj["value"]=bonus; 324 | ar.append(obj); 325 | } 326 | QJsonDocument doc(ar); 327 | file.write(doc.toJson()); 328 | file.close(); 329 | } 330 | void createDescriptionsHulls() 331 | { 332 | QFile file("bonus_descriptions_hulls.json.en.example"); 333 | if(file.exists()){ 334 | return; 335 | } 336 | file.open(QIODevice::WriteOnly | QIODevice::Text); 337 | QStringList types={"Fast","Invincible","Repair","Myoplasmic", 338 | "Pygamore","Ironclad","Conscientious", 339 | "Kindhearted","Peaceful"}; 340 | 341 | QJsonArray ar; 342 | for(auto& specialType:types) 343 | for(int lvl=1; lvl<5; lvl++) 344 | { 345 | QJsonObject obj; 346 | obj["key"]=specialType+":"+QString::number(lvl); 347 | QString bonus; 348 | int effLvl=lvl<4?lvl:2; 349 | if(specialType=="Fast"){ 350 | bonus=QString("speed +%1").arg(effLvl*50+50); 351 | } 352 | else if(specialType=="Invincible") {//Неуязвимый 353 | bonus=QString("defence +%1").arg(effLvl*3); 354 | } 355 | else if(specialType=="Repair") { 356 | bonus=QString("droid +%1").arg((effLvl)*15-5); 357 | } 358 | else if(specialType=="Myoplasmic"){ 359 | bonus=QString("energetic dmg +%1, splinter dmg +%2, speed -%3") 360 | .arg(3*effLvl+1).arg( 2*(2+pow(2,effLvl)) ).arg(effLvl*20); 361 | } 362 | else if(specialType=="Pygamore") { 363 | bonus=QString("rocket dmg +%1, defence -%2, radar -%3") 364 | .arg(effLvl*5).arg(effLvl*2+1).arg(pow(2,effLvl-1)*100+100); 365 | } 366 | else if(specialType=="Dandy") {//Молния (Стиляга) 367 | static const int def[]={3,4,6}; 368 | bonus=QString("radar +%1, jump +%1, defence -%2") 369 | .arg(50+effLvl*50).arg(effLvl*5).arg(def[effLvl-1]); 370 | } 371 | else if(specialType=="Ironclad") {//Броненосец 372 | static const int def[]={3,4,6}; 373 | bonus=QString("energetic dmg +%1, splinter dmg +%2, defence +%3, speed -%4, manoeuvrability -2") 374 | .arg(effLvl*2).arg(effLvl*2-1).arg(def[effLvl-1]).arg(25+25*effLvl); 375 | } 376 | else if(specialType=="") {//Ушастик //TODO: find out 377 | bonus=QString("rocket dmg +%1, charisma +3") 378 | .arg(effLvl*2); 379 | } 380 | else if(specialType=="Conscientious") {//Честный ренегал 381 | bonus=QString("jump +%1, hook +%2, mass -%3\%, trade -3") 382 | .arg(effLvl*2+1).arg(effLvl*10).arg(effLvl*10); 383 | } 384 | else if(specialType=="Kindhearted") {//Добрый лякуша 385 | bonus=QString("energetic dmg +%1, splinter dmg +%2, rocket dmg +%3") 386 | .arg(effLvl+4).arg(effLvl+3).arg(effLvl+1); 387 | } 388 | else if(specialType=="Peaceful") {//Мирный корсар 389 | bonus=QString("armor +%1, defence +%2, atack -3, technics -3") 390 | .arg(effLvl).arg(effLvl*3); 391 | } 392 | obj["value"]=bonus; 393 | ar.append(obj); 394 | } 395 | QJsonDocument doc(ar); 396 | file.write(doc.toJson()); 397 | file.close(); 398 | } 399 | -------------------------------------------------------------------------------- /Equipment.h: -------------------------------------------------------------------------------- 1 | #ifndef EQUIPMENT_H 2 | #define EQUIPMENT_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | //#include 10 | 11 | class Galaxy; 12 | class Equipment 13 | { 14 | public: 15 | enum LocationType {kShipEq, kShipStorage, kShipShop, kJunk, kPlanetShop, kPlanetStorage, kPlanetTreasure}; 16 | Equipment(QTextStream &stream, Galaxy &galaxy, LocationType locationType, unsigned locationId, unsigned id=0); 17 | unsigned id() const 18 | { 19 | return _id; 20 | } 21 | QString locationTypeString() const; 22 | LocationType locationType() const 23 | { 24 | return _locationType; 25 | } 26 | unsigned locationId() const 27 | { 28 | return _locationId; 29 | } 30 | QString name() const 31 | { 32 | return _name; 33 | } 34 | QString extra(const QString& key) const 35 | { 36 | return extraFields.value(key,"none"); 37 | } 38 | 39 | unsigned size() const; 40 | unsigned cost() const; 41 | unsigned techLevel() const; 42 | double durability() const; 43 | 44 | QString type() const; 45 | 46 | QString owner() const; 47 | 48 | QString bonusNote() const; 49 | private: 50 | QString _name; 51 | QString _type; 52 | QString _owner; 53 | unsigned _id; 54 | unsigned _size; 55 | unsigned _cost; 56 | double _durability; 57 | unsigned _techLevel; 58 | LocationType _locationType; 59 | unsigned _locationId; 60 | QMap extraFields; 61 | QString _specialName; 62 | 63 | //static const QMap specialCodes; 64 | static QMap loadDescriptions(const QString& filename); 65 | static const QMap specialTypesDescriptions;//type_name:lvl, description 66 | static const QMap specialHullsDescriptions;//type_name:lvl, description 67 | static const QMap artifactsDescriptions;//type,description 68 | static const QMap micromodulesDescriptions;//name,description 69 | }; 70 | 71 | std::unordered_set readEqlist(QTextStream &stream, Galaxy &galaxy, Equipment::LocationType locationType, unsigned locationId); 72 | 73 | #endif // EQUIPMENT_H 74 | -------------------------------------------------------------------------------- /EquipmentTableModel.cpp: -------------------------------------------------------------------------------- 1 | #include "EquipmentTableModel.h" 2 | #include "Galaxy.h" 3 | #include "FilterHorizontalHeaderView.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | EquipmentTableModel::EquipmentTableModel(const Galaxy *galaxy, QObject *parent) : 10 | QAbstractTableModel(parent),_galaxy(galaxy) 11 | { 12 | for(const QString& name:QColor::colorNames()) { 13 | QColor c(name); 14 | colorNames[c.rgb()]=name; 15 | } 16 | } 17 | 18 | int EquipmentTableModel::rowCount(const QModelIndex &parent) const 19 | { 20 | return _galaxy->equipmentCount(); 21 | } 22 | 23 | int EquipmentTableModel::columnCount(const QModelIndex &parent) const 24 | { 25 | return 14; 26 | } 27 | 28 | QVariant EquipmentTableModel::data(const QModelIndex &index, int role) const 29 | { 30 | if (role == Qt::BackgroundRole) { 31 | return QBrush(colors.value(index.row(),QColor("white"))); 32 | } 33 | int col=index.column(); 34 | if (role == Qt::EditRole) { 35 | if (col==0) { 36 | return colors.value(index.row(),QColor("white")); 37 | } 38 | } 39 | if (role == Qt::ForegroundRole) { 40 | QColor bg=colors.value(index.row(),QColor("white")); 41 | int lightness;//=bg.lightness(); 42 | lightness=bg.red()*0.299 + bg.green()*0.587 + bg.blue()*0.114; 43 | if(lightness<128) { 44 | return QBrush(QColor("white")); 45 | } 46 | return QBrush(QColor("black")); 47 | } 48 | if (role == Qt::DisplayRole) 49 | { 50 | switch (col) 51 | { 52 | case 0: 53 | return colorName(colors.value(index.row(),QColor("white"))); 54 | break; 55 | case 1: 56 | return _galaxy->equipmentName(index.row()); 57 | break; 58 | 59 | case 2: 60 | return _galaxy->equipmentType(index.row()); 61 | break; 62 | 63 | case 3: 64 | return _galaxy->equipmentSize(index.row()); 65 | break; 66 | 67 | case 4: 68 | return _galaxy->equipmentOwner(index.row()); 69 | break; 70 | 71 | case 5: 72 | return _galaxy->equipmentCost(index.row()); 73 | break; 74 | 75 | case 6: 76 | return _galaxy->equipmentTechLevel(index.row()); 77 | break; 78 | 79 | case 7: 80 | return _galaxy->equipmentLocationType(index.row()); 81 | break; 82 | 83 | case 8: 84 | return _galaxy->equipmentLocationName(index.row()); 85 | break; 86 | 87 | case 9: 88 | return _galaxy->equipmentStarName(index.row()); 89 | break; 90 | 91 | case 10://Distance to star from Player 92 | return std::round(_galaxy->equipmentDistFromPlayer(index.row())); 93 | break; 94 | 95 | case 11://Star Owner 96 | return _galaxy->equipmentStarOwner(index.row()); 97 | break; 98 | 99 | case 12: 100 | return std::round(_galaxy->equipmentDurability(index.row())*10.0)/10.0; 101 | break; 102 | 103 | case 13: 104 | return _galaxy->equipmentBonus(index.row()); 105 | break; 106 | 107 | } 108 | 109 | return "asd"; 110 | } 111 | if (role==Qt::ToolTipRole) { 112 | QString str=data(index,Qt::DisplayRole).toString(); 113 | if(! str.isEmpty()) { 114 | return QStringLiteral("

")+str+"

"; 115 | } 116 | } 117 | return QVariant(); 118 | } 119 | 120 | QVariant EquipmentTableModel::headerData(int section, Qt::Orientation orientation, int role) const 121 | { 122 | static const QVector header={tr("Color"),tr("Name"),tr("Type"),tr("Size"),tr("Made"), 123 | tr("Cost"),tr("TL"), tr("Location type"), 124 | tr("Location"),tr("Star"),tr("Dist."), tr("Owner"), tr("Durab."),tr("Bonus")}; 125 | if (role == Qt::DisplayRole) 126 | { 127 | if (orientation == Qt::Vertical) 128 | { 129 | return _galaxy->equipmentId(section); 130 | } 131 | else if (orientation == Qt::Horizontal) { 132 | return header.at(section); 133 | } 134 | } 135 | else if(role==Qt::UserRole) 136 | { 137 | if(orientation == Qt::Horizontal) { 138 | switch (section) 139 | { 140 | case 0: 141 | return FilterHorizontalHeaderView::wtNone; 142 | case 3: 143 | case 5: 144 | case 6: 145 | case 10: 146 | return FilterHorizontalHeaderView::wtInt; 147 | case 12: 148 | return FilterHorizontalHeaderView::wtDouble; 149 | default: 150 | return FilterHorizontalHeaderView::wtString; 151 | } 152 | } 153 | } 154 | return QVariant(); 155 | } 156 | 157 | Qt::ItemFlags EquipmentTableModel::flags(const QModelIndex &index) const 158 | { 159 | if (!index.isValid()) 160 | return Qt::ItemIsEnabled; 161 | 162 | if (index.column()==0) { 163 | return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; 164 | } 165 | return QAbstractItemModel::flags(index); 166 | } 167 | 168 | bool EquipmentTableModel::setData(const QModelIndex &index, const QVariant &value, int role) 169 | { 170 | if (index.isValid() && role == Qt::EditRole && index.column()==0) { 171 | colors[index.row()]=value.value(); 172 | emit dataChanged(index, index); 173 | return true; 174 | } 175 | return false; 176 | } 177 | 178 | 179 | 180 | bool operator<(const QColor &a, const QColor &b) { 181 | return a.redF() < b.redF() 182 | || a.greenF() < b.greenF() 183 | || a.blueF() < b.blueF() 184 | || a.alphaF() < b.alphaF(); 185 | } 186 | -------------------------------------------------------------------------------- /EquipmentTableModel.h: -------------------------------------------------------------------------------- 1 | #ifndef EQUIPMENTTABLEMODEL_H 2 | #define EQUIPMENTTABLEMODEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class Galaxy; 10 | 11 | bool operator<(const QColor & a, const QColor & b); 12 | 13 | class EquipmentTableModel : public QAbstractTableModel 14 | { 15 | Q_OBJECT 16 | public: 17 | explicit EquipmentTableModel(const Galaxy* galaxy, QObject *parent = 0); 18 | int rowCount(const QModelIndex &parent = QModelIndex()) const ; 19 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 20 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 21 | QVariant headerData(int section, Qt::Orientation orientation, int role) const; 22 | Qt::ItemFlags flags(const QModelIndex &index) const; 23 | bool setData(const QModelIndex &index, const QVariant &value, 24 | int role = Qt::EditRole); 25 | void reload() 26 | { 27 | beginResetModel(); 28 | endResetModel(); 29 | colors.clear(); 30 | } 31 | void initialiseFilterWidgets(); 32 | QString colorName(const QColor& c) const { 33 | return colorNames.value(c.rgb(),c.name()); 34 | } 35 | 36 | signals: 37 | 38 | public slots: 39 | 40 | private: 41 | const Galaxy *_galaxy; 42 | QMap colors; 43 | QMap colorNames; 44 | }; 45 | 46 | #endif // EQUIPMENTTABLEMODEL_H 47 | -------------------------------------------------------------------------------- /FilterHorizontalHeaderView.cpp: -------------------------------------------------------------------------------- 1 | #include "FilterHorizontalHeaderView.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | FilterHorizontalHeaderView::FilterHorizontalHeaderView(SortMultiFilterProxyModel *model, QTableView *parent): 10 | QHeaderView(Qt::Horizontal,parent) 11 | { 12 | //setModel(parent->model()); 13 | _model=model; 14 | 15 | setSectionsMovable(parent->horizontalHeader()->sectionsMovable()); 16 | setSectionsClickable(parent->horizontalHeader()->sectionsClickable()); 17 | 18 | insertColumns(0,model->columnCount()-1); 19 | 20 | updateWidgetPositions(); 21 | 22 | contextMenu.addAction(&saveAct); 23 | contextMenu.addAction(&clearAct); 24 | contextMenu.addSeparator(); 25 | connect(&saveAct,&QAction::triggered,this,&FilterHorizontalHeaderView::savePreset); 26 | connect(&clearAct,&QAction::triggered,this,&FilterHorizontalHeaderView::clearAllFilters); 27 | 28 | connect(parent->horizontalScrollBar(),SIGNAL(valueChanged(int)), 29 | this,SLOT(updateWidgetPositions()) ); 30 | connect(this,SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), 31 | this,SLOT(setSortIndicator(int,Qt::SortOrder))); 32 | connect(this,SIGNAL(sectionResized(int,int,int)), 33 | this,SLOT(updateWidgetPositions())); 34 | 35 | connect(model,&QAbstractItemModel::columnsInserted, 36 | [=](const QModelIndex&, 37 | int logicalFirst, int logicalLast) { 38 | insertColumns(logicalFirst,logicalLast); 39 | }); 40 | 41 | timer.setInterval(300); 42 | timer.setSingleShot(true); 43 | connect(&timer,SIGNAL(timeout()),this,SLOT(applyFilters())); 44 | 45 | //TODO: add header data update 46 | //TODO: add sections removal 47 | } 48 | 49 | QSize FilterHorizontalHeaderView::sizeHint() const 50 | { 51 | QSize size=QHeaderView::sizeHint(); 52 | size.setHeight(_height); 53 | return size; 54 | } 55 | 56 | void FilterHorizontalHeaderView::setPreset(const QVariantMap &p) 57 | { 58 | QVariantMap matchFilters=p["match"].toMap(); 59 | QVariantMap notMatchFilters=p["notMatch"].toMap(); 60 | QVariantMap minInts=p["minInt"].toMap(); 61 | QVariantMap maxInts=p["maxInt"].toMap(); 62 | QVariantMap minDoubles=p["minDouble"].toMap(); 63 | QVariantMap maxDoubles=p["maxDouble"].toMap(); 64 | 65 | using MapIntLineEditI=QMap::iterator; 66 | for (MapIntLineEditI i = matchEdits.begin(); i != matchEdits.end(); ++i) 67 | { 68 | const QVariant& var=matchFilters.value(QString::number(i.key()),""); 69 | i.value()->setText(var.toString()); 70 | } 71 | for (MapIntLineEditI i = notMatchEdits.begin(); i != notMatchEdits.end(); ++i) 72 | { 73 | const QVariant& var=notMatchFilters.value(QString::number(i.key()),""); 74 | i.value()->setText(var.toString()); 75 | } 76 | 77 | using MapIntSpinBoxI=QMap::iterator; 78 | for (MapIntSpinBoxI i = minIntEdits.begin(); i != minIntEdits.end(); ++i) 79 | { 80 | const QVariant& var=minInts.value(QString::number(i.key()),0); 81 | i.value()->setValue(var.toInt()); 82 | } 83 | for (MapIntSpinBoxI i = maxIntEdits.begin(); i != maxIntEdits.end(); ++i) 84 | { 85 | const QVariant& var=maxInts.value(QString::number(i.key()),0); 86 | i.value()->setValue(var.toInt()); 87 | } 88 | 89 | using MapIntDoubleSpinBoxI=QMap::iterator; 90 | for (MapIntDoubleSpinBoxI i = minDoubleEdits.begin(); i != minDoubleEdits.end(); ++i) 91 | { 92 | const QVariant& var=minDoubles.value(QString::number(i.key()),0.0); 93 | i.value()->setValue(var.toDouble()); 94 | } 95 | for (MapIntDoubleSpinBoxI i = maxDoubleEdits.begin(); i != maxDoubleEdits.end(); ++i) 96 | { 97 | const QVariant& var=maxDoubles.value(QString::number(i.key()),0.0); 98 | i.value()->setValue(var.toDouble()); 99 | } 100 | 101 | setSortIndicator(p["sortColumn"].toInt(),(Qt::SortOrder)p["sortOrder"].toInt()); 102 | applyFilters(); 103 | _model->sort(p["sortColumn"].toInt(),(Qt::SortOrder)p["sortOrder"].toInt()); 104 | } 105 | 106 | bool FilterHorizontalHeaderView::event(QEvent *event) 107 | { 108 | if(event->type() == QEvent::MouseButtonPress ) 109 | { 110 | mousePressEvent(static_cast(event)); 111 | return false; 112 | } 113 | if(event->type() == QEvent::MouseButtonRelease ) 114 | { 115 | mouseReleaseEvent(static_cast(event)); 116 | return false; 117 | } 118 | return QHeaderView::event(event); 119 | } 120 | 121 | QSize FilterHorizontalHeaderView::sectionSizeFromContents(int logicalIndex) const 122 | { 123 | QVariant variant = model()->headerData(logicalIndex, Qt::Horizontal, Qt::SizeHintRole); 124 | if (variant.isValid()) 125 | return qvariant_cast(variant); 126 | // otherwise use the contents 127 | QStyleOptionHeader opt; 128 | initStyleOption(&opt); 129 | opt.section = logicalIndex; 130 | QVariant var = model()->headerData(logicalIndex, Qt::Horizontal, 131 | Qt::FontRole); 132 | QFont fnt; 133 | if (var.isValid() && var.canConvert()) 134 | fnt = qvariant_cast(var); 135 | else 136 | fnt = font(); 137 | fnt.setBold(true); 138 | opt.fontMetrics = QFontMetrics(fnt); 139 | opt.text = model()->headerData(logicalIndex, Qt::Horizontal, 140 | Qt::DisplayRole).toString(); 141 | variant = model()->headerData(logicalIndex, Qt::Horizontal, Qt::DecorationRole); 142 | opt.icon = qvariant_cast(variant); 143 | if (opt.icon.isNull()) 144 | opt.icon = qvariant_cast(variant); 145 | QSize size = style()->sizeFromContents(QStyle::CT_HeaderSection, &opt, QSize(), this); 146 | /*if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex) { 147 | int margin = style()->pixelMetric(QStyle::PM_HeaderMargin, &opt, this); 148 | if (Qt::Horizontal == Qt::Horizontal) 149 | size.rwidth() += size.height() + margin; 150 | else 151 | size.rheight() += size.width() + margin; 152 | }*/ 153 | size.rwidth()=std::max(size.rwidth(),40); 154 | return size; 155 | } 156 | 157 | void FilterHorizontalHeaderView::setSortIndicator(int col, const Qt::SortOrder &order) 158 | { 159 | headerSortIndicators.value(lastSortSection)->setText(" "); 160 | QString c; 161 | switch (order) 162 | { 163 | case Qt::AscendingOrder: 164 | c="▲"; 165 | break; 166 | case Qt::DescendingOrder: 167 | c="▼"; 168 | break; 169 | default: 170 | c=" "; 171 | break; 172 | } 173 | headerSortIndicators.value(col)->setText(c); 174 | lastSortSection=col; 175 | } 176 | 177 | void FilterHorizontalHeaderView::updateWidgetPositions() const 178 | { 179 | for (int i: headerWidgets.keys()) 180 | { 181 | updateGeometry(i); 182 | } 183 | } 184 | 185 | void FilterHorizontalHeaderView::updateHeaderData(int first, int last) 186 | { 187 | for(int i=first; i<=last; i++) 188 | { 189 | updateHeaderData(i); 190 | } 191 | } 192 | 193 | void FilterHorizontalHeaderView::savePreset() 194 | { 195 | QVariantMap p=preset(); 196 | bool ok; 197 | QString presetName = QInputDialog::getText(this, tr("QInputDialog::getText()"), 198 | tr("Preset name:"), QLineEdit::Normal, 199 | QString(), &ok); 200 | if (ok) { 201 | addPreset(p,presetName); 202 | } 203 | emit presetSaved(p,presetName); 204 | } 205 | 206 | void FilterHorizontalHeaderView::activatePreset(int i) 207 | { 208 | if(i>=_presets.size()) { 209 | return; 210 | } 211 | setPreset(_presets[i]); 212 | } 213 | 214 | void FilterHorizontalHeaderView::clearAllFilters() 215 | { 216 | for(auto& w:matchEdits) 217 | { 218 | w->clear(); 219 | } 220 | for(auto& w:notMatchEdits) 221 | { 222 | w->clear(); 223 | } 224 | for(auto& w:maxIntEdits) 225 | { 226 | w->setValue(w->minimum()); 227 | } 228 | for(auto& w:minIntEdits) 229 | { 230 | w->setValue(w->minimum()); 231 | } 232 | for(auto& w:maxDoubleEdits) 233 | { 234 | w->setValue(w->minimum()); 235 | } 236 | for(auto& w:minDoubleEdits) 237 | { 238 | w->setValue(w->minimum()); 239 | } 240 | applyFilters(); 241 | } 242 | 243 | void FilterHorizontalHeaderView::applyFilters() 244 | { 245 | timer.stop(); 246 | QMap match, notMatch; 247 | QMap min, max; 248 | 249 | using MapIntLineEditCI=QMap::const_iterator; 250 | for (MapIntLineEditCI i = matchEdits.begin(); i != matchEdits.end(); ++i) 251 | { 252 | const QString& value=i.value()->text(); 253 | if(!value.isEmpty()) { 254 | match[i.key()]=value; 255 | } 256 | } 257 | for (MapIntLineEditCI i = notMatchEdits.begin(); i != notMatchEdits.end(); ++i) 258 | { 259 | const QString& value=i.value()->text(); 260 | if(!value.isEmpty()) { 261 | notMatch[i.key()]=i.value()->text(); 262 | } 263 | } 264 | 265 | using MapIntSpinBoxCI=QMap::const_iterator; 266 | for (MapIntSpinBoxCI i = minIntEdits.begin(); i != minIntEdits.end(); ++i) 267 | { 268 | double value=i.value()->value(); 269 | if(value>0.0) { 270 | min[i.key()]=value; 271 | } 272 | } 273 | for (MapIntSpinBoxCI i = maxIntEdits.begin(); i != maxIntEdits.end(); ++i) 274 | { 275 | double value=i.value()->value(); 276 | if(value>0.0) { 277 | max[i.key()]=value; 278 | } 279 | } 280 | 281 | using MapIntDoubleSpinBoxCI=QMap::const_iterator; 282 | for (MapIntDoubleSpinBoxCI i = minDoubleEdits.begin(); i != minDoubleEdits.end(); ++i) 283 | { 284 | double value=i.value()->value(); 285 | if(value>0.0) { 286 | min[i.key()]=value; 287 | } 288 | } 289 | for (MapIntDoubleSpinBoxCI i = maxDoubleEdits.begin(); i != maxDoubleEdits.end(); ++i) 290 | { 291 | double value=i.value()->value(); 292 | if(value>0.0) { 293 | max[i.key()]=value; 294 | } 295 | } 296 | _model->setFilters(match,notMatch,min,max); 297 | } 298 | 299 | QVariantMap FilterHorizontalHeaderView::preset() const 300 | { 301 | QVariantMap allFilters; 302 | 303 | using MapIntLineEditCI=QMap::const_iterator; 304 | QVariantMap matchFilters; 305 | for (MapIntLineEditCI i = matchEdits.begin(); i != matchEdits.end(); ++i) 306 | { 307 | matchFilters.insert(QString::number(i.key()),i.value()->text()); 308 | } 309 | allFilters.insert("match",std::move(matchFilters)); 310 | 311 | QVariantMap notMatchFilters; 312 | for (MapIntLineEditCI i = notMatchEdits.begin(); i != notMatchEdits.end(); ++i) 313 | { 314 | notMatchFilters.insert(QString::number(i.key()),i.value()->text()); 315 | } 316 | allFilters.insert("notMatch",std::move(notMatchFilters)); 317 | 318 | using MapIntSpinBoxCI=QMap::const_iterator; 319 | QVariantMap minInts; 320 | for (MapIntSpinBoxCI i = minIntEdits.begin(); i != minIntEdits.end(); ++i) 321 | { 322 | minInts.insert(QString::number(i.key()),i.value()->text()); 323 | } 324 | allFilters.insert("minInt",std::move(minInts)); 325 | 326 | QVariantMap maxInts; 327 | for (MapIntSpinBoxCI i = maxIntEdits.begin(); i != maxIntEdits.end(); ++i) 328 | { 329 | maxInts.insert(QString::number(i.key()),i.value()->text()); 330 | } 331 | allFilters.insert("maxInt",std::move(maxInts)); 332 | 333 | using MapIntDoubleSpinBoxCI=QMap::const_iterator; 334 | QVariantMap minDoubles; 335 | for (MapIntDoubleSpinBoxCI i = minDoubleEdits.begin(); i != minDoubleEdits.end(); ++i) 336 | { 337 | minDoubles.insert(QString::number(i.key()),i.value()->text()); 338 | } 339 | allFilters.insert("minDouble",std::move(minDoubles)); 340 | 341 | QVariantMap maxDoubles; 342 | for (MapIntDoubleSpinBoxCI i = maxDoubleEdits.begin(); i != maxDoubleEdits.end(); ++i) 343 | { 344 | maxDoubles.insert(QString::number(i.key()),i.value()->text()); 345 | } 346 | allFilters.insert("maxDouble",std::move(maxDoubles)); 347 | 348 | allFilters.insert("sortColumn",_model->sortColumn()); 349 | allFilters.insert("sortOrder",_model->sortOrder()); 350 | 351 | return allFilters; 352 | } 353 | 354 | void FilterHorizontalHeaderView::updateGeometry(int logical) const 355 | { 356 | assert(headerWidgets.contains(logical)); 357 | headerWidgets[logical]->setGeometry(sectionViewportPosition(logical)+2, 0, 358 | sectionSize(logical)-5, height()); 359 | } 360 | 361 | void FilterHorizontalHeaderView::updateHeaderData(int col) 362 | { 363 | headerNames[col]->setText(_model->headerData(col,Qt::Horizontal).toString()); 364 | } 365 | 366 | void FilterHorizontalHeaderView::insertColumns(int first, int last) 367 | { 368 | for(int i=first; i<=last; i++) 369 | { 370 | assert(!headerWidgets.contains(i)); 371 | makeWidget(i); 372 | } 373 | } 374 | 375 | void FilterHorizontalHeaderView::makeWidget(int col) 376 | { 377 | WidgetType wt; 378 | wt=(WidgetType)_model->headerData(col,Qt::Horizontal,Qt::UserRole).toInt(); 379 | QWidget* widget=new QWidget(this); 380 | widget->setContextMenuPolicy(Qt::CustomContextMenu); 381 | connect(widget, &QWidget::customContextMenuRequested,[=](const QPoint& point){ 382 | contextMenu.exec(widget->mapToGlobal(point)); 383 | }); 384 | headerWidgets[col]=widget; 385 | QVBoxLayout *vl=new QVBoxLayout(widget); 386 | QHBoxLayout *hl=new QHBoxLayout(); 387 | 388 | widget->setCursor(Qt::ArrowCursor); 389 | QLabel *nameLbl=headerNames[col]=new QLabel(widget); 390 | QLabel *sortLbl=headerSortIndicators[col]=new QLabel(widget); 391 | sortLbl->setText(" "); 392 | 393 | nameLbl->setWordWrap(true); 394 | nameLbl->setAlignment(Qt::AlignCenter); 395 | sortLbl->setStyleSheet("font: small Courier"); 396 | hl->setContentsMargins(0,0,0,0); 397 | vl->setContentsMargins(0,0,0,1); 398 | vl->setSpacing(1); 399 | hl->setSpacing(0); 400 | 401 | hl->addWidget(nameLbl,1,Qt::AlignHCenter); 402 | hl->addWidget(sortLbl,0,Qt::AlignRight); 403 | vl->addLayout(hl,0); 404 | QWidget *inputTop=nullptr, *inputBottom=nullptr; 405 | switch(wt) 406 | { 407 | case wtString: 408 | { 409 | auto editTop=new QLineEdit(widget); 410 | auto editBottom=new QLineEdit(widget); 411 | matchEdits[col]=editTop; 412 | notMatchEdits[col]=editBottom; 413 | editTop->setFrame(frame); 414 | editBottom->setFrame(frame); 415 | editTop->setToolTip("contains"); 416 | editBottom->setToolTip("not contains"); 417 | inputTop=editTop; 418 | inputBottom=editBottom; 419 | connect(editTop,&QLineEdit::editingFinished, 420 | this, &FilterHorizontalHeaderView::applyFilters); 421 | connect(editTop,&QLineEdit::textChanged,[&](){ 422 | timer.start(); 423 | }); 424 | connect(editBottom,&QLineEdit::editingFinished, 425 | this, &FilterHorizontalHeaderView::applyFilters); 426 | connect(editBottom,&QLineEdit::textChanged,[&](){ 427 | timer.start(); 428 | }); 429 | break; 430 | } 431 | case wtInt: 432 | { 433 | auto editTop=new QSpinBox(widget); 434 | auto editBottom=new QSpinBox(widget); 435 | minIntEdits[col]=editTop; 436 | maxIntEdits[col]=editBottom; 437 | editTop->setToolTip("minimum value"); 438 | editBottom->setToolTip("maximum value"); 439 | editTop->setMaximum(std::numeric_limits::max()); 440 | editBottom->setMaximum(std::numeric_limits::max()); 441 | editTop->setFrame(frame); 442 | editBottom->setFrame(frame); 443 | inputTop=editTop; 444 | inputBottom=editBottom; 445 | connect(editTop,&QSpinBox::editingFinished, 446 | this, &FilterHorizontalHeaderView::applyFilters); 447 | connect(editTop,static_cast(&QSpinBox::valueChanged),[&](){ 448 | timer.start(); 449 | }); 450 | connect(editBottom,&QSpinBox::editingFinished, 451 | this, &FilterHorizontalHeaderView::applyFilters); 452 | connect(editBottom,static_cast(&QSpinBox::valueChanged),[&](){ 453 | timer.start(); 454 | }); 455 | break; 456 | } 457 | case wtDouble: 458 | { 459 | auto editTop=new QDoubleSpinBox(widget); 460 | auto editBottom=new QDoubleSpinBox(widget); 461 | minDoubleEdits[col]=editTop; 462 | maxDoubleEdits[col]=editBottom; 463 | editTop->setToolTip("minimum value"); 464 | editBottom->setToolTip("maximum value"); 465 | editTop->setMaximum(std::numeric_limits::infinity()); 466 | editBottom->setMaximum(std::numeric_limits::infinity()); 467 | editTop->setFrame(frame); 468 | editBottom->setFrame(frame); 469 | inputTop=editTop; 470 | inputBottom=editBottom; 471 | connect(editTop,&QDoubleSpinBox::editingFinished, 472 | this, &FilterHorizontalHeaderView::applyFilters); 473 | connect(editTop,static_cast(&QDoubleSpinBox::valueChanged),[&](){ 474 | timer.start(); 475 | }); 476 | connect(editBottom,&QDoubleSpinBox::editingFinished, 477 | this, &FilterHorizontalHeaderView::applyFilters); 478 | connect(editBottom,static_cast(&QDoubleSpinBox::valueChanged),[&](){ 479 | timer.start(); 480 | }); 481 | break; 482 | } 483 | case wtNone: 484 | inputTop=inputBottom=nullptr; 485 | break; 486 | } 487 | if(inputTop!=nullptr) { 488 | inputTop->setFixedHeight(inputHeight); 489 | inputBottom->setFixedHeight(inputHeight); 490 | vl->addWidget(inputTop,0); 491 | vl->addWidget(inputBottom,0); 492 | } 493 | widget->setLayout(vl); 494 | 495 | updateHeaderData(col); 496 | _height=std::max(_height,headerWidgets[col]->minimumSizeHint().height()); 497 | //setMinimumSectionSize(headerWidgets[col]->minimumSizeHint().width()); 498 | //setDefaultSectionSize(headerWidgets[col]->minimumSizeHint().width()); 499 | 500 | //std::cout<<"col:"<minimumSizeHint().width()<drawControl(QStyle::CE_HeaderSection, &opt, painter, this); 511 | updateGeometry(logicalIndex); 512 | //widgets[logicalIndex]->show(); 513 | } 514 | -------------------------------------------------------------------------------- /FilterHorizontalHeaderView.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTERHORIZONTALHEADERVIEW_H 2 | #define FILTERHORIZONTALHEADERVIEW_H 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include "SortMultiFilterProxyModel.h" 24 | 25 | class FilterHorizontalHeaderView : public QHeaderView 26 | { 27 | Q_OBJECT 28 | public: 29 | enum WidgetType {wtString, wtInt, wtDouble, wtNone}; 30 | explicit FilterHorizontalHeaderView(SortMultiFilterProxyModel* model, QTableView *parent = 0); 31 | QSize sizeHint() const; 32 | void addPreset(const QVariantMap& p, const QString& name) 33 | { 34 | _presets.push_back(p); 35 | QAction *act=new QAction(name,this); 36 | int i=_presets.count()-1; 37 | connect(act,&QAction::triggered,[=](){ 38 | activatePreset(i); 39 | }); 40 | contextMenu.addAction(act); 41 | } 42 | void setPreset(const QVariantMap& p); 43 | QVariantMap preset() const; 44 | signals: 45 | void presetSaved(QVariantMap, QString); 46 | protected: 47 | virtual bool event( QEvent *event ); 48 | virtual QSize sectionSizeFromContents(int logicalIndex) const; 49 | virtual void contextMenuEvent(QContextMenuEvent *event) 50 | { 51 | contextMenu.exec(event->globalPos()); 52 | } 53 | private slots: 54 | void setSortIndicator(int col, const Qt::SortOrder &order); 55 | void updateWidgetPositions() const; 56 | void updateHeaderData(int first, int last); 57 | void savePreset(); 58 | void activatePreset(int i); 59 | void clearAllFilters(); 60 | void applyFilters(); 61 | 62 | private: 63 | void updateGeometry(int logical) const; 64 | void updateHeaderData(int col); 65 | void makeWidget(int col); 66 | void insertColumns(int first, int last); 67 | 68 | protected: 69 | void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const; 70 | 71 | private: 72 | QTimer timer; 73 | 74 | int lastSortSection=0; 75 | int _height=10; 76 | QAction saveAct{tr("save preset"),this}; 77 | QAction clearAct{tr("clear filters"),this}; 78 | QMenu contextMenu{this}; 79 | QVector _presets; 80 | SortMultiFilterProxyModel* _model=nullptr; 81 | 82 | QMap headerWidgets; 83 | QMap headerNames; 84 | QMap headerSortIndicators; 85 | 86 | QMap matchEdits; 87 | QMap notMatchEdits; 88 | QMap minIntEdits; 89 | QMap maxIntEdits; 90 | QMap minDoubleEdits; 91 | QMap maxDoubleEdits; 92 | 93 | bool frame=true; 94 | int inputHeight=QFontMetrics(QFont("sans",11)).height(); 95 | }; 96 | 97 | #endif // FILTERHORIZONTALHEADERVIEW_H 98 | -------------------------------------------------------------------------------- /Galaxy.h: -------------------------------------------------------------------------------- 1 | #ifndef GALAXY_H 2 | #define GALAXY_H 3 | #include "Equipment.h" 4 | #include "Ship.h" 5 | #include "Star.h" 6 | #include "Planet.h" 7 | #include "BlackHole.h" 8 | #include "Galaxy.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | class Galaxy 17 | { 18 | public: 19 | explicit Galaxy(); 20 | void parseDump(QTextStream& stream); 21 | void clear(); 22 | 23 | unsigned shipCount() const; 24 | unsigned equipmentCount() const; 25 | unsigned starCount() const; 26 | unsigned blackHoleCount() const; 27 | unsigned planetCount() const; 28 | 29 | unsigned galaxyTechLevel() const; 30 | 31 | void addEquipment(Equipment&& eq); 32 | void addShip(const Ship&& ship); 33 | void addStar(const Star&& star); 34 | void addBlackHole(const BlackHole&& bh); 35 | void addPlanet(const Planet&& planet); 36 | 37 | QString starOwner(unsigned starId) const; 38 | 39 | unsigned marketsCount() const; 40 | QString marketName(unsigned row) const; 41 | QString marketPlanetEconomy(unsigned row) const; 42 | QString marketPlanetOwner(unsigned row) const; 43 | unsigned marketPlanetSize(unsigned row) const; 44 | unsigned marketPlanetTechLevel(unsigned row) const; 45 | const GoodsArr& marketQuantity(unsigned row) const; 46 | const GoodsArr& marketSale(unsigned row) const; 47 | const GoodsArr& marketBuy(unsigned row) const; 48 | unsigned marketId(unsigned row) const; 49 | double marketDistFromPlayer(unsigned row) const; 50 | QString marketStarName(unsigned row) const; 51 | 52 | unsigned equipmentId(unsigned row) const; 53 | QString equipmentName(unsigned row) const; 54 | QString equipmentType(unsigned row) const; 55 | unsigned equipmentSize(unsigned row) const; 56 | QString equipmentOwner(unsigned row) const; 57 | unsigned equipmentCost(unsigned row) const; 58 | unsigned equipmentTechLevel(unsigned row) const; 59 | QString equipmentLocationType(unsigned row) const; 60 | QString equipmentLocationName(unsigned row) const; 61 | int equipmentDepth(unsigned row) const; 62 | QString equipmentStarName(unsigned row) const; 63 | double equipmentDistFromPlayer(unsigned row) const; 64 | QString equipmentStarOwner(unsigned row) const; 65 | double equipmentDurability(unsigned row) const; 66 | QString equipmentBonus(unsigned row) const; 67 | 68 | unsigned blackHoleId(unsigned row) const; 69 | QString blackHoleStar1(unsigned row) const; 70 | float blackHoleStar1Distance(unsigned row) const; 71 | QString blackHoleStar2(unsigned row) const; 72 | float blackHoleStar2Distance(unsigned row) const; 73 | int blackHoleTurnsToClose(unsigned row) const; 74 | QString blackHoleNextLootChange(unsigned row) const; 75 | 76 | const Planet& planet(unsigned row) const 77 | { 78 | return planetMap.at(planetVec[row]); 79 | } 80 | float planetDistance(unsigned row) const 81 | { 82 | unsigned planetStarId=planet(row).starId(); 83 | unsigned playerStarId=shipMap.at(0).starId(); 84 | QPointF playerPos=starMap.at(playerStarId).position(); 85 | QPointF planetPos=starMap.at(planetStarId).position(); 86 | QPointF delta=playerPos-planetPos; 87 | return std::sqrt(std::pow(delta.x(), 2) + std::pow(delta.y(), 2)); 88 | } 89 | QString planetStarName(unsigned row) const 90 | { 91 | unsigned planetStarId=planet(row).starId(); 92 | return starMap.at(planetStarId).name(); 93 | } 94 | QString planetOwner(unsigned row) const 95 | { 96 | const auto& pl=planet(row); 97 | if (pl.owner()=="Kling") { 98 | unsigned planetStarId=pl.starId(); 99 | return starOwner(planetStarId); 100 | } 101 | return pl.owner(); 102 | } 103 | 104 | const GoodsArr& maxBuyPrice() const 105 | { 106 | return _maxBuyPrice; 107 | } 108 | const GoodsArr& minSellPrice() const 109 | { 110 | return _minSellPrice; 111 | } 112 | QImage map(const unsigned width=700, const int fontSize=8) const; 113 | private: 114 | unsigned marketStarId(unsigned row) const; 115 | unsigned equipmentStarId(unsigned row) const; 116 | private: 117 | std::unordered_map eqMap; 118 | std::unordered_map shipMap; 119 | std::unordered_map starMap; 120 | std::unordered_map planetMap; 121 | std::vector blackHoles; 122 | std::vector planetMarkets; 123 | std::vector shipMarkets; 124 | std::vector eqVec; 125 | std::vector planetVec; 126 | unsigned currentDay=0; 127 | 128 | mutable GoodsArr _maxBuyPrice; 129 | mutable GoodsArr _minSellPrice; 130 | QRectF galaxyMapRect; 131 | static const QMap _ownerToColor;//name,description 132 | }; 133 | 134 | #endif // GALAXY_H 135 | -------------------------------------------------------------------------------- /GoodsArr.cpp: -------------------------------------------------------------------------------- 1 | #include "GoodsArr.h" 2 | #include 3 | GoodsArr::GoodsArr() 4 | { 5 | memset (arr,0,sizeof(arr)); 6 | } 7 | 8 | GoodsArr::GoodsArr(const QString &str) 9 | { 10 | int i=0; 11 | for(const QStringRef& sref : str.splitRef(',')) 12 | { 13 | arr[i++]=sref.toInt(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GoodsArr.h: -------------------------------------------------------------------------------- 1 | #ifndef GOODSARR_H 2 | #define GOODSARR_H 3 | #include 4 | #include 5 | class GoodsArr 6 | { 7 | public: 8 | explicit GoodsArr(); 9 | GoodsArr(const QString &str); 10 | 11 | unsigned& operator[](int i) 12 | { 13 | assert (i<8); 14 | return arr[i]; 15 | } 16 | const unsigned& operator[](int i) const 17 | { 18 | assert (i<8); 19 | return arr[i]; 20 | } 21 | bool empty() const 22 | { 23 | unsigned sum=0; 24 | for(int i=0; i<8; i++){ 25 | sum+=arr[i]; 26 | } 27 | return !sum; 28 | } 29 | void set(unsigned d) 30 | { 31 | for(int i=0; i<8; i++) 32 | { 33 | arr[i]=d; 34 | } 35 | } 36 | 37 | GoodsArr min(const GoodsArr& other) const 38 | { 39 | GoodsArr result; 40 | for(int i=0; i<8; i++){ 41 | result[i]=std::min(arr[i],other.arr[i]); 42 | } 43 | return result; 44 | } 45 | GoodsArr min(const GoodsArr& other, const GoodsArr& sieve) const 46 | { 47 | GoodsArr result; 48 | for(int i=0; i<8; i++){ 49 | if(sieve.arr[i]) 50 | { 51 | result[i]=std::min(arr[i],other.arr[i]); 52 | } 53 | else { 54 | result[i]=arr[i]; 55 | } 56 | } 57 | return result; 58 | } 59 | GoodsArr max(const GoodsArr& other) const 60 | { 61 | GoodsArr result; 62 | for(int i=0; i<8; i++){ 63 | result[i]=std::max(arr[i],other.arr[i]); 64 | } 65 | return result; 66 | } 67 | 68 | private: 69 | unsigned arr[8]; 70 | }; 71 | 72 | #endif // GOODSARR_H 73 | -------------------------------------------------------------------------------- /HierarchicalHeaderView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009, Krasnoshchekov Petr 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY Krasnoshchekov Petr ''AS IS'' AND ANY 17 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL Krasnoshchekov Petr BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef HIERARCHICAL_HEADER_VIEW_H 29 | #define HIERARCHICAL_HEADER_VIEW_H 30 | 31 | #include 32 | 33 | /** 34 | Hierarchical header view for QTableView. 35 | Header data is described by QAbstractItemModel. 36 | Table model's function "data" should return pointer to QAbstractItemModel, representing header structure, 37 | for horizontal header it uses HorizontalHeaderDataRole, for vertical - VerticalHeaderDataRole. 38 | If header's model function "data" with Qt::UserRole return valid QVariant, text in header cell is rotated. 39 | */ 40 | class HierarchicalHeaderView : public QHeaderView 41 | { 42 | Q_OBJECT 43 | 44 | class private_data; 45 | private_data* _pd; 46 | 47 | QStyleOptionHeader styleOptionForCell(int logicalIndex) const; 48 | 49 | protected: 50 | void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const; 51 | QSize sectionSizeFromContents(int logicalIndex) const; 52 | public: 53 | 54 | enum HeaderDataModelRoles 55 | {HorizontalHeaderDataRole=Qt::UserRole, 56 | VerticalHeaderDataRole=Qt::UserRole+1}; 57 | 58 | HierarchicalHeaderView(Qt::Orientation orientation, QWidget* parent = 0); 59 | ~HierarchicalHeaderView(); 60 | 61 | void setModel(QAbstractItemModel* model); 62 | private slots: 63 | void on_sectionResized(int logicalIndex); 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /MainWindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | #ifdef _WIN32 4 | #include 5 | #endif 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "Equipment.h" 27 | #include "Ship.h" 28 | #include "Star.h" 29 | #include "Planet.h" 30 | #include "BlackHole.h" 31 | #include "Galaxy.h" 32 | #include "TradeTableModel.h" 33 | #include "EquipmentTableModel.h" 34 | #include "HierarchicalHeaderView.h" 35 | #include "BlackHolesTableModel.h" 36 | #include "PlanetsTableModel.h" 37 | #include "SortMultiFilterProxyModel.h" 38 | #include "FilterHorizontalHeaderView.h" 39 | 40 | namespace Ui { 41 | class MainWindow; 42 | } 43 | QStringList supportedColors(); 44 | 45 | class ColorListEditor : public QComboBox 46 | { 47 | Q_OBJECT 48 | Q_PROPERTY(QColor color READ color WRITE setColor USER true) 49 | 50 | public: 51 | ColorListEditor(QWidget *widget = 0): QComboBox(widget) 52 | { 53 | populateList(supportedColors()); 54 | } 55 | 56 | public: 57 | QColor color() const 58 | { 59 | return qvariant_cast(itemData(currentIndex(), Qt::DecorationRole)); 60 | } 61 | void setColor(QColor c) 62 | { 63 | setCurrentIndex(findData(c, int(Qt::DecorationRole))); 64 | } 65 | 66 | private: 67 | void populateList(const QStringList& colorNames) 68 | { 69 | for (int i = 0; i < colorNames.size(); ++i) { 70 | QColor color(colorNames[i]); 71 | insertItem(i, colorNames[i]); 72 | setItemData(i, color, Qt::DecorationRole); 73 | } 74 | } 75 | }; 76 | 77 | class MainWindow : public QMainWindow 78 | { 79 | Q_OBJECT 80 | 81 | public: 82 | explicit MainWindow(QWidget *parent = 0); 83 | ~MainWindow(); 84 | void readSettings(); 85 | void writeSettings() const; 86 | void closeEvent(QCloseEvent *event); 87 | public slots: 88 | bool parseDump(const QString &filename=QString()); 89 | bool openDump(); 90 | void showAbout(); 91 | void saveReport(); 92 | void saveAllReports(); 93 | void setMapScale(int width) 94 | { 95 | mapWidth=width; 96 | updateMap(); 97 | } 98 | void setMapFontSize(int pt) 99 | { 100 | mapFontSize=pt; 101 | updateMap(); 102 | } 103 | void loadNextDump(); 104 | void loadPreviousDump(); 105 | 106 | #ifdef _WIN32 107 | public slots: 108 | virtual bool nativeEvent(const QByteArray &eventType, void *message, long*); 109 | void saveDumpWin(); 110 | public: 111 | bool simulateInput(const std::string& str) const; 112 | QImage currentScreen(float kx, float ky, float kw, float kh); 113 | #endif 114 | 115 | private slots: 116 | void customHeaderMenuRequested(QPoint pos); 117 | 118 | private: 119 | // using Scorer=std::vector>; 120 | struct Scorer 121 | { 122 | void read(const QVariantMap& map); 123 | void addPreset(const QString presetName,double weight,bool isBool,bool depthPenalize); 124 | double score(const QMap& reportSummary,const QMap>& _reportDepthList) const 125 | { 126 | double score=0.0; 127 | const double depthOffset=100; 128 | for(int iPreset=0; iPreset presetNames; 153 | QVector weights; 154 | QVector areBoolean; 155 | QVector depthPenalized; 156 | }; 157 | void showMessage(const QString& str,int timeout=0) const 158 | { 159 | std::cout<showMessage(str,timeout); 161 | } 162 | bool openDump(const QString& fileName); 163 | void savePreset(const QVariantMap& preset, const QString& fileName) const; 164 | void generateGalaxies(); 165 | void responsiveSleep(int msec) const; 166 | void loadPresets(); 167 | void updateMap(); 168 | void updateDumpArrows(); 169 | void saveMap(); 170 | bool eventFilter(QObject* object, QEvent* event); 171 | QVariantMap loadPreset(const QString &fileName) const; 172 | QString scoresSummary(bool desc=true) const 173 | { 174 | QString summary; 175 | using MapStrScorerCI=QMap::const_iterator; 176 | for (MapStrScorerCI i = scorers.begin(); i != scorers.end(); ++i) 177 | { 178 | if(desc) {summary+=i.key()+" = ";} 179 | summary+=QString::number(i.value().score(_reportSummary,_reportDepthList))+ 180 | "\t"; 181 | } 182 | return summary; 183 | } 184 | QString scoresSummaryHeader() const 185 | { 186 | QString summary; 187 | using MapStrScorerCI=QMap::const_iterator; 188 | for (MapStrScorerCI i = scorers.begin(); i != scorers.end(); ++i) 189 | { 190 | summary+=i.key()+"\t"; 191 | } 192 | return summary; 193 | } 194 | QString reportSummary(bool desc=true) const 195 | { 196 | QString summary=scoresSummary(desc); 197 | using MapStrIntCI=QMap::const_iterator; 198 | for (MapStrIntCI i = _reportSummary.begin(); i != _reportSummary.end(); ++i) 199 | { 200 | if (desc) { summary+=i.key()+": ";} 201 | summary+=QString::number(i.value())+"\t"; 202 | } 203 | return summary; 204 | } 205 | QString reportSummaryHeader() const 206 | { 207 | QString summary="dump name\t"+scoresSummaryHeader(); 208 | using MapStrIntCI=QMap::const_iterator; 209 | for (MapStrIntCI i = _reportSummary.begin(); i != _reportSummary.end(); ++i) 210 | { 211 | summary+=i.key()+"\t"; 212 | } 213 | return summary; 214 | } 215 | static QMap readScorers(const QString &filename); 216 | 217 | private: 218 | Ui::MainWindow *ui; 219 | QString _filename; 220 | Galaxy galaxy; 221 | QDateTime _fileModified; 222 | 223 | TradeTableModel tradeModel; 224 | QSortFilterProxyModel tradeProxyModel; 225 | 226 | EquipmentTableModel eqModel; 227 | FilterHorizontalHeaderView* eqHeaderView; 228 | SortMultiFilterProxyModel eqProxyModel; 229 | QMenu eqMenu; 230 | unsigned eqMenuRow=0; 231 | 232 | BlackHolesTableModel bhModel; 233 | 234 | PlanetsTableModel planetsModel; 235 | SortMultiFilterProxyModel planetsProxyModel; 236 | FilterHorizontalHeaderView *planetsHeaderView; 237 | 238 | QTimer reloadTimer; 239 | QSpinBox _mapScaleSpinBox{this}; 240 | QSpinBox _mapFontSpinBox{this}; 241 | 242 | QMenu reloadMenu; 243 | QMenu saveReportMenu; 244 | 245 | QSoundEffect sound; 246 | 247 | const QString rangersDir=QStandardPaths::locate(QStandardPaths::DocumentsLocation,"SpaceRangersHD",QStandardPaths::LocateDirectory); 248 | const QString presetDirPlanets="presets/planets/"; 249 | const QString presetDirEq="presets/equipment/"; 250 | const QString presetDirPlanetsReport="presets/planetsReport/"; 251 | const QString presetDirEqReport="presets/equipmentReport/"; 252 | int maxGenerationTime=120000; 253 | int screenSaveLag=200; 254 | int shortSleep=25; 255 | unsigned mapWidth=700; 256 | unsigned mapFontSize=8; 257 | QStringList planetsReportPresets; 258 | QStringList eqReportPresets; 259 | QMap minRowsPreset; 260 | QMap _reportSummary; 261 | QMap> _reportDepthList; 262 | QStringList dumpFileList; 263 | int currentDumpIndex=-1; 264 | QImage galaxyMap; 265 | 266 | QMap scorers; 267 | }; 268 | 269 | #endif // MAINWINDOW_H 270 | -------------------------------------------------------------------------------- /MainWindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 685 10 | 535 11 | 12 | 13 | 14 | SRHDDumpReader 15 | 16 | 17 | 18 | :/icons/galaxy_magnifying_glass.png:/icons/galaxy_magnifying_glass.png 19 | 20 | 21 | 22 | 23 | 24 | 0 25 | 0 26 | 685 27 | 30 28 | 29 | 30 | 31 | 32 | 33 | Toolbar 34 | 35 | 36 | TopToolBarArea 37 | 38 | 39 | false 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Equipment 55 | 56 | 57 | 1 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 156 66 | 0 67 | 68 | 69 | 70 | QTableView::item, QTableView, QHeaderView::section, QHeaderView, FilterHorizontalHeaderView > QWidget > QLabel, FilterHorizontalHeaderView > QWidget > QSpinBox, FilterHorizontalHeaderView > QWidget > QDoubleSpinBox, FilterHorizontalHeaderView > QWidget > QLineEdit 71 | { 72 | font: 9pt "Sans Serif"; 73 | } 74 | 75 | 76 | 77 | QAbstractScrollArea::AdjustToContents 78 | 79 | 80 | false 81 | 82 | 83 | true 84 | 85 | 86 | true 87 | 88 | 89 | false 90 | 91 | 92 | false 93 | 94 | 95 | 10 96 | 97 | 98 | 18 99 | 100 | 101 | true 102 | 103 | 104 | 10 105 | 106 | 107 | 18 108 | 109 | 110 | false 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | QDockWidget::AllDockWidgetFeatures 120 | 121 | 122 | Qt::AllDockWidgetAreas 123 | 124 | 125 | Trade 126 | 127 | 128 | 2 129 | 130 | 131 | 132 | 133 | 134 | 135 | font: 9pt "Sans Serif"; 136 | padding: 0px; 137 | margin: 0px; 138 | QTableView::item 139 | { 140 | border: 0px; 141 | padding: 0px; 142 | margin: 0px; 143 | } 144 | 145 | 146 | QAbstractItemView::NoEditTriggers 147 | 148 | 149 | false 150 | 151 | 152 | true 153 | 154 | 155 | true 156 | 157 | 158 | true 159 | 160 | 161 | false 162 | 163 | 164 | false 165 | 166 | 167 | 10 168 | 169 | 170 | 18 171 | 172 | 173 | true 174 | 175 | 176 | 10 177 | 178 | 179 | 18 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | Black holes 189 | 190 | 191 | 1 192 | 193 | 194 | 195 | 196 | 197 | 198 | font: 9pt "Sans Serif"; 199 | padding: 0px; 200 | margin: 0px; 201 | QTableView::item 202 | { 203 | border: 0px; 204 | padding: 0px; 205 | margin: 0px; 206 | } 207 | 208 | 209 | QAbstractItemView::NoEditTriggers 210 | 211 | 212 | false 213 | 214 | 215 | true 216 | 217 | 218 | true 219 | 220 | 221 | false 222 | 223 | 224 | false 225 | 226 | 227 | 10 228 | 229 | 230 | 18 231 | 232 | 233 | 10 234 | 235 | 236 | 18 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | Planets 246 | 247 | 248 | 2 249 | 250 | 251 | 252 | 253 | 254 | 255 | QTableView::item, QTableView, QHeaderView::section, QHeaderView, FilterHorizontalHeaderView > QWidget > QLabel, FilterHorizontalHeaderView > QWidget > QSpinBox, FilterHorizontalHeaderView > QWidget > QDoubleSpinBox, FilterHorizontalHeaderView > QWidget > QLineEdit 256 | { 257 | font: 9pt "Sans Serif"; 258 | } 259 | 260 | 261 | 262 | QAbstractItemView::NoEditTriggers 263 | 264 | 265 | false 266 | 267 | 268 | false 269 | 270 | 271 | true 272 | 273 | 274 | true 275 | 276 | 277 | false 278 | 279 | 280 | false 281 | 282 | 283 | 10 284 | 285 | 286 | 18 287 | 288 | 289 | true 290 | 291 | 292 | 10 293 | 294 | 295 | 18 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | Galaxy map 305 | 306 | 307 | 1 308 | 309 | 310 | 311 | 312 | 0 313 | 314 | 315 | 0 316 | 317 | 318 | 0 319 | 320 | 321 | 0 322 | 323 | 324 | 0 325 | 326 | 327 | 328 | 329 | true 330 | 331 | 332 | 333 | 334 | 0 335 | 0 336 | 264 337 | 85 338 | 339 | 340 | 341 | 342 | 0 343 | 344 | 345 | 0 346 | 347 | 348 | 0 349 | 350 | 351 | 0 352 | 353 | 354 | 0 355 | 356 | 357 | 358 | 359 | 360 | 0 361 | 0 362 | 363 | 364 | 365 | map 366 | 367 | 368 | false 369 | 370 | 371 | Qt::AlignCenter 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | :/icons/document-open.svgz:/icons/document-open.svgz 386 | 387 | 388 | &open dump 389 | 390 | 391 | Open dump file 392 | 393 | 394 | 395 | 396 | 397 | :/icons/view-refresh.svgz:/icons/view-refresh.svgz 398 | 399 | 400 | &Reload 401 | 402 | 403 | Reload Dump from file 404 | 405 | 406 | 407 | 408 | 409 | :/icons/help-about.svgz:/icons/help-about.svgz 410 | 411 | 412 | About 413 | 414 | 415 | 416 | 417 | 418 | :/icons/report.svg:/icons/report.svg 419 | 420 | 421 | save report 422 | 423 | 424 | Save a report file 425 | 426 | 427 | Ctrl+R 428 | 429 | 430 | Qt::ApplicationShortcut 431 | 432 | 433 | 434 | 435 | false 436 | 437 | 438 | 439 | :/icons/go-next.svgz:/icons/go-next.svgz 440 | 441 | 442 | next dump 443 | 444 | 445 | load next dump in the current folder 446 | 447 | 448 | Ctrl+Right 449 | 450 | 451 | 452 | 453 | false 454 | 455 | 456 | 457 | :/icons/go-previous.svgz:/icons/go-previous.svgz 458 | 459 | 460 | previous dump 461 | 462 | 463 | load previous dump in the current folder 464 | 465 | 466 | Ctrl+Left 467 | 468 | 469 | 470 | 471 | true 472 | 473 | 474 | reload automatically 475 | 476 | 477 | Automatically reload current dump 478 | 479 | 480 | 481 | 482 | true 483 | 484 | 485 | always save 486 | 487 | 488 | Always save report upon parsing the dump 489 | 490 | 491 | 492 | 493 | 494 | :/icons/all_reports.svg:/icons/all_reports.svg 495 | 496 | 497 | Save all reports 498 | 499 | 500 | Generate reports for all dumps in the current folder 501 | 502 | 503 | Qt::ApplicationShortcut 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | actionOpenDump 514 | triggered() 515 | MainWindow 516 | openDump() 517 | 518 | 519 | -1 520 | -1 521 | 522 | 523 | 241 524 | 216 525 | 526 | 527 | 528 | 529 | actionReload 530 | triggered() 531 | MainWindow 532 | parseDump() 533 | 534 | 535 | -1 536 | -1 537 | 538 | 539 | 241 540 | 216 541 | 542 | 543 | 544 | 545 | actionAbout 546 | triggered() 547 | MainWindow 548 | showAbout() 549 | 550 | 551 | -1 552 | -1 553 | 554 | 555 | 265 556 | 267 557 | 558 | 559 | 560 | 561 | actionSaveReport 562 | triggered() 563 | MainWindow 564 | saveReport() 565 | 566 | 567 | -1 568 | -1 569 | 570 | 571 | 265 572 | 267 573 | 574 | 575 | 576 | 577 | actionNextDump 578 | triggered() 579 | MainWindow 580 | loadNextDump() 581 | 582 | 583 | -1 584 | -1 585 | 586 | 587 | 342 588 | 267 589 | 590 | 591 | 592 | 593 | actionPreviousDump 594 | triggered() 595 | MainWindow 596 | loadPreviousDump() 597 | 598 | 599 | -1 600 | -1 601 | 602 | 603 | 342 604 | 267 605 | 606 | 607 | 608 | 609 | actionSaveAllReports 610 | triggered() 611 | MainWindow 612 | saveAllReports() 613 | 614 | 615 | -1 616 | -1 617 | 618 | 619 | 342 620 | 267 621 | 622 | 623 | 624 | 625 | 626 | openDump() 627 | parseDump() 628 | showAbout() 629 | saveReport() 630 | saveCurrentFilter() 631 | loadPreviousDump() 632 | loadNextDump() 633 | saveAllReports() 634 | 635 | 636 | -------------------------------------------------------------------------------- /Planet.cpp: -------------------------------------------------------------------------------- 1 | #include "Planet.h" 2 | #include "Galaxy.h" 3 | #include 4 | 5 | Planet::Planet(QTextStream &stream, Galaxy &galaxy, unsigned id, unsigned starId):_id(id),_starId(starId) 6 | { 7 | const static QMap planetOptions={ 8 | {"PlanetName",0}, 9 | {"Owner",1}, 10 | {"Race",2}, 11 | {"Economy",3}, 12 | {"Goverment",4}, 13 | {"ISize",5}, 14 | {"RelationToPlayer",6}, 15 | {"IMainTechLevel",7}, 16 | {"OrbitCnt",8}, 17 | {"ShopGoods",9}, 18 | {"ShopGoodsSale",10}, 19 | {"ShopGoodsBuy",11}, 20 | {"WaterSpace",12}, 21 | {"LandSpace",13}, 22 | {"HillSpace",14}, 23 | {"WaterComplate",15}, 24 | {"LandComplate",16}, 25 | {"HillComplate",17}, 26 | {"EqShop ^{",18}, 27 | {"Storage ^{",19}, 28 | {"Treasure ^{",20}, 29 | {"Garrison ^{",21}, 30 | {"TechLevels",22}, 31 | {"CurrentInvention",23}, 32 | {"CurrentInventionPoints",24} 33 | }; 34 | int nesting=0; 35 | QString line = stream.readLine().trimmed();; 36 | while (!line.isNull()) 37 | { 38 | nesting+=line.contains('{'); 39 | nesting-=line.contains('}'); 40 | if(line.startsWith("PlanetId")) 41 | { 42 | nesting-=1; 43 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 44 | _id=idRef.toInt(); 45 | 46 | } 47 | if(nesting<0) 48 | { 49 | break; 50 | } 51 | QString varname=line.section('=',0,0); 52 | QString value=line.section('=',-1); 53 | switch(planetOptions.value(varname,-1)) 54 | { 55 | case 0://PlanetName 56 | _name=value; 57 | break; 58 | 59 | case 1://Owner 60 | _owner=value; 61 | break; 62 | 63 | case 2://Race 64 | _race=value; 65 | break; 66 | 67 | case 3://Economy 68 | _economy=value; 69 | break; 70 | 71 | case 4://Goverment 72 | _government=value; 73 | break; 74 | 75 | case 5://ISize 76 | _size=value.toInt(); 77 | break; 78 | 79 | case 6://RelationToPlayer 80 | _relation=value.toInt(); 81 | break; 82 | 83 | case 7://IMainTechLevel 84 | _techLevel=value.toInt(); 85 | break; 86 | 87 | case 8://OrbitCnt 88 | _orbitCount=value.toInt(); 89 | break; 90 | 91 | case 9://ShopGoods 92 | _goodsShopQuantity=GoodsArr(value); 93 | break; 94 | 95 | case 10://ShopGoodsSale 96 | _goodsSale=GoodsArr(value); 97 | break; 98 | 99 | case 11://ShopGoodsBuy 100 | _goodsBuy=GoodsArr(value); 101 | break; 102 | 103 | case 12://WaterSpace 104 | _waterSpace=value.toInt(); 105 | break; 106 | 107 | case 13://LandSpace 108 | _landSpace=value.toInt(); 109 | break; 110 | 111 | case 14://HillSpace 112 | _hillSpace=value.toInt(); 113 | break; 114 | 115 | case 15://WaterComplate 116 | _waterComplete=value.toInt(); 117 | break; 118 | 119 | case 16://LandComplate 120 | _landComplete=value.toInt(); 121 | break; 122 | 123 | case 17://HillComplate 124 | _hillComplete=value.toInt(); 125 | break; 126 | 127 | case 18://EqShop ^{ 128 | if(_owner=="None") { 129 | break; 130 | } 131 | { 132 | auto eqListAppend=readEqlist(stream, galaxy,Equipment::kPlanetShop,_id); 133 | _eqIdList.insert(eqListAppend.begin(),eqListAppend.end()); 134 | --nesting; 135 | } 136 | break; 137 | 138 | case 19://Storage ^{ 139 | { 140 | auto eqListAppend=readEqlist(stream, galaxy,Equipment::kPlanetStorage,_id); 141 | _eqIdList.insert(eqListAppend.begin(),eqListAppend.end()); 142 | --nesting; 143 | } 144 | break; 145 | 146 | case 20://Treasure ^{ 147 | { 148 | auto eqListAppend=readEqlist(stream, galaxy,Equipment::kPlanetTreasure,_id); 149 | _eqIdList.insert(eqListAppend.begin(),eqListAppend.end()); 150 | --nesting; 151 | } 152 | break; 153 | 154 | case 21://Garrison ^{ 155 | readShiplist(stream,galaxy,_starId); 156 | --nesting; 157 | break; 158 | 159 | case 22://TechLevels ^{ 160 | readTechLevels(value); 161 | break; 162 | case 23://CurrentInvention ^{ 163 | _currentInvention=value.toUInt(); 164 | break; 165 | case 24://CurrentInventionPoints ^{ 166 | _currentInventionPoints=value.toFloat(); 167 | break; 168 | default: 169 | //skip record 170 | break; 171 | } 172 | line = stream.readLine().trimmed(); 173 | } 174 | galaxy.addPlanet(std::move(*this)); 175 | } 176 | 177 | 178 | void readPlanets(QTextStream &stream, Galaxy &galaxy, unsigned starId) 179 | { 180 | QString line = stream.readLine().trimmed();; 181 | while (!line.isNull()) 182 | { 183 | if(line.contains("PlanetId")) 184 | { 185 | QStringRef idRef(&line,8,line.indexOf(' ')-8); 186 | unsigned id=idRef.toInt(); 187 | Planet(stream, galaxy, id,starId); 188 | } 189 | else if(line.contains('}')) 190 | { 191 | break; 192 | } 193 | line = stream.readLine().trimmed(); 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /Planet.h: -------------------------------------------------------------------------------- 1 | #ifndef PLANET_H 2 | #define PLANET_H 3 | #include 4 | #include "Equipment.h" 5 | #include "GoodsArr.h" 6 | #include 7 | class Planet 8 | { 9 | public: 10 | Planet(QTextStream &stream, Galaxy& galaxy, unsigned id=0, unsigned starId=0); 11 | unsigned id() const 12 | { 13 | return _id; 14 | } 15 | bool hasMarket() const 16 | { 17 | return _owner!="None" && _owner!="Kling"; 18 | } 19 | QString name() const 20 | { 21 | return _name; 22 | } 23 | const GoodsArr& goodsCount() const 24 | { 25 | return _goodsShopQuantity; 26 | } 27 | const GoodsArr& goodsSale() const 28 | { 29 | return _goodsSale; 30 | } 31 | const GoodsArr& goodsBuy() const 32 | { 33 | return _goodsBuy; 34 | } 35 | unsigned starId() const 36 | { 37 | return _starId; 38 | } 39 | unsigned size() const 40 | { 41 | return _size/10-5; 42 | } 43 | unsigned techLevel() const 44 | { 45 | return _techLevel; 46 | } 47 | unsigned techLevel(int i) const 48 | { 49 | return _techLevels[i]; 50 | } 51 | QString economy() const 52 | { 53 | return _economy; 54 | } 55 | QString owner() const 56 | { 57 | return _owner; 58 | } 59 | void readTechLevels(QString &str) 60 | { 61 | QTextStream a(&str); 62 | char c; 63 | a>>_techLevels[0]; 64 | for(int i=1; i<20; i++) 65 | { 66 | a>>c>>_techLevels[i]; 67 | } 68 | } 69 | float currentInvetionPoints() const 70 | { 71 | return _currentInventionPoints; 72 | } 73 | unsigned currentInvetion() const 74 | { 75 | return _currentInvention; 76 | } 77 | QString race() const 78 | { 79 | return _race; 80 | } 81 | QString government() const 82 | { 83 | return _government; 84 | } 85 | unsigned relation() const 86 | { 87 | return _relation; 88 | } 89 | private: 90 | QString _name, _owner, _race, _economy, _government; 91 | unsigned _id, _size, _relation, _techLevel; 92 | unsigned _waterSpace, _landSpace, _hillSpace; 93 | unsigned _waterComplete, _landComplete, _hillComplete; 94 | unsigned _orbitCount, _currentInvention; 95 | float _currentInventionPoints; 96 | std::unordered_set _eqIdList; 97 | GoodsArr _goodsShopQuantity, _goodsSale, _goodsBuy; 98 | std::array _techLevels; 99 | unsigned _starId; 100 | }; 101 | void readPlanets(QTextStream &stream, Galaxy &galaxy, unsigned starId); 102 | #endif // PLANET_H 103 | -------------------------------------------------------------------------------- /PlanetsTableModel.cpp: -------------------------------------------------------------------------------- 1 | #include "PlanetsTableModel.h" 2 | #include "FilterHorizontalHeaderView.h" 3 | 4 | PlanetsTableModel::PlanetsTableModel(const Galaxy *galaxy, QObject *parent): 5 | QAbstractTableModel(parent),_galaxy(galaxy) 6 | { 7 | 8 | } 9 | 10 | int PlanetsTableModel::rowCount(const QModelIndex &parent) const 11 | { 12 | return _galaxy->planetCount(); 13 | } 14 | 15 | int PlanetsTableModel::columnCount(const QModelIndex &parent) const 16 | { 17 | return 32; 18 | } 19 | QVariant PlanetsTableModel::headerData(int section, Qt::Orientation orientation, int role) const 20 | { 21 | static const QVector header={tr("Name"),tr("Star"),tr("Dist."),tr("Owner"),tr("Race"), 22 | tr("TL"),tr("Size"),tr("Economy"), 23 | tr("Government"),tr("CI"),tr("CIP"), 24 | tr("Relation"),tr("TL0"),tr("TL1"), 25 | tr("TL2"), 26 | tr("TL3"), tr("TL4"),tr("TL5"), 27 | tr("TL6"), tr("TL7"),tr("TL8"), 28 | tr("TL9"), tr("TL10"),tr("TL11"), 29 | tr("TL12"), tr("TL13"),tr("TL14"), 30 | tr("TL15"), tr("TL16"),tr("TL17"), 31 | tr("TL18"), tr("TL19")}; 32 | if (role == Qt::DisplayRole) 33 | { 34 | if (orientation == Qt::Vertical) 35 | { 36 | return _galaxy->planet(section).id(); 37 | } 38 | else if (orientation == Qt::Horizontal) { 39 | return header.at(section); 40 | } 41 | } 42 | if(orientation==Qt::Horizontal && role==Qt::UserRole) 43 | { 44 | if (section==2) { 45 | return FilterHorizontalHeaderView::wtInt; 46 | } 47 | else if(section<5) { 48 | return FilterHorizontalHeaderView::wtString; 49 | } 50 | else if(section==10) { 51 | return FilterHorizontalHeaderView::wtDouble; 52 | } 53 | else if (section<7 || section>8) { 54 | return FilterHorizontalHeaderView::wtInt; 55 | } 56 | return FilterHorizontalHeaderView::wtString; 57 | } 58 | return QVariant(); 59 | } 60 | QVariant PlanetsTableModel::data(const QModelIndex &index, int role) const 61 | { 62 | if (role == Qt::DisplayRole) 63 | { 64 | int col=index.column(); 65 | int row=index.row(); 66 | if(_galaxy->planet(row).owner()=="None" && col>2) { 67 | return "-"; 68 | } 69 | switch (col) 70 | { 71 | case 0: 72 | return _galaxy->planet(row).name(); 73 | case 1: 74 | return _galaxy->planetStarName(row); 75 | case 2: 76 | return std::round(_galaxy->planetDistance(row)); 77 | case 3: 78 | return _galaxy->planetOwner(row); 79 | case 4: 80 | return _galaxy->planet(row).race(); 81 | case 5: 82 | return _galaxy->planet(row).techLevel(); 83 | case 6: 84 | return _galaxy->planet(row).size(); 85 | case 7: 86 | return _galaxy->planet(row).economy(); 87 | case 8: 88 | return _galaxy->planet(row).government(); 89 | case 9: 90 | return _galaxy->planet(row).currentInvetion(); 91 | case 10: 92 | return std::round(_galaxy->planet(row).currentInvetionPoints()*1000.0)*0.001; 93 | case 11: 94 | return _galaxy->planet(row).relation(); 95 | default: 96 | return _galaxy->planet(row).techLevel(col-12); 97 | } 98 | 99 | return QVariant("UC"); 100 | } 101 | return QVariant(); 102 | } 103 | -------------------------------------------------------------------------------- /PlanetsTableModel.h: -------------------------------------------------------------------------------- 1 | #ifndef PLANETSTABLEMODEL_H 2 | #define PLANETSTABLEMODEL_H 3 | 4 | #include 5 | 6 | #include "Galaxy.h" 7 | 8 | class PlanetsTableModel : public QAbstractTableModel 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit PlanetsTableModel(const Galaxy* galaxy, QObject *parent = 0); 13 | int rowCount(const QModelIndex &parent = QModelIndex()) const ; 14 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 15 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 16 | QVariant headerData(int section, Qt::Orientation orientation, int role) const; 17 | void reload() 18 | { 19 | beginResetModel(); 20 | endResetModel(); 21 | } 22 | private: 23 | const Galaxy *_galaxy; 24 | }; 25 | 26 | #endif // PLANETSTABLEMODEL_H 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SRHDDumpReader 2 | Viewer for the Space Rangers HD videogame dump files 3 | 4 | [download 32bit windows version](https://github.com/Burning-Daylight/SRHDDumpReader/releases) 5 | 6 | [more information and discussion](https://snk-games.net/forums/viewtopic.php?f=45&t=1667) 7 | 8 | ![Screenshot](SRHD_GUI_2016-05-17.png) 9 | -------------------------------------------------------------------------------- /README_ru.md: -------------------------------------------------------------------------------- 1 | # Краткое описание: 2 | Программа позволяет просматривать цены в галактике, всё оборудование и ошмётки, включая то, что закопано на планетах, одето на кораблях и доступно в продаже в магазинах. 3 | Вторая функция - автоматическая стартовая генерация. Можно поставить прогу на ночь и она сгенерит несколько сотен стартовых галактик, к каждой сгенерирует короткий репорт: какие планеты сгенерились в стартовой части галактики, какие базы, какие арты закопаны поблизости на незаселёнках. Потом можно по всем этим репортам пройтись поиском и отобрать то, что нужно. Есть возможность настройки информации выводимой в репорт. 4 | Для удобства есть функция QuickDump - быстрое сохранение дампа в игре (а-ля QuickSave): при запущенной игре и раскладке выставленной в английский нажмите F7. В папке с сейвами игры появится новый сейв (autodump.sav) и дамп к нему (autodump.txt). 5 | 6 | [скачать SRHDDumpReader_x32][1] 7 | 8 | [Видеообзор программы от alexkot](https://www.youtube.com/watch?v=M0gzWQGc3XE) 9 | 10 | # Инструкция: 11 | ## Описание интерфейса: 12 | [](SRHD_GUI_2016-05-17.png) 13 | 14 | * Внизу программы есть строка состояния - там отображается текущее состояние программы и сообщения об ошибках. Если у вас что-то не работает - обратите внимание на то, что написано в строке состояния. 15 | * На тулбаре есть кнопки в виде стрелок вперёд и назад - они позволяют открыть следующий и предыдущий по имени дамп в текущей папке в один клик. 16 | * Насыщенность цвета в торговле - индикатор "выгодности". Чем насыщенней - тем выгодней. 17 | * Все закладки можно двигать и андокнуть как отдельные окна и вообще тасовать как угодно (схватите и потяните). 18 | * Закладки оборудования и планет поддерживают фильтрацию. Там где поле текстовое - можно вбить, что отображать (верхнее поле ввода) и что НЕ отображать (нижнее). На самом деле эти фильтры поддерживают полноценные регулярные выражения, но если вы с ними не знакомы - можно просто вбивать текст как при обычном поиске по тексту. Например, можно написать "Art|Nod", что означает Art или Nod. Если в колонке числовые значения - можно указать минимум и максимум. 19 | * Программа рендерит карту галактики (она также сохраняется рядом с репортом в .png формате). Цвет системы на карте отображает то, кто её контролирует. Надписи над системой - список планет. Цифра - размер, буква - тип экономики, цвет - раса. Например гигантская (размер=5) гаальская индустриальная планет выглядит как 5i. Справа и слева - список баз. 20 | 21 | ## Прицип работы функции QuickDump: 22 | Программа эмулирует, будто Bы нажали ктрл+шифт+makedump, забьет "autodump" в качестве имени дампа, дождётся его сохранения и распарсит его. 23 | 24 | ## Автогенерация: 25 | Что бы запустить автогенерацию галактики - нужно выйти в стартовое меню, выставить английскую раскладку клавиатуры и нажать F6. В настройках игры обязательно нужно выставить тип скриншотов - png. Первый прогон будет примерно 2 минуты т.к. программа замеряет, как долго на вашем ПК занимает генерация, затем программа будет подстраиваться и всё будет происходить быстрее. На моём ноутбуке полная итерация занимает ~63 секунды. Автогенератор делает скриншоты, что бы проверить, всё ли нормально и подстроить задержки, поэтому если что-то сбивается, то генерация остановится. Причина остановки отображается в строке состояния. Крайне важно что бы всё сработало нормально во время первого прогона, иначе референсные скриншоты будут неправильные. НО, проверка есть всего в двух местах: на стартовом меню и на экране с интро ("Добровольцы! Вы сделали..."). Программа сохраняет лог генерации в c:\Users\_USERNAME_\Documents\spacerangershd\SRHDDumpReader_generation.log. В логе отображается короткое описание по каждой итерации. 26 | Если игра окажется неактивным окном (например, если Вы нажмёте альт-таб), то через некоторое время (до 60 сек) программа поймёт что что-то не так и остановится, о чём сообщит в строке состояния. 27 | ## Пресеты фильтров: 28 | Настройки фильтров можно сохранять для быстрой загрузки, для этого нужно нажать правой кнопкой на заголовке таблицы (но не на поле ввода) и в контекстном меню выбрать save preset. Из того же контекстного меню их можно загружать. Пресеты фильтров также позволяют настраивать то, что именно выводится в репортах. В репорт сохраняется весь вывод программы, который соответствует заданным пресетам. Когда Вы сохраняете пресет - создается файл в папке программы, подпапке "presets". Имя файла = название пресета. В папке "presets" есть четыре подпапки: 29 | 30 | * *equipment* - пресеты относящиеся к оборудованию - эти пресеты отображаются в контекстном меню, которое отображается по клику ПКМ на заголовке таблицы оборудования. 31 | * *planets* - аналогично, но для планет. 32 | * *equipmentReport* - в этой папке находятся те пресеты фильтров оборудования, которые будут выведены при сохранении репорта. Если вы хотите добавить свой пресет к репорту - его нужно скопировать в эту папку (из папки equipment). 33 | * *planetsReport* - аналогично для планет. 34 | 35 | На тулбаре справа от кнопки "сохранить репорт" есть стрелка, которая отображает выпадающее меню. В этом меню можно указать, хотите ли Вы что бы репорт сохранялся каждый раз при открытии дампа (требует немного дополнительного времени) или только во время автогенерации или если Вы сами нажмёте "сохранить репорт". 36 | 37 | ## Настройка цветовой схемы карты: 38 | У пользователя есть возможность меня цвета используемые при отрисовке карты. Цветовая схема храниться в файле map_colors.json в папке программы. Формат файла - пары ключ-значение где ключ - это модификатор+раса-владелец, а значение - цвет. Примером может послужить тот файл, что идёт вместе с программой по умолчанию. 39 | Цвет можно указывать в разных форматах: 40 | ``` 41 | #RGB (каждая из буков R, G, and B - одна шестнадцатеричная цифра) 42 | #RRGGBB 43 | #AARRGGBB (AA - прозрачность) 44 | #RRRGGGBBB 45 | #RRRRGGGGBBBB 46 | Имя цвета по стандарту World Wide Web Consortium [2], например "steelblue" или "gainsboro" 47 | transparent - прозрачный. 48 | ``` 49 | Технический нюанс: в дампе размер планет задаётся числами от 60 до 100, для удобства в программе 60->1, а 100->5. 50 | 51 | # Установка: 52 | Скачать, распаковать и запустить. 53 | 54 | ## Инструкция по калибровке для слабых компов: 55 | Открыть редактор реестра: win+r; regedit; OK 56 | Перейти в ветку игры: HKCU\Software\p-s team\SRHDDumpReader 57 | Увеличить значения параметров ShortSleepTime и MaxGenerationTime. По умолчанию они составляют 25 мсек и 120000мсек=2мин. 58 | Попробуйте поставить 50мсек и 240000мсек соответсвенно. Подбирать значение нужно под свой комп. 59 | 60 | [github](https://github.com/mdimura/SRHDDumpReader) 61 | 62 | [1]: https://github.com/mdimura/SRHDDumpReader/releases 63 | [2]: http://www.w3.org/TR/SVG/types.html#ColorKeywords -------------------------------------------------------------------------------- /SRHDDumpReader.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2014-07-04T19:00:52 4 | # 5 | #------------------------------------------------- 6 | 7 | COMMIT_DATE = $$system(git show -s --pretty='%ci') 8 | COMMIT_DATE = $$first(COMMIT_DATE) 9 | COMMIT_HASH = $$system(git log --pretty=format:'%h' -n 1) 10 | COMMIT_BRANCH =$$system(git branch -a --contains $$COMMIT_HASH | grep -v HEAD | head -n1 | tr / \' \' | awk \'{print $NF}\') 11 | DEFINES += APP_VERSION=\\\"$$COMMIT_DATE-$$COMMIT_BRANCH-$$COMMIT_HASH\\\" 12 | CONFIG(release, debug|release): DEFINES+=NDEBUG 13 | 14 | RC_FILE = SRHDDumpReader.rc 15 | 16 | QT += core gui 17 | CONFIG += c++14 18 | QMAKE_CXXFLAGS += -std=c++14 #-pthread -Wl,--no-as-needed 19 | QMAKE_LFLAGS += -std=c++14 #-pthread -Wl,--no-as-needed 20 | 21 | 22 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets multimedia 23 | 24 | TARGET = SRHDDumpReader 25 | TEMPLATE = app 26 | 27 | win32:LIBS += -L"$$_PRO_FILE_PWD_/3rdparty/libs/" -lpsapi 28 | 29 | SOURCES += main.cpp\ 30 | MainWindow.cpp \ 31 | Equipment.cpp \ 32 | Ship.cpp \ 33 | Planet.cpp \ 34 | BlackHole.cpp \ 35 | Star.cpp \ 36 | GoodsArr.cpp \ 37 | Galaxy.cpp \ 38 | TradeTableModel.cpp \ 39 | HierarchicalHeaderView.cpp \ 40 | EquipmentTableModel.cpp \ 41 | BlackHolesTableModel.cpp \ 42 | PlanetsTableModel.cpp \ 43 | FilterHorizontalHeaderView.cpp \ 44 | SortMultiFilterProxyModel.cpp 45 | 46 | HEADERS += MainWindow.h \ 47 | Equipment.h \ 48 | Ship.h \ 49 | Planet.h \ 50 | BlackHole.h \ 51 | Star.h \ 52 | GoodsArr.h \ 53 | Galaxy.h \ 54 | TradeTableModel.h \ 55 | HierarchicalHeaderView.h \ 56 | EquipmentTableModel.h \ 57 | BlackHolesTableModel.h \ 58 | PlanetsTableModel.h \ 59 | FilterHorizontalHeaderView.h \ 60 | SortMultiFilterProxyModel.h 61 | 62 | FORMS += MainWindow.ui 63 | 64 | RESOURCES += \ 65 | icons.qrc 66 | 67 | DISTFILES += \ 68 | .gitignore \ 69 | bonus_descriptions_micromodules_en.json \ 70 | bonus_descriptions_micromodules_ru.json \ 71 | Click1.wav \ 72 | make_ru.sh \ 73 | translate_micromodules.sh \ 74 | galaxy_magnifying_glass.ico \ 75 | bonus_descriptions.json \ 76 | bonus_descriptions_artifacts.json \ 77 | bonus_descriptions_hulls.json \ 78 | bonus_descriptions_micromodules.json \ 79 | translate_descriptions.sh \ 80 | bonus_descriptions.json.en \ 81 | bonus_descriptions_hulls.json.en \ 82 | bonus_descriptions_micromodules.json.ru \ 83 | en-ru.txt \ 84 | micromodules_ru-en.txt \ 85 | minRowsPreset.json \ 86 | map_colors.json \ 87 | scorers.json \ 88 | presets/detailed_treasures/equipment/treasure arts or nods 45p.dr.json \ 89 | presets/detailed_treasures/equipmentReport/treasure Antigrav 45p.dr.json \ 90 | presets/detailed_treasures/equipmentReport/treasure arts 45p.dr.json \ 91 | presets/detailed_treasures/equipmentReport/treasure BlastLocaliser 45p.dr.json \ 92 | presets/detailed_treasures/equipmentReport/treasure despensable arts 45p.dr.json \ 93 | presets/detailed_treasures/equipmentReport/treasure Forsage 45p.dr.json \ 94 | presets/detailed_treasures/equipmentReport/treasure GiperJump 45p.dr.json \ 95 | presets/detailed_treasures/equipmentReport/treasure micromodules I 45p.dr.json \ 96 | presets/detailed_treasures/equipmentReport/treasure micromodules II 45p.dr.json \ 97 | presets/detailed_treasures/equipmentReport/treasure micromodules III 45p.dr.json \ 98 | presets/detailed_treasures/equipmentReport/treasure MPA 45p.dr.json \ 99 | presets/detailed_treasures/equipmentReport/treasure Nanitoids 45p.dr.json \ 100 | presets/detailed_treasures/equipmentReport/treasure Transmitters all.dr.json \ 101 | presets/detailed_treasures/equipmentReport/treasure WeaponToSpeed 45p.dr.json \ 102 | presets/detailed_treasures/planets/big+ industrial gaal 45p.dr.json \ 103 | presets/detailed_treasures/planets/huge industrial fei 45p.dr.json \ 104 | presets/detailed_treasures/planets/huge industrial gaal 30p.dr.json \ 105 | presets/detailed_treasures/planets/huge industrial gaal-fei 45p.dr.json \ 106 | presets/detailed_treasures/planetsReport/big+ industrial gaal 45p.dr.json \ 107 | presets/detailed_treasures/planetsReport/huge industrial fei 45p.dr.json \ 108 | presets/detailed_treasures/planetsReport/huge industrial gaal 30p.dr.json \ 109 | presets/detailed_treasures/planetsReport/huge industrial gaal-fei 45p.dr.json \ 110 | presets/equipment/treasure arts or nods 45p.dr.json \ 111 | presets/equipmentReport/treasure arts 45p.dr.json \ 112 | presets/equipmentReport/treasure micromodules 45p.dr.json \ 113 | presets/planets/big+ gaal 45p.dr.json \ 114 | presets/planets/huge fei 45p.dr.json \ 115 | presets/planets/huge gaal-fei 45p.dr.json \ 116 | presets/planets/huge industrial gaal 30p.dr.json \ 117 | presets/planetsReport/huge industrial gaal 30p.dr.json \ 118 | SRHDDumpReader_ru.ts \ 119 | selection_colors.json \ 120 | presets/equipmentReport/treasure Antigrav 45p.dr.json \ 121 | presets/equipmentReport/treasure arts 45p.dr.json \ 122 | presets/equipmentReport/treasure BlastLocaliser 45p.dr.json \ 123 | presets/equipmentReport/treasure despensable arts 45p.dr.json \ 124 | presets/equipmentReport/treasure Forsage 45p.dr.json \ 125 | presets/equipmentReport/treasure GiperJump 45p.dr.json \ 126 | presets/equipmentReport/treasure micromodules 45p.dr.json \ 127 | presets/equipmentReport/treasure micromodules I 45p.dr.json \ 128 | presets/equipmentReport/treasure micromodules II 45p.dr.json \ 129 | presets/equipmentReport/treasure micromodules III 45p.dr.json \ 130 | presets/equipmentReport/treasure MPA 45p.dr.json \ 131 | presets/equipmentReport/treasure Nanitoids 45p.dr.json \ 132 | presets/equipmentReport/treasure rockets tl1 45p.dr.json \ 133 | presets/equipmentReport/treasure rockets tl2 45p.dr.json \ 134 | presets/equipmentReport/treasure rockets tl3 45p.dr.json \ 135 | presets/equipmentReport/treasure rockets tl4 45p.dr.json \ 136 | presets/equipmentReport/treasure Transmitters all.dr.json \ 137 | presets/equipmentReport/treasure WeaponToSpeed 45p.dr.json \ 138 | presets/equipment/treasure arts or nods 45p.dr.json \ 139 | presets/equipmentReport/treasure Antigrav 45p.dr.json \ 140 | presets/equipmentReport/treasure arts 45p.dr.json \ 141 | presets/equipmentReport/treasure BlastLocaliser 45p.dr.json \ 142 | presets/equipmentReport/treasure despensable arts 45p.dr.json \ 143 | presets/equipmentReport/treasure Forsage 45p.dr.json \ 144 | presets/equipmentReport/treasure GiperJump 45p.dr.json \ 145 | presets/equipmentReport/treasure micromodules 45p.dr.json \ 146 | presets/equipmentReport/treasure micromodules I 45p.dr.json \ 147 | presets/equipmentReport/treasure micromodules II 45p.dr.json \ 148 | presets/equipmentReport/treasure micromodules III 45p.dr.json \ 149 | presets/equipmentReport/treasure MPA 45p.dr.json \ 150 | presets/equipmentReport/treasure Nanitoids 45p.dr.json \ 151 | presets/equipmentReport/treasure rockets tl1 45p.dr.json \ 152 | presets/equipmentReport/treasure rockets tl2 45p.dr.json \ 153 | presets/equipmentReport/treasure rockets tl3 45p.dr.json \ 154 | presets/equipmentReport/treasure rockets tl4 45p.dr.json \ 155 | presets/equipmentReport/treasure Transmitters all.dr.json \ 156 | presets/equipmentReport/treasure WeaponToSpeed 45p.dr.json \ 157 | presets/planets/big+ gaal 45p.dr.json \ 158 | presets/planets/big+ industrial gaal 45p.dr.json \ 159 | presets/planets/huge fei 45p.dr.json \ 160 | presets/planets/huge gaal-fei 45p.dr.json \ 161 | presets/planets/huge industrial fei 45p.dr.json \ 162 | presets/planets/huge industrial gaal 30p.dr.json \ 163 | presets/planets/huge industrial gaal-fei 45p.dr.json \ 164 | presets/planetsReport/big+ industrial gaal 45p.dr.json \ 165 | presets/planetsReport/huge industrial fei 45p.dr.json \ 166 | presets/planetsReport/huge industrial gaal 30p.dr.json \ 167 | presets/planetsReport/huge industrial gaal-fei 45p.dr.json \ 168 | README.md \ 169 | presets/equipment/treasure arts 45p.dr.json \ 170 | presets/equipment/treasure micromodules 45p.dr.json \ 171 | presets/equipment/treasure rockets tl4 45p.dr.json \ 172 | presets/equipment/treasure Transmitters all.dr.json \ 173 | presets/equipmentReport/treasure Antigrav 45p.dr.json \ 174 | presets/equipmentReport/treasure arts 45p.dr.json \ 175 | presets/equipmentReport/treasure BlastLocaliser 45p.dr.json \ 176 | presets/equipmentReport/treasure despensable arts 45p.dr.json \ 177 | presets/equipmentReport/treasure Forsage 45p.dr.json \ 178 | presets/equipmentReport/treasure GiperJump 45p.dr.json \ 179 | presets/equipmentReport/treasure micromodules 45p.dr.json \ 180 | presets/equipmentReport/treasure micromodules I 45p.dr.json \ 181 | presets/equipmentReport/treasure micromodules II 45p.dr.json \ 182 | presets/equipmentReport/treasure micromodules III 45p.dr.json \ 183 | presets/equipmentReport/treasure MPA 45p.dr.json \ 184 | presets/equipmentReport/treasure Nanitoids 45p.dr.json \ 185 | presets/equipmentReport/treasure rockets tl1 45p.dr.json \ 186 | presets/equipmentReport/treasure rockets tl2 45p.dr.json \ 187 | presets/equipmentReport/treasure rockets tl3 45p.dr.json \ 188 | presets/equipmentReport/treasure rockets tl4 45p.dr.json \ 189 | presets/equipmentReport/treasure Transmitters all.dr.json \ 190 | presets/equipmentReport/treasure WeaponToSpeed 45p.dr.json \ 191 | presets/planets/huge industrial gaal 30p.dr.json \ 192 | presets/planets/huge industrial gaal-fei 45p.dr.json \ 193 | presets/planetsReport/big+ industrial gaal 45p.dr.json \ 194 | presets/planetsReport/huge industrial fei 45p.dr.json \ 195 | presets/planetsReport/huge industrial gaal 30p.dr.json \ 196 | presets/planetsReport/huge industrial gaal-fei 45p.dr.json \ 197 | presets/equipment/rockets.dr.json \ 198 | presets/equipment/treasure arts 45p.dr.json \ 199 | presets/equipment/treasure micromodules 45p.dr.json \ 200 | presets/equipment/treasure Transmitters all.dr.json \ 201 | presets/equipmentReport/Antigrav.dr.json \ 202 | presets/equipmentReport/arts.dr.json \ 203 | presets/equipmentReport/BH.dr.json \ 204 | presets/equipmentReport/BlastLocaliser.dr.json \ 205 | presets/equipmentReport/Forsage.dr.json \ 206 | presets/equipmentReport/GiperJump.dr.json \ 207 | presets/equipmentReport/micromodules I.dr.json \ 208 | presets/equipmentReport/micromodules II.dr.json \ 209 | presets/equipmentReport/micromodules III.dr.json \ 210 | presets/equipmentReport/MPA.dr.json \ 211 | presets/equipmentReport/Nanitoids.dr.json \ 212 | presets/equipmentReport/rocketsA.dr.json \ 213 | presets/equipmentReport/rocketsB.dr.json \ 214 | presets/equipmentReport/rocketsC.dr.json \ 215 | presets/equipmentReport/rocketsD.dr.json \ 216 | presets/equipmentReport/rocketsE.dr.json \ 217 | presets/equipmentReport/Transmitters.dr.json \ 218 | presets/equipmentReport/WeaponToSpeed.dr.json \ 219 | presets/planets/huge industrial gaal 30p.dr.json \ 220 | presets/planets/huge industrial gaal-fei 45p.dr.json \ 221 | presets/planetsReport/huge industrial gaal 30p.dr.json \ 222 | .gitlab-ci.yml \ 223 | dump2json.sh 224 | -------------------------------------------------------------------------------- /SRHDDumpReader.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "galaxy_magnifying_glass.ico" -------------------------------------------------------------------------------- /SRHD_GUI_2016-05-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/SRHD_GUI_2016-05-17.png -------------------------------------------------------------------------------- /Ship.cpp: -------------------------------------------------------------------------------- 1 | #include "Ship.h" 2 | #include "Galaxy.h" 3 | 4 | Ship::Ship(QTextStream &stream, Galaxy& galaxy, unsigned id, unsigned starId):_id(id),_relation(0),_money(0),_starId(starId),_special(0) 5 | { 6 | const static QMap shipOptions={ 7 | {"ICurStarId",0},{"IFullName",1},{"Goods",2},{"Money",3}, 8 | {"EqList ^{",4}, 9 | {"ArtsList ^{",5},{"EqShop ^{",6},{"Storage ^{",7},{"ShopGoods",8}, 10 | {"ShopGoodsSale",9},{"ShopGoodsBuy",10},{"IType",11},{"Skin",12} 11 | }; 12 | 13 | int nesting=0; 14 | QString line = stream.readLine().trimmed();; 15 | while (!line.isNull()) 16 | { 17 | nesting+=line.contains('{'); 18 | nesting-=line.contains('}'); 19 | if(line.startsWith("ShipId")) 20 | { 21 | nesting-=1; 22 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 23 | _id=idRef.toInt(); 24 | 25 | } 26 | if(line.startsWith("WarriorId")) 27 | { 28 | nesting-=1; 29 | QStringRef idRef(&line,9,line.indexOf(' ')-9); 30 | _id=idRef.toInt(); 31 | } 32 | if(nesting<0) 33 | { 34 | break; 35 | } 36 | const QString& varname=line.section('=',0,0); 37 | const QString& value=line.section('=',-1); 38 | switch(shipOptions.value(varname,-1)) 39 | { 40 | case 0://ICurStarId 41 | _starId=value.toInt(); 42 | break; 43 | 44 | case 1://IFullName 45 | _fullName=value; 46 | break; 47 | 48 | case 2://Goods 49 | _goodsQuantity=GoodsArr(value); 50 | break; 51 | 52 | case 3://Money 53 | _money=value.toInt(); 54 | break; 55 | 56 | case 4: //EqList 57 | case 5: //ArtsList 58 | { 59 | auto eqListAppend=readEqlist(stream, galaxy, Equipment::kShipEq,_id); 60 | _eqIdList.insert(eqListAppend.begin(),eqListAppend.end()); 61 | --nesting; 62 | } 63 | break; 64 | 65 | case 6: //EqShop 66 | { 67 | auto eqListAppend=readEqlist(stream, galaxy, Equipment::kShipShop,_id); 68 | _eqIdList.insert(eqListAppend.begin(),eqListAppend.end()); 69 | --nesting; 70 | } 71 | break; 72 | 73 | case 7: //Storage 74 | { 75 | auto eqListAppend=readEqlist(stream, galaxy, Equipment::kShipStorage,_id); 76 | _eqIdList.insert(eqListAppend.begin(),eqListAppend.end()); 77 | --nesting; 78 | } 79 | break; 80 | 81 | case 8://ShopGoods 82 | _goodsShopQuantity=GoodsArr(value); 83 | break; 84 | 85 | case 9://ShopGoodsSale 86 | _goodsSale=GoodsArr(value); 87 | break; 88 | 89 | case 10://ShopGoodsBuy 90 | _goodsBuy=GoodsArr(value); 91 | break; 92 | 93 | case 11://IType 94 | _type=value; 95 | break; 96 | case 12: 97 | _skin=value; 98 | break; 99 | default: 100 | //skip record 101 | break; 102 | } 103 | line = stream.readLine().trimmed(); 104 | } 105 | compactifyName(); 106 | galaxy.addShip(std::move(*this)); 107 | } 108 | 109 | void Ship::compactifyName() 110 | { 111 | if(_type=="RC") 112 | { 113 | _fullName.replace("Ranger Center","RC"); 114 | _fullName.replace("Центр рейнджеров","ЦР"); 115 | } 116 | else if(_type=="SB") 117 | { 118 | _fullName.replace("Research Station","SB"); 119 | _fullName.replace("Научная база","НБ"); 120 | } 121 | else if(_type=="MC") 122 | { 123 | _fullName.replace("Medical Center","MC"); 124 | _fullName.replace("Медицинский центр","МЦ"); 125 | } 126 | else if(_type=="PB") 127 | { 128 | _fullName.replace("Pirate Base","PB"); 129 | _fullName.replace("Пиратская база","ПБ"); 130 | } 131 | else if(_type=="BK") 132 | { 133 | _fullName.replace("Business Center","BC"); 134 | _fullName.replace("Бизнес-центр","БЦ"); 135 | } 136 | else if(_type=="WB") 137 | { 138 | _fullName.replace("Military Base","MB"); 139 | _fullName.replace("Военная база","ВБ"); 140 | } 141 | else if(_type=="") 142 | { 143 | _fullName.replace("",""); 144 | } 145 | 146 | } 147 | 148 | 149 | void readShiplist(QTextStream &stream, Galaxy &galaxy, unsigned starId) 150 | { 151 | QString line = stream.readLine().trimmed(); 152 | while (!line.isNull()) 153 | { 154 | if(line.startsWith("ShipId")) 155 | { 156 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 157 | unsigned id=idRef.toInt(); 158 | Ship(stream, galaxy, id,starId); 159 | } 160 | else if(line.startsWith("WarriorId")) 161 | { 162 | QStringRef idRef(&line,9,line.indexOf(' ')-9); 163 | unsigned id=idRef.toInt(); 164 | Ship(stream, galaxy, id,starId); 165 | } 166 | else if(line.contains('}')) 167 | { 168 | break; 169 | } 170 | line = stream.readLine().trimmed(); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Ship.h: -------------------------------------------------------------------------------- 1 | #ifndef SHIP_H 2 | #define SHIP_H 3 | #include "GoodsArr.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | class Galaxy; 9 | 10 | class Ship 11 | { 12 | public: 13 | Ship(QTextStream &stream, Galaxy& galaxy, unsigned id, unsigned starId); 14 | unsigned id() const 15 | { 16 | return _id; 17 | } 18 | bool hasMarket() const 19 | { 20 | return !(_goodsSale.empty()); 21 | } 22 | QString name() const 23 | { 24 | return _fullName; 25 | } 26 | const GoodsArr& goodsCount() const 27 | { 28 | return _goodsShopQuantity; 29 | } 30 | const GoodsArr& goodsSale() const 31 | { 32 | return _goodsSale; 33 | } 34 | const GoodsArr& goodsBuy() const 35 | { 36 | return _goodsBuy; 37 | } 38 | unsigned starId() const 39 | { 40 | return _starId; 41 | } 42 | QString race() const 43 | { 44 | if (_type=="Kling") { 45 | return _skin.split('.')[1]; 46 | } 47 | if (_type!="Pirate") { 48 | return "Normal"; 49 | } 50 | return _type; 51 | } 52 | 53 | private: 54 | void compactifyName(); 55 | private: 56 | unsigned _id; 57 | QString _type; 58 | QString _fullName; 59 | QString _skin; 60 | GoodsArr _goodsQuantity; 61 | GoodsArr _goodsShopQuantity, _goodsSale, _goodsBuy; 62 | unsigned _relation; 63 | unsigned _money; 64 | std::unordered_set _eqIdList; 65 | //QString _place; 66 | //unsigned _placeId; 67 | unsigned _starId; 68 | unsigned _special; 69 | 70 | //enum Akrin { kNone, kMyoplasmic, kPygamore, kTranscendental, kUpgraded, kBiogenic, kNanobrolite, kUltraalloy, kHybrid}; 71 | }; 72 | 73 | void readShiplist(QTextStream &stream, Galaxy &galaxy, unsigned starId); 74 | 75 | #endif // SHIP_H 76 | -------------------------------------------------------------------------------- /SortMultiFilterProxyModel.cpp: -------------------------------------------------------------------------------- 1 | #include "SortMultiFilterProxyModel.h" 2 | 3 | SortMultiFilterProxyModel::SortMultiFilterProxyModel(QObject *parent):QSortFilterProxyModel(parent) 4 | { 5 | //timer.setInterval(300); 6 | //timer.setSingleShot(true); 7 | //connect(&timer,SIGNAL(timeout()),this,SLOT(invalidate())); 8 | } 9 | 10 | void SortMultiFilterProxyModel::setFilters(const QMap &match, const QMap ¬Match, const QMap &min, const QMap &max) 11 | { 12 | _match.clear(); 13 | _notMatch.clear(); 14 | _min.clear(); 15 | _max.clear(); 16 | using MapIntStrCI=QMap::const_iterator; 17 | for (MapIntStrCI i = match.begin(); i != match.end(); ++i) 18 | { 19 | _match[i.key()]=i.value(); 20 | } 21 | for (MapIntStrCI i = notMatch.begin(); i != notMatch.end(); ++i) 22 | { 23 | _notMatch[i.key()]=i.value(); 24 | } 25 | 26 | using MapIntDoubleCI=QMap::const_iterator; 27 | for (MapIntDoubleCI i = min.begin(); i != min.end(); ++i) 28 | { 29 | _min[i.key()]=i.value(); 30 | } 31 | for (MapIntDoubleCI i = max.begin(); i != max.end(); ++i) 32 | { 33 | if(i.value()>=_min[i.key()]) { 34 | _max[i.key()]=i.value(); 35 | } 36 | } 37 | invalidateFilter(); 38 | } 39 | 40 | bool SortMultiFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const 41 | { 42 | int colCnt=sourceModel()->columnCount(); 43 | QVector indices; 44 | indices.reserve(colCnt); 45 | for(int col=0; colindex(sourceRow, col, sourceParent)); 48 | } 49 | for(const auto& pair:_min) 50 | { 51 | int col=pair.first; 52 | double cellValue=sourceModel()->data(indices[col]).toDouble(); 53 | if(cellValuedata(indices[col]).toDouble(); 61 | if(cellValue>pair.second) { 62 | return false; 63 | } 64 | } 65 | for(const auto& pair:_match) 66 | { 67 | int col=pair.first; 68 | const QString& cellValue=sourceModel()->data(indices[col]).toString(); 69 | if(! cellValue.contains(QRegularExpression(pair.second,_caseSensitive))) { 70 | return false; 71 | } 72 | } 73 | for(const auto& pair:_notMatch) 74 | { 75 | int col=pair.first; 76 | const QString& cellValue=sourceModel()->data(indices[col]).toString(); 77 | if(cellValue.contains(QRegularExpression(pair.second,_caseSensitive))) { 78 | return false; 79 | } 80 | } 81 | return true; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /SortMultiFilterProxyModel.h: -------------------------------------------------------------------------------- 1 | #ifndef SORTMULTIFILTERPROXYMODEL_H 2 | #define SORTMULTIFILTERPROXYMODEL_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | class SortMultiFilterProxyModel : public QSortFilterProxyModel 12 | { 13 | Q_OBJECT 14 | public: 15 | explicit SortMultiFilterProxyModel(QObject *parent = 0); 16 | public slots: 17 | void setMin(int col, double min) 18 | { 19 | if(min==_min[col]) { 20 | return; 21 | } 22 | _min[col]=min; 23 | correctMinMax(col); 24 | invalidateFilter(); 25 | } 26 | void unsetMin(int col) 27 | { 28 | if(_min.count(col)==0) { 29 | return; 30 | } 31 | _min.erase(col); 32 | invalidateFilter(); 33 | } 34 | void setMax(int col, double max) 35 | { 36 | if(_max[col]==max) { 37 | return; 38 | } 39 | _max[col]=max; 40 | correctMinMax(col); 41 | invalidateFilter(); 42 | } 43 | void unsetMax(int col) 44 | { 45 | if(_max.count(col)==0) { 46 | return; 47 | } 48 | _max.erase(col); 49 | invalidateFilter(); 50 | } 51 | void setMatch(int col, const QString& match ) 52 | { 53 | if (match.isEmpty()) { 54 | unsetMatch(col); 55 | return; 56 | } 57 | if(_match[col]==match) { 58 | return; 59 | } 60 | _match[col]=match; 61 | invalidateFilter(); 62 | } 63 | void unsetMatch(int col) 64 | { 65 | if(_match.count(col)==0) { 66 | return; 67 | } 68 | _match.erase(col); 69 | invalidateFilter(); 70 | } 71 | void setNotMatch(int col, const QString& notMatch ) 72 | { 73 | if (notMatch.isEmpty()) { 74 | unsetNotMatch(col); 75 | return; 76 | } 77 | if(_notMatch[col]==notMatch) { 78 | return; 79 | } 80 | _notMatch[col]=notMatch; 81 | invalidateFilter(); 82 | //std::cout<<"setNotMatch end"<& match, 93 | const QMap& notMatch, 94 | const QMap& min, 95 | const QMap& max); 96 | protected: 97 | bool filterAcceptsRow(int sourceRow, 98 | const QModelIndex &sourceParent) const; 99 | private: 100 | void correctMinMax(int col) 101 | { 102 | if (_min[col]>_max[col] /*|| _max[col]==0.0*/) 103 | { 104 | if(_max.count(col)==0) { 105 | return; 106 | } 107 | _max.erase(col); 108 | } 109 | } 110 | 111 | std::unordered_map _match; 112 | std::unordered_map _notMatch; 113 | std::unordered_map _min; 114 | std::unordered_map _max; 115 | QRegularExpression::PatternOption _caseSensitive=QRegularExpression::CaseInsensitiveOption; 116 | //QTimer timer; 117 | }; 118 | 119 | #endif // SORTMULTIFILTERPROXYMODEL_H 120 | -------------------------------------------------------------------------------- /Star.cpp: -------------------------------------------------------------------------------- 1 | #include "Star.h" 2 | #include "Galaxy.h" 3 | 4 | void readStars(QTextStream &stream, Galaxy &galaxy) 5 | { 6 | 7 | QString line = stream.readLine().trimmed(); 8 | while (!line.isNull()) 9 | { 10 | if(line.contains("StarId")) 11 | { 12 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 13 | unsigned id=idRef.toInt(); 14 | galaxy.addStar(Star(stream, galaxy, id)); 15 | } 16 | else if(line.contains('}')) 17 | { 18 | break; 19 | } 20 | line = stream.readLine().trimmed(); 21 | } 22 | } 23 | 24 | Star::Star(QTextStream &stream, Galaxy &galaxy, unsigned id):_id(id),_x(0.0),_y(0.0) 25 | { 26 | const static QMap starOptions={ 27 | {{"StarName",0},{"X",1},{"Y",2},{"Owners",3},{"DomSeries",4},{"ShipList ^{",5},{"PlanetList ^{",6},{"Junk ^{",7}} 28 | }; 29 | 30 | int nesting=0; 31 | QString line = stream.readLine().trimmed(); 32 | while (!line.isNull()) 33 | { 34 | nesting+=line.contains('{'); 35 | nesting-=line.contains('}'); 36 | if(line.startsWith("StarId")) 37 | { 38 | nesting-=1; 39 | QStringRef idRef(&line,6,line.indexOf(' ')-6); 40 | _id=idRef.toInt(); 41 | } 42 | if(nesting<0) 43 | { 44 | break; 45 | } 46 | QString varname=line.section('=',0,0); 47 | QString value=line.section('=',-1); 48 | 49 | switch(starOptions.value(varname,-1)) 50 | { 51 | case 0://StarName 52 | _name=value; 53 | break; 54 | 55 | case 1://X 56 | value.replace(',','.'); 57 | _x=value.toDouble(); 58 | break; 59 | 60 | case 2://Y 61 | value.replace(',','.'); 62 | _y=value.toDouble(); 63 | break; 64 | 65 | case 3://Owners 66 | _owner=value; 67 | break; 68 | 69 | case 4://DomSeries 70 | _domSeries=value; 71 | break; 72 | 73 | case 5://ShipList ^{ 74 | readShiplist(stream,galaxy,_id); 75 | --nesting; 76 | break; 77 | 78 | case 6://PlanetList ^{ 79 | readPlanets(stream,galaxy,_id); 80 | --nesting; 81 | break; 82 | 83 | case 7://Junk ^{ 84 | readEqlist(stream,galaxy,Equipment::kJunk,_id); 85 | --nesting; 86 | break; 87 | 88 | default: 89 | //skip record 90 | break; 91 | } 92 | line = stream.readLine().trimmed(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Star.h: -------------------------------------------------------------------------------- 1 | #ifndef STAR_H 2 | #define STAR_H 3 | #include 4 | #include 5 | #include 6 | #include "Equipment.h" 7 | #include "Ship.h" 8 | #include "Planet.h" 9 | class Star 10 | { 11 | public: 12 | Star(QTextStream &stream, Galaxy& galaxy, unsigned id=0); 13 | unsigned id() const 14 | { 15 | return _id; 16 | } 17 | QString name() const 18 | { 19 | return _name; 20 | } 21 | QString owner() const 22 | { 23 | return _owner; 24 | } 25 | QString domSeries() const 26 | { 27 | return _domSeries; 28 | } 29 | QPointF position() const 30 | { 31 | return QPointF(_x,_y); 32 | } 33 | private: 34 | unsigned _id; 35 | QString _name, _owner, _domSeries; 36 | double _x, _y; 37 | }; 38 | void readStars(QTextStream &stream, Galaxy &galaxy); 39 | #endif // STAR_H 40 | -------------------------------------------------------------------------------- /TradeTableModel.cpp: -------------------------------------------------------------------------------- 1 | #include "TradeTableModel.h" 2 | #include "HierarchicalHeaderView.h" 3 | TradeTableModel::TradeTableModel(const Galaxy *galaxy, QObject *parent) : 4 | QAbstractTableModel(parent),_galaxy(galaxy) 5 | { 6 | fillHeaderModel(); 7 | } 8 | 9 | int TradeTableModel::rowCount(const QModelIndex &parent) const 10 | { 11 | return _galaxy->marketsCount(); 12 | } 13 | 14 | int TradeTableModel::columnCount(const QModelIndex &parent) const 15 | { 16 | return 31;//3+8*3+4 17 | } 18 | 19 | QVariant TradeTableModel::data(const QModelIndex &index, int role) const 20 | { 21 | if(role==HierarchicalHeaderView::HorizontalHeaderDataRole) 22 | { 23 | QVariant v; 24 | v.setValue((QObject*)&_horizontalHeaderModel); 25 | return v; 26 | } 27 | if (role == Qt::DisplayRole) 28 | { 29 | int col=index.column(); 30 | if(col==0) 31 | { 32 | return _galaxy->marketName(index.row()); 33 | } 34 | else if(col==1) 35 | { 36 | return _galaxy->marketStarName(index.row()); 37 | } 38 | else if(col==2) 39 | { 40 | return std::round(_galaxy->marketDistFromPlayer(index.row())*10.0)/10.0; 41 | } 42 | else if(col==27) 43 | { 44 | return _galaxy->marketPlanetSize(index.row()); 45 | } 46 | else if(col==28) 47 | { 48 | return _galaxy->marketPlanetTechLevel(index.row()); 49 | } 50 | else if(col==29) 51 | { 52 | return _galaxy->marketPlanetEconomy(index.row()); 53 | } 54 | else if(col==30) 55 | { 56 | return _galaxy->marketPlanetOwner(index.row()); 57 | } 58 | else 59 | { 60 | int quantSellBuy=(col-3)%3; 61 | int goodNum=(col-3)/3; 62 | switch(quantSellBuy) 63 | { 64 | case 0://quantity is requested 65 | return _galaxy->marketQuantity(index.row())[goodNum]; 66 | break; 67 | 68 | case 1://sale price is requested 69 | return _galaxy->marketSale(index.row())[goodNum]; 70 | break; 71 | 72 | case 2://buy price is requested 73 | return _galaxy->marketBuy(index.row())[goodNum]; 74 | break; 75 | 76 | } 77 | } 78 | 79 | return index.row()+index.column(); 80 | } 81 | if (role == Qt::BackgroundColorRole) 82 | { 83 | int col=index.column(); 84 | if(col>2 && col<27) 85 | { 86 | int quantSellBuy=(col-3)%3; 87 | if(quantSellBuy==0){ 88 | return QVariant(); 89 | } 90 | int goodNum=(col-3)/3; 91 | int maxBuyPrice=_galaxy->maxBuyPrice()[goodNum]; 92 | int minSellPrice=_galaxy->minSellPrice()[goodNum]; 93 | int quantity=_galaxy->marketQuantity(index.row())[goodNum]; 94 | int scale=-1; 95 | if(quantSellBuy==1) { 96 | int price=_galaxy->marketSale(index.row())[goodNum]; 97 | if(price>maxBuyPrice || quantity==0) { 98 | return QVariant(); 99 | } 100 | scale=255+255.0*(minSellPrice-price)/(maxBuyPrice-minSellPrice); 101 | return QColor(0, 163, 22,std::min(scale,255)); 102 | } 103 | else if(quantSellBuy==2) { 104 | int price=_galaxy->marketBuy(index.row())[goodNum]; 105 | if(price header={tr("Name"),tr("Star"),tr("Dist."), 121 | tr("Fq"), tr("Fs"), tr("Fb"), 122 | tr("Mq"), tr("Ms"), tr("Mb"), 123 | tr("Aq"), tr("As"), tr("Ab"), 124 | tr("Sq"), tr("Ss"), tr("Sb"), 125 | tr("Lq"), tr("Ls"), tr("Lb"), 126 | tr("Tq"), tr("Ts"), tr("Tb"), 127 | tr("Wq"), tr("Ws"), tr("Wb"), 128 | tr("Dq"), tr("Ds"), tr("Db"), 129 | tr("Size"),tr("Tech"),tr("Type"),tr("Owner")}; 130 | if (role == Qt::DisplayRole) 131 | { 132 | if (orientation == Qt::Vertical) 133 | { 134 | return _galaxy->marketId(section); 135 | } 136 | else if (orientation == Qt::Horizontal) { 137 | return header.at(section); 138 | } 139 | } 140 | return QVariant(); 141 | } 142 | 143 | void TradeTableModel::fillHeaderModel() 144 | { 145 | _horizontalHeaderModel.setItem(0, 0, new QStandardItem(tr("Name"))); 146 | _horizontalHeaderModel.setItem(0, 1, new QStandardItem(tr("Star"))); 147 | _horizontalHeaderModel.setItem(0, 2, new QStandardItem(tr("Dist."))); 148 | 149 | static const QVector products={tr("Food"),tr("Meds"),tr("Alcohol"),tr("Minerals"), 150 | tr("Luxury"),tr("Technics"),tr("Weapons"),tr("Drugs")}; 151 | 152 | for(int prod=0; prod<8; prod++) 153 | { 154 | QStandardItem* rootItem = new QStandardItem(products.at(prod)); 155 | QList l; 156 | 157 | l.push_back(new QStandardItem("#")); 158 | rootItem->appendColumn(l); 159 | l.clear(); 160 | 161 | l.push_back(new QStandardItem("S")); 162 | rootItem->appendColumn(l); 163 | l.clear(); 164 | 165 | l.push_back(new QStandardItem("B")); 166 | rootItem->appendColumn(l); 167 | l.clear(); 168 | 169 | _horizontalHeaderModel.setItem(0, prod+3, rootItem); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /TradeTableModel.h: -------------------------------------------------------------------------------- 1 | #ifndef TRADETABLEMODEL_H 2 | #define TRADETABLEMODEL_H 3 | 4 | #include 5 | #include 6 | #include "Galaxy.h" 7 | 8 | class TradeTableModel : public QAbstractTableModel 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit TradeTableModel(const Galaxy* galaxy, QObject *parent = 0); 13 | int rowCount(const QModelIndex &parent = QModelIndex()) const ; 14 | int columnCount(const QModelIndex &parent = QModelIndex()) const; 15 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; 16 | QVariant headerData(int section, Qt::Orientation orientation, int role) const; 17 | void reload() 18 | { 19 | beginResetModel(); 20 | endResetModel(); 21 | } 22 | void fillHeaderModel(); 23 | 24 | signals: 25 | 26 | public slots: 27 | private: 28 | const Galaxy *_galaxy; 29 | QStandardItemModel _horizontalHeaderModel; 30 | }; 31 | 32 | #endif // TRADETABLEMODEL_H 33 | -------------------------------------------------------------------------------- /bonus_descriptions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "Миоплазменный:1", 4 | "value": "energetic dmg +2, splinter dmg +3, speed -10" 5 | }, 6 | { 7 | "key": "Миоплазменный:2", 8 | "value": "energetic dmg +3, splinter dmg +4, speed -20" 9 | }, 10 | { 11 | "key": "Миоплазменный:3", 12 | "value": "energetic dmg +5, splinter dmg +6, speed -30" 13 | }, 14 | { 15 | "key": "Пигамарный:1", 16 | "value": "rocket dmg+2, defence -1, radar -50" 17 | }, 18 | { 19 | "key": "Пигамарный:2", 20 | "value": "rocket dmg+3, defence -2, radar -100" 21 | }, 22 | { 23 | "key": "Пигамарный:3", 24 | "value": "rocket dmg+4, defence -3, radar -250" 25 | }, 26 | { 27 | "key": "Трансцендентальный:1", 28 | "value": "defence +2, mass +10%" 29 | }, 30 | { 31 | "key": "Трансцендентальный:2", 32 | "value": "defence +3, mass +20%" 33 | }, 34 | { 35 | "key": "Трансцендентальный:3", 36 | "value": "defence +4, mass +30%" 37 | }, 38 | { 39 | "key": "Апгрейтинговый:1", 40 | "value": "hook range +10, mobility +1, charizm -2" 41 | }, 42 | { 43 | "key": "Апгрейтинговый:2", 44 | "value": "hook range +15, mobility +1, charizm -2" 45 | }, 46 | { 47 | "key": "Апгрейтинговый:3", 48 | "value": "hook range +20, mobility +1, charizm -2" 49 | }, 50 | { 51 | "key": "Biogenic:1", 52 | "value": "scaner +3, radar +100, technics -2" 53 | }, 54 | { 55 | "key": "Biogenic:2", 56 | "value": "scaner +6, radar +200, technics -2" 57 | }, 58 | { 59 | "key": "Biogenic:3", 60 | "value": "scaner +9, radar +200, technics -2" 61 | }, 62 | { 63 | "key": "Нанобролитовый:1", 64 | "value": "energetic dmg +2, splinter dmg +3, weapon range -10, attack +1, trade -2" 65 | }, 66 | { 67 | "key": "Нанобролитовый:2", 68 | "value": "energetic dmg +4, splinter dmg +5, weapon range -20, attack +1, trade -2" 69 | }, 70 | { 71 | "key": "Нанобролитовый:3", 72 | "value": "energetic dmg +6, splinter dmg +8, weapon range -30, attack +1, trade -2" 73 | }, 74 | { 75 | "key": "Ультрасплавный:1", 76 | "value": "droid +7, engine speed -10, attack -1, technics +1" 77 | }, 78 | { 79 | "key": "Ультрасплавный:2", 80 | "value": "droid +12, engine speed -25, attack -1, technics +1" 81 | }, 82 | { 83 | "key": "Ультрасплавный:3", 84 | "value": "droid +15, engine speed -55, attack -1, technics +1" 85 | } 86 | , 87 | { 88 | "key": "Myoplasmic:1", 89 | "value": "energetic dmg +2, splinter dmg +3, speed -10" 90 | }, 91 | { 92 | "key": "Myoplasmic:2", 93 | "value": "energetic dmg +3, splinter dmg +4, speed -20" 94 | }, 95 | { 96 | "key": "Myoplasmic:3", 97 | "value": "energetic dmg +5, splinter dmg +6, speed -30" 98 | }, 99 | { 100 | "key": "Pygamore:1", 101 | "value": "rocket dmg+2, defence -1, radar -50" 102 | }, 103 | { 104 | "key": "Pygamore:2", 105 | "value": "rocket dmg+3, defence -2, radar -100" 106 | }, 107 | { 108 | "key": "Pygamore:3", 109 | "value": "rocket dmg+4, defence -3, radar -250" 110 | }, 111 | { 112 | "key": "Transcendental:1", 113 | "value": "defence +2, mass +10%" 114 | }, 115 | { 116 | "key": "Transcendental:2", 117 | "value": "defence +3, mass +20%" 118 | }, 119 | { 120 | "key": "Transcendental:3", 121 | "value": "defence +4, mass +30%" 122 | }, 123 | { 124 | "key": "Upgraded:1", 125 | "value": "hook range +10, mobility +1, charizm -2" 126 | }, 127 | { 128 | "key": "Upgraded:2", 129 | "value": "hook range +15, mobility +1, charizm -2" 130 | }, 131 | { 132 | "key": "Upgraded:3", 133 | "value": "hook range +20, mobility +1, charizm -2" 134 | }, 135 | { 136 | "key": "Biogenic:1", 137 | "value": "scaner +3, radar +100, technics -2" 138 | }, 139 | { 140 | "key": "Biogenic:2", 141 | "value": "scaner +6, radar +200, technics -2" 142 | }, 143 | { 144 | "key": "Biogenic:3", 145 | "value": "scaner +9, radar +200, technics -2" 146 | }, 147 | { 148 | "key": "Nanobrolite:1", 149 | "value": "energetic dmg +2, splinter dmg +3, weapon range -10, attack +1, trade -2" 150 | }, 151 | { 152 | "key": "Nanobrolite:2", 153 | "value": "energetic dmg +4, splinter dmg +5, weapon range -20, attack +1, trade -2" 154 | }, 155 | { 156 | "key": "Nanobrolite:3", 157 | "value": "energetic dmg +6, splinter dmg +8, weapon range -30, attack +1, trade -2" 158 | }, 159 | { 160 | "key": "Ultraalloy:1", 161 | "value": "droid +7, engine speed -10, attack -1, technics +1" 162 | }, 163 | { 164 | "key": "Ultraalloy:2", 165 | "value": "droid +12, engine speed -25, attack -1, technics +1" 166 | }, 167 | { 168 | "key": "Ultraalloy:3", 169 | "value": "droid +15, engine speed -55, attack -1, technics +1" 170 | } 171 | ] 172 | -------------------------------------------------------------------------------- /bonus_descriptions.json.en: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "Myoplasmic:1", 4 | "value": "energetic dmg +2, splinter dmg +3, speed -10" 5 | }, 6 | { 7 | "key": "Myoplasmic:2", 8 | "value": "energetic dmg +3, splinter dmg +4, speed -20" 9 | }, 10 | { 11 | "key": "Myoplasmic:3", 12 | "value": "energetic dmg +5, splinter dmg +6, speed -30" 13 | }, 14 | { 15 | "key": "Pygamore:1", 16 | "value": "rocket dmg+2, defence -1, radar -50" 17 | }, 18 | { 19 | "key": "Pygamore:2", 20 | "value": "rocket dmg+3, defence -2, radar -100" 21 | }, 22 | { 23 | "key": "Pygamore:3", 24 | "value": "rocket dmg+4, defence -3, radar -250" 25 | }, 26 | { 27 | "key": "Transcendental:1", 28 | "value": "defence +2, mass +10%" 29 | }, 30 | { 31 | "key": "Transcendental:2", 32 | "value": "defence +3, mass +20%" 33 | }, 34 | { 35 | "key": "Transcendental:3", 36 | "value": "defence +4, mass +30%" 37 | }, 38 | { 39 | "key": "Upgraded:1", 40 | "value": "hook range +10, mobility +1, charizm -2" 41 | }, 42 | { 43 | "key": "Upgraded:2", 44 | "value": "hook range +15, mobility +1, charizm -2" 45 | }, 46 | { 47 | "key": "Upgraded:3", 48 | "value": "hook range +20, mobility +1, charizm -2" 49 | }, 50 | { 51 | "key": "Biogenic:1", 52 | "value": "scaner +3, radar +100, technics -2" 53 | }, 54 | { 55 | "key": "Biogenic:2", 56 | "value": "scaner +6, radar +200, technics -2" 57 | }, 58 | { 59 | "key": "Biogenic:3", 60 | "value": "scaner +9, radar +200, technics -2" 61 | }, 62 | { 63 | "key": "Nanobrolite:1", 64 | "value": "energetic dmg +2, splinter dmg +3, weapon range -10, attack +1, trade -2" 65 | }, 66 | { 67 | "key": "Nanobrolite:2", 68 | "value": "energetic dmg +4, splinter dmg +5, weapon range -20, attack +1, trade -2" 69 | }, 70 | { 71 | "key": "Nanobrolite:3", 72 | "value": "energetic dmg +6, splinter dmg +8, weapon range -30, attack +1, trade -2" 73 | }, 74 | { 75 | "key": "Ultraalloy:1", 76 | "value": "droid +7, engine speed -10, attack -1, technics +1" 77 | }, 78 | { 79 | "key": "Ultraalloy:2", 80 | "value": "droid +12, engine speed -25, attack -1, technics +1" 81 | }, 82 | { 83 | "key": "Ultraalloy:3", 84 | "value": "droid +15, engine speed -55, attack -1, technics +1" 85 | } 86 | ] 87 | -------------------------------------------------------------------------------- /bonus_descriptions_artifacts.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"key":"ArtAntigrav","value":"Масса корабля -25%; c ЧД-транком -50%" }, 3 | {"key":"ArtAnalyzer","value":"Указывает шанс победы над противником. Предсказывает нападения на системы. Показывает наличие артефакта на необитаемой планете, со Сканерным Кэшем показывает артефакты в ЧД" }, 4 | {"key":"ArtDroid","value":"Эффективность дроида +10 ед; c ЧД-дроидом +20" }, 5 | {"key":"ArtHull","value":"Защита корпуса +5; c ЧД-транком +10" }, 6 | {"key":"ArtBomb","value":"При взрыве наносит до 600 урона" }, 7 | {"key":"ArtMiniExpl","value":"После уничтожения противника остается больше его оборудования; c ЧД-Сканером ещё больше" }, 8 | {"key":"ArtNano","value":"Чинят 10% от оборудования.; c ЧД-оборудованием 20%" }, 9 | {"key":"ArtPower","value":"Быстро восстанавливают прежнюю скорость двигателя в бою после замедления. Снижают урон от звезды.; c ЧД-двигателем Эффект усиливается" }, 10 | {"key":"ArtDef","value":"ГЗП +5%; c ЧД-ГЗП +10%" }, 11 | {"key":"ArtRadar","value":"радара +600 ед. Показывает корабли в близлежащих системах (если сканер игрока может пробить защитное поле корабля).; c ЧД-Радаром +1200" }, 12 | {"key":"ArtSpeed","value":"+20% к скорости корабля; c ЧД-двигателем +40%" }, 13 | {"key":"ArtScaner","value":"+10% к мощности сканера. С Вероятностным Анализатором показывает арты в ЧД; c ЧД-Сканером +20%" }, 14 | {"key":"ArtTranclucator","value":"Робот-защитник, можно экипировать и поднимать навыки" }, 15 | {"key":"ArtFuel","value":"Вырабатывает топливо в баке (+2 в день).; c ЧД-баком +4" }, 16 | {"key":"ArtHook","value":"+30 ед. к мощности захвата; c ЧД-захватом +60" }, 17 | {"key":"ArtDefToArms2","value":"+2 орудийных турели - ГЗП" }, 18 | {"key":"ArtArtefactor","value":"+3 артефакта - дроид (позволяет пролонгеру, сканерному кэшу и вероятностному анализатору работать без установки)" }, 19 | {"key":"ArtBio","value":"Продлевает действие стимуляторв, усиливает иммунитет и повышает лимит количества стимуляторов, после которого развивается наркозависимость. Для действия не-информационных эффектов, должен быть экипирован постоянно." }, 20 | {"key":"ArtDecelerate","value":"При нанесении общего урона сильно перегревается двигатель противника.; c ЧД-оск. оружием Эффект усиливается" }, 21 | {"key":"ArtGiperJump","value":"Расстояние для прыжка увеличивается до 40 парсек. уменьшает длительность гиперпрыжка.; c ЧД-двигателем 60 парсек" }, 22 | {"key":"ArtSplinter","value":"+20% урона от осколочного оружия; c ЧД-оск. оружием +40%" }, 23 | {"key":"ArtForsage","value":"срок работы двигателя в режиме форсажа увеличивается вдвое.; c ЧД-двигателем - втрое" }, 24 | {"key":"ArtEnergyDef","value":"В 30% случаев поглощает урон от одного выстрела энергетического оружия.; c ЧД-транком В 50% случаев" }, 25 | {"key":"ArtDefToEnergy","value":"Урон от энергетического оружия увеличивается на 10%, 22.5%, 35%, 47.5%, 60% (в зависимости от количества энергетических орудий, от 5 до 1). ГЗП - 50%; c ЧД-эн. Оружием бонус в 1.5 раза выше, с ЧД-ГЗП - ГЗП -26%" }, 26 | {"key":"ArtDefToArms1","value":"+ орудийная турель -10% генератор защиты; c ЧД-ГЗП штраф отменяется" }, 27 | {"key":"ArtEnergyPulse","value":"Выстрел из энергетического оружия с вероятностью 30% усиливается на 30%.; c ЧД-эн. оружием 50%" }, 28 | {"key":"ArtMissileDef","value":"Блокирует 10%-40% урона от попадания ракетного оружия. Позволяет Уничтожть ракеты игрока; c ЧД-транком 20%-80%" }, 29 | {"key":"ArtWeaponToSpeed","value":"+100 к скорости корабля -орудийная турель; c ЧД-двигателем +200, c ЧД-транком - без штрафа" }, 30 | {"key":"ArtBlackHole","value":"позволяет однократно создать ЧД" }, 31 | {"key":"ArtTransmitter","value":"Вызывает доминаторов в систему. От силы сигнала зависит количество доминаторв. Достаточно высокий заряд, позволяет вызвать все 3 серии: Келлероиды>Терроноиды>Блазероиды. Доминаторы прилетят из ближайших систем к данной. Вызывает лучевую болезнь" }, 32 | {"key":"ArtPDTurret","value":"Уничтожает ракеты, торпеды, клигов и штипов в радиусе 150 ед (до 5 за ход); c ЧД-Радаром радиус 300" } 33 | ] -------------------------------------------------------------------------------- /bonus_descriptions_hulls.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "Быстрый:1", 4 | "value": "speed +100" 5 | }, 6 | { 7 | "key": "Быстрый:2", 8 | "value": "speed +150" 9 | }, 10 | { 11 | "key": "Быстрый:3", 12 | "value": "speed +200" 13 | }, 14 | { 15 | "key": "Быстрый:4", 16 | "value": "speed +150" 17 | }, 18 | { 19 | "key": "Неуязвимый:1", 20 | "value": "defence +3" 21 | }, 22 | { 23 | "key": "Неуязвимый:2", 24 | "value": "defence +6" 25 | }, 26 | { 27 | "key": "Неуязвимый:3", 28 | "value": "defence +9" 29 | }, 30 | { 31 | "key": "Неуязвимый:4", 32 | "value": "defence +6" 33 | }, 34 | { 35 | "key": "Ремонтный:1", 36 | "value": "droid +10" 37 | }, 38 | { 39 | "key": "Ремонтный:2", 40 | "value": "droid +25" 41 | }, 42 | { 43 | "key": "Ремонтный:3", 44 | "value": "droid +40" 45 | }, 46 | { 47 | "key": "Ремонтный:4", 48 | "value": "droid +25" 49 | }, 50 | { 51 | "key": "Миоплазменный:1", 52 | "value": "energetic dmg +4, splinter dmg +8, speed -20" 53 | }, 54 | { 55 | "key": "Миоплазменный:2", 56 | "value": "energetic dmg +7, splinter dmg +12, speed -40" 57 | }, 58 | { 59 | "key": "Миоплазменный:3", 60 | "value": "energetic dmg +10, splinter dmg +20, speed -60" 61 | }, 62 | { 63 | "key": "Миоплазменный:4", 64 | "value": "energetic dmg +7, splinter dmg +12, speed -40" 65 | }, 66 | { 67 | "key": "Пигамарный:1", 68 | "value": "rocket dmg +5, defence -3, radar -200" 69 | }, 70 | { 71 | "key": "Пигамарный:2", 72 | "value": "rocket dmg +10, defence -5, radar -300" 73 | }, 74 | { 75 | "key": "Пигамарный:3", 76 | "value": "rocket dmg +15, defence -7, radar -500" 77 | }, 78 | { 79 | "key": "Пигамарный:4", 80 | "value": "rocket dmg +10, defence -5, radar -300" 81 | }, 82 | { 83 | "key": "Броненосец:1", 84 | "value": "energetic dmg +2, splinter dmg +1, defence +3, speed -50, manoeuvrability -2" 85 | }, 86 | { 87 | "key": "Броненосец:2", 88 | "value": "energetic dmg +4, splinter dmg +3, defence +4, speed -75, manoeuvrability -2" 89 | }, 90 | { 91 | "key": "Броненосец:3", 92 | "value": "energetic dmg +6, splinter dmg +5, defence +6, speed -100, manoeuvrability -2" 93 | }, 94 | { 95 | "key": "Броненосец:4", 96 | "value": "energetic dmg +4, splinter dmg +3, defence +4, speed -75, manoeuvrability -2" 97 | }, 98 | { 99 | "key": "Честный:1", 100 | "value": "jump +3, hook +10, mass -10%, trade -3" 101 | }, 102 | { 103 | "key": "Честный:2", 104 | "value": "jump +5, hook +20, mass -20%, trade -3" 105 | }, 106 | { 107 | "key": "Честный:3", 108 | "value": "jump +7, hook +30, mass -30%, trade -3" 109 | }, 110 | { 111 | "key": "Честный:4", 112 | "value": "jump +5, hook +20, mass -20%, trade -3" 113 | }, 114 | { 115 | "key": "Добрый:1", 116 | "value": "energetic dmg +5, splinter dmg +4, rocket dmg +2" 117 | }, 118 | { 119 | "key": "Добрый:2", 120 | "value": "energetic dmg +6, splinter dmg +5, rocket dmg +3" 121 | }, 122 | { 123 | "key": "Добрый:3", 124 | "value": "energetic dmg +7, splinter dmg +6, rocket dmg +4" 125 | }, 126 | { 127 | "key": "Добрый:4", 128 | "value": "energetic dmg +6, splinter dmg +5, rocket dmg +3" 129 | }, 130 | { 131 | "key": "Мирный:1", 132 | "value": "armor +1, defence +3, atack -3, technics -3" 133 | }, 134 | { 135 | "key": "Мирный:2", 136 | "value": "armor +2, defence +6, atack -3, technics -3" 137 | }, 138 | { 139 | "key": "Мирный:3", 140 | "value": "armor +3, defence +9, atack -3, technics -3" 141 | }, 142 | { 143 | "key": "Мирный:4", 144 | "value": "armor +2, defence +6, atack -3, technics -3" 145 | } 146 | , 147 | { 148 | "key": "Fast:1", 149 | "value": "speed +100" 150 | }, 151 | { 152 | "key": "Fast:2", 153 | "value": "speed +150" 154 | }, 155 | { 156 | "key": "Fast:3", 157 | "value": "speed +200" 158 | }, 159 | { 160 | "key": "Fast:4", 161 | "value": "speed +150" 162 | }, 163 | { 164 | "key": "Invincible:1", 165 | "value": "defence +3" 166 | }, 167 | { 168 | "key": "Invincible:2", 169 | "value": "defence +6" 170 | }, 171 | { 172 | "key": "Invincible:3", 173 | "value": "defence +9" 174 | }, 175 | { 176 | "key": "Invincible:4", 177 | "value": "defence +6" 178 | }, 179 | { 180 | "key": "Repair:1", 181 | "value": "droid +10" 182 | }, 183 | { 184 | "key": "Repair:2", 185 | "value": "droid +25" 186 | }, 187 | { 188 | "key": "Repair:3", 189 | "value": "droid +40" 190 | }, 191 | { 192 | "key": "Repair:4", 193 | "value": "droid +25" 194 | }, 195 | { 196 | "key": "Myoplasmic:1", 197 | "value": "energetic dmg +4, splinter dmg +8, speed -20" 198 | }, 199 | { 200 | "key": "Myoplasmic:2", 201 | "value": "energetic dmg +7, splinter dmg +12, speed -40" 202 | }, 203 | { 204 | "key": "Myoplasmic:3", 205 | "value": "energetic dmg +10, splinter dmg +20, speed -60" 206 | }, 207 | { 208 | "key": "Myoplasmic:4", 209 | "value": "energetic dmg +7, splinter dmg +12, speed -40" 210 | }, 211 | { 212 | "key": "Pygamore:1", 213 | "value": "rocket dmg +5, defence -3, radar -200" 214 | }, 215 | { 216 | "key": "Pygamore:2", 217 | "value": "rocket dmg +10, defence -5, radar -300" 218 | }, 219 | { 220 | "key": "Pygamore:3", 221 | "value": "rocket dmg +15, defence -7, radar -500" 222 | }, 223 | { 224 | "key": "Pygamore:4", 225 | "value": "rocket dmg +10, defence -5, radar -300" 226 | }, 227 | { 228 | "key": "Ironclad:1", 229 | "value": "energetic dmg +2, splinter dmg +1, defence +3, speed -50, manoeuvrability -2" 230 | }, 231 | { 232 | "key": "Ironclad:2", 233 | "value": "energetic dmg +4, splinter dmg +3, defence +4, speed -75, manoeuvrability -2" 234 | }, 235 | { 236 | "key": "Ironclad:3", 237 | "value": "energetic dmg +6, splinter dmg +5, defence +6, speed -100, manoeuvrability -2" 238 | }, 239 | { 240 | "key": "Ironclad:4", 241 | "value": "energetic dmg +4, splinter dmg +3, defence +4, speed -75, manoeuvrability -2" 242 | }, 243 | { 244 | "key": "Conscientious:1", 245 | "value": "jump +3, hook +10, mass -10%, trade -3" 246 | }, 247 | { 248 | "key": "Conscientious:2", 249 | "value": "jump +5, hook +20, mass -20%, trade -3" 250 | }, 251 | { 252 | "key": "Conscientious:3", 253 | "value": "jump +7, hook +30, mass -30%, trade -3" 254 | }, 255 | { 256 | "key": "Conscientious:4", 257 | "value": "jump +5, hook +20, mass -20%, trade -3" 258 | }, 259 | { 260 | "key": "Kindhearted:1", 261 | "value": "energetic dmg +5, splinter dmg +4, rocket dmg +2" 262 | }, 263 | { 264 | "key": "Kindhearted:2", 265 | "value": "energetic dmg +6, splinter dmg +5, rocket dmg +3" 266 | }, 267 | { 268 | "key": "Kindhearted:3", 269 | "value": "energetic dmg +7, splinter dmg +6, rocket dmg +4" 270 | }, 271 | { 272 | "key": "Kindhearted:4", 273 | "value": "energetic dmg +6, splinter dmg +5, rocket dmg +3" 274 | }, 275 | { 276 | "key": "Peaceful:1", 277 | "value": "armor +1, defence +3, atack -3, technics -3" 278 | }, 279 | { 280 | "key": "Peaceful:2", 281 | "value": "armor +2, defence +6, atack -3, technics -3" 282 | }, 283 | { 284 | "key": "Peaceful:3", 285 | "value": "armor +3, defence +9, atack -3, technics -3" 286 | }, 287 | { 288 | "key": "Peaceful:4", 289 | "value": "armor +2, defence +6, atack -3, technics -3" 290 | } 291 | ] 292 | -------------------------------------------------------------------------------- /bonus_descriptions_hulls.json.en: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "key": "Fast:1", 4 | "value": "speed +100" 5 | }, 6 | { 7 | "key": "Fast:2", 8 | "value": "speed +150" 9 | }, 10 | { 11 | "key": "Fast:3", 12 | "value": "speed +200" 13 | }, 14 | { 15 | "key": "Fast:4", 16 | "value": "speed +150" 17 | }, 18 | { 19 | "key": "Invincible:1", 20 | "value": "defence +3" 21 | }, 22 | { 23 | "key": "Invincible:2", 24 | "value": "defence +6" 25 | }, 26 | { 27 | "key": "Invincible:3", 28 | "value": "defence +9" 29 | }, 30 | { 31 | "key": "Invincible:4", 32 | "value": "defence +6" 33 | }, 34 | { 35 | "key": "Repair:1", 36 | "value": "droid +10" 37 | }, 38 | { 39 | "key": "Repair:2", 40 | "value": "droid +25" 41 | }, 42 | { 43 | "key": "Repair:3", 44 | "value": "droid +40" 45 | }, 46 | { 47 | "key": "Repair:4", 48 | "value": "droid +25" 49 | }, 50 | { 51 | "key": "Myoplasmic:1", 52 | "value": "energetic dmg +4, splinter dmg +8, speed -20" 53 | }, 54 | { 55 | "key": "Myoplasmic:2", 56 | "value": "energetic dmg +7, splinter dmg +12, speed -40" 57 | }, 58 | { 59 | "key": "Myoplasmic:3", 60 | "value": "energetic dmg +10, splinter dmg +20, speed -60" 61 | }, 62 | { 63 | "key": "Myoplasmic:4", 64 | "value": "energetic dmg +7, splinter dmg +12, speed -40" 65 | }, 66 | { 67 | "key": "Pygamore:1", 68 | "value": "rocket dmg +5, defence -3, radar -200" 69 | }, 70 | { 71 | "key": "Pygamore:2", 72 | "value": "rocket dmg +10, defence -5, radar -300" 73 | }, 74 | { 75 | "key": "Pygamore:3", 76 | "value": "rocket dmg +15, defence -7, radar -500" 77 | }, 78 | { 79 | "key": "Pygamore:4", 80 | "value": "rocket dmg +10, defence -5, radar -300" 81 | }, 82 | { 83 | "key": "Ironclad:1", 84 | "value": "energetic dmg +2, splinter dmg +1, defence +3, speed -50, manoeuvrability -2" 85 | }, 86 | { 87 | "key": "Ironclad:2", 88 | "value": "energetic dmg +4, splinter dmg +3, defence +4, speed -75, manoeuvrability -2" 89 | }, 90 | { 91 | "key": "Ironclad:3", 92 | "value": "energetic dmg +6, splinter dmg +5, defence +6, speed -100, manoeuvrability -2" 93 | }, 94 | { 95 | "key": "Ironclad:4", 96 | "value": "energetic dmg +4, splinter dmg +3, defence +4, speed -75, manoeuvrability -2" 97 | }, 98 | { 99 | "key": "Conscientious:1", 100 | "value": "jump +3, hook +10, mass -10%, trade -3" 101 | }, 102 | { 103 | "key": "Conscientious:2", 104 | "value": "jump +5, hook +20, mass -20%, trade -3" 105 | }, 106 | { 107 | "key": "Conscientious:3", 108 | "value": "jump +7, hook +30, mass -30%, trade -3" 109 | }, 110 | { 111 | "key": "Conscientious:4", 112 | "value": "jump +5, hook +20, mass -20%, trade -3" 113 | }, 114 | { 115 | "key": "Kindhearted:1", 116 | "value": "energetic dmg +5, splinter dmg +4, rocket dmg +2" 117 | }, 118 | { 119 | "key": "Kindhearted:2", 120 | "value": "energetic dmg +6, splinter dmg +5, rocket dmg +3" 121 | }, 122 | { 123 | "key": "Kindhearted:3", 124 | "value": "energetic dmg +7, splinter dmg +6, rocket dmg +4" 125 | }, 126 | { 127 | "key": "Kindhearted:4", 128 | "value": "energetic dmg +6, splinter dmg +5, rocket dmg +3" 129 | }, 130 | { 131 | "key": "Peaceful:1", 132 | "value": "armor +1, defence +3, atack -3, technics -3" 133 | }, 134 | { 135 | "key": "Peaceful:2", 136 | "value": "armor +2, defence +6, atack -3, technics -3" 137 | }, 138 | { 139 | "key": "Peaceful:3", 140 | "value": "armor +3, defence +9, atack -3, technics -3" 141 | }, 142 | { 143 | "key": "Peaceful:4", 144 | "value": "armor +2, defence +6, atack -3, technics -3" 145 | } 146 | ] 147 | -------------------------------------------------------------------------------- /bonus_descriptions_micromodules.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "key": "Антент", "value": "III: радар +210 ед. сканер +2 ед (100%, все)" }, 3 | { "key": "Аппер", "value": "III: двигатель +20 ед. радар +400 ед. (80%, все)" }, 4 | { "key": "Берсерк", "value": "III: сила оружия +5 ед. дальность оружия +20 ед. размер +30% (90%, все)" }, 5 | { "key": "Боттер", "value": "III: дроид +5 ед. (100%, Фэяне)" }, 6 | { "key": "Бронд", "value": "III: броня +2 ед. гзп +3 ед (100%, все)" }, 7 | { "key": "Вихрь", "value": "III: двигатель +30 ед. прыжок +3 ед. (90%, Люди)" }, 8 | { "key": "Громодрын", "value": "III: дроид +15 ед. стоимость: -50% (70%, Малоки Пеленги)" }, 9 | { "key": "Гугаал", "value": "III: цена: +25%двигатель +60 ед. (75%, Гаальцы)" }, 10 | { "key": "Дальномет", "value": "III: дальность оружия +25 ед. (100%, все)" }, 11 | { "key": "Дальстар", "value": "III: прыжок +8 ед. дальность оружия +30 ед. (70%, Пеленги)" }, 12 | { "key": "Дроннер", "value": "III: дроид +20 ед. размер: +50% (70%, все)" }, 13 | { "key": "Интердизайн", "value": "III: размер корпуса: +7% (70%, все)" }, 14 | { "key": "Клейн", "value": "III: энергетическое +7 ед. осколочное +15 ед. ракетное +10 ед. дальность оружия -20 ед. (75%, все)" }, 15 | { "key": "Миниразмерный", "value": "III: размер: -20%стоимость: -30% (70%, Люди)" }, 16 | { "key": "Пакстон", "value": "III: гзп -1 ед. размер: -75% (80%, Малоки)" }, 17 | { "key": "Патч 0.96 альфа", "value": "III: двигатель +25 ед. радар +250 ед. сканер +2 ед. дроид +4 ед. дальность оружия +30 ед. (70%, все)" }, 18 | { "key": "Платинос", "value": "III: стоимость: +20% (70%, все)" }, 19 | { "key": "Поточный", "value": "III: сканер +3 ед. (100%, все)" }, 20 | { "key": "Ракетон", "value": "III: энергетическое +4 ед. ракетное +10 ед. (100%, все)" }, 21 | { "key": "Ресиз", "value": "III: бак +10 ед. размер: +20% (100%, все)" }, 22 | { "key": "Стаксер", "value": "III: надежность: +67% прыжок +3 ед. (70%, Малоки Пеленги Люди Фэяне)" }, 23 | { "key": "Форсер", "value": "III: Встраивается в корпус. Активирует слоты сканера, радара и форсажа. (70%, все)" }, 24 | { "key": "Фэйджоуль", "value": "III: двигатель +25 ед. прыжок +8 ед. размер: +20% (70%, Фэяне)" }, 25 | { "key": "Цент", "value": "III: цена: -75% размер: +10% (80%, все)" }, 26 | { "key": "Шелест", "value": "III: гзп +3 ед. размер: +25% (70%, все)" }, 27 | { "key": "Электро", "value": "III: энергетическое +5 ед. (100%, все)" }, 28 | { "key": "Аддон", "value": "II: размер корпуса: +15% (40%, Малоки Люди Фэяне Гаальцы)" }, 29 | { "key": "Бронепакет", "value": "II: броня +4 ед. размер: -10% (60%, все)" }, 30 | { "key": "Гезават", "value": "II: Встраивается в корпус. Активирует слот генератора защитного поля и слот захвата. (31%, все)" }, 31 | { "key": "Горанд", "value": "II: надежность: +80% cтоимость: +30% (50%, все)" }, 32 | { "key": "Диамант", "value": "II: Встраивается в корпус. Активирует слот ремонтного дроида и слот захвата. (31%, все)" }, 33 | { "key": "Диощит", "value": "II: гзп +5 ед. ракетное +10 ед. (40%, Люди Фэяне)" }, 34 | { "key": "Дронз", "value": "II: дроид +20 ед. (крhd +20 ед). (50%, Малоки Пеленги)" }, 35 | { "key": "Импелган", "value": "II: сканер +7 ед. стоимость: +25% (40%, все)" }, 36 | { "key": "Интегратор", "value": "II: энергетическое +5 ед. осколочное +15 ед. ракетное +5 ед. размер: +25% (50%, все)" }, 37 | { "key": "Колебратор", "value": "II: радар +700 ед. захват +40 ед. гзп +3 ед. (60%, все)" }, 38 | { "key": "Конвектор", "value": "II: радар +1000 ед. сканер +6 ед. (55%, Люди)" }, 39 | { "key": "Магникум", "value": "II: захват +70 ед. дальность захвата +5 ед. (50%, все)" }, 40 | { "key": "Маформ", "value": "II: размер: +20% стоимость: +60% энергетическое +3 ед. осколочное +5 ед. ракетное +7 ед. (50%, Малоки)" }, 41 | { "key": "Микрострел", "value": "II: дальность прыжка: +10 ед. дальность стрельбы оружия: +50 ед. (65%, Люди Фэяне Гаальцы)" }, 42 | { "key": "Объемник", "value": "II: бак +20 ед. (60%, Пеленги Фэяне)" }, 43 | { "key": "Оптиматор", "value": "II: размер: -20% (40%, Пеленги)" }, 44 | { "key": "Парагон", "value": "II: захват +80 ед. размер: +10% стоимость: +20% (40%, Малоки Люди Фэяне Гаальцы)" }, 45 | { "key": "Патч 0.95 бета", "value": "II: двигатель +50 ед. радар +500 ед. сканер +3 ед. дроид +5 ед. дальность стрельбы оружия: +50 ед. (35%, Пеленги Люди Гаальцы)" }, 46 | { "key": "Раструг", "value": "II: Встраивается в корпус. Активирует слот ремонтного дроида и слот генератора защитного поля. (31%, все)" }, 47 | { "key": "Сдвиг", "value": "II: дальность прыжка: +14 ед. (50%, Пеленги Люди)" }, 48 | { "key": "Сжим", "value": "II: размер: -40% (65%, Фэяне)" }, 49 | { "key": "Спаай", "value": "II: радар +1500 ед. сканер +10 ед. (крhd +10 ед). (50%, Гаальцы)" }, 50 | { "key": "Сплинтер", "value": "II: осколочное оружие: +10 ед. (60%, Малоки Пеленги)" }, 51 | { "key": "Стоплай", "value": "II: размер: -30% стоимость: +50% (50%, все)" }, 52 | { "key": "Стратер", "value": "II: двигатель +100 ед. (крhd +100 ед). (50%, Малоки)" }, 53 | { "key": "Тюринг", "value": "II: оружие -5 ед. дальность стрельбы оружия: -10 ед. размер: -50% (55%, все)" }, 54 | { "key": "Эксплодер", "value": "II: двигатель +150 ед. дальность прыжка: -7 ед. (35%, Пеленги Люди Фэяне Гаальцы)" }, 55 | { "key": "Энергос", "value": "II: энергетическое +7 ед. (60%, все)" }, 56 | { "key": "Эскалибур", "value": "II: энергетическое +15 ед. дальность оружия: +40 ед. (40%, Люди)" }, 57 | { "key": "Акринатор", "value": "I: бонусы акринового оборудования: +200% размер: +100% стоимость: +100% убирает негативные эффекты акринового оборудования (1 раз, все)" }, 58 | { "key": "Антифэй", "value": "I: ракетное +30 ед. (10%, Малоки Пеленги Люди Гаальцы)" }, 59 | { "key": "Армор", "value": "I: Встраивается в корпус. Активирует два слота для оружия. (10%, все)" }, 60 | { "key": "Бач", "value": "I: бак +35 ед. (10%, Люди Гаальцы)" }, 61 | { "key": "Броинг", "value": "I: броня +7 ед. гзп +8 ед. стоимость: +40% (5%, Пеленги)" }, 62 | { "key": "Винтарь", "value": "I: мощность осколочного оружия: +35 ед. цена: +50% (15%, Малоки Пеленги)" }, 63 | { "key": "Дальпун", "value": "I: дальность стрельбы оружия: +120 ед. размер: +35% (10%, Гаальцы)" }, 64 | { "key": "Двима", "value": "I: двигатель +180 ед. дальность прыжка: +20 ед. (10%, Малоки)" }, 65 | { "key": "Джампгейтор 3.11", "value": "I: дальность прыжка: +20 ед. стоимость: +40% (20%, все)" }, 66 | { "key": "Джейк", "value": "I: двигатель +140 ед. (20%, все)" }, 67 | { "key": "Жампа", "value": "I: дальность прыжка: +14 ед. размер: +20% (20%, все)" }, 68 | { "key": "Жжения", "value": "I: энергетическое +20 ед. осколочное +40 ед. ракетное +30 ед. (10%, Пеленги Гаальцы)" }, 69 | { "key": "Иикебанит", "value": "I: стоимость: +150% (5%, Гаальцы)" }, 70 | { "key": "Крепчак", "value": "I: броня +6 ед. (30%, Пеленги Люди)" }, 71 | { "key": "Ламбалд", "value": "I: надежность: +120% (1%, все)" }, 72 | { "key": "Микроразмерный", "value": "I: размер: -30% (10%, Малоки Пеленги Люди Фэяне)" }, 73 | { "key": "Минивизион", "value": "I: радар +1500 ед. размер: -15% (20%, все)" }, 74 | { "key": "Панцирь", "value": "I: броня +8 ед. (1%, Малоки)" }, 75 | { "key": "Перфорит", "value": "I: Встраивается в корпус. Активирует два слота для артефактов. (10%, все)" }, 76 | { "key": "Прозотор", "value": "I: Встраивается в корпус. Активирует один слот для оружия и один слот для артефакта. (10%, все)" }, 77 | { "key": "Редуза", "value": "I: двигатель +140 ед. (5%, Пеленги)" }, 78 | { "key": "Универс", "value": "I: броня +5 ед. бак +15 ед. двигатель +70 ед. радар +800 ед. сканер +6 ед. дроид +30 ед. осколочное +30 ед. ракетное +20 ед. захват +60 ед. гзп +6 ед. энергетическое +20 ед. (1%, все)" }, 79 | { "key": "Хаб", "value": "I: размер корпуса: +25% (3%, Люди Фэяне)" }, 80 | { "key": "Хокус", "value": "I: захват +150 ед. дальность захвата -10 ед. (20%, все)" }, 81 | { "key": "Экстример", "value": "I: размер: +20% стоимость: +60% (20%, Малоки)" } 82 | , 83 | { "key": "Antent", "value": "III: радар +210 ед. сканер +2 ед (100%, все)" }, 84 | { "key": "Upper", "value": "III: двигатель +20 ед. радар +400 ед. (80%, все)" }, 85 | { "key": "Berserker", "value": "III: сила оружия +5 ед. дальность оружия +20 ед. размер +30% (90%, все)" }, 86 | { "key": "Botter", "value": "III: дроид +5 ед. (100%, Фэяне)" }, 87 | { "key": "Brond", "value": "III: броня +2 ед. гзп +3 ед (100%, все)" }, 88 | { "key": "Vortex", "value": "III: двигатель +30 ед. прыжок +3 ед. (90%, Люди)" }, 89 | { "key": "Massodrope", "value": "III: дроид +15 ед. стоимость: -50% (70%, Малоки Пеленги)" }, 90 | { "key": "Gugaal", "value": "III: цена: +25%двигатель +60 ед. (75%, Гаальцы)" }, 91 | { "key": "Farshooter", "value": "III: дальность оружия +25 ед. (100%, все)" }, 92 | { "key": "Dalstar", "value": "III: прыжок +8 ед. дальность оружия +30 ед. (70%, Пеленги)" }, 93 | { "key": "Dronner", "value": "III: дроид +20 ед. размер: +50% (70%, все)" }, 94 | { "key": "Interdesign", "value": "III: размер корпуса: +7% (70%, все)" }, 95 | { "key": "Klein", "value": "III: энергетическое +7 ед. осколочное +15 ед. ракетное +10 ед. дальность оружия -20 ед. (75%, все)" }, 96 | { "key": "Minisized", "value": "III: размер: -20%стоимость: -30% (70%, Люди)" }, 97 | { "key": "Paxton", "value": "III: гзп -1 ед. размер: -75% (80%, Малоки)" }, 98 | { "key": "Patch 0.96 alpha", "value": "III: двигатель +25 ед. радар +250 ед. сканер +2 ед. дроид +4 ед. дальность оружия +30 ед. (70%, все)" }, 99 | { "key": "Platicoat", "value": "III: стоимость: +20% (70%, все)" }, 100 | { "key": "Inliner", "value": "III: сканер +3 ед. (100%, все)" }, 101 | { "key": "Rocketon", "value": "III: энергетическое +4 ед. ракетное +10 ед. (100%, все)" }, 102 | { "key": "Resizer", "value": "III: бак +10 ед. размер: +20% (100%, все)" }, 103 | { "key": "Staxer", "value": "III: надежность: +67% прыжок +3 ед. (70%, Малоки Пеленги Люди Фэяне)" }, 104 | { "key": "Forcer", "value": "III: Встраивается в корпус. Активирует слоты сканера, радара и форсажа. (70%, все)" }, 105 | { "key": "Faejoel", "value": "III: двигатель +25 ед. прыжок +8 ед. размер: +20% (70%, Фэяне)" }, 106 | { "key": "Cent", "value": "III: цена: -75% размер: +10% (80%, все)" }, 107 | { "key": "Rustle", "value": "III: гзп +3 ед. размер: +25% (70%, все)" }, 108 | { "key": "Electro", "value": "III: энергетическое +5 ед. (100%, все)" }, 109 | { "key": "Addon", "value": "II: размер корпуса: +15% (40%, Малоки Люди Фэяне Гаальцы)" }, 110 | { "key": "Armorpack", "value": "II: броня +4 ед. размер: -10% (60%, все)" }, 111 | { "key": "Jeiad", "value": "II: Встраивается в корпус. Активирует слот генератора защитного поля и слот захвата. (31%, все)" }, 112 | { "key": "Gorand", "value": "II: надежность: +80% cтоимость: +30% (50%, все)" }, 113 | { "key": "Diamant", "value": "II: Встраивается в корпус. Активирует слот ремонтного дроида и слот захвата. (31%, все)" }, 114 | { "key": "Dioshield", "value": "II: гзп +5 ед. ракетное +10 ед. (40%, Люди Фэяне)" }, 115 | { "key": "Dronze", "value": "II: дроид +20 ед. (крhd +20 ед). (50%, Малоки Пеленги)" }, 116 | { "key": "Impalegun", "value": "II: сканер +7 ед. стоимость: +25% (40%, все)" }, 117 | { "key": "Integrator", "value": "II: энергетическое +5 ед. осколочное +15 ед. ракетное +5 ед. размер: +25% (50%, все)" }, 118 | { "key": "Colebrator", "value": "II: радар +700 ед. захват +40 ед. гзп +3 ед. (60%, все)" }, 119 | { "key": "Convector", "value": "II: радар +1000 ед. сканер +6 ед. (55%, Люди)" }, 120 | { "key": "Magnicum", "value": "II: захват +70 ед. дальность захвата +5 ед. (50%, все)" }, 121 | { "key": "Maform", "value": "II: размер: +20% стоимость: +60% энергетическое +3 ед. осколочное +5 ед. ракетное +7 ед. (50%, Малоки)" }, 122 | { "key": "Microshooter", "value": "II: дальность прыжка: +10 ед. дальность стрельбы оружия: +50 ед. (65%, Люди Фэяне Гаальцы)" }, 123 | { "key": "Volumer", "value": "II: бак +20 ед. (60%, Пеленги Фэяне)" }, 124 | { "key": "Optimator", "value": "II: размер: -20% (40%, Пеленги)" }, 125 | { "key": "Paragon", "value": "II: захват +80 ед. размер: +10% стоимость: +20% (40%, Малоки Люди Фэяне Гаальцы)" }, 126 | { "key": "Patch 0.95 beta", "value": "II: двигатель +50 ед. радар +500 ед. сканер +3 ед. дроид +5 ед. дальность стрельбы оружия: +50 ед. (35%, Пеленги Люди Гаальцы)" }, 127 | { "key": "Rasta", "value": "II: Встраивается в корпус. Активирует слот ремонтного дроида и слот генератора защитного поля. (31%, все)" }, 128 | { "key": "Displacement", "value": "II: дальность прыжка: +14 ед. (50%, Пеленги Люди)" }, 129 | { "key": "Clip", "value": "II: размер: -40% (65%, Фэяне)" }, 130 | { "key": "Insighter", "value": "II: радар +1500 ед. сканер +10 ед. (крhd +10 ед). (50%, Гаальцы)" }, 131 | { "key": "Splinter", "value": "II: осколочное оружие: +10 ед. (60%, Малоки Пеленги)" }, 132 | { "key": "Stopbark", "value": "II: размер: -30% стоимость: +50% (50%, все)" }, 133 | { "key": "Strutter", "value": "II: двигатель +100 ед. (крhd +100 ед). (50%, Малоки)" }, 134 | { "key": "Turing", "value": "II: оружие -5 ед. дальность стрельбы оружия: -10 ед. размер: -50% (55%, все)" }, 135 | { "key": "Exploder", "value": "II: двигатель +150 ед. дальность прыжка: -7 ед. (35%, Пеленги Люди Фэяне Гаальцы)" }, 136 | { "key": "Energos", "value": "II: энергетическое +7 ед. (60%, все)" }, 137 | { "key": "Excalibur", "value": "II: энергетическое +15 ед. дальность оружия: +40 ед. (40%, Люди)" }, 138 | { "key": "Акринатор", "value": "I: бонусы акринового оборудования: +200% размер: +100% стоимость: +100% убирает негативные эффекты акринового оборудования (1 раз, все)" }, 139 | { "key": "Antifae", "value": "I: ракетное +30 ед. (10%, Малоки Пеленги Люди Гаальцы)" }, 140 | { "key": "Armorer", "value": "I: Встраивается в корпус. Активирует два слота для оружия. (10%, все)" }, 141 | { "key": "Dimin", "value": "I: бак +35 ед. (10%, Люди Гаальцы)" }, 142 | { "key": "Broing", "value": "I: броня +7 ед. гзп +8 ед. стоимость: +40% (5%, Пеленги)" }, 143 | { "key": "Threader", "value": "I: мощность осколочного оружия: +35 ед. цена: +50% (15%, Малоки Пеленги)" }, 144 | { "key": "Farsight", "value": "I: дальность стрельбы оружия: +120 ед. размер: +35% (10%, Гаальцы)" }, 145 | { "key": "Drover", "value": "I: двигатель +180 ед. дальность прыжка: +20 ед. (10%, Малоки)" }, 146 | { "key": "Jumpgator 3.11", "value": "I: дальность прыжка: +20 ед. стоимость: +40% (20%, все)" }, 147 | { "key": "Jake", "value": "I: двигатель +140 ед. (20%, все)" }, 148 | { "key": "Jumpa", "value": "I: дальность прыжка: +14 ед. размер: +20% (20%, все)" }, 149 | { "key": "Burnz", "value": "I: энергетическое +20 ед. осколочное +40 ед. ракетное +30 ед. (10%, Пеленги Гаальцы)" }, 150 | { "key": "Iikebaanite", "value": "I: стоимость: +150% (5%, Гаальцы)" }, 151 | { "key": "Harding", "value": "I: броня +6 ед. (30%, Пеленги Люди)" }, 152 | { "key": "Lambald", "value": "I: надежность: +120% (1%, все)" }, 153 | { "key": "Microsize", "value": "I: размер: -30% (10%, Малоки Пеленги Люди Фэяне)" }, 154 | { "key": "Minivision", "value": "I: радар +1500 ед. размер: -15% (20%, все)" }, 155 | { "key": "Shell", "value": "I: броня +8 ед. (1%, Малоки)" }, 156 | { "key": "Perforator", "value": "I: Встраивается в корпус. Активирует два слота для артефактов. (10%, все)" }, 157 | { "key": "Prozotor", "value": "I: Встраивается в корпус. Активирует один слот для оружия и один слот для артефакта. (10%, все)" }, 158 | { "key": "Redusa", "value": "I: двигатель +140 ед. (5%, Пеленги)" }, 159 | { "key": "Universe", "value": "I: броня +5 ед. бак +15 ед. двигатель +70 ед. радар +800 ед. сканер +6 ед. дроид +30 ед. осколочное +30 ед. ракетное +20 ед. захват +60 ед. гзп +6 ед. энергетическое +20 ед. (1%, все)" }, 160 | { "key": "Hub", "value": "I: размер корпуса: +25% (3%, Люди Фэяне)" }, 161 | { "key": "Hocus", "value": "I: захват +150 ед. дальность захвата -10 ед. (20%, все)" }, 162 | { "key": "Extremer", "value": "I: размер: +20% стоимость: +60% (20%, Малоки)" } 163 | ] -------------------------------------------------------------------------------- /bonus_descriptions_micromodules.json.ru: -------------------------------------------------------------------------------- 1 | [ 2 | { "key": "Антент", "value": "III: радар +210 ед. сканер +2 ед (100%, все)" }, 3 | { "key": "Аппер", "value": "III: двигатель +20 ед. радар +400 ед. (80%, все)" }, 4 | { "key": "Берсерк", "value": "III: сила оружия +5 ед. дальность оружия +20 ед. размер +30% (90%, все)" }, 5 | { "key": "Боттер", "value": "III: дроид +5 ед. (100%, Фэяне)" }, 6 | { "key": "Бронд", "value": "III: броня +2 ед. гзп +3 ед (100%, все)" }, 7 | { "key": "Вихрь", "value": "III: двигатель +30 ед. прыжок +3 ед. (90%, Люди)" }, 8 | { "key": "Громодрын", "value": "III: дроид +15 ед. стоимость: -50% (70%, Малоки Пеленги)" }, 9 | { "key": "Гугаал", "value": "III: цена: +25%двигатель +60 ед. (75%, Гаальцы)" }, 10 | { "key": "Дальномет", "value": "III: дальность оружия +25 ед. (100%, все)" }, 11 | { "key": "Дальстар", "value": "III: прыжок +8 ед. дальность оружия +30 ед. (70%, Пеленги)" }, 12 | { "key": "Дроннер", "value": "III: дроид +20 ед. размер: +50% (70%, все)" }, 13 | { "key": "Интердизайн", "value": "III: размер корпуса: +7% (70%, все)" }, 14 | { "key": "Клейн", "value": "III: энергетическое +7 ед. осколочное +15 ед. ракетное +10 ед. дальность оружия -20 ед. (75%, все)" }, 15 | { "key": "Миниразмерный", "value": "III: размер: -20%стоимость: -30% (70%, Люди)" }, 16 | { "key": "Пакстон", "value": "III: гзп -1 ед. размер: -75% (80%, Малоки)" }, 17 | { "key": "Патч 0.96 альфа", "value": "III: двигатель +25 ед. радар +250 ед. сканер +2 ед. дроид +4 ед. дальность оружия +30 ед. (70%, все)" }, 18 | { "key": "Платинос", "value": "III: стоимость: +20% (70%, все)" }, 19 | { "key": "Поточный", "value": "III: сканер +3 ед. (100%, все)" }, 20 | { "key": "Ракетон", "value": "III: энергетическое +4 ед. ракетное +10 ед. (100%, все)" }, 21 | { "key": "Ресиз", "value": "III: бак +10 ед. размер: +20% (100%, все)" }, 22 | { "key": "Стаксер", "value": "III: надежность: +67% прыжок +3 ед. (70%, Малоки Пеленги Люди Фэяне)" }, 23 | { "key": "Форсер", "value": "III: Встраивается в корпус. Активирует слоты сканера, радара и форсажа. (70%, все)" }, 24 | { "key": "Фэйджоуль", "value": "III: двигатель +25 ед. прыжок +8 ед. размер: +20% (70%, Фэяне)" }, 25 | { "key": "Цент", "value": "III: цена: -75% размер: +10% (80%, все)" }, 26 | { "key": "Шелест", "value": "III: гзп +3 ед. размер: +25% (70%, все)" }, 27 | { "key": "Электро", "value": "III: энергетическое +5 ед. (100%, все)" }, 28 | { "key": "Аддон", "value": "II: размер корпуса: +15% (40%, Малоки Люди Фэяне Гаальцы)" }, 29 | { "key": "Бронепакет", "value": "II: броня +4 ед. размер: -10% (60%, все)" }, 30 | { "key": "Гезават", "value": "II: Встраивается в корпус. Активирует слот генератора защитного поля и слот захвата. (31%, все)" }, 31 | { "key": "Горанд", "value": "II: надежность: +80% cтоимость: +30% (50%, все)" }, 32 | { "key": "Диамант", "value": "II: Встраивается в корпус. Активирует слот ремонтного дроида и слот захвата. (31%, все)" }, 33 | { "key": "Диощит", "value": "II: гзп +5 ед. ракетное +10 ед. (40%, Люди Фэяне)" }, 34 | { "key": "Дронз", "value": "II: дроид +20 ед. (крhd +20 ед). (50%, Малоки Пеленги)" }, 35 | { "key": "Импелган", "value": "II: сканер +7 ед. стоимость: +25% (40%, все)" }, 36 | { "key": "Интегратор", "value": "II: энергетическое +5 ед. осколочное +15 ед. ракетное +5 ед. размер: +25% (50%, все)" }, 37 | { "key": "Колебратор", "value": "II: радар +700 ед. захват +40 ед. гзп +3 ед. (60%, все)" }, 38 | { "key": "Конвектор", "value": "II: радар +1000 ед. сканер +6 ед. (55%, Люди)" }, 39 | { "key": "Магникум", "value": "II: захват +70 ед. дальность захвата +5 ед. (50%, все)" }, 40 | { "key": "Маформ", "value": "II: размер: +20% стоимость: +60% энергетическое +3 ед. осколочное +5 ед. ракетное +7 ед. (50%, Малоки)" }, 41 | { "key": "Микрострел", "value": "II: дальность прыжка: +10 ед. дальность стрельбы оружия: +50 ед. (65%, Люди Фэяне Гаальцы)" }, 42 | { "key": "Объемник", "value": "II: бак +20 ед. (60%, Пеленги Фэяне)" }, 43 | { "key": "Оптиматор", "value": "II: размер: -20% (40%, Пеленги)" }, 44 | { "key": "Парагон", "value": "II: захват +80 ед. размер: +10% стоимость: +20% (40%, Малоки Люди Фэяне Гаальцы)" }, 45 | { "key": "Патч 0.95 бета", "value": "II: двигатель +50 ед. радар +500 ед. сканер +3 ед. дроид +5 ед. дальность стрельбы оружия: +50 ед. (35%, Пеленги Люди Гаальцы)" }, 46 | { "key": "Раструг", "value": "II: Встраивается в корпус. Активирует слот ремонтного дроида и слот генератора защитного поля. (31%, все)" }, 47 | { "key": "Сдвиг", "value": "II: дальность прыжка: +14 ед. (50%, Пеленги Люди)" }, 48 | { "key": "Сжим", "value": "II: размер: -40% (65%, Фэяне)" }, 49 | { "key": "Спаай", "value": "II: радар +1500 ед. сканер +10 ед. (крhd +10 ед). (50%, Гаальцы)" }, 50 | { "key": "Сплинтер", "value": "II: осколочное оружие: +10 ед. (60%, Малоки Пеленги)" }, 51 | { "key": "Стоплай", "value": "II: размер: -30% стоимость: +50% (50%, все)" }, 52 | { "key": "Стратер", "value": "II: двигатель +100 ед. (крhd +100 ед). (50%, Малоки)" }, 53 | { "key": "Тюринг", "value": "II: оружие -5 ед. дальность стрельбы оружия: -10 ед. размер: -50% (55%, все)" }, 54 | { "key": "Эксплодер", "value": "II: двигатель +150 ед. дальность прыжка: -7 ед. (35%, Пеленги Люди Фэяне Гаальцы)" }, 55 | { "key": "Энергос", "value": "II: энергетическое +7 ед. (60%, все)" }, 56 | { "key": "Эскалибур", "value": "II: энергетическое +15 ед. дальность оружия: +40 ед. (40%, Люди)" }, 57 | { "key": "Акринатор", "value": "I: бонусы акринового оборудования: +200% размер: +100% стоимость: +100% убирает негативные эффекты акринового оборудования (1 раз, все)" }, 58 | { "key": "Антифэй", "value": "I: ракетное +30 ед. (10%, Малоки Пеленги Люди Гаальцы)" }, 59 | { "key": "Армор", "value": "I: Встраивается в корпус. Активирует два слота для оружия. (10%, все)" }, 60 | { "key": "Бач", "value": "I: бак +35 ед. (10%, Люди Гаальцы)" }, 61 | { "key": "Броинг", "value": "I: броня +7 ед. гзп +8 ед. стоимость: +40% (5%, Пеленги)" }, 62 | { "key": "Винтарь", "value": "I: мощность осколочного оружия: +35 ед. цена: +50% (15%, Малоки Пеленги)" }, 63 | { "key": "Дальпун", "value": "I: дальность стрельбы оружия: +120 ед. размер: +35% (10%, Гаальцы)" }, 64 | { "key": "Двима", "value": "I: двигатель +180 ед. дальность прыжка: +20 ед. (10%, Малоки)" }, 65 | { "key": "Джампгейтор 3.11", "value": "I: дальность прыжка: +20 ед. стоимость: +40% (20%, все)" }, 66 | { "key": "Джейк", "value": "I: двигатель +140 ед. (20%, все)" }, 67 | { "key": "Жампа", "value": "I: дальность прыжка: +14 ед. размер: +20% (20%, все)" }, 68 | { "key": "Жжения", "value": "I: энергетическое +20 ед. осколочное +40 ед. ракетное +30 ед. (10%, Пеленги Гаальцы)" }, 69 | { "key": "Иикебанит", "value": "I: стоимость: +150% (5%, Гаальцы)" }, 70 | { "key": "Крепчак", "value": "I: броня +6 ед. (30%, Пеленги Люди)" }, 71 | { "key": "Ламбалд", "value": "I: надежность: +120% (1%, все)" }, 72 | { "key": "Микроразмерный", "value": "I: размер: -30% (10%, Малоки Пеленги Люди Фэяне)" }, 73 | { "key": "Минивизион", "value": "I: радар +1500 ед. размер: -15% (20%, все)" }, 74 | { "key": "Панцирь", "value": "I: броня +8 ед. (1%, Малоки)" }, 75 | { "key": "Перфорит", "value": "I: Встраивается в корпус. Активирует два слота для артефактов. (10%, все)" }, 76 | { "key": "Прозотор", "value": "I: Встраивается в корпус. Активирует один слот для оружия и один слот для артефакта. (10%, все)" }, 77 | { "key": "Редуза", "value": "I: двигатель +140 ед. (5%, Пеленги)" }, 78 | { "key": "Универс", "value": "I: броня +5 ед. бак +15 ед. двигатель +70 ед. радар +800 ед. сканер +6 ед. дроид +30 ед. осколочное +30 ед. ракетное +20 ед. захват +60 ед. гзп +6 ед. энергетическое +20 ед. (1%, все)" }, 79 | { "key": "Хаб", "value": "I: размер корпуса: +25% (3%, Люди Фэяне)" }, 80 | { "key": "Хокус", "value": "I: захват +150 ед. дальность захвата -10 ед. (20%, все)" }, 81 | { "key": "Экстример", "value": "I: размер: +20% стоимость: +60% (20%, Малоки)" } 82 | ] -------------------------------------------------------------------------------- /descriptions.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/descriptions.xlsx -------------------------------------------------------------------------------- /dump2json.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | TAB=$'\t' 3 | sed -E -e 's:::g' \ 4 | -e 's///g' \ 5 | -e 's/"/\\"/g' \ 6 | -e 's/=/": "/g' \ 7 | -e 's/^\t*/&"/g' \ 8 | -e 's/\r//g' \ 9 | -e 's/$/",/' \ 10 | -e 's/ \^\{"/": {/g' \ 11 | -e 's/"\}"/}/g' \ 12 | -e 's/\{,/{/g' \ 13 | -e "\$a }" \ 14 | -e '1s;^;{ ;' \ 15 | $1 | tr '\n' '\f' | sed 's/,\(\f\t*\}\)/\1/g' | tr '\f' '\n' -------------------------------------------------------------------------------- /en-ru.txt: -------------------------------------------------------------------------------- 1 | Ultraalloy Ультрасплавный 2 | Transcendental Трансцендентальный 3 | Nanobrolite Нанобролитовый 4 | Pygamore Пигамарный 5 | Myoplasmic Миоплазменный 6 | Upgraded Апгрейтинговый 7 | Fast Быстрый 8 | Conscientious Честный 9 | Ironclad Броненосец 10 | Kindhearted Добрый 11 | Peaceful Мирный 12 | Repair Ремонтный 13 | Invincible Неуязвимый 14 | Dandy Молния 15 | -------------------------------------------------------------------------------- /galaxy_magnifying_glass.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/galaxy_magnifying_glass.ico -------------------------------------------------------------------------------- /icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | icons/view-refresh.svgz 4 | icons/document-open.svgz 5 | icons/help-about.svgz 6 | icons/galaxy_magnifying_glass.png 7 | icons/document-save-as.svgz 8 | icons/report.svg 9 | icons/go-next.svgz 10 | icons/go-previous.svgz 11 | icons/all_reports.svg 12 | 13 | 14 | -------------------------------------------------------------------------------- /icons/document-open.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/document-open.svgz -------------------------------------------------------------------------------- /icons/document-save-as.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/document-save-as.svgz -------------------------------------------------------------------------------- /icons/galaxy_magnifying_glass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/galaxy_magnifying_glass.png -------------------------------------------------------------------------------- /icons/go-next.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/go-next.svgz -------------------------------------------------------------------------------- /icons/go-previous.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/go-previous.svgz -------------------------------------------------------------------------------- /icons/help-about.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/help-about.svgz -------------------------------------------------------------------------------- /icons/view-refresh.svgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mdimura/SRHDDumpReader/a4022d0cf47208be75651473ed3b3f0789ec47f3/icons/view-refresh.svgz -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "MainWindow.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QApplication a(argc, argv); 10 | a.setApplicationVersion(APP_VERSION); 11 | QTranslator translator; 12 | translator.load("SRHDDumpReader_ru"); 13 | a.installTranslator(&translator); 14 | MainWindow w; 15 | #ifdef _WIN32 16 | RegisterHotKey((HWND)w.winId(), 100, 0, 0x76);//F7 17 | RegisterHotKey((HWND)w.winId(), 101, 0, 0x75);//F6 18 | QDir::setCurrent(QCoreApplication::applicationDirPath()); 19 | #endif 20 | std::cout<<"devicePixelRatio()="<devicePixelRatio()< bonus_descriptions.json.ru 11 | eval sed $CMD bonus_descriptions_hulls.json.en > bonus_descriptions_hulls.json.ru 12 | 13 | 14 | 15 | #micromodules 16 | CMD="" 17 | while read ln; do 18 | NAMERU=`echo "$ln" | awk -F$'\t' '{print $1}'` 19 | NAMEEN=`echo "$ln" | awk -F$'\t' '{print $2}'` 20 | CMD=$CMD" -e "\''s/'$NAMERU/$NAMEEN'/g'\' 21 | done < micromodules_ru-en.txt 22 | eval sed $CMD bonus_descriptions_micromodules.json.ru > bonus_descriptions_micromodules.json.en 23 | 24 | #fuse en and ru 25 | for f in bonus_descriptions.json bonus_descriptions_hulls.json bonus_descriptions_micromodules.json; do 26 | echo $f 27 | head -n -1 ${f}.ru > ${f} 28 | echo "," >> ${f} 29 | tail -n +2 ${f}.en >> ${f} 30 | done 31 | 32 | rm bonus_descriptions.json.ru bonus_descriptions_hulls.json.ru bonus_descriptions_micromodules.json.en 33 | #head -n -1 bonus_descriptions_micromodules_ru.json > bonus_descriptions_micromodules.json 34 | #echo "," >> bonus_descriptions_micromodules.json 35 | #tail -n +2 bonus_descriptions_micromodules_en.json >> bonus_descriptions_micromodules.json --------------------------------------------------------------------------------