quantumde1 14 ساعت پیش
والد
کامیت
a7c4029a05
7فایلهای تغییر یافته به همراه233 افزوده شده و 312 حذف شده
  1. 170 248
      source/dialogs/dialogbox.d
  2. 2 2
      source/graphics/engine.d
  3. 4 5
      source/graphics/gamelogic.d
  4. 44 49
      source/scripts/lua.d
  5. 7 4
      source/system/cleanup.d
  6. 2 0
      source/ui/menu.d
  7. 4 4
      source/variables.d

+ 170 - 248
source/dialogs/dialogbox.d

@@ -9,341 +9,263 @@ import std.typecons;
 import std.algorithm;
 import variables;
 
+// Dialog state variables
 int currentPage = 0;
 float textDisplayProgress = 0.0f;
 bool textFullyDisplayed = false;
 
 // Texture variables
-bool texturesLoaded = false;
 float circleRotationAngle = 0.0f;
 
 // Border sizes for 9-slice scaling
-const int DIALOG_BORDER = 32; // Border size that won't be stretched
-const int CHOICE_BORDER = 32;  // Border size for choice window
+const int DIALOG_BORDER = 32; // Border that won't be stretched
+const int CHOICE_BORDER = 32; // Choice window border
 
+// Draws a texture with 9-slice scaling
 void draw9SliceTexture(Texture2D tex, Rectangle dest, int borderSize, Color tint) {
-    // Source rectangle is the whole texture
     Rectangle src = Rectangle(0, 0, tex.width, tex.height);
     
-    // Prevent division by zero
-    if (borderSize <= 0) borderSize = 1;
-    if (borderSize * 2 >= src.width) borderSize = cast(int)src.width / 3;
-    if (borderSize * 2 >= src.height) borderSize = cast(int)src.height / 3;
+    // Prevent invalid border sizes
+    borderSize = max(1, min(borderSize, tex.width/3, tex.height/3));
     
-    // Calculate inner source rectangle (without borders)
     Rectangle innerSrc = Rectangle(
-        borderSize, 
-        borderSize, 
-        src.width - borderSize * 2, 
-        src.height - borderSize * 2
+        borderSize, borderSize, 
+        src.width - borderSize*2, src.height - borderSize*2
     );
     
-    // Calculate inner destination rectangle
     Rectangle innerDest = Rectangle(
-        dest.x + borderSize, 
-        dest.y + borderSize, 
-        dest.width - borderSize * 2, 
-        dest.height - borderSize * 2
+        dest.x + borderSize, dest.y + borderSize,
+        dest.width - borderSize*2, dest.height - borderSize*2
     );
     
-    // Draw 9 parts:
-    // 1. Top-left corner
-    DrawTexturePro(tex, 
-        Rectangle(src.x, src.y, borderSize, borderSize),
-        Rectangle(dest.x, dest.y, borderSize, borderSize),
-        Vector2(0, 0), 0, tint);
-    
-    // 2. Top edge
-    DrawTexturePro(tex, 
-        Rectangle(src.x + borderSize, src.y, innerSrc.width, borderSize),
-        Rectangle(dest.x + borderSize, dest.y, innerDest.width, borderSize),
-        Vector2(0, 0), 0, tint);
-    
-    // 3. Top-right corner
-    DrawTexturePro(tex, 
-        Rectangle(src.x + src.width - borderSize, src.y, borderSize, borderSize),
-        Rectangle(dest.x + dest.width - borderSize, dest.y, borderSize, borderSize),
-        Vector2(0, 0), 0, tint);
-    
-    // 4. Left edge
-    DrawTexturePro(tex, 
-        Rectangle(src.x, src.y + borderSize, borderSize, innerSrc.height),
-        Rectangle(dest.x, dest.y + borderSize, borderSize, innerDest.height),
-        Vector2(0, 0), 0, tint);
-    
-    // 5. Center (stretched)
-    DrawTexturePro(tex, 
-        innerSrc,
-        innerDest,
-        Vector2(0, 0), 0, tint);
-    
-    // 6. Right edge
-    DrawTexturePro(tex, 
-        Rectangle(src.x + src.width - borderSize, src.y + borderSize, borderSize, innerSrc.height),
-        Rectangle(dest.x + dest.width - borderSize, dest.y + borderSize, borderSize, innerDest.height),
-        Vector2(0, 0), 0, tint);
+    // Draw all 9 parts
+    void drawPart(Rectangle s, Rectangle d) {
+        DrawTexturePro(tex, s, d, Vector2(0, 0), 0, tint);
+    }
     
-    // 7. Bottom-left corner
-    DrawTexturePro(tex, 
-        Rectangle(src.x, src.y + src.height - borderSize, borderSize, borderSize),
-        Rectangle(dest.x, dest.y + dest.height - borderSize, borderSize, borderSize),
-        Vector2(0, 0), 0, tint);
+    // Corners
+    drawPart(Rectangle(src.x, src.y, borderSize, borderSize),
+             Rectangle(dest.x, dest.y, borderSize, borderSize));
+    drawPart(Rectangle(src.x + src.width - borderSize, src.y, borderSize, borderSize),
+             Rectangle(dest.x + dest.width - borderSize, dest.y, borderSize, borderSize));
+    drawPart(Rectangle(src.x, src.y + src.height - borderSize, borderSize, borderSize),
+             Rectangle(dest.x, dest.y + dest.height - borderSize, borderSize, borderSize));
+    drawPart(Rectangle(src.x + src.width - borderSize, src.y + src.height - borderSize, borderSize, borderSize),
+             Rectangle(dest.x + dest.width - borderSize, dest.y + dest.height - borderSize, borderSize, borderSize));
     
-    // 8. Bottom edge
-    DrawTexturePro(tex, 
-        Rectangle(src.x + borderSize, src.y + src.height - borderSize, innerSrc.width, borderSize),
-        Rectangle(dest.x + borderSize, dest.y + dest.height - borderSize, innerDest.width, borderSize),
-        Vector2(0, 0), 0, tint);
+    // Edges
+    drawPart(Rectangle(src.x + borderSize, src.y, innerSrc.width, borderSize),
+             Rectangle(dest.x + borderSize, dest.y, innerDest.width, borderSize));
+    drawPart(Rectangle(src.x, src.y + borderSize, borderSize, innerSrc.height),
+             Rectangle(dest.x, dest.y + borderSize, borderSize, innerDest.height));
+    drawPart(Rectangle(src.x + src.width - borderSize, src.y + borderSize, borderSize, innerSrc.height),
+             Rectangle(dest.x + dest.width - borderSize, dest.y + borderSize, borderSize, innerDest.height));
+    drawPart(Rectangle(src.x + borderSize, src.y + src.height - borderSize, innerSrc.width, borderSize),
+             Rectangle(dest.x + borderSize, dest.y + dest.height - borderSize, innerDest.width, borderSize));
     
-    // 9. Bottom-right corner
-    DrawTexturePro(tex, 
-        Rectangle(src.x + src.width - borderSize, src.y + src.height - borderSize, borderSize, borderSize),
-        Rectangle(dest.x + dest.width - borderSize, dest.y + dest.height - borderSize, borderSize, borderSize),
-        Vector2(0, 0), 0, tint);
+    // Center
+    drawPart(innerSrc, innerDest);
 }
 
-void displayDialog(string[] pages, string[] choices, ref int selectedChoice, int choicePage, Font dialogFont, 
-bool *showDialog, ref float textSpeed, Color dialogColor, 
-Texture2D circle, Texture2D dialogBackgroundTex, Texture2D choiceWindowTex) {
-
-    int pagesLength = cast(int)pages.length;
-    int screenWidth = GetScreenWidth();
-    int screenHeight = GetScreenHeight();
+// Main dialog display function
+void displayDialog(string[] pages, string[] choices, ref int selectedChoice, 
+                   int choicePage, Font dialogFont, bool* showDialog, 
+                   ref float textSpeed, Texture2D circle, 
+                   Texture2D dialogBackgroundTex, Texture2D choiceWindowTex) {
     
-    const int screenPadding = 10;
+    const screenWidth = GetScreenWidth();
+    const screenHeight = GetScreenHeight();
+    const screenPadding = 10;
     
-    // Dialog background rectangle с отступами
+    // Dialog background rectangle with padding
     Rectangle dialogRect = Rectangle(
-        screenPadding, // X с отступом
-        screenHeight - screenHeight / 3 - screenPadding, // Y с отступом
-        screenWidth - 2 * screenPadding, // Ширина с учетом отступов
-        screenHeight / 3 // Высота (без изменения)
-    );
-    
-    // Draw dialog background with 9-slice scaling
-    draw9SliceTexture(
-        dialogBackgroundTex,
-        dialogRect,
-        DIALOG_BORDER,
-        Color(255, 255, 255, 220) // Slightly transparent
+        screenPadding,
+        screenHeight - screenHeight/3 - screenPadding,
+        screenWidth - 2*screenPadding,
+        screenHeight/3
     );
+    // Draw dialog background
+    draw9SliceTexture(dialogBackgroundTex, dialogRect, DIALOG_BORDER, Colors.WHITE);
     
+    // Text layout parameters
     const float textLeftMargin = 33.0f;
     const float textTopMargin = 20.0f;
+    const float textRightMargin = 33.0f;
+    const float textWidth = dialogRect.width - textLeftMargin - textRightMargin;
+    const float fontSize = 40.0f;
+    const float spacing = 1.0f;
+    string name;
     
-    float marginLeft = dialogRect.x + textLeftMargin; // Отступ от левого края фона
-    float marginRight = screenWidth/6.5f;
-    float marginTop = dialogRect.y + textTopMargin; // Отступ от верхнего края фона
-    float textWidth = dialogRect.width - textLeftMargin - marginRight;
-    float fontSize = 40.0f;
-    float spacing = 1.0f;
-    
+    // Text display logic
     string currentText = pages[currentPage];
-    int textLength = cast(int)currentText.length;
-    
-    if (IsKeyPressed(KeyboardKey.KEY_ENTER) && !textFullyDisplayed) {
-        textDisplayProgress = textLength;
-        textFullyDisplayed = true;
-    }
-    else if (IsKeyPressed(KeyboardKey.KEY_ENTER) && textFullyDisplayed) {
-        currentPage += 1;
-        textDisplayProgress = 0.0f;
-        textFullyDisplayed = false;
+    string displayText = currentText;
+
+    if (currentText[0] == '[') {
+        
+        size_t start = currentText.indexOf('[') + 1;
+        size_t end = currentText.lastIndexOf(']');
+        name = currentText[start..end];
+        
+        size_t nameStart = currentText.indexOf('[');
+        size_t nameEnd = currentText.lastIndexOf(']') + 1;
+        displayText = currentText[0..nameStart] ~ currentText[nameEnd..$];
+        Rectangle nameRect = Rectangle(
+            screenPadding,
+            dialogRect.y - screenHeight/12,
+            screenWidth / 12 + MeasureTextEx(dialogFont, name.toStringz(), fontSize, spacing).x,
+            screenHeight / 12
+        );
+        draw9SliceTexture(choiceWindowTex, nameRect, DIALOG_BORDER, Colors.WHITE);
+        Vector2 nameSize = MeasureTextEx(dialogFont, name.toStringz(), fontSize, spacing);
+        
+        Vector2 namePos = Vector2(
+            nameRect.x + (nameRect.width - nameSize.x) / 2,
+            nameRect.y + (nameRect.height - nameSize.y) / 2
+        );
+        
+        DrawTextEx(dialogFont, name.toStringz(), namePos + Vector2(2, 2), fontSize, spacing, Colors.BLACK);
+        DrawTextEx(dialogFont, name.toStringz(), namePos, fontSize, spacing, Colors.WHITE);
     }
-    else if (!textFullyDisplayed) {
-        textDisplayProgress += textSpeed;
-        if (textDisplayProgress >= textLength) {
-            textDisplayProgress = textLength;
+
+    if (IsKeyPressed(KeyboardKey.KEY_ENTER)) {
+        if (!textFullyDisplayed) {
+            textDisplayProgress = displayText.length;
             textFullyDisplayed = true;
+        } else {
+            currentPage++;
+            textDisplayProgress = 0.0f;
+            textFullyDisplayed = false;
         }
+    } else if (!textFullyDisplayed) {
+        textDisplayProgress = min(textDisplayProgress + textSpeed, cast(float)displayText.length);
+        textFullyDisplayed = textDisplayProgress >= displayText.length;
     }
     
-    int charsToShow = cast(int)textDisplayProgress;
-    string displayedText = currentText[0 .. min(charsToShow, textLength)];
-    
+    // Split text into lines that fit the dialog width
     string[] lines;
-    string remainingText = displayedText;
+    string remaining = displayText[0..min(cast(int)textDisplayProgress, displayText.length)];
     
-    while (remainingText.length > 0) {
+    while (!remaining.empty) {
         int fitChars = 0;
-        float width = 0.0f;
+        float lineWidth = 0.0f;
         
-        while (fitChars < remainingText.length) {
-            int nextChar = fitChars;
-            while (nextChar < remainingText.length && !isWhite(remainingText[nextChar])) {
-                nextChar++;
-            }
+        while (fitChars < remaining.length) {
+            int wordEnd = fitChars;
+            while (wordEnd < remaining.length && !remaining[wordEnd].isWhite) wordEnd++;
             
-            string word = remainingText[fitChars..nextChar];
+            string word = remaining[fitChars..wordEnd];
             float wordWidth = MeasureTextEx(dialogFont, word.toStringz(), fontSize, spacing).x;
             
-            if (width + wordWidth > textWidth && width > 0) {
-                break;
-            }
+            if (lineWidth > 0 && lineWidth + wordWidth > textWidth) break;
             
-            width += wordWidth;
-            fitChars = nextChar;
+            lineWidth += wordWidth;
+            fitChars = wordEnd;
             
-            while (fitChars < remainingText.length && isWhite(remainingText[fitChars])) {
-                width += MeasureTextEx(dialogFont, " ".toStringz(), fontSize, spacing).x;
+            // Add whitespace
+            while (fitChars < remaining.length && remaining[fitChars].isWhite) {
+                lineWidth += MeasureTextEx(dialogFont, " ".toStringz(), fontSize, spacing).x;
                 fitChars++;
             }
         }
         
-        if (fitChars == 0) {
-            fitChars = 1;
-        }
-        
-        lines ~= remainingText[0..fitChars];
-        remainingText = remainingText[fitChars..$];
+        if (fitChars == 0) fitChars = 1;
+        lines ~= remaining[0..fitChars];
+        remaining = remaining[fitChars..$];
     }
     
-    float lineHeight = MeasureTextEx(dialogFont, "A", fontSize, spacing).y * 1.4;
-    for (int i = 0; i < lines.length; i++) {
-        DrawTextEx(
-            dialogFont,
-            lines[i].toStringz(),
-            Vector2(marginLeft+3, 3+(marginTop + i * lineHeight)),
-            fontSize,
-            spacing,
-            Colors.BLACK
-        );
-        DrawTextEx(
-            dialogFont,
-            lines[i].toStringz(),
-            Vector2(marginLeft, marginTop + i * lineHeight),
-            fontSize,
-            spacing,
-            Colors.WHITE
-        );
+    // Draw text lines with shadow effect
+    const float lineHeight = MeasureTextEx(dialogFont, "A", fontSize, spacing).y * 1.4;
+    foreach(i, line; lines) {
+        Vector2 pos = Vector2(dialogRect.x + textLeftMargin, dialogRect.y + textTopMargin + i*lineHeight);
+        DrawTextEx(dialogFont, line.toStringz(), pos + Vector2(3, 3), fontSize, spacing, Colors.BLACK);
+        DrawTextEx(dialogFont, line.toStringz(), pos, fontSize, spacing, Colors.WHITE);
     }
     
-    if (textFullyDisplayed && lines.length > 0) {
-        // Обновляем угол вращения (например, 45 градусов в секунду)
-        circleRotationAngle += 45.0f * GetFrameTime();
-        if (circleRotationAngle >= 360.0f) {
-            circleRotationAngle -= 360.0f;
-        }
-
-        // Получаем позицию и размер последней строки текста
-        float lastLineWidth = 10 + MeasureTextEx(dialogFont, lines[$-1].toStringz(), fontSize, spacing).x;
-        float lastLineY = marginTop + 20 + (lines.length - 1) * lineHeight;
-        
-        // Позиция круга справа от последней строки
-        float circleX = marginLeft + lastLineWidth + 10; // 10 - отступ от текста
-        float circleY = lastLineY;
+    // Draw continue indicator when text is fully displayed
+    if (textFullyDisplayed && !lines.empty) {
+        circleRotationAngle = (circleRotationAngle + 45*GetFrameTime()) % 360;
         
-        // Размер круга (можете настроить)
-        float circleSize = 30.0f;
+        float lastLineWidth = MeasureTextEx(dialogFont, lines[$-1].toStringz(), fontSize, spacing).x;
+        Vector2 circlePos = Vector2(
+            dialogRect.x + textLeftMargin + lastLineWidth + 20,
+            dialogRect.y + textTopMargin + (lines.length-1)*lineHeight
+        );
         
-        Rectangle destRect = Rectangle(circleX, circleY, circleSize, circleSize);
-        Rectangle sourceRect = Rectangle(0, 0, circle.width, circle.height);
-        Vector2 origin = Vector2(circleSize/2, circleSize/2);
         DrawTexturePro(
             circle,
-            sourceRect,
-            destRect,
-            origin,
+            Rectangle(0, 0, circle.width, circle.height),
+            Rectangle(circlePos.x, circlePos.y+20, 30, 30),
+            Vector2(15, 15),
             circleRotationAngle,
             Colors.WHITE
         );
     }
     
-   if (currentPage == choicePage) {
-        int verticalPadding = 30;
-        int choiceHeight = 50;
-        int choiceSpacing = 10;
-
-        int choiceWindowWidth = screenWidth / 2;
-        int choiceWindowHeight = cast(int)(verticalPadding * 2 + choices.length * choiceHeight + (choices.length - 1) * choiceSpacing);
-
-        int choiceWindowX = (screenWidth - choiceWindowWidth) / 2;
-        int choiceWindowY = (screenHeight - choiceWindowHeight) / 2;
-
-        // Draw choice window with 9-slice scaling
-        draw9SliceTexture(
-            choiceWindowTex,
-            Rectangle(choiceWindowX, choiceWindowY, choiceWindowWidth, choiceWindowHeight),
-            CHOICE_BORDER,
-            Colors.WHITE
+    // Choice selection logic
+    if (currentPage == choicePage) {
+        const choiceHeight = 50;
+        const choiceSpacing = 10;
+        const verticalPadding = 30;
+        
+        Rectangle choiceWindow = Rectangle(
+            (screenWidth - screenWidth/2)/2,
+            (screenHeight - (verticalPadding*2 + choices.length*(choiceHeight + choiceSpacing)))/2,
+            screenWidth/2,
+            verticalPadding*2 + choices.length*(choiceHeight + choiceSpacing)
         );
-
+        
+        draw9SliceTexture(choiceWindowTex, choiceWindow, CHOICE_BORDER, Colors.WHITE);
+        
         Vector2 mousePos = GetMousePosition();
         bool mouseClicked = IsMouseButtonPressed(MouseButton.MOUSE_BUTTON_LEFT);
         
-        for (int i = 0; i < choices.length; i++) {
+        foreach(i, choice; choices) {
             Rectangle choiceRect = Rectangle(
-                choiceWindowX + 40,
-                choiceWindowY + verticalPadding + i * (choiceHeight + choiceSpacing),
-                choiceWindowWidth - 80,
+                choiceWindow.x + 40,
+                choiceWindow.y + verticalPadding + i*(choiceHeight + choiceSpacing),
+                choiceWindow.width - 80,
                 choiceHeight
             );
             
-            bool isHovered = CheckCollisionPointRec(mousePos, choiceRect);
+            bool hovered = CheckCollisionPointRec(mousePos, choiceRect);
+            if (hovered) selectedChoice = cast(int)i;
             
-            if (isHovered) {
-                selectedChoice = i;
-                if (mouseClicked) {
-                    currentPage += 1;
-                    textDisplayProgress = 0.0f;
-                    textFullyDisplayed = false;
-                }
-            }
-            
-            Color color = (i == selectedChoice) ? Colors.YELLOW : (isHovered ? Colors.LIGHTGRAY : Colors.WHITE);
-            
-            if (isHovered || i == selectedChoice) {
+            if (hovered || i == selectedChoice) {
                 DrawRectangleRec(choiceRect, Color(60, 60, 60, 200));
             }
             
-            Vector2 textSize = MeasureTextEx(dialogFont, choices[i].toStringz(), 39, spacing);
+            Vector2 textSize = MeasureTextEx(dialogFont, choice.toStringz(), 39, spacing);
             Vector2 textPos = Vector2(
-                choiceRect.x + (choiceRect.width - textSize.x) / 2,
-                choiceRect.y + (choiceRect.height - textSize.y) / 2
-            );
-            DrawTextEx(
-                dialogFont,
-                choices[i].toStringz(),
-                Vector2(textPos.x+3, textPos.y+3),
-                39,
-                spacing,
-                Colors.BLACK
+                choiceRect.x + (choiceRect.width - textSize.x)/2,
+                choiceRect.y + (choiceRect.height - textSize.y)/2
             );
             
-            DrawTextEx(
-                dialogFont,
-                choices[i].toStringz(),
-                textPos,
-                39,
-                spacing,
-                color
-            );
-        }
-        
-        if (IsKeyPressed(KeyboardKey.KEY_DOWN)) {
-            selectedChoice = cast(int)((selectedChoice + 1) % choices.length);
-        }
-        if (IsKeyPressed(KeyboardKey.KEY_UP)) {
-            selectedChoice = cast(int)((selectedChoice - 1 + choices.length) % choices.length);
-        }
-        if (IsMouseButtonPressed(MouseButton.MOUSE_BUTTON_LEFT)) {
-            currentPage += 1;
-            textDisplayProgress = 0.0f;
-            textFullyDisplayed = false;
+            DrawTextEx(dialogFont, choice.toStringz(), textPos + Vector2(3, 3), 39, spacing, Colors.BLACK);
+            DrawTextEx(dialogFont, choice.toStringz(), textPos, 39, spacing, 
+                      (i == selectedChoice) ? Colors.YELLOW : (hovered ? Colors.LIGHTGRAY : Colors.WHITE));
+            
+            if (hovered && mouseClicked) {
+                currentPage++;
+                textDisplayProgress = 0.0f;
+                textFullyDisplayed = false;
+            }
         }
+        // Keyboard navigation
+        if (IsKeyPressed(KeyboardKey.KEY_DOWN)) selectedChoice = cast(int)((selectedChoice + 1) % choices.length);
+        if (IsKeyPressed(KeyboardKey.KEY_UP)) selectedChoice = cast(int)((selectedChoice - 1 + choices.length) % choices.length);
     }
     
+    // Fast-forward with Ctrl
     if ((IsKeyDown(KeyboardKey.KEY_LEFT_CONTROL) || IsKeyDown(KeyboardKey.KEY_RIGHT_CONTROL)) 
-    && currentPage != choicePage && currentPage < pages.length) {
-        currentPage += 1;
+        && currentPage != choicePage && currentPage < pages.length) {
+        currentPage++;
     }
-    if (currentPage >= pagesLength) {
+    
+    // Close dialog when all pages are shown
+    if (currentPage >= pages.length) {
         currentPage = 0;
         textDisplayProgress = 0.0f;
         textFullyDisplayed = false;
-        pages = [];
-        textSpeed = 0.6f;
         *showDialog = false;
-        return;
     }
 }

+ 2 - 2
source/graphics/engine.d

@@ -37,8 +37,8 @@ import core.stdc.time;
 
 void engine_loader()
 {
-    int screenWidth = GetScreenWidth();
-    int screenHeight = GetScreenHeight();
+    int screenWidth = 1344;
+    int screenHeight = 1008;
     // Initialization
     debug debugWriteln("Engine version: ", ver);
     SetExitKey(0);

+ 4 - 5
source/graphics/gamelogic.d

@@ -26,7 +26,6 @@ void gameInit()
     circle = LoadTexture("res/misc/circle.png");
     dialogBackgroundTex = LoadTexture("res/misc/TEX#win_01d.PNG");
     choiceWindowTex = LoadTexture("res/misc/TEX#win_00d.PNG");
-    texturesLoaded = true;
     if (WindowShouldClose()) {
         currentGameState = GameState.Exit;
     } else {
@@ -117,14 +116,14 @@ void characterLogic() {
             float centeredX = characterTextures[i].x - (characterTextures[i].width * characterTextures[i].scale / 2);
             float centeredY = characterTextures[i].y - (characterTextures[i].height * characterTextures[i].scale / 2);
             
-            Color tint = Colors.WHITE;
-            tint.a = cast(ubyte)(255 * characterFades[i].alpha);
+            
+            characterColor.a = cast(ubyte)(255 * characterFades[i].alpha);
             
             DrawTextureEx(characterTextures[i].texture,
                         Vector2(centeredX, centeredY), 
                         0.0, 
                         characterTextures[i].scale, 
-                        tint);
+                        characterColor);
         }
     }
 }
@@ -132,6 +131,6 @@ void characterLogic() {
 void dialogLogic() {
     if (showDialog) {
         displayDialog(messageGlobal, choices, selectedChoice, choicePage, textFont, &showDialog, typingSpeed, 
-        dialogColor, circle, dialogBackgroundTex, choiceWindowTex);
+        circle, dialogBackgroundTex, choiceWindowTex);
     }
 }

+ 44 - 49
source/scripts/lua.d

@@ -21,15 +21,6 @@ import std.algorithm;
  * Not all engine functions usable for scripting are yet implemented.
 */
 
-string hint;
-
-extern (C) nothrow int luaL_showHint(lua_State* L)
-{
-    hint = "" ~ to!string(luaL_checkstring(L, 1));
-    hintNeeded = true;
-    return 0;
-}
-
 /* text window */
 
 extern (C) nothrow int luaL_dialogBox(lua_State* L)
@@ -58,9 +49,6 @@ extern (C) nothrow int luaL_dialogBox(lua_State* L)
         choices[i] = luaL_checkstring(L, -1).to!string;
         lua_pop(L, 1);
     }
-    dialogColor = Colors.GREEN;
-    int colorArgPos = -1;
-
     //if provided, get page on which choices must be shown
     if (lua_gettop(L) >= 3) {
         choicePage = cast(int)luaL_checkinteger(L, 3);
@@ -69,36 +57,6 @@ extern (C) nothrow int luaL_dialogBox(lua_State* L)
     if (lua_gettop(L) >= 4 && !lua_istable(L, 4)) {
         typingSpeed = cast(float) luaL_checknumber(L, 4);
     }
-    
-    //if 4 argument is a table - it must be a color
-    if (lua_gettop(L) >= 4 && lua_istable(L, 4)) {
-        colorArgPos = 4;
-    }
-    //else if 5 argument is a table its a color
-    else if (lua_gettop(L) >= 5 && lua_istable(L, 5)) {
-        colorArgPos = 5;
-    }
-
-    if (colorArgPos != -1) {
-        lua_getfield(L, colorArgPos, "r");
-        dialogColor.r = cast(ubyte)lua_tointeger(L, -1);
-        lua_pop(L, 1);
-        
-        lua_getfield(L, colorArgPos, "g");
-        dialogColor.g = cast(ubyte)lua_tointeger(L, -1);
-        lua_pop(L, 1);
-        
-        lua_getfield(L, colorArgPos, "b");
-        dialogColor.b = cast(ubyte)lua_tointeger(L, -1);
-        lua_pop(L, 1);
-        
-        lua_getfield(L, colorArgPos, "a");
-        //if a empty, reset to default
-        if (!lua_isnil(L, -1)) {
-            dialogColor.a = cast(ubyte)lua_tointeger(L, -1);
-        }
-        lua_pop(L, 1);
-    }
     return 0;
 }
 
@@ -113,12 +71,6 @@ extern (C) nothrow int luaL_isDialogExecuted(lua_State *L) {
     return 1;
 }
 
-extern (C) nothrow int luaL_dialogAnswerValue(lua_State* L)
-{
-    lua_pushinteger(L, selectedChoice);
-    return 1;
-}
-
 /* background drawing and loading */
 
 extern (C) nothrow int luaL_load2Dbackground(lua_State* L)
@@ -229,7 +181,30 @@ extern (C) nothrow int luaL_draw2Dcharacter(lua_State* L)
         characterTextures[count].x = cast(int) luaL_checkinteger(L, 1);
         characterTextures[count].drawTexture = true;
         characterTextures[count].justDrawn = true;
+        if (lua_gettop(L) == 5) {
+            lua_getfield(L, 5, "r");
+            characterColor.r = cast(ubyte)lua_tointeger(L, -1);
+            lua_pop(L, 1);
+            
+            lua_getfield(L, 5, "g");
+            characterColor.g = cast(ubyte)lua_tointeger(L, -1);
+            lua_pop(L, 1);
+            
+            lua_getfield(L, 5, "b");
+            characterColor.b = cast(ubyte)lua_tointeger(L, -1);
+            lua_pop(L, 1);
+            
+            lua_getfield(L, 5, "a");
+            //if empty, reset to default
+            if (!lua_isnil(L, -1)) {
+                characterColor.a = cast(ubyte)lua_tointeger(L, -1);
+            }
+            lua_pop(L, 1);
+        } else {
+            characterColor = Colors.WHITE;
+        }
         debugWriteln("Count: ", count, " drawTexture cond: ", characterTextures[count].drawTexture);
+        debugWriteln("arguments count: ", lua_gettop(L));
     } catch (Exception e) {
         debugWriteln(e.msg);
     }
@@ -325,6 +300,7 @@ extern (C) nothrow int luaL_playVideo(lua_State* L)
 
 extern (C) nothrow int luaL_moveCamera(lua_State *L) {
     try {
+        oldCamera = camera;
         float targetX = cast(float) luaL_checknumber(L, 1);
         float targetY = cast(float) luaL_checknumber(L, 2);
         float zoom = cast(float) luaL_optnumber(L, 3, 1.0f);
@@ -341,6 +317,11 @@ extern (C) nothrow int luaL_moveCamera(lua_State *L) {
     return 0;
 }
 
+extern (C) nothrow int luaL_restoreCamera(lua_State *L) {
+    camera = oldCamera;
+    return 0;
+}
+
 extern (C) nothrow int luaL_isCameraMoving(lua_State *L) {
     lua_pushboolean(L, isCameraMoving);
     return 1;
@@ -696,7 +677,6 @@ extern (C) nothrow int luaL_drawTextureEx(lua_State *L) {
 extern (C) nothrow void luaL_loader(lua_State* L)
 {
     lua_register(L, "dialogBox", &luaL_dialogBox);
-    lua_register(L, "dialogAnswerValue", &luaL_dialogAnswerValue);
     lua_register(L, "isDialogExecuted", &luaL_isDialogExecuted);
     lua_register(L, "getAnswerValue", &luaL_getAnswerValue);
     lua_register(L, "loadAnimationUI", &luaL_loadUIAnimation);
@@ -704,6 +684,7 @@ extern (C) nothrow void luaL_loader(lua_State* L)
     lua_register(L, "stopAnimationUI", &luaL_stopUIAnimation);
     lua_register(L, "unloadAnimationUI", &luaL_unloadUIAnimation);
     lua_register(L, "moveCamera", &luaL_moveCamera);
+    lua_register(L, "restoreCamera", &luaL_restoreCamera);
     lua_register(L, "isCameraMoving", &luaL_isCameraMoving);
     lua_register(L, "playVideo", &luaL_playVideo);
     lua_register(L, "loadMusic", &luaL_loadMusic);
@@ -742,6 +723,20 @@ extern (C) nothrow void luaL_loader(lua_State* L)
     lua_register(L, "measureTextY", &luaL_measureTextY);
     lua_register(L, "getTextureWidth", &luaL_getTextureWidth);
     lua_register(L, "getTextureHeight", &luaL_getTextureHeight);
+
+    debugWriteln("strict mode enabled");
+    const char* strict_lua =
+    `local mt = {
+        __index = function(_, name)
+            error("attempt to call undefined function: " .. tostring(name), 2)
+        end
+    }
+    setmetatable(_G, mt)`;
+
+    if (luaL_dostring(L, strict_lua) != LUA_OK) {
+        debugWriteln("Failed to set strict mode: ", to!string(lua_tostring(L, -1)));
+        lua_pop(L, 1); // Pop the error message
+    }
 }
 
 int luaInit(string luaExec)

+ 7 - 4
source/system/cleanup.d

@@ -9,15 +9,18 @@ void unloadResourcesLogic()
 {
     debugWriteln("Exiting. See ya'!");
     EndDrawing();
-    for (int i = cast(int)framesUI.length; i < framesUI.length; i++) {
-        debugWriteln("unloading animations");
+    debugWriteln("unloading animations");
+    for (int i = 0; i < framesUI.length; i++) {
         UnloadTexture(framesUI[i]);
     }
+    debugWriteln("unloading font");
     UnloadFont(textFont);
-    for (int i = cast(int)characterTextures.length; i < characterTextures.length; i++) {
+    debugWriteln("unloading characters");
+    for (int i = 0; i < characterTextures.length; i++) {
         UnloadTexture(characterTextures[i].texture);
     }
-    for (int i = cast(int)backgroundTextures.length; i < backgroundTextures.length; i++) {
+    debugWriteln("unloading backgrounds");
+    for (int i = 0; i < backgroundTextures.length; i++) {
         UnloadTexture(backgroundTextures[i].texture);
     }
 }

+ 2 - 0
source/ui/menu.d

@@ -102,6 +102,8 @@ int showMainMenu() {
         EndMode2D();
         EndDrawing();
     }
+    debugWriteln("menu assets unloading");
+    UnloadFont(textFont);
     StopMusicStream(music);
     UnloadMusicStream(music);
     luaReload = true;

+ 4 - 4
source/variables.d

@@ -70,6 +70,8 @@ enum EngineExitCodes {
 
 Camera2D camera;
 
+Camera2D oldCamera;
+
 TextureEngine[] characterTextures;
 
 TextureEngine[] backgroundTextures;
@@ -82,17 +84,15 @@ Font textFont;
 
 Music music;
 
-Color dialogColor;
-
 FadeEffect[] characterFades;
 
 FadeEffect[] backgroundFades;
 
 FadeEffect dialogFade;
 
-/* booleans */
+Color characterColor = Color(255, 255, 255);
 
-bool hintNeeded = false;
+/* booleans */
 
 bool playAnimation = false;