Merge pull request #192 from GriffinRichards/pokefirered
Add pokefirered support
This commit is contained in:
commit
91f8db10a5
29 changed files with 1438 additions and 583 deletions
|
@ -7,15 +7,15 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1117</width>
|
||||
<height>747</height>
|
||||
<height>788</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>porymap</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
<item row="0" column="0">
|
||||
<widget class="QSplitter" name="splitter_main">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -512,7 +512,7 @@
|
|||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<widget class="QPushButton" name="pushButton_ChangeDimensions">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Change a map layout's width and height.</p></body></html></string>
|
||||
</property>
|
||||
|
@ -561,8 +561,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>469</width>
|
||||
<height>608</height>
|
||||
<width>545</width>
|
||||
<height>628</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
|
@ -736,305 +736,6 @@
|
|||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame_Tilesets">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_PrimaryTileset">
|
||||
<property name="text">
|
||||
<string>Primary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_PrimaryTileset">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Primary Tileset</p><p>Defines the first 0x200 metatiles available for the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_SecondaryTileset">
|
||||
<property name="text">
|
||||
<string>Secondary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_SecondaryTileset">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Secondary Tileset</p><p>Defines the second 0x200 metatiles available for the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QFrame" name="frame_currentMetatileSelection">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>92</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>92</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Selection</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QScrollArea" name="scrollArea_6">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>324</width>
|
||||
<height>77</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="graphicsView_currentMetatileSelection">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="interactive">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_17">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Border</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_16">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QGraphicsView" name="graphicsView_BorderMetatile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The border is a 2x2 metatile which is repeated outside of the map layout's boundary. Draw on this border area to modify it.</p></body></html></string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QScrollArea" name="scrollArea_2">
|
||||
<property name="sizePolicy">
|
||||
|
@ -1064,10 +765,10 @@
|
|||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<x>8</x>
|
||||
<y>0</y>
|
||||
<width>307</width>
|
||||
<height>362</height>
|
||||
<width>221</width>
|
||||
<height>324</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -1160,6 +861,309 @@
|
|||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QFrame" name="frame_currentMetatileSelection">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>92</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>92</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Selection</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_17">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QScrollArea" name="scrollArea_6">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>256</width>
|
||||
<height>74</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="graphicsView_currentMetatileSelection">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="interactive">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_17">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>110</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>110</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Border</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_16">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QScrollArea" name="scrollArea_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>231</width>
|
||||
<height>83</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_18">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGraphicsView" name="graphicsView_BorderMetatile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The border is a group of metatiles which are repeated outside of the map layout's boundary. Draw on this border area to modify it.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QSlider" name="horizontalSlider_MetatileZoom">
|
||||
<property name="minimum">
|
||||
|
@ -1176,6 +1180,64 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame_Tilesets">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_PrimaryTileset">
|
||||
<property name="text">
|
||||
<string>Primary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_PrimaryTileset">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Primary Tileset</p><p>Defines the first 0x200 metatiles available for the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_SecondaryTileset">
|
||||
<property name="text">
|
||||
<string>Secondary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_SecondaryTileset">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Secondary Tileset</p><p>Defines the second 0x200 metatiles available for the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_collision">
|
||||
|
@ -1344,8 +1406,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>381</width>
|
||||
<height>657</height>
|
||||
<width>371</width>
|
||||
<height>684</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
|
@ -1618,7 +1680,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>568</height>
|
||||
<height>575</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -2094,6 +2156,26 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_FloorNumber">
|
||||
<property name="text">
|
||||
<string>Floor Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_FloorNumber">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Floor number to be used for maps with elevators.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-128</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -2531,8 +2613,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>826</width>
|
||||
<height>557</height>
|
||||
<width>818</width>
|
||||
<height>574</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_14">
|
||||
|
@ -2796,7 +2878,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1117</width>
|
||||
<height>21</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Width">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
<string>Map Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -90,7 +90,7 @@
|
|||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Height">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
<string>Map Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -105,13 +105,47 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_BorderWidth">
|
||||
<property name="text">
|
||||
<string>Border Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_BorderWidth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width (in blocks) of the new map's border.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_BorderHeight">
|
||||
<property name="text">
|
||||
<string>Border Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_BorderHeight">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Height (in blocks) of the new map's border.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Primary_Tileset">
|
||||
<property name="text">
|
||||
<string>Primary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<item row="6" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Primary_Tileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The primary tileset for the new map.</p></body></html></string>
|
||||
|
@ -121,14 +155,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Secondary_Tileset">
|
||||
<property name="text">
|
||||
<string>Secondary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="7" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Secondary_Tileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The secondary tileset for the new map.</p></body></html></string>
|
||||
|
@ -138,14 +172,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Type">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<item row="8" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Type">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.</p></body></html></string>
|
||||
|
@ -155,14 +189,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Location">
|
||||
<property name="text">
|
||||
<string>Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<item row="9" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Location">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.</p></body></html></string>
|
||||
|
@ -172,14 +206,14 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Flyable">
|
||||
<property name="text">
|
||||
<string>Can Fly To</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Flyable">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Whether to add a heal location to the new map.</p></body></html></string>
|
||||
|
@ -189,48 +223,65 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Allow_Running">
|
||||
<property name="text">
|
||||
<string>Allow Running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Allow_Biking">
|
||||
<property name="text">
|
||||
<string>Allow Biking</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Allow_Escape_Rope">
|
||||
<property name="text">
|
||||
<string>Allow Escape Rope</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Running">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<item row="12" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Biking">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<item row="13" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Escape_Rope">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Floor_Number">
|
||||
<property name="text">
|
||||
<string>Floor Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_Floor_Number">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Floor number to be used for maps with elevators.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>272</width>
|
||||
<height>539</height>
|
||||
<height>625</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
|
@ -198,30 +198,31 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<item row="13" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_metatileLabel">
|
||||
<property name="text">
|
||||
<string>Metatile Label (Optional)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_metatileLabel"/>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_layerType">
|
||||
<property name="text">
|
||||
<string>Metatile Behavior</string>
|
||||
<string>Layer Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="NoScrollComboBox" name="comboBox_metatileBehaviors"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_encounterType">
|
||||
<property name="text">
|
||||
<string>Bottom/Top</string>
|
||||
<string>Encounter Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_terrainType">
|
||||
<property name="text">
|
||||
<string>Terrain Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -247,15 +248,15 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_BottomTop">
|
||||
<property name="text">
|
||||
<string>Layer Type</string>
|
||||
<string>Bottom/Top</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="comboBox_layerType"/>
|
||||
<item row="10" column="0">
|
||||
<widget class="QComboBox" name="comboBox_encounterType"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
|
@ -270,6 +271,38 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_metatileLabel"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="comboBox_layerType"/>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="3">
|
||||
<widget class="NoScrollComboBox" name="comboBox_metatileBehaviors" native="true"/>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="3">
|
||||
<widget class="QLabel" name="label_metatileBehavior">
|
||||
<property name="text">
|
||||
<string>Metatile Behavior</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QComboBox" name="comboBox_terrainType"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -377,8 +410,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>367</height>
|
||||
<width>384</width>
|
||||
<height>265</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
|
@ -394,19 +427,6 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
|
@ -420,16 +440,6 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGraphicsView" name="graphicsView_Tiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
|
@ -443,6 +453,29 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGraphicsView" name="graphicsView_Tiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
|
@ -471,7 +504,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>21</height>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
@ -572,6 +605,13 @@
|
|||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
@ -109,6 +109,8 @@ public:
|
|||
void setUsePoryScript(bool usePoryScript);
|
||||
bool getUsePoryScript();
|
||||
void setProjectDir(QString projectDir);
|
||||
void setUseCustomBorderSize(bool enable);
|
||||
bool getUseCustomBorderSize();
|
||||
protected:
|
||||
QString getConfigFilepath();
|
||||
void parseConfigKeyValue(QString key, QString value);
|
||||
|
@ -119,6 +121,7 @@ private:
|
|||
QString projectDir;
|
||||
bool useEncounterJson;
|
||||
bool usePoryScript;
|
||||
bool useCustomBorderSize;
|
||||
};
|
||||
|
||||
extern ProjectConfig projectConfig;
|
||||
|
|
|
@ -9,14 +9,17 @@ class HealLocation {
|
|||
|
||||
public:
|
||||
HealLocation()=default;
|
||||
HealLocation(QString, int, uint16_t, uint16_t);
|
||||
HealLocation(QString, QString, int, uint16_t, uint16_t, QString = "", uint16_t = 0);
|
||||
friend QDebug operator<<(QDebug debug, const HealLocation &hl);
|
||||
|
||||
public:
|
||||
QString name;
|
||||
QString idName;
|
||||
QString mapName;
|
||||
int index;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
QString respawnMap;
|
||||
uint16_t respawnNPC;
|
||||
static HealLocation fromEvent(Event*);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,9 +6,12 @@
|
|||
class HistoryItem {
|
||||
public:
|
||||
Blockdata *metatiles;
|
||||
Blockdata *border;
|
||||
int layoutWidth;
|
||||
int layoutHeight;
|
||||
HistoryItem(Blockdata *metatiles, int layoutWidth, int layoutHeight);
|
||||
int borderWidth;
|
||||
int borderHeight;
|
||||
HistoryItem(Blockdata *metatiles, Blockdata *border, int layoutWidth, int layoutHeight, int borderWidth, int borderHeight);
|
||||
~HistoryItem();
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
#include <QGraphicsPixmapItem>
|
||||
#include <math.h>
|
||||
|
||||
#define DEFAULT_BORDER_WIDTH 2
|
||||
#define DEFAULT_BORDER_HEIGHT 2
|
||||
|
||||
// Number of metatiles to draw out from edge of map. Could allow modification of this in the future.
|
||||
// porymap will reflect changes to it, but the value is hard-coded in the projects at the moment
|
||||
#define BORDER_DISTANCE 7
|
||||
|
||||
class Map : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -35,6 +42,7 @@ public:
|
|||
QString allowRunning;
|
||||
QString allowBiking;
|
||||
QString allowEscapeRope;
|
||||
int floorNumber;
|
||||
QString battle_scene;
|
||||
QString sharedEventsMap = "";
|
||||
QString sharedScriptsMap = "";
|
||||
|
@ -57,6 +65,8 @@ public:
|
|||
static QString bgEventsLabelFromName(QString mapName);
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
int getBorderWidth();
|
||||
int getBorderHeight();
|
||||
QPixmap render(bool ignoreCache, MapLayout * fromLayout = nullptr);
|
||||
QPixmap renderCollision(qreal opacity, bool ignoreCache);
|
||||
bool mapBlockChanged(int i, Blockdata * cache);
|
||||
|
@ -77,12 +87,14 @@ public:
|
|||
void addEvent(Event*);
|
||||
QPixmap renderConnection(MapConnection, MapLayout *);
|
||||
QPixmap renderBorder();
|
||||
void setDimensions(int newWidth, int newHeight, bool setNewBlockData = true);
|
||||
void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true);
|
||||
void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true);
|
||||
void cacheBorder();
|
||||
bool hasUnsavedChanges();
|
||||
|
||||
private:
|
||||
void setNewDimensionsBlockdata(int newWidth, int newHeight);
|
||||
void setNewBorderDimensionsBlockdata(int newWidth, int newHeight);
|
||||
|
||||
signals:
|
||||
void mapChanged(Map *map);
|
||||
|
|
|
@ -15,6 +15,8 @@ public:
|
|||
QString name;
|
||||
QString width;
|
||||
QString height;
|
||||
QString border_width;
|
||||
QString border_height;
|
||||
QString border_path;
|
||||
QString blockdata_path;
|
||||
QString tileset_primary_label;
|
||||
|
|
|
@ -11,8 +11,10 @@ public:
|
|||
Metatile();
|
||||
public:
|
||||
QList<Tile> *tiles = nullptr;
|
||||
uint8_t behavior;
|
||||
uint16_t behavior; // 8 bits RSE, 9 bits FRLG
|
||||
uint8_t layerType;
|
||||
uint8_t encounterType; // FRLG only
|
||||
uint8_t terrainType; // FRLG only
|
||||
QString label;
|
||||
|
||||
Metatile *copy();
|
||||
|
|
|
@ -147,6 +147,7 @@ private:
|
|||
void updateMirroredConnectionMap(MapConnection*, QString);
|
||||
void updateMirroredConnection(MapConnection*, QString, QString, bool isDelete = false);
|
||||
void updateEncounterFields(EncounterFields newFields);
|
||||
int getBorderDrawDistance(int dimension);
|
||||
Event* createNewObjectEvent();
|
||||
Event* createNewWarpEvent();
|
||||
Event* createNewHealLocationEvent();
|
||||
|
|
|
@ -68,6 +68,7 @@ private slots:
|
|||
void on_checkBox_AllowRunning_clicked(bool checked);
|
||||
void on_checkBox_AllowBiking_clicked(bool checked);
|
||||
void on_checkBox_AllowEscapeRope_clicked(bool checked);
|
||||
void on_spinBox_FloorNumber_valueChanged(int offset);
|
||||
|
||||
void on_tabWidget_currentChanged(int index);
|
||||
|
||||
|
@ -118,7 +119,7 @@ private slots:
|
|||
void on_comboBox_EmergeMap_currentTextChanged(const QString &mapName);
|
||||
void on_comboBox_PrimaryTileset_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_SecondaryTileset_currentTextChanged(const QString &arg1);
|
||||
void on_pushButton_clicked();
|
||||
void on_pushButton_ChangeDimensions_clicked();
|
||||
void on_checkBox_smartPaths_stateChanged(int selected);
|
||||
void on_checkBox_Visibility_clicked(bool checked);
|
||||
void on_checkBox_ToggleBorder_stateChanged(int arg1);
|
||||
|
@ -215,6 +216,7 @@ private:
|
|||
bool openRecentProject();
|
||||
void updateTilesetEditor();
|
||||
QString getEventGroupFromTabWidget(QWidget *tab);
|
||||
void closeSupplementaryWindows();
|
||||
|
||||
bool isProjectOpen();
|
||||
};
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
QStringList *coordEventWeatherNames = nullptr;
|
||||
QStringList *secretBaseIds = nullptr;
|
||||
QStringList *bgEventFacingDirections = nullptr;
|
||||
QStringList *trainerTypes = nullptr;
|
||||
QMap<QString, int> metatileBehaviorMap;
|
||||
QMap<int, QString> metatileBehaviorMapInverse;
|
||||
QMap<QString, QString> facingDirections;
|
||||
|
@ -127,6 +128,7 @@ public:
|
|||
void saveTilesetTilesImage(Tileset*);
|
||||
void saveTilesetPalettes(Tileset*, bool);
|
||||
|
||||
QString defaultSong;
|
||||
QStringList getSongNames();
|
||||
QStringList getVisibilities();
|
||||
QMap<QString, QStringList> getTilesetLabels();
|
||||
|
@ -143,6 +145,7 @@ public:
|
|||
bool readCoordEventWeatherNames();
|
||||
bool readSecretBaseIds();
|
||||
bool readBgEventFacingDirections();
|
||||
bool readTrainerTypes();
|
||||
bool readMetatileBehaviors();
|
||||
bool readHealLocations();
|
||||
bool readMiscellaneousConstants();
|
||||
|
|
|
@ -10,6 +10,14 @@ class NewEventToolButton : public QToolButton
|
|||
public:
|
||||
explicit NewEventToolButton(QWidget *parent = nullptr);
|
||||
QString getSelectedEventType();
|
||||
QAction *newObjectAction;
|
||||
QAction *newWarpAction;
|
||||
QAction *newHealLocationAction;
|
||||
QAction *newTriggerAction;
|
||||
QAction *newWeatherTriggerAction;
|
||||
QAction *newSignAction;
|
||||
QAction *newHiddenItemAction;
|
||||
QAction *newSecretBaseAction;
|
||||
public slots:
|
||||
void newObject();
|
||||
void newWarp();
|
||||
|
@ -23,14 +31,6 @@ signals:
|
|||
void newEventAdded(QString);
|
||||
private:
|
||||
QString selectedEventType;
|
||||
QAction *newObjectAction;
|
||||
QAction *newWarpAction;
|
||||
QAction *newHealLocationAction;
|
||||
QAction *newTriggerAction;
|
||||
QAction *newWeatherTriggerAction;
|
||||
QAction *newSignAction;
|
||||
QAction *newHiddenItemAction;
|
||||
QAction *newSecretBaseAction;
|
||||
void init();
|
||||
};
|
||||
|
||||
|
|
|
@ -77,6 +77,10 @@ private slots:
|
|||
|
||||
void on_comboBox_layerType_activated(int arg1);
|
||||
|
||||
void on_comboBox_encounterType_activated(int arg1);
|
||||
|
||||
void on_comboBox_terrainType_activated(int arg1);
|
||||
|
||||
void on_actionExport_Primary_Tiles_Image_triggered();
|
||||
|
||||
void on_actionExport_Secondary_Tiles_Image_triggered();
|
||||
|
|
|
@ -324,11 +324,13 @@ QString PorymapConfig::getTheme() {
|
|||
|
||||
const QMap<BaseGameVersion, QString> baseGameVersionMap = {
|
||||
{BaseGameVersion::pokeruby, "pokeruby"},
|
||||
{BaseGameVersion::pokefirered, "pokefirered"},
|
||||
{BaseGameVersion::pokeemerald, "pokeemerald"},
|
||||
};
|
||||
|
||||
const QMap<QString, BaseGameVersion> baseGameVersionReverseMap = {
|
||||
{"pokeruby", BaseGameVersion::pokeruby},
|
||||
{"pokefirered", BaseGameVersion::pokefirered},
|
||||
{"pokeemerald", BaseGameVersion::pokeemerald},
|
||||
};
|
||||
|
||||
|
@ -346,7 +348,7 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->baseGameVersion = baseGameVersionReverseMap.value(baseGameVersion);
|
||||
} else {
|
||||
this->baseGameVersion = BaseGameVersion::pokeemerald;
|
||||
logWarn(QString("Invalid config value for base_game_version: '%1'. Must be 'pokeruby' or 'pokeemerald'.").arg(value));
|
||||
logWarn(QString("Invalid config value for base_game_version: '%1'. Must be 'pokeruby', 'pokefirered' or 'pokeemerald'.").arg(value));
|
||||
}
|
||||
} else if (key == "use_encounter_json") {
|
||||
bool ok;
|
||||
|
@ -354,12 +356,18 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for use_encounter_json: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else if(key == "use_poryscript") {
|
||||
} else if (key == "use_poryscript") {
|
||||
bool ok;
|
||||
this->usePoryScript = value.toInt(&ok);
|
||||
if(!ok) {
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for use_poryscript: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else if (key == "use_custom_border_size") {
|
||||
bool ok;
|
||||
this->useCustomBorderSize = value.toInt(&ok);
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for use_custom_border_size: '%1'. Must be 0 or 1.").arg(value));
|
||||
}
|
||||
} else {
|
||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||
}
|
||||
|
@ -370,6 +378,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
|||
map.insert("base_game_version", baseGameVersionMap.value(this->baseGameVersion));
|
||||
map.insert("use_encounter_json", QString::number(this->useEncounterJson));
|
||||
map.insert("use_poryscript", QString::number(this->usePoryScript));
|
||||
map.insert("use_custom_border_size", QString::number(this->useCustomBorderSize));
|
||||
return map;
|
||||
}
|
||||
|
||||
|
@ -387,6 +396,7 @@ void ProjectConfig::onNewConfigFileCreated() {
|
|||
|
||||
QComboBox *baseGameVersionComboBox = new QComboBox();
|
||||
baseGameVersionComboBox->addItem("pokeruby", BaseGameVersion::pokeruby);
|
||||
baseGameVersionComboBox->addItem("pokefirered", BaseGameVersion::pokefirered);
|
||||
baseGameVersionComboBox->addItem("pokeemerald", BaseGameVersion::pokeemerald);
|
||||
form.addRow(new QLabel("Game Version"), baseGameVersionComboBox);
|
||||
|
||||
|
@ -398,6 +408,7 @@ void ProjectConfig::onNewConfigFileCreated() {
|
|||
this->baseGameVersion = static_cast<BaseGameVersion>(baseGameVersionComboBox->currentData().toInt());
|
||||
}
|
||||
}
|
||||
this->useCustomBorderSize = this->baseGameVersion == BaseGameVersion::pokefirered;
|
||||
this->useEncounterJson = true;
|
||||
this->usePoryScript = false;
|
||||
}
|
||||
|
@ -432,3 +443,12 @@ void ProjectConfig::setUsePoryScript(bool usePoryScript) {
|
|||
bool ProjectConfig::getUsePoryScript() {
|
||||
return this->usePoryScript;
|
||||
}
|
||||
|
||||
void ProjectConfig::setUseCustomBorderSize(bool enable) {
|
||||
this->useCustomBorderSize = enable;
|
||||
this->save();
|
||||
}
|
||||
|
||||
bool ProjectConfig::getUseCustomBorderSize() {
|
||||
return this->useCustomBorderSize;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "event.h"
|
||||
#include "map.h"
|
||||
#include "project.h"
|
||||
#include "config.h"
|
||||
|
||||
QString EventType::Object = "event_object";
|
||||
QString EventType::Warp = "event_warp";
|
||||
|
@ -58,6 +59,9 @@ Event* Event::createNewObjectEvent(Project *project)
|
|||
event->put("event_type", EventType::Object);
|
||||
event->put("sprite", project->getEventObjGfxConstants().keys().first());
|
||||
event->put("movement_type", project->movementTypes->first());
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
event->put("in_connection", false);
|
||||
}
|
||||
event->put("radius_x", 0);
|
||||
event->put("radius_y", 0);
|
||||
event->put("script_label", "NULL");
|
||||
|
@ -86,7 +90,12 @@ Event* Event::createNewHealLocationEvent(QString map_name)
|
|||
event->put("event_group_type", "heal_event_group");
|
||||
event->put("event_type", EventType::HealLocation);
|
||||
event->put("loc_name", QString(Map::mapConstantFromName(map_name)).remove(0,4));
|
||||
event->put("id_name", map_name.replace(QRegularExpression("([a-z])([A-Z])"), "\\1_\\2").toUpper());
|
||||
event->put("elevation", 3);
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
event->put("respawn_map", map_name);
|
||||
event->put("respawn_npc", 1);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
|
@ -131,6 +140,10 @@ Event* Event::createNewHiddenItemEvent(Project *project)
|
|||
event->put("item", project->itemNames->first());
|
||||
event->put("flag", project->flagNames->first());
|
||||
event->put("elevation", 3);
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
event->put("quantity", 1);
|
||||
event->put("underfoot", false);
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
|
@ -158,19 +171,36 @@ QMap<QString, bool> Event::getExpectedFields()
|
|||
{
|
||||
QString type = this->get("event_type");
|
||||
if (type == EventType::Object) {
|
||||
return QMap<QString, bool> {
|
||||
{"graphics_id", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"movement_type", true},
|
||||
{"movement_range_x", true},
|
||||
{"movement_range_y", true},
|
||||
{"trainer_type", true},
|
||||
{"trainer_sight_or_berry_tree_id", true},
|
||||
{"script", true},
|
||||
{"flag", true},
|
||||
};
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
return QMap<QString, bool> {
|
||||
{"graphics_id", true},
|
||||
{"in_connection", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"movement_type", true},
|
||||
{"movement_range_x", true},
|
||||
{"movement_range_y", true},
|
||||
{"trainer_type", true},
|
||||
{"trainer_sight_or_berry_tree_id", true},
|
||||
{"script", true},
|
||||
{"flag", true},
|
||||
};
|
||||
} else {
|
||||
return QMap<QString, bool> {
|
||||
{"graphics_id", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"movement_type", true},
|
||||
{"movement_range_x", true},
|
||||
{"movement_range_y", true},
|
||||
{"trainer_type", true},
|
||||
{"trainer_sight_or_berry_tree_id", true},
|
||||
{"script", true},
|
||||
{"flag", true},
|
||||
};
|
||||
}
|
||||
} else if (type == EventType::Warp) {
|
||||
return QMap<QString, bool> {
|
||||
{"x", true},
|
||||
|
@ -207,14 +237,27 @@ QMap<QString, bool> Event::getExpectedFields()
|
|||
{"script", true},
|
||||
};
|
||||
} else if (type == EventType::HiddenItem) {
|
||||
return QMap<QString, bool> {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"item", true},
|
||||
{"flag", true},
|
||||
};
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
return QMap<QString, bool> {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"item", true},
|
||||
{"flag", true},
|
||||
{"quantity", true},
|
||||
{"underfoot", true},
|
||||
};
|
||||
} else {
|
||||
return QMap<QString, bool> {
|
||||
{"type", true},
|
||||
{"x", true},
|
||||
{"y", true},
|
||||
{"elevation", true},
|
||||
{"item", true},
|
||||
{"flag", true},
|
||||
};
|
||||
}
|
||||
} else if (type == EventType::SecretBase) {
|
||||
return QMap<QString, bool> {
|
||||
{"type", true},
|
||||
|
@ -252,6 +295,9 @@ OrderedJson::object Event::buildObjectEventJSON()
|
|||
{
|
||||
OrderedJson::object eventObj;
|
||||
eventObj["graphics_id"] = this->get("sprite");
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
eventObj["in_connection"] = this->getInt("in_connection") > 0 || this->get("in_connection") == "TRUE";
|
||||
}
|
||||
eventObj["x"] = this->getU16("x");
|
||||
eventObj["y"] = this->getU16("y");
|
||||
eventObj["elevation"] = this->getInt("elevation");
|
||||
|
@ -331,6 +377,10 @@ OrderedJson::object Event::buildHiddenItemEventJSON()
|
|||
hiddenItemObj["elevation"] = this->getInt("elevation");
|
||||
hiddenItemObj["item"] = this->get("item");
|
||||
hiddenItemObj["flag"] = this->get("flag");
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
hiddenItemObj["quantity"] = this->getInt("quantity");
|
||||
hiddenItemObj["underfoot"] = this->getInt("underfoot") > 0 || this->get("underfoot") == "TRUE";
|
||||
}
|
||||
this->addCustomValuesTo(&hiddenItemObj);
|
||||
|
||||
return hiddenItemObj;
|
||||
|
|
|
@ -1,17 +1,23 @@
|
|||
#include "heallocation.h"
|
||||
#include "config.h"
|
||||
#include "map.h"
|
||||
|
||||
HealLocation::HealLocation(QString map, int i, uint16_t x, uint16_t y)
|
||||
HealLocation::HealLocation(QString id, QString map, int i, uint16_t x, uint16_t y, QString respawnMap, uint16_t respawnNPC)
|
||||
{
|
||||
this->name = map;
|
||||
this->idName = id;
|
||||
this->mapName = map;
|
||||
this->index = i;
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->respawnMap = respawnMap;
|
||||
this->respawnNPC = respawnNPC;
|
||||
}
|
||||
|
||||
HealLocation HealLocation::fromEvent(Event *event)
|
||||
{
|
||||
HealLocation hl;
|
||||
hl.name = event->get("loc_name");
|
||||
hl.idName = event->get("id_name");
|
||||
hl.mapName = event->get("loc_name");
|
||||
try {
|
||||
hl.index = event->get("index").toInt();
|
||||
}
|
||||
|
@ -20,11 +26,15 @@ HealLocation HealLocation::fromEvent(Event *event)
|
|||
}
|
||||
hl.x = event->getU16("x");
|
||||
hl.y = event->getU16("y");
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
hl.respawnNPC = event->getU16("respawn_npc");
|
||||
hl.respawnMap = Map::mapConstantFromName(event->get("respawn_map")).remove(0,4);
|
||||
}
|
||||
return hl;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const HealLocation &hl)
|
||||
{
|
||||
debug << "HealLocation_" + hl.name << "(" << hl.x << ',' << hl.y << ")";
|
||||
debug << "HealLocation_" + hl.mapName << "(" << hl.x << ',' << hl.y << ")";
|
||||
return debug;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
#include "historyitem.h"
|
||||
|
||||
HistoryItem::HistoryItem(Blockdata *metatiles, int layoutWidth, int layoutHeight) {
|
||||
HistoryItem::HistoryItem(Blockdata *metatiles, Blockdata *border, int layoutWidth, int layoutHeight, int borderWidth, int borderHeight) {
|
||||
this->metatiles = metatiles;
|
||||
this->border = border;
|
||||
this->layoutWidth = layoutWidth;
|
||||
this->layoutHeight = layoutHeight;
|
||||
this->borderWidth = borderWidth;
|
||||
this->borderHeight = borderHeight;
|
||||
}
|
||||
|
||||
HistoryItem::~HistoryItem() {
|
||||
if (this->metatiles) delete this->metatiles;
|
||||
if (this->border) delete this->border;
|
||||
}
|
||||
|
||||
RegionMapHistoryItem::RegionMapHistoryItem(int which, QVector<uint8_t> tiles, QString cityMap) {
|
||||
|
|
124
src/core/map.cpp
124
src/core/map.cpp
|
@ -59,6 +59,14 @@ int Map::getHeight() {
|
|||
return layout->height.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
int Map::getBorderWidth() {
|
||||
return layout->border_width.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
int Map::getBorderHeight() {
|
||||
return layout->border_height.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
bool Map::mapBlockChanged(int i, Blockdata * cache) {
|
||||
if (!cache)
|
||||
return true;
|
||||
|
@ -213,27 +221,33 @@ QPixmap Map::render(bool ignoreCache = false, MapLayout * fromLayout) {
|
|||
}
|
||||
|
||||
QPixmap Map::renderBorder() {
|
||||
bool changed_any = false;
|
||||
int width_ = 2;
|
||||
int height_ = 2;
|
||||
bool changed_any = false, border_resized = false;
|
||||
int width_ = getBorderWidth();
|
||||
int height_ = getBorderHeight();
|
||||
if (layout->border_image.isNull()) {
|
||||
layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
|
||||
changed_any = true;
|
||||
}
|
||||
if (layout->border_image.width() != width_ * 16 || layout->border_image.height() != height_ * 16) {
|
||||
layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
|
||||
border_resized = true;
|
||||
}
|
||||
if (!(layout->border && layout->border->blocks)) {
|
||||
layout->border_pixmap = layout->border_pixmap.fromImage(layout->border_image);
|
||||
return layout->border_pixmap;
|
||||
}
|
||||
QPainter painter(&layout->border_image);
|
||||
for (int i = 0; i < layout->border->blocks->length(); i++) {
|
||||
if (!borderBlockChanged(i, layout->cached_border)) {
|
||||
if (!border_resized && !borderBlockChanged(i, layout->cached_border)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
changed_any = true;
|
||||
Block block = layout->border->blocks->value(i);
|
||||
QImage metatile_image = getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
int map_y = i / width_;
|
||||
int map_x = i % width_;
|
||||
uint16_t tile = block.tile;
|
||||
QImage metatile_image = getMetatileImage(tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
int map_y = width_ ? i / width_ : 0;
|
||||
int map_x = width_ ? i % width_ : 0;
|
||||
painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image);
|
||||
}
|
||||
painter.end();
|
||||
|
@ -249,23 +263,23 @@ QPixmap Map::renderConnection(MapConnection connection, MapLayout * fromLayout)
|
|||
int x, y, w, h;
|
||||
if (connection.direction == "up") {
|
||||
x = 0;
|
||||
y = getHeight() - 6;
|
||||
y = getHeight() - BORDER_DISTANCE;
|
||||
w = getWidth();
|
||||
h = 6;
|
||||
h = BORDER_DISTANCE;
|
||||
} else if (connection.direction == "down") {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = getWidth();
|
||||
h = 6;
|
||||
h = BORDER_DISTANCE;
|
||||
} else if (connection.direction == "left") {
|
||||
x = getWidth() - 6;
|
||||
x = getWidth() - BORDER_DISTANCE;
|
||||
y = 0;
|
||||
w = 6;
|
||||
w = BORDER_DISTANCE;
|
||||
h = getHeight();
|
||||
} else if (connection.direction == "right") {
|
||||
x = 0;
|
||||
y = 0;
|
||||
w = 6;
|
||||
w = BORDER_DISTANCE;
|
||||
h = getHeight();
|
||||
} else {
|
||||
// this should not happen
|
||||
|
@ -298,6 +312,25 @@ void Map::setNewDimensionsBlockdata(int newWidth, int newHeight) {
|
|||
layout->blockdata->copyFrom(newBlockData);
|
||||
}
|
||||
|
||||
void Map::setNewBorderDimensionsBlockdata(int newWidth, int newHeight) {
|
||||
int oldWidth = getBorderWidth();
|
||||
int oldHeight = getBorderHeight();
|
||||
|
||||
Blockdata* newBlockData = new Blockdata;
|
||||
|
||||
for (int y = 0; y < newHeight; y++)
|
||||
for (int x = 0; x < newWidth; x++) {
|
||||
if (x < oldWidth && y < oldHeight) {
|
||||
int index = y * oldWidth + x;
|
||||
newBlockData->addBlock(layout->border->blocks->value(index));
|
||||
} else {
|
||||
newBlockData->addBlock(0);
|
||||
}
|
||||
}
|
||||
|
||||
layout->border->copyFrom(newBlockData);
|
||||
}
|
||||
|
||||
void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata) {
|
||||
if (setNewBlockdata) {
|
||||
setNewDimensionsBlockdata(newWidth, newHeight);
|
||||
|
@ -309,6 +342,17 @@ void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata) {
|
|||
emit mapChanged(this);
|
||||
}
|
||||
|
||||
void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata) {
|
||||
if (setNewBlockdata) {
|
||||
setNewBorderDimensionsBlockdata(newWidth, newHeight);
|
||||
}
|
||||
|
||||
layout->border_width = QString::number(newWidth);
|
||||
layout->border_height = QString::number(newHeight);
|
||||
|
||||
emit mapChanged(this);
|
||||
}
|
||||
|
||||
Block* Map::getBlock(int x, int y) {
|
||||
if (layout->blockdata && layout->blockdata->blocks) {
|
||||
if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
|
||||
|
@ -363,35 +407,63 @@ void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_
|
|||
}
|
||||
|
||||
void Map::undo() {
|
||||
bool redraw = false, changed = false;
|
||||
HistoryItem *commit = metatileHistory.back();
|
||||
if (!commit)
|
||||
return;
|
||||
|
||||
if (layout->blockdata) {
|
||||
layout->blockdata->copyFrom(commit->metatiles);
|
||||
if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight())
|
||||
{
|
||||
if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight()) {
|
||||
this->setDimensions(commit->layoutWidth, commit->layoutHeight, false);
|
||||
emit mapNeedsRedrawing();
|
||||
redraw = true;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (layout->border) {
|
||||
layout->border->copyFrom(commit->border);
|
||||
if (commit->borderWidth != this->getBorderWidth() || commit->borderHeight != this->getBorderHeight()) {
|
||||
this->setBorderDimensions(commit->borderWidth, commit->borderHeight, false);
|
||||
redraw = true;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
emit mapNeedsRedrawing();
|
||||
}
|
||||
if (changed) {
|
||||
emit mapChanged(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Map::redo() {
|
||||
bool redraw = false, changed = false;
|
||||
HistoryItem *commit = metatileHistory.next();
|
||||
if (!commit)
|
||||
return;
|
||||
|
||||
if (layout->blockdata) {
|
||||
layout->blockdata->copyFrom(commit->metatiles);
|
||||
if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight())
|
||||
{
|
||||
if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight()) {
|
||||
this->setDimensions(commit->layoutWidth, commit->layoutHeight, false);
|
||||
emit mapNeedsRedrawing();
|
||||
redraw = true;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
if (layout->border) {
|
||||
layout->border->copyFrom(commit->border);
|
||||
if (commit->borderWidth != this->getBorderWidth() || commit->borderHeight != this->getBorderHeight()) {
|
||||
this->setBorderDimensions(commit->borderWidth, commit->borderHeight, false);
|
||||
redraw = true;
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (redraw) {
|
||||
emit mapNeedsRedrawing();
|
||||
}
|
||||
if (changed) {
|
||||
emit mapChanged(this);
|
||||
}
|
||||
}
|
||||
|
@ -401,14 +473,22 @@ void Map::commit() {
|
|||
return;
|
||||
}
|
||||
|
||||
int layoutWidth = this->getWidth();
|
||||
int layoutHeight = this->getHeight();
|
||||
int borderWidth = this->getBorderWidth();
|
||||
int borderHeight = this->getBorderHeight();
|
||||
|
||||
if (layout->blockdata) {
|
||||
HistoryItem *item = metatileHistory.current();
|
||||
bool atCurrentHistory = item
|
||||
&& layout->blockdata->equals(item->metatiles)
|
||||
&& this->getWidth() == item->layoutWidth
|
||||
&& this->getHeight() == item->layoutHeight;
|
||||
&& layout->border->equals(item->border)
|
||||
&& layoutWidth == item->layoutWidth
|
||||
&& layoutHeight == item->layoutHeight
|
||||
&& borderWidth == item->borderWidth
|
||||
&& borderHeight == item->borderHeight;
|
||||
if (!atCurrentHistory) {
|
||||
HistoryItem *commit = new HistoryItem(layout->blockdata->copy(), this->getWidth(), this->getHeight());
|
||||
HistoryItem *commit = new HistoryItem(layout->blockdata->copy(), layout->border->copy(), layoutWidth, layoutHeight, borderWidth, borderHeight);
|
||||
metatileHistory.push(commit);
|
||||
emit mapChanged(this);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ Metatile* Metatile::copy() {
|
|||
Metatile *copy = new Metatile;
|
||||
copy->behavior = this->behavior;
|
||||
copy->layerType = this->layerType;
|
||||
copy->encounterType = this->encounterType;
|
||||
copy->terrainType = this->terrainType;
|
||||
copy->tiles = new QList<Tile>;
|
||||
copy->label = this->label;
|
||||
for (Tile tile : *this->tiles) {
|
||||
|
@ -22,6 +24,8 @@ Metatile* Metatile::copy() {
|
|||
void Metatile::copyInPlace(Metatile *other) {
|
||||
this->behavior = other->behavior;
|
||||
this->layerType = other->layerType;
|
||||
this->encounterType = other->encounterType;
|
||||
this->terrainType = other->terrainType;
|
||||
this->label = other->label;
|
||||
for (int i = 0; i < this->tiles->length(); i++) {
|
||||
(*this->tiles)[i] = other->tiles->at(i);
|
||||
|
|
|
@ -84,6 +84,8 @@ QList<Metatile*> *MetatileParser::parse(QString filepath, bool *error, bool prim
|
|||
(static_cast<unsigned char>(in.at(attrOffset + 1)) << 8);
|
||||
metatile->behavior = value & 0xFF;
|
||||
metatile->layerType = (value & 0xF000) >> 12;
|
||||
metatile->encounterType = 0;
|
||||
metatile->terrainType = 0;
|
||||
metatile->tiles = tiles;
|
||||
metatiles->append(metatile);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "metatile.h"
|
||||
#include "project.h"
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
|
@ -115,8 +116,13 @@ bool Tileset::appendToHeaders(QString headerFile, QString friendlyName){
|
|||
dataString.append(QString("\t.4byte gTilesetTiles_%1\n").arg(friendlyName));
|
||||
dataString.append(QString("\t.4byte gTilesetPalettes_%1\n").arg(friendlyName));
|
||||
dataString.append(QString("\t.4byte gMetatiles_%1\n").arg(friendlyName));
|
||||
dataString.append(QString("\t.4byte gMetatileAttributes_%1\n").arg(friendlyName));
|
||||
dataString.append("\t.4byte NULL\n");
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
dataString.append("\t.4byte NULL\n");
|
||||
dataString.append(QString("\t.4byte gMetatileAttributes_%1\n").arg(friendlyName));
|
||||
} else {
|
||||
dataString.append(QString("\t.4byte gMetatileAttributes_%1\n").arg(friendlyName));
|
||||
dataString.append("\t.4byte NULL\n");
|
||||
}
|
||||
file.write(dataString.toUtf8());
|
||||
file.flush();
|
||||
file.close();
|
||||
|
|
|
@ -48,6 +48,8 @@ void Editor::undo() {
|
|||
map->undo();
|
||||
map_item->draw();
|
||||
collision_item->draw();
|
||||
selected_border_metatiles_item->draw();
|
||||
displayMapBorder();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +58,8 @@ void Editor::redo() {
|
|||
map->redo();
|
||||
map_item->draw();
|
||||
collision_item->draw();
|
||||
selected_border_metatiles_item->draw();
|
||||
displayMapBorder();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1136,10 +1140,10 @@ void Editor::displayMapMetatiles() {
|
|||
int tw = 16;
|
||||
int th = 16;
|
||||
scene->setSceneRect(
|
||||
-6 * tw,
|
||||
-6 * th,
|
||||
map_item->pixmap().width() + 12 * tw,
|
||||
map_item->pixmap().height() + 12 * th
|
||||
-BORDER_DISTANCE * tw,
|
||||
-BORDER_DISTANCE * th,
|
||||
map_item->pixmap().width() + BORDER_DISTANCE * 2 * tw,
|
||||
map_item->pixmap().height() + BORDER_DISTANCE * 2 * th
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1334,9 +1338,13 @@ void Editor::displayMapBorder() {
|
|||
}
|
||||
borderItems.clear();
|
||||
|
||||
int borderWidth = map->getBorderWidth();
|
||||
int borderHeight = map->getBorderHeight();
|
||||
int borderHorzDist = getBorderDrawDistance(borderWidth);
|
||||
int borderVertDist = getBorderDrawDistance(borderHeight);
|
||||
QPixmap pixmap = map->renderBorder();
|
||||
for (int y = -6; y < map->getHeight() + 6; y += 2)
|
||||
for (int x = -6; x < map->getWidth() + 6; x += 2) {
|
||||
for (int y = -borderVertDist; y < map->getHeight() + borderVertDist; y += borderHeight)
|
||||
for (int x = -borderHorzDist; x < map->getWidth() + borderHorzDist; x += borderWidth) {
|
||||
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
|
||||
item->setX(x * 16);
|
||||
item->setY(y * 16);
|
||||
|
@ -1346,6 +1354,17 @@ void Editor::displayMapBorder() {
|
|||
}
|
||||
}
|
||||
|
||||
int Editor::getBorderDrawDistance(int dimension) {
|
||||
// Draw sufficient border blocks to fill the player's view (BORDER_DISTANCE)
|
||||
if (dimension >= BORDER_DISTANCE) {
|
||||
return dimension;
|
||||
} else if (dimension) {
|
||||
return dimension * (BORDER_DISTANCE / dimension + (BORDER_DISTANCE % dimension ? 1 : 0));
|
||||
} else {
|
||||
return BORDER_DISTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::displayMapGrid() {
|
||||
for (QGraphicsLineItem* item : gridLines) {
|
||||
if (item && item->scene()) {
|
||||
|
|
|
@ -50,7 +50,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
// Re-initialize everything to a blank slate if opening the recent project failed.
|
||||
this->initWindow();
|
||||
}
|
||||
|
||||
on_toolButton_Paint_clicked();
|
||||
}
|
||||
|
||||
|
@ -160,19 +159,38 @@ void MainWindow::setProjectSpecificUIVisibility()
|
|||
ui->checkBox_AllowRunning->setVisible(false);
|
||||
ui->checkBox_AllowBiking->setVisible(false);
|
||||
ui->checkBox_AllowEscapeRope->setVisible(false);
|
||||
ui->spinBox_FloorNumber->setVisible(false);
|
||||
ui->label_AllowRunning->setVisible(false);
|
||||
ui->label_AllowBiking->setVisible(false);
|
||||
ui->label_AllowEscapeRope->setVisible(false);
|
||||
ui->label_FloorNumber->setVisible(false);
|
||||
ui->actionRegion_Map_Editor->setVisible(true);
|
||||
break;
|
||||
case BaseGameVersion::pokeemerald:
|
||||
ui->checkBox_AllowRunning->setVisible(true);
|
||||
ui->checkBox_AllowBiking->setVisible(true);
|
||||
ui->checkBox_AllowEscapeRope->setVisible(true);
|
||||
ui->spinBox_FloorNumber->setVisible(false);
|
||||
ui->label_AllowRunning->setVisible(true);
|
||||
ui->label_AllowBiking->setVisible(true);
|
||||
ui->label_AllowEscapeRope->setVisible(true);
|
||||
ui->label_FloorNumber->setVisible(false);
|
||||
ui->actionRegion_Map_Editor->setVisible(true);
|
||||
break;
|
||||
case BaseGameVersion::pokefirered:
|
||||
ui->checkBox_AllowRunning->setVisible(true);
|
||||
ui->checkBox_AllowBiking->setVisible(true);
|
||||
ui->checkBox_AllowEscapeRope->setVisible(true);
|
||||
ui->spinBox_FloorNumber->setVisible(true);
|
||||
ui->label_AllowRunning->setVisible(true);
|
||||
ui->label_AllowBiking->setVisible(true);
|
||||
ui->label_AllowEscapeRope->setVisible(true);
|
||||
ui->label_FloorNumber->setVisible(true);
|
||||
ui->newEventToolButton->newWeatherTriggerAction->setVisible(false);
|
||||
ui->newEventToolButton->newSecretBaseAction->setVisible(false);
|
||||
// TODO: pokefirered is not set up for the Region Map Editor and vice versa.
|
||||
// porymap will crash on attempt. Remove below once resolved
|
||||
ui->actionRegion_Map_Editor->setVisible(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -275,6 +293,7 @@ bool MainWindow::openProject(QString dir) {
|
|||
projectConfig.setProjectDir(dir);
|
||||
projectConfig.load();
|
||||
|
||||
this->closeSupplementaryWindows();
|
||||
this->setProjectSpecificUIVisibility();
|
||||
|
||||
bool already_open = isProjectOpen() && (editor->project->root == dir);
|
||||
|
@ -504,6 +523,7 @@ void MainWindow::displayMapProperties() {
|
|||
ui->checkBox_AllowRunning->setChecked(map->allowRunning.toInt() > 0 || map->allowRunning == "TRUE");
|
||||
ui->checkBox_AllowBiking->setChecked(map->allowBiking.toInt() > 0 || map->allowBiking == "TRUE");
|
||||
ui->checkBox_AllowEscapeRope->setChecked(map->allowEscapeRope.toInt() > 0 || map->allowEscapeRope == "TRUE");
|
||||
ui->spinBox_FloorNumber->setValue(map->floorNumber);
|
||||
|
||||
// Custom fields table.
|
||||
ui->tableWidget_CustomHeaderFields->blockSignals(true);
|
||||
|
@ -607,6 +627,13 @@ void MainWindow::on_checkBox_AllowEscapeRope_clicked(bool checked)
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_spinBox_FloorNumber_valueChanged(int offset)
|
||||
{
|
||||
if (editor && editor->map) {
|
||||
editor->map->floorNumber = offset;
|
||||
}
|
||||
}
|
||||
|
||||
bool MainWindow::loadDataStructures() {
|
||||
Project *project = editor->project;
|
||||
bool success = project->readMapLayouts()
|
||||
|
@ -619,15 +646,18 @@ bool MainWindow::loadDataStructures() {
|
|||
&& project->readMapTypes()
|
||||
&& project->readMapBattleScenes()
|
||||
&& project->readWeatherNames()
|
||||
&& project->readCoordEventWeatherNames()
|
||||
&& project->readSecretBaseIds()
|
||||
&& project->readBgEventFacingDirections()
|
||||
&& project->readTrainerTypes()
|
||||
&& project->readMetatileBehaviors()
|
||||
&& project->readTilesetProperties()
|
||||
&& project->readHealLocations()
|
||||
&& project->readMiscellaneousConstants()
|
||||
&& project->readSpeciesIconPaths()
|
||||
&& project->readWildMonData();
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeemerald || projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby)
|
||||
success = success
|
||||
&& project->readSecretBaseIds()
|
||||
&& project->readCoordEventWeatherNames();
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
@ -969,6 +999,8 @@ void MainWindow::on_actionNew_Tileset_triggered() {
|
|||
}
|
||||
mt->behavior = 0;
|
||||
mt->layerType = 0;
|
||||
mt->encounterType = 0;
|
||||
mt->terrainType = 0;
|
||||
|
||||
newSet->metatiles->append(mt);
|
||||
}
|
||||
|
@ -1334,6 +1366,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
QList<EventPropertiesFrame *> frames;
|
||||
|
||||
bool pokefirered = projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered;
|
||||
for (DraggablePixmapItem *item : *events) {
|
||||
EventPropertiesFrame *frame = new EventPropertiesFrame;
|
||||
// frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
|
@ -1387,17 +1420,20 @@ void MainWindow::updateSelectedObjects() {
|
|||
field_labels["radius_y"] = "Movement Radius Y";
|
||||
field_labels["trainer_type"] = "Trainer Type";
|
||||
field_labels["sight_radius_tree_id"] = "Sight Radius / Berry Tree ID";
|
||||
field_labels["in_connection"] = "In Connection";
|
||||
field_labels["destination_warp"] = "Destination Warp";
|
||||
field_labels["destination_map_name"] = "Destination Map";
|
||||
field_labels["script_var"] = "Var";
|
||||
field_labels["script_var_value"] = "Var Value";
|
||||
field_labels["player_facing_direction"] = "Player Facing Direction";
|
||||
field_labels["item"] = "Item";
|
||||
field_labels["item_unknown5"] = "Unknown 5";
|
||||
field_labels["item_unknown6"] = "Unknown 6";
|
||||
field_labels["quantity"] = "Quantity";
|
||||
field_labels["underfoot"] = "Requires Itemfinder";
|
||||
field_labels["weather"] = "Weather";
|
||||
field_labels["flag"] = "Flag";
|
||||
field_labels["secret_base_id"] = "Secret Base Id";
|
||||
field_labels["respawn_map"] = "Respawn Map";
|
||||
field_labels["respawn_npc"] = "Respawn NPC";
|
||||
|
||||
QStringList fields;
|
||||
|
||||
|
@ -1425,6 +1461,9 @@ void MainWindow::updateSelectedObjects() {
|
|||
fields << "event_flag";
|
||||
fields << "trainer_type";
|
||||
fields << "sight_radius_tree_id";
|
||||
if (pokefirered) {
|
||||
fields << "in_connection";
|
||||
}
|
||||
}
|
||||
else if (event_type == EventType::Warp) {
|
||||
fields << "destination_map_name";
|
||||
|
@ -1445,6 +1484,10 @@ void MainWindow::updateSelectedObjects() {
|
|||
else if (event_type == EventType::HiddenItem) {
|
||||
fields << "item";
|
||||
fields << "flag";
|
||||
if (pokefirered) {
|
||||
fields << "quantity";
|
||||
fields << "underfoot";
|
||||
}
|
||||
}
|
||||
else if (event_type == EventType::SecretBase) {
|
||||
fields << "secret_base_id";
|
||||
|
@ -1453,8 +1496,15 @@ void MainWindow::updateSelectedObjects() {
|
|||
// Hide elevation so users don't get impression that editing it is meaningful.
|
||||
frame->ui->spinBox_z->setVisible(false);
|
||||
frame->ui->label_z->setVisible(false);
|
||||
if (pokefirered) {
|
||||
fields << "respawn_map";
|
||||
fields << "respawn_npc";
|
||||
}
|
||||
}
|
||||
|
||||
// Some keys shouldn't use a combobox
|
||||
QStringList spinKeys = {"quantity", "respawn_npc"};
|
||||
QStringList checkKeys = {"underfoot", "in_connection"};
|
||||
for (QString key : fields) {
|
||||
QString value = item->event->get(key);
|
||||
QWidget *widget = new QWidget(frame);
|
||||
|
@ -1462,30 +1512,17 @@ void MainWindow::updateSelectedObjects() {
|
|||
fl->setContentsMargins(9, 0, 9, 0);
|
||||
fl->setRowWrapPolicy(QFormLayout::WrapLongRows);
|
||||
|
||||
NoScrollComboBox *combo = new NoScrollComboBox(widget);
|
||||
combo->setEditable(true);
|
||||
NoScrollSpinBox *spin;
|
||||
NoScrollComboBox *combo;
|
||||
QCheckBox *check;
|
||||
|
||||
// trainer_type has custom values, so it has special signal logic.
|
||||
if (key == "trainer_type") {
|
||||
combo->setEditable(false);
|
||||
combo->addItem("NONE", "0");
|
||||
combo->addItem("NORMAL", "1");
|
||||
combo->addItem("SEE ALL DIRECTIONS", "3");
|
||||
combo->setToolTip("The trainer type of this object event.\n"
|
||||
"If it is not a trainer, use NONE. SEE ALL DIRECTIONS\n"
|
||||
"should only be used with a sight radius of 1.");
|
||||
combo->setMinimumContentsLength(10);
|
||||
|
||||
int index = combo->findData(value);
|
||||
if (index != -1) {
|
||||
combo->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
fl->addRow(new QLabel(field_labels[key], widget), combo);
|
||||
widget->setLayout(fl);
|
||||
frame->layout()->addWidget(widget);
|
||||
item->bindToUserData(combo, key);
|
||||
continue;
|
||||
if (spinKeys.contains(key)) {
|
||||
spin = new NoScrollSpinBox(widget);
|
||||
} else if (checkKeys.contains(key)) {
|
||||
check = new QCheckBox(widget);
|
||||
} else {
|
||||
combo = new NoScrollComboBox(widget);
|
||||
combo->setEditable(true);
|
||||
}
|
||||
|
||||
if (key == "destination_map_name") {
|
||||
|
@ -1501,6 +1538,12 @@ void MainWindow::updateSelectedObjects() {
|
|||
combo->addItem(value);
|
||||
}
|
||||
combo->addItems(*editor->project->itemNames);
|
||||
} else if (key == "quantity") {
|
||||
spin->setToolTip("The number of items received when the hidden item is picked up.");
|
||||
// Min 1 not needed. 0 is treated as a valid quantity and works as expected in-game.
|
||||
spin->setMaximum(127);
|
||||
} else if (key == "underfoot") {
|
||||
check->setToolTip("If checked, hidden item can only be picked up using the Itemfinder");
|
||||
} else if (key == "flag" || key == "event_flag") {
|
||||
if (!editor->project->flagNames->contains(value)) {
|
||||
combo->addItem(value);
|
||||
|
@ -1564,20 +1607,72 @@ void MainWindow::updateSelectedObjects() {
|
|||
combo->setMinimumContentsLength(4);
|
||||
} else if (key == "script_label") {
|
||||
combo->setToolTip("The script which is executed with this event.");
|
||||
} else if (key == "trainer_type") {
|
||||
combo->addItems(*editor->project->trainerTypes);
|
||||
combo->setToolTip("The trainer type of this object event.\n"
|
||||
"If it is not a trainer, use NONE. SEE ALL DIRECTIONS\n"
|
||||
"should only be used with a sight radius of 1.");
|
||||
} else if (key == "sight_radius_tree_id") {
|
||||
combo->setToolTip("The maximum sight range of a trainer,\n"
|
||||
"OR the unique id of the berry tree.");
|
||||
combo->setMinimumContentsLength(4);
|
||||
} else if (key == "in_connection") {
|
||||
check->setToolTip("Check if object is positioned in the connection to another map.");
|
||||
} else if (key == "respawn_map") {
|
||||
if (!editor->project->mapNames->contains(value)) {
|
||||
combo->addItem(value);
|
||||
}
|
||||
combo->addItems(*editor->project->mapNames);
|
||||
combo->setToolTip("The map where the player will respawn after whiteout.");
|
||||
} else if (key == "respawn_npc") {
|
||||
spin->setToolTip("event_object ID of the NPC the player interacts with\n"
|
||||
"upon respawning after whiteout.");
|
||||
spin->setMinimum(1);
|
||||
spin->setMaximum(126);
|
||||
} else {
|
||||
combo->addItem(value);
|
||||
}
|
||||
combo->setCurrentText(value);
|
||||
|
||||
fl->addRow(new QLabel(field_labels[key], widget), combo);
|
||||
widget->setLayout(fl);
|
||||
frame->layout()->addWidget(widget);
|
||||
// Keys using spin boxes
|
||||
if (spinKeys.contains(key)) {
|
||||
spin->setValue(value.toInt());
|
||||
|
||||
item->bind(combo, key);
|
||||
fl->addRow(new QLabel(field_labels[key], widget), spin);
|
||||
widget->setLayout(fl);
|
||||
frame->layout()->addWidget(widget);
|
||||
|
||||
connect(spin, QOverload<int>::of(&NoScrollSpinBox::valueChanged), [item, key](int value) {
|
||||
item->event->put(key, value);
|
||||
});
|
||||
// Keys using check boxes
|
||||
} else if (checkKeys.contains(key)) {
|
||||
check->setChecked(value.toInt());
|
||||
|
||||
fl->addRow(new QLabel(field_labels[key], widget), check);
|
||||
widget->setLayout(fl);
|
||||
frame->layout()->addWidget(widget);
|
||||
|
||||
connect(check, &QCheckBox::stateChanged, [item, key](int state) {
|
||||
switch (state)
|
||||
{
|
||||
case Qt::Checked:
|
||||
item->event->put(key, true);
|
||||
break;
|
||||
case Qt::Unchecked:
|
||||
item->event->put(key, false);
|
||||
break;
|
||||
}
|
||||
});
|
||||
// Keys using combo boxes
|
||||
} else {
|
||||
combo->setCurrentText(value);
|
||||
|
||||
fl->addRow(new QLabel(field_labels[key], widget), combo);
|
||||
widget->setLayout(fl);
|
||||
frame->layout()->addWidget(widget);
|
||||
|
||||
item->bind(combo, key);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom fields table.
|
||||
|
@ -2064,7 +2159,7 @@ void MainWindow::on_comboBox_SecondaryTileset_currentTextChanged(const QString &
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_clicked()
|
||||
void MainWindow::on_pushButton_ChangeDimensions_clicked()
|
||||
{
|
||||
QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||
dialog.setWindowTitle("Change Map Dimensions");
|
||||
|
@ -2074,15 +2169,31 @@ void MainWindow::on_pushButton_clicked()
|
|||
|
||||
QSpinBox *widthSpinBox = new QSpinBox();
|
||||
QSpinBox *heightSpinBox = new QSpinBox();
|
||||
QSpinBox *bwidthSpinBox = new QSpinBox();
|
||||
QSpinBox *bheightSpinBox = new QSpinBox();
|
||||
widthSpinBox->setMinimum(1);
|
||||
heightSpinBox->setMinimum(1);
|
||||
bwidthSpinBox->setMinimum(1);
|
||||
bheightSpinBox->setMinimum(1);
|
||||
// See below for explanation of maximum map dimensions
|
||||
widthSpinBox->setMaximum(0x1E7);
|
||||
heightSpinBox->setMaximum(0x1D1);
|
||||
// Maximum based only on data type (u8) of map border width/height
|
||||
bwidthSpinBox->setMaximum(255);
|
||||
bheightSpinBox->setMaximum(255);
|
||||
widthSpinBox->setValue(editor->map->getWidth());
|
||||
heightSpinBox->setValue(editor->map->getHeight());
|
||||
form.addRow(new QLabel("Width"), widthSpinBox);
|
||||
form.addRow(new QLabel("Height"), heightSpinBox);
|
||||
bwidthSpinBox->setValue(editor->map->getBorderWidth());
|
||||
bheightSpinBox->setValue(editor->map->getBorderHeight());
|
||||
if (projectConfig.getUseCustomBorderSize()) {
|
||||
form.addRow(new QLabel("Map Width"), widthSpinBox);
|
||||
form.addRow(new QLabel("Map Height"), heightSpinBox);
|
||||
form.addRow(new QLabel("Border Width"), bwidthSpinBox);
|
||||
form.addRow(new QLabel("Border Height"), bheightSpinBox);
|
||||
} else {
|
||||
form.addRow(new QLabel("Width"), widthSpinBox);
|
||||
form.addRow(new QLabel("Height"), heightSpinBox);
|
||||
}
|
||||
|
||||
QLabel *errorLabel = new QLabel();
|
||||
QPalette errorPalette;
|
||||
|
@ -2104,8 +2215,8 @@ void MainWindow::on_pushButton_clicked()
|
|||
dialog.accept();
|
||||
} else {
|
||||
QString errorText = QString("Error: The specified width and height are too large.\n"
|
||||
"The maximum width and height is the following: (width + 15) * (height + 14) <= 10240\n"
|
||||
"The specified width and height was: (%1 + 15) * (%2 + 14) = %3")
|
||||
"The maximum map width and height is the following: (width + 15) * (height + 14) <= 10240\n"
|
||||
"The specified map width and height was: (%1 + 15) * (%2 + 14) = %3")
|
||||
.arg(widthSpinBox->value())
|
||||
.arg(heightSpinBox->value())
|
||||
.arg(numMetatiles);
|
||||
|
@ -2119,6 +2230,7 @@ void MainWindow::on_pushButton_clicked()
|
|||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
editor->map->setDimensions(widthSpinBox->value(), heightSpinBox->value());
|
||||
editor->map->setBorderDimensions(bwidthSpinBox->value(), bheightSpinBox->value());
|
||||
editor->map->commit();
|
||||
onMapNeedsRedrawing();
|
||||
}
|
||||
|
@ -2299,6 +2411,17 @@ void MainWindow::on_actionRegion_Map_Editor_triggered() {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::closeSupplementaryWindows() {
|
||||
if (this->tilesetEditor)
|
||||
delete this->tilesetEditor;
|
||||
if (this->regionMapEditor)
|
||||
delete this->regionMapEditor;
|
||||
if (this->mapImageExporter)
|
||||
delete this->mapImageExporter;
|
||||
if (this->newmapprompt)
|
||||
delete this->newmapprompt;
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
if (projectHasUnsavedChanges || editor->map->hasUnsavedChanges()) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
|
|
405
src/project.cpp
405
src/project.cpp
|
@ -8,6 +8,7 @@
|
|||
#include "tile.h"
|
||||
#include "tileset.h"
|
||||
#include "imageexport.h"
|
||||
#include "map.h"
|
||||
|
||||
#include "orderedjson.h"
|
||||
|
||||
|
@ -48,6 +49,7 @@ Project::Project()
|
|||
coordEventWeatherNames = new QStringList;
|
||||
secretBaseIds = new QStringList;
|
||||
bgEventFacingDirections = new QStringList;
|
||||
trainerTypes = new QStringList;
|
||||
map_cache = new QMap<QString, Map*>;
|
||||
mapConstantsToMapNames = new QMap<QString, QString>;
|
||||
mapNamesToMapConstants = new QMap<QString, QString>;
|
||||
|
@ -105,8 +107,8 @@ QMap<QString, bool> Project::getTopLevelMapFields() {
|
|||
{"requires_flash", true},
|
||||
{"weather", true},
|
||||
{"map_type", true},
|
||||
{"allow_bike", true},
|
||||
{"allow_escape_rope", true},
|
||||
{"allow_cycling", true},
|
||||
{"allow_escaping", true},
|
||||
{"allow_running", true},
|
||||
{"show_map_name", true},
|
||||
{"battle_scene", true},
|
||||
|
@ -118,6 +120,31 @@ QMap<QString, bool> Project::getTopLevelMapFields() {
|
|||
{"shared_events_map", true},
|
||||
{"shared_scripts_map", true},
|
||||
};
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
return QMap<QString, bool>
|
||||
{
|
||||
{"id", true},
|
||||
{"name", true},
|
||||
{"layout", true},
|
||||
{"music", true},
|
||||
{"region_map_section", true},
|
||||
{"requires_flash", true},
|
||||
{"weather", true},
|
||||
{"map_type", true},
|
||||
{"allow_cycling", true},
|
||||
{"allow_escaping", true},
|
||||
{"allow_running", true},
|
||||
{"show_map_name", true},
|
||||
{"floor_number", true},
|
||||
{"battle_scene", true},
|
||||
{"connections", true},
|
||||
{"object_events", true},
|
||||
{"warp_events", true},
|
||||
{"coord_events", true},
|
||||
{"bg_events", true},
|
||||
{"shared_events_map", true},
|
||||
{"shared_scripts_map", true},
|
||||
};
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||
return QMap<QString, bool>
|
||||
{
|
||||
|
@ -169,9 +196,14 @@ bool Project::loadMapData(Map* map) {
|
|||
map->show_location = QString::number(mapObj["show_map_name"].toBool());
|
||||
map->battle_scene = mapObj["battle_scene"].toString();
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeemerald) {
|
||||
map->allowBiking = QString::number(mapObj["allow_bike"].toBool());
|
||||
map->allowEscapeRope = QString::number(mapObj["allow_escape_rope"].toBool());
|
||||
map->allowBiking = QString::number(mapObj["allow_cycling"].toBool());
|
||||
map->allowEscapeRope = QString::number(mapObj["allow_escaping"].toBool());
|
||||
map->allowRunning = QString::number(mapObj["allow_running"].toBool());
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
map->allowBiking = QString::number(mapObj["allow_cycling"].toBool());
|
||||
map->allowEscapeRope = QString::number(mapObj["allow_escaping"].toBool());
|
||||
map->allowRunning = QString::number(mapObj["allow_running"].toBool());
|
||||
map->floorNumber = mapObj["floor_number"].toInt();
|
||||
}
|
||||
map->sharedEventsMap = mapObj["shared_events_map"].toString();
|
||||
map->sharedScriptsMap = mapObj["shared_scripts_map"].toString();
|
||||
|
@ -184,6 +216,9 @@ bool Project::loadMapData(Map* map) {
|
|||
Event *object = new Event(event, EventType::Object);
|
||||
object->put("map_name", map->name);
|
||||
object->put("sprite", event["graphics_id"].toString());
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
object->put("in_connection", event["in_connection"].toBool());
|
||||
}
|
||||
object->put("x", QString::number(event["x"].toInt()));
|
||||
object->put("y", QString::number(event["y"].toInt()));
|
||||
object->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
|
@ -230,17 +265,22 @@ bool Project::loadMapData(Map* map) {
|
|||
HealLocation loc = *it;
|
||||
|
||||
//if TRUE map is flyable / has healing location
|
||||
if (loc.name == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) {
|
||||
if (loc.mapName == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) {
|
||||
Event *heal = new Event;
|
||||
heal->put("map_name", map->name);
|
||||
heal->put("x", loc.x);
|
||||
heal->put("y", loc.y);
|
||||
heal->put("loc_name", loc.name);
|
||||
heal->put("loc_name", loc.mapName);
|
||||
heal->put("id_name", loc.idName);
|
||||
heal->put("index", loc.index);
|
||||
heal->put("elevation", 3); // TODO: change this?
|
||||
heal->put("destination_map_name", mapConstantsToMapNames->value(map->name));
|
||||
heal->put("event_group_type", "heal_event_group");
|
||||
heal->put("event_type", EventType::HealLocation);
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
heal->put("respawn_map", mapConstantsToMapNames->value(QString("MAP_" + loc.respawnMap)));
|
||||
heal->put("respawn_npc", loc.respawnNPC);
|
||||
}
|
||||
map->events["heal_event_group"].append(heal);
|
||||
}
|
||||
|
||||
|
@ -300,6 +340,10 @@ bool Project::loadMapData(Map* map) {
|
|||
bg->put("elevation", QString::number(event["elevation"].toInt()));
|
||||
bg->put("item", event["item"].toString());
|
||||
bg->put("flag", event["flag"].toString());
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
bg->put("quantity", event["quantity"].toInt());
|
||||
bg->put("underfoot", event["underfoot"].toBool());
|
||||
}
|
||||
bg->put("event_group_type", "bg_event_group");
|
||||
map->events["bg_event_group"].append(bg);
|
||||
} else if (type == "secret_base") {
|
||||
|
@ -378,12 +422,12 @@ QString Project::readMapLocation(QString map_name) {
|
|||
}
|
||||
|
||||
void Project::setNewMapHeader(Map* map, int mapIndex) {
|
||||
map->song = "MUS_DAN02";
|
||||
map->layoutId = QString("%1").arg(mapIndex);
|
||||
map->location = "MAPSEC_LITTLEROOT_TOWN";
|
||||
map->location = mapSectionValueToName.value(0);
|
||||
map->requiresFlash = "FALSE";
|
||||
map->weather = "WEATHER_SUNNY";
|
||||
map->type = "MAP_TYPE_TOWN";
|
||||
map->weather = weatherNames->value(0, "WEATHER_NONE");
|
||||
map->type = mapTypes->value(0, "MAP_TYPE_NONE");
|
||||
map->song = defaultSong;
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||
map->show_location = "TRUE";
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeemerald) {
|
||||
|
@ -391,9 +435,15 @@ void Project::setNewMapHeader(Map* map, int mapIndex) {
|
|||
map->allowEscapeRope = "0";
|
||||
map->allowRunning = "1";
|
||||
map->show_location = "1";
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
map->allowBiking = "1";
|
||||
map->allowEscapeRope = "0";
|
||||
map->allowRunning = "1";
|
||||
map->show_location = "1";
|
||||
map->floorNumber = 0;
|
||||
}
|
||||
|
||||
map->battle_scene = "MAP_BATTLE_SCENE_NORMAL";
|
||||
map->battle_scene = mapBattleScenes->value(0, "MAP_BATTLE_SCENE_NORMAL");
|
||||
}
|
||||
|
||||
bool Project::loadMapLayout(Map* map) {
|
||||
|
@ -408,9 +458,14 @@ bool Project::loadMapLayout(Map* map) {
|
|||
return false;
|
||||
}
|
||||
|
||||
return loadMapTilesets(map)
|
||||
&& loadBlockdata(map)
|
||||
&& loadMapBorder(map);
|
||||
// Force these to run even if one fails
|
||||
bool loadedTilesets = loadMapTilesets(map);
|
||||
bool loadedBlockdata = loadBlockdata(map);
|
||||
bool loadedBorder = loadMapBorder(map);
|
||||
|
||||
return loadedTilesets
|
||||
&& loadedBlockdata
|
||||
&& loadedBorder;
|
||||
}
|
||||
|
||||
bool Project::readMapLayouts() {
|
||||
|
@ -449,8 +504,15 @@ bool Project::readMapLayouts() {
|
|||
"border_filepath",
|
||||
"blockdata_filepath",
|
||||
};
|
||||
bool useCustomBorderSize = projectConfig.getUseCustomBorderSize();
|
||||
if (useCustomBorderSize) {
|
||||
requiredFields.append("border_width");
|
||||
requiredFields.append("border_height");
|
||||
}
|
||||
for (int i = 0; i < layouts.size(); i++) {
|
||||
QJsonObject layoutObj = layouts[i].toObject();
|
||||
if (layoutObj.isEmpty())
|
||||
continue;
|
||||
if (!parser.ensureFieldsExist(layoutObj, requiredFields)) {
|
||||
logError(QString("Layout %1 is missing field(s) in %2.").arg(i).arg(layoutsFilepath));
|
||||
return false;
|
||||
|
@ -478,6 +540,23 @@ bool Project::readMapLayouts() {
|
|||
return false;
|
||||
}
|
||||
layout->height = QString::number(lheight);
|
||||
if (useCustomBorderSize) {
|
||||
int bwidth = layoutObj["border_width"].toInt();
|
||||
if (bwidth <= 0) { // 0 is an expected border width/height that should be handled, GF used it for the RS layouts in FRLG
|
||||
logWarn(QString("Invalid layout 'border_width' value '%1' on layout %2 in %3. Must be greater than 0. Using default (%4) instead.").arg(bwidth).arg(i).arg(layoutsFilepath).arg(DEFAULT_BORDER_WIDTH));
|
||||
bwidth = DEFAULT_BORDER_WIDTH;
|
||||
}
|
||||
layout->border_width = QString::number(bwidth);
|
||||
int bheight = layoutObj["border_height"].toInt();
|
||||
if (bheight <= 0) {
|
||||
logWarn(QString("Invalid layout 'border_height' value '%1' on layout %2 in %3. Must be greater than 0. Using default (%4) instead.").arg(bheight).arg(i).arg(layoutsFilepath).arg(DEFAULT_BORDER_HEIGHT));
|
||||
bheight = DEFAULT_BORDER_HEIGHT;
|
||||
}
|
||||
layout->border_height = QString::number(bheight);
|
||||
} else {
|
||||
layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
|
||||
layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
|
||||
}
|
||||
layout->tileset_primary_label = layoutObj["primary_tileset"].toString();
|
||||
if (layout->tileset_primary_label.isEmpty()) {
|
||||
logError(QString("Missing 'primary_tileset' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
|
||||
|
@ -521,6 +600,7 @@ void Project::saveMapLayouts() {
|
|||
OrderedJson::object layoutsObj;
|
||||
layoutsObj["layouts_table_label"] = layoutsLabel;
|
||||
|
||||
bool useCustomBorderSize = projectConfig.getUseCustomBorderSize();
|
||||
OrderedJson::array layoutsArr;
|
||||
for (QString layoutId : mapLayoutsTableMaster) {
|
||||
MapLayout *layout = mapLayouts.value(layoutId);
|
||||
|
@ -529,6 +609,10 @@ void Project::saveMapLayouts() {
|
|||
layoutObj["name"] = layout->name;
|
||||
layoutObj["width"] = layout->width.toInt(nullptr, 0);
|
||||
layoutObj["height"] = layout->height.toInt(nullptr, 0);
|
||||
if (useCustomBorderSize) {
|
||||
layoutObj["border_width"] = layout->border_width.toInt(nullptr, 0);
|
||||
layoutObj["border_height"] = layout->border_height.toInt(nullptr, 0);
|
||||
}
|
||||
layoutObj["primary_tileset"] = layout->tileset_primary_label;
|
||||
layoutObj["secondary_tileset"] = layout->tileset_secondary_label;
|
||||
layoutObj["border_filepath"] = layout->border_path;
|
||||
|
@ -549,10 +633,12 @@ void Project::setNewMapLayout(Map* map) {
|
|||
layout->name = QString("%1_Layout").arg(map->name);
|
||||
layout->width = "20";
|
||||
layout->height = "20";
|
||||
layout->border_width = DEFAULT_BORDER_WIDTH;
|
||||
layout->border_height = DEFAULT_BORDER_HEIGHT;
|
||||
layout->border_path = QString("data/layouts/%1/border.bin").arg(map->name);
|
||||
layout->blockdata_path = QString("data/layouts/%1/map.bin").arg(map->name);
|
||||
layout->tileset_primary_label = "gTileset_General";
|
||||
layout->tileset_secondary_label = "gTileset_Petalburg";
|
||||
layout->tileset_primary_label = tilesetLabels["primary"].value(0, "gTileset_General");
|
||||
layout->tileset_secondary_label = tilesetLabels["secondary"].value(0, projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered ? "gTileset_PalletTown" : "gTileset_Petalburg");
|
||||
map->layout = layout;
|
||||
map->layoutId = layout->id;
|
||||
|
||||
|
@ -716,9 +802,19 @@ void Project::saveMapConstantsHeader() {
|
|||
// saves heal location coords in root + /src/data/heal_locations.h
|
||||
// and indexes as defines in root + /include/constants/heal_locations.h
|
||||
void Project::saveHealLocationStruct(Map *map) {
|
||||
QString data_text = QString("%1%2struct HealLocation sHealLocations[] =\n{\n")
|
||||
QString constantPrefix, arrayName;
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
constantPrefix = "SPAWN_";
|
||||
arrayName = "sSpawnPoints";
|
||||
} else {
|
||||
constantPrefix = "HEAL_LOCATION_";
|
||||
arrayName = "sHealLocations";
|
||||
}
|
||||
|
||||
QString data_text = QString("%1%2struct HealLocation %3[] =\n{\n")
|
||||
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
||||
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "");
|
||||
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "")
|
||||
.arg(arrayName);
|
||||
|
||||
QString constants_text = QString("#ifndef GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
|
||||
constants_text += QString("#define GUARD_CONSTANTS_HEAL_LOCATIONS_H\n\n");
|
||||
|
@ -729,7 +825,7 @@ void Project::saveHealLocationStruct(Map *map) {
|
|||
// set flyableMapsDupes and flyableMapsUnique
|
||||
for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
|
||||
HealLocation loc = *it;
|
||||
QString xname = loc.name;
|
||||
QString xname = loc.idName;
|
||||
if (flyableMapsUnique.contains(xname)) {
|
||||
flyableMapsDupes[xname] = 1;
|
||||
}
|
||||
|
@ -745,33 +841,58 @@ void Project::saveHealLocationStruct(Map *map) {
|
|||
}
|
||||
|
||||
int i = 1;
|
||||
|
||||
for (auto map_in : flyableMaps) {
|
||||
data_text += QString(" {MAP_GROUP(%1), MAP_NUM(%1), %2, %3},\n")
|
||||
.arg(map_in.name)
|
||||
// add numbered suffix for duplicate constants
|
||||
if (flyableMapsDupes.keys().contains(map_in.idName)) {
|
||||
map_in.idName += QString("_%1").arg(flyableMapsDupes[map_in.idName]);
|
||||
flyableMapsDupes[map_in.idName]++;
|
||||
}
|
||||
|
||||
// Save first array (heal location coords), only data array in RSE
|
||||
data_text += QString(" [%1%2 - 1] = {MAP_GROUP(%3), MAP_NUM(%3), %4, %5},\n")
|
||||
.arg(constantPrefix)
|
||||
.arg(map_in.idName)
|
||||
.arg(map_in.mapName)
|
||||
.arg(map_in.x)
|
||||
.arg(map_in.y);
|
||||
|
||||
QString ending = QString("");
|
||||
|
||||
// must add _1 / _2 for maps that have duplicates
|
||||
if (flyableMapsDupes.keys().contains(map_in.name)) {
|
||||
// map contains multiple heal locations
|
||||
ending += QString("_%1").arg(flyableMapsDupes[map_in.name]);
|
||||
flyableMapsDupes[map_in.name]++;
|
||||
}
|
||||
// Save constants
|
||||
if (map_in.index != 0) {
|
||||
constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
|
||||
.arg(map_in.name + ending)
|
||||
constants_text += QString("#define %1%2 %3\n")
|
||||
.arg(constantPrefix)
|
||||
.arg(map_in.idName)
|
||||
.arg(map_in.index);
|
||||
}
|
||||
else {
|
||||
constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
|
||||
.arg(map_in.name + ending)
|
||||
} else {
|
||||
constants_text += QString("#define %1%2 %3\n")
|
||||
.arg(constantPrefix)
|
||||
.arg(map_in.idName)
|
||||
.arg(i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
// Save second array (map where player respawns for each heal location)
|
||||
data_text += QString("};\n\n%1%2u16 sWhiteoutRespawnHealCenterMapIdxs[][2] =\n{\n")
|
||||
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
||||
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "");
|
||||
for (auto map_in : flyableMaps) {
|
||||
data_text += QString(" [%1%2 - 1] = {MAP_GROUP(%3), MAP_NUM(%3)},\n")
|
||||
.arg(constantPrefix)
|
||||
.arg(map_in.idName)
|
||||
.arg(map_in.respawnMap);
|
||||
}
|
||||
|
||||
// Save third array (object id of NPC player speaks to upon respawning for each heal location)
|
||||
data_text += QString("};\n\n%1%2u8 sWhiteoutRespawnHealerNpcIds[] =\n{\n")
|
||||
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
||||
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "");
|
||||
for (auto map_in : flyableMaps) {
|
||||
data_text += QString(" [%1%2 - 1] = %3,\n")
|
||||
.arg(constantPrefix)
|
||||
.arg(map_in.idName)
|
||||
.arg(map_in.respawnNPC);
|
||||
}
|
||||
}
|
||||
|
||||
data_text += QString("};\n");
|
||||
constants_text += QString("\n#endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
|
||||
|
@ -876,9 +997,21 @@ void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
|
|||
QFile attrs_file(tileset->metatile_attrs_path);
|
||||
if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
QByteArray data;
|
||||
for (Metatile *metatile : *tileset->metatiles) {
|
||||
data.append(static_cast<char>(metatile->behavior));
|
||||
data.append(static_cast<char>((metatile->layerType << 4) & 0xF0));
|
||||
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
for (Metatile *metatile : *tileset->metatiles) {
|
||||
data.append(static_cast<char>(metatile->behavior));
|
||||
data.append(static_cast<char>(metatile->behavior >> 8) |
|
||||
static_cast<char>(metatile->terrainType << 1));
|
||||
data.append(static_cast<char>(0));
|
||||
data.append(static_cast<char>(metatile->encounterType) |
|
||||
static_cast<char>(metatile->layerType << 5));
|
||||
}
|
||||
} else {
|
||||
for (Metatile *metatile : *tileset->metatiles) {
|
||||
data.append(static_cast<char>(metatile->behavior));
|
||||
data.append(static_cast<char>((metatile->layerType << 4) & 0xF0));
|
||||
}
|
||||
}
|
||||
attrs_file.write(data);
|
||||
} else {
|
||||
|
@ -927,14 +1060,26 @@ bool Project::loadMapTilesets(Map* map) {
|
|||
|
||||
map->layout->tileset_primary = getTileset(map->layout->tileset_primary_label);
|
||||
if (!map->layout->tileset_primary) {
|
||||
logError(QString("Map layout %1 has invalid primary tileset '%2'").arg(map->layout->id).arg(map->layout->tileset_primary_label));
|
||||
return false;
|
||||
QString defaultTileset = tilesetLabels["primary"].value(0, "gTileset_General");
|
||||
logWarn(QString("Map layout %1 has invalid primary tileset '%2'. Using default '%3'").arg(map->layout->id).arg(map->layout->tileset_primary_label).arg(defaultTileset));
|
||||
map->layout->tileset_primary_label = defaultTileset;
|
||||
map->layout->tileset_primary = getTileset(map->layout->tileset_primary_label);
|
||||
if (!map->layout->tileset_primary) {
|
||||
logError(QString("Failed to set default primary tileset."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
|
||||
if (!map->layout->tileset_secondary) {
|
||||
logError(QString("Map layout %1 has invalid secondary tileset '%2'").arg(map->layout->id).arg(map->layout->tileset_secondary_label));
|
||||
return false;
|
||||
QString defaultTileset = tilesetLabels["secondary"].value(0, projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered ? "gTileset_PalletTown" : "gTileset_Petalburg");
|
||||
logWarn(QString("Map layout %1 has invalid secondary tileset '%2'. Using default '%3'").arg(map->layout->id).arg(map->layout->tileset_secondary_label).arg(defaultTileset));
|
||||
map->layout->tileset_secondary_label = defaultTileset;
|
||||
map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
|
||||
if (!map->layout->tileset_secondary) {
|
||||
logError(QString("Failed to set default secondary tileset."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -954,8 +1099,13 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
|||
tileset->tiles_label = values->value(3);
|
||||
tileset->palettes_label = values->value(4);
|
||||
tileset->metatiles_label = values->value(5);
|
||||
tileset->metatile_attrs_label = values->value(6);
|
||||
tileset->callback_label = values->value(7);
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
tileset->callback_label = values->value(6);
|
||||
tileset->metatile_attrs_label = values->value(7);
|
||||
} else {
|
||||
tileset->metatile_attrs_label = values->value(6);
|
||||
tileset->callback_label = values->value(7);
|
||||
}
|
||||
|
||||
loadTilesetAssets(tileset);
|
||||
|
||||
|
@ -997,7 +1147,7 @@ bool Project::loadMapBorder(Map *map) {
|
|||
|
||||
QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
|
||||
map->layout->border = readBlockdata(path);
|
||||
int borderLength = 4;
|
||||
int borderLength = map->getBorderWidth() * map->getBorderHeight();
|
||||
if (map->layout->border->blocks->count() != borderLength) {
|
||||
logWarn(QString("Layout border blockdata length %1 must be %2. Resizing border blockdata.")
|
||||
.arg(map->layout->border->blocks->count())
|
||||
|
@ -1009,10 +1159,21 @@ bool Project::loadMapBorder(Map *map) {
|
|||
|
||||
void Project::setNewMapBorder(Map *map) {
|
||||
Blockdata *blockdata = new Blockdata;
|
||||
blockdata->addBlock(qint16(0x01D4));
|
||||
blockdata->addBlock(qint16(0x01D5));
|
||||
blockdata->addBlock(qint16(0x01DC));
|
||||
blockdata->addBlock(qint16(0x01DD));
|
||||
if (map->getBorderWidth() != DEFAULT_BORDER_WIDTH || map->getBorderHeight() != DEFAULT_BORDER_HEIGHT) {
|
||||
for (int i = 0; i < map->getBorderWidth() * map->getBorderHeight(); i++) {
|
||||
blockdata->addBlock(0);
|
||||
}
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
blockdata->addBlock(qint16(0x0014));
|
||||
blockdata->addBlock(qint16(0x0015));
|
||||
blockdata->addBlock(qint16(0x001C));
|
||||
blockdata->addBlock(qint16(0x001D));
|
||||
} else {
|
||||
blockdata->addBlock(qint16(0x01D4));
|
||||
blockdata->addBlock(qint16(0x01D5));
|
||||
blockdata->addBlock(qint16(0x01DC));
|
||||
blockdata->addBlock(qint16(0x01DD));
|
||||
}
|
||||
map->layout->border = blockdata;
|
||||
}
|
||||
|
||||
|
@ -1058,14 +1219,14 @@ void Project::saveMap(Map *map) {
|
|||
QString text = this->getScriptDefaultString(projectConfig.getUsePoryScript(), map->name);
|
||||
saveTextFile(root + "/data/maps/" + map->name + "/scripts" + this->getScriptFileExtension(projectConfig.getUsePoryScript()), text);
|
||||
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby || projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
// Create file data/maps/<map_name>/text.inc
|
||||
saveTextFile(root + "/data/maps/" + map->name + "/text" + this->getScriptFileExtension(projectConfig.getUsePoryScript()), "\n");
|
||||
}
|
||||
|
||||
// Simply append to data/event_scripts.s.
|
||||
text = QString("\n\t.include \"data/maps/%1/scripts.inc\"\n").arg(map->name);
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby || projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
text += QString("\t.include \"data/maps/%1/text.inc\"\n").arg(map->name);
|
||||
}
|
||||
appendTextFile(root + "/data/event_scripts.s", text);
|
||||
|
@ -1099,6 +1260,10 @@ void Project::saveMap(Map *map) {
|
|||
newLayoutObj["name"] = map->layout->name;
|
||||
newLayoutObj["width"] = map->layout->width.toInt();
|
||||
newLayoutObj["height"] = map->layout->height.toInt();
|
||||
if (projectConfig.getUseCustomBorderSize()) {
|
||||
newLayoutObj["border_width"] = map->layout->border_width.toInt();
|
||||
newLayoutObj["border_height"] = map->layout->border_height.toInt();
|
||||
}
|
||||
newLayoutObj["primary_tileset"] = map->layout->tileset_primary_label;
|
||||
newLayoutObj["secondary_tileset"] = map->layout->tileset_secondary_label;
|
||||
newLayoutObj["border_filepath"] = map->layout->border_path;
|
||||
|
@ -1125,10 +1290,13 @@ void Project::saveMap(Map *map) {
|
|||
mapObj["requires_flash"] = map->requiresFlash.toInt() > 0 || map->requiresFlash == "TRUE";
|
||||
mapObj["weather"] = map->weather;
|
||||
mapObj["map_type"] = map->type;
|
||||
mapObj["allow_bike"] = map->allowBiking.toInt() > 0 || map->allowBiking == "TRUE";
|
||||
mapObj["allow_escape_rope"] = map->allowEscapeRope.toInt() > 0 || map->allowEscapeRope == "TRUE";
|
||||
mapObj["allow_cycling"] = map->allowBiking.toInt() > 0 || map->allowBiking == "TRUE";
|
||||
mapObj["allow_escaping"] = map->allowEscapeRope.toInt() > 0 || map->allowEscapeRope == "TRUE";
|
||||
mapObj["allow_running"] = map->allowRunning.toInt() > 0 || map->allowRunning == "TRUE";
|
||||
mapObj["show_map_name"] = map->show_location.toInt() > 0 || map->show_location == "TRUE";
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
mapObj["floor_number"] = map->floorNumber;
|
||||
}
|
||||
mapObj["battle_scene"] = map->battle_scene;
|
||||
|
||||
// Connections
|
||||
|
@ -1254,8 +1422,9 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
|||
if (tileset->name.isNull()) {
|
||||
return;
|
||||
}
|
||||
QRegularExpression re("([a-z])([A-Z0-9])");
|
||||
QString tilesetName = tileset->name;
|
||||
QString dir_path = root + "/data/tilesets/" + category + "/" + tilesetName.replace("gTileset_", "").toLower();
|
||||
QString dir_path = root + "/data/tilesets/" + category + "/" + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower();
|
||||
|
||||
QList<QStringList> *graphics = parser.parseAsm("data/tilesets/graphics.inc");
|
||||
QStringList *tiles_values = parser.getLabelValues(graphics, tileset->tiles_label);
|
||||
|
@ -1394,16 +1563,43 @@ void Project::loadTilesetMetatiles(Tileset* tileset) {
|
|||
if (attrs_file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data = attrs_file.readAll();
|
||||
int num_metatiles = tileset->metatiles->count();
|
||||
int num_metatileAttrs = data.length() / 2;
|
||||
if (num_metatiles != num_metatileAttrs) {
|
||||
logWarn(QString("Metatile count %1 does not match metatile attribute count %2 in %3").arg(num_metatiles).arg(num_metatileAttrs).arg(tileset->name));
|
||||
if (num_metatileAttrs > num_metatiles)
|
||||
num_metatileAttrs = num_metatiles;
|
||||
}
|
||||
for (int i = 0; i < num_metatileAttrs; i++) {
|
||||
int value = (static_cast<unsigned char>(data.at(i * 2 + 1)) << 8) | static_cast<unsigned char>(data.at(i * 2));
|
||||
tileset->metatiles->at(i)->behavior = value & 0xFF;
|
||||
tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12;
|
||||
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
int num_metatileAttrs = data.length() / 4;
|
||||
if (num_metatiles != num_metatileAttrs) {
|
||||
logWarn(QString("Metatile count %1 does not match metatile attribute count %2 in %3").arg(num_metatiles).arg(num_metatileAttrs).arg(tileset->name));
|
||||
if (num_metatileAttrs > num_metatiles)
|
||||
num_metatileAttrs = num_metatiles;
|
||||
}
|
||||
bool unusedAttribute = false;
|
||||
for (int i = 0; i < num_metatileAttrs; i++) {
|
||||
int value = (static_cast<unsigned char>(data.at(i * 4 + 3)) << 24) |
|
||||
(static_cast<unsigned char>(data.at(i * 4 + 2)) << 16) |
|
||||
(static_cast<unsigned char>(data.at(i * 4 + 1)) << 8) |
|
||||
(static_cast<unsigned char>(data.at(i * 4 + 0)));
|
||||
tileset->metatiles->at(i)->behavior = value & 0x1FF;
|
||||
tileset->metatiles->at(i)->terrainType = (value & 0x3E00) >> 9;
|
||||
tileset->metatiles->at(i)->encounterType = (value & 0x7000000) >> 24;
|
||||
tileset->metatiles->at(i)->layerType = (value & 0x60000000) >> 29;
|
||||
if (value & ~(0x67003FFF))
|
||||
unusedAttribute = true;
|
||||
}
|
||||
if (unusedAttribute)
|
||||
logWarn(QString("Unrecognized metatile attributes in %1 will not be saved.").arg(tileset->metatile_attrs_path));
|
||||
} else {
|
||||
int num_metatileAttrs = data.length() / 2;
|
||||
if (num_metatiles != num_metatileAttrs) {
|
||||
logWarn(QString("Metatile count %1 does not match metatile attribute count %2 in %3").arg(num_metatiles).arg(num_metatileAttrs).arg(tileset->name));
|
||||
if (num_metatileAttrs > num_metatiles)
|
||||
num_metatileAttrs = num_metatiles;
|
||||
}
|
||||
for (int i = 0; i < num_metatileAttrs; i++) {
|
||||
int value = (static_cast<unsigned char>(data.at(i * 2 + 1)) << 8) | static_cast<unsigned char>(data.at(i * 2));
|
||||
tileset->metatiles->at(i)->behavior = value & 0xFF;
|
||||
tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12;
|
||||
tileset->metatiles->at(i)->encounterType = 0;
|
||||
tileset->metatiles->at(i)->terrainType = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logError(QString("Could not open tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path));
|
||||
|
@ -1812,21 +2008,46 @@ bool Project::readRegionMapSections() {
|
|||
bool Project::readHealLocations() {
|
||||
dataQualifiers.clear();
|
||||
flyableMaps.clear();
|
||||
|
||||
QString filename = "src/data/heal_locations.h";
|
||||
QString text = parser.readTextFile(root + "/" + filename);
|
||||
text.replace(QRegularExpression("//.*?(\r\n?|\n)|/\\*.*?\\*/", QRegularExpression::DotMatchesEverythingOption), "");
|
||||
|
||||
dataQualifiers.insert("heal_locations", getDataQualifiers(text, "sHealLocations"));
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
dataQualifiers.insert("heal_locations", getDataQualifiers(text, "sSpawnPoints"));
|
||||
QRegularExpression spawnRegex("SPAWN_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = \\{MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\2)[\\s\\)]+,\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)");
|
||||
QRegularExpression respawnMapRegex("SPAWN_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = \\{MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\2)[\\s\\)]+}");
|
||||
QRegularExpression respawnNPCRegex("SPAWN_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = (?<npc>[0-9]+)");
|
||||
QRegularExpressionMatchIterator spawns = spawnRegex.globalMatch(text);
|
||||
QRegularExpressionMatchIterator respawnMaps = respawnMapRegex.globalMatch(text);
|
||||
QRegularExpressionMatchIterator respawnNPCs = respawnNPCRegex.globalMatch(text);
|
||||
|
||||
QRegularExpression regex("MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\1)[\\s\\)]+,\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)");
|
||||
QRegularExpressionMatchIterator iter = regex.globalMatch(text);
|
||||
for (int i = 1; iter.hasNext(); i++) {
|
||||
QRegularExpressionMatch match = iter.next();
|
||||
QString mapName = match.captured("map");
|
||||
unsigned x = match.captured("x").toUShort();
|
||||
unsigned y = match.captured("y").toUShort();
|
||||
flyableMaps.append(HealLocation(mapName, i, x, y));
|
||||
// This would be better if idName was used to look up data from the other two arrays
|
||||
// As it is, element total and order needs to be the same in the 3 arrays to work. This should always be true though
|
||||
for (int i = 1; spawns.hasNext(); i++) {
|
||||
QRegularExpressionMatch spawn = spawns.next();
|
||||
QRegularExpressionMatch respawnMap = respawnMaps.next();
|
||||
QRegularExpressionMatch respawnNPC = respawnNPCs.next();
|
||||
QString idName = spawn.captured("id");
|
||||
QString mapName = spawn.captured("map");
|
||||
QString respawnMapName = respawnMap.captured("map");
|
||||
unsigned x = spawn.captured("x").toUShort();
|
||||
unsigned y = spawn.captured("y").toUShort();
|
||||
unsigned npc = respawnNPC.captured("npc").toUShort();
|
||||
flyableMaps.append(HealLocation(idName, mapName, i, x, y, respawnMapName, npc));
|
||||
}
|
||||
} else {
|
||||
dataQualifiers.insert("heal_locations", getDataQualifiers(text, "sHealLocations"));
|
||||
|
||||
QRegularExpression regex("HEAL_LOCATION_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = \\{MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\2)[\\s\\)]+,\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)");
|
||||
QRegularExpressionMatchIterator iter = regex.globalMatch(text);
|
||||
for (int i = 1; iter.hasNext(); i++) {
|
||||
QRegularExpressionMatch match = iter.next();
|
||||
QString idName = match.captured("id");
|
||||
QString mapName = match.captured("map");
|
||||
unsigned x = match.captured("x").toUShort();
|
||||
unsigned y = match.captured("y").toUShort();
|
||||
flyableMaps.append(HealLocation(idName, mapName, i, x, y));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1961,6 +2182,18 @@ bool Project::readBgEventFacingDirections() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Project::readTrainerTypes() {
|
||||
trainerTypes->clear();
|
||||
QStringList prefixes = (QStringList() << "TRAINER_TYPE_");
|
||||
QString filename = "include/constants/trainer_types.h";
|
||||
parser.readCDefinesSorted(filename, prefixes, trainerTypes);
|
||||
if (trainerTypes->isEmpty()) {
|
||||
logError(QString("Failed to read trainer type constants from %1").arg(filename));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Project::readMetatileBehaviors() {
|
||||
this->metatileBehaviorMap.clear();
|
||||
this->metatileBehaviorMapInverse.clear();
|
||||
|
@ -1969,7 +2202,7 @@ bool Project::readMetatileBehaviors() {
|
|||
QString filename = "include/constants/metatile_behaviors.h";
|
||||
this->metatileBehaviorMap = parser.readCDefines(filename, prefixes);
|
||||
if (this->metatileBehaviorMap.isEmpty()) {
|
||||
logError(QString("Failed to metatile behaviors from %1.").arg(filename));
|
||||
logError(QString("Failed to read metatile behaviors from %1.").arg(filename));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1984,6 +2217,7 @@ QStringList Project::getSongNames() {
|
|||
songDefinePrefixes << "SE_" << "MUS_";
|
||||
QMap<QString, int> songDefines = parser.readCDefines("include/constants/songs.h", songDefinePrefixes);
|
||||
QStringList names = songDefines.keys();
|
||||
this->defaultSong = names.value(0, "MUS_DUMMY");
|
||||
|
||||
return names;
|
||||
}
|
||||
|
@ -2085,16 +2319,19 @@ void Project::loadEventPixmaps(QList<Event*> objects) {
|
|||
QImage spritesheet(root + "/" + path);
|
||||
if (!spritesheet.isNull()) {
|
||||
// Infer the sprite dimensions from the OAM labels.
|
||||
int spriteWidth = spritesheet.width();
|
||||
int spriteHeight = spritesheet.height();
|
||||
int spriteWidth, spriteHeight;
|
||||
QRegularExpression re("\\S+_(\\d+)x(\\d+)");
|
||||
QRegularExpressionMatch dimensionMatch = re.match(dimensions_label);
|
||||
if (dimensionMatch.hasMatch()) {
|
||||
QRegularExpressionMatch oamTablesMatch = re.match(subsprites_label);
|
||||
if (oamTablesMatch.hasMatch()) {
|
||||
spriteWidth = dimensionMatch.captured(1).toInt();
|
||||
spriteHeight = dimensionMatch.captured(2).toInt();
|
||||
}
|
||||
QRegularExpressionMatch oamTablesMatch = re.match(subsprites_label);
|
||||
if (oamTablesMatch.hasMatch()) {
|
||||
spriteWidth = oamTablesMatch.captured(1).toInt();
|
||||
spriteHeight = oamTablesMatch.captured(2).toInt();
|
||||
} else if (dimensionMatch.hasMatch()) {
|
||||
spriteWidth = dimensionMatch.captured(1).toInt();
|
||||
spriteHeight = dimensionMatch.captured(2).toInt();
|
||||
} else {
|
||||
spriteWidth = spritesheet.width();
|
||||
spriteHeight = spritesheet.height();
|
||||
}
|
||||
object->setPixmapFromSpritesheet(spritesheet, spriteWidth, spriteHeight, object->frame, object->hFlip);
|
||||
}
|
||||
|
|
|
@ -8,10 +8,12 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
int width = map->getBorderWidth();
|
||||
int height = map->getBorderHeight();
|
||||
|
||||
for (int i = 0; i < selectionDimensions.x() && (i + x) < 2; i++) {
|
||||
for (int j = 0; j < selectionDimensions.y() && (j + y) < 2; j++) {
|
||||
int blockIndex = (j + y) * 2 + (i + x);
|
||||
for (int i = 0; i < selectionDimensions.x() && (i + x) < width; i++) {
|
||||
for (int j = 0; j < selectionDimensions.y() && (j + y) < height; j++) {
|
||||
int blockIndex = (j + y) * width + (i + x);
|
||||
uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i);
|
||||
(*map->layout->border->blocks)[blockIndex].tile = tile;
|
||||
}
|
||||
|
@ -22,15 +24,17 @@ void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
}
|
||||
|
||||
void BorderMetatilesPixmapItem::draw() {
|
||||
QImage image(32, 32, QImage::Format_RGBA8888);
|
||||
int width = map->getBorderWidth();
|
||||
int height = map->getBorderHeight();
|
||||
QImage image(16 * width, 16 * height, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
QVector<Block> *blocks = map->layout->border->blocks;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
int x = i * 16;
|
||||
int y = j * 16;
|
||||
int index = j * 2 + i;
|
||||
int index = j * width + i;
|
||||
QImage metatile_image = getMetatileImage(blocks->value(index).tile, map->layout->tileset_primary, map->layout->tileset_secondary);
|
||||
QPoint metatile_origin = QPoint(x, y);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
|
@ -38,5 +42,6 @@ void BorderMetatilesPixmapItem::draw() {
|
|||
}
|
||||
|
||||
painter.end();
|
||||
map->commit();
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ void MapImageExporter::updatePreview() {
|
|||
int borderHeight = 0, borderWidth = 0;
|
||||
bool forceDrawBorder = showUpConnections || showDownConnections || showLeftConnections || showRightConnections;
|
||||
if (showBorder || forceDrawBorder) {
|
||||
borderHeight = 32 * 3, borderWidth = 32 * 3;
|
||||
borderHeight = BORDER_DISTANCE * 16, borderWidth = BORDER_DISTANCE * 16;
|
||||
QPixmap newPreview = QPixmap(map->pixmap.width() + borderWidth * 2, map->pixmap.height() + borderHeight * 2);
|
||||
QPainter borderPainter(&newPreview);
|
||||
for (auto borderItem : editor->borderItems) {
|
||||
|
|
|
@ -62,11 +62,15 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) {
|
|||
ui->comboBox_NewMap_Secondary_Tileset->setCurrentText(project->mapLayouts.value(layoutId)->tileset_secondary_label);
|
||||
ui->spinBox_NewMap_Width->setDisabled(true);
|
||||
ui->spinBox_NewMap_Height->setDisabled(true);
|
||||
ui->spinBox_NewMap_BorderWidth->setDisabled(true);
|
||||
ui->spinBox_NewMap_BorderHeight->setDisabled(true);
|
||||
ui->comboBox_NewMap_Primary_Tileset->setDisabled(true);
|
||||
ui->comboBox_NewMap_Secondary_Tileset->setDisabled(true);
|
||||
} else {
|
||||
ui->spinBox_NewMap_Width->setValue(20);
|
||||
ui->spinBox_NewMap_Height->setValue(20);
|
||||
ui->spinBox_NewMap_BorderWidth->setValue(DEFAULT_BORDER_WIDTH);
|
||||
ui->spinBox_NewMap_BorderHeight->setValue(DEFAULT_BORDER_HEIGHT);
|
||||
}
|
||||
|
||||
ui->comboBox_NewMap_Type->addItems(*project->mapTypes);
|
||||
|
@ -81,21 +85,44 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) {
|
|||
ui->checkBox_NewMap_Allow_Running->setVisible(false);
|
||||
ui->checkBox_NewMap_Allow_Biking->setVisible(false);
|
||||
ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(false);
|
||||
ui->spinBox_NewMap_Floor_Number->setVisible(false);
|
||||
ui->label_NewMap_Allow_Running->setVisible(false);
|
||||
ui->label_NewMap_Allow_Biking->setVisible(false);
|
||||
ui->label_NewMap_Allow_Escape_Rope->setVisible(false);
|
||||
ui->label_NewMap_Floor_Number->setVisible(false);
|
||||
break;
|
||||
case BaseGameVersion::pokeemerald:
|
||||
ui->checkBox_NewMap_Allow_Running->setVisible(true);
|
||||
ui->checkBox_NewMap_Allow_Biking->setVisible(true);
|
||||
ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(true);
|
||||
ui->spinBox_NewMap_Floor_Number->setVisible(false);
|
||||
ui->label_NewMap_Allow_Running->setVisible(true);
|
||||
ui->label_NewMap_Allow_Biking->setVisible(true);
|
||||
ui->label_NewMap_Allow_Escape_Rope->setVisible(true);
|
||||
ui->label_NewMap_Floor_Number->setVisible(false);
|
||||
break;
|
||||
case BaseGameVersion::pokefirered:
|
||||
ui->checkBox_NewMap_Allow_Running->setVisible(true);
|
||||
ui->checkBox_NewMap_Allow_Biking->setVisible(true);
|
||||
ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(true);
|
||||
ui->spinBox_NewMap_Floor_Number->setVisible(true);
|
||||
ui->label_NewMap_Allow_Running->setVisible(true);
|
||||
ui->label_NewMap_Allow_Biking->setVisible(true);
|
||||
ui->label_NewMap_Allow_Escape_Rope->setVisible(true);
|
||||
ui->label_NewMap_Floor_Number->setVisible(true);
|
||||
break;
|
||||
}
|
||||
if (projectConfig.getUseCustomBorderSize()) {
|
||||
ui->spinBox_NewMap_BorderWidth->setVisible(true);
|
||||
ui->spinBox_NewMap_BorderHeight->setVisible(true);
|
||||
ui->label_NewMap_BorderWidth->setVisible(true);
|
||||
ui->label_NewMap_BorderHeight->setVisible(true);
|
||||
} else {
|
||||
ui->spinBox_NewMap_BorderWidth->setVisible(false);
|
||||
ui->spinBox_NewMap_BorderHeight->setVisible(false);
|
||||
ui->label_NewMap_BorderWidth->setVisible(false);
|
||||
ui->label_NewMap_BorderHeight->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapPopup::on_lineEdit_NewMap_Name_textChanged(const QString &text) {
|
||||
|
@ -123,11 +150,11 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
|||
newMap->name = newMapName;
|
||||
newMap->type = this->ui->comboBox_NewMap_Type->currentText();
|
||||
newMap->location = this->ui->comboBox_NewMap_Location->currentText();
|
||||
newMap->song = "MUS_DAN02";
|
||||
newMap->song = this->project->defaultSong;
|
||||
newMap->requiresFlash = "0";
|
||||
newMap->weather = "WEATHER_SUNNY";
|
||||
newMap->weather = this->project->weatherNames->value(0, "WEATHER_NONE");
|
||||
newMap->show_location = "1";
|
||||
newMap->battle_scene = "MAP_BATTLE_SCENE_NORMAL";
|
||||
newMap->battle_scene = this->project->mapBattleScenes->value(0, "MAP_BATTLE_SCENE_NORMAL");
|
||||
|
||||
if (this->existingLayout) {
|
||||
layout = this->project->mapLayouts.value(this->layoutId);
|
||||
|
@ -138,6 +165,13 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
|||
layout->name = QString("%1_Layout").arg(newMap->name);
|
||||
layout->width = QString::number(this->ui->spinBox_NewMap_Width->value());
|
||||
layout->height = QString::number(this->ui->spinBox_NewMap_Height->value());
|
||||
if (projectConfig.getUseCustomBorderSize()) {
|
||||
layout->border_width = QString::number(this->ui->spinBox_NewMap_BorderWidth->value());
|
||||
layout->border_height = QString::number(this->ui->spinBox_NewMap_BorderHeight->value());
|
||||
} else {
|
||||
layout->border_width = QString::number(DEFAULT_BORDER_WIDTH);
|
||||
layout->border_height = QString::number(DEFAULT_BORDER_HEIGHT);
|
||||
}
|
||||
layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText();
|
||||
layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText();
|
||||
layout->border_path = QString("data/layouts/%1/border.bin").arg(newMapName);
|
||||
|
@ -152,6 +186,11 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
|||
newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked() ? "1" : "0";
|
||||
newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked() ? "1" : "0";
|
||||
newMap->allowEscapeRope = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked() ? "1" : "0";
|
||||
} else if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked() ? "1" : "0";
|
||||
newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked() ? "1" : "0";
|
||||
newMap->allowEscapeRope = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked() ? "1" : "0";
|
||||
newMap->floorNumber = this->ui->spinBox_NewMap_Floor_Number->value();
|
||||
}
|
||||
|
||||
group = project->groupNames->indexOf(this->ui->comboBox_NewMap_Group->currentText());
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "metatileparser.h"
|
||||
#include "paletteutil.h"
|
||||
#include "imageexport.h"
|
||||
#include "config.h"
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
|
@ -61,6 +62,25 @@ void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString
|
|||
this->ui->spinBox_paletteSelector->setMinimum(0);
|
||||
this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
this->ui->comboBox_encounterType->setVisible(true);
|
||||
this->ui->label_encounterType->setVisible(true);
|
||||
this->ui->comboBox_encounterType->addItem("None", 0);
|
||||
this->ui->comboBox_encounterType->addItem("Land", 1);
|
||||
this->ui->comboBox_encounterType->addItem("Water", 2);
|
||||
this->ui->comboBox_terrainType->setVisible(true);
|
||||
this->ui->label_terrainType->setVisible(true);
|
||||
this->ui->comboBox_terrainType->addItem("Normal", 0);
|
||||
this->ui->comboBox_terrainType->addItem("Grass", 1);
|
||||
this->ui->comboBox_terrainType->addItem("Water", 2);
|
||||
this->ui->comboBox_terrainType->addItem("Waterfall", 3);
|
||||
} else {
|
||||
this->ui->comboBox_encounterType->setVisible(false);
|
||||
this->ui->label_encounterType->setVisible(false);
|
||||
this->ui->comboBox_terrainType->setVisible(false);
|
||||
this->ui->label_terrainType->setVisible(false);
|
||||
}
|
||||
|
||||
//only allow characters valid for a symbol
|
||||
QRegExp expression("[_A-Za-z0-9]*$");
|
||||
QRegExpValidator *validator = new QRegExpValidator(expression);
|
||||
|
@ -206,6 +226,10 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
|
|||
this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior));
|
||||
this->ui->lineEdit_metatileLabel->setText(this->metatile->label);
|
||||
this->ui->comboBox_layerType->setCurrentIndex(this->ui->comboBox_layerType->findData(this->metatile->layerType));
|
||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||
this->ui->comboBox_encounterType->setCurrentIndex(this->ui->comboBox_encounterType->findData(this->metatile->encounterType));
|
||||
this->ui->comboBox_terrainType->setCurrentIndex(this->ui->comboBox_terrainType->findData(this->metatile->terrainType));
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredTileChanged(uint16_t tile) {
|
||||
|
@ -355,6 +379,26 @@ void TilesetEditor::on_comboBox_layerType_activated(int layerType)
|
|||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_encounterType_activated(int encounterType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = this->metatile->copy();
|
||||
this->metatile->encounterType = static_cast<uint8_t>(encounterType);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy());
|
||||
metatileHistory.push(commit);
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_terrainType_activated(int terrainType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = this->metatile->copy();
|
||||
this->metatile->terrainType = static_cast<uint8_t>(terrainType);
|
||||
MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy());
|
||||
metatileHistory.push(commit);
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionSave_Tileset_triggered()
|
||||
{
|
||||
saveMetatileLabel();
|
||||
|
@ -559,6 +603,8 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
|
|||
Metatile *metatile = new Metatile;
|
||||
metatile->behavior = 0;
|
||||
metatile->layerType = 0;
|
||||
metatile->encounterType = 0;
|
||||
metatile->terrainType = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
metatile->tiles->append(tile);
|
||||
}
|
||||
|
@ -577,6 +623,8 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
|
|||
Metatile *metatile = new Metatile;
|
||||
metatile->behavior = 0;
|
||||
metatile->layerType = 0;
|
||||
metatile->encounterType = 0;
|
||||
metatile->terrainType = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
metatile->tiles->append(tile);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue