Code: Select all
#RequireContext CGameCtnEditorPluginScriptHandler
#Include "MapUnits" as MapUnits
#Include "MathLib" as MathLib
Text CreateManialink()
{
declare MLText =
"""
<script><!--
Void UpdateTxtDebug() {
declare Text TxtDebug for Page;
declare TxtDebugCtrl <=> (Page.GetFirstChild("TxtDebugPlacedValue") as CGameManialinkLabel);
TxtDebugCtrl.SetText( TxtDebug );
}
Void OnPlaceBlocks()
{
declare Boolean StartPlacing for Page;
if(!StartPlacing) {
StartPlacing = True;
}
}
main ()
{
while(True) {
yield;
UpdateTxtDebug();
foreach(Event in PendingEvents) {
if(Event.Type == CGameManialinkScriptEvent::Type::MouseClick) {
if (Event.ControlId == "PlaceQuad") {
OnPlaceBlocks();
}
}
}
}
}
--></script>
<frame>
<quad id="PluginTitleQuad" posn="-138 82 1" sizen="42 13"
halign="center" valign="center" style="Bgs1InRace"
substyle="BgTitle3_1"/>
<label id="PluginTitleLabel" text="Labyz"
posn="-138 82 1" halign="center" valign="center" style="TextTitle3"/>
<quad id="PluginQuad" posn="-138 76 1" sizen="38 22"
halign="center" valign="top" style="Bgs1"
substyle="BgList" ScriptEvents="1"/>
<!-- quad id="PluginQuad" posn="-156 76 1" sizen="200 28"
halign="left" valign="top" style="Bgs1"
substyle="BgList" ScriptEvents="1"/ -->
<label id="LabySizeLabel" text="Size : 15 x 15 x 13"
posn="-138 73 1" halign="center" valign="center"
textsize="2"/>
<label id="TxtDebugPlacedValue" text="0"
posn="-150 68 2" sizen="200 5"
halign="left" valign="center" textsize="2"/>
<quad id="PlaceQuad" posn="-138 60 4" sizen="30 6"
halign="center" valign="center" style="Bgs1InRace"
substyle="BgCard" ScriptEvents="1"/>
<label id="PlaceLabel" text="CALCULER" posn="-138 60 4"
halign="center" valign="center" style="TextButtonSmall"
textsize="2"/>
</frame>
""";
return MLText;
}
Void PB(Text BlockName, Integer X, Integer Y, Integer Z, ::CardinalDirections Dir)
{
PlaceBlock(BlockModels[BlockName], <X, Y, Z>, Dir);
}
Void PlaceStart(
Integer X, Integer Z, Integer Y,
::CardinalDirections Dir,
Integer CoordYBaseSol)
{
PB("ArenaStart", 1+(X*2), CoordYBaseSol+(Y*2), 1+(Z*2), Dir);
}
Void PlaceFinish(
Integer X, Integer Z, Integer Y,
::CardinalDirections Dir,
Integer CoordYBaseSol)
{
PB("ArenaFinish", 1+(X*2), CoordYBaseSol+(Y*2), 1+(Z*2), Dir);
}
Void PlaceUp(
Integer X, Integer Z, Integer Y,
::CardinalDirections Dir,
Integer CoordYBaseSol)
{
declare Integer Xl = 1 + (X*2);
declare Integer Yl = CoordYBaseSol + (Y*2);
declare Integer Zl = 1 + (Z*2);
if (Dir == ::CardinalDirections::North) {
PB("ArenaSlopeStart", Xl, Yl, Zl+1, Dir);
PB("ArenaSlopeEnd", Xl, Yl+1, Zl+2, Dir);
}
if (Dir == ::CardinalDirections::East) {
PB("ArenaSlopeStart", Xl-1, Yl, Zl, Dir);
PB("ArenaSlopeEnd", Xl-2, Yl+1, Zl, Dir);
}
if (Dir == ::CardinalDirections::South) {
PB("ArenaSlopeStart", Xl, Yl, Zl-1, Dir);
PB("ArenaSlopeEnd", Xl, Yl+1, Zl-2, Dir);
}
if (Dir == ::CardinalDirections::West) {
PB("ArenaSlopeStart", Xl+1, Yl, Zl, Dir);
PB("ArenaSlopeEnd", Xl+2, Yl+1, Zl, Dir);
}
}
Void PlaceNESW(Integer X, Integer Y, Integer Z, Integer Val, Boolean Light)
{
declare Text TypeBloc = "ArenaSimpleBase";
if (Light) {
TypeBloc = "ArenaFloodLightBaseCeiling";
}
PB(TypeBloc, X, Y, Z, ::CardinalDirections::North);
TypeBloc = "ArenaSimpleBaseNoPillar";
declare Boolean ValBitN = ((Val / 1 ) % 2) > 0;
declare Boolean ValBitE = ((Val / 2 ) % 2) > 0;
declare Boolean ValBitS = ((Val / 4 ) % 2) > 0;
declare Boolean ValBitW = ((Val / 8 ) % 2) > 0;
if (ValBitN) {
PB(TypeBloc, X, Y, Z+1, ::CardinalDirections::North);
}
if (ValBitE) {
PB(TypeBloc, X-1, Y, Z, ::CardinalDirections::East);
}
if (ValBitS) {
PB(TypeBloc, X, Y, Z-1, ::CardinalDirections::South);
}
if (ValBitW) {
PB(TypeBloc, X+1, Y, Z, ::CardinalDirections::West);
}
}
/////////////////////////////////////
// Draw the laby
Void DrawLaby(
Integer[] Tab,
Integer XSize, Integer ZSize, Integer YSize,
Integer CoordYBaseSol)
{
declare Text TxtDebug for ManialinkPage;
declare Integer XMaxLocal = XSize-1;
declare Integer ZMaxLocal = ZSize-1;
declare Integer YMaxLocal = YSize-1;
for(Y,0,YMaxLocal) {
for(Z,0,ZMaxLocal) {
for(X,0,XMaxLocal) {
PlaceNESW(
1+(X*2), CoordYBaseSol + (Y*2), 1+(Z*2),
Tab[ X + (Z*XSize) + (Y*XSize*ZSize) ],
Y > 0);
}
}
TxtDebug = "" ^ (YMaxLocal-Y);
yield;
}
}
/////////////////////////////////////
// Vérifie si un bloc est totalement vide
Boolean EstVide( Integer X, Integer Y, Integer Z )
{
declare CGameCtnBlock B = GetBlock(<X, Y, Z>);
return (B==Null);
}
/////////////////////////////////////
// Return ValRetour if Block is of known type
Integer ValIf(
Integer X, Integer Y, Integer Z,
Integer ValRetour,
Text[] ListBlocsAcceptables)
{
declare CGameCtnBlock B = GetBlock(<X, Y, Z>);
if (B != Null) {
if ( ListBlocsAcceptables.exists(B.BlockModel.Id) ) {
return ValRetour;
}
}
return 0;
}
Void Pass_1_3( Integer CoordYBaseSol )
{
declare Text TxtDebug for ManialinkPage;
TxtDebug = "Pass 1/3";
declare Text[] BlocsOk =
[ "ArenaSimpleBase", "ArenaSimpleBaseNoPillar", "ArenaFloodLightBaseCeiling" ];
declare Text[] BlocsErr =
[ "ArenaSlopeStart", "ArenaSlopeEnd",
"RoadRaceCornerOut", "RoadRaceToArena", "RoadRaceToArenaMirror" ];
declare Text[] BlocsDirt =
[ "Dirt" ];
declare Integer X;
declare Integer Y;
declare Integer Z;
declare Integer S;
declare Integer XMax = Map.Size[0]-2;
declare Integer YMax = Map.Size[1]-2;
declare Integer ZMax = Map.Size[2]-2;
/* (!!) Supra important : yield sert à mettre à jour
* l'affichage et à prendre en compte tous les changements
* sur la map (= pose de blocs etc.) et TANT QU'ON NE FAIT
* PAS "yield", des appels tels que GetBlock(<X, Y, Z>)
* reverront du *VIDE* même si on a posé des blocs.
* => Juste avant d'utiliser intensivement la détection
* de ce qu'il y a posé afin d'embellir le circuit,
* j'appelle "yield", pour m'assurer que tout est ok :
*/
yield;
//XMax = 10;
//YMax = CoordYBaseSol+2;
//ZMax = 10;
// Coordonnées à tester via des bits activés :
//
// 1 2 4
// 8 16 32
// 64 128 256
//
// 512 = autre bloc non autorisé
Y = CoordYBaseSol;
while (Y <= YMax) {
Z = 1;
while (Z <= ZMax) {
X = 1;
while (X <= XMax) {
S =
ValIf( X+1, Y, Z+1, 1, BlocsOk) + ValIf( X , Y, Z+1, 2, BlocsOk) + ValIf( X-1, Y, Z+1, 4, BlocsOk) +
ValIf( X+1, Y, Z , 8, BlocsOk) + ValIf( X , Y, Z , 16, BlocsOk) + ValIf( X-1, Y, Z , 32, BlocsOk) +
ValIf( X+1, Y, Z-1, 64, BlocsOk) + ValIf( X , Y, Z-1, 128, BlocsOk) + ValIf( X-1, Y, Z-1, 256, BlocsOk) +
// (!) Astuce : on ajoute un bit qui fait qu'on ne
// pourra jamais rien poser car le chiffre sera trop
// élevé, s'il y a des blocs qu'on ne veut pas qui
// soient présents :
ValIf( X+1, Y , Z+1, 512, BlocsErr) + ValIf( X , Y, Z+1, 1024, BlocsErr) + ValIf( X-1, Y, Z+1, 2048, BlocsErr) +
ValIf( X+1, Y , Z , 4096, BlocsErr) + ValIf( X-1, Y, Z , 8192, BlocsErr) +
ValIf( X+1, Y , Z-1, 16384, BlocsErr) + ValIf( X , Y, Z-1, 32768, BlocsErr) + ValIf( X-1, Y, Z-1, 65536, BlocsErr) +
ValIf( X , Y+1, Z , 131072, BlocsErr);
if ((S==18) && ((X!=1) || (Y>CoordYBaseSol) || (Z!=1))) {
//
// 18 = Ces blocs :
//
// --- 2 ---
// --- 16 ---
// --- --- ---
//
PB("ArenaSimpleBase", X, Y+1, Z, ::CardinalDirections::North);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
if (S==144) {
//
// 144 = Ces blocs :
//
// --- --- ---
// --- 16 ---
// --- 128 ---
//
PB("ArenaSimpleBase", X, Y+1, Z, ::CardinalDirections::North);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
if ((S==24) && ((X!=1) || (Y>CoordYBaseSol) || (Z!=1))) {
//
// 24 = Ces blocs :
//
// --- --- ---
// 8 16 ---
// --- --- ---
//
PB("ArenaSimpleBase", X, Y+1, Z, ::CardinalDirections::North);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
if (S==48) {
//
// 48 = Ces blocs :
//
// --- --- ---
// --- 16 32
// --- --- ---
//
PB("ArenaSimpleBase", X, Y+1, Z, ::CardinalDirections::North);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
X += 1;
}
Z += 1;
}
yield;
Y += 2;
}
}
Void Pass_2_3( Integer CoordYBaseSol )
{
declare Text TxtDebug for ManialinkPage;
TxtDebug = "Pass 2/3";
declare Text[] BlocsOk =
[ "ArenaSimpleBase", "ArenaSimpleBaseNoPillar", "ArenaFloodLightBaseCeiling" ];
declare Text[] BlocsErr =
[ "ArenaSlopeStart", "ArenaSlopeEnd",
"RoadRaceCornerOut", "RoadRaceToArena", "RoadRaceToArenaMirror" ];
declare Text[] BlocsDirt =
[ "Dirt" ];
declare Integer X;
declare Integer Y;
declare Integer Z;
declare Integer S;
declare Integer XMax = Map.Size[0]-2;
declare Integer YMax = Map.Size[1]-2;
declare Integer ZMax = Map.Size[2]-2;
/* (!!) Supra important : voir commentaire sur yield dans Pass_1_3() */
yield;
//XMax = 10;
//YMax = CoordYBaseSol+2;
//ZMax = 10;
// Coordonnées à tester via des bits activés :
//
// 1 2 4
// 8 16 32
// 64 128 256
//
// 512 = autre bloc non autorisé
Y = CoordYBaseSol;
while (Y <= YMax) {
Z = 1;
while (Z <= ZMax) {
X = 1;
while (X <= XMax) {
S =
ValIf( X+1, Y, Z+1, 1, BlocsOk) + ValIf( X , Y, Z+1, 2, BlocsOk) + ValIf( X-1, Y, Z+1, 4, BlocsOk) +
ValIf( X+1, Y, Z , 8, BlocsOk) + ValIf( X , Y, Z , 16, BlocsOk) + ValIf( X-1, Y, Z , 32, BlocsOk) +
ValIf( X+1, Y, Z-1, 64, BlocsOk) + ValIf( X , Y, Z-1, 128, BlocsOk) + ValIf( X-1, Y, Z-1, 256, BlocsOk) +
// (!) Astuce : on ajoute un bit qui fait qu'on ne
// pourra jamais rien poser car le chiffre sera trop
// élevé, s'il y a des blocs qu'on ne veut pas qui
// soient présents :
ValIf( X+1, Y , Z+1, 512, BlocsErr) + ValIf( X , Y, Z+1, 1024, BlocsErr) + ValIf( X-1, Y, Z+1, 2048, BlocsErr) +
ValIf( X+1, Y , Z , 4096, BlocsErr) + ValIf( X-1, Y, Z , 8192, BlocsErr) +
ValIf( X+1, Y , Z-1, 16384, BlocsErr) + ValIf( X , Y, Z-1, 32768, BlocsErr) + ValIf( X-1, Y, Z-1, 65536, BlocsErr) +
ValIf( X , Y+1, Z , 131072, BlocsErr);
if (S==50) {
//
// 50 = Ces blocs :
//
// --- 2 ---
// --- 16 32
// --- --- ---
//
// Blocks pour le nord :
RemoveBlock(<X, Y+1, Z+1>);
RemoveBlock(<X, Y , Z+1>);
// Blocks pour l'est :
RemoveBlock(<X-1, Y+1, Z>);
RemoveBlock(<X-1, Y , Z>);
PB("RoadRaceCornerOut", X, Y+1, Z, ::CardinalDirections::North);
PB("RoadRaceToArenaMirror", X, Y, Z+1, ::CardinalDirections::South);
PB("RoadRaceToArena", X-1, Y, Z, ::CardinalDirections::West);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
if (S==26) {
//
// 26 = Ces blocs :
//
// --- 2 ---
// 8 16 ---
// --- --- ---
//
// Blocks pour le nord :
RemoveBlock(<X, Y+1, Z+1>);
RemoveBlock(<X, Y , Z+1>);
// Blocks pour l'ouest :
RemoveBlock(<X+1, Y+1, Z>);
RemoveBlock(<X+1, Y , Z>);
PB("RoadRaceCornerOut", X, Y+1, Z, ::CardinalDirections::West);
PB("RoadRaceToArena", X, Y, Z+1, ::CardinalDirections::South);
PB("RoadRaceToArenaMirror", X+1, Y, Z, ::CardinalDirections::East);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
if (S==152) {
//
// 152 = Ces blocs :
//
// --- --- ---
// 8 16 ---
// --- 128 ---
//
// Blocks pour le sud :
RemoveBlock(<X, Y+1, Z-1>);
RemoveBlock(<X, Y , Z-1>);
// Blocks pour l'ouest :
RemoveBlock(<X+1, Y+1, Z>);
RemoveBlock(<X+1, Y , Z>);
PB("RoadRaceCornerOut", X, Y+1, Z, ::CardinalDirections::South);
PB("RoadRaceToArena", X+1, Y, Z, ::CardinalDirections::East);
PB("RoadRaceToArenaMirror", X, Y, Z-1, ::CardinalDirections::North);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
if (S==176) {
//
// 176 = Ces blocs :
//
// --- --- ---
// --- 16 32
// --- 128 ---
//
// Blocks pour le sud :
RemoveBlock(<X, Y+1, Z-1>);
RemoveBlock(<X, Y , Z-1>);
// Blocks pour l'est :
RemoveBlock(<X-1, Y+1, Z>);
RemoveBlock(<X-1, Y , Z>);
RemoveBlock(<X, Y+1 , Z>);
PB("RoadRaceCornerOut", X, Y+1, Z, ::CardinalDirections::East);
PB("RoadRaceToArenaMirror", X-1, Y, Z, ::CardinalDirections::West);
PB("RoadRaceToArena", X, Y, Z-1, ::CardinalDirections::North);
/* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
X += 1;
}
Z += 1;
}
yield;
Y += 2;
}
}
Void Pass_3_3( Integer CoordYBaseSol )
{
declare Text TxtDebug for ManialinkPage;
TxtDebug = "Pass 3/3";
declare Text[] BlocsOk =
[ "ArenaSimpleBase", "ArenaSimpleBaseNoPillar", "ArenaFloodLightBaseCeiling" ];
declare Text[] BlocsToArena =
[ "RoadRaceToArena", "RoadRaceToArenaMirror" ];
declare Integer X;
declare Integer Y;
declare Integer Z;
declare Integer S;
declare Integer XMax = Map.Size[0]-2;
declare Integer YMax = Map.Size[1]-2;
declare Integer ZMax = Map.Size[2]-2;
/* (!!) Supra important : voir commentaire sur yield dans Pass_1_3() */
yield;
//XMax = 3;
YMax = CoordYBaseSol+2;
//ZMax = 3;
// Coordonnées à tester via des bits activés :
//
// 1 2 4
// 8 16 32
// 64 128 256
//
// 512 = autre bloc non autorisé
Y = CoordYBaseSol+2;
while (Y <= YMax) {
Z = 1;
while (Z <= ZMax) {
X = 1;
while (X <= XMax) {
if ( (ValIf( X-1, Y, Z, 1, BlocsToArena)==1) &&
(ValIf( X, Y, Z, 1, BlocsOk)==1) &&
(ValIf( X, Y, Z-1, 1, BlocsOk)==1) &&
EstVide( X+1, Y, Z) &&
EstVide( X, Y, Z+1) ) {
// Retirer BlocsToArena
RemoveBlock(<X-1, Y+1, Z>);
//// Blocks pour BlocsToArena :
RemoveBlock(<X, Y+1, Z-1>);
RemoveBlock(<X, Y , Z-1>);
PB("RoadRaceStraight", X-1, Y+1, Z, ::CardinalDirections::North);
PB("RoadRaceCornerIn", X, Y+1, Z, ::CardinalDirections::North);
PB("RoadRaceToArenaMirror", X, Y, Z-1, ::CardinalDirections::North);
///* (!) Voir gros commentaire sur yield juste avant cette boucle : */
yield;
}
X += 1;
}
Z += 1;
yield;
}
Y += 2;
}
declare CGameCtnBlock B;
B = GetBlock(<2, CoordYBaseSol+3, 3>);
if (B != Null) {
log(B.BlockModel.Id);
}
}
/////////////////////////////////////
// Place all blocks
Void PlaceBlocks()
{
declare Text TxtDebug for ManialinkPage;
declare CBlockModel BMArenaSimpleBase;
BMArenaSimpleBase <=> BlockModels["ArenaSimpleBase"];
RemoveAllBlocksAndTerrain();
ComputeShadows();
yield;
// Calculer la hauteur du sol = la hauteur minimale pour
// poser le bloc :
declare CoordYBaseSol = GetBlockGroundHeight(
BMArenaSimpleBase, 19, 19, ::CardinalDirections::East);
PB("ArenaStart", 1, CoordYBaseSol, 0, ::CardinalDirections::North);
PB("ArenaFinish", 0, CoordYBaseSol+6, 11, ::CardinalDirections::East);
// Up <=> Down slopes :
PlaceUp( 2, 1, 0, ::CardinalDirections::West, CoordYBaseSol);
PlaceUp( 1, 2, 0, ::CardinalDirections::West, CoordYBaseSol);
PlaceUp( 3, 3, 0, ::CardinalDirections::West, CoordYBaseSol);
PlaceUp( 4, 4, 0, ::CardinalDirections::East, CoordYBaseSol);
PlaceUp( 2, 3, 1, ::CardinalDirections::North, CoordYBaseSol);
PlaceUp( 1, 4, 1, ::CardinalDirections::South, CoordYBaseSol);
PlaceUp( 3, 1, 2, ::CardinalDirections::East, CoordYBaseSol);
PlaceUp( 4, 1, 2, ::CardinalDirections::North, CoordYBaseSol);
PlaceUp( 1, 2, 2, ::CardinalDirections::North, CoordYBaseSol);
PlaceUp( 4, 4, 2, ::CardinalDirections::East, CoordYBaseSol);
DrawLaby(
[
// Etage 0
1, 9, 10, 11, 2, 1,
5, 13, 3, 12, 2, 5,
13, 6, 5, 8, 10, 7,
4, 8, 15, 3, 1, 5,
9, 10, 6, 4, 13, 7,
12, 10, 2, 8, 6, 4,
// Etage 1
9, 10, 11, 2, 9, 3,
4, 9, 6, 8, 7, 4,
8, 7, 0, 9, 14, 2,
8, 14, 10, 6, 8, 3,
9, 11, 11, 2, 9, 6,
4, 4, 12, 10, 14, 2,
// Etage 2
8, 11, 10, 10, 3, 1,
8, 14, 2, 9, 14, 6,
9, 2, 9, 6, 9, 3,
5, 0, 12, 3, 5, 4,
13, 3, 1, 5, 13, 3,
4, 12, 14, 14, 6, 4,
// Etage 3
9, 10, 10, 2, 9, 3,
12, 11, 2, 9, 6, 4,
9, 14, 10, 7, 0, 1,
5, 0, 1, 12, 11, 7,
13, 10, 6, 0, 4, 5,
4, 8, 10, 10, 10, 6
],
6,6,4,
CoordYBaseSol
);
Pass_1_3( CoordYBaseSol );
Pass_2_3( CoordYBaseSol );
Pass_3_3( CoordYBaseSol );
log( "Done !");
TxtDebug = "Done !";
}
/////////////////////////////////////
// Main
main()
{
declare Integer NbBlocks for ManialinkPage;
declare Boolean StartPlacing for ManialinkPage;
ManialinkText = CreateManialink();
while(True) {
yield;
if(StartPlacing) {
PlaceBlocks();
StartPlacing = False;
}
}
}
/////////////////////////////////////