Part 34: Fixed doors and switches
Downloads
Fixing the doors
void CDoors::drawDoor(QImage* image, CVec2 tablePos, CTile* tile)
{
SDoorElem& cell = tabDoor[tablePos.y][tablePos.x];
int doorNum = cell.file[0] - '0';
if (doorNum >= 0)
{
//----------------------------------------------------------------------------
// get door image
int doorType = tile->getDoorParam("Type");
std::string fileName = std::string("gfx/3DView/doors/") + doorsDatas[doorType].files[2].toUtf8().constData();
QImage doorImage = fileCache.getImage(fileName);
//----------------------------------------------------------------------------
// draw the ornate
int ornateType = tile->getDoorOrnateParam("Ornate");
std::string ornateName = doorOrnatesDatas[ornateType].file.toUtf8().constData();
QImage ornateImage;
CVec2 ornatePos;
if (ornateName.empty() == false)
{
ornateImage = fileCache.getImage(std::string("gfx/3DView/door_ornates/") + ornateName);
ornatePos = doorOrnatesDatas[ornateType].pos;
graph2D.drawImage(&doorImage, ornatePos, ornateImage);
// see-through ornates
if (ornateType == DOOR_ORNATE_ARCHED || ornateType == DOOR_ORNATE_ARCHED + 1)
{
QSize qSize = ornateImage.size();
for (int y = 0; y < qSize.height(); ++y)
for (int x = 0; x < qSize.width(); ++x)
{
QRgb pixel = ornateImage.pixel(x, y);
if (qRed(pixel) == 204 &&
qGreen(pixel) == 136 &&
qBlue(pixel) == 102)
{
CVec2 destPos = ornatePos + CVec2(x, y);
doorImage.setPixel(destPos.x, destPos.y, 0);
}
}
}
}
//----------------------------------------------------------------------------
// darken
static const float shadowLevels[] = {0.0f, 0.2f, 0.4f};
float shadow = shadowLevels[WALL_TABLE_HEIGHT - 2 - tablePos.y];
graph2D.darken(&doorImage, shadow);
//----------------------------------------------------------------------------
// draw
static const int doorScalesX[] = {96, 64, 44};
static const int doorScalesY[] = {88, 61, 38};
float scaleX = (float)doorScalesX[WALL_TABLE_HEIGHT - 2 - tablePos.y] / 96.0;
float scaleY = (float)doorScalesY[WALL_TABLE_HEIGHT - 2 - tablePos.y] / 88.0;
bool isHorizontal = tile->getBoolParam("isHorizontal");
int doorPos = tile->getIntParam("pos") / DOOR_POS_FACTOR;
if (isHorizontal == false)
{
//----------------------------------------------------------------------------
// vertical door
doorPos *= scaleY;
CVec2 pos(cell.x, cell.y + doorPos);
QRect clip(cell.cx1, cell.cy1,
cell.cx2 - cell.cx1 + 1, cell.cy2 - cell.cy1 + 1);
clipToMainView(&clip);
if (clip.width() > 0 && clip.height() > 0)
graph2D.drawImageScaled(image, pos, doorImage, scaleX, false, scaleY, clip);
}
else
{
//----------------------------------------------------------------------------
// horizontal door
doorPos *= scaleX;
CVec2 pos(cell.x + doorPos, cell.y);
int halfwidth = (cell.cx2 - cell.cx1 + 1) / 2;
QRect clip1(cell.cx1, cell.cy1,
halfwidth + doorPos, cell.cy2 - cell.cy1 + 1);
clipToMainView(&clip1);
if (clip1.width() > 0 && clip1.height() > 0)
graph2D.drawImageScaled(image, pos, doorImage, scaleX, false, scaleY, clip1);
pos.x = cell.x - doorPos;
QRect clip2(cell.cx1 + halfwidth - doorPos, cell.cy1,
halfwidth + doorPos, cell.cy2 - cell.cy1 + 1);
clipToMainView(&clip2);
if (clip2.width() > 0 && clip2.height() > 0)
graph2D.drawImageScaled(image, pos, doorImage, scaleX, false, scaleY, clip2);
}
}
}
Object shadow
The switches
<ornate name="Lever Off">
<image_front>Lever_Off_front.png</image_front>
<image_side>Lever_Off_side.png</image_side>
<pos_front x="105" y="69"/>
<pos_side x="47" y="72"/>
</ornate>
<ornate name="Lever On">
<image_front>Lever_On_front.png</image_front>
<image_side>Lever_On_side.png</image_side>
<pos_front x="105" y="69"/>
<pos_side x="47" y="72"/>
</ornate>
In the editor they will have 2 script parameters and a boolean to hold their state.
<wall name="Switch">
<image>Switch.png</image>
<param type="enum" values="Lever;Green button;Blue button;Big button">Type</param>
<param type="script">onTurnOn</param>
<param type="script">onTurnOff</param>
<param type="bool">isOn</param>
</wall>
In this part, I wrote the scripts for most of the switches and a few pressure plates.
The hidden alcove
Target Wall 6 3 down
SetType 5
SetEnum Type 1
AddObject 10
SetType changes the type of the target from a switch wall to an alcove one.
//--------------------------------------------------------------------------
void CScripts::executeSetType(std::vector<std::string>& words)
{
int type = stoi(words[1]);
if (mTargetType == eTargetType_Tile)
{
}
else
{
CWall* target = (CWall*)mTarget;
target->setType(type);
}
}
//--------------------------------------------------------------------------
void CScripts::executeSetEnum(std::vector<std::string>& words)
{
QString param = QString::fromStdString(words[1]);
int type = stoi(words[2]);
if (mTargetType == eTargetType_Tile)
{
}
else
{
CWall* target = (CWall*)mTarget;
target->setEnumParam(param, type);
}
}
//--------------------------------------------------------------------------
void CScripts::executeAddObject(std::vector<std::string>& words)
{
int type = stoi(words[1]);
CObjectStack* stack = map.addObjectsStack(mTargetPos, mTargetSide);
CObject newObj;
newObj.setType(type);
stack->addObject(newObj);
}
The 2 next switches
Target Tile 5 9
SetBool isOpened true
and "L02_CloseDoor05.txt"
Target Tile 5 9
SetBool isOpened false
The following switch will close a pit. That will be for a future part.
The door 19 puzzle
The door 20 puzzle
Target Tile 18 20
If Wall 22 19 right isOn
SetBool isOpened true
If the condition is not fullfiled, the next line after the "If" is skipped.
void CScripts::executeLine(std::vector<std::string>& words)
{
if (lastIf == true)
{
if (words[0] == "Target")
executeTarget(words);
else if (words[0] == "SetBool")
executeSetBool(words);
else if (words[0] == "SwitchBool")
executeSwitchBool(words);
else if (words[0] == "SetType")
executeSetType(words);
else if (words[0] == "SetEnum")
executeSetEnum(words);
else if (words[0] == "AddObject")
executeAddObject(words);
else if (words[0] == "If")
executeIf(words);
else if (words[0] == "SetString")
executeSetString(words);
}
else
{
lastIf = true;
}
}
Door 24 and the hidden room
Target Wall 14 28 down
SetType 0
Target Wall 13 29 right
SetType 0
The disappearing text
Target Wall 22 8 left
SetType 1
But to make it reappear, we both need to change the type back to a "text wall" and to set back the "Text" parameter.
Target Wall 22 8 left
SetType 6
SetString Text WALL_TEXT03
The SetString command is as simple as the SetBool one:
void CScripts::executeSetString(std::vector<std::string>& words)
{
QString param = QString::fromStdString(words[1]);
if (mTargetType == eTargetType_Tile)
{
}
else
{
((CWall*)mTarget)->setStringParam(param, words[2]);
}
}