1
0
mirror of https://github.com/blupi-games/planetblupi synced 2024-12-30 10:15:36 +01:00
planetblupi/decblupi.cpp
Mathieu Schroeter 93047957fd Replace BOOL by bool
And replace structs that are stored from BOOL to int.
2017-01-22 00:15:32 +01:00

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;
}