-- Addon: WoWTR Cataclysm-Movies v4.00 2024/05/03
-- Description: AddOn displays translated subtitles during playing cinematics or movies.
-- Autor: Platine, Hakan YILMAZ
-- (e-mail: platine.wow@gmail.com)
-- WWW: https://www.wowtr.com.tr

local MF_OwnName = "0";      --> 0=nazwy własne EN, 1=nazwy własne PL

-- General Variables
local MF_version = GetAddOnMetadata("WoWTR_Cataclysm", "Version");
local MF_race = UnitRace("player");
local MF_class = UnitClass("player");
local MF_name = UnitName("player");
local MF_movieID, MF_SubTitle, MF_lp, MF_ID, MF_playing, MF_showing, MF_timer, MF_time1, MF_last_ST, MF_pytanie1, MF_pytanie2;
if (MF_class == "Death Knight") then
   MF_race = MF_class;
end

-- fonty z polskimi znakami diakrytycznymi
local MF_Font = QTR_Font2;

local player_race, player_class;
local p_race = {
      ["Blood Elf"] = { M1="Blood Elf", D1="Blood Elf", C1="Blood Elf", B1="Blood Elf", N1="Blood Elf", K1="Blood Elf", W1="Blood Elf", M2="Blood Elf", D2="Blood Elf", C2="Blood Elf", B2="Blood Elf", N2="Blood Elf", K2="Blood Elf", W2="Blood Elf" }, 
      ["Dark Iron Dwarf"] = { M1="Dark Iron Dwarf", D1="Dark Iron Dwarf", C1="Dark Iron Dwarf", B1="Dark Iron Dwarf", N1="Dark Iron Dwarf", K1="Dark Iron Dwarf", W1="Dark Iron Dwarf", M2="Dark Iron Dwarf", D2="Dark Iron Dwarf", C2="Dark Iron Dwarf", B2="Dark Iron Dwarf", N2="Dark Iron Dwarf", K2="Dark Iron Dwarf", W2="Dark Iron Dwarf" }, 
      ["Dracthyr"] = { M1="Dracthyr", D1="Dracthyr", C1="Dracthyr", B1="Dracthyr", N1="Dracthyr", K1="Dracthyr", W1="Dracthyr", M2="Dracthyr", D2="Dracthyr", C2="Dracthyr", B2="Dracthyr", N2="Dracthyr", K2="Dracthyr", W2="Dracthyr" }, 
      ["Draenei"] = { M1="Draenei", D1="Draenei", C1="Draenei", B1="Draenei", N1="Draenei", K1="Draenei", W1="Draenei", M2="Draenei", D2="Draenei", C2="Draenei", B2="Draenei", N2="Draenei", K2="Draenei", W2="Draenei" }, 
      ["Dwarf"] = { M1="Dwarf", D1="Dwarf", C1="Dwarf", B1="Dwarf", N1="Dwarf", K1="Dwarf", W1="Dwarf", M2="Dwarf", D2="Dwarf", C2="Dwarf", B2="Dwarf", N2="Dwarf", K2="Dwarf", W2="Dwarf" }, 
      ["Gnome"] = { M1="Gnome", D1="Gnome", C1="Gnome", B1="Gnome", N1="Gnome", K1="Gnome", W1="Gnome", M2="Gnome", D2="Gnome", C2="Gnome", B2="Gnome", N2="Gnome", K2="Gnome", W2="Gnome" }, 
      ["Goblin"] = { M1="Goblin", D1="Goblin", C1="Goblin", B1="Goblin", N1="Goblin", K1="Goblin", W1="Goblin", M2="Goblin", D2="Goblin", C2="Goblin", B2="Goblin", N2="Goblin", K2="Goblin", W2="Goblin" }, 
      ["Highmountain Tauren"] = { M1="Highmountain Tauren", D1="Highmountain Tauren", C1="Highmountain Tauren", B1="Highmountain Tauren", N1="Highmountain Tauren", K1="Highmountain Tauren", W1="Highmountain Tauren", M2="Highmountain Tauren", D2="Highmountain Tauren", C2="Highmountain Tauren", B2="Highmountain Tauren", N2="Highmountain Tauren", K2="Highmountain Tauren", W2="Highmountain Tauren" }, 
      ["Human"] = { M1="Human", D1="Human", C1="Human", B1="Human", N1="Human", K1="Human", W1="Human", M2="Human", D2="Human", C2="Human", B2="Human", N2="Human", K2="Human", W2="Human" }, 
      ["Kul Tiran"] = { M1="Kul Tiran", D1="Kul Tiran", C1="Kul Tiran", B1="Kul Tiran", N1="Kul Tiran", K1="Kul Tiran", W1="Kul Tiran", M2="Kul Tiran", D2="Kul Tiran", C2="Kul Tiran", B2="Kul Tiran", N2="Kul Tiran", K2="Kul Tiran", W2="Kul Tiran" }, 
      ["Lightforged Draenei"] = { M1="Lightforged Draenei", D1="Lightforged Draenei", C1="Lightforged Draenei", B1="Lightforged Draenei", N1="Lightforged Draenei", K1="Lightforged Draenei", W1="Lightforged Draenei", M2="Lightforged Draenei", D2="Lightforged Draenei", C2="Lightforged Draenei", B2="Lightforged Draenei", N2="Lightforged Draenei", K2="Lightforged Draenei", W2="Lightforged Draenei" }, 
      ["Mag'har Orc"] = { M1="Mag'har Orc", D1="Mag'har Orc", C1="Mag'har Orc", B1="Mag'har Orc", N1="Mag'har Orc", K1="Mag'har Orc", W1="Mag'har Orc", M2="Mag'har Orc", D2="Mag'har Orc", C2="Mag'har Orc", B2="Mag'har Orc", N2="Mag'har Orc", K2="Mag'har Orc", W2="Mag'har Orc" }, 
      ["Mechagnome"] = { M1="Mechagnome", D1="Mechagnome", C1="Mechagnome", B1="Mechagnome", N1="Mechagnome", K1="Mechagnome", W1="Mechagnome", M2="Mechagnome", D2="Mechagnome", C2="Mechagnome", B2="Mechagnome", N2="Mechagnome", K2="Mechagnome", W2="Mechagnome" }, 
      ["Nightborne"] = { M1="Nightborne", D1="Nightborne", C1="Nightborne", B1="Nightborne", N1="Nightborne", K1="Nightborne", W1="Nightborne", M2="Nightborne", D2="Nightborne", C2="Nightborne", B2="Nightborne", N2="Nightborne", K2="Nightborne", W2="Nightborne" }, 
      ["Night Elf"] = { M1="Night Elf", D1="Night Elf", C1="Night Elf", B1="Night Elf", N1="Night Elf", K1="Night Elf", W1="Night Elf", M2="Night Elf", D2="Night Elf", C2="Night Elf", B2="Night Elf", N2="Night Elf", K2="Night Elf", W2="Night Elf" }, 
      ["Orc"] = { M1="Orc", D1="Orc", C1="Orc", B1="Orc", N1="Orc", K1="Orc", W1="Orc", M2="Orc", D2="Orc", C2="Orc", B2="Orc", N2="Orc", K2="Orc", W2="Orc" }, 
      ["Pandaren"] = { M1="Pandaren", D1="Pandaren", C1="Pandaren", B1="Pandaren", N1="Pandaren", K1="Pandaren", W1="Pandaren", M2="Pandaren", D2="Pandaren", C2="Pandaren", B2="Pandaren", N2="Pandaren", K2="Pandaren", W2="Pandaren" }, 
      ["Tauren"] = { M1="Tauren", D1="Tauren", C1="Tauren", B1="Tauren", N1="Tauren", K1="Tauren", W1="Tauren", M2="Tauren", D2="Tauren", C2="Tauren", B2="Tauren", N2="Tauren", K2="Tauren", W2="Tauren" }, 
      ["Troll"] = { M1="Troll", D1="Troll", C1="Troll", B1="Troll", N1="Troll", K1="Troll", W1="Troll", M2="Troll", D2="Troll", C2="Troll", B2="Troll", N2="Troll", K2="Troll", W2="Troll" }, 
      ["Undead"] = { M1="Undead", D1="Undead", C1="Undead", B1="Undead", N1="Undead", K1="Undead", W1="Undead", M2="Undead", D2="Undead", C2="Undead", B2="Undead", N2="Undead", K2="Undead", W2="Undead" }, 
      ["Void Elf"] = { M1="Void Elf", D1="Void Elf", C1="Void Elf", B1="Void Elf", N1="Void Elf", K1="Void Elf", W1="Void Elf", M2="Void Elf", D2="Void Elf", C2="Void Elf", B2="Void Elf", N2="Void Elf", K2="Void Elf", W2="Void Elf" }, 
      ["Vulpera"] = { M1="Vulpera", D1="Vulpera", C1="Vulpera", B1="Vulpera", N1="Vulpera", K1="Vulpera", W1="Vulpera", M2="Vulpera", D2="Vulpera", C2="Vulpera", B2="Vulpera", N2="Vulpera", K2="Vulpera", W2="Vulpera" }, 
      ["Worgen"] = { M1="Worgen", D1="Worgen", C1="Worgen", B1="Worgen", N1="Worgen", K1="Worgen", W1="Worgen", M2="Worgen", D2="Worgen", C2="Worgen", B2="Worgen", N2="Worgen", K2="Worgen", W2="Worgen" }, 
      ["Zandalari Troll"] = { M1="Zandalari Troll", D1="Zandalari Troll", C1="Zandalari Troll", B1="Zandalari Troll", N1="Zandalari Troll", K1="Zandalari Troll", W1="Zandalari Troll", M2="Zandalari Troll", D2="Zandalari Troll", C2="Zandalari Troll", B2="Zandalari Troll", N2="Zandalari Troll", K2="Zandalari Troll", W2="Zandalari Troll" }, 
}
local p_class = {
      ["Death Knight"] = { M1="Death Knight", D1="Death Knight", C1="Death Knight", B1="Death Knight", N1="Death Knight", K1="Death Knight", W1="Death Knight", M2="Death Knight", D2="Death Knight", C2="Death Knight", B2="Death Knight", N2="Death Knight", K2="Death Knight", W2="Death Knight" }, 
      ["Demon Hunter"] = { M1="Demon Hunter", D1="Demon Hunter", C1="Demon Hunter", B1="Demon Hunter", N1="Demon Hunter", K1="Demon Hunter", W1="Demon Hunter", M2="Demon Hunter", D2="Demon Hunter", C2="Demon Hunter", B2="Demon Hunter", N2="Demon Hunter", K2="Demon Hunter", W2="Demon Hunter" }, 
      ["Druid"] = { M1="Druid", D1="Druid", C1="Druid", B1="Druid", N1="Druid", K1="Druid", W1="Druid", M2="Druid", D2="Druid", C2="Druid", B2="Druid", N2="Druid", K2="Druid", W2="Druid" }, 
      ["Evoker"] = { M1="Evoker", D1="Evoker", C1="Evoker", B1="Evoker", N1="Evoker", K1="Evoker", W1="Evoker", M2="Evoker", D2="Evoker", C2="Evoker", B2="Evoker", N2="Evoker", K2="Evoker", W2="Evoker" }, 
      ["Hunter"] = { M1="Hunter", D1="Hunter", C1="Hunter", B1="Hunter", N1="Hunter", K1="Hunter", W1="Hunter", M2="Hunter", D2="Hunter", C2="Hunter", B2="Hunter", N2="Hunter", K2="Hunter", W2="Hunter" }, 
      ["Mage"] = { M1="Mage", D1="Mage", C1="Mage", B1="Mage", N1="Mage", K1="Mage", W1="Mage", M2="Mage", D2="Mage", C2="Mage", B2="Mage", N2="Mage", K2="Mage", W2="Mage" }, 
      ["Monk"] = { M1="Monk", D1="Monk", C1="Monk", B1="Monk", N1="Monk", K1="Monk", W1="Monk", M2="Monk", D2="Monk", C2="Monk", B2="Monk", N2="Monk", K2="Monk", W2="Monk" }, 
      ["Paladin"] = { M1="Paladin", D1="Paladin", C1="Paladin", B1="Paladin", N1="Paladin", K1="Paladin", W1="Paladin", M2="Paladin", D2="Paladin", C2="Paladin", B2="Paladin", N2="Paladin", K2="Paladin", W2="Paladin" }, 
      ["Priest"] = { M1="Priest", D1="Priest", C1="Priest", B1="Priest", N1="Priest", K1="Priest", W1="Priest", M2="Priest", D2="Priest", C2="Priest", B2="Priest", N2="Priest", K2="Priest", W2="Priest" }, 
      ["Rogue"] = { M1="Rogue", D1="Rogue", C1="Rogue", B1="Rogue", N1="Rogue", K1="Rogue", W1="Rogue", M2="Rogue", D2="Rogue", C2="Rogue", B2="Rogue", N2="Rogue", K2="Rogue", W2="Rogue" }, 
      ["Shaman"] = { M1="Shaman", D1="Shaman", C1="Shaman", B1="Shaman", N1="Shaman", K1="Shaman", W1="Shaman", M2="Shaman", D2="Shaman", C2="Shaman", B2="Shaman", N2="Shaman", K2="Shaman", W2="Shaman" }, 
      ["Warlock"] = { M1="Warlock", D1="Warlock", C1="Warlock", B1="Warlock", N1="Warlock", K1="Warlock", W1="Warlock", M2="Warlock", D2="Warlock", C2="Warlock", B2="Warlock", N2="Warlock", K2="Warlock", W2="Warlock" }, 
      ["Warrior"] = { M1="Warrior", D1="Warrior", C1="Warrior", B1="Warrior", N1="Warrior", K1="Warrior", W1="Warrior", M2="Warrior", D2="Warrior", C2="Warrior", B2="Warrior", N2="Warrior", K2="Warrior", W2="Warrior" }, 
}
if (p_race[MF_race]) then      
   player_race = { M1=p_race[MF_race].M1, D1=p_race[MF_race].D1, C1=p_race[MF_race].C1, B1=p_race[MF_race].B1, N1=p_race[MF_race].N1, K1=p_race[MF_race].K1, W1=p_race[MF_race].W1, M2=p_race[MF_race].M2, D2=p_race[MF_race].D2, C2=p_race[MF_race].C2, B2=p_race[MF_race].B2, N2=p_race[MF_race].N2, K2=p_race[MF_race].K2, W2=p_race[MF_race].W2 };
else   
   player_race = { M1=MF_race, D1=MF_race, C1=MF_race, B1=MF_race, N1=MF_race, K1=MF_race, W1=MF_race, M2=MF_race, D2=MF_race, C2=MF_race, B2=MF_race, N2=MF_race, K2=MF_race, W2=MF_race };
end
if (p_class[MF_class]) then
   player_class = { M1=p_class[MF_class].M1, D1=p_class[MF_class].D1, C1=p_class[MF_class].C1, B1=p_class[MF_class].B1, N1=p_class[MF_class].N1, K1=p_class[MF_class].K1, W1=p_class[MF_class].W1, M2=p_class[MF_class].M2, D2=p_class[MF_class].D2, C2=p_class[MF_class].C2, B2=p_class[MF_class].B2, N2=p_class[MF_class].N2, K2=p_class[MF_class].K2, W2=p_class[MF_class].W2 };
else
   player_class = { M1=MF_class, D1=MF_class, C1=MF_class, B1=MF_class, N1=MF_class, K1=MF_class, W1=MF_class, M2=MF_class, D2=MF_class, C2=MF_class, B2=MF_class, N2=MF_class, K2=MF_class, W2=MF_class };
end

local function StringHash(text)           -- funkcja tworząca Hash (32-bitowa liczba) podanego tekstu
  text = string.gsub(text, "$N$", "");
  text = string.gsub(text, "$N", "");
  text = string.gsub(text, "$R", "");
  text = string.gsub(text, "$C", "");
  local counter = 1;
  local pomoc = 0;
  local dlug = string.len(text);
  for i = 1, dlug, 3 do 
    counter = math.fmod(counter*8161, 4294967279);  -- 2^32 - 17: Prime!
    pomoc = (string.byte(text,i)*16776193);
    counter = counter + pomoc;
    pomoc = ((string.byte(text,i+1) or (dlug-i+256))*8372226);
    counter = counter + pomoc;
    pomoc = ((string.byte(text,i+2) or (dlug-i+256))*3932164);
    counter = counter + pomoc;
  end
  return math.fmod(counter, 4294967291) -- 2^32 - 5: Prime (and different from the prime in the loop)
end


function RenderujKody(txt)
   txt = string.gsub(txt, UnitName("player"), "$N");
   txt = string.gsub(txt, string.upper(UnitName("player")), "$N$");
   txt = string.gsub(txt, UnitRace("player"), "$R");
   txt = string.gsub(txt, string.lower(UnitRace("player")), "$R");
   txt = string.gsub(txt, UnitClass("player"), "$C");
   txt = string.gsub(txt, string.lower(UnitClass("player")), "$C");
   return txt;
end


function MF_OnEvent(self, event, ...)
   if (event=="PLAY_MOVIE") then
      MF_movieID = ... ;
      if (MF_movieID) then
--print("MF-uruchamiam movie ID="..MF_movieID);      
--         MovieFrame.CloseDialog:SetText("Czy na pewno chcesz przerwać wyświetlanie tego filmu?");
         if (MF_pytanie1 == nil) then
            MF_pytanie1 = MovieFrame.CloseDialog:CreateFontString(nil, "ARTWORK");
            MF_pytanie1:SetFontObject(GameFontNormal);
            MF_pytanie1:SetJustifyH("CENTER");
            MF_pytanie1:SetJustifyV("CENTER");
            MF_pytanie1:ClearAllPoints();
            MF_pytanie1:SetPoint("CENTER", MovieFrame.CloseDialog, "CENTER", 0, 6);
            MF_pytanie1:SetFont(MF_Font, 13);
            MF_pytanie1:SetText("Videoyu durdurmak mı istiyorsun?");
         end
         MovieFrame.CloseDialog.ConfirmButton:SetText("Evet");
         MovieFrame.CloseDialog.ResumeButton:SetText("Hayır");
         MovieFrame:EnableSubtitles(true);      -- włącz wyświetlanie napisów
         MF_last_ST = "";
         MF_lp = 0;
         MF_ID = tostring(MF_movieID);
         while (string.len(MF_ID)<3) do
            MF_ID = "0"..MF_ID;
         end
         local _font, _size, _3 = MovieFrameSubtitleString:GetFont();
         MovieFrameSubtitleString:SetFont(MF_Font, _size);           -- polskie czcionki do napisów
         MovieFrame:HookScript("OnMovieShowSubtitle", MF_ShowMovieSubtitles);
      end
   elseif (event=="CINEMATIC_START") then
--      print("MF-uruchamiam cinematic");
--      CinematicFrameCloseDialog:SetText("Czy na pewno chcesz przerwać wyświetlanie tego filmu?");
      if (MF_pytanie2 == nil) then
         MF_pytanie2 = CinematicFrameCloseDialog:CreateFontString(nil, "ARTWORK");
         MF_pytanie2:SetFontObject(GameFontNormal);
         MF_pytanie2:SetJustifyH("CENTER");
         MF_pytanie2:SetJustifyV("CENTER");
         MF_pytanie2:ClearAllPoints();
         MF_pytanie2:SetPoint("CENTER", CinematicFrameCloseDialog, "CENTER", 0, 6);
         MF_pytanie2:SetFont(MF_Font, 13);
         MF_pytanie2:SetText("Videoyu durdurmak mı istiyorsun?");
      end
      CinematicFrameCloseDialogConfirmButton:SetText("Evet");
      CinematicFrameCloseDialogResumeButton:SetText("Hayır");
      if (((UnitLevel("player")==1) and (C_Map.GetBestMapForUnit("player")~=1409) and (C_Map.GetBestMapForUnit("player")~=1726) and (C_Map.GetBestMapForUnit("player")~=1727)) or ((MF_class == "Death Knight") and (UnitLevel("player")==55))) then
         MF_SubTitle = CinematicFrame:CreateFontString(nil, "ARTWORK");    -- mamy Cinematic INTRO
         MF_SubTitle:SetFontObject(GameFontNormalLarge);
         MF_SubTitle:SetJustifyH("CENTER"); 
         MF_SubTitle:SetJustifyV("MIDDLE");
         MF_SubTitle:ClearAllPoints();
         MF_SubTitle:SetPoint("CENTER", CinematicFrame, "BOTTOM", 0, 65);
         MF_SubTitle:SetText("");
         MF_SubTitle:SetFont(MF_Font, 22);
         MF_playing = false;
         MF_lp = 1;
         MF_showing = false;
         if (MF_Data[MF_race.."3"..":01"]) then
            MF_sub1 = MF_Data[MF_race.."3"..":01"]["START"];
            MF_sub2 = MF_Data[MF_race.."3"..":01"]["STOP"];
            MF_sub3 = MF_Data[MF_race.."3"..":01"]["NAPIS"];
            CinematicFrame:HookScript("OnUpdate", MF_ShowCinematicIntro);
         end
      else                                      -- mamy cinematic on game
         CinematicFrame:HookScript("OnUpdate", MF_ShowCinematicSubtitles);
         MF_time1 = GetTime();
      end      
   elseif (event=="CINEMATIC_STOP") then
      CinematicFrame:SetScript("OnUpdate", nil);
      -- wyłącz napisy
      if (MF_SubTitle) then
         MF_SubTitle:Hide();
      end
   end
end

function MF_ShowMovieSubtitles()       -- wyświetlanie napisów w MOVIES
   local MF_readed_ST = MovieFrameSubtitleString:GetText();
   if (MF_readed_ST ~= MF_last_ST) then      -- napis jest inny niż ostatni
      MF_lp = MF_lp + 1;
      local MF_lpSTR = tostring(MF_lp);
      if (MF_lp<10) then
         MF_lpSTR = "0"..MF_lpSTR;
      end
      MF_last_ST = MF_readed_ST;             -- zapisz jako ostatni napis
      MF_hash = StringHash(MF_readed_ST);
      if (MF_Hash[MF_hash]) then             -- jest w bazie tłumaczenie napisu nr MF_lp
         MovieFrameSubtitleString:SetText(MF_Hash[MF_hash]);
         MovieFrameSubtitleString:SetFont(MF_Font, MF_Size); 
      else           -- nie ma tego Hasha - zapisz dane
         MF_PS[MF_ID..":"..MF_lpSTR..":"..MF_hash] = MF_readed_ST;
      end
   end
end


function BB_FindProS(text)                 -- znajdź, czy jest tekst '%s' w podanym tłumaczeniu
   local dl_txt = string.len(text)-1;
   for i_j=1,dl_txt,1 do
      if (strsub(text,i_j,i_j+1)=="%s") then       
         return i_j;
      end
   end
   return 0;
end


function MF_ShowCinematicSubtitles()            -- wyświetlanie napisów w CINEMATIC
   if (GetTime() - MF_time1 > 0.25) then        -- minęło conajmniej 0.25 sek.
      if (CinematicFrame.Subtitle1 and CinematicFrame.Subtitle1:IsVisible()) then        -- jest widoczny napis
         local MF_napis = CinematicFrame.Subtitle1:GetText();     -- odczytaj napis angielski
         if (MF_napis and (string.len(MF_napis)>0) and (string.find(MF_napis,"@")==nil)) then  -- znak '@' wskazuje na tekst polski
            MF_time1 = GetTime() + 1;                             -- +1 sek. nie trzeba sprawdzać
            local MF_zapisz_EN = true;
            MF_napis = RenderujKody(MF_napis);                    -- przeszukaj tekst i zamien na kody $x
            local MF_hash = StringHash(MF_napis);                 -- zrób Hash z tego tekstu
            local p1, p2 = string.find(MF_napis,":");             -- poszukaj znaku ':'
            if (p1 and (p1>0) and (p1<30)) then         -- jest znak ':' w początkowej części napisu (NPC says:)
               local MF_napis2 = RenderujKody(string.sub(MF_napis, p1+2));
               local MF_hash2 = StringHash(MF_napis2);
               if (BB_Bubbles[MF_hash2]) then            -- istnieje tłumaczenie w dymkach
                  local MF_output = string.sub(MF_napis,1,p1-1).." mówi: "..MF_ZmienKody(BB_Bubbles[MF_hash2].."@");
                  local _font, _size, _3 = CinematicFrame.Subtitle1:GetFont();   -- odczytaj wielkość czcionki
                  CinematicFrame.Subtitle1:SetText(MF_output);                   -- podmień wyświetlany tekst
                  CinematicFrame.Subtitle1:SetFont(MF_Font, _size);              -- zmień czcionkę na polską
                  MF_zapisz_EN = false;
               else
                  if (MF_zapisz_EN) then             -- zapisz oryginalny tekst wraz z kodem Hash
                     MF_PS[tostring(MF_hash)] = MF_napis;       
                  end
               end
            else
               if (BB_Bubbles[MF_hash]) then            -- istnieje tłumaczenie w dymkach
                  local MF_tekst = MF_ZmienKody(BB_Bubbles[MF_hash]);
                  local nr_poz = BB_FindProS(MF_tekst,1);   -- znajdź tekst '%s'
                  if (strsub(MF_tekst,1,2)=="%o") then 
                     MF_tekst = strsub(MF_tekst, 3):gsub("^%s*", "");
                  elseif (nr_poz>0) then           -- mamy formę opisową dymku %s np. NPC_name wpada w szał!
                     if (nr_poz==1) then
                        MF_tekst = name_NPC..strsub(MF_tekst, 3);
                     else
                        MF_tekst = strsub(MF_tekst,1,nr_poz-1)..name_NPC..strsub(MF_tekst, nr_poz+2);
                     end
                  end
                  local MF_output = MF_tekst.."@";
                  local _font, _size, _3 = CinematicFrame.Subtitle1:GetFont();   -- odczytaj wielkość czcionki
                  CinematicFrame.Subtitle1:SetText(MF_output);                   -- podmień wyświetlany tekst
                  CinematicFrame.Subtitle1:SetFont(MF_Font, _size);              -- zmień czcionkę na polską
                  MF_zapisz_EN = false;
               else
                  if (MF_zapisz_EN) then             -- zapisz oryginalny tekst wraz z kodem Hash
                     MF_PS[tostring(MF_hash)] = MF_napis;       
                  end
               end
            end
         end
      end
   end
end


function MF_ShowCinematicIntro()    -- wyświetlanie własnych napisów w INTRO
   if (MF_playing==false) then         
      MF_timer = GetTime();         -- wystartuj zegar filmu
      MF_playing=true;
   end
   if ((MF_showing==false) and (GetTime() > (MF_timer + MF_sub1))) then      -- czas wystartować napis
      MF_SubTitle:SetText(MF_sub3);
      MF_showing=true;
   end      
   if ((MF_showing==true) and (GetTime() > (MF_timer + MF_sub2))) then       -- czas zatrzymać napis
      MF_SubTitle:SetText("");
      -- ładuj następny
      MF_showing=false;
      MF_lp = MF_lp + 1;
      local MF_lpSTR = tostring(MF_lp);
      if (MF_lp<10) then
         MF_lpSTR = "0"..MF_lpSTR;
      end
      if (MF_Data[MF_race.."3"..":"..MF_lpSTR]) then
         MF_sub1 = MF_Data[MF_race.."3"..":"..MF_lpSTR]["START"];
         MF_sub2 = MF_Data[MF_race.."3"..":"..MF_lpSTR]["STOP"];
         MF_sub3 = MF_ZmienKody(MF_Data[MF_race.."3"..":"..MF_lpSTR]["NAPIS"]);
      else
         MF_sub1=1000;
         MF_sub2=1000;
      end
   end          
end


function MF_ZmienKody(message)
   message = string.gsub(message, "$n$", string.upper(MF_name));    -- i trzeba ją zamienić na nazwę gracza
   message = string.gsub(message, "$N$", string.upper(MF_name));    -- tu jeszcze pisane DUŻYMI LITERAMI
   message = string.gsub(message, "$n", MF_name);
   message = string.gsub(message, "$N", MF_name);
   message = string.gsub(message, "$g", "$G");     -- obsługa kodu $g(m;ż)
   local MF_forma = "";
   local nr_1, nr_2, nr_3 = 0;
   local nr_poz = string.find(message, "$G");    -- gdy nie znalazł, jest: nil; liczy od 1
   while (nr_poz and nr_poz>0) do
      nr_1 = nr_poz + 1;   
      while (string.sub(message, nr_1, nr_1) ~= "(") do   -- szukaj nawiasu otwierającego
         nr_1 = nr_1 + 1;
      end
      if (string.sub(message, nr_1, nr_1) == "(") then
         nr_2 =  nr_1 + 1;
         while (string.sub(message, nr_2, nr_2) ~= ";") do   -- szukaj średnika oddzielającego
            nr_2 = nr_2 + 1;
         end
         if (string.sub(message, nr_2, nr_2) == ";") then
            nr_3 = nr_2 + 1;
            while (string.sub(message, nr_3, nr_3) ~= ")") do   -- szukaj nawiasu zamykającego
               nr_3 = nr_3 + 1;
            end
            if (string.sub(message, nr_3, nr_3) == ")") then
               if (MF_sex==3) then         -- wypowiedzi wyświetlaj w formie żeńskiej
                  MF_forma = string.sub(message,nr_2+1,nr_3-1);
               else                                -- wypowiedzi wyświetlaj w formie męskiej
                  MF_forma = string.sub(message,nr_1+1,nr_2-1);
               end
               message = string.sub(message,1,nr_poz-1) .. MF_forma .. string.sub(message,nr_3+1);
            end   
         end
      end
      nr_poz = string.find(message, "$G");
   end
   
-- jeszcze obsłużyć nazwy własne $o(EN;PL)
   message = string.gsub(message, "$o", "$O");   -- obsługa kodu $o(EN;PL)
   local nr_1, nr_2, nr_3 = 0;
   local MF_forma = "";
   local nr_poz = string.find(message, "$O");    -- gdy nie znalazł, jest: nil
   while (nr_poz and nr_poz>0) do
      nr_1 = nr_poz + 1;   
      while (string.sub(message, nr_1, nr_1) ~= "(") do
         nr_1 = nr_1 + 1;
      end
      if (string.sub(message, nr_1, nr_1) == "(") then
         nr_2 =  nr_1 + 1;
         while (string.sub(message, nr_2, nr_2) ~= ";") do
            nr_2 = nr_2 + 1;
         end
         if (string.sub(message, nr_2, nr_2) == ";") then
            nr_3 = nr_2 + 1;
            while (string.sub(message, nr_3, nr_3) ~= ")") do
               nr_3 = nr_3 + 1;
            end
            if (string.sub(message, nr_3, nr_3) == ")") then
               if (MF_OwnName == "0") then        -- forma angielska
                  MF_forma = string.sub(message,nr_2+1,nr_3-1);
               else                               -- forma polska
                  MF_forma = string.sub(message,nr_1+1,nr_2-1);
               end
               message = string.sub(message,1,nr_poz-1) .. MF_forma .. string.sub(message,nr_3+1);
            end   
         end
      end
      nr_poz = string.find(message, "$O");
   end

   message = string.gsub(message, "$r", "$R");  
   message = string.gsub(message, "$c", "$C");    
   if (MF_sex==3) then       -- gracz gra kobietą
      message = string.gsub(message, "$R1", player_race.M2);
      message = string.gsub(message, "$R2", player_race.D2);
      message = string.gsub(message, "$R3", player_race.C2);
      message = string.gsub(message, "$R4", player_race.B2);
      message = string.gsub(message, "$R5", player_race.N2);
      message = string.gsub(message, "$R6", player_race.K2);
      message = string.gsub(message, "$R7", player_race.W2);
      message = string.gsub(message, "$R", player_race.M2);
      message = string.gsub(message, "$C1", player_class.M2);
      message = string.gsub(message, "$C2", player_class.D2);
      message = string.gsub(message, "$C3", player_class.C2);
      message = string.gsub(message, "$C4", player_class.B2);
      message = string.gsub(message, "$C5", player_class.N2);
      message = string.gsub(message, "$C6", player_class.K2);
      message = string.gsub(message, "$C7", player_class.W2);
      message = string.gsub(message, "$C", player_class.M2);
   else                          -- gracz gra facetem
      message = string.gsub(message, "$R1", player_race.M1);
      message = string.gsub(message, "$R2", player_race.D1);
      message = string.gsub(message, "$R3", player_race.C1);
      message = string.gsub(message, "$R4", player_race.B1);
      message = string.gsub(message, "$R5", player_race.N1);
      message = string.gsub(message, "$R6", player_race.K1);
      message = string.gsub(message, "$R7", player_race.W1);
      message = string.gsub(message, "$R", player_race.M1);
      message = string.gsub(message, "$C1", player_class.M1);
      message = string.gsub(message, "$C2", player_class.D1);
      message = string.gsub(message, "$C3", player_class.C1);
      message = string.gsub(message, "$C4", player_class.B1);
      message = string.gsub(message, "$C5", player_class.N1);
      message = string.gsub(message, "$C6", player_class.K1);
      message = string.gsub(message, "$C7", player_class.W1);
      message = string.gsub(message, "$C", player_class.M1);
   end

   return message;   
end


MF_Frame = CreateFrame("Frame");
MF_Frame:SetScript("OnEvent", MF_OnEvent);
MF_Frame:RegisterEvent("PLAY_MOVIE");
MF_Frame:RegisterEvent("CINEMATIC_START");
MF_Frame:RegisterEvent("CINEMATIC_STOP");
if (not MF_PS) then
   MF_PS = {};
end

-- DEFAULT_CHAT_FRAME:AddMessage("|cffffff00WoWTR Cataclysm-Movies  ver. "..MF_version);