mirror of
https://github.com/blupi-games/planetblupi
synced 2024-12-30 10:15:36 +01:00
952 lines
21 KiB
C++
952 lines
21 KiB
C++
/*
|
|
* This file is part of the planetblupi source code
|
|
* Copyright (C) 1997, Daniel Roux & EPSITEC SA
|
|
* Copyright (C) 2017, Mathieu Schroeter
|
|
* http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see http://gnu.org/licenses
|
|
*/
|
|
|
|
#include "decor.h"
|
|
#include "misc.h"
|
|
|
|
// clang-format off
|
|
// Cette table indique les quarts de cases contenant de
|
|
// l'eau lorsque la valeur est à un.
|
|
// 0 1
|
|
// 2 3
|
|
static const char tableSee[14 * 4] =
|
|
{
|
|
0, 0, 0, 0, // 1
|
|
0, 1, 0, 1, // 2
|
|
0, 0, 1, 1, // 3
|
|
1, 0, 1, 0, // 4
|
|
1, 1, 0, 0, // 5
|
|
0, 0, 0, 1, // 6
|
|
0, 0, 1, 0, // 7
|
|
1, 0, 0, 0, // 8
|
|
0, 1, 0, 0, // 9
|
|
0, 1, 1, 1, // 10
|
|
1, 0, 1, 1, // 11
|
|
1, 1, 1, 0, // 12
|
|
1, 1, 0, 1, // 13
|
|
1, 1, 1, 1, // 14
|
|
};
|
|
|
|
// Cette table indique les quarts de cases contenant de
|
|
// la mousse ou de la terre lorsque la valeur est à un.
|
|
// 0 1
|
|
// 2 3
|
|
static const char tableDark[13 * 4] =
|
|
{
|
|
1, 1, 1, 1, // 20
|
|
0, 1, 0, 1, // 21
|
|
0, 0, 1, 1, // 22
|
|
1, 0, 1, 0, // 23
|
|
1, 1, 0, 0, // 24
|
|
0, 0, 0, 1, // 25
|
|
0, 0, 1, 0, // 26
|
|
1, 0, 0, 0, // 27
|
|
0, 1, 0, 0, // 28
|
|
1, 1, 1, 0, // 29
|
|
1, 1, 0, 1, // 30
|
|
0, 1, 1, 1, // 31
|
|
1, 0, 1, 1, // 32
|
|
};
|
|
// clang-format on
|
|
|
|
// Retourne les bits contenant de l'eau.
|
|
|
|
bool
|
|
CDecor::GetSeeBits (Point cel, char * pBits, Sint32 index)
|
|
{
|
|
Sint32 icon;
|
|
|
|
pBits[0] = 0;
|
|
pBits[1] = 0;
|
|
pBits[2] = 0;
|
|
pBits[3] = 0;
|
|
|
|
if (cel.x < 0 || cel.x >= MAXCELX || cel.y < 0 || cel.y >= MAXCELY)
|
|
return false;
|
|
|
|
icon = m_decor[cel.x / 2][cel.y / 2].floorIcon;
|
|
|
|
if (index == 0) // eau ?
|
|
{
|
|
if (icon < 1 || icon > 14)
|
|
return true;
|
|
icon -= 1;
|
|
pBits[0] = tableSee[icon * 4 + 0];
|
|
pBits[1] = tableSee[icon * 4 + 1];
|
|
pBits[2] = tableSee[icon * 4 + 2];
|
|
pBits[3] = tableSee[icon * 4 + 3];
|
|
}
|
|
|
|
if (index == 1) // mousse ?
|
|
{
|
|
if (icon >= 2 && icon <= 14)
|
|
return false; // eau ?
|
|
if (icon == 66 || icon == 79) // mousse spéciale ?
|
|
{
|
|
pBits[0] = 1;
|
|
pBits[1] = 1;
|
|
pBits[2] = 1;
|
|
pBits[3] = 1;
|
|
return true;
|
|
}
|
|
if (icon < 20 || icon > 32)
|
|
return true;
|
|
icon -= 20;
|
|
pBits[0] = tableDark[icon * 4 + 0];
|
|
pBits[1] = tableDark[icon * 4 + 1];
|
|
pBits[2] = tableDark[icon * 4 + 2];
|
|
pBits[3] = tableDark[icon * 4 + 3];
|
|
}
|
|
|
|
if (index == 2) // terre ?
|
|
{
|
|
if (icon >= 2 && icon <= 14)
|
|
return false; // eau ?
|
|
if (
|
|
(icon >= 46 && icon <= 48) || // terre spéciale ?
|
|
icon == 71) // terre à fer ?
|
|
{
|
|
pBits[0] = 1;
|
|
pBits[1] = 1;
|
|
pBits[2] = 1;
|
|
pBits[3] = 1;
|
|
return true;
|
|
}
|
|
if (icon < 33 || icon > 45)
|
|
return true;
|
|
icon -= 33;
|
|
pBits[0] = tableDark[icon * 4 + 0];
|
|
pBits[1] = tableDark[icon * 4 + 1];
|
|
pBits[2] = tableDark[icon * 4 + 2];
|
|
pBits[3] = tableDark[icon * 4 + 3];
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
CopyBits (char * pDst, char * pSrc)
|
|
{
|
|
for (Sint32 i = 0; i < 4; i++)
|
|
*pDst++ = *pSrc++;
|
|
}
|
|
|
|
static bool
|
|
ChangeBits (char * pDst, char * pSrc)
|
|
{
|
|
for (Sint32 i = 0; i < 4; i++)
|
|
{
|
|
if (*pDst++ != *pSrc++)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Retourne l'icône correspondant aux bits d'eaux.
|
|
|
|
Sint32
|
|
CDecor::GetSeeIcon (char * pBits, Sint32 index)
|
|
{
|
|
Sint32 i;
|
|
|
|
if (index == 0) // eau ?
|
|
{
|
|
for (i = 0; i < 14; i++)
|
|
{
|
|
if (
|
|
tableSee[i * 4 + 0] == pBits[0] && tableSee[i * 4 + 1] == pBits[1] &&
|
|
tableSee[i * 4 + 2] == pBits[2] && tableSee[i * 4 + 3] == pBits[3])
|
|
return i + 1;
|
|
}
|
|
}
|
|
|
|
if (index == 1) // mousse ?
|
|
{
|
|
for (i = 0; i < 13; i++)
|
|
{
|
|
if (
|
|
tableDark[i * 4 + 0] == pBits[0] && tableDark[i * 4 + 1] == pBits[1] &&
|
|
tableDark[i * 4 + 2] == pBits[2] && tableDark[i * 4 + 3] == pBits[3])
|
|
return i + 20;
|
|
}
|
|
}
|
|
|
|
if (index == 2) // terre ?
|
|
{
|
|
for (i = 0; i < 13; i++)
|
|
{
|
|
if (
|
|
tableDark[i * 4 + 0] == pBits[0] && tableDark[i * 4 + 1] == pBits[1] &&
|
|
tableDark[i * 4 + 2] == pBits[2] && tableDark[i * 4 + 3] == pBits[3])
|
|
return i + 33;
|
|
}
|
|
}
|
|
|
|
if (pBits[0] == 0 && pBits[1] == 0 && pBits[2] == 0 && pBits[3] == 0)
|
|
return 1; // herbe
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Arrange le sol après une modification.
|
|
|
|
void
|
|
CDecor::ArrangeFloor (Point cel)
|
|
{
|
|
Point test;
|
|
Sint32 max, index, icon;
|
|
char here[4], bits[4], init[4];
|
|
bool bModif = false;
|
|
|
|
icon = m_decor[cel.x / 2][cel.y / 2].floorIcon;
|
|
|
|
if (icon >= 59 && icon <= 64)
|
|
return; // pont ?
|
|
|
|
max = 3;
|
|
if (icon >= 15 && icon <= 18) // dalle spéciale ?
|
|
{
|
|
max = 1; // s'occupe que de l'eau !
|
|
}
|
|
|
|
for (index = 0; index < max; index++)
|
|
{
|
|
if (!GetSeeBits (cel, here, index))
|
|
continue;
|
|
|
|
test.x = cel.x - 2; // en bas à gauche
|
|
test.y = cel.y + 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
if (
|
|
bits[2] == here[2] && bits[0] != here[2] && bits[1] != here[2] &&
|
|
bits[3] != here[2])
|
|
{
|
|
here[2] = bits[1];
|
|
bModif = true;
|
|
}
|
|
}
|
|
|
|
test.x = cel.x - 2; // en haut à gauche
|
|
test.y = cel.y - 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
if (
|
|
bits[0] == here[0] && bits[1] != here[0] && bits[2] != here[0] &&
|
|
bits[3] != here[0])
|
|
{
|
|
here[0] = bits[3];
|
|
bModif = true;
|
|
}
|
|
}
|
|
|
|
test.x = cel.x + 2; // en haut à droite
|
|
test.y = cel.y - 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
if (
|
|
bits[1] == here[1] && bits[0] != here[1] && bits[2] != here[1] &&
|
|
bits[3] != here[1])
|
|
{
|
|
here[1] = bits[2];
|
|
bModif = true;
|
|
}
|
|
}
|
|
|
|
test.x = cel.x + 2; // en bas à droite
|
|
test.y = cel.y + 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
if (
|
|
bits[3] == here[3] && bits[0] != here[3] && bits[1] != here[3] &&
|
|
bits[2] != here[3])
|
|
{
|
|
here[3] = bits[0];
|
|
bModif = true;
|
|
}
|
|
}
|
|
|
|
if (bModif)
|
|
{
|
|
icon = GetSeeIcon (here, index);
|
|
if (icon != -1)
|
|
m_decor[cel.x / 2][cel.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x - 2; // à gauche
|
|
test.y = cel.y;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[1] = here[0] ? 1 : 0;
|
|
bits[3] = here[2] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x - 2; // en haut à gauche
|
|
test.y = cel.y - 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[3] = here[0] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x; // en haut
|
|
test.y = cel.y - 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[2] = here[0] ? 1 : 0;
|
|
bits[3] = here[1] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x + 2; // en haut à droite
|
|
test.y = cel.y - 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[2] = here[1] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x + 2; // à droite
|
|
test.y = cel.y;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[0] = here[1] ? 1 : 0;
|
|
bits[2] = here[3] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x + 2; // en bas à droite
|
|
test.y = cel.y + 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[0] = here[3] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x; // en bas
|
|
test.y = cel.y + 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[0] = here[2] ? 1 : 0;
|
|
bits[1] = here[3] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
|
|
test.x = cel.x - 2; // en bas à gauche
|
|
test.y = cel.y + 2;
|
|
if (GetSeeBits (test, bits, index))
|
|
{
|
|
CopyBits (init, bits);
|
|
bits[1] = here[2] ? 1 : 0;
|
|
icon = GetSeeIcon (bits, index);
|
|
if (ChangeBits (init, bits) && icon != -1)
|
|
m_decor[test.x / 2][test.y / 2].floorIcon = icon;
|
|
}
|
|
}
|
|
}
|
|
|
|
// clang-format off
|
|
// Cette table donne les directions dans l'ordre
|
|
// est-sud-ouest-nord pour les murs.
|
|
static const char tableMur[5 * 15] =
|
|
{
|
|
20, 1, 0, 1, 0,
|
|
21, 0, 1, 0, 1,
|
|
22, 1, 1, 0, 0,
|
|
23, 0, 1, 1, 0,
|
|
24, 0, 0, 1, 1,
|
|
25, 1, 0, 0, 1,
|
|
26, 1, 1, 1, 1,
|
|
|
|
26, 0, 1, 1, 1,
|
|
26, 1, 0, 1, 1,
|
|
26, 1, 1, 0, 1,
|
|
26, 1, 1, 1, 0,
|
|
|
|
20, 1, 0, 0, 0,
|
|
20, 0, 0, 1, 0,
|
|
21, 0, 1, 0, 0,
|
|
21, 0, 0, 0, 1,
|
|
};
|
|
|
|
static const Sint16 tableMurDir[4 * 2] =
|
|
{
|
|
+2, 0, // est
|
|
0, +2, // sur
|
|
-2, 0, // ouest
|
|
0, -2, // nord
|
|
};
|
|
// clang-format on
|
|
|
|
// Arrange un mur en fonction des autres murs dans toutes
|
|
// les directions.
|
|
// index=0 si mur (20..26)
|
|
// index=1 si palissade (65..71)
|
|
// index=2 si barrière (106..112)
|
|
|
|
void
|
|
CDecor::ArrangeMur (Point cel, Sint32 & icon, Sint32 index)
|
|
{
|
|
Sint32 i, x, y, channel;
|
|
Sint32 first, last, matiere;
|
|
Sint32 icons[4];
|
|
char murs[4];
|
|
|
|
if (index == 0)
|
|
{
|
|
first = 20;
|
|
last = 26;
|
|
matiere = 44; // pierres
|
|
}
|
|
if (index == 1)
|
|
{
|
|
first = 65;
|
|
last = 71;
|
|
matiere = 36; // planches
|
|
}
|
|
if (index == 2)
|
|
{
|
|
first = 106;
|
|
last = 112;
|
|
matiere = 36; // planches
|
|
}
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
x = cel.x + tableMurDir[i * 2 + 0];
|
|
y = cel.y + tableMurDir[i * 2 + 1];
|
|
|
|
if (IsValid (GetCel (x, y)))
|
|
{
|
|
icons[i] = m_decor[x / 2][y / 2].objectIcon;
|
|
if (icons[i] == matiere) // pierres/planches ?
|
|
MoveGetObject (GetCel (x, y), channel, icons[i]);
|
|
|
|
if (icons[i] < first || icons[i] > last)
|
|
icons[i] = -1;
|
|
}
|
|
else
|
|
icons[i] = -1;
|
|
}
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (icons[i] == -1)
|
|
murs[i] = 0;
|
|
else
|
|
murs[i] = tableMur[(icons[i] - first) * 5 + 1 + ((i + 2) % 4)];
|
|
}
|
|
|
|
for (i = 0; i < 15; i++)
|
|
{
|
|
if (
|
|
murs[0] == tableMur[i * 5 + 1] && murs[1] == tableMur[i * 5 + 2] &&
|
|
murs[2] == tableMur[i * 5 + 3] && murs[3] == tableMur[i * 5 + 4])
|
|
{
|
|
icon = tableMur[i * 5 + 0];
|
|
icon += first - 20;
|
|
return;
|
|
}
|
|
}
|
|
|
|
icon = -1;
|
|
}
|
|
|
|
// Arrange les objets avant une construction.
|
|
|
|
void
|
|
CDecor::ArrangeBuild (Point cel, Sint32 & channel, Sint32 & icon)
|
|
{
|
|
Sint32 index, i, x, y;
|
|
Sint32 first, last, matiere;
|
|
Sint32 oldChannel, oldIcon;
|
|
|
|
for (index = 0; index < 3; index++)
|
|
{
|
|
if (index == 0)
|
|
{
|
|
first = 20;
|
|
last = 26;
|
|
matiere = 44; // pierres
|
|
}
|
|
if (index == 1)
|
|
{
|
|
first = 65;
|
|
last = 71;
|
|
matiere = 36; // planches
|
|
}
|
|
if (index == 2)
|
|
{
|
|
first = 106;
|
|
last = 112;
|
|
matiere = 36; // planches
|
|
}
|
|
|
|
// Rien à faire si pas mur.
|
|
if (channel != CHOBJECT || icon != last)
|
|
continue;
|
|
|
|
oldChannel = m_decor[cel.x / 2][cel.y / 2].objectChannel;
|
|
oldIcon = m_decor[cel.x / 2][cel.y / 2].objectIcon;
|
|
|
|
m_decor[cel.x / 2][cel.y / 2].objectChannel = channel;
|
|
m_decor[cel.x / 2][cel.y / 2].objectIcon = icon;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
x = cel.x + tableMurDir[i * 2 + 0];
|
|
y = cel.y + tableMurDir[i * 2 + 1];
|
|
|
|
if (IsValid (GetCel (x, y)))
|
|
{
|
|
icon = m_decor[x / 2][y / 2].objectIcon;
|
|
if (icon == matiere) // pierres/planches ?
|
|
MoveGetObject (GetCel (x, y), channel, icon);
|
|
|
|
if (icon >= first && icon <= last)
|
|
{
|
|
ArrangeMur (GetCel (x, y), icon, index);
|
|
|
|
if (icon != -1)
|
|
{
|
|
if (!MovePutObject (GetCel (x, y), channel, icon))
|
|
{
|
|
m_decor[x / 2][y / 2].objectChannel = channel;
|
|
m_decor[x / 2][y / 2].objectIcon = icon;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_decor[cel.x / 2][cel.y / 2].objectChannel = oldChannel;
|
|
m_decor[cel.x / 2][cel.y / 2].objectIcon = oldIcon;
|
|
|
|
ArrangeMur (cel, icon, index);
|
|
if (icon == -1)
|
|
icon = last;
|
|
}
|
|
}
|
|
|
|
// Arrange les objets après une modification.
|
|
|
|
void
|
|
CDecor::ArrangeObject (Point cel)
|
|
{
|
|
Sint32 channel, icon;
|
|
Sint32 first, last;
|
|
Sint32 index, i, j, k, x, y;
|
|
Point vector, test, pos;
|
|
bool bTour;
|
|
|
|
for (index = 0; index < 3; index++)
|
|
{
|
|
if (index == 0)
|
|
{
|
|
first = 20; // murs
|
|
last = 26;
|
|
}
|
|
if (index == 1)
|
|
{
|
|
first = 65; // palissades
|
|
last = 71;
|
|
}
|
|
if (index == 2)
|
|
{
|
|
first = 106; // barrière
|
|
last = 112;
|
|
}
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
x = cel.x + tableMurDir[i * 2 + 0];
|
|
y = cel.y + tableMurDir[i * 2 + 1];
|
|
|
|
if (IsValid (GetCel (x, y)))
|
|
{
|
|
icon = m_decor[x / 2][y / 2].objectIcon;
|
|
if (icon >= first && icon <= last)
|
|
{
|
|
ArrangeMur (GetCel (x, y), icon, index);
|
|
|
|
if (icon != -1)
|
|
{
|
|
m_decor[x / 2][y / 2].objectChannel = CHOBJECT;
|
|
m_decor[x / 2][y / 2].objectIcon = icon;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_decor[cel.x / 2][cel.y / 2].objectIcon == last)
|
|
{
|
|
ArrangeMur (cel, icon, index);
|
|
if (icon == -1)
|
|
icon = last;
|
|
|
|
m_decor[cel.x / 2][cel.y / 2].objectChannel = CHOBJECT;
|
|
m_decor[cel.x / 2][cel.y / 2].objectIcon = icon;
|
|
}
|
|
}
|
|
|
|
if (
|
|
g_restoreBugs &&
|
|
(m_decor[cel.x / 2][cel.y / 2].objectIcon != 27 && // not a tower?
|
|
m_decor[cel.x / 2][cel.y / 2].objectIcon != -1))
|
|
return;
|
|
|
|
// Arrange les rayons entre les tours.
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
vector = GetVector (i * 2 * 16);
|
|
test = cel;
|
|
|
|
bTour = false;
|
|
j = 0;
|
|
while (true)
|
|
{
|
|
test.x += vector.x * 2;
|
|
test.y += vector.y * 2;
|
|
|
|
if (m_decor[test.x / 2][test.y / 2].objectIcon == 27) // tour ?
|
|
{
|
|
bTour = true;
|
|
break;
|
|
}
|
|
|
|
if (
|
|
m_decor[test.x / 2][test.y / 2].objectIcon != -1 &&
|
|
m_decor[test.x / 2][test.y / 2].objectIcon != 10001 - i % 2)
|
|
break;
|
|
|
|
j++;
|
|
if (j >= 2 + 1)
|
|
break;
|
|
}
|
|
|
|
if (m_decor[cel.x / 2][cel.y / 2].objectIcon != 27) // pas tour ?
|
|
bTour = false;
|
|
|
|
test = cel;
|
|
for (k = 0; k < j; k++)
|
|
{
|
|
test.x += vector.x * 2;
|
|
test.y += vector.y * 2;
|
|
|
|
if (bTour)
|
|
{
|
|
channel = CHOBJECT;
|
|
icon = 10001 - i % 2; // rayon e-o (10001) ou n-s (10000)
|
|
}
|
|
else
|
|
{
|
|
channel = -1;
|
|
icon = -1;
|
|
}
|
|
m_decor[test.x / 2][test.y / 2].objectChannel = channel;
|
|
m_decor[test.x / 2][test.y / 2].objectIcon = icon;
|
|
|
|
if (!m_bBuild && bTour)
|
|
{
|
|
if (MoveCreate (
|
|
test, -1, false, CHOBJECT, -1, -1, -1, 9999, 1, 0, true))
|
|
{
|
|
MoveAddIcons (test, 5 - i % 2, true); // éclairs
|
|
}
|
|
|
|
pos = ConvCelToPos (test);
|
|
m_pSound->PlayImage (SOUND_RAYON1, pos);
|
|
}
|
|
|
|
if (!m_bBuild && !bTour)
|
|
MoveFinish (test);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test s'il faut remplir le sol ici.
|
|
|
|
bool
|
|
CDecor::ArrangeFillTestFloor (Point cel1, Point cel2)
|
|
{
|
|
Point cel;
|
|
Sint32 icon1, icon2;
|
|
|
|
icon1 = m_fillSearchIcon;
|
|
icon2 = m_fillSearchIcon;
|
|
|
|
if (
|
|
m_fillPutChannel == CHFLOOR && m_fillPutIcon == 1 && // met de l'herbe..
|
|
m_fillSearchIcon == 14) // ..sur de l'eau ?
|
|
{
|
|
icon1 = 2;
|
|
icon2 = 14; // eau & rives
|
|
}
|
|
|
|
if (
|
|
m_fillPutChannel == CHFLOOR && m_fillPutIcon == 14 && // met de l'eau..
|
|
m_fillSearchIcon == 1) // ..sur de l'herbe ?
|
|
{
|
|
icon1 = 1;
|
|
icon2 = 13; // herbe & rives
|
|
}
|
|
|
|
for (cel.x = cel1.x; cel.x <= cel2.x; cel.x += 2)
|
|
{
|
|
for (cel.y = cel1.y; cel.y <= cel2.y; cel.y += 2)
|
|
{
|
|
if (!IsValid (cel))
|
|
continue;
|
|
|
|
if (
|
|
m_decor[cel.x / 2][cel.y / 2].floorChannel != m_fillSearchChannel ||
|
|
m_decor[cel.x / 2][cel.y / 2].floorIcon < icon1 ||
|
|
m_decor[cel.x / 2][cel.y / 2].floorIcon > icon2)
|
|
return false;
|
|
|
|
if (
|
|
m_fillPutChannel == CHFLOOR && m_fillPutIcon == 14 && // met de l'eau ?
|
|
m_decor[cel.x / 2][cel.y / 2].objectIcon != -1)
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (
|
|
m_fillPutChannel == CHFLOOR && m_fillPutIcon == 14 && // met de l'eau ?
|
|
IsBlupiHereEx (cel1, cel2, -1, false))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Test s'il faut remplir ici.
|
|
|
|
bool
|
|
CDecor::ArrangeFillTest (Point pos)
|
|
{
|
|
Point cel1, cel2;
|
|
|
|
if (m_pFillMap[(pos.x / 2) + (pos.y / 2) * (MAXCELX / 2)] == 1)
|
|
return false;
|
|
|
|
if (m_bFillFloor)
|
|
{
|
|
cel1.x = pos.x - 2;
|
|
cel1.y = pos.y - 2;
|
|
cel2.x = pos.x + 3;
|
|
cel2.y = pos.y + 3;
|
|
return ArrangeFillTestFloor (cel1, cel2);
|
|
}
|
|
else
|
|
{
|
|
if (
|
|
m_decor[pos.x / 2][pos.y / 2].objectChannel == m_fillSearchChannel &&
|
|
m_decor[pos.x / 2][pos.y / 2].objectIcon == m_fillSearchIcon &&
|
|
!IsBlupiHereEx (
|
|
GetCel (pos.x + 0, pos.y + 0), GetCel (pos.x + 1, pos.y + 1), -1,
|
|
false))
|
|
{
|
|
if (
|
|
m_decor[pos.x / 2][pos.y / 2].floorChannel == CHFLOOR &&
|
|
m_decor[pos.x / 2][pos.y / 2].floorIcon >= 2 &&
|
|
m_decor[pos.x / 2][pos.y / 2].floorIcon <= 14) // rive ou eau ?
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Modifie le décor lors d'un remplissage.
|
|
|
|
void
|
|
CDecor::ArrangeFillPut (Point pos, Sint32 channel, Sint32 icon)
|
|
{
|
|
if (m_bFillFloor)
|
|
{
|
|
PutFloor (pos, channel, icon);
|
|
ArrangeFloor (pos);
|
|
}
|
|
else
|
|
{
|
|
if (icon >= 0 && icon <= 5) // plantes ?
|
|
icon = Random (0, 5);
|
|
if (icon >= 6 && icon <= 11) // arbres ?
|
|
icon = Random (6, 11);
|
|
if (icon >= 37 && icon <= 43) // rochers ?
|
|
icon = Random (37, 43);
|
|
PutObject (pos, channel, icon);
|
|
ArrangeObject (pos);
|
|
}
|
|
}
|
|
|
|
// Rempli un sol à partir d'une position donnée.
|
|
|
|
void
|
|
CDecor::ArrangeFillSearch (Point pos)
|
|
{
|
|
Sint32 startX, endX;
|
|
|
|
// Cherche la borne gauche.
|
|
startX = pos.x;
|
|
endX = pos.x;
|
|
while (pos.x > 0 && ArrangeFillTest (pos))
|
|
pos.x -= 2;
|
|
startX = pos.x + 2;
|
|
|
|
// Cherche la borne droite.
|
|
pos.x = endX;
|
|
while (pos.x < MAXCELX - 2 && ArrangeFillTest (pos))
|
|
pos.x += 2;
|
|
endX = pos.x - 2;
|
|
|
|
// Rempli toute la ligne trouvée.
|
|
pos.x = startX;
|
|
while (pos.x <= endX)
|
|
{
|
|
m_pFillMap[(pos.x / 2) + (pos.y / 2) * (MAXCELX / 2)] = 1;
|
|
pos.x += 2;
|
|
}
|
|
|
|
// Cherche la ligne au-dessus.
|
|
if (pos.y > 0)
|
|
{
|
|
pos.y -= 2;
|
|
pos.x = startX;
|
|
while (pos.x <= endX)
|
|
{
|
|
while (pos.x <= endX && !ArrangeFillTest (pos))
|
|
pos.x += 2;
|
|
if (pos.x > endX)
|
|
break;
|
|
|
|
if (ArrangeFillTest (pos))
|
|
{
|
|
ArrangeFillSearch (pos); // appel récursif
|
|
}
|
|
|
|
while (pos.x <= endX && ArrangeFillTest (pos))
|
|
pos.x += 2;
|
|
}
|
|
pos.y += 2;
|
|
}
|
|
|
|
// Cherche la ligne au-dessous.
|
|
if (pos.y < MAXCELY - 2)
|
|
{
|
|
pos.y += 2;
|
|
pos.x = startX;
|
|
while (pos.x <= endX)
|
|
{
|
|
while (pos.x <= endX && !ArrangeFillTest (pos))
|
|
pos.x += 2;
|
|
if (pos.x > endX)
|
|
break;
|
|
|
|
if (ArrangeFillTest (pos))
|
|
{
|
|
ArrangeFillSearch (pos); // appel récursif
|
|
}
|
|
|
|
while (pos.x <= endX && ArrangeFillTest (pos))
|
|
pos.x += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Rempli un sol à partir d'une position donnée.
|
|
|
|
void
|
|
CDecor::ArrangeFill (Point pos, Sint32 channel, Sint32 icon, bool bFloor)
|
|
{
|
|
m_bFillFloor = bFloor;
|
|
|
|
pos.x = (pos.x / 2) * 2;
|
|
pos.y = (pos.y / 2) * 2;
|
|
|
|
m_fillPutChannel = channel;
|
|
m_fillPutIcon = icon;
|
|
|
|
if (bFloor)
|
|
GetFloor (pos, m_fillSearchChannel, m_fillSearchIcon);
|
|
else
|
|
GetObject (pos, m_fillSearchChannel, m_fillSearchIcon);
|
|
|
|
m_pFillMap = (char *) malloc (MAXCELX * MAXCELY * sizeof (char) / 4);
|
|
if (m_pFillMap == nullptr)
|
|
return;
|
|
memset (m_pFillMap, 0, MAXCELX * MAXCELY * sizeof (char) / 4);
|
|
|
|
ArrangeFillSearch (pos);
|
|
|
|
for (pos.x = 0; pos.x < MAXCELX; pos.x += 2)
|
|
{
|
|
for (pos.y = 0; pos.y < MAXCELY; pos.y += 2)
|
|
{
|
|
if (m_pFillMap[(pos.x / 2) + (pos.y / 2) * (MAXCELX / 2)] == 1)
|
|
ArrangeFillPut (pos, channel, icon);
|
|
}
|
|
}
|
|
|
|
free (m_pFillMap);
|
|
}
|
|
|
|
// Supprime tous les personnages bloqués dans des murs
|
|
// ou debout sur l'eau.
|
|
|
|
void
|
|
CDecor::ArrangeBlupi ()
|
|
{
|
|
Sint32 rank;
|
|
|
|
for (rank = 0; rank < MAXBLUPI; rank++)
|
|
{
|
|
if (m_blupi[rank].bExist)
|
|
{
|
|
if (!IsFreeCel (m_blupi[rank].cel, rank))
|
|
m_blupi[rank].bExist = false;
|
|
}
|
|
}
|
|
}
|