mirror of
https://github.com/blupi-games/planetblupi
synced 2024-12-30 10:15:36 +01:00
4895 lines
105 KiB
C++
4895 lines
105 KiB
C++
// DecBlupi.cpp
|
|
//
|
|
|
|
#include "DEF.H"
|
|
#include "DECOR.H"
|
|
#include "ACTION.H"
|
|
#include "MISC.H"
|
|
#include "RESOURCE.H"
|
|
#include "decgoal.h"
|
|
|
|
// Cette table donne l'action à effectuer pour un bouton
|
|
// enfoncé.
|
|
short table_actions[] =
|
|
{
|
|
WM_ACTION_GO,
|
|
WM_ACTION_STOP,
|
|
WM_ACTION_MANGE,
|
|
WM_ACTION_CARRY,
|
|
WM_ACTION_DEPOSE,
|
|
WM_ACTION_ABAT1,
|
|
WM_ACTION_ROC1,
|
|
WM_ACTION_CULTIVE,
|
|
WM_ACTION_BUILD1,
|
|
WM_ACTION_BUILD2,
|
|
WM_ACTION_BUILD3,
|
|
WM_ACTION_BUILD4,
|
|
WM_ACTION_BUILD5,
|
|
WM_ACTION_BUILD6,
|
|
WM_ACTION_MUR,
|
|
WM_ACTION_PALIS,
|
|
WM_ACTION_ABAT1,
|
|
WM_ACTION_ROC1,
|
|
WM_ACTION_PONTE,
|
|
WM_ACTION_TOUR,
|
|
WM_ACTION_BOIT,
|
|
WM_ACTION_LABO,
|
|
WM_ACTION_FLEUR1,
|
|
WM_ACTION_FLEUR1,
|
|
WM_ACTION_DYNAMITE,
|
|
WM_ACTION_BATEAUE,
|
|
WM_ACTION_DJEEP,
|
|
WM_ACTION_DRAPEAU,
|
|
WM_ACTION_EXTRAIT,
|
|
WM_ACTION_FABJEEP,
|
|
WM_ACTION_FABMINE,
|
|
WM_ACTION_FABDISC,
|
|
WM_ACTION_REPEAT,
|
|
WM_ACTION_DARMURE,
|
|
WM_ACTION_FABARMURE,
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Supprime tous les blupi.
|
|
|
|
void CDecor::BlupiFlush()
|
|
{
|
|
int i;
|
|
|
|
memset(m_blupi, 0, sizeof(Blupi)*MAXBLUPI);
|
|
|
|
for ( i=0 ; i<MAXBLUPI ; i++ )
|
|
{
|
|
m_blupi[i].bExist = false;
|
|
}
|
|
}
|
|
|
|
// Crée un nouveau blupi, et retourne son rang.
|
|
|
|
int CDecor::BlupiCreate(POINT cel, int action, int direct,
|
|
int perso, int energy)
|
|
{
|
|
int rank;
|
|
|
|
if ( perso == 0 && action == ACTION_STOP && // blupi ?
|
|
energy <= MAXENERGY/4 )
|
|
{
|
|
action = ACTION_STOPf;
|
|
}
|
|
|
|
if ( perso == 1 && action == ACTION_STOP ) // araignée ?
|
|
{
|
|
action = ACTION_A_STOP;
|
|
}
|
|
|
|
if ( perso == 2 && action == ACTION_STOP ) // virus ?
|
|
{
|
|
action = ACTION_V_STOP;
|
|
}
|
|
|
|
if ( perso == 3 && action == ACTION_STOP ) // tracks ?
|
|
{
|
|
action = ACTION_T_STOP;
|
|
}
|
|
|
|
if ( perso == 4 && action == ACTION_STOP ) // robot ?
|
|
{
|
|
action = ACTION_R_STOP;
|
|
}
|
|
|
|
if ( perso == 5 && action == ACTION_STOP ) // bombe ?
|
|
{
|
|
action = ACTION_B_STOP;
|
|
}
|
|
|
|
if ( perso == 7 && action == ACTION_STOP ) // électro ?
|
|
{
|
|
action = ACTION_E_STOP;
|
|
}
|
|
|
|
if ( perso == 8 && action == ACTION_STOP ) // disciple ?
|
|
{
|
|
action = ACTION_D_STOP;
|
|
}
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].cel.x == cel.x &&
|
|
m_blupi[rank].cel.y == cel.y )
|
|
{
|
|
m_blupi[rank].aDirect = ((m_blupi[rank].aDirect/16+1)%8)*16;
|
|
m_blupi[rank].sDirect = m_blupi[rank].aDirect;
|
|
m_blupi[rank].perso = perso;
|
|
m_blupi[rank].energy = energy;
|
|
m_blupi[rank].action = action;
|
|
BlupiActualise(rank);
|
|
return rank;
|
|
}
|
|
}
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( !m_blupi[rank].bExist )
|
|
{
|
|
m_blupi[rank].bExist = true;
|
|
m_blupi[rank].bHili = false;
|
|
m_blupi[rank].perso = perso;
|
|
m_blupi[rank].energy = energy;
|
|
m_blupi[rank].goalAction = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].goalCel.y = -1;
|
|
m_blupi[rank].cel = cel;
|
|
m_blupi[rank].fix = cel;
|
|
m_blupi[rank].action = action;
|
|
m_blupi[rank].interrupt = 1;
|
|
m_blupi[rank].aDirect = direct;
|
|
m_blupi[rank].sDirect = direct;
|
|
m_blupi[rank].phase = 0;
|
|
m_blupi[rank].step = rank*13; // un peu de hazard !
|
|
m_blupi[rank].channel = -1;
|
|
m_blupi[rank].icon = -1;
|
|
m_blupi[rank].lastIcon = -1;
|
|
m_blupi[rank].pos.x = 0;
|
|
m_blupi[rank].pos.y = 0;
|
|
m_blupi[rank].posZ = 0;
|
|
m_blupi[rank].takeChannel = -1;
|
|
m_blupi[rank].passCel.x = -1;
|
|
m_blupi[rank].jaugePhase = -1;
|
|
m_blupi[rank].jaugeMax = -1;
|
|
m_blupi[rank].stop = 0;
|
|
m_blupi[rank].bArrow = false;
|
|
m_blupi[rank].bRepeat = false;
|
|
m_blupi[rank].bMalade = false;
|
|
m_blupi[rank].bCache = false;
|
|
m_blupi[rank].vehicule = 0;
|
|
m_blupi[rank].busyCount = 0;
|
|
m_blupi[rank].busyDelay = 0;
|
|
m_blupi[rank].clicCount = 0;
|
|
m_blupi[rank].clicDelay = 0;
|
|
|
|
ListFlush(rank);
|
|
FlushUsed(rank);
|
|
BlupiDestCel(rank);
|
|
BlupiPushFog(rank);
|
|
BlupiActualise(rank);
|
|
return rank;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Supprime un blupi existant.
|
|
// Si perso == -1, supprime n'importe quel personnage ici.
|
|
// Si perso >= 0, supprime seulement ce personnage.
|
|
|
|
bool CDecor::BlupiDelete(POINT cel, int perso)
|
|
{
|
|
int rank;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].cel.x == cel.x &&
|
|
m_blupi[rank].cel.y == cel.y &&
|
|
(perso == -1 || m_blupi[rank].perso == perso) )
|
|
{
|
|
m_blupi[rank].bExist = false;
|
|
|
|
if ( !m_bBuild ) // phase de jeu ?
|
|
{
|
|
if ( perso == 6 ) // détonnateur invisible ?
|
|
{
|
|
MoveFinish(rank); // stoppe décompte à rebourd
|
|
}
|
|
if ( m_nbBlupiHili > 0 &&
|
|
m_rankBlupiHili == rank ) // est-ce le blupi sélectionné ?
|
|
{
|
|
m_nbBlupiHili = 0;
|
|
m_rankBlupiHili = -1;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Supprime un blupi existant.
|
|
|
|
void CDecor::BlupiDelete(int rank)
|
|
{
|
|
m_blupi[rank].bExist = false;
|
|
|
|
if ( !m_bBuild && // phase de jeu ?
|
|
m_nbBlupiHili > 0 &&
|
|
m_rankBlupiHili == rank ) // est-ce le blupi sélectionné ?
|
|
{
|
|
m_nbBlupiHili = 0;
|
|
m_rankBlupiHili = -1;
|
|
}
|
|
}
|
|
|
|
// Supprime tout dans un périmètre donné suite à une explosion.
|
|
// type=0 -> explosion
|
|
// type=1 -> électro
|
|
|
|
void CDecor::BlupiKill(int exRank, POINT cel, int type)
|
|
{
|
|
int rank, action, x, y, icon;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
// Supprime sans condition les blupi placés
|
|
// dans la cellule où a lieu l'explosion.
|
|
if ( rank != exRank &&
|
|
m_blupi[rank].bExist &&
|
|
m_blupi[rank].vehicule != 3 && // pas armure ?
|
|
!m_bInvincible &&
|
|
m_blupi[rank].cel.x >= cel.x &&
|
|
m_blupi[rank].cel.x <= cel.x+1 &&
|
|
m_blupi[rank].cel.y >= cel.y &&
|
|
m_blupi[rank].cel.y <= cel.y+1 )
|
|
{
|
|
GoalUnwork(rank);
|
|
|
|
if ( type == 0 ) // explosion ?
|
|
{
|
|
m_blupi[rank].bExist = false; // mort instantannée
|
|
}
|
|
|
|
if ( type == 1 ) // électro ?
|
|
{
|
|
x = m_blupi[rank].cel.x;
|
|
y = m_blupi[rank].cel.y;
|
|
icon = m_decor[x/2][y/2].objectIcon;
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule == 0 && // à pied ?
|
|
!m_bInvincible &&
|
|
icon != 113 && // maison ?
|
|
icon != 28 && icon != 29 && // laboratoire ?
|
|
icon != 119 && icon != 120 && // usine ?
|
|
icon != 121 && icon != 122 ) // mine de fer ?
|
|
{
|
|
if ( m_blupi[rank].bMalade )
|
|
{
|
|
action = WM_ACTION_ELECTROm;
|
|
}
|
|
else
|
|
{
|
|
action = WM_ACTION_ELECTRO;
|
|
}
|
|
GoalStart(rank, action, m_blupi[rank].cel);
|
|
//? BlupiChangeAction(rank, ACTION_ELECTRO);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Supprime les blupi placés une case autour de la
|
|
// cellule où a lieu l'explosion, seulement s'ils
|
|
// ne sont pas cachés (pas dans un batiment).
|
|
if ( type == 0 &&
|
|
rank != exRank &&
|
|
m_blupi[rank].bExist &&
|
|
m_blupi[rank].vehicule != 3 && // pas armure ?
|
|
!m_bInvincible &&
|
|
!m_blupi[rank].bCache && // pas dans un batiment ?
|
|
m_blupi[rank].cel.x >= cel.x-1 &&
|
|
m_blupi[rank].cel.x <= cel.x+2 &&
|
|
m_blupi[rank].cel.y >= cel.y-1 &&
|
|
m_blupi[rank].cel.y <= cel.y+2 )
|
|
{
|
|
GoalUnwork(rank);
|
|
m_blupi[rank].bExist = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Test si un blupi existe.
|
|
|
|
bool CDecor::BlupiIfExist(int rank)
|
|
{
|
|
return !!m_blupi[rank].bExist;
|
|
}
|
|
|
|
|
|
// Triche pour tous les blupi.
|
|
// #1 -> (POWER) redonne l'énergie maximale
|
|
// #2 -> (LONESOME) tue toutes les araignées/virus/etc.
|
|
|
|
void CDecor::BlupiCheat(int cheat)
|
|
{
|
|
int rank;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( cheat == 1 ) // power ?
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].perso == 0 )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY;
|
|
m_blupi[rank].bMalade = false;
|
|
}
|
|
}
|
|
|
|
if ( cheat == 2 ) // lonesome ?
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].perso != 0 &&
|
|
m_blupi[rank].perso != 8 ) // araignée/virus/etc. ?
|
|
{
|
|
m_blupi[rank].bExist = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Actualise un blupi pour pouvoir le dessiner dans son état.
|
|
|
|
void CDecor::BlupiActualise(int rank)
|
|
{
|
|
short sound;
|
|
|
|
Action(m_blupi[rank].action,
|
|
m_blupi[rank].aDirect,
|
|
m_blupi[rank].phase,
|
|
m_blupi[rank].step,
|
|
m_blupi[rank].channel,
|
|
m_blupi[rank].icon,
|
|
m_blupi[rank].pos,
|
|
m_blupi[rank].posZ,
|
|
sound);
|
|
BlupiAdaptIcon(rank);
|
|
|
|
m_blupi[rank].lastIcon = -1;
|
|
m_blupi[rank].phase = 0;
|
|
m_blupi[rank].pos.x = 0;
|
|
m_blupi[rank].pos.y = 0;
|
|
m_blupi[rank].posZ = 0;
|
|
}
|
|
|
|
// Adapte une icône.
|
|
|
|
void CDecor::BlupiAdaptIcon(int rank)
|
|
{
|
|
int direct;
|
|
|
|
if ( m_blupi[rank].icon == -1 ) return;
|
|
|
|
if ( m_blupi[rank].bMalade ) // malade ?
|
|
{
|
|
if ( m_blupi[rank].icon >= 69 &&
|
|
m_blupi[rank].icon <= 92 )
|
|
{
|
|
m_blupi[rank].icon += 100; // 169..192 (tout vert)
|
|
}
|
|
else if ( m_blupi[rank].icon == 270 ) // écrasé ?
|
|
{
|
|
m_blupi[rank].icon = 271;
|
|
}
|
|
else if ( m_blupi[rank].icon < 318 || // pas télétransporté ?
|
|
m_blupi[rank].icon > 321 )
|
|
{
|
|
direct = GetIconDirect(m_blupi[rank].icon);
|
|
if ( direct < 0 )
|
|
{
|
|
m_blupi[rank].icon = 169; // debout direction est !
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].icon = 169+3*(direct/16);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule == 1 ) // en bateau ?
|
|
{
|
|
direct = GetIconDirect(m_blupi[rank].icon);
|
|
if ( direct < 0 )
|
|
{
|
|
m_blupi[rank].icon = 234; // bateau direction est !
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].icon = 234+(direct/(16/2));
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule == 2 ) // en jeep ?
|
|
{
|
|
direct = GetIconDirect(m_blupi[rank].icon);
|
|
if ( direct < 0 )
|
|
{
|
|
m_blupi[rank].icon = 250; // bateau direction est !
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].icon = 250+(direct/(16/2));
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule == 3 ) // armure ?
|
|
{
|
|
if ( m_blupi[rank].icon < 322 ||
|
|
m_blupi[rank].icon > 347 )
|
|
{
|
|
if ( m_blupi[rank].icon == 106 || // élan pour saut ?
|
|
m_blupi[rank].icon == 194 ) // mèche ?
|
|
{
|
|
m_blupi[rank].icon = 347;
|
|
}
|
|
else
|
|
{
|
|
direct = GetIconDirect(m_blupi[rank].icon);
|
|
if ( direct < 0 )
|
|
{
|
|
m_blupi[rank].icon = 322; // armure direction est !
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].icon = 322+3*(direct/16);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 8 ) // disciple ?
|
|
{
|
|
direct = GetIconDirect(m_blupi[rank].icon);
|
|
if ( direct < 0 )
|
|
{
|
|
m_blupi[rank].icon = 290; // disciple direction est !
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].icon = 290+(direct/(16/2));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Fait entendre un son pour un blupi.
|
|
// Si bStop=true, on stoppe le son précédent associé
|
|
// à ce blupi (rank), si nécessaire.
|
|
|
|
void CDecor::BlupiSound(int rank, int sound, POINT pos, bool bStop)
|
|
{
|
|
int newSound;
|
|
|
|
if ( rank == -1 )
|
|
{
|
|
rank = m_rankBlupiHili;
|
|
}
|
|
|
|
if ( rank != -1 && m_blupi[rank].perso == 8 ) // disciple ?
|
|
{
|
|
if ( sound == SOUND_HOP ||
|
|
sound == SOUND_BRULE ||
|
|
sound == SOUND_TCHAO ||
|
|
sound == SOUND_FLEUR ||
|
|
sound == SOUND_ARROSE )
|
|
{
|
|
newSound = -1;
|
|
}
|
|
else
|
|
{
|
|
newSound = sound;
|
|
}
|
|
|
|
if ( sound == SOUND_BOING ||
|
|
sound == SOUND_BOING1 ||
|
|
sound == SOUND_BOING2 ||
|
|
sound == SOUND_BOING3 )
|
|
{
|
|
newSound = SOUND_D_BOING;
|
|
}
|
|
if ( sound == SOUND_GO1 ||
|
|
sound == SOUND_GO2 ||
|
|
sound == SOUND_GO3 ||
|
|
sound == SOUND_GO4 ||
|
|
sound == SOUND_GO5 ||
|
|
sound == SOUND_GO6 )
|
|
{
|
|
newSound = SOUND_D_GO;
|
|
}
|
|
if ( sound == SOUND_OK1 ||
|
|
sound == SOUND_OK2 ||
|
|
sound == SOUND_OK3 ||
|
|
sound == SOUND_OK4 ||
|
|
sound == SOUND_OK5 ||
|
|
sound == SOUND_OK6 ||
|
|
sound == SOUND_OK1f ||
|
|
sound == SOUND_OK2f ||
|
|
sound == SOUND_OK3f ||
|
|
sound == SOUND_OK1e ||
|
|
sound == SOUND_OK2e ||
|
|
sound == SOUND_OK3e )
|
|
{
|
|
newSound = SOUND_D_OK;
|
|
}
|
|
if ( sound == SOUND_TERM1 ||
|
|
sound == SOUND_TERM2 ||
|
|
sound == SOUND_TERM3 ||
|
|
sound == SOUND_TERM4 ||
|
|
sound == SOUND_TERM5 ||
|
|
sound == SOUND_TERM6 )
|
|
{
|
|
newSound = SOUND_D_TERM;
|
|
}
|
|
|
|
if ( newSound == -1 ) return;
|
|
sound = newSound;
|
|
}
|
|
|
|
if ( bStop )
|
|
{
|
|
m_pSound->PlayImage(sound, pos, rank);
|
|
}
|
|
else
|
|
{
|
|
m_pSound->PlayImage(sound, pos);
|
|
}
|
|
}
|
|
|
|
// Sons associés à des actions.
|
|
|
|
static short tableSound[] =
|
|
{
|
|
ACTION_BRULE, SOUND_BRULE,
|
|
ACTION_TCHAO, SOUND_TCHAO,
|
|
ACTION_MANGE, SOUND_MANGE,
|
|
ACTION_BOIT, SOUND_BOIT,
|
|
ACTION_GLISSE, SOUND_GLISSE,
|
|
ACTION_R_CHARGE, SOUND_R_CHARGE,
|
|
-1
|
|
};
|
|
|
|
// Effectue quelques initialisations pour une nouvelle action.
|
|
|
|
void CDecor::BlupiInitAction(int rank, int action, int direct)
|
|
{
|
|
short* pTable = tableSound;
|
|
POINT pos;
|
|
int rand;
|
|
|
|
while ( *pTable != -1 )
|
|
{
|
|
if ( pTable[0] == action )
|
|
{
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
BlupiSound(rank, pTable[1], pos);
|
|
break;
|
|
}
|
|
|
|
pTable += 2;
|
|
}
|
|
|
|
m_blupi[rank].action = action;
|
|
|
|
if ( m_blupi[rank].perso == 0 ) // blupi ?
|
|
{
|
|
if ( m_blupi[rank].vehicule == 1 ) // en bateau ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_STOPb;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_MARCHEb;
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].vehicule == 2 ) // en jeep ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_STOPj;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_MARCHEj;
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].vehicule == 3 ) // armure ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_STOPa;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_MARCHEa;
|
|
m_blupi[rank].step = (m_blupi[rank].step/2)*2;
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].energy <= MAXENERGY/4 ) // peu de forces ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_STOPf;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_MARCHEf;
|
|
m_blupi[rank].step = (m_blupi[rank].step/2)*2;
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP &&
|
|
m_blupi[rank].goalAction == 0 ) // à pied ?
|
|
{
|
|
rand = Random(0,400);
|
|
if ( rand >= 10 && rand <= 15 &&
|
|
m_blupi[rank].takeChannel == -1 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC1; // épaules
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
if ( rand >= 20 && rand <= 23 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC2; // grat-grat
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
if ( rand == 30 &&
|
|
m_blupi[rank].takeChannel == -1 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC3; // yoyo
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
if ( rand >= 40 && rand <= 45 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC4; // ferme les yeux
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
if ( rand == 50 &&
|
|
m_blupi[rank].takeChannel == -1 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC5; // ohé
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
if ( rand == 60 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC6; // diabolo
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
}
|
|
if ( m_blupi[rank].action == ACTION_STOPf &&
|
|
m_blupi[rank].goalAction == 0 )
|
|
{
|
|
rand = Random(0,100);
|
|
if ( rand == 10 && // propabilité 1/100
|
|
m_blupi[rank].takeChannel == -1 )
|
|
{
|
|
m_blupi[rank].action = ACTION_MISC1f;
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
}
|
|
|
|
if ( direct != -1 )
|
|
{
|
|
m_blupi[rank].sDirect = direct;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_BUILD ||
|
|
m_blupi[rank].action == ACTION_BUILDBREF ||
|
|
m_blupi[rank].action == ACTION_BUILDSEC ||
|
|
m_blupi[rank].action == ACTION_BUILDSOURD ||
|
|
m_blupi[rank].action == ACTION_BUILDPIERRE ||
|
|
m_blupi[rank].action == ACTION_PIOCHE ||
|
|
m_blupi[rank].action == ACTION_PIOCHEPIERRE ||
|
|
m_blupi[rank].action == ACTION_PIOCHESOURD ||
|
|
m_blupi[rank].action == ACTION_ARROSE ||
|
|
m_blupi[rank].action == ACTION_BECHE ||
|
|
m_blupi[rank].action == ACTION_SCIE ||
|
|
m_blupi[rank].action == ACTION_TAKE ||
|
|
m_blupi[rank].action == ACTION_DEPOSE ||
|
|
m_blupi[rank].action == ACTION_BRULE ||
|
|
m_blupi[rank].action == ACTION_TCHAO ||
|
|
m_blupi[rank].action == ACTION_GRILLE1 ||
|
|
m_blupi[rank].action == ACTION_GRILLE2 ||
|
|
m_blupi[rank].action == ACTION_GRILLE3 ||
|
|
m_blupi[rank].action == ACTION_ELECTRO ||
|
|
m_blupi[rank].action == ACTION_MANGE ||
|
|
m_blupi[rank].action == ACTION_BOIT ||
|
|
m_blupi[rank].action == ACTION_NAISSANCE ||
|
|
m_blupi[rank].action == ACTION_SAUTE1 ||
|
|
m_blupi[rank].action == ACTION_SAUTE2 ||
|
|
m_blupi[rank].action == ACTION_SAUTE3 ||
|
|
m_blupi[rank].action == ACTION_SAUTE4 ||
|
|
m_blupi[rank].action == ACTION_SAUTE5 ||
|
|
//? m_blupi[rank].action == ACTION_GLISSE ||
|
|
m_blupi[rank].action == ACTION_PONT ||
|
|
m_blupi[rank].action == ACTION_MECHE ||
|
|
m_blupi[rank].action == ACTION_A_GRILLE ||
|
|
m_blupi[rank].action == ACTION_V_GRILLE ||
|
|
m_blupi[rank].action == ACTION_T_ECRASE ||
|
|
m_blupi[rank].action == ACTION_R_MARCHE ||
|
|
m_blupi[rank].action == ACTION_R_APLAT ||
|
|
m_blupi[rank].action == ACTION_R_BUILD ||
|
|
m_blupi[rank].action == ACTION_R_CHARGE ||
|
|
m_blupi[rank].action == ACTION_B_MARCHE ||
|
|
m_blupi[rank].action == ACTION_E_MARCHE ||
|
|
m_blupi[rank].action == ACTION_MARCHEb ||
|
|
m_blupi[rank].action == ACTION_MARCHEj ||
|
|
m_blupi[rank].action == ACTION_TELEPORTE1 ||
|
|
m_blupi[rank].action == ACTION_TELEPORTE2 ||
|
|
m_blupi[rank].action == ACTION_TELEPORTE3 ||
|
|
m_blupi[rank].action == ACTION_ARMUREOPEN ||
|
|
m_blupi[rank].action == ACTION_ARMURECLOSE )
|
|
{
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 1 ) // araignée ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_A_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_A_STOP;
|
|
m_blupi[rank].sDirect = Random(0,7)*16;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 2 ) // virus ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_V_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_V_STOP;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 3 ) // tracks ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_T_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_T_STOP;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 4 ) // robot ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_R_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_R_STOP;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 5 ) // bombe ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_B_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_B_STOP;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 7 ) // électro ?
|
|
{
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_E_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_E_STOP;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 8 ) // disciple ?
|
|
{
|
|
if ( direct != -1 )
|
|
{
|
|
m_blupi[rank].sDirect = direct;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_MARCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_MARCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_STOP )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_STOP;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_PIOCHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_PIOCHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_BUILD )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_BUILD;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_SCIE )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_SCIE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_TCHAO )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_TCHAO;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_CUEILLE1 )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_CUEILLE1;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_CUEILLE2 )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_CUEILLE2;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_MECHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_MECHE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_ARROSE )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_ARROSE;
|
|
}
|
|
|
|
if ( m_blupi[rank].action == ACTION_BECHE )
|
|
{
|
|
m_blupi[rank].action = ACTION_D_BECHE;
|
|
}
|
|
|
|
m_blupi[rank].step = 0;
|
|
}
|
|
}
|
|
|
|
// Change l'action de blupi.
|
|
|
|
void CDecor::BlupiChangeAction(int rank, int action, int direct)
|
|
{
|
|
if ( rank < 0 ) return;
|
|
BlupiInitAction(rank, action, direct);
|
|
BlupiDestCel(rank);
|
|
m_blupi[rank].phase = 0;
|
|
m_blupi[rank].pos.x = 0;
|
|
m_blupi[rank].pos.y = 0;
|
|
BlupiNextAction(rank);
|
|
}
|
|
|
|
|
|
|
|
// Vide la liste des actions.
|
|
|
|
void CDecor::ListFlush(int rank)
|
|
{
|
|
int i;
|
|
|
|
for ( i=0 ; i<MAXLIST ; i++ )
|
|
{
|
|
m_blupi[rank].listButton[i] = -1;
|
|
}
|
|
m_blupi[rank].repeatLevelHope = -1;
|
|
m_blupi[rank].repeatLevel = -1;
|
|
}
|
|
|
|
// Retourne le paramètre associé à une action.
|
|
|
|
int CDecor::ListGetParam(int rank, int button, POINT cel)
|
|
{
|
|
int icon;
|
|
|
|
if ( button == BUTTON_CARRY ||
|
|
button == BUTTON_FLEUR )
|
|
{
|
|
return m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
}
|
|
|
|
if ( button == BUTTON_DEPOSE )
|
|
{
|
|
return m_blupi[rank].takeIcon;
|
|
}
|
|
|
|
if ( button == BUTTON_GO &&
|
|
cel.x%2 == 1 && cel.y%2 == 1 )
|
|
{
|
|
icon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
if ( icon == 117 || // bateau ?
|
|
icon == 118 ) // voiture ?
|
|
{
|
|
return icon;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Ajoute une action dans la liste.
|
|
|
|
bool CDecor::ListPut(int rank, int button, POINT cel, POINT cMem)
|
|
{
|
|
int i, last;
|
|
|
|
if ( button == BUTTON_REPEAT ||
|
|
button == BUTTON_GO ) return true;
|
|
|
|
// Mémorise "mange" seulement après un "cultive".
|
|
if ( button == BUTTON_MANGE &&
|
|
m_blupi[rank].listButton[0] != BUTTON_CULTIVE ) return true;
|
|
|
|
// Si prend/dépose à la suite au même endroit,
|
|
// il est inutile de mémoriser !
|
|
last = m_blupi[rank].listButton[0];
|
|
if ( (button == BUTTON_CARRY && last == BUTTON_DEPOSE) ||
|
|
(button == BUTTON_DEPOSE && last == BUTTON_CARRY ) )
|
|
{
|
|
if ( cel.x/2 == m_blupi[rank].listCel[0].x/2 &&
|
|
cel.y/2 == m_blupi[rank].listCel[0].y/2 )
|
|
{
|
|
ListRemove(rank);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
for ( i=MAXLIST-1 ; i>0 ; i-- )
|
|
{
|
|
m_blupi[rank].listButton[i] = m_blupi[rank].listButton[i-1];
|
|
m_blupi[rank].listCel[i] = m_blupi[rank].listCel[i-1];
|
|
m_blupi[rank].listParam[i] = m_blupi[rank].listParam[i-1];
|
|
}
|
|
|
|
m_blupi[rank].listButton[0] = button;
|
|
m_blupi[rank].listCel[0] = cMem;
|
|
m_blupi[rank].listParam[0] = ListGetParam(rank, button, cel);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Enlève la dernière action ajoutée dans la liste.
|
|
|
|
void CDecor::ListRemove(int rank)
|
|
{
|
|
int i;
|
|
|
|
if ( m_blupi[rank].listButton[0] == BUTTON_CULTIVE ) return;
|
|
|
|
for ( i=0 ; i<MAXLIST-1 ; i++ )
|
|
{
|
|
m_blupi[rank].listButton[i] = m_blupi[rank].listButton[i+1];
|
|
m_blupi[rank].listCel[i] = m_blupi[rank].listCel[i+1];
|
|
m_blupi[rank].listParam[i] = m_blupi[rank].listParam[i+1];
|
|
}
|
|
|
|
m_blupi[rank].listButton[MAXLIST-1] = -1;
|
|
}
|
|
|
|
// Cherche une action à répéter dans la liste.
|
|
// Retourne la profondeur de la répétition.
|
|
// Retourne -1 si aucune répétiton n'est possible.
|
|
|
|
int CDecor::ListSearch(int rank, int button, POINT cel,
|
|
int &textForButton)
|
|
{
|
|
int i, j, param, nb;
|
|
|
|
static int table_series[] =
|
|
{
|
|
TX_REPEAT_CULTIVE,
|
|
2, BUTTON_CULTIVE, BUTTON_MANGE,
|
|
|
|
TX_REPEAT_FLEUR,
|
|
4, BUTTON_FLEUR, BUTTON_CARRY, BUTTON_LABO, BUTTON_DEPOSE,
|
|
|
|
TX_REPEAT_FLEURQ,
|
|
3, BUTTON_CARRY, BUTTON_LABO, BUTTON_DEPOSE,
|
|
|
|
TX_REPEAT_FABMINE,
|
|
3, BUTTON_EXTRAIT, BUTTON_FABMINE, BUTTON_DEPOSE,
|
|
|
|
TX_REPEAT_FABJEEP,
|
|
3, BUTTON_EXTRAIT, BUTTON_FABJEEP, BUTTON_DJEEP,
|
|
|
|
TX_REPEAT_FABARMURE,
|
|
3, BUTTON_EXTRAIT, BUTTON_FABARMURE, BUTTON_DARMURE,
|
|
|
|
TX_REPEAT_PALIS,
|
|
4, BUTTON_ABAT, BUTTON_CARRY, BUTTON_DEPOSE, BUTTON_PALIS,
|
|
|
|
TX_REPEAT_PALISQ,
|
|
3, BUTTON_CARRY, BUTTON_DEPOSE, BUTTON_PALIS,
|
|
|
|
TX_REPEAT_PONT,
|
|
4, BUTTON_ABAT, BUTTON_CARRY, BUTTON_DEPOSE, BUTTON_PONT,
|
|
|
|
TX_REPEAT_PONTQ,
|
|
3, BUTTON_CARRY, BUTTON_DEPOSE, BUTTON_PONT,
|
|
|
|
TX_REPEAT_BATEAU,
|
|
4, BUTTON_ABAT, BUTTON_CARRY, BUTTON_DEPOSE, BUTTON_BATEAU,
|
|
|
|
TX_REPEAT_BATEAUQ,
|
|
3, BUTTON_CARRY, BUTTON_DEPOSE, BUTTON_BATEAU,
|
|
|
|
-1,
|
|
};
|
|
|
|
param = ListGetParam(rank, button, cel);
|
|
|
|
i = 0;
|
|
while ( table_series[i] != -1 )
|
|
{
|
|
nb = table_series[i+1];
|
|
if ( button == m_blupi[rank].listButton[nb-1] &&
|
|
param == m_blupi[rank].listParam[nb-1] &&
|
|
cel.x >= m_blupi[rank].listCel[nb-1].x-50 &&
|
|
cel.x <= m_blupi[rank].listCel[nb-1].x+50 &&
|
|
cel.y >= m_blupi[rank].listCel[nb-1].y-50 &&
|
|
cel.y <= m_blupi[rank].listCel[nb-1].y+50 )
|
|
{
|
|
for ( j=0 ; j<nb ; j++ )
|
|
{
|
|
if ( table_series[i+2+j] !=
|
|
m_blupi[rank].listButton[nb-1-j] )
|
|
{
|
|
goto next;
|
|
}
|
|
}
|
|
textForButton = table_series[i];
|
|
return nb-1;
|
|
}
|
|
|
|
next:
|
|
i += nb+2;
|
|
}
|
|
|
|
#if 0
|
|
for ( i=0 ; i<MAXLIST ; i++ )
|
|
{
|
|
if ( button == m_blupi[rank].listButton[i] &&
|
|
param == m_blupi[rank].listParam[i] &&
|
|
cel.x >= m_blupi[rank].listCel[i].x-50 &&
|
|
cel.x <= m_blupi[rank].listCel[i].x+50 &&
|
|
cel.y >= m_blupi[rank].listCel[i].y-50 &&
|
|
cel.y <= m_blupi[rank].listCel[i].y+50 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return -1;
|
|
}
|
|
|
|
// Ajuste une action à répéter.
|
|
|
|
bool CDecor::RepeatAdjust(int rank, int button,
|
|
POINT &cel, POINT &cMem, int param, int list)
|
|
{
|
|
int i, channel, icon, icon1, icon2, flags;
|
|
POINT test;
|
|
|
|
static int table_object[] =
|
|
{
|
|
BUTTON_ABAT, CHOBJECT, 6, 11,
|
|
BUTTON_ROC, CHOBJECT, 37, 43,
|
|
BUTTON_MANGE, CHOBJECT, 60, 60,
|
|
BUTTON_PALIS, CHOBJECT, 36, 36,
|
|
BUTTON_BATEAU, CHOBJECT, 36, 36,
|
|
BUTTON_DEPOSE, -1, -1, -1,
|
|
BUTTON_DJEEP, -1, -1, -1,
|
|
BUTTON_DARMURE, -1, -1, -1,
|
|
0,
|
|
};
|
|
|
|
static int table_mur[] =
|
|
{
|
|
+2, 0, // 1<<0
|
|
0,+2, // 1<<1
|
|
-2, 0, // 1<<2
|
|
0,-2, // 1<<3
|
|
};
|
|
|
|
if ( button == BUTTON_DEPOSE && // dépose pour une palissade ?
|
|
list > 0 &&
|
|
m_blupi[rank].listButton[list-1] == BUTTON_PALIS )
|
|
{
|
|
icon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
|
|
flags = 0;
|
|
if ( icon == 65 ) flags = (1<<0)|(1<<2);
|
|
if ( icon == 66 ) flags = (1<<1)|(1<<3);
|
|
if ( icon == 67 ) flags = (1<<0)|(1<<1);
|
|
if ( icon == 68 ) flags = (1<<1)|(1<<2);
|
|
if ( icon == 69 ) flags = (1<<2)|(1<<3);
|
|
if ( icon == 70 ) flags = (1<<0)|(1<<3);
|
|
if ( icon == 71 )
|
|
{
|
|
for ( i=0 ; i<4 ; i++ )
|
|
{
|
|
test.x = cel.x + table_mur[i*2+0];
|
|
test.y = cel.y + table_mur[i*2+1];
|
|
if ( IsValid(test) &&
|
|
m_decor[test.x/2][test.y/2].floorIcon == 15 && // dalle grise ?
|
|
CelOkForAction(test, WM_ACTION_DEPOSE, rank) == 0 )
|
|
{
|
|
cel = test;
|
|
cMem = test;
|
|
goto ok;
|
|
}
|
|
}
|
|
flags = (1<<0)|(1<<1)|(1<<2)|(1<<3);
|
|
}
|
|
|
|
if ( flags == 0 )
|
|
{
|
|
if ( CelOkForAction(cel, WM_ACTION_DEPOSE, rank) == 0 )
|
|
{
|
|
goto ok;
|
|
}
|
|
}
|
|
|
|
for ( i=0 ; i<4 ; i++ )
|
|
{
|
|
if ( flags & (1<<i) )
|
|
{
|
|
test.x = cel.x + table_mur[i*2+0];
|
|
test.y = cel.y + table_mur[i*2+1];
|
|
if ( CelOkForAction(test, WM_ACTION_DEPOSE, rank) == 0 )
|
|
{
|
|
cel = test;
|
|
cMem = test;
|
|
goto ok;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if ( button == BUTTON_DEPOSE && // dépose pour un bateau ?
|
|
list > 0 &&
|
|
m_blupi[rank].listButton[list-1] == BUTTON_BATEAU )
|
|
{
|
|
if ( SearchOtherBateau(rank, cel, 100, test, icon) )
|
|
{
|
|
cel = test;
|
|
cMem = test;
|
|
goto ok;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//? if ( button == BUTTON_MANGE )
|
|
//? {
|
|
//? cel = m_blupi[rank].cel; // cherche là où est blupi !
|
|
//? }
|
|
|
|
i = 0;
|
|
channel = -2;
|
|
icon1 = -1;
|
|
icon2 = -1;
|
|
while ( table_object[i] != 0 )
|
|
{
|
|
if ( button == table_object[i] )
|
|
{
|
|
channel = table_object[i+1];
|
|
icon1 = table_object[i+2];
|
|
icon2 = table_object[i+3];
|
|
break;
|
|
}
|
|
i += 4;
|
|
}
|
|
|
|
if ( button == BUTTON_CARRY ||
|
|
button == BUTTON_FLEUR )
|
|
{
|
|
channel = CHOBJECT;
|
|
icon1 = param;
|
|
icon2 = param;
|
|
}
|
|
if ( button == BUTTON_GO && // va en bateau/jeep ?
|
|
param != -1 )
|
|
{
|
|
channel = CHOBJECT;
|
|
icon1 = param;
|
|
icon2 = param;
|
|
}
|
|
|
|
if ( channel != -2 )
|
|
{
|
|
if ( !SearchOtherObject(rank, cel, table_actions[button],
|
|
50*2, channel,
|
|
icon1, icon2, -1, -1,
|
|
cel, icon1) )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( button == BUTTON_PALIS )
|
|
{
|
|
cMem = cel;
|
|
}
|
|
|
|
ok:
|
|
if ( cel.x%2 == 0 ) cel.x ++;
|
|
if ( cel.y%2 == 0 ) cel.y ++; // sur l'objet
|
|
|
|
m_blupi[rank].interrupt = 1;
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
// Démarre une action.
|
|
|
|
void CDecor::GoalStart(int rank, int action, POINT cel)
|
|
{
|
|
m_blupi[rank].goalHili = cel;
|
|
m_blupi[rank].goalAction = action;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].bRepeat = false;
|
|
|
|
GoalInitJauge(rank);
|
|
FlushUsed(rank);
|
|
}
|
|
|
|
// Effectue la méta opération suivante.
|
|
// Retourne false lorsque c'est fini !
|
|
|
|
bool CDecor::GoalNextPhase(int rank)
|
|
{
|
|
short* pTable;
|
|
int i, nb;
|
|
|
|
if ( m_blupi[rank].goalAction == 0 ) return false;
|
|
|
|
pTable = GetTableGoal(m_blupi[rank].goalAction);
|
|
if ( pTable == NULL )
|
|
{
|
|
GoalStop(rank, true);
|
|
return false;
|
|
}
|
|
|
|
for ( i=0 ; i<m_blupi[rank].goalPhase ; i++ )
|
|
{
|
|
if ( *pTable == 0 ) return false;
|
|
pTable += 1+table_goal_nbop[*pTable];
|
|
}
|
|
|
|
if ( *pTable == GOAL_GROUP )
|
|
{
|
|
m_blupi[rank].goalPhase ++;
|
|
nb = pTable[1];
|
|
pTable += 2;
|
|
|
|
for ( i=0 ; i<nb ; i++ )
|
|
{
|
|
m_blupi[rank].goalPhase ++;
|
|
if ( !GoalNextOp(rank, pTable) ) return false;
|
|
pTable += 1+table_goal_nbop[*pTable];
|
|
}
|
|
}
|
|
|
|
m_blupi[rank].goalPhase ++;
|
|
return GoalNextOp(rank, pTable);
|
|
}
|
|
|
|
// Initialise la jauge pour une méta opération.
|
|
|
|
void CDecor::GoalInitJauge(int rank)
|
|
{
|
|
short* pTable;
|
|
int max=0, op;
|
|
|
|
m_blupi[rank].jaugePhase = -1;
|
|
m_blupi[rank].jaugeMax = -1;
|
|
|
|
if ( m_blupi[rank].perso != 0 &&
|
|
m_blupi[rank].perso != 8 ) return; // araignée/virus/etc. ?
|
|
if ( m_blupi[rank].goalAction == 0 ) return;
|
|
|
|
pTable = GetTableGoal(m_blupi[rank].goalAction);
|
|
if ( pTable == NULL ) goto term;
|
|
|
|
while ( true )
|
|
{
|
|
op = *pTable;
|
|
if ( op == 0 ||
|
|
op == GOAL_TERM ) goto term;
|
|
|
|
if ( op == GOAL_ACTION &&
|
|
pTable[1] != ACTION_STOP )
|
|
{
|
|
max ++;
|
|
}
|
|
|
|
pTable += 1+table_goal_nbop[*pTable];
|
|
}
|
|
|
|
term:
|
|
if ( max > 0 )
|
|
{
|
|
m_blupi[rank].jaugePhase = 0;
|
|
m_blupi[rank].jaugeMax = max;
|
|
}
|
|
}
|
|
|
|
// Permet de passer à travers certains arbres.
|
|
|
|
void CDecor::GoalInitPassCel(int rank)
|
|
{
|
|
POINT cel;
|
|
int channel, icon;
|
|
|
|
cel.x = (m_blupi[rank].goalCel.x/2)*2;
|
|
cel.y = (m_blupi[rank].goalCel.y/2)*2;
|
|
|
|
GetObject(cel, channel, icon);
|
|
|
|
if ( channel == CHOBJECT &&
|
|
((icon >= 8 && icon <= 11) || // arbres touffus ?
|
|
(icon >= 30 && icon <= 35) || // arbres touffus sans feuilles ?
|
|
(icon >= 37 && icon <= 43) || // rochers ?
|
|
(icon == 81 || icon == 83 || icon == 94) || // fleurs ?
|
|
(icon >= 100 && icon <= 105) || // usine ?
|
|
(icon == 115 || icon == 116) || // usine ?
|
|
(icon == 17 || icon == 18) || // usine ?
|
|
(icon == 117) || // bateau ?
|
|
(icon == 118) || // jeep ?
|
|
(icon == 16)) ) // armure ?
|
|
{
|
|
m_blupi[rank].passCel = m_blupi[rank].goalCel;
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].passCel.x = -1;
|
|
}
|
|
}
|
|
|
|
// Ajuste une coordonnée de cellule.
|
|
|
|
void CDecor::GoalAdjustCel(int rank, int &x, int &y)
|
|
{
|
|
if ( x == -10 && y == -10 )
|
|
{
|
|
if ( m_blupi[rank].goalAction == WM_ACTION_PONTEL )
|
|
{
|
|
x = m_blupi[rank].fix.x + m_blupi[rank].cLoop*2;
|
|
y = m_blupi[rank].fix.y;
|
|
return;
|
|
}
|
|
if ( m_blupi[rank].goalAction == WM_ACTION_PONTOL )
|
|
{
|
|
x = m_blupi[rank].fix.x - m_blupi[rank].cLoop*2;
|
|
y = m_blupi[rank].fix.y;
|
|
return;
|
|
}
|
|
if ( m_blupi[rank].goalAction == WM_ACTION_PONTSL )
|
|
{
|
|
x = m_blupi[rank].fix.x;
|
|
y = m_blupi[rank].fix.y + m_blupi[rank].cLoop*2;
|
|
return;
|
|
}
|
|
if ( m_blupi[rank].goalAction == WM_ACTION_PONTNL )
|
|
{
|
|
x = m_blupi[rank].fix.x;
|
|
y = m_blupi[rank].fix.y - m_blupi[rank].cLoop*2;
|
|
return;
|
|
}
|
|
}
|
|
|
|
x += m_blupi[rank].cel.x;
|
|
y += m_blupi[rank].cel.y;
|
|
}
|
|
|
|
// Liste des buts multiples.
|
|
|
|
int table_multi_goal[16*2] =
|
|
{
|
|
0, 0,
|
|
+1, 0,
|
|
0,+1,
|
|
+1,+1,
|
|
0,-1,
|
|
+1,-1,
|
|
0,+2,
|
|
+1,+2,
|
|
-1,-1,
|
|
-1, 0,
|
|
-1,+1,
|
|
-1,+2,
|
|
+2,-1,
|
|
+2, 0,
|
|
+2,+1,
|
|
+2,+2,
|
|
};
|
|
|
|
// Effectue une méta opération.
|
|
|
|
bool CDecor::GoalNextOp(int rank, short *pTable)
|
|
{
|
|
int op, x, y;
|
|
int action, direct, channel, icon, mchannel, micon;
|
|
int total, step, delai, first, last, first2, last2, flag, i;
|
|
int button, param;
|
|
POINT pos, cel, cMem, destCel;
|
|
bool bOK, bError=true;
|
|
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
|
|
op = *pTable++;
|
|
|
|
if ( op == GOAL_ACTION &&
|
|
*pTable != ACTION_STOP )
|
|
{
|
|
m_blupi[rank].jaugePhase ++;
|
|
}
|
|
|
|
if ( op == GOAL_GOHILI )
|
|
{
|
|
m_blupi[rank].goalCel.x = m_blupi[rank].goalHili.x+(*pTable++);
|
|
m_blupi[rank].goalCel.y = m_blupi[rank].goalHili.y+(*pTable++);
|
|
flag = *pTable++;
|
|
//? m_blupi[rank].passCel.x = -1;
|
|
FlushUsed(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_GOHILI2 )
|
|
{
|
|
cel.x = (m_blupi[rank].goalHili.x/2)*2+(*pTable++);
|
|
cel.y = (m_blupi[rank].goalHili.y/2)*2+(*pTable++);
|
|
flag = *pTable++;
|
|
if ( !!flag )
|
|
{
|
|
m_blupi[rank].goalCel = cel;
|
|
GoalInitPassCel(rank);
|
|
}
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_GOBLUPI )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
flag = *pTable++;
|
|
if ( !!flag )
|
|
{
|
|
if ( IsBlupiHereEx(cel, rank, false) ) // destination occupée ?
|
|
{
|
|
m_blupi[rank].goalPhase --; // on attend ...
|
|
return true;
|
|
}
|
|
m_blupi[rank].goalCel = cel;
|
|
GoalInitPassCel(rank);
|
|
}
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_TESTOBJECT )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
GetObject(cel, mchannel, micon);
|
|
if ( channel != mchannel || icon != micon ) goto error;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_PUTFLOOR )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
if ( icon == -2 ) icon = m_blupi[rank].vIcon;
|
|
PutFloor(GetCel(x,y), channel, icon);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_PUTOBJECT )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
if ( channel == -3 && icon == -3 ) // l'objet transporté ?
|
|
{
|
|
channel = m_blupi[rank].takeChannel;
|
|
icon = m_blupi[rank].takeIcon;
|
|
}
|
|
PutObject(GetCel(x,y), channel, icon);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_BUILDFLOOR )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
cel.x = (x/2)*2;
|
|
cel.y = (y/2)*2;
|
|
GetFloor(cel, channel, i);
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
mchannel = *pTable++;
|
|
micon = *pTable++;
|
|
total = *pTable++;
|
|
delai = *pTable++;
|
|
step = *pTable++;
|
|
|
|
if ( i >= 19 && i <= 32 && // herbe foncée ?
|
|
icon == 57 ) icon = 58; // sol tomate foncé
|
|
if ( i == 58 &&
|
|
icon == 1 ) icon = 20; // remet herbe foncée
|
|
|
|
if ( !MoveCreate(cel, rank, true,
|
|
channel, icon,
|
|
mchannel, micon,
|
|
total, delai, step) ) goto error;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_BUILDOBJECT )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
cel.x = (x/2)*2;
|
|
cel.y = (y/2)*2;
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
mchannel = *pTable++;
|
|
micon = *pTable++;
|
|
total = *pTable++;
|
|
delai = *pTable++;
|
|
step = *pTable++;
|
|
if ( channel == -2 && icon == -2 ) // l'objet actuel ?
|
|
{
|
|
GetObject(cel, channel, icon);
|
|
}
|
|
ArrangeBuild(cel, channel, icon); // arrange les murs autour
|
|
if ( !MoveCreate(cel, rank, false,
|
|
channel, icon,
|
|
mchannel, micon,
|
|
total, delai, step) ) goto error;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_FINISHMOVE )
|
|
{
|
|
MoveFinish(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ARRANGEOBJECT )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
MoveFinish(GetCel(x,y));
|
|
ArrangeObject(GetCel(x,y));
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_EXPLOSE1 )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
cel = GetCel(x,y);
|
|
|
|
BlupiKill(rank, cel, 0);
|
|
MoveFinish(cel);
|
|
|
|
// Faut-il démarrer une explosion en chaîne.
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT && icon == 85 ) // dynamite ?
|
|
{
|
|
rank = BlupiCreate(GetCel(cel,1,1), ACTION_STOP, DIRECT_E,
|
|
6, MAXENERGY); // crée un détonnateur
|
|
if ( rank >= 0 )
|
|
{
|
|
GoalStart(rank, WM_ACTION_T_DYNAMITE, cel);
|
|
m_blupi[rank].bCache = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PutObject(cel, -1,-1); // supprime l'objet
|
|
ArrangeObject(cel);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_EXPLOSE2 )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
cel = GetCel((x/2)*2,(y/2)*2);
|
|
|
|
GetObject(cel, channel, icon);
|
|
if ( channel != CHOBJECT || icon != 85 ) // dynamite ?
|
|
{
|
|
channel = CHOBJECT;
|
|
icon = -1;
|
|
ArrangeBuild(cel, channel, icon); // arrange les murs autour
|
|
if ( !MoveCreate(cel, rank, false,
|
|
CHOBJECT,-1, -1,-1,
|
|
10, 1, -1*100) ) goto error;
|
|
MoveAddIcons(cel, 6); // explosion
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ADDMOVES )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
icon = *pTable++;
|
|
MoveAddMoves(GetCel(x,y), icon);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ADDICONS )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
icon = *pTable++;
|
|
MoveAddIcons(GetCel(x,y), icon);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ACTION )
|
|
{
|
|
action = *pTable++;
|
|
direct = *pTable++;
|
|
BlupiInitAction(rank, action, direct);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ELECTRO )
|
|
{
|
|
x = *pTable++;
|
|
y = *pTable++;
|
|
GoalAdjustCel(rank, x,y);
|
|
cel = GetCel((x/2)*2,(y/2)*2);
|
|
icon = *pTable++;
|
|
if ( MoveCreate(cel, rank, true,
|
|
CHFLOOR,-1, -1,-1,
|
|
100,1,100, false, true) )
|
|
{
|
|
MoveAddIcons(cel, icon);
|
|
}
|
|
BlupiKill(rank, cel, 1);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_MALADE )
|
|
{
|
|
m_blupi[rank].bMalade = *pTable++;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_WORK )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
m_decor[cel.x/2][cel.y/2].workBlupi = rank;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_INTERRUPT )
|
|
{
|
|
m_blupi[rank].interrupt = *pTable++; // change le niveau
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ENERGY )
|
|
{
|
|
if ( m_blupi[rank].energy <= *pTable++ ) goto error;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ISNOMALADE )
|
|
{
|
|
if ( m_blupi[rank].bMalade ) goto error;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_TAKE )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
MoveFinish(rank);
|
|
m_blupi[rank].takeChannel = m_decor[cel.x/2][cel.y/2].objectChannel;
|
|
m_blupi[rank].takeIcon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
m_decor[cel.x/2][cel.y/2].objectChannel = -1;
|
|
m_decor[cel.x/2][cel.y/2].objectIcon = -1;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_TAKEOBJECT )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
m_blupi[rank].takeChannel = channel;
|
|
m_blupi[rank].takeIcon = icon;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_LABO )
|
|
{
|
|
m_blupi[rank].takeChannel = CHOBJECT;
|
|
if ( m_blupi[rank].takeIcon == 82 ) // fleurs normales ?
|
|
{
|
|
m_blupi[rank].takeIcon = 80; // bouteille
|
|
}
|
|
if ( m_blupi[rank].takeIcon == 84 ) // fleurs foncées ?
|
|
{
|
|
m_blupi[rank].takeIcon = 85; // dynamite
|
|
}
|
|
if ( m_blupi[rank].takeIcon == 95 ) // fleurs vertes ?
|
|
{
|
|
m_blupi[rank].takeIcon = 93; // piège
|
|
}
|
|
if ( m_blupi[rank].takeIcon == 60 ) // tomates ?
|
|
{
|
|
m_blupi[rank].takeIcon = 92; // poison
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_CACHE )
|
|
{
|
|
m_blupi[rank].bCache = *pTable++;
|
|
if ( *pTable++ && // bDynamite ?
|
|
m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule == 3 && // armure ?
|
|
!m_bInvincible )
|
|
{
|
|
m_blupi[rank].bCache = false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_DELETE )
|
|
{
|
|
if ( m_blupi[rank].perso == 0 && // blupi ?
|
|
m_blupi[rank].vehicule == 3 && // armure ?
|
|
!m_bInvincible )
|
|
{
|
|
return true;
|
|
}
|
|
BlupiDelete(rank); // snif ...
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_DEPOSE )
|
|
{
|
|
m_blupi[rank].takeChannel = -1;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_NEWBLUPI )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
PutObject(cel, -1,-1); // enlève les oeufs
|
|
|
|
rank = BlupiCreate(cel, ACTION_STOP, DIRECT_E, 0, MAXENERGY/4);
|
|
if ( rank >= 0 )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY/4;
|
|
BlupiInitAction(rank, ACTION_NAISSANCE);
|
|
}
|
|
|
|
cel.x ++;
|
|
rank = BlupiCreate(cel, ACTION_STOP, DIRECT_E, 0, MAXENERGY/4);
|
|
if ( rank >= 0 )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY/4;
|
|
BlupiInitAction(rank, ACTION_NAISSANCE);
|
|
}
|
|
|
|
cel.x --;
|
|
cel.y ++;
|
|
rank = BlupiCreate(cel, ACTION_STOP, DIRECT_E, 0, MAXENERGY/4);
|
|
if ( rank >= 0 )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY/4;
|
|
BlupiInitAction(rank, ACTION_NAISSANCE);
|
|
}
|
|
|
|
cel.x ++;
|
|
rank = BlupiCreate(cel, ACTION_STOP, DIRECT_E, 0, MAXENERGY/4);
|
|
if ( rank >= 0 )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY/4;
|
|
BlupiInitAction(rank, ACTION_NAISSANCE);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_NEWPERSO )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
icon = *pTable++;
|
|
|
|
destCel = cel;
|
|
destCel.x ++;
|
|
if ( IsBlupiHereEx(destCel, rank, false) ) // destination occupée ?
|
|
{
|
|
m_blupi[rank].goalPhase --; // on attend ...
|
|
return true;
|
|
}
|
|
destCel.x ++;
|
|
if ( IsBlupiHereEx(destCel, rank, false) ) // destination occupée ?
|
|
{
|
|
destCel.y --;
|
|
if ( icon == 5 || // bombe ?
|
|
IsBlupiHereEx(destCel, rank, false) ) // destination occupée ?
|
|
{
|
|
m_blupi[rank].goalPhase --; // on attend ...
|
|
return true;
|
|
}
|
|
}
|
|
|
|
rank = BlupiCreate(cel, ACTION_STOP, DIRECT_E, icon, MAXENERGY);
|
|
if ( rank >= 0 )
|
|
{
|
|
m_blupi[rank].goalCel = destCel;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_USINEBUILD )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
if ( !IsUsineBuild(rank, cel) ) goto error;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_USINEFREE )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
if ( !IsUsineFree(rank, cel) )
|
|
{
|
|
GoalStop(rank, true);
|
|
m_blupi[rank].goalCel = GetCel(cel,1,-1); // à côté de la porte
|
|
//? m_blupi[rank].goalAction = 0; // stoppe sitôt après
|
|
//? m_blupi[rank].interrupt = 1;
|
|
//? GoalUnwork(rank);
|
|
//? FlushUsed(rank);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_AMORCE )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
if ( IsBlupiHereEx(cel, rank, false) ) goto error;
|
|
// Crée un détonnateur de mine (blupi invisible).
|
|
rank = BlupiCreate(cel, ACTION_STOP, DIRECT_E, 6, MAXENERGY);
|
|
if ( rank >= 0 )
|
|
{
|
|
m_blupi[rank].bCache = true; // invisible
|
|
m_blupi[rank].goalAction = WM_ACTION_MINE2;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].interrupt = 1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_VEHICULE )
|
|
{
|
|
m_blupi[rank].vehicule = *pTable++;
|
|
if ( m_blupi[rank].vehicule != 0 && // pas à pied ?
|
|
m_blupi[rank].takeChannel != -1 && // porte qq chose ?
|
|
m_blupi[rank].energy <= MAXENERGY/4 ) // faible ?
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY/4+1;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ACTUALISE )
|
|
{
|
|
BlupiActualise(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_SOUND )
|
|
{
|
|
icon = *pTable++;
|
|
BlupiSound(rank, icon, pos);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_REPEAT )
|
|
{
|
|
icon = *pTable++;
|
|
m_blupi[rank].bRepeat = icon;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_OTHER )
|
|
{
|
|
if ( !m_blupi[rank].bRepeat ) goto term;
|
|
|
|
// Bouton stop pressé ?
|
|
if ( m_blupi[rank].stop == 1 ) goto term;
|
|
|
|
channel = *pTable++;
|
|
first = *pTable++;
|
|
last = *pTable++;
|
|
first2 = *pTable++;
|
|
last2 = *pTable++;
|
|
action = *pTable++;
|
|
if ( !SearchOtherObject(rank, m_blupi[rank].cel, action, 100,
|
|
channel, first, last, first2, last2,
|
|
m_blupi[rank].goalHili, icon) ) goto term;
|
|
if ( action == WM_ACTION_ABAT1 ||
|
|
action == WM_ACTION_ROC1 )
|
|
{
|
|
action += icon-first; // WM_ACTION_ABAT1..6
|
|
}
|
|
m_blupi[rank].goalAction = action;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].interrupt = 1;
|
|
GoalInitJauge(rank);
|
|
GoalUnwork(rank);
|
|
FlushUsed(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_OTHERFIX )
|
|
{
|
|
if ( !m_blupi[rank].bRepeat ) goto term;
|
|
|
|
// Bouton stop pressé ?
|
|
if ( m_blupi[rank].stop == 1 ) goto term;
|
|
|
|
channel = *pTable++;
|
|
first = *pTable++;
|
|
last = *pTable++;
|
|
first2 = *pTable++;
|
|
last2 = *pTable++;
|
|
action = *pTable++;
|
|
if ( !SearchOtherObject(rank, m_blupi[rank].fix, action, 100,
|
|
channel, first, last, first2, last2,
|
|
m_blupi[rank].goalHili, icon) ) goto term;
|
|
if ( action == WM_ACTION_ABAT1 ||
|
|
action == WM_ACTION_ROC1 )
|
|
{
|
|
action += icon-first; // WM_ACTION_ABAT1..6
|
|
}
|
|
m_blupi[rank].goalAction = action;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].interrupt = 1;
|
|
GoalInitJauge(rank);
|
|
GoalUnwork(rank);
|
|
FlushUsed(rank);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_OTHERLOOP )
|
|
{
|
|
action = *pTable++;
|
|
if ( m_blupi[rank].cLoop < m_blupi[rank].nLoop )
|
|
{
|
|
m_blupi[rank].goalAction = action;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].interrupt = 1;
|
|
GoalInitJauge(rank);
|
|
GoalUnwork(rank);
|
|
FlushUsed(rank);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_NEXTLOOP )
|
|
{
|
|
m_blupi[rank].cLoop ++;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_FIX )
|
|
{
|
|
m_blupi[rank].fix.x = m_blupi[rank].cel.x+(*pTable++);
|
|
m_blupi[rank].fix.y = m_blupi[rank].cel.y+(*pTable++);
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_FLOORJUMP )
|
|
{
|
|
channel = *pTable++;
|
|
icon = *pTable++;
|
|
action = *pTable++;
|
|
GetFloor(m_blupi[rank].cel, mchannel, micon);
|
|
if ( channel == mchannel && icon == micon )
|
|
{
|
|
m_blupi[rank].goalAction = action;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].interrupt = 1;
|
|
GoalInitJauge(rank);
|
|
GoalUnwork(rank);
|
|
FlushUsed(rank);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_ADDDRAPEAU )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
AddDrapeau(cel); // cellule sondée
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_TELEPORTE )
|
|
{
|
|
pos.x = *pTable++;
|
|
pos.y = *pTable++;
|
|
|
|
cMem = m_blupi[rank].cel;
|
|
GetFloor(cMem, channel, icon);
|
|
PutFloor(cMem, -1, -1);
|
|
bOK = SearchOtherObject(rank, m_blupi[rank].cel, WM_ACTION_GO,
|
|
1000, CHFLOOR,80,80,-1,-1, cel, i);
|
|
PutFloor(cMem, channel, icon);
|
|
if ( !bOK ) goto error;
|
|
|
|
cel.x += pos.x;
|
|
cel.y += pos.y;
|
|
if ( IsBlupiHereEx(cel, rank, false) ||
|
|
!IsFreeCel(cel, rank) ) goto error;
|
|
m_blupi[rank].cel = cel;
|
|
BlupiPushFog(rank);
|
|
if ( m_blupi[rank].bHili )
|
|
{
|
|
SetCoin(cel, true);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_IFTERM )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
if ( !IsFreeCel(cel, rank) ||
|
|
IsBlupiHereEx(cel, rank, false) ) goto term;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_IFDEBARQUE )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
m_blupi[rank].vehicule = 0; // à pied
|
|
bOK = IsFreeCel(cel, rank) &&
|
|
!IsBlupiHereEx(cel, rank, false);
|
|
m_blupi[rank].vehicule = 1; // en bateau
|
|
if ( !bOK ) goto term;
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_SKIPSKILL )
|
|
{
|
|
i = (*pTable++);
|
|
total = (*pTable++);
|
|
if ( m_skill == i )
|
|
{
|
|
m_blupi[rank].goalPhase += total; // saute qq instructions
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if ( op == GOAL_TERM )
|
|
{
|
|
term:
|
|
bError = false;
|
|
}
|
|
|
|
if ( op == GOAL_WAITFREE )
|
|
{
|
|
cel.x = m_blupi[rank].cel.x+(*pTable++);
|
|
cel.y = m_blupi[rank].cel.y+(*pTable++);
|
|
if ( IsBlupiHereEx(cel, rank, false) ) // destination occupée ?
|
|
{
|
|
m_blupi[rank].goalPhase --; // on attend ...
|
|
|
|
rank = m_blupiHere;
|
|
if ( m_blupi[rank].goalAction != WM_ACTION_GO &&
|
|
m_blupi[rank].goalAction != WM_ACTION_ELECTRO &&
|
|
m_blupi[rank].goalAction != WM_ACTION_ELECTROm )
|
|
{
|
|
destCel.x = cel.x;
|
|
destCel.y = cel.y-1;
|
|
if ( !IsBlupiHereEx(destCel, rank, false) )
|
|
{
|
|
GoalStart(rank, WM_ACTION_GO, destCel);
|
|
return true;
|
|
}
|
|
|
|
destCel.x = cel.x+1;
|
|
destCel.y = cel.y;
|
|
if ( !IsBlupiHereEx(destCel, rank, false) )
|
|
{
|
|
GoalStart(rank, WM_ACTION_GO, destCel);
|
|
return true;
|
|
}
|
|
|
|
destCel.x = cel.x;
|
|
destCel.y = cel.y+1;
|
|
if ( !IsBlupiHereEx(destCel, rank, false) )
|
|
{
|
|
GoalStart(rank, WM_ACTION_GO, destCel);
|
|
return true;
|
|
}
|
|
|
|
destCel.x = cel.x+1;
|
|
destCel.y = cel.y-1;
|
|
if ( !IsBlupiHereEx(destCel, rank, false) )
|
|
{
|
|
GoalStart(rank, WM_ACTION_GO, destCel);
|
|
return true;
|
|
}
|
|
|
|
destCel.x = cel.x+1;
|
|
destCel.y = cel.y+1;
|
|
if ( !IsBlupiHereEx(destCel, rank, false) )
|
|
{
|
|
GoalStart(rank, WM_ACTION_GO, destCel);
|
|
return true;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 0 )
|
|
{
|
|
if ( m_blupi[rank].bMalade )
|
|
{
|
|
action = WM_ACTION_ELECTROm;
|
|
}
|
|
else
|
|
{
|
|
action = WM_ACTION_ELECTRO;
|
|
}
|
|
GoalStart(rank, action, m_blupi[rank].cel);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
error:
|
|
i = m_blupi[rank].repeatLevel;
|
|
GoalStop(rank, bError, i==-1);
|
|
if ( i != -1 ) // répétition en cours ?
|
|
{
|
|
button = m_blupi[rank].listButton[i];
|
|
cMem = m_blupi[rank].listCel[i];
|
|
param = m_blupi[rank].listParam[i];
|
|
cel = cMem;
|
|
if ( RepeatAdjust(rank, button, cel, cMem, param, i) )
|
|
{
|
|
if ( IsBlupiHereEx(cel, rank, false) ) // destination occupée ?
|
|
{
|
|
m_blupi[rank].repeatLevel = i; // on continue ...
|
|
GoalStart(rank, WM_ACTION_GO, m_blupi[rank].cel); // on attend ...
|
|
return true;
|
|
}
|
|
if ( BlupiGoal(rank, button, cel, cMem) )
|
|
{
|
|
m_blupi[rank].repeatLevel = i; // on continue ...
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Supprime le blocage de la cellule dans laquelle
|
|
// blupi travaille.
|
|
|
|
void CDecor::GoalUnwork(int rank)
|
|
{
|
|
int x, y;
|
|
|
|
for ( x=0 ; x<MAXCELX/2 ; x++ )
|
|
{
|
|
for ( y=0 ; y<MAXCELY/2 ; y++ )
|
|
{
|
|
if ( m_decor[x][y].workBlupi == rank )
|
|
{
|
|
m_decor[x][y].workBlupi = -1; // débloque
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Stoppe complètement une action.
|
|
|
|
void CDecor::GoalStop(int rank, bool bError, bool bSound)
|
|
{
|
|
POINT pos;
|
|
|
|
static int table_sound_term[6] =
|
|
{
|
|
SOUND_TERM1,
|
|
SOUND_TERM2,
|
|
SOUND_TERM3,
|
|
SOUND_TERM4,
|
|
SOUND_TERM5,
|
|
SOUND_TERM6,
|
|
};
|
|
|
|
static int table_sound_boing[3] =
|
|
{
|
|
SOUND_BOING1,
|
|
SOUND_BOING2,
|
|
SOUND_BOING3,
|
|
};
|
|
|
|
if ( bError && bSound )
|
|
{
|
|
ListRemove(rank); // supprime la dernière action mémorisée
|
|
}
|
|
|
|
m_blupi[rank].goalAction = 0;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].jaugePhase = -1;
|
|
m_blupi[rank].jaugeMax = -1;
|
|
m_blupi[rank].interrupt = 1; // remet le niveau normal
|
|
m_blupi[rank].busyCount = 0;
|
|
m_blupi[rank].busyDelay = 0;
|
|
m_blupi[rank].repeatLevel = -1; // stoppe la répétition
|
|
FlushUsed(rank);
|
|
MoveFinish(rank);
|
|
GoalUnwork(rank);
|
|
|
|
// En cas d'erreur, il faut accepter de traverser la
|
|
// construction avortée (par exemple, le massif d'arbres
|
|
// dans lequel blupi se trouve, mais qui n'a pas pu
|
|
// être abattu).
|
|
if ( !bError )
|
|
{
|
|
m_blupi[rank].passCel.x = -1;
|
|
}
|
|
|
|
m_blupi[rank].stop = 0; // relâche bouton stop
|
|
|
|
if ( bSound &&
|
|
(m_blupi[rank].perso == 0 || // blupi ?
|
|
m_blupi[rank].perso == 8 ) ) // assistant ?
|
|
{
|
|
if ( bError )
|
|
{
|
|
pos.x = LXIMAGE/2;
|
|
pos.y = LYIMAGE/2;
|
|
BlupiSound(rank, table_sound_boing[Random(0,2)], pos, true);
|
|
}
|
|
else
|
|
{
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
BlupiSound(rank, table_sound_term[Random(0,5)], pos, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Teste si une cellule est déjà utilisée comme but pour
|
|
// n'importe quel blupi.
|
|
|
|
bool CDecor::BlupiIsGoalUsed(POINT cel)
|
|
{
|
|
int rank;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].goalCel.x/2 == cel.x/2 &&
|
|
m_blupi[rank].goalCel.y/2 == cel.y/2 ) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// Démarre ou stoppe un rayon entre deux tours.
|
|
|
|
void CDecor::BlupiStartStopRayon(int rank, POINT startCel, POINT endCel)
|
|
{
|
|
int i, icon, icon2;
|
|
POINT cel, cel2, vector, pos;
|
|
|
|
if ( m_blupi[rank].perso == 1 || // araignée ?
|
|
m_blupi[rank].perso == 2 ) // virus ?
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Stoppe un rayon.
|
|
cel.x = (endCel.x/2)*2;
|
|
cel.y = (endCel.y/2)*2;
|
|
icon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
if ( (icon == 10000 || icon == 10001) &&
|
|
MoveIsUsed(cel) )
|
|
{
|
|
if ( MoveIsUsed(cel) )
|
|
{
|
|
MoveFinish(cel);
|
|
|
|
pos = ConvCelToPos(cel);
|
|
BlupiSound(rank, SOUND_RAYON2, pos);
|
|
}
|
|
|
|
for ( i=0 ; i<4 ; i++ )
|
|
{
|
|
vector = GetVector(i*2*16);
|
|
cel.x = (endCel.x/2)*2 + vector.x*2;
|
|
cel.y = (endCel.y/2)*2 + vector.y*2;
|
|
icon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
if ( icon == 10000 || icon == 10001 )
|
|
{
|
|
MoveFinish(cel);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Démarre un rayon.
|
|
cel.x = (startCel.x/2)*2;
|
|
cel.y = (startCel.y/2)*2;
|
|
cel2.x = (endCel.x/2)*2;
|
|
cel2.y = (endCel.y/2)*2;
|
|
icon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
icon2 = m_decor[cel2.x/2][cel2.y/2].objectIcon;
|
|
if ( (icon == 10000 || icon == 10001) &&
|
|
icon2 != 10000 && icon2 != 10001 )
|
|
{
|
|
if ( MoveCreate(cel, -1, false, CHOBJECT,-1,
|
|
-1,-1, 9999,1,0, true) )
|
|
{
|
|
MoveAddIcons(cel, icon==10000?4:5, true); // éclairs
|
|
}
|
|
|
|
pos = ConvCelToPos(cel);
|
|
BlupiSound(rank, SOUND_RAYON1, pos);
|
|
|
|
for ( i=0 ; i<4 ; i++ )
|
|
{
|
|
vector = GetVector(i*2*16);
|
|
cel.x = (startCel.x/2)*2 + vector.x*2;
|
|
cel.y = (startCel.y/2)*2 + vector.y*2;
|
|
icon = m_decor[cel.x/2][cel.y/2].objectIcon;
|
|
if ( icon == 10000 || icon == 10001 )
|
|
{
|
|
if ( MoveCreate(cel, -1, false, CHOBJECT,-1,
|
|
-1,-1, 9999,1,0, true) )
|
|
{
|
|
MoveAddIcons(cel, icon==10000?4:5, true); // éclairs
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Tourne un blupi, si nécessaire.
|
|
// Retourne false si ce n'est pas nécessaire.
|
|
|
|
bool CDecor::BlupiRotate(int rank)
|
|
{
|
|
int aDirect, sDirect, ip, in, sens;
|
|
bool bOK;
|
|
POINT pos;
|
|
|
|
aDirect = m_blupi[rank].aDirect;
|
|
sDirect = m_blupi[rank].sDirect;
|
|
|
|
if ( aDirect == sDirect ) return false;
|
|
|
|
if ( sDirect > aDirect ) ip = sDirect+0*16-aDirect;
|
|
else ip = sDirect+8*16-aDirect;
|
|
|
|
if ( aDirect > sDirect ) in = aDirect+0*16-sDirect;
|
|
else in = aDirect+8*16-sDirect;
|
|
|
|
if ( ip == 0 || in == 0 )
|
|
{
|
|
m_blupi[rank].aDirect = m_blupi[rank].sDirect;
|
|
return false;
|
|
}
|
|
|
|
if ( m_blupi[rank].perso == 0 && // blupi ?
|
|
m_blupi[rank].vehicule == 1 ) // en bateau ?
|
|
{
|
|
if ( ip == in ) sens = Random(0,1)?8:8*16-8;
|
|
if ( ip < in ) sens = 8;
|
|
if ( ip > in ) sens = 8*16-8;
|
|
aDirect = (aDirect+sens)%(8*16);
|
|
}
|
|
else if ( m_blupi[rank].perso == 0 && // blupi ?
|
|
m_blupi[rank].vehicule == 2 ) // en jeep ?
|
|
{
|
|
if ( ip == in ) sens = Random(0,1)?8:8*16-8;
|
|
if ( ip < in ) sens = 8;
|
|
if ( ip > in ) sens = 8*16-8;
|
|
aDirect = (aDirect+sens)%(8*16);
|
|
}
|
|
else if ( m_blupi[rank].perso == 0 && // blupi ?
|
|
m_blupi[rank].vehicule == 3 ) // armure ?
|
|
{
|
|
if ( ip == in ) sens = Random(0,1)?4:8*16-4;
|
|
if ( ip < in ) sens = 4;
|
|
if ( ip > in ) sens = 8*16-4;
|
|
aDirect = (aDirect+sens)%(8*16);
|
|
}
|
|
else if ( m_blupi[rank].perso == 3 ) // tracks ?
|
|
{
|
|
if ( ip == in ) sens = Random(0,1)?4:8*16-4;
|
|
if ( ip < in ) sens = 4;
|
|
if ( ip > in ) sens = 8*16-4;
|
|
aDirect = (aDirect+sens)%(8*16);
|
|
}
|
|
else if ( m_blupi[rank].perso == 4 ) // robot ?
|
|
{
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
BlupiSound(rank, SOUND_R_ROTATE, pos);
|
|
|
|
if ( ip == in ) sens = Random(0,1)?2:8*16-2;
|
|
if ( ip < in ) sens = 2;
|
|
if ( ip > in ) sens = 8*16-2;
|
|
aDirect = (aDirect+sens)%(8*16);
|
|
}
|
|
else if ( m_blupi[rank].perso == 8 ) // disciple ?
|
|
{
|
|
if ( ip == in ) sens = Random(0,1)?8:8*16-8;
|
|
if ( ip < in ) sens = 8;
|
|
if ( ip > in ) sens = 8*16-8;
|
|
aDirect = (aDirect+sens)%(8*16);
|
|
}
|
|
else
|
|
{
|
|
if ( ip == in ) sens = Random(0,1)?1:7;
|
|
if ( ip < in ) sens = 1;
|
|
if ( ip > in ) sens = 7;
|
|
aDirect = ((aDirect/16+sens)%8)*16;
|
|
}
|
|
|
|
m_blupi[rank].lastIcon = m_blupi[rank].icon;
|
|
bOK = Rotate(m_blupi[rank].icon, aDirect);
|
|
if ( bOK )
|
|
{
|
|
m_blupi[rank].aDirect = aDirect;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].aDirect = m_blupi[rank].sDirect;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Avance un blupi existant.
|
|
|
|
bool CDecor::BlupiNextAction(int rank)
|
|
{
|
|
bool bOK;
|
|
POINT pos, iCel;
|
|
int a, min;
|
|
short sound;
|
|
|
|
if ( !m_blupi[rank].bExist ) return false;
|
|
|
|
if ( m_blupi[rank].clicDelay > 0 )
|
|
{
|
|
m_blupi[rank].clicDelay --;
|
|
}
|
|
if ( m_blupi[rank].clicDelay == 0 )
|
|
{
|
|
m_blupi[rank].clicCount = 0;
|
|
}
|
|
|
|
bOK = true;
|
|
if ( !BlupiRotate(rank) ) // si rotation pas nécessaire
|
|
{
|
|
m_blupi[rank].lastIcon = m_blupi[rank].icon;
|
|
|
|
bOK = Action(m_blupi[rank].action,
|
|
m_blupi[rank].aDirect,
|
|
m_blupi[rank].phase,
|
|
m_blupi[rank].step,
|
|
m_blupi[rank].channel,
|
|
m_blupi[rank].icon,
|
|
m_blupi[rank].pos,
|
|
m_blupi[rank].posZ,
|
|
sound);
|
|
BlupiAdaptIcon(rank);
|
|
|
|
if ( sound != -1 )
|
|
{
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
BlupiSound(rank, sound, pos);
|
|
}
|
|
}
|
|
|
|
a = GetAmplitude(m_blupi[rank].action);
|
|
|
|
iCel = m_blupi[rank].cel;
|
|
|
|
if ( m_blupi[rank].pos.x == (DIMCELX/2)*a &&
|
|
m_blupi[rank].pos.y == (DIMCELY/2)*a )
|
|
{
|
|
m_blupi[rank].cel.x += a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == -(DIMCELX/2)*a &&
|
|
m_blupi[rank].pos.y == -(DIMCELY/2)*a )
|
|
{
|
|
m_blupi[rank].cel.x -= a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == -(DIMCELX/2)*a &&
|
|
m_blupi[rank].pos.y == (DIMCELY/2)*a )
|
|
{
|
|
m_blupi[rank].cel.y += a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == (DIMCELX/2)*a &&
|
|
m_blupi[rank].pos.y == -(DIMCELY/2)*a )
|
|
{
|
|
m_blupi[rank].cel.y -= a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == 0 &&
|
|
m_blupi[rank].pos.y == DIMCELY*a )
|
|
{
|
|
m_blupi[rank].cel.x += a;
|
|
m_blupi[rank].cel.y += a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == 0 &&
|
|
m_blupi[rank].pos.y == -DIMCELY*a )
|
|
{
|
|
m_blupi[rank].cel.x -= a;
|
|
m_blupi[rank].cel.y -= a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == DIMCELX*a &&
|
|
m_blupi[rank].pos.y == 0 )
|
|
{
|
|
m_blupi[rank].cel.x += a;
|
|
m_blupi[rank].cel.y -= a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
if ( m_blupi[rank].pos.x == -DIMCELX*a &&
|
|
m_blupi[rank].pos.y == 0 )
|
|
{
|
|
m_blupi[rank].cel.x -= a;
|
|
m_blupi[rank].cel.y += a;
|
|
BlupiPushFog(rank);
|
|
BlupiStartStopRayon(rank, iCel, m_blupi[rank].cel);
|
|
}
|
|
|
|
// Blupi perd de l'énergie s'il fait qq chose.
|
|
if ( m_blupi[rank].action != ACTION_STOP &&
|
|
m_blupi[rank].action != ACTION_STOPf &&
|
|
m_blupi[rank].action != ACTION_STOPb &&
|
|
m_blupi[rank].action != ACTION_STOPj &&
|
|
m_blupi[rank].action != ACTION_MISC1 &&
|
|
m_blupi[rank].action != ACTION_MISC2 &&
|
|
m_blupi[rank].action != ACTION_MISC3 &&
|
|
m_blupi[rank].action != ACTION_MISC4 &&
|
|
m_blupi[rank].action != ACTION_MISC5 &&
|
|
m_blupi[rank].action != ACTION_MISC6 &&
|
|
m_blupi[rank].action != ACTION_MISC1f )
|
|
{
|
|
if ( m_blupi[rank].energy > 0 &&
|
|
m_blupi[rank].perso == 0 && // blupi ?
|
|
m_blupi[rank].vehicule == 0 ) // à pied ?
|
|
{
|
|
if ( m_bSuper ) a = 0;
|
|
else a = 1;
|
|
min = 0;
|
|
if ( m_blupi[rank].goalAction == WM_ACTION_MUR ||
|
|
m_blupi[rank].goalAction == WM_ACTION_TOUR )
|
|
{
|
|
a = 5;
|
|
min = 1;
|
|
}
|
|
if ( m_blupi[rank].action == ACTION_GLISSE )
|
|
{
|
|
if ( m_bSuper ) a = 0;
|
|
else a = 40;
|
|
}
|
|
m_blupi[rank].energy -= a; // blupi se fatigue +/-
|
|
if ( m_blupi[rank].energy < min )
|
|
{
|
|
m_blupi[rank].energy = min;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Blupi prend de l'énergie s'il mange.
|
|
if ( m_blupi[rank].action == ACTION_MANGE )
|
|
{
|
|
if ( m_blupi[rank].energy < MAXENERGY )
|
|
{
|
|
m_blupi[rank].energy += MAXENERGY/(40*3);
|
|
}
|
|
}
|
|
|
|
// Le robot perd de l'énergie s'il fait qq chose.
|
|
if ( m_blupi[rank].action != ACTION_R_STOP )
|
|
{
|
|
if ( m_blupi[rank].energy > 0 &&
|
|
m_blupi[rank].perso == 4 )
|
|
{
|
|
m_blupi[rank].energy -= 3; // le robot se fatigue
|
|
if ( m_blupi[rank].energy < 1 )
|
|
{
|
|
m_blupi[rank].energy = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Le robot prend de l'énergie s'il se recharge.
|
|
if ( m_blupi[rank].action == ACTION_R_CHARGE )
|
|
{
|
|
if ( m_blupi[rank].energy < MAXENERGY )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY;
|
|
}
|
|
}
|
|
|
|
// Blupi guérrit s'il boit.
|
|
if ( m_blupi[rank].action == ACTION_BOIT )
|
|
{
|
|
m_blupi[rank].bMalade = false;
|
|
if ( m_blupi[rank].energy < MAXENERGY )
|
|
{
|
|
m_blupi[rank].energy += MAXENERGY/(40*3);
|
|
}
|
|
}
|
|
|
|
// Si blupi est presque complètement épuisé, il stoppe.
|
|
if ( !bOK &&
|
|
m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].energy < 50 &&
|
|
m_blupi[rank].energy != 0 &&
|
|
m_blupi[rank].action == ACTION_MARCHEf )
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStop(rank, true);
|
|
}
|
|
|
|
return bOK;
|
|
}
|
|
|
|
// Action suivante pour un blupi existant.
|
|
|
|
void CDecor::BlupiNextGoal(int rank)
|
|
{
|
|
int direct, action, channel, icon, min, lg, fRank, i;
|
|
POINT pos, cel, vector;
|
|
|
|
if ( !m_blupi[rank].bExist ) return;
|
|
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
|
|
// Si blupi termine une action "mort", il doit disparaître.
|
|
if ( m_blupi[rank].action == ACTION_BRULE ||
|
|
m_blupi[rank].action == ACTION_TCHAO ||
|
|
m_blupi[rank].action == ACTION_A_GRILLE ||
|
|
m_blupi[rank].action == ACTION_V_GRILLE )
|
|
{
|
|
BlupiDelete(rank); // snif ...
|
|
return;
|
|
}
|
|
|
|
// Si blupi passe trop prêt du feu, aie aie aie ...
|
|
if ( IsFireCel(m_blupi[rank].cel) ) // blupi se brule les ailes ?
|
|
{
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule != 3 && // pas armure ?
|
|
!m_bInvincible &&
|
|
m_blupi[rank].goalAction != WM_ACTION_GRILLE )
|
|
{
|
|
BlupiDeselect(rank);
|
|
GoalStart(rank, WM_ACTION_GRILLE, m_blupi[rank].cel);
|
|
goto goal;
|
|
//? BlupiInitAction(rank, ACTION_BRULE);
|
|
//? goto init;
|
|
}
|
|
if ( m_blupi[rank].perso == 1 || // araignée ?
|
|
m_blupi[rank].perso == 2 ) // virus ?
|
|
{
|
|
BlupiDelete(rank); // la bestiole meurt
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Si blupi passe trop prêt d'un virus ...
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule != 1 && // pas en bateau ?
|
|
m_blupi[rank].vehicule != 3 && // pas armure ?
|
|
!m_blupi[rank].bMalade && // en bonne santé ?
|
|
m_blupi[rank].goalAction != WM_ACTION_GRILLE &&
|
|
m_blupi[rank].goalAction != WM_ACTION_ELECTRO &&
|
|
m_blupi[rank].goalAction != WM_ACTION_ELECTROm &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUDE &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUDS &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUDO &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUDN &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUAE &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUAS &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUAO &&
|
|
m_blupi[rank].goalAction != WM_ACTION_BATEAUAN &&
|
|
!m_bInvincible &&
|
|
IsVirusCel(m_blupi[rank].cel) ) // blupi chope un virus ?
|
|
{
|
|
m_blupi[rank].bMalade = true;
|
|
|
|
if ( m_blupi[rank].energy > MAXENERGY/4 )
|
|
{
|
|
m_blupi[rank].energy = MAXENERGY/4;
|
|
}
|
|
|
|
BlupiSound(rank, SOUND_VIRUS, pos);
|
|
|
|
if ( m_blupi[rank].vehicule == 2 ) // en jeep ?
|
|
{
|
|
GoalStart(rank, WM_ACTION_DJEEP, m_blupi[rank].cel);
|
|
goto goal;
|
|
}
|
|
}
|
|
|
|
// Si blupi est complètement épuisé, il meurt.
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].energy == 0 )
|
|
{
|
|
BlupiDeselect(rank);
|
|
BlupiInitAction(rank, ACTION_TCHAO);
|
|
goto init;
|
|
}
|
|
|
|
// Assigne un but s'il s'agit d'une araignée.
|
|
if ( m_blupi[rank].perso == 1 && // araignée ?
|
|
m_blupi[rank].goalAction != WM_ACTION_A_MORT )
|
|
{
|
|
cel = m_blupi[rank].cel;
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
(icon == 10000 || icon == 10001) && // rayon ?
|
|
MoveIsUsed(cel) ) // enclenché ?
|
|
{
|
|
BlupiInitAction(rank, ACTION_A_GRILLE);
|
|
goto init;
|
|
}
|
|
|
|
cel = m_blupi[rank].cel;
|
|
if ( cel.x%2 != 0 && cel.y%2 != 0 )
|
|
{
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == 60 ) // tomates ?
|
|
{
|
|
PutObject(cel, -1,-1); // plus de tomates
|
|
BlupiSound(rank, SOUND_A_HIHI, pos);
|
|
}
|
|
if ( channel == CHOBJECT &&
|
|
icon == 92 ) // poison ?
|
|
{
|
|
PutObject(cel, -1,-1); // plus de poison
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStart(rank, WM_ACTION_A_MORT, m_blupi[rank].cel);
|
|
m_blupi[rank].goalCel = m_blupi[rank].cel;
|
|
goto goal;
|
|
//? BlupiSound(rank, SOUND_A_POISON, pos);
|
|
//? BlupiInitAction(rank, ACTION_A_POISON);
|
|
//? goto init;
|
|
}
|
|
if ( channel == CHOBJECT &&
|
|
icon == 93 ) // piège ?
|
|
{
|
|
BlupiSound(rank, SOUND_PIEGE, pos);
|
|
PutObject(cel, CHOBJECT, 96); // araignée piégée
|
|
BlupiDelete(rank); // supprime araignée
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_blupi[rank].bExist = false;
|
|
if ( m_time%5 == rank%5 && // pas trop souvent !
|
|
SearchSpiderObject(rank, m_blupi[rank].cel, 100, cel, icon) )
|
|
{
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
// direct = DirectSearch(m_blupi[rank].cel, cel);
|
|
// if ( direct != -1 )
|
|
// {
|
|
// vector = GetVector(direct);
|
|
// m_blupi[rank].goalCel.x = m_blupi[rank].cel.x + vector.x;
|
|
// m_blupi[rank].goalCel.y = m_blupi[rank].cel.y + vector.y;
|
|
// FlushUsed(rank);
|
|
// }
|
|
}
|
|
m_blupi[rank].bExist = true;
|
|
}
|
|
|
|
// Assigne un but s'il s'agit d'un virus.
|
|
if ( m_blupi[rank].perso == 2 ) // virus ?
|
|
{
|
|
cel = m_blupi[rank].cel;
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
(icon == 10000 || icon == 10001) && // rayon ?
|
|
MoveIsUsed(cel) ) // enclenché ?
|
|
{
|
|
BlupiInitAction(rank, ACTION_V_GRILLE);
|
|
goto init;
|
|
}
|
|
|
|
min = 50; // ignore si trop loin !
|
|
fRank = -1;
|
|
for ( i=0 ; i<MAXBLUPI ; i++ )
|
|
{
|
|
if ( m_blupi[i].bExist &&
|
|
m_blupi[i].perso == 0 &&
|
|
!m_blupi[i].bMalade )
|
|
{
|
|
lg = abs(m_blupi[rank].cel.x-m_blupi[i].cel.x)+
|
|
abs(m_blupi[rank].cel.y-m_blupi[i].cel.y);
|
|
if ( lg < min )
|
|
{
|
|
min = lg;
|
|
fRank = i;
|
|
}
|
|
}
|
|
}
|
|
if ( fRank != -1 )
|
|
{
|
|
direct = DirectSearch(m_blupi[rank].cel, m_blupi[fRank].cel);
|
|
if ( direct != -1 )
|
|
{
|
|
vector = GetVector(direct);
|
|
m_blupi[rank].goalCel.x = m_blupi[rank].cel.x + vector.x;
|
|
m_blupi[rank].goalCel.y = m_blupi[rank].cel.y + vector.y;
|
|
FlushUsed(rank);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Assigne un but s'il s'agit d'un tracks.
|
|
if ( m_blupi[rank].perso == 3 && // tracks ?
|
|
m_blupi[rank].goalAction != WM_ACTION_T_DYNAMITE )
|
|
{
|
|
cel = m_blupi[rank].cel;
|
|
if ( cel.x%2 != 0 && cel.y%2 != 0 )
|
|
{
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
IsTracksObject(icon) )
|
|
{
|
|
if ( icon == 85 ) // dynamite ?
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStart(rank, WM_ACTION_T_DYNAMITE, cel);
|
|
goto goal;
|
|
}
|
|
if ( icon == 125 || // mine ?
|
|
icon == 127 )
|
|
{
|
|
// Supprime le détonnateur.
|
|
BlupiDelete(GetCel(cel.x+1,cel.y+1), 6);
|
|
}
|
|
if ( icon == 93 ) // piège ?
|
|
{
|
|
BlupiSound(rank, SOUND_PIEGE, pos);
|
|
PutObject(cel, CHOBJECT, 97); // tracks piégé
|
|
BlupiDelete(rank); // supprime tracks
|
|
return;
|
|
}
|
|
|
|
PutObject(cel, -1,-1); // plus d'objet
|
|
|
|
BlupiSound(rank, SOUND_T_ECRASE, pos);
|
|
BlupiInitAction(rank, ACTION_T_ECRASE);
|
|
goto init;
|
|
}
|
|
}
|
|
cel = m_blupi[rank].cel;
|
|
m_blupi[rank].bExist = false;
|
|
if ( IsBlupiHere(cel, false) &&
|
|
m_blupi[m_blupiHere].perso == 0 &&
|
|
m_blupi[m_blupiHere].vehicule == 0 ) // à pied ?
|
|
{
|
|
m_blupi[rank].bExist = true;
|
|
// Blupi écrasé au sol.
|
|
if ( MoveCreate(cel, rank, true, CHFLOOR,-1, -1,-1,
|
|
100,1,100, false, true) )
|
|
{
|
|
if ( m_blupi[m_blupiHere].bMalade ) MoveAddIcons(cel, 10);
|
|
else MoveAddIcons(cel, 9);
|
|
}
|
|
BlupiDelete(m_blupiHere); // plus de blupi !
|
|
BlupiSound(rank, SOUND_AIE, pos);
|
|
BlupiInitAction(rank, ACTION_T_ECRASE); // écrase blupi
|
|
goto init;
|
|
}
|
|
m_blupi[rank].bExist = true;
|
|
|
|
// if ( m_blupi[rank].goalCel.x != -1 )
|
|
// {
|
|
// GetObject(m_blupi[rank].goalCel, channel, icon);
|
|
// if ( IsTracksObject(icon) ) goto action;
|
|
// }
|
|
m_blupi[rank].bExist = false;
|
|
if ( m_time%5 == rank%5 && // pas trop souvent !
|
|
SearchTracksObject(rank, m_blupi[rank].cel, 25, cel, icon) )
|
|
{
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
}
|
|
m_blupi[rank].bExist = true;
|
|
}
|
|
|
|
// Assigne un but s'il s'agit d'un robot.
|
|
if ( m_blupi[rank].perso == 4 && // robot ?
|
|
m_blupi[rank].goalAction != WM_ACTION_T_DYNAMITE )
|
|
{
|
|
cel = m_blupi[rank].cel;
|
|
if ( cel.x%2 != 0 && cel.y%2 != 0 )
|
|
{
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
IsRobotObject(icon) )
|
|
{
|
|
if ( icon == 85 ) // dynamite ?
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStart(rank, WM_ACTION_T_DYNAMITE, cel);
|
|
goto goal;
|
|
}
|
|
if ( icon == 125 || // mine ?
|
|
icon == 127 )
|
|
{
|
|
// Supprime le détonnateur.
|
|
BlupiDelete(GetCel(cel.x+1,cel.y+1), 6);
|
|
}
|
|
if ( icon == 93 ) // piège ?
|
|
{
|
|
BlupiSound(rank, SOUND_PIEGE, pos);
|
|
PutObject(cel, CHOBJECT, 98); // robot piégé
|
|
BlupiDelete(rank); // supprime robot
|
|
return;
|
|
}
|
|
|
|
PutObject(cel, -1,-1); // plus d'objet
|
|
|
|
BlupiSound(rank, SOUND_T_ECRASE, pos);
|
|
BlupiInitAction(rank, ACTION_R_ECRASE);
|
|
goto init;
|
|
}
|
|
}
|
|
cel = m_blupi[rank].cel;
|
|
if ( m_blupi[rank].goalAction == 0 &&
|
|
m_time%17 == rank%17 && // pas trop souvent !
|
|
SearchRobotObject(rank, m_blupi[rank].fix, 50, cel, icon, action) )
|
|
{
|
|
if ( action == -1 )
|
|
{
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
}
|
|
else
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStart(rank, action, cel);
|
|
goto goal;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Assigne un but s'il s'agit d'une bombe.
|
|
if ( m_blupi[rank].perso == 5 && // bombe ?
|
|
m_blupi[rank].goalAction != WM_ACTION_T_DYNAMITE )
|
|
{
|
|
cel = m_blupi[rank].cel;
|
|
if ( cel.x%2 != 0 && cel.y%2 != 0 )
|
|
{
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == 93 ) // piège ?
|
|
{
|
|
BlupiSound(rank, SOUND_PIEGE, pos);
|
|
PutObject(cel, CHOBJECT, 114); // bombe piégée
|
|
BlupiDelete(rank); // supprime bombe
|
|
return;
|
|
}
|
|
}
|
|
for ( i=0 ; i<4 ; i++ )
|
|
{
|
|
vector = GetVector(i*2*16);
|
|
cel.x = ((m_blupi[rank].cel.x + vector.x*2)/2)*2;
|
|
cel.y = ((m_blupi[rank].cel.y + vector.y*2)/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
IsBombeObject(icon) && // cabane, palissade, etc. ?
|
|
icon != 93 ) // pas piège ?
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStart(rank, WM_ACTION_T_DYNAMITE, m_blupi[rank].cel);
|
|
goto goal;
|
|
}
|
|
}
|
|
cel = m_blupi[rank].cel;
|
|
if ( m_blupi[rank].goalAction == 0 &&
|
|
m_time%17 == rank%17 && // pas trop souvent !
|
|
SearchBombeObject(rank, cel, 100, cel, icon) )
|
|
{
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
}
|
|
}
|
|
|
|
// Assigne un but s'il s'agit d'un électro.
|
|
if ( m_blupi[rank].perso == 7 ) // électro ?
|
|
{
|
|
cel = m_blupi[rank].cel;
|
|
if ( cel.x%2 != 0 && cel.y%2 != 0 )
|
|
{
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == 93 ) // piège ?
|
|
{
|
|
BlupiSound(rank, SOUND_PIEGE, pos);
|
|
PutObject(cel, CHOBJECT, 19); // électro piégée
|
|
BlupiDelete(rank); // supprime électro
|
|
return;
|
|
}
|
|
}
|
|
cel = m_blupi[rank].cel;
|
|
if ( m_blupi[rank].goalAction == 0 &&
|
|
m_blupi[rank].goalCel.x == -1 &&
|
|
m_time%37 == rank%37 && // pas trop souvent !
|
|
SearchElectroObject(rank, cel, 100, cel, icon) )
|
|
{
|
|
if ( icon == -1 ) // sur un blupi ?
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
GoalStart(rank, WM_ACTION_E_RAYON, cel);
|
|
m_blupi[rank].fix = cel;
|
|
goto goal;
|
|
}
|
|
m_blupi[rank].goalCel = cel;
|
|
FlushUsed(rank);
|
|
}
|
|
}
|
|
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
|
|
goal:
|
|
if ( m_blupi[rank].goalCel.x != -1 ) // y a-t-il un but ?
|
|
{
|
|
direct = DirectSearch(m_blupi[rank].cel,
|
|
m_blupi[rank].goalCel);
|
|
|
|
if ( direct == -1 ) // but atteint ?
|
|
{
|
|
m_blupi[rank].goalCel.x = -1;
|
|
FlushUsed(rank);
|
|
}
|
|
else
|
|
{
|
|
// Si blupi a peu d'énergie et qu'il transporte
|
|
// qq chose, il doit stopper !
|
|
if ( m_blupi[rank].energy <= MAXENERGY/4 &&
|
|
m_blupi[rank].takeChannel != -1 &&
|
|
(m_blupi[rank].vehicule == 0 || // à pied ?
|
|
m_blupi[rank].vehicule == 3) ) // armure ?
|
|
{
|
|
// Si blupi est en train de descendre de la jeep
|
|
// et qu'il est malade tout en transportant qq
|
|
// chose, il ne faut pas stopper !!!
|
|
cel = m_blupi[rank].cel;
|
|
if ( cel.x%2 != 0 && cel.y%2 != 0 &&
|
|
m_decor[cel.x/2][cel.y/2].objectIcon == 118 && // jeep
|
|
m_blupi[rank].bMalade &&
|
|
m_blupi[rank].takeChannel != -1 ) goto search;
|
|
GoalStop(rank, true);
|
|
}
|
|
else
|
|
{
|
|
search:
|
|
//- BlupiInitAction(rank, ACTION_MARCHE, direct);
|
|
if ( SearchBestPass(rank, action) )
|
|
{
|
|
//- if ( (action >= ACTION_SAUTE2 &&
|
|
//- action <= ACTION_SAUTE5) ||
|
|
//- action == ACTION_GLISSE )
|
|
//- {
|
|
BlupiInitAction(rank, action);
|
|
//- }
|
|
}
|
|
else
|
|
{
|
|
BlupiInitAction(rank, ACTION_STOP);
|
|
if ( m_blupi[rank].perso == 0 || // blupi ?
|
|
m_blupi[rank].perso == 8 ) // disciple ?
|
|
{
|
|
if ( m_blupi[rank].busyCount == 0 ) // dernière tentative ?
|
|
{
|
|
GoalStop(rank, true);
|
|
m_blupi[rank].goalCel.x = -1;
|
|
m_blupi[rank].goalPhase = 0;
|
|
m_blupi[rank].interrupt = 1;
|
|
}
|
|
}
|
|
else // perso ennemi ?
|
|
{
|
|
// On cherchera un autre but !
|
|
GoalStop(rank, true);
|
|
//? m_blupi[rank].goalCel.x = -1;
|
|
//? m_blupi[rank].goalPhase = 0;
|
|
//? m_blupi[rank].interrupt = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GoalNextPhase(rank); // méta opération suivante
|
|
}
|
|
|
|
init:
|
|
BlupiDestCel(rank);
|
|
|
|
m_blupi[rank].phase = 0;
|
|
m_blupi[rank].pos.x = 0;
|
|
m_blupi[rank].pos.y = 0;
|
|
|
|
BlupiNextAction(rank);
|
|
}
|
|
|
|
// Calcule la cellule de destination.
|
|
|
|
void CDecor::BlupiDestCel(int rank)
|
|
{
|
|
int a;
|
|
POINT vector;
|
|
|
|
m_blupi[rank].destCel = m_blupi[rank].cel;
|
|
|
|
if ( m_blupi[rank].action == ACTION_MARCHE ||
|
|
m_blupi[rank].action == ACTION_MARCHEf ||
|
|
m_blupi[rank].action == ACTION_MARCHEb ||
|
|
m_blupi[rank].action == ACTION_MARCHEj ||
|
|
m_blupi[rank].action == ACTION_MARCHEa ||
|
|
m_blupi[rank].action == ACTION_A_MARCHE ||
|
|
m_blupi[rank].action == ACTION_V_MARCHE ||
|
|
m_blupi[rank].action == ACTION_T_MARCHE ||
|
|
m_blupi[rank].action == ACTION_R_MARCHE ||
|
|
m_blupi[rank].action == ACTION_B_MARCHE ||
|
|
m_blupi[rank].action == ACTION_E_MARCHE ||
|
|
m_blupi[rank].action == ACTION_D_MARCHE )
|
|
{
|
|
vector = GetVector(m_blupi[rank].sDirect);
|
|
|
|
m_blupi[rank].destCel.x += vector.x;
|
|
m_blupi[rank].destCel.y += vector.y;
|
|
}
|
|
|
|
a = GetAmplitude(m_blupi[rank].action);
|
|
if ( a > 1 )
|
|
{
|
|
vector = GetVector(m_blupi[rank].sDirect);
|
|
|
|
m_blupi[rank].destCel.x += vector.x*a;
|
|
m_blupi[rank].destCel.y += vector.y*a;
|
|
}
|
|
}
|
|
|
|
// Avance tous les blupis.
|
|
|
|
void CDecor::BlupiStep(bool bFirst)
|
|
{
|
|
int rank;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist )
|
|
{
|
|
if ( !BlupiNextAction(rank) )
|
|
{
|
|
BlupiNextGoal(rank);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( bFirst )
|
|
{
|
|
m_timeConst ++; // avance le temps absolu global constant
|
|
|
|
if ( m_timeConst == m_timeFlipOutline )
|
|
{
|
|
m_bOutline = false; // supprime le mode "outline"
|
|
}
|
|
}
|
|
m_time ++; // avance le temps absolu global
|
|
}
|
|
|
|
|
|
// Retourne le rectangle occupé par un blupi,
|
|
// pour les sélections (pas exact).
|
|
|
|
void CDecor::BlupiGetRect(int rank, RECT &rect)
|
|
{
|
|
POINT pos;
|
|
|
|
pos = ConvCelToPos(m_blupi[rank].cel);
|
|
pos.x += m_blupi[rank].pos.x;
|
|
pos.y += m_blupi[rank].pos.y-(DIMBLUPIY-DIMCELY)-SHIFTBLUPIY;
|
|
|
|
rect.left = pos.x+16;
|
|
rect.top = pos.y+10;
|
|
rect.right = pos.x+DIMBLUPIX-16;
|
|
rect.bottom = pos.y+DIMBLUPIY;
|
|
}
|
|
|
|
// Retourne le blupi visé par la souris.
|
|
|
|
int CDecor::GetTargetBlupi(POINT pos)
|
|
{
|
|
#if 1
|
|
int rank, found, prof;
|
|
POINT test, rel, cel;
|
|
|
|
cel = ConvPosToCel(pos);
|
|
|
|
found = -1;
|
|
prof = 0;
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
(m_blupi[rank].perso == 0 || // blupi ?
|
|
m_blupi[rank].perso == 8) ) // disciple ?
|
|
{
|
|
test = ConvCelToPos(m_blupi[rank].cel);
|
|
test.x += m_blupi[rank].pos.x;
|
|
test.y += m_blupi[rank].pos.y-(DIMBLUPIY-DIMCELY)-SHIFTBLUPIY;
|
|
|
|
if ( pos.x >= test.x &&
|
|
pos.x <= test.x+DIMBLUPIX &&
|
|
pos.y >= test.y &&
|
|
pos.y <= test.y+DIMBLUPIY )
|
|
{
|
|
rel.x = pos.x-test.x;
|
|
rel.y = pos.y-test.y;
|
|
if ( (cel.x == m_blupi[rank].cel.x &&
|
|
cel.y == m_blupi[rank].cel.y ) ||
|
|
(cel.x == m_blupi[rank].destCel.x &&
|
|
cel.y == m_blupi[rank].destCel.y ) ||
|
|
m_pPixmap->IsIconPixel(m_blupi[rank].channel,
|
|
m_blupi[rank].icon,
|
|
rel) )
|
|
{
|
|
if ( found != -1 &&
|
|
test.y < prof ) continue;
|
|
|
|
found = rank;
|
|
prof = test.y;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return found;
|
|
#else
|
|
int rank, found, prof;
|
|
RECT rect;
|
|
POINT cel;
|
|
|
|
found = -1;
|
|
prof = 0;
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
(m_blupi[rank].perso == 0 || // blupi ?
|
|
m_blupi[rank].perso == 8) ) // disciple ?
|
|
{
|
|
BlupiGetRect(rank, rect);
|
|
|
|
if ( pos.x >= rect.left &&
|
|
pos.x <= rect.right &&
|
|
pos.y >= rect.top &&
|
|
pos.y <= rect.bottom )
|
|
{
|
|
if ( found != -1 &&
|
|
rect.top < prof ) continue;
|
|
|
|
found = rank;
|
|
prof = rect.top;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( found != -1 ) return found;
|
|
|
|
cel = ConvPosToCel(pos);
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
(m_blupi[rank].perso == 0 || // blupi ?
|
|
m_blupi[rank].perso == 8) ) // disciple ?
|
|
{
|
|
if ( cel.x == m_blupi[rank].cel.x &&
|
|
cel.y == m_blupi[rank].cel.y ) return rank;
|
|
|
|
if ( cel.x == m_blupi[rank].destCel.x &&
|
|
cel.y == m_blupi[rank].destCel.y ) return rank;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
#endif
|
|
}
|
|
|
|
|
|
// Déslectionne tous les blupi.
|
|
|
|
void CDecor::BlupiDeselect()
|
|
{
|
|
int rank;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
m_blupi[rank].bHili = false;
|
|
m_blupi[rank].bArrow = false;
|
|
}
|
|
|
|
m_nbBlupiHili = 0;
|
|
m_rankBlupiHili = -1;
|
|
}
|
|
|
|
// Déslectionne un blupi.
|
|
|
|
void CDecor::BlupiDeselect(int rank)
|
|
{
|
|
m_blupi[rank].bHili = false;
|
|
m_blupi[rank].bArrow = false;
|
|
|
|
if ( m_nbBlupiHili > 0 &&
|
|
m_rankBlupiHili == rank ) // est-ce le blupi sélectionné ?
|
|
{
|
|
m_nbBlupiHili = 0;
|
|
m_rankBlupiHili = -1;
|
|
}
|
|
}
|
|
|
|
// Met ou enlève une flèche au blupi sélectionné blupi.
|
|
|
|
void CDecor::BlupiSetArrow(int rank, bool bArrow)
|
|
{
|
|
m_celArrow.x = -1;
|
|
|
|
if ( bArrow )
|
|
{
|
|
m_blupi[rank].bArrow = true;
|
|
}
|
|
else
|
|
{
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
m_blupi[rank].bArrow = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialise la zone outline en fonction du rectangle de sélection.
|
|
|
|
void CDecor::InitOutlineRect()
|
|
{
|
|
if ( !m_bOutline && m_bHiliRect )
|
|
{
|
|
m_celOutline1.x = m_p1Hili.x<m_p2Hili.x ? m_p1Hili.x : m_p2Hili.x;
|
|
m_celOutline1.y = m_p1Hili.y<m_p2Hili.y ? m_p1Hili.y : m_p2Hili.y;
|
|
m_celOutline2.x = m_p1Hili.x>m_p2Hili.x ? m_p1Hili.x : m_p2Hili.x;
|
|
m_celOutline2.y = m_p1Hili.y>m_p2Hili.y ? m_p1Hili.y : m_p2Hili.y;
|
|
m_celOutline1.x = (m_celOutline1.x/2)*2;
|
|
m_celOutline1.y = (m_celOutline1.y/2)*2;
|
|
m_celOutline2.x += 2;
|
|
m_celOutline2.y += 2;
|
|
}
|
|
else
|
|
{
|
|
m_celOutline1.x = -1;
|
|
m_celOutline2.x = -1;
|
|
}
|
|
}
|
|
|
|
// Sélectionne un blupi lorsque le bouton est pressé.
|
|
|
|
void CDecor::BlupiHiliDown(POINT pos, bool bAdd)
|
|
{
|
|
if ( MapMove(pos) ) return;
|
|
|
|
if ( !bAdd ) BlupiDeselect();
|
|
|
|
m_p1Hili = ConvPosToCel(pos);
|
|
m_p2Hili = ConvPosToCel(pos);
|
|
m_bHiliRect = true;
|
|
m_celHili.x = -1;
|
|
|
|
InitOutlineRect();
|
|
}
|
|
|
|
// Sélectionne un blupi lorsque la souris est déplacée.
|
|
|
|
void CDecor::BlupiHiliMove(POINT pos, bool bAdd)
|
|
{
|
|
if ( m_bHiliRect ) // rectangle de sélection existe ?
|
|
{
|
|
m_p2Hili = ConvPosToCel(pos);
|
|
InitOutlineRect();
|
|
}
|
|
}
|
|
|
|
// Sélectionne un blupi lorsque le bouton est relâché.
|
|
// Retourne false si la sélection n'a pas changé !
|
|
|
|
void CDecor::BlupiHiliUp(POINT pos, bool bAdd)
|
|
{
|
|
int rank, r, nb, sound;
|
|
bool bEnerve = false;
|
|
POINT c1, c2;
|
|
|
|
static int table_sound_ok[6] =
|
|
{
|
|
SOUND_OK1,
|
|
SOUND_OK2,
|
|
SOUND_OK3,
|
|
SOUND_OK4,
|
|
SOUND_OK5,
|
|
SOUND_OK6,
|
|
};
|
|
|
|
static int table_sound_okf[3] = // si fatigué
|
|
{
|
|
SOUND_OK1f,
|
|
SOUND_OK2f,
|
|
SOUND_OK3f,
|
|
};
|
|
|
|
static int table_sound_oke[3] = // si énervé
|
|
{
|
|
SOUND_OK1e,
|
|
SOUND_OK2e,
|
|
SOUND_OK3e,
|
|
};
|
|
|
|
if ( m_bHiliRect ) // rectangle de sélection existe ?
|
|
{
|
|
nb = 0;
|
|
|
|
if ( m_p1Hili.x == m_p2Hili.x &&
|
|
m_p1Hili.y == m_p2Hili.y )
|
|
{
|
|
rank = GetTargetBlupi(pos); // rank <- blupi visé par la souris
|
|
if ( rank != -1 )
|
|
{
|
|
m_blupi[rank].bHili = !m_blupi[rank].bHili;
|
|
if ( m_blupi[rank].bHili )
|
|
{
|
|
if ( m_blupi[rank].clicDelay > 0 )
|
|
{
|
|
m_blupi[rank].clicDelay = 80;
|
|
m_blupi[rank].clicCount ++;
|
|
if ( m_blupi[rank].clicCount > 4 )
|
|
{
|
|
bEnerve = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].clicDelay = 40;
|
|
}
|
|
nb = 1;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( m_p1Hili.x < m_p2Hili.x )
|
|
{
|
|
c1.x = m_p1Hili.x;
|
|
c2.x = m_p2Hili.x+1;
|
|
}
|
|
else
|
|
{
|
|
c1.x = m_p2Hili.x;
|
|
c2.x = m_p1Hili.x+1;
|
|
}
|
|
|
|
if ( m_p1Hili.y < m_p2Hili.y )
|
|
{
|
|
c1.y = m_p1Hili.y;
|
|
c2.y = m_p2Hili.y+1;
|
|
}
|
|
else
|
|
{
|
|
c1.y = m_p2Hili.y;
|
|
c2.y = m_p1Hili.y+1;
|
|
}
|
|
|
|
for ( r=0 ; r<MAXBLUPI ; r++ )
|
|
{
|
|
if ( m_blupi[r].bExist &&
|
|
(m_blupi[r].perso == 0 || // blupi ?
|
|
m_blupi[r].perso == 8) ) // disciple ?
|
|
{
|
|
if ( m_blupi[r].cel.x >= c1.x &&
|
|
m_blupi[r].cel.x < c2.x &&
|
|
m_blupi[r].cel.y >= c1.y &&
|
|
m_blupi[r].cel.y < c2.y )
|
|
{
|
|
m_blupi[r].bHili = true;
|
|
nb ++;
|
|
rank = r;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_bHiliRect = false; // plus de rectangle
|
|
InitOutlineRect();
|
|
|
|
if ( nb > 0 )
|
|
{
|
|
if ( nb > 1 ) // sélection multiple ?
|
|
{
|
|
sound = table_sound_ok[Random(0,5)];
|
|
}
|
|
else
|
|
{
|
|
if ( m_blupi[rank].energy <= MAXENERGY/4 )
|
|
{
|
|
sound = table_sound_okf[Random(0,2)];
|
|
}
|
|
else
|
|
{
|
|
sound = table_sound_ok[Random(0,5)];
|
|
}
|
|
if ( bEnerve ) // déjà sélectionné y'a peu ?
|
|
{
|
|
sound = table_sound_oke[Random(0,2)];
|
|
}
|
|
}
|
|
BlupiSound(rank, sound, pos, true);
|
|
}
|
|
}
|
|
|
|
m_nbBlupiHili = 0;
|
|
m_rankBlupiHili = -1;
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
m_blupi[rank].bArrow = false;
|
|
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].bHili )
|
|
{
|
|
m_nbBlupiHili ++;
|
|
m_rankBlupiHili = rank;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dessine le rectangle de sélection, si nécessaire.
|
|
|
|
void CDecor::BlupiDrawHili()
|
|
{
|
|
POINT c1, c2, cc;
|
|
POINT p1, p2, p3, p4;
|
|
POINT start, pos;
|
|
RECT rect;
|
|
int shift;
|
|
|
|
if ( !m_bHiliRect ) return;
|
|
|
|
if ( m_p1Hili.x < m_p2Hili.x )
|
|
{
|
|
c1.x = m_p1Hili.x;
|
|
c2.x = m_p2Hili.x+1;
|
|
}
|
|
else
|
|
{
|
|
c1.x = m_p2Hili.x;
|
|
c2.x = m_p1Hili.x+1;
|
|
}
|
|
|
|
if ( m_p1Hili.y < m_p2Hili.y )
|
|
{
|
|
c1.y = m_p1Hili.y;
|
|
c2.y = m_p2Hili.y+1;
|
|
}
|
|
else
|
|
{
|
|
c1.y = m_p2Hili.y;
|
|
c2.y = m_p1Hili.y+1;
|
|
}
|
|
|
|
p1 = ConvCelToPos(c1); // p1 en haut
|
|
p2 = ConvCelToPos(c2); // p2 en bas
|
|
|
|
cc.x = c1.x;
|
|
cc.y = c2.y;
|
|
p3 = ConvCelToPos(cc); // p3 à gauche
|
|
|
|
cc.x = c2.x;
|
|
cc.y = c1.y;
|
|
p4 = ConvCelToPos(cc); // p4 à droite
|
|
|
|
p1.x += DIMCELX/2;
|
|
p2.x += DIMCELX/2;
|
|
p3.x += DIMCELX/2;
|
|
p4.x += DIMCELX/2;
|
|
|
|
shift = m_shiftHili%(64/2);
|
|
|
|
start.x = p1.x-shift*2;
|
|
start.y = p1.y-shift-1;
|
|
while ( start.x < p4.x )
|
|
{
|
|
pos = start;
|
|
rect.left = 0;
|
|
rect.right = 64;
|
|
rect.top = 0;
|
|
rect.bottom = 66/2;
|
|
if ( pos.x+rect.right > p4.x )
|
|
{
|
|
rect.right = p4.x-pos.x;
|
|
}
|
|
if ( pos.x < p1.x )
|
|
{
|
|
rect.left += p1.x-pos.x;
|
|
rect.top += (p1.x-pos.x)/2;
|
|
pos.x = p1.x;
|
|
pos.y = p1.y-1;
|
|
}
|
|
m_pPixmap->DrawPart(-1, CHHILI, pos, rect); // ligne p1-p4
|
|
|
|
start.x += 64;
|
|
start.y += 64/2;
|
|
}
|
|
|
|
start.x = p3.x-shift*2;
|
|
start.y = p3.y-shift-1;
|
|
while ( start.x < p2.x )
|
|
{
|
|
pos = start;
|
|
rect.left = 0;
|
|
rect.right = 64;
|
|
rect.top = 0;
|
|
rect.bottom = 66/2;
|
|
if ( pos.x+rect.right > p2.x )
|
|
{
|
|
rect.right = p2.x-pos.x;
|
|
}
|
|
if ( pos.x < p3.x )
|
|
{
|
|
rect.left += p3.x-pos.x;
|
|
rect.top += (p3.x-pos.x)/2;
|
|
pos.x = p3.x;
|
|
pos.y = p3.y-1;
|
|
}
|
|
m_pPixmap->DrawPart(-1, CHHILI, pos, rect); // ligne p3-p2
|
|
|
|
start.x += 64;
|
|
start.y += 64/2;
|
|
}
|
|
|
|
start.x = p3.x-shift*2;
|
|
start.y = p3.y+shift-66/2;
|
|
while ( start.x < p1.x )
|
|
{
|
|
pos = start;
|
|
rect.left = 0;
|
|
rect.right = 64;
|
|
rect.top = 66/2;
|
|
rect.bottom = 66;
|
|
if ( pos.x+rect.right > p1.x )
|
|
{
|
|
rect.right = p1.x-pos.x;
|
|
}
|
|
if ( pos.x < p3.x )
|
|
{
|
|
rect.left += p3.x-pos.x;
|
|
rect.bottom -= (p3.x-pos.x)/2;
|
|
pos.x = p3.x;
|
|
}
|
|
m_pPixmap->DrawPart(-1, CHHILI, pos, rect); // ligne p3-p1
|
|
|
|
start.x += 64;
|
|
start.y -= 64/2;
|
|
}
|
|
|
|
start.x = p2.x-shift*2;
|
|
start.y = p2.y+shift-66/2;
|
|
while ( start.x < p4.x )
|
|
{
|
|
pos = start;
|
|
rect.left = 0;
|
|
rect.right = 64;
|
|
rect.top = 66/2;
|
|
rect.bottom = 66;
|
|
if ( pos.x+rect.right > p4.x )
|
|
{
|
|
rect.right = p4.x-pos.x;
|
|
}
|
|
if ( pos.x < p2.x )
|
|
{
|
|
rect.left += p2.x-pos.x;
|
|
rect.bottom -= (p2.x-pos.x)/2;
|
|
pos.x = p2.x;
|
|
}
|
|
m_pPixmap->DrawPart(-1, CHHILI, pos, rect); // ligne p2-p4
|
|
|
|
start.x += 64;
|
|
start.y -= 64/2;
|
|
}
|
|
|
|
m_shiftHili += 3;
|
|
}
|
|
|
|
|
|
// Retourne le bouton par défaut à un endroit donné.
|
|
// Est utilisé pour trouver que faire lors d'un clic
|
|
// avec le bouton de droite.
|
|
|
|
int CDecor::GetDefButton(POINT cel)
|
|
{
|
|
int button, rank, channel, icon;
|
|
POINT iCel;
|
|
|
|
iCel = cel;
|
|
cel.x = (cel.x/2)*2;
|
|
cel.y = (cel.y/2)*2;
|
|
GetObject(cel, channel, icon);
|
|
|
|
if ( m_nbBlupiHili == 0 ) return -1;
|
|
if ( m_nbBlupiHili > 1 ) return BUTTON_GO;
|
|
rank = m_rankBlupiHili;
|
|
|
|
button = BUTTON_GO;
|
|
|
|
if ( channel == CHOBJECT )
|
|
{
|
|
if ( icon >= 7 &&
|
|
icon <= 11 ) button = BUTTON_ABAT;
|
|
if ( icon >= 37 &&
|
|
icon <= 43 ) button = BUTTON_ROC;
|
|
|
|
if ( icon == 61 ) button = BUTTON_CULTIVE; // cabane
|
|
if ( icon == 122 ) button = BUTTON_EXTRAIT; // extrait
|
|
|
|
if ( iCel.x%2 == 1 && iCel.y%2 == 1 )
|
|
{
|
|
if ( icon == 14 ) button = BUTTON_CARRY; // métal
|
|
if ( icon == 36 ) button = BUTTON_CARRY; // planches
|
|
if ( icon == 44 ) button = BUTTON_CARRY; // pierres
|
|
if ( icon == 60 ) button = BUTTON_MANGE; // tomates
|
|
if ( icon == 63 ) button = BUTTON_CARRY; // oeufs
|
|
if ( icon == 80 ) button = BUTTON_BOIT; // bouteille
|
|
if ( icon == 82 ) button = BUTTON_CARRY; // fleurs
|
|
if ( icon == 84 ) button = BUTTON_CARRY; // fleurs
|
|
if ( icon == 95 ) button = BUTTON_CARRY; // fleurs
|
|
if ( icon == 85 ) button = BUTTON_CARRY; // dynamite
|
|
if ( icon == 92 ) button = BUTTON_CARRY; // poison
|
|
if ( icon == 93 ) button = BUTTON_CARRY; // piège
|
|
if ( icon == 123 ) button = BUTTON_CARRY; // fer
|
|
if ( icon == 125 ) button = BUTTON_CARRY; // mine
|
|
}
|
|
|
|
if ( icon == 28 && // laboratoire ?
|
|
m_blupi[rank].energy > MAXENERGY/4 &&
|
|
m_blupi[rank].takeChannel == CHOBJECT &&
|
|
(m_blupi[rank].takeIcon == 82 || // porte fleurs ?
|
|
m_blupi[rank].takeIcon == 84 ||
|
|
m_blupi[rank].takeIcon == 95 ||
|
|
m_blupi[rank].takeIcon == 60) ) // porte tomates ?
|
|
{
|
|
button = BUTTON_LABO; // transforme
|
|
}
|
|
}
|
|
|
|
if ( !m_blupi[rank].bMalade &&
|
|
button == BUTTON_BOIT )
|
|
{
|
|
button = BUTTON_CARRY; // porte la bouteille si pas malade
|
|
}
|
|
|
|
if ( (m_blupi[rank].energy <= MAXENERGY/4 ||
|
|
m_blupi[rank].takeChannel != -1 ) &&
|
|
(button == BUTTON_ABAT ||
|
|
button == BUTTON_CARRY ||
|
|
button == BUTTON_ROC ||
|
|
button == BUTTON_CULTIVE ) )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
if ( m_blupi[rank].energy > (MAXENERGY/4)*3 &&
|
|
button == BUTTON_MANGE )
|
|
{
|
|
button = BUTTON_CARRY;
|
|
}
|
|
|
|
if ( m_buttonExist[button] == 0 ) // bouton existe ?
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return button;
|
|
}
|
|
|
|
// Indique un but visé à long terme, pour un blupi donné.
|
|
|
|
bool CDecor::BlupiGoal(int rank, int button, POINT cel, POINT cMem)
|
|
{
|
|
POINT goalHili, goalHili2, goal, test;
|
|
int i, action, channel, icon, error, direct, step;
|
|
bool bRepeat = false;
|
|
|
|
// Si plusieurs blupi sont sélectionnés, ils ne vont pas
|
|
// tous à la même destination.
|
|
if ( button == BUTTON_GO )
|
|
{
|
|
step = 0;
|
|
for ( i=0 ; i<rank ; i++ )
|
|
{
|
|
if ( m_blupi[i].bExist &&
|
|
m_blupi[i].bHili ) step ++;
|
|
}
|
|
if ( step > 15 ) step = 15;
|
|
cel.x += table_multi_goal[step*2+0];
|
|
cel.y += table_multi_goal[step*2+1];
|
|
cMem.x += table_multi_goal[step*2+0];
|
|
cMem.y += table_multi_goal[step*2+1];
|
|
}
|
|
|
|
if ( !IsCheminFree(rank, cel, button) ) return false;
|
|
|
|
goal = cel;
|
|
goalHili = cel;
|
|
goalHili2.x = (cel.x/2)*2;
|
|
goalHili2.y = (cel.y/2)*2;
|
|
|
|
if ( button == BUTTON_GO &&
|
|
m_decor[goalHili.x/2][goalHili.y/2].objectIcon == 113 ) // maison ?
|
|
{
|
|
goalHili.x = (goalHili.x/2)*2+1;
|
|
goalHili.y = (goalHili.y/2)*2+1;
|
|
}
|
|
|
|
if ( button == BUTTON_ABATn )
|
|
{
|
|
button = BUTTON_ABAT;
|
|
bRepeat = true;
|
|
}
|
|
if ( button == BUTTON_ROCn )
|
|
{
|
|
button = BUTTON_ROC;
|
|
bRepeat = true;
|
|
}
|
|
if ( button == BUTTON_FLEURn )
|
|
{
|
|
button = BUTTON_FLEUR;
|
|
bRepeat = true;
|
|
}
|
|
action = table_actions[button];
|
|
|
|
if ( action == WM_ACTION_STOP )
|
|
{
|
|
if ( m_blupi[rank].goalAction != 0 &&
|
|
m_blupi[rank].interrupt <= 0 )
|
|
{
|
|
m_blupi[rank].stop = 1; // faudra stopper
|
|
}
|
|
else
|
|
{
|
|
m_blupi[rank].goalCel = m_blupi[rank].destCel;
|
|
m_blupi[rank].goalAction = 0;
|
|
}
|
|
m_blupi[rank].repeatLevel = -1; // stoppe la répétition
|
|
return false;
|
|
}
|
|
|
|
// Action prioritaire en cours ?
|
|
if ( m_blupi[rank].goalAction != 0 &&
|
|
m_blupi[rank].interrupt <= 0 ) return false;
|
|
|
|
error = CelOkForAction(goalHili, action, rank);
|
|
if ( error != 0 && error != ERROR_TOURISOL ) return false;
|
|
|
|
if ( action == WM_ACTION_GO &&
|
|
m_blupi[rank].energy <= MAXENERGY/4 &&
|
|
m_blupi[rank].takeChannel != -1 ) return false;
|
|
|
|
if ( action == WM_ACTION_GO )
|
|
{
|
|
GetObject(goalHili2, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == 120 && // usine ?
|
|
goalHili.x%2 == 0 && // au fond ?
|
|
goalHili.y%2 == 1 )
|
|
{
|
|
return false; // action refusée
|
|
}
|
|
if ( m_blupi[rank].perso != 8 && // pas disciple ?
|
|
channel == CHOBJECT &&
|
|
icon == 118 && // jeep ?
|
|
goalHili.x%2 == 1 && // sur la jeep ?
|
|
goalHili.y%2 == 1 )
|
|
{
|
|
action = WM_ACTION_MJEEP;
|
|
}
|
|
if ( m_blupi[rank].perso != 8 && // pas disciple ?
|
|
m_blupi[rank].takeChannel == -1 && // ne porte rien ?
|
|
channel == CHOBJECT &&
|
|
icon == 16 && // armure ?
|
|
goalHili.x%2 == 1 && // sur l'armure ?
|
|
goalHili.y%2 == 1 )
|
|
{
|
|
action = WM_ACTION_MARMURE;
|
|
}
|
|
if ( m_blupi[rank].perso != 8 && // pas disciple ?
|
|
channel == CHOBJECT &&
|
|
icon == 113 ) // maison ?
|
|
{
|
|
action = WM_ACTION_MAISON;
|
|
}
|
|
GetFloor(goalHili2, channel, icon);
|
|
if ( m_blupi[rank].perso == 0 &&
|
|
m_blupi[rank].vehicule == 0 && // à pied ?
|
|
m_blupi[rank].takeChannel == -1 && // ne porte rien ?
|
|
channel == CHFLOOR &&
|
|
icon == 80 ) // téléporteur ?
|
|
{
|
|
if ( cel.x%2 == 0 && cel.y%2 == 0 )
|
|
{
|
|
action = WM_ACTION_TELEPORTE00;
|
|
}
|
|
if ( cel.x%2 == 1 && cel.y%2 == 0 )
|
|
{
|
|
action = WM_ACTION_TELEPORTE10;
|
|
}
|
|
if ( cel.x%2 == 0 && cel.y%2 == 1 )
|
|
{
|
|
action = WM_ACTION_TELEPORTE01;
|
|
}
|
|
if ( cel.x%2 == 1 && cel.y%2 == 1 )
|
|
{
|
|
action = WM_ACTION_TELEPORTE11;
|
|
}
|
|
}
|
|
IsFreeCelEmbarque(goalHili, rank, action, goal);
|
|
IsFreeCelDebarque(goalHili, rank, action, goal);
|
|
}
|
|
|
|
if ( action == WM_ACTION_DEPOSE &&
|
|
m_blupi[rank].energy <= MAXENERGY/4 )
|
|
{
|
|
// Energie juste pour déposer l'objet transporté.
|
|
m_blupi[rank].energy = MAXENERGY/4+20;
|
|
}
|
|
|
|
if ( action == WM_ACTION_ABAT1 )
|
|
{
|
|
GetObject(goalHili2, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon >= 6 && icon <= 11 ) // arbre ?
|
|
{
|
|
action += icon-6; // WM_ACTION_ABAT1..6
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_ROC1 )
|
|
{
|
|
GetObject(goalHili2, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon >= 37 && icon <= 43 ) // rochers ?
|
|
{
|
|
action += icon-37; // WM_ACTION_ROC1..7
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_FLEUR1 )
|
|
{
|
|
GetObject(goalHili2, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == 83 ) // fleurs foncées ?
|
|
{
|
|
action = WM_ACTION_FLEUR2;
|
|
}
|
|
if ( channel == CHOBJECT &&
|
|
icon == 94 ) // fleurs vertes ?
|
|
{
|
|
action = WM_ACTION_FLEUR3;
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_PONTE )
|
|
{
|
|
cel = goalHili2;
|
|
test = goalHili2;
|
|
if ( IsBuildPont(test, icon) != 0 ) return false;
|
|
|
|
m_blupi[rank].nLoop = static_cast<short> (abs((test.x-cel.x)+(test.y-cel.y))/2);
|
|
m_blupi[rank].cLoop = 0;
|
|
m_blupi[rank].vIcon = icon;
|
|
m_blupi[rank].fix = cel;
|
|
|
|
if ( test.x-cel.x < 0 ) action = WM_ACTION_PONTO;
|
|
if ( test.y-cel.y > 0 ) action = WM_ACTION_PONTS;
|
|
if ( test.y-cel.y < 0 ) action = WM_ACTION_PONTN;
|
|
}
|
|
|
|
if ( action == WM_ACTION_BATEAUE )
|
|
{
|
|
if ( !IsBuildBateau(goalHili2, direct) ) return false;
|
|
|
|
if ( direct == DIRECT_S ) action = WM_ACTION_BATEAUS;
|
|
if ( direct == DIRECT_O ) action = WM_ACTION_BATEAUO;
|
|
if ( direct == DIRECT_N ) action = WM_ACTION_BATEAUN;
|
|
}
|
|
|
|
if ( action == WM_ACTION_CARRY )
|
|
{
|
|
if ( IsBlupiHereEx(GetCel(goalHili2,0,1), rank, true) )
|
|
{
|
|
action = WM_ACTION_CARRY2;
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_DEPOSE )
|
|
{
|
|
GetFloor(goalHili2, channel, icon);
|
|
if ( channel == CHFLOOR && icon == 52 && // nurserie ?
|
|
m_blupi[rank].takeChannel == CHOBJECT &&
|
|
m_blupi[rank].takeIcon == 63 ) // oeufs ?
|
|
{
|
|
action = WM_ACTION_NEWBLUPI;
|
|
}
|
|
if ( !IsFreeCelDepose(GetCel(goalHili2,0,1), rank) ||
|
|
IsBlupiHereEx(GetCel(goalHili2,0,1), rank, true) )
|
|
{
|
|
action = WM_ACTION_DEPOSE2;
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_MANGE )
|
|
{
|
|
if ( IsBlupiHereEx(GetCel(goalHili2,0,1), rank, true) )
|
|
{
|
|
action = WM_ACTION_MANGE2;
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_BOIT )
|
|
{
|
|
if ( IsBlupiHereEx(GetCel(goalHili2,0,1), rank, true) )
|
|
{
|
|
action = WM_ACTION_BOIT2;
|
|
}
|
|
}
|
|
|
|
if ( action == WM_ACTION_DYNAMITE )
|
|
{
|
|
GetObject(goalHili2, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == 125 ) // mine ?
|
|
{
|
|
action = WM_ACTION_MINE;
|
|
}
|
|
else
|
|
{
|
|
if ( m_blupi[rank].takeChannel == CHOBJECT &&
|
|
m_blupi[rank].takeIcon == 85 ) // porte dynamite ?
|
|
{
|
|
action = WM_ACTION_DYNAMITE2;
|
|
}
|
|
}
|
|
}
|
|
|
|
GoalStart(rank, action, goal);
|
|
m_blupi[rank].bRepeat = bRepeat;
|
|
m_blupi[rank].busyCount = 5; // 5 tentatives au maximum
|
|
m_blupi[rank].busyDelay = 0;
|
|
|
|
if ( action == WM_ACTION_REPEAT )
|
|
{
|
|
m_blupi[rank].repeatLevel = m_blupi[rank].repeatLevelHope;
|
|
m_blupi[rank].listCel[m_blupi[rank].repeatLevel] = goal;
|
|
}
|
|
else
|
|
{
|
|
ListPut(rank, button, goal, cMem);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Indique un but visé à long terme, pour tous les blupi
|
|
// sélectionnés.
|
|
|
|
void CDecor::BlupiGoal(POINT cel, int button)
|
|
{
|
|
POINT bPos, avg;
|
|
int rank, nb, nbHili;
|
|
|
|
static int table_sound_go[6] =
|
|
{
|
|
SOUND_GO1,
|
|
SOUND_GO2,
|
|
SOUND_GO3,
|
|
SOUND_GO4,
|
|
SOUND_GO5,
|
|
SOUND_GO6,
|
|
};
|
|
|
|
static int table_sound_gom[3] =
|
|
{
|
|
SOUND_GO4,
|
|
SOUND_GO5,
|
|
SOUND_GO6,
|
|
};
|
|
|
|
static int table_sound_boing[3] =
|
|
{
|
|
SOUND_BOING1,
|
|
SOUND_BOING2,
|
|
SOUND_BOING3,
|
|
};
|
|
|
|
if ( button == -1 )
|
|
{
|
|
avg = ConvCelToPos(cel);
|
|
m_pSound->PlayImage(table_sound_boing[Random(0,2)], avg);
|
|
return;
|
|
}
|
|
|
|
avg.x = 0;
|
|
avg.y = 0;
|
|
nb = 0;
|
|
nbHili = 0;
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].bHili )
|
|
{
|
|
bPos = ConvCelToPos(m_blupi[rank].cel);
|
|
avg.x += bPos.x;
|
|
avg.y += bPos.y;
|
|
nbHili ++;
|
|
|
|
if ( BlupiGoal(rank, button, cel, cel) )
|
|
{
|
|
nb ++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( button == BUTTON_STOP ) return;
|
|
|
|
if ( nbHili > 0 )
|
|
{
|
|
avg.x /= nbHili;
|
|
avg.y /= nbHili;
|
|
}
|
|
if ( avg.x < 0 ) avg.x = 0;
|
|
if ( avg.x > LXIMAGE ) avg.x = LXIMAGE;
|
|
avg.y = LYIMAGE/2;
|
|
|
|
if ( nb == 0 && nbHili > 0 )
|
|
{
|
|
if ( nbHili == 1 )
|
|
{
|
|
BlupiSound(m_rankBlupiHili, table_sound_boing[Random(0,2)], avg, true);
|
|
}
|
|
else
|
|
{
|
|
m_pSound->PlayImage(table_sound_boing[Random(0,2)], avg);
|
|
}
|
|
}
|
|
|
|
if ( nb > 0 )
|
|
{
|
|
if ( nbHili == 1 )
|
|
{
|
|
BlupiSound(m_rankBlupiHili, table_sound_go[Random(0,5)], avg, true);
|
|
}
|
|
else
|
|
{
|
|
m_pSound->PlayImage(table_sound_gom[Random(0,2)], avg);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Indique si une cellule est occupée pour un tracks.
|
|
// La cellule est considérée libre uniquement si elle
|
|
// contient un blupi à pied ou un détonnateur de mine
|
|
// (personnage invisible).
|
|
|
|
bool CDecor::IsTracksHere(POINT cel, bool bSkipInMove)
|
|
{
|
|
int rank;
|
|
|
|
if ( !IsValid(cel) ) return false;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
(m_blupi[rank].perso != 0 || // blupi ?
|
|
m_blupi[rank].vehicule != 0 || // à pied ?
|
|
m_bInvincible) &&
|
|
m_blupi[rank].perso != 6 ) // détonnateur ?
|
|
{
|
|
if ( bSkipInMove && m_blupi[rank].goalCel.x != -1 ) continue;
|
|
|
|
if ( cel.x == m_blupi[rank].cel.x &&
|
|
cel.y == m_blupi[rank].cel.y )
|
|
{
|
|
m_blupiHere = rank;
|
|
return true;
|
|
}
|
|
|
|
if ( cel.x == m_blupi[rank].destCel.x &&
|
|
cel.y == m_blupi[rank].destCel.y )
|
|
{
|
|
m_blupiHere = rank;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Indique si une cellule est occupée par un blupi.
|
|
// Le blupi donné dans exRank est ignoré !
|
|
|
|
bool CDecor::IsBlupiHereEx(POINT cel1, POINT cel2, int exRank, bool bSkipInMove)
|
|
{
|
|
int rank;
|
|
|
|
if ( !IsValid(cel1) ) return false;
|
|
if ( !IsValid(cel2) ) return false;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].perso != 6 && // pas le détonnateur de mine
|
|
rank != exRank )
|
|
{
|
|
if ( bSkipInMove && m_blupi[rank].goalCel.x != -1 ) continue;
|
|
|
|
if ( cel1.x <= m_blupi[rank].cel.x &&
|
|
cel2.x >= m_blupi[rank].cel.x &&
|
|
cel1.y <= m_blupi[rank].cel.y &&
|
|
cel2.y >= m_blupi[rank].cel.y )
|
|
{
|
|
m_blupiHere = rank;
|
|
return true;
|
|
}
|
|
|
|
if ( cel1.x <= m_blupi[rank].destCel.x &&
|
|
cel2.x >= m_blupi[rank].destCel.x &&
|
|
cel1.y <= m_blupi[rank].destCel.y &&
|
|
cel2.y >= m_blupi[rank].destCel.y )
|
|
{
|
|
m_blupiHere = rank;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Indique si une cellule est occupée par un blupi.
|
|
// Le blupi donné dans exRank est ignoré !
|
|
|
|
bool CDecor::IsBlupiHereEx(POINT cel, int exRank, bool bSkipInMove)
|
|
{
|
|
int rank;
|
|
|
|
if ( !IsValid(cel) ) return false;
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].perso != 6 && // pas le détonnateur de mine
|
|
rank != exRank )
|
|
{
|
|
if ( bSkipInMove && m_blupi[rank].goalCel.x != -1 ) continue;
|
|
|
|
if ( cel.x == m_blupi[rank].cel.x &&
|
|
cel.y == m_blupi[rank].cel.y )
|
|
{
|
|
m_blupiHere = rank;
|
|
return true;
|
|
}
|
|
|
|
if ( cel.x == m_blupi[rank].destCel.x &&
|
|
cel.y == m_blupi[rank].destCel.y )
|
|
{
|
|
m_blupiHere = rank;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Indique si une cellule est occupée par un blupi.
|
|
|
|
bool CDecor::IsBlupiHere(POINT cel, bool bSkipInMove)
|
|
{
|
|
return IsBlupiHereEx(cel, -1, bSkipInMove);
|
|
}
|
|
|
|
// Indique si une cellule future (dans une direction donnée)
|
|
// est déjà occupée par un blupi.
|
|
|
|
bool CDecor::IsBlupiHere(POINT cel, int direct, bool bSkipInMove)
|
|
{
|
|
POINT vector;
|
|
|
|
vector = GetVector(direct);
|
|
|
|
cel.x += vector.x;
|
|
cel.y += vector.y;
|
|
|
|
return IsBlupiHereEx(cel, -1, bSkipInMove);
|
|
}
|
|
|
|
|
|
// Retourne les niveaux des jauges.
|
|
|
|
void CDecor::GetLevelJauge(int *pLevels, int *pTypes)
|
|
{
|
|
int rank;
|
|
|
|
pLevels[0] = -1;
|
|
pLevels[1] = -1;
|
|
|
|
rank = m_rankBlupiHili;
|
|
|
|
if ( m_nbBlupiHili == 1 ) // un seul blupi sélectionné ?
|
|
{
|
|
pLevels[0] = (m_blupi[rank].energy*100)/MAXENERGY;
|
|
|
|
pTypes[0] = 1; // rouge
|
|
if ( m_blupi[rank].energy > MAXENERGY/4 )
|
|
{
|
|
pTypes[0] = 2; // bleu
|
|
}
|
|
}
|
|
|
|
if ( m_blupi[rank].interrupt == 0 &&
|
|
m_blupi[rank].jaugeMax > 0 )
|
|
{
|
|
pLevels[1] = (m_blupi[rank].jaugePhase*100)/
|
|
m_blupi[rank].jaugeMax;
|
|
pTypes[1] = 3; // jaune
|
|
}
|
|
}
|
|
|
|
|
|
// Retourne true si un blupi est déjà sélectionné et qu'il
|
|
// effectue une action prioritaire. Dans ce cas, il faut tout
|
|
// de suite mettre le menu "stoppe" s'il est cliqué.
|
|
|
|
bool CDecor::IsWorkBlupi(int rank)
|
|
{
|
|
if ( m_blupi[rank].bHili &&
|
|
m_blupi[m_rankBlupiHili].goalAction != 0 &&
|
|
m_blupi[m_rankBlupiHili].interrupt <= 0 ) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// Retourne les boutons possibles à un endroit donné,
|
|
// pour le blupi sélectionné.
|
|
|
|
void CDecor::BlupiGetButtons(POINT pos, int &nb,
|
|
int *pButtons, int *pErrors, int &perso)
|
|
{
|
|
int* pB = pButtons;
|
|
int* pE = pErrors;
|
|
POINT cel, cel2;
|
|
int i, rank, button, error, channel, icon, textForButton;
|
|
bool bBuild = false;
|
|
bool bPut;
|
|
|
|
static int table_buttons[] =
|
|
{
|
|
BUTTON_GO, 0,
|
|
BUTTON_DJEEP, 0,
|
|
BUTTON_DARMURE, 0,
|
|
BUTTON_MANGE, 0,
|
|
BUTTON_BOIT, 0,
|
|
BUTTON_CARRY, 0,
|
|
BUTTON_DEPOSE, 0,
|
|
BUTTON_LABO, 0,
|
|
BUTTON_ABAT, 0,
|
|
BUTTON_ABATn, 0,
|
|
BUTTON_ROC, 0,
|
|
BUTTON_ROCn, 0,
|
|
BUTTON_CULTIVE, 0,
|
|
BUTTON_FLEUR, 0,
|
|
BUTTON_FLEURn, 0,
|
|
BUTTON_DYNAMITE, 0,
|
|
BUTTON_DRAPEAU, 0,
|
|
BUTTON_EXTRAIT, 0,
|
|
BUTTON_FABJEEP, 0,
|
|
BUTTON_FABMINE, 0,
|
|
BUTTON_FABDISC, 0,
|
|
BUTTON_FABARMURE, 0,
|
|
BUTTON_BUILD1, 36, // si planches (cabane)
|
|
BUTTON_BUILD2, 36, // si planches (nurserie)
|
|
BUTTON_BUILD4, 36, // si planches (mine)
|
|
BUTTON_PALIS, 36, // si planches
|
|
BUTTON_PONT, 36, // si planches
|
|
BUTTON_BATEAU, 36, // si planches
|
|
BUTTON_BUILD6, 36, // si planches (téléporteur)
|
|
BUTTON_BUILD3, 44, // si pierres (laboratoire)
|
|
BUTTON_BUILD5, 44, // si pierres (usine)
|
|
BUTTON_MUR, 44, // si pierres
|
|
BUTTON_TOUR, 44, // si pierres
|
|
BUTTON_STOP, 0,
|
|
-1
|
|
};
|
|
|
|
nb = 0;
|
|
perso = 0;
|
|
|
|
cel = ConvPosToCel(pos);
|
|
cel2 = ConvPosToCel2(pos);
|
|
|
|
if ( m_nbBlupiHili == 0 ) return;
|
|
|
|
if ( m_nbBlupiHili > 1 ) // sélection multiple ?
|
|
{
|
|
error = CelOkForAction(cel, table_actions[BUTTON_GO], m_rankBlupiHili);
|
|
if ( error == 0 )
|
|
{
|
|
*pB++ = BUTTON_GO;
|
|
*pE++ = 0;
|
|
nb ++;
|
|
}
|
|
|
|
for ( rank=0 ; rank<MAXBLUPI ; rank++ )
|
|
{
|
|
if ( m_blupi[rank].bExist &&
|
|
m_blupi[rank].goalAction != 0 )
|
|
{
|
|
*pB++ = BUTTON_STOP;
|
|
*pE++ = 0;
|
|
nb ++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ( m_nbBlupiHili != 1 ) return;
|
|
|
|
perso = m_blupi[m_rankBlupiHili].perso;
|
|
|
|
// Si action prioritaire en cours -> seulement stoppe.
|
|
if ( m_blupi[m_rankBlupiHili].goalAction != 0 &&
|
|
m_blupi[m_rankBlupiHili].interrupt <= 0 )
|
|
{
|
|
if ( abs(m_blupi[m_rankBlupiHili].cel.x-cel.x) <= 3 &&
|
|
abs(m_blupi[m_rankBlupiHili].cel.y-cel.y) <= 3 &&
|
|
CelOkForAction(cel, table_actions[BUTTON_STOP], m_rankBlupiHili) == 0 )
|
|
{
|
|
*pB++ = BUTTON_STOP;
|
|
*pE++ = 0;
|
|
nb ++;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Vérifie si le blupi sélectionné peut construire.
|
|
if ( m_rankBlupiHili >= 0 )
|
|
{
|
|
if ( m_blupi[m_rankBlupiHili].energy > MAXENERGY/4 &&
|
|
m_blupi[m_rankBlupiHili].takeChannel == -1 &&
|
|
m_blupi[m_rankBlupiHili].vehicule == 0 ) // à pied ?
|
|
{
|
|
bBuild = true;
|
|
}
|
|
}
|
|
|
|
// Met les différentes actions.
|
|
i = 0;
|
|
while ( table_buttons[i] != -1 )
|
|
{
|
|
button = table_buttons[i];
|
|
|
|
if ( m_buttonExist[button] == 0 ) goto next;
|
|
|
|
error = CelOkForAction(cel, table_actions[button], m_rankBlupiHili);
|
|
|
|
if ( error == 0 ) bPut = true;
|
|
else bPut = false;
|
|
|
|
if ( bBuild &&
|
|
table_buttons[i+1] != 0 && // toujours présent si matière ?
|
|
(m_rankBlupiHili < 0 ||
|
|
m_blupi[m_rankBlupiHili].perso != 8 || // pas disciple ?
|
|
table_buttons[i+1] != 44) ) // ni pierres ?
|
|
{
|
|
GetObject(cel2, channel, icon);
|
|
if ( channel == CHOBJECT &&
|
|
icon == table_buttons[i+1] && // matière ?
|
|
cel.x%2 == 1 && cel.y%2 == 1 )
|
|
{
|
|
bPut = true; // bouton présent, mais disable !
|
|
}
|
|
}
|
|
|
|
if ( bPut )
|
|
{
|
|
*pB++ = button;
|
|
*pE++ = error;
|
|
nb ++;
|
|
}
|
|
|
|
next:
|
|
i += 2;
|
|
}
|
|
|
|
// Si le premier bouton est "abat", ajoute "va" devant !
|
|
if ( pButtons[0] == BUTTON_ABAT )
|
|
{
|
|
for ( i=nb ; i>0 ; i-- )
|
|
{
|
|
pButtons[i] = pButtons[i-1];
|
|
pErrors[i] = pErrors[i-1];
|
|
}
|
|
|
|
pButtons[0] = BUTTON_GO;
|
|
pErrors[0] = ERROR_MISC;
|
|
nb ++;
|
|
}
|
|
|
|
// Regarde s'il faut ajouter le bouton "répète".
|
|
if ( m_blupi[m_rankBlupiHili].repeatLevel != -1 ||
|
|
m_blupi[m_rankBlupiHili].energy <= MAXENERGY/4 ||
|
|
m_buttonExist[BUTTON_REPEAT] == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
for ( i=0 ; i<nb ; i++ )
|
|
{
|
|
rank = ListSearch(m_rankBlupiHili, pButtons[i], cel, textForButton);
|
|
if ( rank > 0 ) // au moins 2 actions à répéter ?
|
|
{
|
|
m_blupi[m_rankBlupiHili].repeatLevelHope = rank;
|
|
|
|
pButtons[nb] = BUTTON_REPEAT;
|
|
pErrors[nb] = textForButton;
|
|
nb ++;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Initialise les conditions de fin.
|
|
|
|
void CDecor::TerminatedInit()
|
|
{
|
|
m_winCount = 50;
|
|
|
|
m_winLastHachBlupi = 0;
|
|
m_winLastHachPlanche = 0;
|
|
m_winLastHachTomate = 0;
|
|
m_winLastHachMetal = 0;
|
|
m_winLastHachRobot = 0;
|
|
m_winLastHome = 0;
|
|
m_winLastHomeBlupi = 0;
|
|
m_winLastRobots = 0;
|
|
}
|
|
|
|
// Vérifie si la partie est terminée.
|
|
// Retourne 0 si la partie n'est pas terminée.
|
|
// Retourne 1 si la partie est perdue.
|
|
// Retourne 2 si la partie est gagnée.
|
|
|
|
int CDecor::IsTerminated()
|
|
{
|
|
int nb, count, out;
|
|
POINT pos;
|
|
|
|
pos.x = LXIMAGE/2;
|
|
pos.y = LYIMAGE/2;
|
|
|
|
count = m_winCount;
|
|
m_winCount = 50;
|
|
|
|
if ( m_winLastHome > m_nbStatHome ) // une maison en moins ?
|
|
{
|
|
out = 1; // perdu
|
|
goto delay;
|
|
}
|
|
m_winLastHome = m_nbStatHome;
|
|
|
|
nb = StatisticGetBlupi();
|
|
if ( nb < m_term.nbMinBlupi )
|
|
{
|
|
out = 1; // perdu
|
|
goto delay;
|
|
}
|
|
if ( nb < m_term.nbMaxBlupi ) return 0; // continue
|
|
|
|
if ( m_term.bStopFire )
|
|
{
|
|
nb = StatisticGetFire();
|
|
if ( nb > 0 ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bHachBlupi )
|
|
{
|
|
if ( m_winLastHachBlupi < m_nbStatHachBlupi )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastHachBlupi = m_nbStatHachBlupi;
|
|
|
|
if ( m_nbStatHachBlupi < m_nbStatHach*4 ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bHachPlanche )
|
|
{
|
|
if ( m_winLastHachPlanche < m_nbStatHachPlanche )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastHachPlanche = m_nbStatHachPlanche;
|
|
|
|
if ( m_nbStatHachPlanche < m_nbStatHach ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bHachTomate )
|
|
{
|
|
if ( m_winLastHachTomate < m_nbStatHachTomate )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastHachTomate = m_nbStatHachTomate;
|
|
|
|
if ( m_nbStatHachTomate < m_nbStatHach ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bHachMetal )
|
|
{
|
|
if ( m_winLastHachMetal < m_nbStatHachMetal )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastHachMetal = m_nbStatHachMetal;
|
|
|
|
if ( m_nbStatHachMetal < m_nbStatHach ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bHachRobot )
|
|
{
|
|
if ( m_winLastRobots > m_nbStatRobots )
|
|
{
|
|
out = 1; // perdu
|
|
goto delay;
|
|
}
|
|
m_winLastRobots = m_nbStatRobots;
|
|
|
|
if ( m_winLastHachRobot < m_nbStatHachRobot )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastHachRobot = m_nbStatHachRobot;
|
|
|
|
if ( m_nbStatHachRobot < m_nbStatHach ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bHomeBlupi )
|
|
{
|
|
if ( m_winLastHomeBlupi < m_nbStatHomeBlupi )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastHomeBlupi = m_nbStatHomeBlupi;
|
|
|
|
if ( m_nbStatHomeBlupi < m_nbStatHome ) return 0; // continue;
|
|
}
|
|
|
|
if ( m_term.bKillRobots )
|
|
{
|
|
if ( m_winLastRobots > m_nbStatRobots )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
m_winLastRobots = m_nbStatRobots;
|
|
|
|
if ( m_nbStatRobots > 0 ) return 0; // continue;
|
|
}
|
|
|
|
out = 2; // gagné
|
|
|
|
delay:
|
|
m_winCount = count;
|
|
if ( m_winCount == 0 )
|
|
{
|
|
if ( out == 1 ) // perdu ?
|
|
{
|
|
if ( !m_pSound->PlayImage(SOUND_LOST, pos) )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !m_pSound->PlayImage(SOUND_WIN, pos) )
|
|
{
|
|
m_pSound->PlayImage(SOUND_BUT, pos);
|
|
}
|
|
}
|
|
|
|
return out; // perdu/gagné
|
|
}
|
|
m_winCount --;
|
|
return 0; // continue
|
|
}
|
|
|
|
// Retourne la structure pour terminer une partie.
|
|
|
|
Term* CDecor::GetTerminated()
|
|
{
|
|
return &m_term;
|
|
}
|
|
|